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