User Tools

Site Tools


libfuse

Table of Contents

libfuse

  • Definition: libfuse (Filesystem in Userspace) is a library that provides a simple interface for userspace programs to export a virtual filesystem to the Linux kernel. It allows developers to create custom filesystems without writing kernel code.
  • Function: Facilitates the creation and implementation of filesystems that run in user space, enabling the development of custom filesystem logic without requiring kernel-level programming.
  • Components:
     * '''libfuse Library''': The core library that provides the FUSE API for creating user-space filesystems.
     * '''fusermount Utility''': A helper program to mount and unmount FUSE filesystems.
     * '''FUSE Daemon''': A user-space process that implements the filesystem logic.
  • Features:
     * '''User-Space Filesystem Development''': Allows filesystems to be developed and run in user space.
     * '''Portability''': Supported on Linux and other Unix-like operating systems.
     * '''Flexibility''': Enables the creation of various types of filesystems, such as network filesystems, encrypted filesystems, and more.
     * '''Ease of Use''': Simplifies the development process by providing a high-level API.
  • Usage: Commonly used for developing custom filesystems, network-based filesystems, and other specialized filesystems that require user-space implementation.

Examples

  • Creating a simple FUSE filesystem in C:
     ```c
     #define FUSE_USE_VERSION 31
     #include 
     #include 

 static const char *hello_str = "Hello World!\n";
 static const char *hello_path = "/hello";
 static int hello_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) {
     (void) fi;
     memset(stbuf, 0, sizeof(struct stat));
     if (strcmp(path, "/") == 0) {
         stbuf->st_mode = S_IFDIR | 0755;
         stbuf->st_nlink = 2;
     } else if (strcmp(path, hello_path) == 0) {
         stbuf->st_mode = S_IFREG | 0444;
         stbuf->st_nlink = 1;
         stbuf->st_size = strlen(hello_str);
     } else {
         return -ENOENT;
     }
     return 0;
 }
 static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags) {
     (void) offset;
     (void) fi;
     (void) flags;
     if (strcmp(path, "/") != 0) {
         return -ENOENT;
     }
     filler(buf, ".", NULL, 0, 0);
     filler(buf, "..", NULL, 0, 0);
     filler(buf, "hello", NULL, 0, 0);
     return 0;
 }
 static int hello_open(const char *path, struct fuse_file_info *fi) {
     if (strcmp(path, hello_path) != 0) {
         return -ENOENT;
     }
     if ((fi->flags & O_ACCMODE) != O_RDONLY) {
         return -EACCES;
     }
     return 0;
 }
 static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
     size_t len;
     (void) fi;
     if (strcmp(path, hello_path) != 0) {
         return -ENOENT;
     }
     len = strlen(hello_str);
     if (offset < len) {
         if (offset + size > len) {
             size = len - offset;
         }
         memcpy(buf, hello_str + offset, size);
     } else {
         size = 0;
     }
     return size;
 }
 static const struct fuse_operations hello_oper = {
     .getattr = hello_getattr,
     .readdir = hello_readdir,
     .open = hello_open,
     .read = hello_read,
 };
 int main(int argc, char *argv[]) {
     return fuse_main(argc, argv, &hello_oper, NULL);
 }
 ```

  • Using libfuse in a Python script (with the `fusepy` library):
     ```python
     from fuse import FUSE, Operations

 class HelloFS(Operations):
     def getattr(self, path, fh=None):
         if path == '/':
             return dict(st_mode=(0o755 | 0o040000), st_nlink=2)
         elif path == '/hello':
             return dict(st_mode=(0o444 | 0o100000), st_nlink=1, st_size=len("Hello World!\n"))
         else:
             raise FuseOSError(ENOENT)
     def readdir(self, path, fh):
         return ['.', '..', 'hello']
     def open(self, path, flags):
         if path != '/hello':
             raise FuseOSError(ENOENT)
     def read(self, path, size, offset, fh):
         return "Hello World!\n"[offset:offset + size]
 if __name__ == '__main__':
     fuse = FUSE(HelloFS(), 'mnt', foreground=True)
 ```

  • Using libfuse in a Java program (with a hypothetical Java binding):
     ```java
     import ru.serce.jnrfuse.FuseStubFS;
     import ru.serce.jnrfuse.struct.FileStat;

 import java.nio.ByteBuffer;
 import java.nio.file.Paths;
 public class HelloFS extends FuseStubFS {
     private static final String HELLO_PATH = "/hello";
     private static final String HELLO_STR = "Hello World!\n";
     @Override
     public int getattr(String path, FileStat stat) {
         if (path.equals("/")) {
             stat.st_mode.set(FileStat.S_IFDIR | 0755);
             stat.st_nlink.set(2);
         } else if (path.equals(HELLO_PATH)) {
             stat.st_mode.set(FileStat.S_IFREG | 0444);
             stat.st_nlink.set(1);
             stat.st_size.set(HELLO_STR.length());
         } else {
             return -ErrorCodes.ENOENT();
         }
         return 0;
     }
     @Override
     public int readdir(String path, DirectoryFiller filler) {
         if (!path.equals("/")) {
             return -ErrorCodes.ENOENT();
         }
         filler.add(".");
         filler.add("..");
         filler.add("hello");
         return 0;
     }
     @Override
     public int open(String path, FuseFileInfo fi) {
         if (!path.equals(HELLO_PATH)) {
             return -ErrorCodes.ENOENT();
         }
         return 0;
     }
     @Override
     public int read(String path, ByteBuffer buf, long size, long offset, FuseFileInfo fi) {
         if (!path.equals(HELLO_PATH)) {
             return -ErrorCodes.ENOENT();
         }
         String s = HELLO_STR;
         if (offset < s.length()) {
             if (offset + size > s.length()) {
                 size = s.length() - offset;
             }
             buf.put(s.getBytes(), (int) offset, (int) size);
         } else {
             size = 0;
         }
         return (int) size;
     }
     public static void main(String[] args) {
         HelloFS fs = new HelloFS();
         try {
             fs.mount(Paths.get("/mnt"), true, false);
         } finally {
             fs.umount();
         }
     }
 }
 ```

Summary

  • libfuse: A library for creating user-space filesystems, allowing developers to implement custom filesystem logic without writing kernel code. It provides an API for filesystem development, supported on Linux and other Unix-like operating systems. libfuse is widely used for creating network filesystems, encrypted filesystems, and other specialized filesystems.
libfuse.txt · Last modified: 2024/08/12 05:26 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki