|
|
|
@ -17,6 +17,7 @@ package fuse |
|
|
|
|
import ( |
|
|
|
|
"context" |
|
|
|
|
"fmt" |
|
|
|
|
"log" |
|
|
|
|
"net" |
|
|
|
|
"os" |
|
|
|
|
"os/exec" |
|
|
|
@ -53,11 +54,17 @@ func Mount( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Begin the mounting process, which will continue in the background.
|
|
|
|
|
if config.DebugLogger != nil { |
|
|
|
|
config.DebugLogger.Println("Beginning the mounting kickoff process") |
|
|
|
|
} |
|
|
|
|
ready := make(chan error, 1) |
|
|
|
|
dev, err := mount(dir, config, ready) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("mount: %v", err) |
|
|
|
|
} |
|
|
|
|
if config.DebugLogger != nil { |
|
|
|
|
config.DebugLogger.Println("Completed the mounting kickoff process") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Choose a parent context for ops.
|
|
|
|
|
cfgCopy := *config |
|
|
|
@ -65,6 +72,9 @@ func Mount( |
|
|
|
|
cfgCopy.OpContext = context.Background() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if config.DebugLogger != nil { |
|
|
|
|
config.DebugLogger.Println("Creating a connection object") |
|
|
|
|
} |
|
|
|
|
// Create a Connection object wrapping the device.
|
|
|
|
|
connection, err := newConnection( |
|
|
|
|
cfgCopy, |
|
|
|
@ -74,6 +84,9 @@ func Mount( |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("newConnection: %v", err) |
|
|
|
|
} |
|
|
|
|
if config.DebugLogger != nil { |
|
|
|
|
config.DebugLogger.Println("Successfully created the connection") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Serve the connection in the background. When done, set the join status.
|
|
|
|
|
go func() { |
|
|
|
@ -82,6 +95,10 @@ func Mount( |
|
|
|
|
close(mfs.joinStatusAvailable) |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
if config.DebugLogger != nil { |
|
|
|
|
config.DebugLogger.Println("Waiting for mounting process to complete") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Wait for the mount process to complete.
|
|
|
|
|
if err := <-ready; err != nil { |
|
|
|
|
return nil, fmt.Errorf("mount (background): %v", err) |
|
|
|
@ -110,13 +127,19 @@ func checkMountPoint(dir string) error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func fusermount(binary string, argv []string, additionalEnv []string, wait bool) (*os.File, error) { |
|
|
|
|
func fusermount(binary string, argv []string, additionalEnv []string, wait bool, debugLogger *log.Logger) (*os.File, error) { |
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Creating a socket pair") |
|
|
|
|
} |
|
|
|
|
// Create a socket pair.
|
|
|
|
|
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("Socketpair: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Creating files to wrap the sockets") |
|
|
|
|
} |
|
|
|
|
// Wrap the sockets into os.File objects that we will pass off to fusermount.
|
|
|
|
|
writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes") |
|
|
|
|
defer writeFile.Close() |
|
|
|
@ -124,6 +147,9 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool) |
|
|
|
|
readFile := os.NewFile(uintptr(fds[1]), "fusermount-parent-reads") |
|
|
|
|
defer readFile.Close() |
|
|
|
|
|
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Starting fusermount/os mount") |
|
|
|
|
} |
|
|
|
|
// Start fusermount/mount_macfuse/mount_osxfuse.
|
|
|
|
|
cmd := exec.Command(binary, argv...) |
|
|
|
|
cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3") |
|
|
|
@ -141,6 +167,9 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool) |
|
|
|
|
return nil, fmt.Errorf("running %v: %v", binary, err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Wrapping socket pair in a connection") |
|
|
|
|
} |
|
|
|
|
// Wrap the socket file in a connection.
|
|
|
|
|
c, err := net.FileConn(readFile) |
|
|
|
|
if err != nil { |
|
|
|
@ -148,12 +177,18 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool) |
|
|
|
|
} |
|
|
|
|
defer c.Close() |
|
|
|
|
|
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Checking that we have a unix domain socket") |
|
|
|
|
} |
|
|
|
|
// We expect to have a Unix domain socket.
|
|
|
|
|
uc, ok := c.(*net.UnixConn) |
|
|
|
|
if !ok { |
|
|
|
|
return nil, fmt.Errorf("Expected UnixConn, got %T", c) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Read a message from socket") |
|
|
|
|
} |
|
|
|
|
// Read a message.
|
|
|
|
|
buf := make([]byte, 32) // expect 1 byte
|
|
|
|
|
oob := make([]byte, 32) // expect 24 bytes
|
|
|
|
@ -175,6 +210,10 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool) |
|
|
|
|
|
|
|
|
|
scm := scms[0] |
|
|
|
|
|
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Successfully read the socket message.") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Pull out the FD returned by fusermount
|
|
|
|
|
gotFds, err := syscall.ParseUnixRights(&scm) |
|
|
|
|
if err != nil { |
|
|
|
@ -185,6 +224,9 @@ func fusermount(binary string, argv []string, additionalEnv []string, wait bool) |
|
|
|
|
return nil, fmt.Errorf("wanted 1 fd; got %#v", gotFds) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if debugLogger != nil { |
|
|
|
|
debugLogger.Println("Converting FD into os.File") |
|
|
|
|
} |
|
|
|
|
// Turn the FD into an os.File.
|
|
|
|
|
return os.NewFile(uintptr(gotFds[0]), "/dev/fuse"), nil |
|
|
|
|
} |
|
|
|
|