github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/pkg/mount/mountinfo_linux.go (about) 1 package mount 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os" 8 "strings" 9 ) 10 11 const ( 12 /* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue 13 (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) 14 15 (1) mount ID: unique identifier of the mount (may be reused after umount) 16 (2) parent ID: ID of parent (or of self for the top of the mount tree) 17 (3) major:minor: value of st_dev for files on filesystem 18 (4) root: root of the mount within the filesystem 19 (5) mount point: mount point relative to the process's root 20 (6) mount options: per mount options 21 (7) optional fields: zero or more fields of the form "tag[:value]" 22 (8) separator: marks the end of the optional fields 23 (9) filesystem type: name of filesystem of the form "type[.subtype]" 24 (10) mount source: filesystem specific information or "none" 25 (11) super options: per super block options*/ 26 mountinfoFormat = "%d %d %d:%d %s %s %s %s" 27 ) 28 29 // Parse /proc/self/mountinfo because comparing Dev and ino does not work from 30 // bind mounts 31 func parseMountTable() ([]*Info, error) { 32 f, err := os.Open("/proc/self/mountinfo") 33 if err != nil { 34 return nil, err 35 } 36 defer f.Close() 37 38 return parseInfoFile(f) 39 } 40 41 func parseInfoFile(r io.Reader) ([]*Info, error) { 42 var ( 43 s = bufio.NewScanner(r) 44 out = []*Info{} 45 ) 46 47 for s.Scan() { 48 if err := s.Err(); err != nil { 49 return nil, err 50 } 51 52 var ( 53 p = &Info{} 54 text = s.Text() 55 optionalFields string 56 ) 57 58 if _, err := fmt.Sscanf(text, mountinfoFormat, 59 &p.ID, &p.Parent, &p.Major, &p.Minor, 60 &p.Root, &p.Mountpoint, &p.Opts, &optionalFields); err != nil { 61 return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err) 62 } 63 // Safe as mountinfo encodes mountpoints with spaces as \040. 64 index := strings.Index(text, " - ") 65 postSeparatorFields := strings.Fields(text[index+3:]) 66 if len(postSeparatorFields) < 3 { 67 return nil, fmt.Errorf("Error found less than 3 fields post '-' in %q", text) 68 } 69 70 if optionalFields != "-" { 71 p.Optional = optionalFields 72 } 73 74 p.Fstype = postSeparatorFields[0] 75 p.Source = postSeparatorFields[1] 76 p.VfsOpts = strings.Join(postSeparatorFields[2:], " ") 77 out = append(out, p) 78 } 79 return out, nil 80 } 81 82 // PidMountInfo collects the mounts for a specific process ID. If the process 83 // ID is unknown, it is better to use `GetMounts` which will inspect 84 // "/proc/self/mountinfo" instead. 85 func PidMountInfo(pid int) ([]*Info, error) { 86 f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid)) 87 if err != nil { 88 return nil, err 89 } 90 defer f.Close() 91 92 return parseInfoFile(f) 93 }