diff --git a/mount/flags_freebsd.go b/mount/flags_freebsd.go index a59b589..f166cb2 100644 --- a/mount/flags_freebsd.go +++ b/mount/flags_freebsd.go @@ -8,12 +8,25 @@ package mount import "C" const ( - RDONLY = C.MNT_RDONLY - NOSUID = C.MNT_NOSUID - NOEXEC = C.MNT_NOEXEC - SYNCHRONOUS = C.MNT_SYNCHRONOUS - NOATIME = C.MNT_NOATIME + // RDONLY will mount the filesystem as read-only. + RDONLY = C.MNT_RDONLY + // NOSUID will not allow set-user-identifier or set-group-identifier bits to + // take effect. + NOSUID = C.MNT_NOSUID + + // NOEXEC will not allow execution of any binaries on the mounted file system. + NOEXEC = C.MNT_NOEXEC + + // SYNCHRONOUS will allow any I/O to the file system to be done synchronously. + SYNCHRONOUS = C.MNT_SYNCHRONOUS + + // NOATIME will not update the file access time when reading from a file. + NOATIME = C.MNT_NOATIME +) + +// These flags are unsupported. +const ( BIND = 0 DIRSYNC = 0 MANDLOCK = 0 diff --git a/mount/flags_linux.go b/mount/flags_linux.go index 9986621..2f9f5c5 100644 --- a/mount/flags_linux.go +++ b/mount/flags_linux.go @@ -5,26 +5,81 @@ import ( ) const ( - RDONLY = syscall.MS_RDONLY - NOSUID = syscall.MS_NOSUID - NODEV = syscall.MS_NODEV - NOEXEC = syscall.MS_NOEXEC + // RDONLY will mount the file system read-only. + RDONLY = syscall.MS_RDONLY + + // NOSUID will not allow set-user-identifier or set-group-identifier bits to + // take effect. + NOSUID = syscall.MS_NOSUID + + // NODEV will not interpret character or block special devices on the file + // system. + NODEV = syscall.MS_NODEV + + // NOEXEC will not allow execution of any binaries on the mounted file system. + NOEXEC = syscall.MS_NOEXEC + + // SYNCHRONOUS will allow I/O to the file system to be done synchronously. SYNCHRONOUS = syscall.MS_SYNCHRONOUS - DIRSYNC = syscall.MS_DIRSYNC - REMOUNT = syscall.MS_REMOUNT - MANDLOCK = syscall.MS_MANDLOCK - NOATIME = syscall.MS_NOATIME - NODIRATIME = syscall.MS_NODIRATIME - BIND = syscall.MS_BIND - RBIND = syscall.MS_BIND | syscall.MS_REC - UNBINDABLE = syscall.MS_UNBINDABLE + + // DIRSYNC will force all directory updates within the file system to be done + // synchronously. This affects the following system calls: creat, link, + // unlink, symlink, mkdir, rmdir, mknod and rename. + DIRSYNC = syscall.MS_DIRSYNC + + // REMOUNT will attempt to remount an already-mounted file system. This is + // commonly used to change the mount flags for a file system, especially to + // make a readonly file system writeable. It does not change device or mount + // point. + REMOUNT = syscall.MS_REMOUNT + + // MANDLOCK will force mandatory locks on a filesystem. + MANDLOCK = syscall.MS_MANDLOCK + + // NOATIME will not update the file access time when reading from a file. + NOATIME = syscall.MS_NOATIME + + // NODIRATIME will not update the directory access time. + NODIRATIME = syscall.MS_NODIRATIME + + // BIND remounts a subtree somewhere else. + BIND = syscall.MS_BIND + + // RBIND remounts a subtree and all possible submounts somewhere else. + RBIND = syscall.MS_BIND | syscall.MS_REC + + // UNBINDABLE creates a mount which cannot be cloned through a bind operation. + UNBINDABLE = syscall.MS_UNBINDABLE + + // RUNBINDABLE marks the entire mount tree as UNBINDABLE. RUNBINDABLE = syscall.MS_UNBINDABLE | syscall.MS_REC - PRIVATE = syscall.MS_PRIVATE - RPRIVATE = syscall.MS_PRIVATE | syscall.MS_REC - SLAVE = syscall.MS_SLAVE - RSLAVE = syscall.MS_SLAVE | syscall.MS_REC - SHARED = syscall.MS_SHARED - RSHARED = syscall.MS_SHARED | syscall.MS_REC - RELATIME = syscall.MS_RELATIME + + // PRIVATE creates a mount which carries no propagation abilities. + PRIVATE = syscall.MS_PRIVATE + + // RPRIVATE marks the entire mount tree as PRIVATE. + RPRIVATE = syscall.MS_PRIVATE | syscall.MS_REC + + // SLAVE creates a mount which receives propagation from its master, but not + // vice versa. + SLAVE = syscall.MS_SLAVE + + // RSLAVE marks the entire mount tree as SLAVE. + RSLAVE = syscall.MS_SLAVE | syscall.MS_REC + + // SHARED creates a mount which provides the ability to create mirrors of + // that mount such that mounts and unmounts within any of the mirrors + // propagate to the other mirrors. + SHARED = syscall.MS_SHARED + + // RSHARED marks the entire mount tree as SHARED. + RSHARED = syscall.MS_SHARED | syscall.MS_REC + + // RELATIME updates inode access times relative to modify or change time. + RELATIME = syscall.MS_RELATIME + + // STRICTATIME allows to explicitly request full atime updates. This makes + // it possible for the kernel to default to relatime or noatime but still + // allow userspace to override it. STRICTATIME = syscall.MS_STRICTATIME ) diff --git a/mount/flags_unsupported.go b/mount/flags_unsupported.go index c4f8217..a90d3d1 100644 --- a/mount/flags_unsupported.go +++ b/mount/flags_unsupported.go @@ -2,6 +2,7 @@ package mount +// These flags are unsupported. const ( BIND = 0 DIRSYNC = 0 diff --git a/mount/mount.go b/mount/mount.go index 5ca7316..9a20df2 100644 --- a/mount/mount.go +++ b/mount/mount.go @@ -4,11 +4,12 @@ import ( "time" ) +// GetMounts retrieves a list of mounts for the current running process. func GetMounts() ([]*MountInfo, error) { return parseMountTable() } -// Looks at /proc/self/mountinfo to determine of the specified +// Mounted looks at /proc/self/mountinfo to determine of the specified // mountpoint has been mounted func Mounted(mountpoint string) (bool, error) { entries, err := parseMountTable() @@ -25,9 +26,10 @@ func Mounted(mountpoint string) (bool, error) { return false, nil } -// Mount the specified options at the target path only if -// the target is not mounted -// Options must be specified as fstab style +// Mount will mount filesystem according to the specified configuration, on the +// condition that the target path is *not* already mounted. Options must be +// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See +// flags.go for supported option flags. func Mount(device, target, mType, options string) error { flag, _ := parseOptions(options) if flag&REMOUNT != REMOUNT { @@ -38,9 +40,10 @@ func Mount(device, target, mType, options string) error { return ForceMount(device, target, mType, options) } -// Mount the specified options at the target path -// reguardless if the target is mounted or not -// Options must be specified as fstab style +// ForceMount will mount a filesystem according to the specified configuration, +// *regardless* if the target path is not already mounted. Options must be +// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See +// flags.go for supported option flags. func ForceMount(device, target, mType, options string) error { flag, data := parseOptions(options) if err := mount(device, target, mType, uintptr(flag), data); err != nil { @@ -49,7 +52,7 @@ func ForceMount(device, target, mType, options string) error { return nil } -// Unmount the target only if it is mounted +// Unmount will unmount the target filesystem, so long as it is mounted. func Unmount(target string) error { if mounted, err := Mounted(target); err != nil || !mounted { return err @@ -57,7 +60,8 @@ func Unmount(target string) error { return ForceUnmount(target) } -// Unmount the target reguardless if it is mounted or not +// ForceUnmount will force an unmount of the target filesystem, regardless if +// it is mounted or not. func ForceUnmount(target string) (err error) { // Simple retry logic for unmount for i := 0; i < 10; i++ { diff --git a/mount/mountinfo.go b/mount/mountinfo.go index ec8e8bc..8ea0864 100644 --- a/mount/mountinfo.go +++ b/mount/mountinfo.go @@ -1,7 +1,40 @@ package mount +// MountInfo reveals information about a particular mounted filesystem. This +// struct is populated from the content in the /proc//mountinfo file. type MountInfo struct { - Id, Parent, Major, Minor int - Root, Mountpoint, Opts, Optional string - Fstype, Source, VfsOpts string + // Id is a unique identifier of the mount (may be reused after umount). + Id int + + // Parent indicates the ID of the mount parent (or of self for the top of the + // mount tree). + Parent int + + // Major indicates one half of the device ID which identifies the device class. + Major int + + // Minor indicates one half of the device ID which identifies a specific + // instance of device. + Minor int + + // Root of the mount within the filesystem. + Root string + + // Mountpoint indicates the mount point relative to the process's root. + Mountpoint string + + // Opts represents mount-specific options. + Opts string + + // Optional represents optional fields. + Optional string + + // Fstype indicates the type of filesystem, such as EXT3. + Fstype string + + // Source indicates filesystem specific information or "none". + Source string + + // VfsOpts represents per super block options. + VfsOpts string } diff --git a/mount/mountinfo_freebsd.go b/mount/mountinfo_freebsd.go index 2fe9186..add7c3b 100644 --- a/mount/mountinfo_freebsd.go +++ b/mount/mountinfo_freebsd.go @@ -13,7 +13,8 @@ import ( "unsafe" ) -// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts +// Parse /proc/self/mountinfo because comparing Dev and ino does not work from +// bind mounts. func parseMountTable() ([]*MountInfo, error) { var rawEntries *C.struct_statfs diff --git a/mount/mountinfo_linux.go b/mount/mountinfo_linux.go index 0eb018e..351a58e 100644 --- a/mount/mountinfo_linux.go +++ b/mount/mountinfo_linux.go @@ -28,7 +28,8 @@ const ( mountinfoFormat = "%d %d %d:%d %s %s %s %s" ) -// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts +// 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 { @@ -80,7 +81,9 @@ func parseInfoFile(r io.Reader) ([]*MountInfo, error) { return out, nil } -// PidMountInfo collects the mounts for a specific Pid +// PidMountInfo collects the mounts for a specific process ID. If the process +// ID is unknown, it is better to use `GetMounts` which will inspect +// "/proc/self/mountinfo" instead. func PidMountInfo(pid int) ([]*MountInfo, error) { f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid)) if err != nil { diff --git a/mount/sharedsubtree_linux.go b/mount/sharedsubtree_linux.go index cd9b86c..47303bb 100644 --- a/mount/sharedsubtree_linux.go +++ b/mount/sharedsubtree_linux.go @@ -2,34 +2,50 @@ package mount +// MakeShared ensures a mounted filesystem has the SHARED mount option enabled. +// See the supported options in flags.go for further reference. func MakeShared(mountPoint string) error { return ensureMountedAs(mountPoint, "shared") } +// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled. +// See the supported options in flags.go for further reference. func MakeRShared(mountPoint string) error { return ensureMountedAs(mountPoint, "rshared") } +// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled. +// See the supported options in flags.go for further reference. func MakePrivate(mountPoint string) error { return ensureMountedAs(mountPoint, "private") } +// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option +// enabled. See the supported options in flags.go for further reference. func MakeRPrivate(mountPoint string) error { return ensureMountedAs(mountPoint, "rprivate") } +// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled. +// See the supported options in flags.go for further reference. func MakeSlave(mountPoint string) error { return ensureMountedAs(mountPoint, "slave") } +// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled. +// See the supported options in flags.go for further reference. func MakeRSlave(mountPoint string) error { return ensureMountedAs(mountPoint, "rslave") } +// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option +// enabled. See the supported options in flags.go for further reference. func MakeUnbindable(mountPoint string) error { return ensureMountedAs(mountPoint, "unbindable") } +// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount +// option enabled. See the supported options in flags.go for further reference. func MakeRUnbindable(mountPoint string) error { return ensureMountedAs(mountPoint, "runbindable") }