123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- package procfs
- import (
- "bufio"
- "bytes"
- "fmt"
- "strconv"
- "strings"
- "github.com/prometheus/procfs/internal/util"
- )
- type MountInfo struct {
-
- MountID int
-
- ParentID int
-
- MajorMinorVer string
-
-
- Root string
-
- MountPoint string
-
- Options map[string]string
-
- OptionalFields map[string]string
-
- FSType string
-
- Source string
-
- SuperOptions map[string]string
- }
- func parseMountInfo(info []byte) ([]*MountInfo, error) {
- mounts := []*MountInfo{}
- scanner := bufio.NewScanner(bytes.NewReader(info))
- for scanner.Scan() {
- mountString := scanner.Text()
- parsedMounts, err := parseMountInfoString(mountString)
- if err != nil {
- return nil, err
- }
- mounts = append(mounts, parsedMounts)
- }
- err := scanner.Err()
- return mounts, err
- }
- func parseMountInfoString(mountString string) (*MountInfo, error) {
- var err error
- mountInfo := strings.Split(mountString, " ")
- mountInfoLength := len(mountInfo)
- if mountInfoLength < 10 {
- return nil, fmt.Errorf("couldn't find enough fields in mount string: %s", mountString)
- }
- if mountInfo[mountInfoLength-4] != "-" {
- return nil, fmt.Errorf("couldn't find separator in expected field: %s", mountInfo[mountInfoLength-4])
- }
- mount := &MountInfo{
- MajorMinorVer: mountInfo[2],
- Root: mountInfo[3],
- MountPoint: mountInfo[4],
- Options: mountOptionsParser(mountInfo[5]),
- OptionalFields: nil,
- FSType: mountInfo[mountInfoLength-3],
- Source: mountInfo[mountInfoLength-2],
- SuperOptions: mountOptionsParser(mountInfo[mountInfoLength-1]),
- }
- mount.MountID, err = strconv.Atoi(mountInfo[0])
- if err != nil {
- return nil, fmt.Errorf("failed to parse mount ID")
- }
- mount.ParentID, err = strconv.Atoi(mountInfo[1])
- if err != nil {
- return nil, fmt.Errorf("failed to parse parent ID")
- }
-
-
- if mountInfo[6] != "" {
- mount.OptionalFields, err = mountOptionsParseOptionalFields(mountInfo[6 : mountInfoLength-4])
- if err != nil {
- return nil, err
- }
- }
- return mount, nil
- }
- func mountOptionsIsValidField(s string) bool {
- switch s {
- case
- "shared",
- "master",
- "propagate_from",
- "unbindable":
- return true
- }
- return false
- }
- 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
- }
- func mountOptionsParser(mountOptions string) map[string]string {
- opts := make(map[string]string)
- options := strings.Split(mountOptions, ",")
- for _, opt := range options {
- splitOption := strings.Split(opt, "=")
- if len(splitOption) < 2 {
- key := splitOption[0]
- opts[key] = ""
- } else {
- key, value := splitOption[0], splitOption[1]
- opts[key] = value
- }
- }
- return opts
- }
- func GetMounts() ([]*MountInfo, error) {
- data, err := util.ReadFileNoStat("/proc/self/mountinfo")
- if err != nil {
- return nil, err
- }
- return parseMountInfo(data)
- }
- func GetProcMounts(pid int) ([]*MountInfo, error) {
- data, err := util.ReadFileNoStat(fmt.Sprintf("/proc/%d/mountinfo", pid))
- if err != nil {
- return nil, err
- }
- return parseMountInfo(data)
- }
|