1

I am developing a file system using libfuse and need to find a way to intercept calls for storage size querying, i.e. du and df. But I have been unable to identify how to this and unable to find an example that showcase this.

Looking at the debug output from my filesystem, doesn't give much information either, as I am unsure which call I should intercept.

Lars Nielsen
  • 2,005
  • 2
  • 25
  • 48
  • 1
    The filesystem driver isn't directly involved in running commands. It's used to access the file containing the program, but it can't tell the difference between running the program and reading it for some other purpose. – Barmar Feb 18 '21 at 08:36
  • So this is not possible? – Lars Nielsen Feb 18 '21 at 08:36
  • So if you try to intercept it in the driver, you'll also intercept things like `wc -c /usr/bin/du` – Barmar Feb 18 '21 at 08:36
  • oh... okay thanks for the info :) – Lars Nielsen Feb 18 '21 at 08:37
  • What is it you're really trying to accomplish by intercepting uses of specific programs? – Barmar Feb 18 '21 at 08:37
  • 1
    Shouldn't you just implement the filesystem operations that the programs use internally? E.g. `stat()` and `statfs()`? – Barmar Feb 18 '21 at 08:38
  • So due to an internal directory structure for the specific file system, commands like `du` and `df` has a high processing time. I would like to avoid this by implementing a "pool" where it can find this information. But you actually answered a question that has buggled me for a while: Why do other fuse systems sometimes have their own tool for this – Lars Nielsen Feb 18 '21 at 08:39
  • I have stat and statfs implemented :) – Lars Nielsen Feb 18 '21 at 08:39
  • 1
    Calling `strace du ` and `strace df ` gave me some `stat` and `statfs` calls so you should intercept these in your code. Don't know about df/statfs but regarding du there's no way to hack it - the program just traverses the files and calls stat. You could only prepare a fast cache for it. – Oren Kishon Feb 18 '21 at 09:35
  • @OrenKishon yeah, I feared as much. Making my own tool instead :/ – Lars Nielsen Feb 18 '21 at 10:07

1 Answers1

1

For the df you can implement the statfs() operation, something like this:

static int do_statfs(const char *path, struct statvfs *st)
{
        int rv; 

        rv = statvfs("/", st);
        st->f_bavail = 15717083;

        return rv; 
}

In the example above, just to simplify, I query the root filesystem, than modify blocks available, but you can (and should) feel the complete statvfs structure with the information regarding your filesystem.

Now for the du, the man says: "Summarize disk usage of each FILE, recursively for directories", so every file will be queried. For this you need to implement the stat() operation.

static int do_getattr(const char *path, struct stat *st)
{
    st->st_uid = getuid();
    st->st_gid = getgid();
    st->st_atime = time(NULL);
    st->st_mtime = time(NULL);

    // fill the rest of the stat structure

    return 0;
}

Once those are implemented you have to add them do fuse_operations structure:

static struct fuse_operations operations = {
        .open           = do_open,
        .getattr        = do_getattr,
        .readdir        = do_readdir,
        .read           = do_read,
        .statfs         = do_statfs,
        .release        = do_release,
};

and pass it as a parameter to the fuse_main()

int main(int argc, char *argv[])
{
        return fuse_main(argc, argv, &operations, NULL);
}
Alberto Pires
  • 319
  • 1
  • 5
  • 10