/* Copyright (C) Eugene 'Vindex' Stulin, 2023-2026
 *
 * 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 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;
}

