123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- package command
- import (
- "bufio"
- "fmt"
- "io"
- "os"
- "strings"
- "github.com/seaweedfs/fuse"
- )
- 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 %s"
- )
- // Info reveals information about a particular mounted filesystem. This
- // struct is populated from the content in the /proc/<pid>/mountinfo file.
- type Info struct {
- // 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
- }
- // Mounted determines if a specified mountpoint has been mounted.
- // On Linux it looks at /proc/self/mountinfo and on Solaris at mnttab.
- func mounted(mountPoint string) (bool, error) {
- entries, err := parseMountTable()
- if err != nil {
- return false, err
- }
- // Search the table for the mountPoint
- for _, e := range entries {
- if e.Mountpoint == mountPoint {
- return true, nil
- }
- }
- return false, nil
- }
- // Parse /proc/self/mountinfo because comparing Dev and ino does not work from
- // bind mounts
- func parseMountTable() ([]*Info, 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) ([]*Info, error) {
- var (
- s = bufio.NewScanner(r)
- out []*Info
- )
- for s.Scan() {
- if err := s.Err(); err != nil {
- return nil, err
- }
- var (
- p = &Info{}
- text = s.Text()
- optionalFields string
- )
- if _, err := fmt.Sscanf(text, mountinfoFormat,
- &p.ID, &p.Parent, &p.Major, &p.Minor,
- &p.Root, &p.Mountpoint, &p.Opts, &optionalFields); 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 found less than 3 fields post '-' in %q", text)
- }
- if optionalFields != "-" {
- p.Optional = optionalFields
- }
- p.Fstype = postSeparatorFields[0]
- p.Source = postSeparatorFields[1]
- p.VfsOpts = strings.Join(postSeparatorFields[2:], " ")
- out = append(out, p)
- }
- return out, nil
- }
- func osSpecificMountOptions() []fuse.MountOption {
- return []fuse.MountOption{
- fuse.AllowNonEmptyMount(),
- }
- }
- func checkMountPointAvailable(dir string) bool {
- mountPoint := dir
- if mountPoint != "/" && strings.HasSuffix(mountPoint, "/") {
- mountPoint = mountPoint[0 : len(mountPoint)-1]
- }
- if mounted, err := mounted(mountPoint); err != nil || mounted {
- return false
- }
- return true
- }
|