在 FUSE 文件系统上的 mkdir 期间,lstat 错误“不允许操作”

时间:2021-06-07 15:44:04

标签: c linux filesystems fuse

我有一个应该创建目录的 FUSE 文件系统的简单实现。当我使用 -d 选项挂载它时,我注意到在 mkdir newdir 上它失败并且我收到错误 Operation not permitted 因为 mkddir 熔丝操作在我尝试的新目录上调用 getattr() 函数create 因此 lstat 失败,因为该目录尚不存在(尚未创建)。 mkdir new_dir 上的调试输出:

LOOKUP /new_dir
getattr[NULL] /new_dir
[getattr] file: /home/mrima/mifuse/root/new_dir
        
lstat error
   unique: 246, error: -1 (Operation not permitted), outsize: 16

我觉得我的实现中缺少一些非常基本的东西。我该如何解决这个问题?

这是我的代码:

#define FUSE_USE_VERSION 30
#include <fuse.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>


#define BB_DATA ((struct mi_state *) fuse_get_context()->private_data)
struct mi_state{
    char *root_dir;
};


static void mi_fullpath(char fpath[PATH_MAX], const char *path)
{
    strcpy(fpath, BB_DATA->root_dir);
    strncat(fpath, path, PATH_MAX);
}

static int mi_getattr(const char *path, struct stat *st)
{
    int res;

    char fpath[PATH_MAX];
    mi_fullpath(fpath, path);

    printf("[getattr] file: %s\n", fpath);

    res = lstat(fpath,st);
    if (res != 0)
        printf("\t\t\nlstat error\n\t");

    return res;
}


static int do_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
                       struct fuse_file_info *fi)
{
    (void) offset;
    (void) fi;
    char fpath[PATH_MAX];
    mi_fullpath(fpath, path);
    printf("[readdir] %s\n", fpath);
    struct dirent *dir;
    DIR *dr = opendir(fpath);
    if (dr == NULL)
        return -ENOMEM;

    do {
        if (filler(buf, dir->d_name, NULL, 0, 0) != 0) {
            return -ENOMEM;
        }
    } while ((dir = readdir(dr)) != NULL);

    return 0;
}



static int do_mkdir(const char *path, mode_t mode)
{
    char fpath[PATH_MAX];
    mi_fullpath(fpath, path);
    return mkdir(fpath, mode);
}

int mi_statfs(const char *path, struct statvfs *statv)
{
    int retstat = 0;
    char fpath[PATH_MAX];
    mi_fullpath(fpath, path);

    // get stats for underlying filesystem
    retstat = statvfs(fpath, statv);
    return retstat;
}
void *mi_init()
{
    fuse_get_context();
    return BB_DATA;
}


static struct fuse_operations fuse_example_operations = {
        .getattr = mi_getattr,
        .readdir = do_readdir,
        .mkdir   = do_mkdir,
        .init    = mi_init,
        .statfs  = mi_statfs,
};


void mifuse_usage()
{
    fprintf(stderr, "usage:  ./mfuse [FUSE and mount options] rootDir mountPoint\n");
    abort();
}

int main(int argc, char *argv[]){
    struct mi_state *mi_data;

    if ((getuid() == 0) || (geteuid() == 0)) {
        fprintf(stderr, "Running MiFUSE as root opens unnacceptable security holes\n");
        return 1;
    }
    if ((argc < 3) || (argv[argc-2][0] == '-') || (argv[argc-1][0] == '-'))
        mifuse_usage();
    fprintf(stderr, "Fuse library version %d.%d\n", FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION);

    mi_data = malloc(sizeof(struct mi_state));
    if (mi_data == NULL) {
        perror("main calloc");
        abort();
    }
    mi_data->root_dir = realpath(argv[argc - 2], NULL);
    argv[argc-2] = argv[argc-1];
    argv[argc-1] = NULL;
    argc--;
    return fuse_main(argc, argv, &fuse_example_operations, mi_data);
}

我用 gcc -Wall main.c ``pkg-config fuse3 --cflags --libs`` -o hello

编译它

0 个答案:

没有答案
相关问题