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

📄 fuse.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 5 页
字号:
        perror("fuse: clock_gettime");        abort();    }}static void update_stat(struct node *node, const struct stat *stbuf){    if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||                              stbuf->st_size != node->size))        node->cache_valid = 0;    node->mtime.tv_sec = stbuf->st_mtime;    node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);    node->size = stbuf->st_size;    curr_time(&node->stat_updated);}static int lookup_path(struct fuse *f, fuse_ino_t nodeid,                       const char *name, const char *path,                       struct fuse_entry_param *e, struct fuse_file_info *fi){    int res;    memset(e, 0, sizeof(struct fuse_entry_param));    if (fi)        res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);    else        res = fuse_fs_getattr(f->fs, path, &e->attr);    if (res == 0) {        struct node *node;        node = find_node(f, nodeid, name);        if (node == NULL)            res = -ENOMEM;        else {            e->ino = node->nodeid;            e->generation = node->generation;            e->entry_timeout = f->conf.entry_timeout;            e->attr_timeout = f->conf.attr_timeout;            if (f->conf.auto_cache) {                pthread_mutex_lock(&f->lock);                update_stat(node, &e->attr);                pthread_mutex_unlock(&f->lock);            }            set_stat(f, e->ino, &e->attr);            if (f->conf.debug)                fprintf(stderr, "   NODEID: %lu\n", (unsigned long) e->ino);        }    }    return res;}static struct fuse_context_i *fuse_get_context_internal(void){    struct fuse_context_i *c;    c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);    if (c == NULL) {        c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i));        if (c == NULL) {            /* This is hard to deal with properly, so just abort.  If               memory is so low that the context cannot be allocated,               there's not much hope for the filesystem anyway */             fprintf(stderr, "fuse: failed to allocate thread specific data\n");            abort();        }        pthread_setspecific(fuse_context_key, c);    }    return c;}static void fuse_freecontext(void *data){    free(data);}static int fuse_create_context_key(void){    int err = 0;    pthread_mutex_lock(&fuse_context_lock);    if (!fuse_context_ref) {        err = pthread_key_create(&fuse_context_key, fuse_freecontext);        if (err) {            fprintf(stderr, "fuse: failed to create thread specific key: %s\n",                    strerror(err));            pthread_mutex_unlock(&fuse_context_lock);            return -1;        }    }    fuse_context_ref++;    pthread_mutex_unlock(&fuse_context_lock);    return 0;}static void fuse_delete_context_key(void){    pthread_mutex_lock(&fuse_context_lock);    fuse_context_ref--;    if (!fuse_context_ref) {        free(pthread_getspecific(fuse_context_key));        pthread_key_delete(fuse_context_key);    }    pthread_mutex_unlock(&fuse_context_lock);}static struct fuse *req_fuse_prepare(fuse_req_t req){    struct fuse_context_i *c = fuse_get_context_internal();    const struct fuse_ctx *ctx = fuse_req_ctx(req);    c->req = req;    c->ctx.fuse = req_fuse(req);    c->ctx.uid = ctx->uid;    c->ctx.gid = ctx->gid;    c->ctx.pid = ctx->pid;    return c->ctx.fuse;}static inline void reply_err(fuse_req_t req, int err){    /* fuse_reply_err() uses non-negated errno values */    fuse_reply_err(req, -err);}static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,                        int err){    if (!err) {        struct fuse *f = req_fuse(req);        if (fuse_reply_entry(req, e) == -ENOENT)            forget_node(f, e->ino, 1);    } else        reply_err(req, err);}void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn){    fuse_get_context()->private_data = fs->user_data;    if (fs->op.init)        fs->user_data = fs->op.init(conn);}static void fuse_lib_init(void *data, struct fuse_conn_info *conn){    struct fuse *f = (struct fuse *) data;    struct fuse_context_i *c = fuse_get_context_internal();    memset(c, 0, sizeof(*c));    c->ctx.fuse = f;    fuse_fs_init(f->fs, conn);}void fuse_fs_destroy(struct fuse_fs *fs){    fuse_get_context()->private_data = fs->user_data;    if (fs->op.destroy)        fs->op.destroy(fs->user_data);    free(fs);}static void fuse_lib_destroy(void *data){    struct fuse *f = (struct fuse *) data;    struct fuse_context_i *c = fuse_get_context_internal();    memset(c, 0, sizeof(*c));    c->ctx.fuse = f;    fuse_fs_destroy(f->fs);    f->fs = NULL;}static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,                            const char *name){    struct fuse *f = req_fuse_prepare(req);    struct fuse_entry_param e;    char *path;    int err;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path_name(f, parent, name);    if (path != NULL) {        struct fuse_intr_data d;        if (f->conf.debug)            fprintf(stderr, "LOOKUP %s\n", path);        fuse_prepare_interrupt(f, req, &d);         err = lookup_path(f, parent, name, path, &e, NULL);        if (err == -ENOENT && f->conf.negative_timeout != 0.0) {            e.ino = 0;            e.entry_timeout = f->conf.negative_timeout;            err = 0;        }        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_entry(req, &e, err);}static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,                            unsigned long nlookup){    struct fuse *f = req_fuse(req);    if (f->conf.debug)        fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup);    forget_node(f, ino, nlookup);    fuse_reply_none(req);}static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,                             struct fuse_file_info *fi){    struct fuse *f = req_fuse_prepare(req);    struct stat buf;    char *path;    int err;    (void) fi;    memset(&buf, 0, sizeof(buf));    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path(f, ino);    if (path != NULL) {        struct fuse_intr_data d;        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_getattr(f->fs, path, &buf);        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    if (!err) {        if (f->conf.auto_cache) {            pthread_mutex_lock(&f->lock);            update_stat(get_node(f, ino), &buf);            pthread_mutex_unlock(&f->lock);        }        set_stat(f, ino, &buf);        fuse_reply_attr(req, &buf, f->conf.attr_timeout);    } else        reply_err(req, err);}int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode){    fuse_get_context()->private_data = fs->user_data;    if (fs->op.chmod)        return fs->op.chmod(path, mode);    else        return -ENOSYS;}static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,                             int valid, struct fuse_file_info *fi){    struct fuse *f = req_fuse_prepare(req);    struct stat buf;    char *path;    int err;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path(f, ino);    if (path != NULL) {        struct fuse_intr_data d;        fuse_prepare_interrupt(f, req, &d);        err = 0;        if (!err && (valid & FUSE_SET_ATTR_MODE))            err = fuse_fs_chmod(f->fs, path, attr->st_mode);        if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {            uid_t uid =                 (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;            gid_t gid =                 (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;            err = fuse_fs_chown(f->fs, path, uid, gid);        }        if (!err && (valid & FUSE_SET_ATTR_SIZE)) {            if (fi)                err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi);            else                err = fuse_fs_truncate(f->fs, path, attr->st_size);        }        if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==            (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {            struct timespec tv[2];            tv[0].tv_sec = attr->st_atime;            tv[0].tv_nsec = ST_ATIM_NSEC(attr);            tv[1].tv_sec = attr->st_mtime;            tv[1].tv_nsec = ST_MTIM_NSEC(attr);            err = fuse_fs_utimens(f->fs, path, tv);        }        if (!err)            err = fuse_fs_getattr(f->fs,  path, &buf);        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    if (!err) {        if (f->conf.auto_cache) {            pthread_mutex_lock(&f->lock);            update_stat(get_node(f, ino), &buf);            pthread_mutex_unlock(&f->lock);        }        set_stat(f, ino, &buf);        fuse_reply_attr(req, &buf, f->conf.attr_timeout);    } else        reply_err(req, err);}static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask){    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) {        struct fuse_intr_data d;        if (f->conf.debug)            fprintf(stderr, "ACCESS %s 0%o\n", path, mask);        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_access(f->fs, path, mask);        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino){    struct fuse *f = req_fuse_prepare(req);    char linkname[PATH_MAX + 1];    char *path;    int err;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path(f, ino);    if (path != NULL) {        struct fuse_intr_data d;        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    if (!err) {        linkname[PATH_MAX] = '\0';        fuse_reply_readlink(req, linkname);    } else        reply_err(req, err);}static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,                           mode_t mode, dev_t rdev){    struct fuse *f = req_fuse_prepare(req);    struct fuse_entry_param e;    char *path;    int err;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path_name(f, parent, name);    if (path) {        struct fuse_intr_data d;        if (f->conf.debug)            fprintf(stderr, "MKNOD %s\n", path);        fuse_prepare_interrupt(f, req, &d);        err = -ENOSYS;        if (S_ISREG(mode)) {            struct fuse_file_info fi;            memset(&fi, 0, sizeof(fi));            fi.flags = O_CREAT | O_EXCL | O_WRONLY;            err = fuse_fs_create(f->fs, path, mode, &fi);            if (!err) {                err = lookup_path(f, parent, name, path, &e, &fi);                fuse_fs_release(f->fs, path, &fi);            }        }        if (err == -ENOSYS) {            err = fuse_fs_mknod(f->fs, path, mode, rdev);            if (!err)                err = lookup_path(f, parent, name, path, &e, NULL);        }        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_entry(req, &e, err);}static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,                           mode_t mode){    struct fuse *f = req_fuse_prepare(req);    struct fuse_entry_param e;    char *path;    int err;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path_name(f, parent, name);    if (path != NULL) {        struct fuse_intr_data d;        if (f->conf.debug)            fprintf(stderr, "MKDIR %s\n", path);        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_mkdir(f->fs, path, mode);        if (!err)            err = lookup_path(f, parent, name, path, &e, NULL);        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_entry(req, &e, err);}static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,                            const char *name){    struct fuse *f = req_fuse_prepare(req);    char *path;    int err;    err = -ENOENT;    pthread_rwlock_wrlock(&f->tree_lock);    path = get_path_name(f, parent, name);    if (path != NULL) {        struct fuse_intr_data d;        if (f->conf.debug)            fprintf(stderr, "UNLINK %s\n", path);        fuse_prepare_interrupt(f, req, &d);        if (!f->conf.hard_remove && is_open(f, parent, name))            err = hide_node(f, path, parent, name);        else {            err = fuse_fs_unlink(f->fs, path);            if (!err)                remove_node(f, parent, name);        }        fuse_finish_interrupt(f, req, &d);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name){    struct fuse *f = req_fuse_prepare(req);    char *path;    int err;    err = -ENOENT;    pthread_rwlock_wrlock(&f->tree_lock);    path = get_path_name(f, parent, name);    if (path != NULL) {        struct fuse_intr_data d;        if (f->conf.debug)            fprintf(stderr, "RMDIR %s\n", path);        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_rmdir(f->fs, path);        fuse_finish_interrupt(f, req, &d);        if (!err)            remove_node(f, parent, name);        free(path);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static void fuse_lib_symlink(fuse_req_t req, const char *linkname,                             fuse_ino_t parent, const char *name){

⌨️ 快捷键说明

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