【问题标题】:How to tell fuse3 that you need a device and a mount point in command-line arguments如何在命令行参数中告诉 fuse3 你需要一个设备和一个挂载点
【发布时间】:2021-08-11 06:11:32
【问题描述】:

我正在使用 fuse3 编写一个文件系统驱动程序,它应该解析所有 fuse 选项,然后接受两个参数,一个设备路径(或包含文件系统映像的文件)和一个挂载点。

有没有方便的方法使用fuse的命令行解析从命令行中提取设备?在我将它们交给 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 似乎在打印帮助之前检查了挂载点的可行性。

这肯定是一件很常见的事情,所以我想知道这样一个文件系统的正确习惯用法是什么。

【问题讨论】:

    标签: filesystems fuse


    【解决方案1】:

    因此,您必须按照 cmd 参数的顺序限制用户(所有 fuse/mount 选项都位于 devicepath 和 mountpoint 之前)。为简单起见,请确保最后提供设备和挂载点的路径:

    因此,在您的主函数中,此语句将检查参数数量是否正确,并且挂载点和设备不像选项那样以连字符开头。

        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)
    

    并且还在你的 init 函数中调用 fuse_get_context 并返回 BB_DATA:

    void *my_init()
    {
        fuse_get_context();
        return BB_DATA;
    }
    

    返回值将在 fuse_context 的 private_data 字段中传递给所有文件操作,并作为参数传递给 destroy() 方法。 fuse_context是在调用这个函数之前设置好的,fuse_get_context()->private_data返回传给fuse_main()的user_data。

    【讨论】:

    • @user3188445 我也一直在搞保险丝,希望我的回答有帮助
    • 是的,谢谢你的回答。我正在做类似的事情——它不像我预期的那么优雅。也许所有“真正的”文件系统都使用较低级别的接口,所以这不会出现?
    • cs.nmsu.edu/~pfeiffer/fuse-tutorial 查看该链接,这里有完整功能文件系统的源代码
    猜你喜欢
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2021-09-11
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多