diff --git a/fuse/mount.go b/fuse/mount.go new file mode 100644 index 000000000..874d9c459 --- /dev/null +++ b/fuse/mount.go @@ -0,0 +1,48 @@ +package fuse + +import ( + "fmt" + "net" + "os" + "syscall" +) + +func getConnection(local *os.File) (int, error) { + conn, err := net.FileConn(local) + if err != nil { + return 0, err + } + defer conn.Close() + unixConn := conn.(*net.UnixConn) + + var data [4]byte + control := make([]byte, 4*256) + + _, oobn, _, _, err := unixConn.ReadMsgUnix(data[:], control[:]) + if err != nil { + return 0, err + } + + messages, err := syscall.ParseSocketControlMessage(control[:oobn]) + if err != nil { + return 0, err + } + if len(messages) != 1 { + return 0, fmt.Errorf("getConnection: expect 1 control message, got %#v", messages) + } + message := messages[0] + + fds, err := syscall.ParseUnixRights(&message) + if err != nil { + return 0, err + } + if len(fds) != 1 { + return 0, fmt.Errorf("getConnection: expect 1 fd, got %#v", fds) + } + fd := fds[0] + + if fd < 0 { + return 0, fmt.Errorf("getConnection: fd < 0: %d", fd) + } + return fd, nil +} diff --git a/fuse/mount_darwin.go b/fuse/mount_darwin.go index 1112799bb..cabdaa29c 100644 --- a/fuse/mount_darwin.go +++ b/fuse/mount_darwin.go @@ -11,7 +11,6 @@ import ( "os/exec" "strings" "syscall" - "unsafe" ) func unixgramSocketpair() (l, r *os.File, err error) { @@ -90,33 +89,6 @@ func unmount(dir string, opts *MountOptions) error { return syscall.Unmount(dir, 0) } -func getConnection(local *os.File) (int, error) { - var data [4]byte - control := make([]byte, 4*256) - - // n, oobn, recvflags, from, errno - todo: error checking. - _, oobn, _, _, - err := syscall.Recvmsg( - int(local.Fd()), data[:], control[:], 0) - if err != nil { - return 0, err - } - - message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0])) - fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr)) - - if message.Type != syscall.SCM_RIGHTS { - return 0, fmt.Errorf("getConnection: recvmsg returned wrong control type: %d", message.Type) - } - if oobn <= syscall.SizeofCmsghdr { - return 0, fmt.Errorf("getConnection: too short control message. Length: %d", oobn) - } - if fd < 0 { - return 0, fmt.Errorf("getConnection: fd < 0: %d", fd) - } - return int(fd), nil -} - func fusermountBinary() (string, error) { binPaths := []string{ "/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse", diff --git a/fuse/mount_linux.go b/fuse/mount_linux.go index c6abf035e..96111d3b7 100644 --- a/fuse/mount_linux.go +++ b/fuse/mount_linux.go @@ -12,7 +12,6 @@ import ( "path" "strings" "syscall" - "unsafe" ) func unixgramSocketpair() (l, r *os.File, err error) { @@ -203,33 +202,6 @@ func unmount(mountPoint string, opts *MountOptions) (err error) { return err } -func getConnection(local *os.File) (int, error) { - var data [4]byte - control := make([]byte, 4*256) - - // n, oobn, recvflags, from, errno - todo: error checking. - _, oobn, _, _, - err := syscall.Recvmsg( - int(local.Fd()), data[:], control[:], 0) - if err != nil { - return 0, err - } - - message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0])) - fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr)) - - if message.Type != 1 { - return 0, fmt.Errorf("getConnection: recvmsg returned wrong control type: %d", message.Type) - } - if oobn <= syscall.SizeofCmsghdr { - return 0, fmt.Errorf("getConnection: too short control message. Length: %d", oobn) - } - if fd < 0 { - return 0, fmt.Errorf("getConnection: fd < 0: %d", fd) - } - return int(fd), nil -} - // lookPathFallback - search binary in PATH and, if that fails, // in fallbackDir. This is useful if PATH is possible empty. func lookPathFallback(file string, fallbackDir string) (string, error) {