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

📄 fuse.c

📁 UNIX/LINUX下面的用户文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode){    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){    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, "SYMLINK %s\n", path);        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_symlink(f->fs, linkname, path);        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_rename(fuse_req_t req, fuse_ino_t olddir,                            const char *oldname, fuse_ino_t newdir,                            const char *newname){    struct fuse *f = req_fuse_prepare(req);    char *oldpath;    char *newpath;    int err;    err = -ENOENT;    pthread_rwlock_wrlock(&f->tree_lock);    oldpath = get_path_name(f, olddir, oldname);    if (oldpath != NULL) {        newpath = get_path_name(f, newdir, newname);        if (newpath != NULL) {            struct fuse_intr_data d;            if (f->conf.debug)                fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath);            err = 0;            fuse_prepare_interrupt(f, req, &d);            if (!f->conf.hard_remove && is_open(f, newdir, newname))                err = hide_node(f, newpath, newdir, newname);            if (!err) {                err = fuse_fs_rename(f->fs, oldpath, newpath);                if (!err)                    err = rename_node(f, olddir, oldname, newdir, newname, 0);            }            fuse_finish_interrupt(f, req, &d);            free(newpath);        }        free(oldpath);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_err(req, err);}static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,                          const char *newname){    struct fuse *f = req_fuse_prepare(req);    struct fuse_entry_param e;    char *oldpath;    char *newpath;    int err;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    oldpath = get_path(f, ino);    if (oldpath != NULL) {        newpath =  get_path_name(f, newparent, newname);        if (newpath != NULL) {            struct fuse_intr_data d;            if (f->conf.debug)                fprintf(stderr, "LINK %s\n", newpath);            fuse_prepare_interrupt(f, req, &d);            err = fuse_fs_link(f->fs, oldpath, newpath);            if (!err)                err = lookup_path(f, newparent, newname, newpath, &e, NULL);            fuse_finish_interrupt(f, req, &d);            free(newpath);        }        free(oldpath);    }    pthread_rwlock_unlock(&f->tree_lock);    reply_entry(req, &e, err);}static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,                            struct fuse_file_info *fi){    struct node *node;    int unlink_hidden = 0;    fuse_fs_release(f->fs, path ? path : "-", fi);    pthread_mutex_lock(&f->lock);    node = get_node(f, ino);    assert(node->open_count > 0);    --node->open_count;    if (node->is_hidden && !node->open_count) {        unlink_hidden = 1;        node->is_hidden = 0;    }    pthread_mutex_unlock(&f->lock);    if(unlink_hidden && path)        fuse_fs_unlink(f->fs, path);}static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,                            const char *name, mode_t mode,                            struct fuse_file_info *fi){    struct fuse *f = req_fuse_prepare(req);    struct fuse_intr_data d;    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) {        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_create(f->fs, path, mode, fi);        if (!err) {            err = lookup_path(f, parent, name, path, &e, fi);            if (err)                fuse_fs_release(f->fs, path, fi);            else if (!S_ISREG(e.attr.st_mode)) {                err = -EIO;                fuse_fs_release(f->fs, path, fi);                forget_node(f, e.ino, 1);            } else {                if (f->conf.direct_io)                    fi->direct_io = 1;                if (f->conf.kernel_cache)                    fi->keep_cache = 1;            }        }        fuse_finish_interrupt(f, req, &d);    }    if (!err) {        pthread_mutex_lock(&f->lock);        get_node(f, e.ino)->open_count++;        pthread_mutex_unlock(&f->lock);        if (fuse_reply_create(req, &e, fi) == -ENOENT) {            /* The open syscall was interrupted, so it must be cancelled */            fuse_prepare_interrupt(f, req, &d);            fuse_do_release(f, e.ino, path, fi);            fuse_finish_interrupt(f, req, &d);            forget_node(f, e.ino, 1);        } else if (f->conf.debug) {            fprintf(stderr, "  CREATE[%llu] flags: 0x%x %s\n",                    (unsigned long long) fi->fh, fi->flags, path);        }    } else        reply_err(req, err);    if (path)        free(path);    pthread_rwlock_unlock(&f->tree_lock);}static double diff_timespec(const struct timespec *t1,                            const struct timespec *t2){    return (t1->tv_sec - t2->tv_sec) +         ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;}static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,                            struct fuse_file_info *fi){    struct node *node;    pthread_mutex_lock(&f->lock);    node = get_node(f, ino);    if (node->cache_valid) {        struct timespec now;        curr_time(&now);        if (diff_timespec(&now, &node->stat_updated) > f->conf.ac_attr_timeout) {            struct stat stbuf;            int err;            pthread_mutex_unlock(&f->lock);            err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);            pthread_mutex_lock(&f->lock);            if (!err)                update_stat(node, &stbuf);            else                node->cache_valid = 0;        }    }    if (node->cache_valid)        fi->keep_cache = 1;    node->cache_valid = 1;    pthread_mutex_unlock(&f->lock);}static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,                          struct fuse_file_info *fi){    struct fuse *f = req_fuse_prepare(req);    struct fuse_intr_data d;    char *path = NULL;    int err = 0;    err = -ENOENT;    pthread_rwlock_rdlock(&f->tree_lock);    path = get_path(f, ino);    if (path) {        fuse_prepare_interrupt(f, req, &d);        err = fuse_fs_open(f->fs, path, fi);        if (!err) {            if (f->conf.direct_io)                fi->direct_io = 1;            if (f->conf.kernel_cache)                fi->keep_cache = 1;            if (f->conf.auto_cache)                open_auto_cache(f, ino, path, fi);        }        fuse_finish_interrupt(f, req, &d);    }    if (!err) {        pthread_mutex_lock(&f->lock);        get_node(f, ino)->open_count++;        pthread_mutex_unlock(&f->lock);        if (fuse_reply_open(req, fi) == -ENOENT) {            /* The open syscall was interrupted, so it must be cancelled */            fuse_prepare_interrupt(f, req, &d);            fuse_do_release(f, ino, path, fi);            fuse_finish_interrupt(f, req, &d);        } else if (f->conf.debug) {

⌨️ 快捷键说明

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