我有一个应该创建目录的 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