📄 fuse.c
字号:
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 + -