Jump to:  OMake Home • Guide Home • Guide (single-page) • Contents (short) • Contents (long)
Index:  All • Variables • Functions • Objects • Targets • Options

Chapter 19  The Fuse binding

Fuse is a “Filesystem in userspace” module. Essentially, Fuse makes it possible for a normal Unix user to write a program that implements a filesystem, then mount and use that filesystem [at time of writing, there is no Win32 port].

The model for Fuse is based on VFS (virtual filesystem), a generic filesystem interface for Unix-like kernels. VFS is neither a specific nor standard API. The first widespread VFS API was developed by Sun Microsystems, and the idea behind the design has been adopted, in similar form, by many other Unix variants. However, VFS is kernel-only: it provides a way for Unix system calls to access the filesystem in a generic way.

FUSE changes this in two ways. Probably the most important is that it provides a userspace interface, so that it can be used by normal users without administrator/root priviledges. As a secondary benefit, it provides an unofficial standard for filesystem implementations. The interface borrows its model of VFS.

In this section, we document an OCaml/OMake port for the high-level interface, based on a set of filesystem callback functions.

19.1  The Fuse Object

In OMake, a Fuse object represents a filesystem. It is implemented with the following constants and methods.

19.2  Constants

19.2.1  Error codes

The error codes have the standard meanings; see the man page errno(2) for an explanation of the error codes.

In the high level interface, a method returns 0 or a positive number on success, or else a negated error code on failure.

19.2.2  Constants for stat

These stat constants represent file modes and attributes. See the man page for stat(2) for more detail.

19.2.3  Timespec

A file time.

Fields:

19.2.4  OpenStat

The object OpenStat provides a method OpenStat.of-stat(stat) that takes a normal Stat 11.5.2 object and converts it to a Fuse OpenStat object.

Fields:

19.2.5  Fuse

The Fuse object implements a filesystem, defined by a set of callbacks. For the Fuse object, the callbacks are implemented as methods. To define a filesystem, one implements some or all of the filesystem's methods. In most cases, it is acceptable to leave some of the methods unimplemented, the default behavior is often sufficient.

19.2.6  Fuse.getattr

getattr(name : String, stat : Stat)

Get the file attributes. name is the name of the file, relative to the filesystem mount point. The stat argument should be filled in with the file's information. The function coerce-Stat can be used for this purposed.

19.2.7  Fuse.readlink

readlink(name : String, buffer : char *, len : nativeint)

The name refers to a symbolic link. The method should copy the target of the link into the buffer. The function strncpy can be used for copying the string.

19.2.8  Fuse.mknod

mknod(name : String, mode : nativeint, dev : nativeint)

Create a file or device with the given mode.

19.2.9  Fuse.mkdir

mkdir(name : String, mode : nativeint)

Create a directory with the given mode.

19.2.10  Fuse.unlink

unlink(name : String)

Unlink (remove) the specified file.

19.2.11  Fuse.rmdir

rmdir(name : String)

Remove the specified directory.

19.2.12  Fuse.symlink

symlink(name : String, link : String)

Create a symbolic link. The name is the name of the link, the link is the target of the link.

19.2.13  Fuse.rename

rename(name1 : String, name2 : String)

Rename (mv) a file.

19.2.14  Fuse.link

link(name1 : String, name2 : String)

Create a hard link. The name1 is the name of the file to be created, and name2 is the file it refers to.

19.2.15  Fuse.chmod

chmod(name : String, mode : nativeint)

Change the permission of a file, device, or directory.

19.2.16  Fuse.chown

chown(name : String, uid : nativeint, gid : nativeint)

Change the owner and group for a file.

19.2.17  Fuse.truncate

truncate(name : String, len : nativeint)

Change the length of a file. As usual, the length may be longer than the current length of the file.

19.2.18  Fuse.utime

utime(name : String, time : Timespec)

Change the modification time for a file.

19.2.19  Fuse.open

open(name : String, info)

Open a file. This is mainly an optimization—you may wish to initialize some data structures when the file is opened.

19.2.20  Fuse.read

read(name : String, buffer : char *, size : nativeint, off : nativeint)

Read some data from the file. The function should return the total number of bytes read, or a negative errno on failure.

19.2.21  Fuse.write

write(name : String, buffer : char *, size : nativeint, off : nativeint)

Write some data to a file. The function should return the total number of bytes written, or a negative errno on failure.

19.2.22  Fuse.statfs

statfs(name : String, stat : Statfs)

Fetch the filesystem information.

19.2.23  Fuse.flush

flush(name : String, info)

Flush the file to disk. This is an optimization.

19.2.24  Fuse.release

release(name : String, info)

A process has closed the file. Note that this doesn't mean the file is closed, because there may be other processes that have opened the file.

19.2.25  Fuse.fsync

fsync(name : String, sync, info)

Sync the file, flushing the contents to permanent storage.

19.2.26  Fuse.setxattr

setxattr(name : String, attr : String, buffer : char*, size : nativeint, i : nativeint)

Set an extended attribute.

19.2.27  Fuse.getxattr

getxattr(name : String, attr : String, buffer : char*, size : nativeint)

Get an extended attribute.

19.2.28  Fuse.listxattr

listxattr(name : String, buffer : char*, size : nativeint)

List the names of all the extended attributes.

19.2.29  Fuse.removexattr

removexattr(name : String, attr : String)

Remove an extended attribute.

19.2.30  Fuse.opendir

opendir(name : String, info)

Prepare a directory for reading.

19.2.31  Fuse.readdir

readdir(name : String, buffer : char*, fill-dir, off : nativeint, info)

Read the next directory entry.

19.2.32  Fuse.releasedir

releasedir(name : String, info)

A process has closed the directory, and is no longer reading from it.

19.2.33  Fuse.fsyncdir

fsyncdir(name : String, sync, info)

Flush a directory to permanent storage.

19.2.34  Fuse.init

init(conn)

Called when the filesystem is first created.

19.2.35  Fuse.destroy

destroy(data)

Called when the filesystem is unmounted.

19.2.36  Fuse.access

access(name : String, mode : nativeint)

Check that the given access should be allowed. See the man page for access(2).

19.2.37  Fuse.create

create(name : String, mode : nativeint, info)

Create an empty file with the given mode. The file should ot already exist.

19.2.38  Fuse.ftruncate

ftruncate(name : String, off : nativeint, info)

Change the length of the file.

19.2.39  Fuse.fgetattr

fgetattr(name : String, stat : Stat, info)

Get the stat(2) attributes of the file.

19.2.40  Fuse.lock

lock(name : String, info, cmd, lock)

Manage file locks.

19.2.41  Fuse.utimens

utimens(name : String, tv : Timeval)

Change the file times.

19.2.42  Fuse.bmap

bmap(name : String, blocksize : nativeint, idx)

[JYH: I believe this is supposed to return a bitmask specifying which of the file's blocks are actually allocated on disk (for sparse files).]

19.3  An example

Here is a filesystem that has a single file /foo with contents Hello world\n.

open fuse

TimeZero. =
    extends $(timespec)
    tv_sec = 0
    tv_nsec = 0

FileZero. =
    extends $(_OpenStat)

    st_dev = 0
    st_ino = 1
    st_mode = 0o100777
    st_nlink = 1
    st_uid = 0
    st_gid = 0
    st_rdev = 0
    st_atimespec = $(TimeZero)
    st_mtimespec = $(TimeZero)
    st_ctimespec = $(TimeZero)
    st_size = 12
    st_blocks = 1
    st_blksize = 4096
    st_flags = 0
    st_gen = 0

DirZero. =
    extends $(FileZero)
    st_ino = 2
    st_mode = 0o40777

hellofs. =
    extends $(Fuse)

    getattr(name, stat) =
        eprintln(+++ getattr: $(name))
        switch $(name)
        case /
            coerce_Stat($(stat), $(DirZero))
            value 0
        case /foo
            coerce_Stat($(stat), $(FileZero))
            value 0
        default
            neg($(ENOENT))

    open-file(name, info) =
        eprintln(+++ open: $(name))
        switch $(name)
        case /foo
            value 0
        default
            neg($(ENOENT))

    hello = $(void-p $(dll-pointer-of-string $"Hello world$(nl)"))

    read(name, buffer, size, off, info) =
        eprintln(+++ read: $(name))
        switch $(name)
        case /foo
            memcpy($(void-p $(buffer)), $(hello), $(size))
            value $(size)
        default
            neg($(ENOENT))

    opendir(name, info) =
        eprintln(+++ opendir: $(name))
        switch $(name)
        case /
            value 0
        default
            neg($(ENOTDIR))

    readdir(name, buf, fill-dir, off, info) =
        eprintln(+++ readdir: $(name))
        switch $(name)
        case /
            foo = $(dll-pointer-of-string foo)
            stat = $(make_Stat $(FileZero))
            fuse_apply_fill_dir($(fill-dir), $(buf), $(foo), $(stat), 0)
            value 0
        default
            neg($(ENOTDIR))

hellofs.main(fuse /tmp/fuse -d)
Jump to:  OMake Home • Guide Home • Guide (single-page) • Contents (short) • Contents (long)
Index:  All • Variables • Functions • Objects • Targets • Options