如何在命令行参数中告诉 fuse3 你需要一个设备和一个挂载点
How to tell fuse3 that you need a device and a mount point in command-line arguments
我正在使用 fuse3 编写一个文件系统驱动程序,该驱动程序应解析所有保险丝选项,然后采用两个参数,一个设备路径(或包含文件系统映像的文件)和一个挂载点。
有没有方便的方法使用fuse的命令行解析从命令行提取设备?在我把它们交给像这样融合之前,我已经开始操纵参数:
struct fuse_args args;
const char *device = NULL;
memset(&args, 0, sizeof(args));
for (int i = 0; i < argc; ++i)
if (i > 0 && i == argc - 2 && *argv[i] != '-')
image = argv[i];
else
fuse_opt_add_arg(&args, argv[i]);
if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
return 1;
if (!device) {
usage(argv[0]);
fuse_opt_add_arg(&args, "--help");
}
fuse_main(args.argc, args.argv, &oper, nullptr);
但是如果用户只指定了一个参数,这就太粗鲁了,并且不太有效,除非该参数恰好也是一个有效的挂载点,因为 fuse 似乎在打印帮助之前检查挂载点的可行性。
当然这一定是一件很常见的事情,所以我想知道对于这样的文件系统正确的习惯用法是什么。
因此,为此您必须限制用户使用 cmd 参数的顺序(所有 fuse/mount 选项都在设备路径和安装点之前)。为简单起见,确保最后提供设备路径和挂载点:
因此在您的主函数中,此语句将检查参数数量是否正确,并且挂载点和设备不像选项那样以连字符开头。
if ((argc < 3) || (argv[argc-2][0] == '-') || (argv[argc-1][0] == '-'))
{
fprintf(stderr, "usage: ./myfuse [FUSE and mount options] devicepath mountPoint\n");
abort();
}
然后提取设备路径并存储在一个结构中:
struct my_state *my_data;
my_data = malloc(sizeof(struct mi_state));
if (mi_data == NULL) {
perror("main calloc");
abort();
}
my_data->devicepath = realpath(argv[argc - 2], NULL);
argv[argc-2] = argv[argc-1];
argv[argc-1] = NULL;
argc--;
请注意,在将 hem 传递给 fuse_main 函数之前,我从 argv 中删除了设备路径并将 argc 减 1
然后在调用 fuse_main 函数时确保传递 my_data 结构:
fuse_main(argc, argv, &my_fuse_operations, mi_data);
这是 my_state 结构的定义,您可以将其放入头文件中:
struct my_state{
char *devicepath;
};
您还应该在头文件中的结构定义下方添加此定义:
#define BB_DATA ((struct mi_state *) fuse_get_context()->private_data)
并且在你的初始化函数中调用 fuse_get_context 和 return BB_DATA:
void *my_init()
{
fuse_get_context();
return BB_DATA;
}
return 值将在 fuse_context 的 private_data 字段中传递给所有文件操作,并作为 destroy() 方法的参数。
fuse_context是在调用这个函数之前设置的,fuse_get_context()->private_data returns user_data传递给fuse_main( ).
我正在使用 fuse3 编写一个文件系统驱动程序,该驱动程序应解析所有保险丝选项,然后采用两个参数,一个设备路径(或包含文件系统映像的文件)和一个挂载点。
有没有方便的方法使用fuse的命令行解析从命令行提取设备?在我把它们交给像这样融合之前,我已经开始操纵参数:
struct fuse_args args;
const char *device = NULL;
memset(&args, 0, sizeof(args));
for (int i = 0; i < argc; ++i)
if (i > 0 && i == argc - 2 && *argv[i] != '-')
image = argv[i];
else
fuse_opt_add_arg(&args, argv[i]);
if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
return 1;
if (!device) {
usage(argv[0]);
fuse_opt_add_arg(&args, "--help");
}
fuse_main(args.argc, args.argv, &oper, nullptr);
但是如果用户只指定了一个参数,这就太粗鲁了,并且不太有效,除非该参数恰好也是一个有效的挂载点,因为 fuse 似乎在打印帮助之前检查挂载点的可行性。
当然这一定是一件很常见的事情,所以我想知道对于这样的文件系统正确的习惯用法是什么。
因此,为此您必须限制用户使用 cmd 参数的顺序(所有 fuse/mount 选项都在设备路径和安装点之前)。为简单起见,确保最后提供设备路径和挂载点:
因此在您的主函数中,此语句将检查参数数量是否正确,并且挂载点和设备不像选项那样以连字符开头。
if ((argc < 3) || (argv[argc-2][0] == '-') || (argv[argc-1][0] == '-'))
{
fprintf(stderr, "usage: ./myfuse [FUSE and mount options] devicepath mountPoint\n");
abort();
}
然后提取设备路径并存储在一个结构中:
struct my_state *my_data;
my_data = malloc(sizeof(struct mi_state));
if (mi_data == NULL) {
perror("main calloc");
abort();
}
my_data->devicepath = realpath(argv[argc - 2], NULL);
argv[argc-2] = argv[argc-1];
argv[argc-1] = NULL;
argc--;
请注意,在将 hem 传递给 fuse_main 函数之前,我从 argv 中删除了设备路径并将 argc 减 1 然后在调用 fuse_main 函数时确保传递 my_data 结构:
fuse_main(argc, argv, &my_fuse_operations, mi_data);
这是 my_state 结构的定义,您可以将其放入头文件中:
struct my_state{
char *devicepath;
};
您还应该在头文件中的结构定义下方添加此定义:
#define BB_DATA ((struct mi_state *) fuse_get_context()->private_data)
并且在你的初始化函数中调用 fuse_get_context 和 return BB_DATA:
void *my_init()
{
fuse_get_context();
return BB_DATA;
}
return 值将在 fuse_context 的 private_data 字段中传递给所有文件操作,并作为 destroy() 方法的参数。 fuse_context是在调用这个函数之前设置的,fuse_get_context()->private_data returns user_data传递给fuse_main( ).