[[tags: egg]] == fuse [[toc:]] === Description A [[http://fuse.sourceforge.net/|FUSE]] interface. Installation requires the libfuse library and headers (API version 26) and a CHICKEN version 4.8.2 or newer. The source for this extension is available at [[https://bitbucket.org/evhan/chicken-fuse|Bitbucket]]. '''This extension's interface is subject to change without notice or deprecation period.''' ==== Requirements * [[/egg/concurrent-native-callbacks|concurrent-native-callbacks]] * [[/egg/foreigners|foreigners]] * [[/egg/matchable|matchable]] ==== Platform Notes '''This extension is only officially supported on Linux and OpenBSD.''' It has also been installed successfully on FreeBSD and Mac OS X, but tested far less thoroughly on those platforms. On OpenBSD, each filesystem's main loop is single-threaded, the '''{{{ioctl:}}}''' callback is not available, and stopping a filesystem via {{filesystem-stop!}} is significantly slower than stopping it via {{umount(2)}}. ==== Runtime Structure Each filesystem is executed in a separate native thread that communicates with the (single, shared) CHICKEN runtime via Unix pipe, per [[/egg/concurrent-native-callbacks|concurrent-native-callbacks]]. More than one filesystem can be run at once, but FUSE operations are synchronous across all filesystems so long-running callbacks should be avoided. More importantly, care must be taken not to deadlock the Scheme runtime by requesting a filesystem operation from within CHICKEN that itself requires a response from CHICKEN, for example by accessing a file that's part of a running filesystem. The easiest way to avoid this situation is to run each filesystem in a more-or-less dedicated OS-level process whose sole responsibility is to service FUSE requests. === API filesystem (filesystem? object) -> boolean A {{filesystem}} is an opaque, {{defstruct}}-style record type representing a set of FUSE filesystem operations. (make-filesystem #!key ...) -> filesystem Create a FUSE filesystem. The keyword arguments to {{make-filesystem}} specify the resulting {{filesystem}}'s callback procedures. Each {{}} should be one the following: ; {{access:}}: {{(procedure path mode) -> value}} ; {{chmod:}}: {{(procedure path mode) -> value}} ; {{chown:}}: {{(procedure uid gid) -> value}} ; {{create:}}: {{(procedure path mode) -> (or handle #f)}} ; {{destroy:}}: {{(procedure) -> void}} ; {{flush:}}: {{(procedure path) -> value}} ; {{fsync:}}: {{(procedure path) -> value}} ; {{getattr:}}: {{(procedure path) -> (or (vector mode nlink uid gid size atime ctime mtime) #f)}} ; {{init:}}: {{(procedure) -> void}} ; {{ioctl:}}: {{(procedure path int pointer) -> value}} ; {{link:}}: {{(procedure path path) -> value}} ; {{mkdir:}}: {{(procedure path mode) -> value}} ; {{mknod:}}: {{(procedure path mode) -> value}} ; {{open:}}: {{(procedure path mode) -> (or handle #f)}} ; {{readdir:}}: {{(procedure path) -> (or (list path ...) value)}} ; {{readlink:}}: {{(procedure path) -> (or path #f)}} ; {{read:}}: {{(procedure handle size offset) -> (or size string value)}} ; {{release:}}: {{(procedure handle) -> value}} ; {{rename:}}: {{(procedure path path) -> value}} ; {{rmdir:}}: {{(procedure path) -> value}} ; {{statfs:}}: {{(procedure path) -> (or (vector bsize blocks bfree bavail files ffree namemax) #f)}} ; {{symlink:}}: {{(procedure path path) -> value}} ; {{truncate:}}: {{(procedure path) -> value}} ; {{unlink:}}: {{(procedure path) -> value}} ; {{utimens:}}: {{(procedure path atime mtime) -> value}} ; {{write:}}: {{(procedure handle string offset) -> (or size string value)}} {{offset}}, {{size}}, {{mode}}, {{nlink}}, {{uid}}, {{gid}}, {{size}}, {{atime}}, {{ctime}} and {{mtime}} are numeric values with the obvious meanings. A {{path}} is a pathname string. {{bsize}}, {{blocks}}, {{bfree}}, {{bavail}}, {{files}}, {{ffree}} and {{namemax}} are positive numeric values corresponding to the {{statvfs(2)}} struct members of the same names. A {{value}} may be any Scheme object and indicates whether the filesystem operation was successful. When {{#f}}, the filesystem will indicate a nonexistent file ({{ENOENT}}); any other value indicates success. Callbacks should signal other types of failures by raising an appropriate {{errno(3)}} value. For example, to signal insufficient permissions, an '''{{access:}}''' operation should {{(raise errno/perm)}}. A {{handle}} may be any Scheme object and represents a file handle. When returned as the result of an '''{{open:}}''' or '''{{create:}}'''callback, this value is provided to that file's subsequent '''{{read:}}''', '''{{write:}}''' and '''{{release:}}''' operations. Note that this object is evicted into static memory (via {{object-evict}}) until just before '''{{release:}}''', so it is more efficient (as well as memory-safe) to use simple values as file handles; the same caveats that apply to {{object-evict}} apply here. '''{{release:}}''' is guaranteed to be called once for every successful '''{{open:}}''', while '''{{read:}}''' and '''{{write:}}''' should be prepared to be called multiple times with diverse {{offset}} values. (filesystem-start! path filesystem) -> (or #f undefined) Start {{filesystem}} at the given {{path}}. {{path}} should be a pathname string indicating an empty directory. On successful startup, the filesystem is mounted, its '''{{init:}}''' callback is executed, any threads waiting for the filesystem to start are unblocked, and a non-{{#f}} value is returned. On failure, {{#f}} is returned immediately. {{filesystem-start!}} does not wait for filesystem initialization before returning. To block until the filesystem is becomes available, use {{filesystem-wait!}}. The effective exception handler for the filesystem's operations at {{path}} is that of the call to {{filesystem-start!}}'s dynamic environment, and must ''always'' return with a suitable {{errno(3)}} integer value. Failure to do so may result in orphaned mounts, infinite loops, and locusts. (filesystem-stop! path filesystem) -> undefined Stop {{filesystem}} at the given {{path}}. {{path}} should be a pathname string and must exactly match the value provided to {{filesystem-start!}} when the {{filesystem}} was started (according to {{string=?}}). If the given {{filesystem}} isn't currently mounted at {{path}}, this procedure is a noop. Otherwise, the filesystem is unmounted, any threads waiting for the filesystem to stop are unblocked, and its '''{{destroy:}}''' callback is executed. {{filesystem-stop!}} does not wait for filesystem shutdown before returning. To block until the filesystem is fully stopped, use {{filesystem-wait!}}. (filesystem-wait! path filesystem [status]) -> undefined Block until {{filesystem}} is started or stopped at {{path}}. {{path}} should be a pathname string and must exactly match the value provided to {{filesystem-start!}} when the {{filesystem}} was started (according to {{string=?}}). The optional {{status}} argument should be a symbol indicating the filesystem state for which to wait, either {{started}} or {{stopped}}. By default, {{(eq? status stopped)}}. (filesystem-running? path filesystem) -> boolean Determine whether {{filesystem}} is currently running at {{path}}. {{path}} should be a pathname string and must exactly match the value provided to {{filesystem-start!}} when the {{filesystem}} was started (according to {{string=?}}). file/fifo file/chr file/blk file/reg file/dir file/lnk file/sock These values correspond to the {{S_IF*}} flags specified by {{stat(2)}}. They're not FUSE-specific, but may be useful when defining '''{{getattr:}}''' callbacks. === Examples Usage examples can be found in the project's [[https://bitbucket.org/evhan/chicken-fuse/src/master/examples/|examples]] directory. === Author [[/users/evan-hanson|Evan Hanson]] Credit to [[/users/ivan-raikov|Ivan Raikov]] for initial work on libfuse bindings and inspiration for the keyword-based API. Credit to [[/users/jorg-wittenberger|Jörg Wittenberger]] for lots of helpful bug hunting. === License Copyright (c) 2013-2014, 3-Clause BSD.