summaryrefslogtreecommitdiff
path: root/pkg/mount/mountinfo_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/mount/mountinfo_linux.go')
-rw-r--r--pkg/mount/mountinfo_linux.go73
1 files changed, 73 insertions, 0 deletions
diff --git a/pkg/mount/mountinfo_linux.go b/pkg/mount/mountinfo_linux.go
new file mode 100644
index 0000000000..01c954fff3
--- /dev/null
+++ b/pkg/mount/mountinfo_linux.go
@@ -0,0 +1,73 @@
+package mount
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+)
+
+const (
+ /* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
+ (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
+
+ (1) mount ID: unique identifier of the mount (may be reused after umount)
+ (2) parent ID: ID of parent (or of self for the top of the mount tree)
+ (3) major:minor: value of st_dev for files on filesystem
+ (4) root: root of the mount within the filesystem
+ (5) mount point: mount point relative to the process's root
+ (6) mount options: per mount options
+ (7) optional fields: zero or more fields of the form "tag[:value]"
+ (8) separator: marks the end of the optional fields
+ (9) filesystem type: name of filesystem of the form "type[.subtype]"
+ (10) mount source: filesystem specific information or "none"
+ (11) super options: per super block options*/
+ mountinfoFormat = "%d %d %d:%d %s %s %s "
+)
+
+// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts
+func parseMountTable() ([]*MountInfo, error) {
+ f, err := os.Open("/proc/self/mountinfo")
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return parseInfoFile(f)
+}
+
+func parseInfoFile(r io.Reader) ([]*MountInfo, error) {
+ var (
+ s = bufio.NewScanner(r)
+ out = []*MountInfo{}
+ )
+
+ for s.Scan() {
+ if err := s.Err(); err != nil {
+ return nil, err
+ }
+
+ var (
+ p = &MountInfo{}
+ text = s.Text()
+ )
+
+ if _, err := fmt.Sscanf(text, mountinfoFormat,
+ &p.Id, &p.Parent, &p.Major, &p.Minor,
+ &p.Root, &p.Mountpoint, &p.Opts); err != nil {
+ return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err)
+ }
+ // Safe as mountinfo encodes mountpoints with spaces as \040.
+ index := strings.Index(text, " - ")
+ postSeparatorFields := strings.Fields(text[index+3:])
+ if len(postSeparatorFields) != 3 {
+ return nil, fmt.Errorf("Error did not find 3 fields post '-' in '%s'", text)
+ }
+ p.Fstype = postSeparatorFields[0]
+ p.Source = postSeparatorFields[1]
+ p.VfsOpts = postSeparatorFields[2]
+ out = append(out, p)
+ }
+ return out, nil
+}