📄 fuse.c
字号:
int err){ if (!err) { if (fuse_reply_entry(req, e) == -ENOENT) forget_node(req_fuse(req), e->ino, 1); } else reply_err(req, err);}static void fuse_data_init(void *data){ struct fuse *f = (struct fuse *) data; struct fuse_context *c = fuse_get_context(); memset(c, 0, sizeof(*c)); c->fuse = f; if (f->op.init) f->user_data = f->op.init();}static void fuse_data_destroy(void *data){ struct fuse *f = (struct fuse *) data; struct fuse_context *c = fuse_get_context(); memset(c, 0, sizeof(*c)); c->fuse = f; c->private_data = f->user_data; if (f->op.destroy) f->op.destroy(f->user_data);}static void fuse_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) { if (f->conf.debug) { printf("LOOKUP %s\n", path); fflush(stdout); } err = -ENOSYS; if (f->op.getattr) { 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; } } free(path); } pthread_rwlock_unlock(&f->tree_lock); reply_entry(req, &e, err);}static void fuse_forget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup){ struct fuse *f = req_fuse(req); if (f->conf.debug) { printf("FORGET %llu/%lu\n", (unsigned long long) ino, nlookup); fflush(stdout); } forget_node(f, ino, nlookup); fuse_reply_none(req);}static void fuse_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; err = -ENOENT; pthread_rwlock_rdlock(&f->tree_lock); path = get_path(f, ino); if (path != NULL) { err = -ENOSYS; if (f->op.getattr) err = f->op.getattr(path, &buf); free(path); } pthread_rwlock_unlock(&f->tree_lock); if (!err) { 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, const char *path, struct stat *attr){ int err; err = -ENOSYS; if (f->op.chmod) err = f->op.chmod(path, attr->st_mode); return err;}static int do_chown(struct fuse *f, 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) err = f->op.chown(path, uid, gid); return err;}static int do_truncate(struct fuse *f, const char *path, struct stat *attr, struct fuse_file_info *fi){ int err; err = -ENOSYS; if (fi && f->op.ftruncate) err = f->op.ftruncate(path, attr->st_size, fi); else if (f->op.truncate) err = f->op.truncate(path, attr->st_size); return err;}static int do_utime(struct fuse *f, const char *path, struct stat *attr){ int err; struct utimbuf buf; buf.actime = attr->st_atime; buf.modtime = attr->st_mtime; err = -ENOSYS; if (f->op.utime) err = f->op.utime(path, &buf); 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, path, attr); if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) err = do_chown(f, path, attr, valid); if (!err && (valid & FUSE_SET_ATTR_SIZE)) err = do_truncate(f, path, attr, fi); if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) err = do_utime(f, path, attr); if (!err) err = f->op.getattr(path, &buf); } free(path); } pthread_rwlock_unlock(&f->tree_lock); if (!err) { 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) err = f->op.access(path, mask); 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) err = f->op.readlink(path, linkname, sizeof(linkname)); 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 = f->op.create(path, mode, &fi); if (!err) { err = lookup_path(f, parent, name, path, &e, &fi); if (f->op.release) f->op.release(path, &fi); } } else if (f->op.mknod && f->op.getattr) { err = f->op.mknod(path, mode, rdev); if (!err) err = lookup_path(f, 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) { err = f->op.mkdir(path, mode); if (!err) err = lookup_path(f, 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, path, parent, name); else { err = f->op.unlink(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) { err = f->op.rmdir(path); 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) { err = f->op.symlink(linkname, path); if (!err) err = lookup_path(f, 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, newpath, newdir, newname); if (!err) { err = f->op.rename(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) { err = f->op.link(oldpath, newpath); if (!err) err = lookup_path(f, 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 = f->op.create(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, parent, name, path, &e, fi); if (err) { if (f->op.release) f->op.release(path, fi); } else if (!S_ISREG(e.attr.st_mode)) { err = -EIO; if (f->op.release) f->op.release(path, fi); forget_node(f, e.ino, 1); } } } } if (!err) { if (f->conf.direct_io) fi->direct_io = 1; if (f->conf.kernel_cache) fi->keep_cache = 1; pthread_mutex_lock(&f->lock); if (fuse_reply_create(req, &e, fi) == -ENOENT) { /* The open syscall was interrupted, so it must be cancelled */ if(f->op.release) f->op.release(path, fi); forget_node(f, e.ino, 1); } else { struct node *node = get_node(f, e.ino); node->open_count ++; } pthread_mutex_unlock(&f->lock); } else reply_err(req, err); if (path) free(path); pthread_rwlock_unlock(&f->tree_lock);}static void fuse_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi){ struct fuse *f = req_fuse_prepare(req); char *path = NULL; int err = 0; pthread_rwlock_rdlock(&f->tree_lock); if (f->op.open) { err = -ENOENT; path = get_path(f, ino); if (path != NULL) err = fuse_do_open(f, path, fi); } if (!err) { if (f->conf.debug) { printf("OPEN[%llu] flags: 0x%x\n", (unsigned long long) fi->fh, fi->flags); fflush(stdout); } if (f->conf.direct_io) fi->direct_io = 1; if (f->conf.kernel_cache) fi->keep_cache = 1; pthread_mutex_lock(&f->lock);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -