📄 fuse.c
字号:
memset(&buf, 0, sizeof(buf)); err = -ENOENT; pthread_rwlock_rdlock(&f->tree_lock); path = get_path(f, ino); if (path != NULL) { err = -ENOSYS; if (f->op.getattr) err = fuse_do_getattr(f, req, path, &buf); 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 int do_chmod(struct fuse *f, fuse_req_t req, const char *path, struct stat *attr){ int err; err = -ENOSYS; if (f->op.chmod) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.chmod(path, attr->st_mode); fuse_finish_interrupt(f, req, &d); } return err;}static int do_chown(struct fuse *f, fuse_req_t req, const char *path, struct stat *attr, int valid){ int err; 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 = -ENOSYS; if (f->op.chown) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.chown(path, uid, gid); fuse_finish_interrupt(f, req, &d); } return err;}static int do_truncate(struct fuse *f, fuse_req_t req, const char *path, struct stat *attr, struct fuse_file_info *fi){ int err; struct fuse_intr_data d; err = -ENOSYS; if (fi && f->op.ftruncate) { fuse_prepare_interrupt(f, req, &d); err = f->op.ftruncate(path, attr->st_size, fi); fuse_finish_interrupt(f, req, &d); } else if (f->op.truncate) { fuse_prepare_interrupt(f, req, &d); err = f->op.truncate(path, attr->st_size); fuse_finish_interrupt(f, req, &d); } return err;}static int do_utimens(struct fuse *f, fuse_req_t req, const char *path, struct stat *attr){ int err; struct fuse_intr_data d; err = -ENOSYS; if (f->op.utimens) { struct timespec tv[2];#ifdef FUSE_STAT_HAS_NANOSEC tv[0] = ST_ATIM(attr); tv[1] = ST_MTIM(attr);#else tv[0].tv_sec = attr->st_atime; tv[0].tv_nsec = 0; tv[1].tv_sec = attr->st_mtime; tv[1].tv_nsec = 0;#endif fuse_prepare_interrupt(f, req, &d); err = f->op.utimens(path, tv); fuse_finish_interrupt(f, req, &d); } else if (f->op.utime) { struct utimbuf buf; buf.actime = attr->st_atime; buf.modtime = attr->st_mtime; fuse_prepare_interrupt(f, req, &d); err = f->op.utime(path, &buf); fuse_finish_interrupt(f, req, &d); } return err;}static void fuse_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) { err = -ENOSYS; if (f->op.getattr) { err = 0; if (!err && (valid & FUSE_SET_ATTR_MODE)) err = do_chmod(f, req, path, attr); if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) err = do_chown(f, req, path, attr, valid); if (!err && (valid & FUSE_SET_ATTR_SIZE)) err = do_truncate(f, req, path, attr, fi); if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) err = do_utimens(f, req, path, attr); if (!err) err = fuse_do_getattr(f, req, path, &buf); } 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_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) { if (f->conf.debug) { printf("ACCESS %s 0%o\n", path, mask); fflush(stdout); } err = -ENOSYS; if (f->op.access) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.access(path, mask); fuse_finish_interrupt(f, req, &d); } free(path); } pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err);}static void fuse_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) { err = -ENOSYS; if (f->op.readlink) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.readlink(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_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 != NULL) { if (f->conf.debug) { printf("MKNOD %s\n", path); fflush(stdout); } err = -ENOSYS; if (S_ISREG(mode) && f->op.create && f->op.getattr) { struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.flags = O_CREAT | O_EXCL | O_WRONLY; err = fuse_do_create(f, req, path, mode, &fi); if (!err) { err = lookup_path(f, req, parent, name, path, &e, &fi); if (f->op.release) fuse_do_release(f, req, path, &fi); } } else if (f->op.mknod && f->op.getattr) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.mknod(path, mode, rdev); fuse_finish_interrupt(f, req, &d); if (!err) err = lookup_path(f, req, parent, name, path, &e, NULL); } free(path); } pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err);}static void fuse_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) { if (f->conf.debug) { printf("MKDIR %s\n", path); fflush(stdout); } err = -ENOSYS; if (f->op.mkdir && f->op.getattr) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.mkdir(path, mode); fuse_finish_interrupt(f, req, &d); if (!err) err = lookup_path(f, req, parent, name, path, &e, NULL); } free(path); } pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err);}static void fuse_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) { if (f->conf.debug) { printf("UNLINK %s\n", path); fflush(stdout); } err = -ENOSYS; if (f->op.unlink) { if (!f->conf.hard_remove && is_open(f, parent, name)) err = hide_node(f, req, path, parent, name); else { err = fuse_do_unlink(f, req, path); if (!err) remove_node(f, parent, name); } } free(path); } pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err);}static void fuse_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) { if (f->conf.debug) { printf("RMDIR %s\n", path); fflush(stdout); } err = -ENOSYS; if (f->op.rmdir) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.rmdir(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_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) { if (f->conf.debug) { printf("SYMLINK %s\n", path); fflush(stdout); } err = -ENOSYS; if (f->op.symlink && f->op.getattr) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.symlink(linkname, path); fuse_finish_interrupt(f, req, &d); if (!err) err = lookup_path(f, req, parent, name, path, &e, NULL); } free(path); } pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err);}static void fuse_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) { if (f->conf.debug) { printf("RENAME %s -> %s\n", oldpath, newpath); fflush(stdout); } err = -ENOSYS; if (f->op.rename) { err = 0; if (!f->conf.hard_remove && is_open(f, newdir, newname)) err = hide_node(f, req, newpath, newdir, newname); if (!err) { err = fuse_do_rename(f, req, oldpath, newpath); if (!err) err = rename_node(f, olddir, oldname, newdir, newname, 0); } } free(newpath); } free(oldpath); } pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err);}static void fuse_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) { if (f->conf.debug) { printf("LINK %s\n", newpath); fflush(stdout); } err = -ENOSYS; if (f->op.link && f->op.getattr) { struct fuse_intr_data d; fuse_prepare_interrupt(f, req, &d); err = f->op.link(oldpath, newpath); fuse_finish_interrupt(f, req, &d); if (!err) err = lookup_path(f, req, newparent, newname, newpath, &e, NULL); } free(newpath); } free(oldpath); } pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err);}static void fuse_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_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) { err = -ENOSYS; if (f->op.create && f->op.getattr) { err = fuse_do_create(f, req, path, mode, fi); if (!err) { if (f->conf.debug) { printf("CREATE[%llu] flags: 0x%x %s\n", (unsigned long long) fi->fh, fi->flags, path); fflush(stdout); } err = lookup_path(f, req, parent, name, path, &e, fi); if (err) { if (f->op.release) fuse_do_release(f, req, path, fi); } else if (!S_ISREG(e.attr.st_mode)) { err = -EIO; if (f->op.release) fuse_do_release(f, req, path, fi); forget_node(f, e.ino, 1); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -