loggedfs on mac with osxfuse stuck

246 views Asked by At

I would like to log every syscall of a specified directory and I've found this repository https://github.com/rflament/loggedfs

It creates a virtual filesystem with fuse and log everything in it, just like I want.

I tried to port it on mac but it uses a "trick" that doesn't works on osx. The lstat is stuck 10s and crash.

I would like to understand why ?

This is a main part of my code :

//  g++ -Wall main.cpp `pkg-config fuse --cflags --libs` -o hello

#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

static char *path;
static int  savefd;

static int getattr(const char *path, struct stat *stbuf)
{
    int res;
    char rPath[1024];

    strcpy(rPath, "."); strcat(rPath, path);

    res = lstat(rPath, stbuf); // Mac stuck here
    return (res == -1 ? -errno : 0); 
}

static void* loggedFS_init(struct fuse_conn_info* info)
{
     fchdir(savefd); close(savefd); return NULL;
}

int main(int argc, char *argv[])
{
    struct fuse_operations oper;

    bzero(&oper, sizeof(fuse_operations));
    oper.init       = loggedFS_init;
    oper.getattr    = getattr;

    path = strdup(argv[argc - 1]);
    printf("chdir to %s\n", path);
    chdir(path);
    savefd = open(".", 0); 

    return fuse_main(argc, argv, &oper, NULL);
}
1

There are 1 answers

0
s-m-e On

I had a very close look at LoggedFS and tested it for POSIX compliance using pjdfstest, resulting in 3 issues (or groups of issues). I ended up re-implementing it in Python, fully POSIX compliant. I have not tested it on OS X yet, so I'd be happy to receive some feedback ;)

The "trick" you are mentioning could be the root cause of your issue, although I am not entirely sure. It causes a fundamental problem by adding another character to the path, which leads to issues when the length of path gets close to PATH_MAX. libfuse already passes paths with a leading / into FUSE operations. The additional . plus the "misleading" / (root of the mounted filesystem, not the "global" root folder) are two characters "too many", effectively reducing the maximum allowed path length to PATH_MAX minus 2. I explored options of altering PATH_MAX and informing user land software about a smaller PATH_MAX, which turned out to be impossible.

There is a way around, however. Do not close the file descriptor savefd in the init routine. Keep it open and instead close it in the destroy routine, which will be called by FUSE when the filesystem is unmounted. You can actually use savefd for specifying paths relative to it. You can then use fstatat (Linux, OS X / BSD) instead of lstat. Its prototype looks like this:

int fstatat(int dirfd, const char *pathname, struct stat *buf,
        int flags);

You have to pass savefd into dirfd and remove the leading / from the content of path before passing it into pathname.