summaryrefslogtreecommitdiff
path: root/vendor/github.com/prometheus/procfs/mountinfo.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/prometheus/procfs/mountinfo.go')
-rw-r--r--vendor/github.com/prometheus/procfs/mountinfo.go128
1 files changed, 65 insertions, 63 deletions
diff --git a/vendor/github.com/prometheus/procfs/mountinfo.go b/vendor/github.com/prometheus/procfs/mountinfo.go
index 61fa61887..59f4d5055 100644
--- a/vendor/github.com/prometheus/procfs/mountinfo.go
+++ b/vendor/github.com/prometheus/procfs/mountinfo.go
@@ -15,19 +15,13 @@ package procfs
import (
"bufio"
+ "bytes"
"fmt"
- "io"
- "os"
"strconv"
"strings"
-)
-var validOptionalFields = map[string]bool{
- "shared": true,
- "master": true,
- "propagate_from": true,
- "unbindable": true,
-}
+ "github.com/prometheus/procfs/internal/util"
+)
// A MountInfo is a type that describes the details, options
// for each mount, parsed from /proc/self/mountinfo.
@@ -35,10 +29,10 @@ var validOptionalFields = map[string]bool{
// is described in the following man page.
// http://man7.org/linux/man-pages/man5/proc.5.html
type MountInfo struct {
- // Unique Id for the mount
- MountId int
- // The Id of the parent mount
- ParentId int
+ // Unique ID for the mount
+ MountID int
+ // The ID of the parent mount
+ ParentID int
// The value of `st_dev` for the files on this FS
MajorMinorVer string
// The pathname of the directory in the FS that forms
@@ -58,18 +52,10 @@ type MountInfo struct {
SuperOptions map[string]string
}
-// Returns part of the mountinfo line, if it exists, else an empty string.
-func getStringSliceElement(parts []string, idx int, defaultValue string) string {
- if idx >= len(parts) {
- return defaultValue
- }
- return parts[idx]
-}
-
// Reads each line of the mountinfo file, and returns a list of formatted MountInfo structs.
-func parseMountInfo(r io.Reader) ([]*MountInfo, error) {
+func parseMountInfo(info []byte) ([]*MountInfo, error) {
mounts := []*MountInfo{}
- scanner := bufio.NewScanner(r)
+ scanner := bufio.NewScanner(bytes.NewReader(info))
for scanner.Scan() {
mountString := scanner.Text()
parsedMounts, err := parseMountInfoString(mountString)
@@ -89,58 +75,76 @@ func parseMountInfo(r io.Reader) ([]*MountInfo, error) {
func parseMountInfoString(mountString string) (*MountInfo, error) {
var err error
- // OptionalFields can be zero, hence these checks to ensure we do not populate the wrong values in the wrong spots
- separatorIndex := strings.Index(mountString, "-")
- if separatorIndex == -1 {
- return nil, fmt.Errorf("no separator found in mountinfo string: %s", mountString)
+ mountInfo := strings.Split(mountString, " ")
+ mountInfoLength := len(mountInfo)
+ if mountInfoLength < 10 {
+ return nil, fmt.Errorf("couldn't find enough fields in mount string: %s", mountString)
}
- beforeFields := strings.Fields(mountString[:separatorIndex])
- afterFields := strings.Fields(mountString[separatorIndex+1:])
- if (len(beforeFields) + len(afterFields)) < 7 {
- return nil, fmt.Errorf("too few fields")
+
+ if mountInfo[mountInfoLength-4] != "-" {
+ return nil, fmt.Errorf("couldn't find separator in expected field: %s", mountInfo[mountInfoLength-4])
}
mount := &MountInfo{
- MajorMinorVer: getStringSliceElement(beforeFields, 2, ""),
- Root: getStringSliceElement(beforeFields, 3, ""),
- MountPoint: getStringSliceElement(beforeFields, 4, ""),
- Options: mountOptionsParser(getStringSliceElement(beforeFields, 5, "")),
+ MajorMinorVer: mountInfo[2],
+ Root: mountInfo[3],
+ MountPoint: mountInfo[4],
+ Options: mountOptionsParser(mountInfo[5]),
OptionalFields: nil,
- FSType: getStringSliceElement(afterFields, 0, ""),
- Source: getStringSliceElement(afterFields, 1, ""),
- SuperOptions: mountOptionsParser(getStringSliceElement(afterFields, 2, "")),
+ FSType: mountInfo[mountInfoLength-3],
+ Source: mountInfo[mountInfoLength-2],
+ SuperOptions: mountOptionsParser(mountInfo[mountInfoLength-1]),
}
- mount.MountId, err = strconv.Atoi(getStringSliceElement(beforeFields, 0, ""))
+ mount.MountID, err = strconv.Atoi(mountInfo[0])
if err != nil {
return nil, fmt.Errorf("failed to parse mount ID")
}
- mount.ParentId, err = strconv.Atoi(getStringSliceElement(beforeFields, 1, ""))
+ mount.ParentID, err = strconv.Atoi(mountInfo[1])
if err != nil {
return nil, fmt.Errorf("failed to parse parent ID")
}
// Has optional fields, which is a space separated list of values.
// Example: shared:2 master:7
- if len(beforeFields) > 6 {
- mount.OptionalFields = make(map[string]string)
- optionalFields := beforeFields[6:]
- for _, field := range optionalFields {
- optionSplit := strings.Split(field, ":")
- target, value := optionSplit[0], ""
- if len(optionSplit) == 2 {
- value = optionSplit[1]
- }
- // Checks if the 'keys' in the optional fields in the mountinfo line are acceptable.
- // Allowed 'keys' are shared, master, propagate_from, unbindable.
- if _, ok := validOptionalFields[target]; ok {
- mount.OptionalFields[target] = value
- }
+ if mountInfo[6] != "" {
+ mount.OptionalFields, err = mountOptionsParseOptionalFields(mountInfo[6 : mountInfoLength-4])
+ if err != nil {
+ return nil, err
}
}
return mount, nil
}
-// Parses the mount options, superblock options.
+// mountOptionsIsValidField checks a string against a valid list of optional fields keys.
+func mountOptionsIsValidField(s string) bool {
+ switch s {
+ case
+ "shared",
+ "master",
+ "propagate_from",
+ "unbindable":
+ return true
+ }
+ return false
+}
+
+// mountOptionsParseOptionalFields parses a list of optional fields strings into a double map of strings.
+func mountOptionsParseOptionalFields(o []string) (map[string]string, error) {
+ optionalFields := make(map[string]string)
+ for _, field := range o {
+ optionSplit := strings.SplitN(field, ":", 2)
+ value := ""
+ if len(optionSplit) == 2 {
+ value = optionSplit[1]
+ }
+ if mountOptionsIsValidField(optionSplit[0]) {
+ optionalFields[optionSplit[0]] = value
+ }
+ }
+ return optionalFields, nil
+}
+
+// mountOptionsParser parses the mount options, superblock options.
func mountOptionsParser(mountOptions string) map[string]string {
opts := make(map[string]string)
options := strings.Split(mountOptions, ",")
@@ -157,22 +161,20 @@ func mountOptionsParser(mountOptions string) map[string]string {
return opts
}
-// Retrieves mountinfo information from `/proc/self/mountinfo`.
+// GetMounts retrieves mountinfo information from `/proc/self/mountinfo`.
func GetMounts() ([]*MountInfo, error) {
- f, err := os.Open("/proc/self/mountinfo")
+ data, err := util.ReadFileNoStat("/proc/self/mountinfo")
if err != nil {
return nil, err
}
- defer f.Close()
- return parseMountInfo(f)
+ return parseMountInfo(data)
}
-// Retrieves mountinfo information from a processes' `/proc/<pid>/mountinfo`.
+// GetProcMounts retrieves mountinfo information from a processes' `/proc/<pid>/mountinfo`.
func GetProcMounts(pid int) ([]*MountInfo, error) {
- f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid))
+ data, err := util.ReadFileNoStat(fmt.Sprintf("/proc/%d/mountinfo", pid))
if err != nil {
return nil, err
}
- defer f.Close()
- return parseMountInfo(f)
+ return parseMountInfo(data)
}