Skip to content

Commit

Permalink
Remove macOS support
Browse files Browse the repository at this point in the history
OSXFUSE is no longer open source, see e.g.
https://colatkinson.site/macos/fuse/2019/09/29/osxfuse/

It looks like Apple is killing the whole category:
https://news.ycombinator.com/item?id=22251076

I will not personally put uncompensated effort into supporting
non-open source environments, especially ones that are this hostile to
work with. The macOS kludges were a significant amount of code, about
25% of the remaining non-test lines, and the primary source of
complexity and alternate code paths.

The API definitions will be remain for a short while, with deprecation
markers. This should let multiplatform callers work without changes.
Everything deprecated will be removed soon, so please adjust
your code.

Fixes #224
  • Loading branch information
tv42 committed Apr 15, 2020
1 parent 5883e5a commit 60eaf8f
Show file tree
Hide file tree
Showing 49 changed files with 237 additions and 1,702 deletions.
22 changes: 14 additions & 8 deletions doc/mount-linux-error-init.seq → doc/mount-error-init.seq
Expand Up @@ -17,16 +17,22 @@ seqdiag {
fusermount -> kernel [label="mount(2)"];
kernel ->> mounts [label="mount is visible"];
fusermount <-- kernel [label="mount(2) returns"];
fuse <<-- fusermount [diagonal, label="exit, receive /dev/fuse fd", leftnote="on Linux, successful exit here\nmeans the mount has happened,\nthough InitRequest might not have yet"];
app <-- fuse [label="Mount returns\nConn.Ready is already closed"];
fuse <<-- fusermount [diagonal, label="exit, receive /dev/fuse fd"];

app -> fuse [label="fs.Serve"];
fuse => kernel [label="read /dev/fuse fd", note="starts with InitRequest"];
fuse -> app [label="Init"];
fuse <-- app [color=red];
fuse => kernel [label="read /dev/fuse fd: InitRequest"];
fuse -> kernel [label="write /dev/fuse fd", color=red];
kernel -> kernel [label="set connection\nstate to error", color=red];
fuse <-- kernel;
... conn.MountError == nil, so it is still mounted ...
... call conn.Close to clean up ...

... Mount calls Unmount to clean up ...
fuse -> fusermount [label="fusermount -u"];
fusermount -> kernel;
kernel <<-- mounts;
fusermount <-- kernel;
fuse <<-- fusermount [diagonal];

fuse => kernel [label="close /dev/fuse fd"];
fuse <<-- kernel [diagonal, label="/dev/fuse is released"];

app <-- fuse [label="Mount returns", color=red];
}
Binary file added doc/mount-error-init.seq.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/mount-linux-error-init.seq.png
Binary file not shown.
Binary file removed doc/mount-linux.seq.png
Binary file not shown.
32 changes: 0 additions & 32 deletions doc/mount-osx-error-init.seq

This file was deleted.

Binary file removed doc/mount-osx-error-init.seq.png
Binary file not shown.
45 changes: 0 additions & 45 deletions doc/mount-osx.seq

This file was deleted.

Binary file removed doc/mount-osx.seq.png
Binary file not shown.
20 changes: 5 additions & 15 deletions doc/mount-sequence.md
Expand Up @@ -7,24 +7,14 @@ more complex API on us.

## Successful runs

On Linux, the mount is immediate and file system accesses wait until
the requests are served.
The mount is immediate and file system accesses wait until the requests are served.

![Diagram of Linux FUSE mount sequence](mount-linux.seq.png)

On OS X, the mount becomes visible only after `InitRequest` (and maybe
more) have been served.

![Diagram of OSXFUSE mount sequence](mount-osx.seq.png)
![Diagram of the mount sequence](mount.seq.png)


## Errors

Let's see what happens if `InitRequest` gets an error response. On
Linux, the mountpoint is there but all operations will fail:

![Diagram of Linux error handling](mount-linux-error-init.seq.png)

On OS X, the mount never happened:
Let's see what happens if `InitRequest` gets an error response.
The mountpoint is temporarily there but all operations will fail:

![Diagram of OS X error handling](mount-osx-error-init.seq.png)
![Diagram of error handling](mount-error-init.seq.png)
19 changes: 12 additions & 7 deletions doc/mount-linux.seq → doc/mount.seq
@@ -1,5 +1,5 @@
seqdiag {
// seqdiag -T svg -o doc/mount-osx.svg doc/mount-osx.seq
// seqdiag -T svg -o doc/mount.svg doc/mount.seq
app;
fuse [label="bazil.org/fuse"];
fusermount;
Expand All @@ -12,16 +12,21 @@ seqdiag {
fusermount -> kernel [label="mount(2)"];
kernel ->> mounts [label="mount is visible"];
fusermount <-- kernel [label="mount(2) returns"];
fuse <<-- fusermount [diagonal, label="exit, receive /dev/fuse fd", leftnote="on Linux, successful exit here\nmeans the mount has happened,\nthough InitRequest might not have yet"];
app <-- fuse [label="Mount returns\nConn.Ready is already closed", rightnote="InitRequest and StatfsRequest\nmay or may not be seen\nbefore Conn.Ready,\ndepending on platform"];
fuse <<-- fusermount [diagonal, label="exit, receive /dev/fuse fd"];

fuse => kernel [label="read /dev/fuse fd: InitRequest"];
fuse => kernel [label="write /dev/fuse fd: InitResponse"];

app <-- fuse [label="Mount returns"];

app -> fuse [label="fs.Serve"];
fuse => kernel [label="read /dev/fuse fd", note="starts with InitRequest"];
fuse => kernel [label="read /dev/fuse fd"];
fuse => app [label="FS/Node/Handle methods"];
fuse => kernel [label="write /dev/fuse fd"];
... repeat ...

... shutting down ...
fuse -> kernel [label="read /dev/fuse fd"];
app -> fuse [label="Unmount"];
fuse -> fusermount [label="fusermount -u"];
fusermount -> kernel;
Expand All @@ -31,11 +36,11 @@ seqdiag {
app <-- fuse [label="Unmount returns"];

// actually triggers before above
fuse <<-- kernel [diagonal, label="/dev/fuse EOF"];
fuse <-- kernel [diagonal, label="/dev/fuse EOF"];
app <-- fuse [label="fs.Serve returns"];

app -> fuse [label="conn.Close"];
fuse -> kernel [label="close /dev/fuse fd"];
fuse <-- kernel;
fuse => kernel [label="close /dev/fuse fd"];
fuse <<-- kernel [diagonal, label="/dev/fuse is released"];
app <-- fuse;
}
Binary file added doc/mount.seq.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 0 additions & 17 deletions error_darwin.go

This file was deleted.

11 changes: 5 additions & 6 deletions error_std.go
Expand Up @@ -4,17 +4,16 @@ package fuse
// across platforms.
//
// getxattr return value for "extended attribute does not exist" is
// ENOATTR on OS X, and ENODATA on Linux and apparently at least
// NetBSD. There may be a #define ENOATTR on Linux too, but the value
// is ENODATA in the actual syscalls. FreeBSD and OpenBSD have no
// ENODATA, only ENOATTR. ENOATTR is not in any of the standards,
// ENODATA exists but is only used for STREAMs.
// ENODATA on Linux and apparently at least NetBSD. There may be a
// #define ENOATTR on Linux too, but the value is ENODATA in the
// actual syscalls. FreeBSD and OpenBSD have no ENODATA, only ENOATTR.
// ENOATTR is not in any of the standards, ENODATA exists but is only
// used for STREAMs.
//
// Each platform will define it a errNoXattr constant, and this file
// will enforce that it implements the right interfaces and hide the
// implementation.
//
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/getxattr.2.html
// http://mail-index.netbsd.org/tech-kern/2012/04/30/msg013090.html
// http://mail-index.netbsd.org/tech-kern/2012/04/30/msg013097.html
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
Expand Down
8 changes: 0 additions & 8 deletions examples/clockfs/clockfs.go
Expand Up @@ -29,8 +29,6 @@ func run(mountpoint string) error {
mountpoint,
fuse.FSName("clock"),
fuse.Subtype("clockfsfs"),
fuse.LocalVolume(),
fuse.VolumeName("Clock filesystem"),
)
if err != nil {
return err
Expand Down Expand Up @@ -58,12 +56,6 @@ func run(mountpoint string) error {
if err := srv.Serve(filesys); err != nil {
return err
}

// Check if the mount process has an error to report.
<-c.Ready
if err := c.MountError; err != nil {
return err
}
return nil
}

Expand Down
8 changes: 0 additions & 8 deletions examples/hellofs/hello.go
Expand Up @@ -34,8 +34,6 @@ func main() {
mountpoint,
fuse.FSName("helloworld"),
fuse.Subtype("hellofs"),
fuse.LocalVolume(),
fuse.VolumeName("Hello world!"),
)
if err != nil {
log.Fatal(err)
Expand All @@ -46,12 +44,6 @@ func main() {
if err != nil {
log.Fatal(err)
}

// check if the mount process has an error to report
<-c.Ready
if err := c.MountError; err != nil {
log.Fatal(err)
}
}

// FS implements the hello world file system.
Expand Down
22 changes: 1 addition & 21 deletions fs/fstestutil/mounted.go
@@ -1,7 +1,6 @@
package fstestutil

import (
"errors"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -67,9 +66,6 @@ func (mnt *Mount) Close() {
// filesystem used is constructed by calling a function, to allow
// storing fuse.Conn and fs.Server in the FS.
//
// It also waits until the filesystem is known to be visible (OS X
// workaround).
//
// After successful return, caller must clean up by calling Close.
func MountedFunc(fn func(*Mount) fs.FS, conf *fs.Config, options ...fuse.MountOption) (*Mount, error) {
dir, err := ioutil.TempDir("", "fusetest")
Expand All @@ -96,27 +92,11 @@ func MountedFunc(fn func(*Mount) fs.FS, conf *fs.Config, options ...fuse.MountOp
serveErr <- server.Serve(filesys)
}()

select {
case <-mnt.Conn.Ready:
if err := mnt.Conn.MountError; err != nil {
return nil, err
}
return mnt, nil
case err = <-mnt.Error:
// Serve quit early
if err != nil {
return nil, err
}
//lint:ignore ST1005 uppercase because it's an idenfier
return nil, errors.New("Serve exited early")
}
return mnt, nil
}

// Mounted mounts the fuse.Server at a temporary directory.
//
// It also waits until the filesystem is known to be visible (OS X
// workaround).
//
// After successful return, caller must clean up by calling Close.
func Mounted(filesys fs.FS, conf *fs.Config, options ...fuse.MountOption) (*Mount, error) {
fn := func(*Mount) fs.FS { return filesys }
Expand Down
41 changes: 0 additions & 41 deletions fs/fstestutil/mountinfo_darwin.go

This file was deleted.

3 changes: 1 addition & 2 deletions fs/fstestutil/mountinfo_linux.go
Expand Up @@ -27,8 +27,7 @@ var fstabUnescape = strings.NewReplacer(
var errNotFound = errors.New("mount not found")

func getMountInfo(mnt string) (*MountInfo, error) {
// TODO delay a little to minimize an undiagnosed race between
// fuse.Conn.Ready and /proc/mounts
// TODO delay a little to minimize an undiagnosed race
// https://github.com/bazil/fuse/issues/228
time.Sleep(10 * time.Millisecond)
data, err := ioutil.ReadFile("/proc/mounts")
Expand Down

0 comments on commit 60eaf8f

Please sign in to comment.