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

📄 fuse.c

📁 linux下的用户文件系统fuse-2.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
static void fuse_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size){    struct fuse *f = req_fuse_prepare(req);    int res;    if (size) {        char *list = (char *) malloc(size);        if (list == NULL) {            reply_err(req, -ENOMEM);            return;        }        res = common_listxattr(f, ino, list, size);        if (res > 0)            fuse_reply_buf(req, list, res);        else            reply_err(req, res);        free(list);    } else {        res = common_listxattr(f, ino, NULL, 0);        if (res >= 0)            fuse_reply_xattr(req, res);        else            reply_err(req, res);    }}static void fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name){    struct fuse *f = req_fuse_prepare(req);    char *path;    int err;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path(f, ino);    if (path != NULL) {        err = -ENOSYS;        if (f->op.removexattr)            err = f->op.removexattr(path, name);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static struct fuse_lowlevel_ops fuse_path_ops = {    .init = fuse_data_init,    .destroy = fuse_data_destroy,    .lookup = fuse_lookup,    .forget = fuse_forget,    .getattr = fuse_getattr,    .setattr = fuse_setattr,    .access = fuse_access,    .readlink = fuse_readlink,    .mknod = fuse_mknod,    .mkdir = fuse_mkdir,    .unlink = fuse_unlink,    .rmdir = fuse_rmdir,    .symlink = fuse_symlink,    .rename = fuse_rename,    .link = fuse_link,    .create = fuse_create,    .open = fuse_open,    .read = fuse_read,    .write = fuse_write,    .flush = fuse_flush,    .release = fuse_release,    .fsync = fuse_fsync,    .opendir = fuse_opendir,    .readdir = fuse_readdir,    .releasedir = fuse_releasedir,    .fsyncdir = fuse_fsyncdir,    .statfs = fuse_statfs,    .setxattr = fuse_setxattr,    .getxattr = fuse_getxattr,    .listxattr = fuse_listxattr,    .removexattr = fuse_removexattr,};static void free_cmd(struct fuse_cmd *cmd){    free(cmd->buf);    free(cmd);}void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd){    fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);    free_cmd(cmd);}int fuse_exited(struct fuse *f){    return fuse_session_exited(f->se);}struct fuse_session *fuse_get_session(struct fuse *f){    return f->se;}static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize){    struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));    if (cmd == NULL) {        fprintf(stderr, "fuse: failed to allocate cmd\n");        return NULL;    }    cmd->buf = (char *) malloc(bufsize);    if (cmd->buf == NULL) {        fprintf(stderr, "fuse: failed to allocate read buffer\n");        free(cmd);        return NULL;    }    return cmd;}struct fuse_cmd *fuse_read_cmd(struct fuse *f){    struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL);    size_t bufsize = fuse_chan_bufsize(ch);    struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);    if (cmd != NULL) {        int res = fuse_chan_receive(ch, cmd->buf, bufsize);        if (res <= 0) {            free_cmd(cmd);            if (res == -1)                fuse_exit(f);            return NULL;        }        cmd->buflen = res;        cmd->ch = ch;    }    return cmd;}int fuse_loop(struct fuse *f){    if (f)        return fuse_session_loop(f->se);    else        return -1;}int fuse_invalidate(struct fuse *f, const char *path){    (void) f;    (void) path;    return -EINVAL;}void fuse_exit(struct fuse *f){    fuse_session_exit(f->se);}struct fuse_context *fuse_get_context(){    static struct fuse_context context;    if (fuse_getcontext)        return fuse_getcontext();    else        return &context;}void fuse_set_getcontext_func(struct fuse_context *(*func)(void)){    fuse_getcontext = func;}enum {    KEY_HELP,    KEY_KEEP};#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }static const struct fuse_opt fuse_lib_opts[] = {    FUSE_OPT_KEY("-h",                    KEY_HELP),    FUSE_OPT_KEY("--help",                KEY_HELP),    FUSE_OPT_KEY("debug",                 KEY_KEEP),    FUSE_OPT_KEY("-d",                    KEY_KEEP),    FUSE_LIB_OPT("debug",                 debug, 1),    FUSE_LIB_OPT("-d",                    debug, 1),    FUSE_LIB_OPT("hard_remove",           hard_remove, 1),    FUSE_LIB_OPT("use_ino",               use_ino, 1),    FUSE_LIB_OPT("readdir_ino",           readdir_ino, 1),    FUSE_LIB_OPT("direct_io",             direct_io, 1),    FUSE_LIB_OPT("kernel_cache",          kernel_cache, 1),    FUSE_LIB_OPT("umask=",                set_mode, 1),    FUSE_LIB_OPT("umask=%o",              umask, 0),    FUSE_LIB_OPT("uid=",                  set_uid, 1),    FUSE_LIB_OPT("uid=%d",                uid, 0),    FUSE_LIB_OPT("gid=",                  set_gid, 1),    FUSE_LIB_OPT("gid=%d",                gid, 0),    FUSE_LIB_OPT("entry_timeout=%lf",     entry_timeout, 0),    FUSE_LIB_OPT("attr_timeout=%lf",      attr_timeout, 0),    FUSE_LIB_OPT("negative_timeout=%lf",  negative_timeout, 0),    FUSE_OPT_END};static void fuse_lib_help(void){    fprintf(stderr,            "    -o hard_remove         immediate removal (don't hide files)\n"            "    -o use_ino             let filesystem set inode numbers\n"            "    -o readdir_ino         try to fill in d_ino in readdir\n"            "    -o direct_io           use direct I/O\n"            "    -o kernel_cache        cache files in kernel\n"            "    -o umask=M             set file permissions (octal)\n"            "    -o uid=N               set file owner\n"            "    -o gid=N               set file group\n"            "    -o entry_timeout=T     cache timeout for names (1.0s)\n"            "    -o negative_timeout=T  cache timeout for deleted names (0.0s)\n"            "    -o attr_timeout=T      cache timeout for attributes (1.0s)\n"            "\n");}static int fuse_lib_opt_proc(void *data, const char *arg, int key,                             struct fuse_args *outargs){    (void) data; (void) arg; (void) outargs;    if (key == KEY_HELP)        fuse_lib_help();    return 1;}int fuse_is_lib_option(const char *opt){    return fuse_lowlevel_is_lib_option(opt) ||        fuse_opt_match(fuse_lib_opts, opt);}struct fuse *fuse_new_common(int fd, struct fuse_args *args,                             const struct fuse_operations *op,                             size_t op_size, int compat){    struct fuse_chan *ch;    struct fuse *f;    struct node *root;    if (sizeof(struct fuse_operations) < op_size) {        fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");        op_size = sizeof(struct fuse_operations);    }    f = (struct fuse *) calloc(1, sizeof(struct fuse));    if (f == NULL) {        fprintf(stderr, "fuse: failed to allocate fuse object\n");        goto out;    }    f->conf.entry_timeout = 1.0;    f->conf.attr_timeout = 1.0;    f->conf.negative_timeout = 0.0;    if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)            goto out_free;#ifdef __FreeBSD__    /*     * In FreeBSD, we always use these settings as inode numbers are needed to     * make getcwd(3) work.     */    f->conf.readdir_ino = 1;#endif    f->se = fuse_lowlevel_new(args, &fuse_path_ops, sizeof(fuse_path_ops), f);    if (f->se == NULL)        goto out_free;    ch = fuse_kern_chan_new(fd);    if (ch == NULL)        goto out_free_session;    fuse_session_add_chan(f->se, ch);    f->ctr = 0;    f->generation = 0;    /* FIXME: Dynamic hash table */    f->name_table_size = 14057;    f->name_table = (struct node **)        calloc(1, sizeof(struct node *) * f->name_table_size);    if (f->name_table == NULL) {        fprintf(stderr, "fuse: memory allocation failed\n");        goto out_free_session;    }    f->id_table_size = 14057;    f->id_table = (struct node **)        calloc(1, sizeof(struct node *) * f->id_table_size);    if (f->id_table == NULL) {        fprintf(stderr, "fuse: memory allocation failed\n");        goto out_free_name_table;    }    mutex_init(&f->lock);    memcpy(&f->op, op, op_size);    f->compat = compat;    root = (struct node *) calloc(1, sizeof(struct node));    if (root == NULL) {        fprintf(stderr, "fuse: memory allocation failed\n");        goto out_free_id_table;    }    root->name = strdup("/");    if (root->name == NULL) {        fprintf(stderr, "fuse: memory allocation failed\n");        goto out_free_root;    }    root->parent = 0;    root->nodeid = FUSE_ROOT_ID;    root->generation = 0;    root->refctr = 1;    root->nlookup = 1;    hash_id(f, root);    return f; out_free_root:    free(root); out_free_id_table:    free(f->id_table); out_free_name_table:    free(f->name_table); out_free_session:    fuse_session_destroy(f->se); out_free:    free(f); out:    return NULL;}struct fuse *fuse_new(int fd, struct fuse_args *args,                      const struct fuse_operations *op, size_t op_size){    return fuse_new_common(fd, args, op, op_size, 0);}void fuse_destroy(struct fuse *f){    size_t i;    for (i = 0; i < f->id_table_size; i++) {        struct node *node;        for (node = f->id_table[i]; node != NULL; node = node->id_next) {            if (node->is_hidden) {                char *path = get_path(f, node->nodeid);                if (path) {                    f->op.unlink(path);                    free(path);                }            }        }    }    for (i = 0; i < f->id_table_size; i++) {        struct node *node;        struct node *next;        for (node = f->id_table[i]; node != NULL; node = next) {            next = node->id_next;            free_node(node);        }    }    free(f->id_table);    free(f->name_table);    pthread_mutex_destroy(&f->lock);    fuse_session_destroy(f->se);    free(f);}#ifndef __FreeBSD__#include "fuse_compat.h"static int fuse_do_open(struct fuse *f, char *path, struct fuse_file_info *fi){    if (!f->compat)        return f->op.open(path, fi);    else if (f->compat == 22) {        int err;        struct fuse_file_info_compat22 tmp;        memcpy(&tmp, fi, sizeof(tmp));        err = ((struct fuse_operations_compat22 *) &f->op)->open(path, &tmp);        memcpy(fi, &tmp, sizeof(tmp));        fi->fh = tmp.fh;        return err;    } else        return            ((struct fuse_operations_compat2 *) &f->op)->open(path, fi->flags);}static void fuse_do_release(struct fuse *f, char *path,                           struct fuse_file_info *fi){    if (!f->compat || f->compat >= 22)        f->op.release(path ? path : "-", fi);    else if (path)        ((struct fuse_operations_compat2 *) &f->op)->release(path, fi->flags);}static int fuse_do_opendir(struct fuse *f, char *path,                           struct fuse_file_info *fi){    if (!f->compat) {        return f->op.opendir(path, fi);    } else {        int err;        struct fuse_file_info_compat22 tmp;        memcpy(&tmp, fi, sizeof(tmp));        err = ((struct fuse_operations_compat22 *) &f->op)->opendir(path, &tmp);        memcpy(fi, &tmp, sizeof(tmp));        fi->fh = tmp.fh;        return err;    }}static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,                                  struct statvfs *stbuf){    stbuf->f_bsize   = compatbuf->block_size;    stbuf->f_blocks  = compatbuf->blocks;    stbuf->f_bfree   = compatbuf->blocks_free;    stbuf->f_bavail  = compatbuf->blocks_free;    stbuf->f_files   = compatbuf->files;    stbuf->f_ffree   = compatbuf->files_free;    stbuf->f_namemax = compatbuf->namelen;}static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf){    stbuf->f_bsize   = oldbuf->f_bsize;    stbuf->f_blocks  = oldbuf->f_blocks;    stbuf->f_bfree   = oldbuf->f_bfree;    stbuf->f_bavail  = oldbuf->f_bavail;    stbuf->f_files   = oldbuf->f_files;    stbuf->f_ffree   = oldbuf->f_ffree;    stbuf->f_namemax = oldbuf->f_namelen;}static int fuse_do_statfs(struct fuse *f, char *path, struct statvfs *buf){    int err;    if (!f->compat) {        err = f->op.statfs(path, buf);    } else if (f->compat > 11) {        struct statfs oldbuf;        err = ((struct fuse_operations_compat22 *) &f->op)->statfs("/", &oldbuf);        if (!err)            convert_statfs_old(&oldbuf, buf);    } else {        struct fuse_statfs_compat1 compatbuf;        memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));        err = ((struct fuse_operations_compat1 *) &f->op)->statfs(&compatbuf);        if (!err)            convert_statfs_compat(&compatbuf, buf);    }    return err;}static struct fuse *fuse_new_common_compat(int fd, const char *opts,                                           const struct fuse_operations *op,                                           size_t op_size, int compat){    struct fuse *f;    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;    }    f = fuse_new_common(fd, &args, op, op_size, compat);    fuse_opt_free_args(&args);    return f;}struct fuse *fuse_new_compat22(int fd, const char *opts,                               const struct fuse_operations_compat22 *op,                               size_t op_size){    return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,                                  op_size, 22);}struct fuse *fuse_new_compat2(int fd, const char *opts,                              const struct fuse_operations_compat2 *op){    return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,                                  sizeof(struct fuse_operations_compat2), 21);}struct fuse *fuse_new_compat1(int fd, int flags,                              const struct fuse_operations_compat1 *op){    const char *opts = NULL;    if (flags & FUSE_DEBUG_COMPAT1)        opts = "debug";    return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,                                  sizeof(struct fuse_operations_compat1), 11);}__asm__(".symver fuse_exited,__fuse_exited@");__asm__(".symver fuse_process_cmd,__fuse_process_cmd@");__asm__(".symver fuse_read_cmd,__fuse_read_cmd@");__asm__(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");__asm__(".symver fuse_new_compat2,fuse_new@");__asm__(".symver fuse_new_compat22,fuse_new@FUSE_2.2");#else /* __FreeBSD__ */static int fuse_do_open(struct fuse *f, char *path, struct fuse_file_info *fi){    return f->op.open(path, fi);}static void fuse_do_release(struct fuse *f, char *path,                           struct fuse_file_info *fi){    f->op.release(path ? path : "-", fi);}static int fuse_do_opendir(struct fuse *f, char *path,                           struct fuse_file_info *fi){    return f->op.opendir(path, fi);}static int fuse_do_statfs(struct fuse *f, char *path, struct statvfs *buf){    return f->op.statfs(path, buf);}#endif /* __FreeBSD__ */

⌨️ 快捷键说明

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