Rust FUSE - Filesystem in Userspace

Rust library crate for easy implementation of Crate documentation

Rust FUSE - Filesystem in Userspace

About

fuse-rs is a Rust library crate for easy implementation of FUSE filesystems in userspace.

fuse-rs does not just provide bindings, it is a rewrite of the original FUSE C library to fully take advantage of Rust's architecture.

Documentation

Crate documentation

Details

A working FUSE filesystem consists of three parts:

  1. The kernel driver that registers as a filesystem and forwards operations into a communication channel to a userspace process that handles them.
  2. The userspace library (libfuse) that helps the userspace process to establish and run communication with the kernel driver.
  3. The userspace implementation that actually processes the filesystem operations.

The kernel driver is provided by the FUSE project, the userspace implementation needs to be provided by the developer. fuse-rs provides a replacement for the libfuse userspace library between these two. This way, a developer can fully take advantage of the Rust type interface and runtime features when building a FUSE filesystem in Rust.

Except for a single setup (mount) function call and a final teardown (unmount) function call to libfuse, everything runs in Rust.

Dependencies

FUSE must be installed to build or run programs that use fuse-rs (i.e. kernel driver and libraries. Some platforms may also require userland utils like fusermount). A default installation of FUSE is usually sufficient.

To build fuse-rs or any program that depends on it, pkg-config needs to be installed as well.

Linux

FUSE for Linux is available in most Linux distributions and usually called fuse. To install on a Debian based system:

Install on CentOS:

To build, FUSE libraries and headers are required. The package is usually called libfuse-dev or fuse-devel. Also pkg-config is required for locating libraries and headers.

macOS

Installer packages can be downloaded from the FUSE for macOS homepage.

To install using Homebrew:

To install pkg-config (required for building only):

FreeBSD

Install packages fusefs-libs and pkgconf.

Usage

Put this in your Cargo.toml:

To create a new filesystem, implement the trait fuse::Filesystem. See the documentation for details or the examples directory for some basic examples.

To Do

There's still a lot of stuff to be done. Feel free to contribute. See the list of issues on GitHub and search the source files for comments containing "TODO" or "FIXME" to see what's still missing.

Compatibility

Developed and tested on macOS. Tested under Linux, macOS and FreeBSD using stable, beta and nightly Rust versions (see CI for details).

Contribution

Fork, hack, submit pull request. Make sure to make it useful for the target audience, keep the project's philosophy and Rust coding standards in mind. For larger or essential changes, you may want to open an issue for discussion first. Also remember to update the Changelog if your changes are relevant to the users.

Issues

Collection of the latest Issues

liamnaddell

liamnaddell

1

I'm coming from the redox-os project which relies on fuse to build redoxfs.

Steps to reproduce:

install fuse3, clone fuse-rs, run cargo build.

how to fix: When I switch the build.rs to search for fuse3 instead of fuse, the package compiles perfectly.

mike-kfed

mike-kfed

1

I checked on my Apple M1 powered machine (where the old osxfuse 3.x does not run anymore). Here are the steps to reproduce:

  • install macFUSE 4.0.5 from the osxfuse.github.io website binary package
  • brew install pkg-config
  • edit fuse-sys/build.rs and also use LIBFUSE_NAME = "fuse" for macOS like for any OS
  • cargo run --example hello -- mountpoint works fine
  • cargo test runs fine

I was thinking to make a pull request for this, but I am not sure how you want to handle this. One option to check for the macFUSE 4.x series is to test for existence of the file /Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse as the program was renamed from osxfuse 3.x to macfuse 4.x = this makes sure the system has v4 installed. This file check can be added to build.rs to decide the LIBFUSE_NAME, but this means the LIBFUSE_NAME cannot be static anymore (at least I think it'll come from a function, unless there is some macro magic that I don't know of).

Other option is to make macfuse 4 support a cfg-feature flag? May make sense, as version 4 and above are no longer open source and this way users actively have to choose to compile against the non-OSS version? However osxfuse v3 is deprecated on homebrew, so easy v3 install will go away at some point (and already went away on M1) meaning the binary only v4 install is the future as of now.

for any of those two options, install instructions for macOS need updating accordingly. Not sure how this will integrate with CI testing though. I will happily provide a pull request for all this if you want, just let me know how you prefer to check for osxfuse v3 vs. v4 on macOS in the build.rs

changweige

changweige

0

Hi, After a quick glance at this fuse-rs crate. If I didn't miss something, it seems that it can't be interrupted when reading(receive()) messages from fuse device like what libfuse does. Is that not essential for a fuse library? Looks like that this fuse-rs relies on umount(2) to close in-kernel fuse device fd to unblock read(2). Can we just interrupt read(2) and make relevant threads exit in an elegant way. Or is Rust thread model limits?

samuela

samuela

8

It looks like the latest version on cargo is 0.3.1, but that version still depends on an old version of time (pre-0.2.0). It's also 3 years old now. Would it be possible to get a new cargo release put out?

gsurrel

gsurrel

1

I have a panic with the two examples. I have installed fuse first with brew (with a reboot), then with the package provided on the website, but the behavior is the same:

Am I missing anything? I was following the readme at the project's root.

Sherlock-Holo

Sherlock-Holo

2

I want to handle the file lock in fuse not kernel, so I implement setlk and getlk method, but I don't see any log about them, even I write a panic!("boom"), the fuse doesn't panic.

Am I doing wrong? If I am wrong, how do I implement them rightly

Sherlock-Holo

Sherlock-Holo

0

I read the doc but it doesn't mention how to handle interrupted when setlk is waiting.

If user try to setlk, but he waits for a long time, so he presses Ctrl+C and the fd is closed, how do I know this?

vi

vi

8

ioctl(TCGETS) on a file opened from a filesystem implemented with fuse-rc causes filesystem to be unmounted:

Such ioctl is issued e.g. by git gui on file .git/HEAD for some reason.

Using Linux kernel version 4.19.85.

akhi3030

akhi3030

0

Currently, the value of max_write is hardcoded in https://github.com/zargony/fuse-rs/blob/master/src/request.rs#L93. This is a bit problematic for my usecase where I want to be able to create file sytems with different max_write` parameters.

I have a patch which I will submit as a PR shortly that implements the above. However, the PR changes the API of mount and spawn_mount. Given the existing API, I wasn't sure how else to introduce this feature. Feedback is welcome.

vi

vi

5

README:

Rust-FUSE does not just provide bindings, it is a rewrite of the original FUSE C library to fully take advantage of Rust's architecture.

Changelog:

Link libosxfuse on macOS, libfuse on all other systems.

Where's the truth? I supposed it only needed fusermount suid executable, not the library.


Can I cross-compile projects using rust-fuse without having C compiler or libraries around? Or how else can I use advantages of it being "not just the bindings"?

asyade

asyade

2

I work a lot with rust-fuse under Android however there is a lot of adjustment to make it work, several reasons for this:

  • Libfuse is mostley unavailable (mountpoint must be mount from the FUSE device using libc::mount).
  • FUSE filesystem can only be mounted from a root process.
  • There is some Android kernel specific FUSE operations that are actually very specific to the FAT emulation layer of Android.
  • On Android device mountpoint must match the FAT emulation layer.

for theses reasons a native rust mount feature must be written, a remove-all of the libfuse depandancy and some OS specific op code to make it work. Currently all these features are available into my fork although some rewriting is required to maintain code quality so I wonder if it's worth to start a serious PR for the addition of Android support or these too specific changes and low demand make it should stay in a indepandant fork.

Dawen18

Dawen18

question
1

Hi, I have only fuse3 installed and not fuse. When I build, I have this message

But I have installed Fuse from libfuse repository and pkg-config found it

Do I install libfuse-dev like in #54 ? If I build with Fuse2 is this compatible with Fuse3?

wwylele

wwylele

enhancement
2

Currently if a ReplyRaw drops without a reply, it sends a EIO and logs a warning https://github.com/zargony/rust-fuse/blob/73b841a544e33f58d1034df247457ce40208ec83/src/reply.rs#L189-L194

This however is not good for debugging errors like forgetting to put a reply in the code. The usage of log is not documented, while one must be aware of it and link a logger library in the executable (and potentially adjust the log level) to see the log. This makes the default behaviour effectively silent EIO reply, which can be mixed with other intended EIO from the executable. IMO the library should just panic on missing reply, as one should always explicitly return EIO if it is intended, and missing reply is almost definitely an mistake.

If you insist on keeping this a warning, please document the usage of log to help debugging.

jmmv

jmmv

enhancement
3

This issue is to start a discussion to see whatever is needed to support newer kernel protocol versions. I'm particularly interested in this for two reasons: first, to support parallelization, which shouldn't be too difficult; and, second but more complex, to support cache invalidations.

Now, the question is: do we need to worry about maintaining compatibility with the older protocol versions? Why?

The current library supports protocol version 7.8, but this is ancient. Looking at the history of fuse_kernel.h, the oldest changes recorded are from 2008 and they already document 7.11, which means 7.8 is likely some years older. I don't think it's worth supporting such old versions, if only because I doubt the Rust toolchain could be used to target the corresponding old Linux distributions.

That said, this doesn't mean "ignore all older versions" because some protocol versions are quite recent and supporting their differences is probably a necessity. But... that also depends on whoever the users of this library are. If they don't care about older versions (I, as a user, do not for example)... maybe the library shouldn't either until the demand appears, for simplicity reasons.

So the question is: what should be the minimum protocol version that we are willing to support? Once that is fixed, we can see how the newer features should optionally be exposed. But I think targeting 7.8 as the minimum version is a mistake.

CC @kornholi

asomers

asomers

enhancement
0

The current signature of fuse::mount requires providing an actual array of &OsStr references. Those are annoying to create, especially from constants. It would be more ergonomic if it could take any argument that implements AsRef<OsStr>. It would look something like this:

asomers

asomers

enhancement
3

It would be nice to be able to unit test my filesystem's FUSE interface. Right now the only way to test it is to mount an actual filesystem and use the command line. But if rust-fuse did the following, then I would be able to write tests that hook into my filesystem's rust-fuse interface and exercise the whole API. This would require:

  • Public constructor (possibly Default for Request)
  • Public constructors for all the various Reply types.
  • Public accessors for the various Reply types, for example to see the data stored by ReplyData::data.

Information - Updated Jun 15, 2022

Stars: 856
Forks: 123
Issues: 53

Repositories & Extras

Rust bindings for libinjection

Add libinjection to dependencies of Cargo

Rust bindings for libinjection

Rust bindings for the C++ api of PyTorch

LIghtweight wrapper for pytorch eg libtorch in rust

Rust bindings for the C++ api of PyTorch

Rust leveldb bindings

Almost-complete bindings for leveldb for Rust

Rust leveldb bindings

Cross-platform filesystem notification library for Rust

Add file-system notifications via this library for Rust

Cross-platform filesystem notification library for Rust

Catfs is a caching filesystem written in Rust

Catfs allows you to have cached access to another (possibly remote)

Catfs is a caching filesystem written in Rust

a tool to analyze file system usage written in Rust

coloured output, according to the LS_COLORS environment variable

a tool to analyze file system usage written in Rust

FUSE (Filesystem in Userspace) for Rust

FUSE-Rust is a FUSE filesystems in userspace

FUSE (Filesystem in Userspace) for Rust

Rust library to manipulate file system access control lists (ACL) on macOS, Linux, and FreeBSD

This module provides two high level functions, getfacl and setfacl

Rust library to manipulate file system access control lists (ACL) on macOS, Linux, and FreeBSD

A file abstraction system for Rust

Chicon is a library meant to provide a simple, uniform and universal API interacting with any filesystem

A file abstraction system for Rust

Raw Filesystem API for Rust — enable simpler browsing with ease

RFSAPI requests are made by setting a GET request's X-Raw-Filesystem-API header to 1

Raw Filesystem API for Rust — enable simpler browsing with ease
Facebook Instagram Twitter GitHub Dribbble
Privacy