84 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package mount
 | 
						|
 | 
						|
// On Solaris we can't invoke the mount system call directly.  First,
 | 
						|
// the mount system call takes more than 6 arguments, and go doesn't
 | 
						|
// support invoking system calls that take more than 6 arguments.  Past
 | 
						|
// that, the mount system call is a private interfaces.  For example,
 | 
						|
// the arguments and data structures passed to the kernel to create an
 | 
						|
// nfs mount are private and can change at any time.  The only public
 | 
						|
// and stable interface for creating mounts on Solaris is the mount.8
 | 
						|
// command, so we'll invoke that here.
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"os/exec"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"golang.org/x/sys/unix"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	mountCmd = "/usr/sbin/mount"
 | 
						|
)
 | 
						|
 | 
						|
func doMount(arg ...string) error {
 | 
						|
	cmd := exec.Command(mountCmd, arg...)
 | 
						|
 | 
						|
	/* Setup Stdin, Stdout, and Stderr */
 | 
						|
	stderr := new(bytes.Buffer)
 | 
						|
	cmd.Stdin = nil
 | 
						|
	cmd.Stdout = nil
 | 
						|
	cmd.Stderr = stderr
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Run the command.  If the command fails create a new error
 | 
						|
	 * object to return that includes stderr output.
 | 
						|
	 */
 | 
						|
	err := cmd.Start()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	err = cmd.Wait()
 | 
						|
	if err != nil {
 | 
						|
		return errors.New(fmt.Sprintf("%v: %s", err, stderr.String()))
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (m *Mount) Mount(target string) error {
 | 
						|
	var err error
 | 
						|
 | 
						|
	if len(m.Options) == 0 {
 | 
						|
		err = doMount("-F", m.Type, m.Source, target)
 | 
						|
	} else {
 | 
						|
		err = doMount("-F", m.Type, "-o", strings.Join(m.Options, ","),
 | 
						|
			m.Source, target)
 | 
						|
	}
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func Unmount(mount string, flags int) error {
 | 
						|
	return unix.Unmount(mount, flags)
 | 
						|
}
 | 
						|
 | 
						|
// UnmountAll repeatedly unmounts the given mount point until there
 | 
						|
// are no mounts remaining (EINVAL is returned by mount), which is
 | 
						|
// useful for undoing a stack of mounts on the same mount point.
 | 
						|
func UnmountAll(mount string, flags int) error {
 | 
						|
	for {
 | 
						|
		if err := Unmount(mount, flags); err != nil {
 | 
						|
			// EINVAL is returned if the target is not a
 | 
						|
			// mount point, indicating that we are
 | 
						|
			// done. It can also indicate a few other
 | 
						|
			// things (such as invalid flags) which we
 | 
						|
			// unfortunately end up squelching here too.
 | 
						|
			if err == unix.EINVAL {
 | 
						|
				return nil
 | 
						|
			}
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |