⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fuse_lowlevel.c

📁 Linux下fuse用户文件系统的的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        }        fflush(stdout);    }    f->conn.proto_major = arg->major;    f->conn.proto_minor = arg->minor;    if (arg->major < 7) {        fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",                arg->major, arg->minor);        fuse_reply_err(req, EPROTO);        return;    }    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {        if (f->conn.async_read)            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;        if (arg->max_readahead < f->conn.max_readahead)            f->conn.max_readahead = arg->max_readahead;    } else {        f->conn.async_read = 0;        f->conn.max_readahead = 0;    }    if (bufsize < FUSE_MIN_READ_BUFFER) {        fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",                bufsize);        bufsize = FUSE_MIN_READ_BUFFER;    }    bufsize -= 4096;    if (bufsize < f->conn.max_write)        f->conn.max_write = bufsize;    f->got_init = 1;    if (f->op.init)        f->op.init(f->userdata, &f->conn);    memset(&outarg, 0, sizeof(outarg));    outarg.major = FUSE_KERNEL_VERSION;    outarg.minor = FUSE_KERNEL_MINOR_VERSION;    if (f->conn.async_read)        outarg.flags |= FUSE_ASYNC_READ;    if (f->op.getlk && f->op.setlk)        outarg.flags |= FUSE_POSIX_LOCKS;    outarg.max_readahead = f->conn.max_readahead;    outarg.max_write = f->conn.max_write;    if (f->debug) {        printf("   INIT: %u.%u\n", outarg.major, outarg.minor);        printf("   flags=0x%08x\n", outarg.flags);        printf("   max_readahead=0x%08x\n", outarg.max_readahead);        printf("   max_write=0x%08x\n", outarg.max_write);        fflush(stdout);    }    send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));}static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg){    struct fuse_ll *f = req->f;    (void) nodeid;    (void) inarg;    f->got_destroy = 1;    if (f->op.destroy)        f->op.destroy(f->userdata);    send_reply_ok(req, NULL, 0);}void *fuse_req_userdata(fuse_req_t req){    return req->f->userdata;}const struct fuse_ctx *fuse_req_ctx(fuse_req_t req){    return &req->ctx;}void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,                             void *data){    pthread_mutex_lock(&req->lock);    req->u.ni.func = func;    req->u.ni.data = data;    if (req->interrupted && func)        func(req, data);    pthread_mutex_unlock(&req->lock);}int fuse_req_interrupted(fuse_req_t req){    int interrupted;    pthread_mutex_lock(&req->f->lock);    interrupted = req->interrupted;    pthread_mutex_unlock(&req->f->lock);    return interrupted;}static struct {    void (*func)(fuse_req_t, fuse_ino_t, const void *);    const char *name;} fuse_ll_ops[] = {    [FUSE_LOOKUP]      = { do_lookup,      "LOOKUP"      },    [FUSE_FORGET]      = { do_forget,      "FORGET"      },    [FUSE_GETATTR]     = { do_getattr,     "GETATTR"     },    [FUSE_SETATTR]     = { do_setattr,     "SETATTR"     },    [FUSE_READLINK]    = { do_readlink,    "READLINK"    },    [FUSE_SYMLINK]     = { do_symlink,     "SYMLINK"     },    [FUSE_MKNOD]       = { do_mknod,       "MKNOD"       },    [FUSE_MKDIR]       = { do_mkdir,       "MKDIR"       },    [FUSE_UNLINK]      = { do_unlink,      "UNLINK"      },    [FUSE_RMDIR]       = { do_rmdir,       "RMDIR"       },    [FUSE_RENAME]      = { do_rename,      "RENAME"      },    [FUSE_LINK]        = { do_link,        "LINK"        },    [FUSE_OPEN]        = { do_open,        "OPEN"        },    [FUSE_READ]        = { do_read,        "READ"        },    [FUSE_WRITE]       = { do_write,       "WRITE"       },    [FUSE_STATFS]      = { do_statfs,      "STATFS"      },    [FUSE_RELEASE]     = { do_release,     "RELEASE"     },    [FUSE_FSYNC]       = { do_fsync,       "FSYNC"       },    [FUSE_SETXATTR]    = { do_setxattr,    "SETXATTR"    },    [FUSE_GETXATTR]    = { do_getxattr,    "GETXATTR"    },    [FUSE_LISTXATTR]   = { do_listxattr,   "LISTXATTR"   },    [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },    [FUSE_FLUSH]       = { do_flush,       "FLUSH"       },    [FUSE_INIT]        = { do_init,        "INIT"        },    [FUSE_OPENDIR]     = { do_opendir,     "OPENDIR"     },    [FUSE_READDIR]     = { do_readdir,     "READDIR"     },    [FUSE_RELEASEDIR]  = { do_releasedir,  "RELEASEDIR"  },    [FUSE_FSYNCDIR]    = { do_fsyncdir,    "FSYNCDIR"    },    [FUSE_GETLK]       = { do_getlk,       "GETLK"       },    [FUSE_SETLK]       = { do_setlk,       "SETLK"       },    [FUSE_SETLKW]      = { do_setlkw,      "SETLKW"      },    [FUSE_ACCESS]      = { do_access,      "ACCESS"      },    [FUSE_CREATE]      = { do_create,      "CREATE"      },    [FUSE_INTERRUPT]   = { do_interrupt,   "INTERRUPT"   },    [FUSE_BMAP]        = { do_bmap,        "BMAP"        },    [FUSE_DESTROY]     = { do_destroy,     "DESTROY"     },};#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))static const char *opname(enum fuse_opcode opcode){    if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)        return "???";    else        return fuse_ll_ops[opcode].name;}static void fuse_ll_process(void *data, const char *buf, size_t len,                     struct fuse_chan *ch){    struct fuse_ll *f = (struct fuse_ll *) data;    struct fuse_in_header *in = (struct fuse_in_header *) buf;    const void *inarg = buf + sizeof(struct fuse_in_header);    struct fuse_req *req;    if (f->debug) {        printf("unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",               (unsigned long long) in->unique,               opname((enum fuse_opcode) in->opcode), in->opcode,               (unsigned long) in->nodeid, len);        fflush(stdout);    }    req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));    if (req == NULL) {        fprintf(stderr, "fuse: failed to allocate request\n");        return;    }    req->f = f;    req->unique = in->unique;    req->ctx.uid = in->uid;    req->ctx.gid = in->gid;    req->ctx.pid = in->pid;    req->ch = ch;    req->ctr = 1;    list_init_req(req);    fuse_mutex_init(&req->lock);    if (!f->got_init && in->opcode != FUSE_INIT)        fuse_reply_err(req, EIO);    else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&             in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&             in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&             in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&             in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {        fuse_reply_err(req, EACCES);    } else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)        fuse_reply_err(req, ENOSYS);    else {        if (in->opcode != FUSE_INTERRUPT) {            struct fuse_req *intr;            pthread_mutex_lock(&f->lock);            intr = check_interrupt(f, req);            list_add_req(req, &f->list);            pthread_mutex_unlock(&f->lock);            if (intr)                fuse_reply_err(intr, EAGAIN);        }        fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);    }}enum {    KEY_HELP,    KEY_VERSION,};static struct fuse_opt fuse_ll_opts[] = {    { "debug", offsetof(struct fuse_ll, debug), 1 },    { "-d", offsetof(struct fuse_ll, debug), 1 },    { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },    { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },    { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },    { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },    { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },    FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),    FUSE_OPT_KEY("-h", KEY_HELP),    FUSE_OPT_KEY("--help", KEY_HELP),    FUSE_OPT_KEY("-V", KEY_VERSION),    FUSE_OPT_KEY("--version", KEY_VERSION),    FUSE_OPT_END};static void fuse_ll_version(void){    fprintf(stderr, "using FUSE kernel interface version %i.%i\n",            FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);}static void fuse_ll_help(void){    fprintf(stderr,"    -o max_write=N         set maximum size of write requests\n""    -o max_readahead=N     set maximum readahead\n""    -o async_read          perform reads asynchronously (default)\n""    -o sync_read           perform reads synchronously\n");}static int fuse_ll_opt_proc(void *data, const char *arg, int key,                            struct fuse_args *outargs){    (void) data; (void) outargs;    switch (key) {    case KEY_HELP:        fuse_ll_help();        break;    case KEY_VERSION:        fuse_ll_version();        break;    default:        fprintf(stderr, "fuse: unknown option `%s'\n", arg);    }    return -1;}int fuse_lowlevel_is_lib_option(const char *opt){    return fuse_opt_match(fuse_ll_opts, opt);}static void fuse_ll_destroy(void *data){    struct fuse_ll *f = (struct fuse_ll *) data;    if (f->got_init && !f->got_destroy) {        if (f->op.destroy)            f->op.destroy(f->userdata);    }    pthread_mutex_destroy(&f->lock);    free(f);}/* * always call fuse_lowlevel_new_common() internally, to work around a * misfeature in the FreeBSD runtime linker, which links the old * version of a symbol to internal references. */struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,                                       const struct fuse_lowlevel_ops *op,                                       size_t op_size, void *userdata){    struct fuse_ll *f;    struct fuse_session *se;    struct fuse_session_ops sop = {        .process = fuse_ll_process,        .destroy = fuse_ll_destroy,    };    if (sizeof(struct fuse_lowlevel_ops) < op_size) {        fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");        op_size = sizeof(struct fuse_lowlevel_ops);    }    f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));    if (f == NULL) {        fprintf(stderr, "fuse: failed to allocate fuse object\n");        goto out;    }    f->conn.async_read = 1;    f->conn.max_write = UINT_MAX;    f->conn.max_readahead = UINT_MAX;    list_init_req(&f->list);    list_init_req(&f->interrupts);    fuse_mutex_init(&f->lock);    if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)        goto out_free;    memcpy(&f->op, op, op_size);    f->owner = getuid();    f->userdata = userdata;    se = fuse_session_new(&sop, f);    if (!se)        goto out_free;    return se; out_free:    free(f); out:    return NULL;}struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,                                       const struct fuse_lowlevel_ops *op,                                       size_t op_size, void *userdata){    return fuse_lowlevel_new_common(args, op, op_size, userdata);}#ifndef __FreeBSD__static void fill_open_compat(struct fuse_open_out *arg,                      const struct fuse_file_info_compat *f){    arg->fh = f->fh;    if (f->direct_io)        arg->open_flags |= FOPEN_DIRECT_IO;    if (f->keep_cache)        arg->open_flags |= FOPEN_KEEP_CACHE;}static void convert_statfs_compat(const struct statfs *compatbuf,                                  struct statvfs *buf){    buf->f_bsize	= compatbuf->f_bsize;    buf->f_blocks	= compatbuf->f_blocks;    buf->f_bfree	= compatbuf->f_bfree;    buf->f_bavail	= compatbuf->f_bavail;    buf->f_files	= compatbuf->f_files;    buf->f_ffree	= compatbuf->f_ffree;    buf->f_namemax	= compatbuf->f_namelen;}int fuse_reply_open_compat(fuse_req_t req,                           const struct fuse_file_info_compat *f){    struct fuse_open_out arg;    memset(&arg, 0, sizeof(arg));    fill_open_compat(&arg, f);    return send_reply_ok(req, &arg, sizeof(arg));}int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf){    struct statvfs newbuf;    memset(&newbuf, 0, sizeof(newbuf));    convert_statfs_compat(stbuf, &newbuf);    return fuse_reply_statfs(req, &newbuf);}struct fuse_session *fuse_lowlevel_new_compat(const char *opts,                            const struct fuse_lowlevel_ops_compat *op,                            size_t op_size, void *userdata){    struct fuse_session *se;    struct fuse_args args = FUSE_ARGS_INIT(0, NULL);    if (opts &&        (fuse_opt_add_arg(&args, "") == -1 ||         fuse_opt_add_arg(&args, "-o") == -1 ||         fuse_opt_add_arg(&args, opts) == -1)) {        fuse_opt_free_args(&args);        return NULL;    }    se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op,                           op_size, userdata);    fuse_opt_free_args(&args);    return se;}struct fuse_ll_compat_conf {    unsigned max_read;    int set_max_read;};static const struct fuse_opt fuse_ll_opts_compat[] = {    { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },    { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },    FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),    FUSE_OPT_END};int fuse_sync_compat_args(struct fuse_args *args){    struct fuse_ll_compat_conf conf;    memset(&conf, 0, sizeof(conf));    if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)        return -1;    if (fuse_opt_insert_arg(args, 1, "-osync_read"))        return -1;    if (conf.set_max_read) {        char tmpbuf[64];        sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);        if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)            return -1;    }    return 0;}__asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");__asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");__asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");#else /* __FreeBSD__ */int fuse_sync_compat_args(struct fuse_args *args){    (void) args;    return 0;}#endif /* __FreeBSD__ */struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,                        const struct fuse_lowlevel_ops_compat25 *op,                        size_t op_size, void *userdata){    if (fuse_sync_compat_args(args) == -1)        return NULL;    return fuse_lowlevel_new_common(args,                                    (const struct fuse_lowlevel_ops *) op,                                    op_size, userdata);}__asm__(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -