This project is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.

**Official repositories**:

- [https://codeberg.org/os-18/oxfuse](https://codeberg.org/os-18/oxfuse)
- [https://gitlab.com/os-18/oxfuse](https://gitlab.com/os-18/oxfuse)


*Keywords*:  
dlang, d, fuse, libfuse, libfuse3, binding, wrapper, filesystem.

---

## About

OXFuse (Object-oriented eXtension for FUSE) is a D language binding
for [libfuse3](https://github.com/libfuse/libfuse), allowing developers
to create user-space filesystems for Linux with an object-oriented interface.

### Features

- To implement your own file system, inherit from
  the `oxfuse.FileSystem` class and override any methods
  representing file operations.

- Forty libfuse operations are supported
  (everything except `write_buf()`/`read_buf()`).

- The behavior of all non-overloaded functions is determined by FUSE
  and the OS kernel.

- Errors with accompanying messages and `errno` are represented
  by `FuseException` and the `fe()` function.

- The [original library](https://github.com/libfuse/libfuse) broke backward
  compatibility for the `fuse_config` and `fuse_file_info` structures.
  Our library takes into account the current system version of libfuse3.
  All structures in the final build have the correct versions.

- At present, only the high-level part has been ported; the low-level part
  is not available.

---

## Documentation

[https://os-18.codeberg.page/oxfuse/](https://os-18.codeberg.page/oxfuse/)

The "examples/" directory contains several different implementations
of file systems.

Useful information is also available here:
[https://github.com/libfuse/libfuse/wiki](https://github.com/libfuse/libfuse/wiki).

---

## Ready-made packages

See:  
[Download Page of OS-18](https://codeberg.org/os-18/os-18-docs/src/branch/master/OS-18_Packages.md)

The page contains information about installing several packages, including
OXFuse.

---

## Build from source

### Prerequisities

You must have [make](https://www.gnu.org/software/make/)
and at least one of these compilers:

- [Digital Mars D Compiler](https://dlang.org/download.html#dmd)
- [LLVM D Compiler](https://wiki.dlang.org/LDC)
- [GNU D Compiler](https://www.gdcproject.org)

Also the library needs **libfuse3**.

### Compilation and installation

To build static and dynamic libraries using the **ldc2** compiler (default):

```bash
make
```

Installation (root privileges may be required):

```bash
make install
```

The Makefile contains variables:

* `DESTDIR` specifies the root directory for installing (empty, by default);
* `PREFIX` points to the base directory like `usr/local` or `usr`.

The installation directory is defined as `$(DESTDIR)/$(PREFIX)` in the Makefile.

You can install the library files in any directory; example for `$HOME/.local`:

```bash
make install DESTDIR=$HOME PREFIX=.local
```

Uninstall:

```bash
make uninstall
```

If the project was installed in a non-default location,
use the corresponding paths:

```bash
make uninstall DESTDIR=$HOME PREFIX=.local
```

### Other compilers

The default compiler is **ldc2**.
You can choose another compiler (for example, **gdc**):

```bash
make DC=gdc
```

Installing:

```bash
make install DC=gdc
```

Uninstalling:

```bash
make uninstall DC=gdc
```

---

## Simple example

This simple filesystem provides only a single file. The mountpoint needs to be
a file rather than a directory. All writes to the file will be discarded,
and reading the file always returns zeros.

This code is copied from `examples/nullfs.d`.

```d
import core.sys.posix.sys.stat : stat_t, S_IFREG;
import core.stdc.errno : ENOENT;
import core.sys.posix.unistd : getuid, getgid;
import core.stdc.time : time;

import std.conv : octal;
import std.stdio;

import oxfuse;


class NullFS : FileSystem {
    enum size = 1UL << 32;  // 4 GiB

    override stat_t getattr(string path, FileInfo fi) {
        stat_t st;
        fe(path == "/", ENOENT);
        st.st_mode = S_IFREG | octal!644;
        st.st_nlink = 1;
        st.st_uid = getuid();
        st.st_gid = getgid();
        st.st_size = size;
        st.st_atime = st.st_mtime = st.st_ctime = time(null);
        return st;
    }

    override int read(string path, ubyte[] buf, off_t offset, FileInfo fi) {
        buf[] = 0;
        return (offset > size) ? 0 : cast(int) buf.length;
    }

    override int write(
        string path, const ubyte[] buf, off_t offset, FileInfo fi
    ) {
        return (offset > size) ? 0 : cast(int) buf.length;
    }
}


int main(string[] args) {
    if (args.length < 2 || args[1] == "--help" || args[1] == "-h") {
        writefln("Usage: %s <mount/point> <fuse options>", args[0]);
        writeln("Mount point is any regular file.");
        return 0;
    }
    string mountpoint = args[1];
    string[] fuseArgs = args[2 .. $];  // like "-d"
    auto fs = new NullFS();
    auto ret = oxfuse.mount("null", fs, mountpoint, fuseArgs);
    if (0 != ret) {
        stderr.writefln!"FUSE has been exited with code %s"(ret);
    }
    return ret;
}
```

Compile (OXFuse must be installed):

```bash
ldc2 nullfs.d -link-defaultlib-shared $(pkg-config --cflags --libs oxfuse-ldc2)
```

Run with debug mode:

```bash
./nullfs <any_file_as_mountpoint> -d
```

Unmount:

```bash
fusermount -uz <mountpoint>
```

More filesystems can be found in `examples/`.

---

## Feedback

For questions, suggestions, comments, or bug reports:

**tech.vindex@gmail.com**

Also use the repository service tools.

---
