/* Copyright (C) Eugene 'Vindex' Stulin, 2023-2024
 *
 * This example is written according to the original from libfuse.
 * Distributed under BSL 1.0 or (at your option) the GNU GPL 3.0 or later.
 * This file is offered as-is, without any warranty.
 */

/**
 * This "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.
 */

import std.algorithm : remove;
import std.conv : o = octal;
import std.file : isFile;
import std.stdio;

import core.sys.posix.sys.stat : stat_t, S_IFDIR, S_IFREG;
import core.stdc.errno : ENOENT, EFAULT;
import core.stdc.string : memset;
import core.sys.posix.unistd : getuid, getgid;
import core.stdc.time : time;

import oxfuse;


class NullFS : FileSystem {

    override stat_t getattr(string path, ffi_t* fi) {
        stat_t st;
        fe(path == "/", ENOENT);
        st.st_mode = S_IFREG | o!644;
        st.st_nlink = 1;
        st.st_uid = getuid();
        st.st_gid = getgid();
        st.st_size = 1UL << 32;  // 4 GiB
        st.st_blocks = 0;
        st.st_atime = st.st_mtime = st.st_ctime = time(null);
        return st;
    }

    override void truncate(string path, off_t offset, ffi_t* fi) {
        fe(path == "/", ENOENT);
    }

    override void open(string path, ffi_t* fi) {
        fe(path == "/", ENOENT);
    }

    override int read(
        string path, ubyte* buf, size_t size, off_t offset, ffi_t* fi
    ) {
        fe(path == "/", ENOENT);
        if (offset >= (1UL << 32)) {
            return 0;
        }
        memset(buf, 0, size);
        return cast(int)size;
    }

    override int write(
        string path, const ubyte* data, size_t size, off_t offset, ffi_t* fi
    ) {
        fe(path == "/", ENOENT);
        return cast(int)size;
    }
}


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];
    args = args[2 .. $];
    auto fs = new NullFS();
    auto ret = oxfuse.mount("null", fs, mountpoint, args);
    if (0 != ret) {
        stderr.writefln!"FUSE has been exited with code %s"(ret);
    }
    return ret;
}

