📄 fuse_lowlevel.c
字号:
static void do_flush(fuse_req_t req, fuse_ino_t nodeid, struct fuse_flush_in *arg){ struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; fi.fh_old = fi.fh; if (req->f->op.flush) req->f->op.flush(req, nodeid, &fi); else fuse_reply_err(req, ENOSYS);}static void do_release(fuse_req_t req, fuse_ino_t nodeid, struct fuse_release_in *arg){ struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; fi.fh = arg->fh; fi.fh_old = fi.fh; if (req->f->op.release) req->f->op.release(req, nodeid, &fi); else fuse_reply_err(req, 0);}static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, struct fuse_fsync_in *inarg){ struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.fh = inarg->fh; fi.fh_old = fi.fh; if (req->f->op.fsync) req->f->op.fsync(req, nodeid, inarg->fsync_flags & 1, &fi); else fuse_reply_err(req, ENOSYS);}static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, struct fuse_open_in *arg){ struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; if (req->f->op.opendir) req->f->op.opendir(req, nodeid, &fi); else fuse_reply_open(req, &fi);}static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, struct fuse_read_in *arg){ struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; fi.fh_old = fi.fh; if (req->f->op.readdir) req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi); else fuse_reply_err(req, ENOSYS);}static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, struct fuse_release_in *arg){ struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; fi.fh = arg->fh; fi.fh_old = fi.fh; if (req->f->op.releasedir) req->f->op.releasedir(req, nodeid, &fi); else fuse_reply_err(req, 0);}static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, struct fuse_fsync_in *inarg){ struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); fi.fh = inarg->fh; fi.fh_old = fi.fh; if (req->f->op.fsyncdir) req->f->op.fsyncdir(req, nodeid, inarg->fsync_flags & 1, &fi); else fuse_reply_err(req, ENOSYS);}static void do_statfs(fuse_req_t req){ if (req->f->op.statfs) req->f->op.statfs(req); else fuse_reply_err(req, ENOSYS);}static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, struct fuse_setxattr_in *arg){ char *name = PARAM(arg); char *value = name + strlen(name) + 1; if (req->f->op.setxattr) req->f->op.setxattr(req, nodeid, name, value, arg->size, arg->flags); else fuse_reply_err(req, ENOSYS);}static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, struct fuse_getxattr_in *arg){ if (req->f->op.getxattr) req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size); else fuse_reply_err(req, ENOSYS);}static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, struct fuse_getxattr_in *arg){ if (req->f->op.listxattr) req->f->op.listxattr(req, nodeid, arg->size); else fuse_reply_err(req, ENOSYS);}static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, char *name){ if (req->f->op.removexattr) req->f->op.removexattr(req, nodeid, name); else fuse_reply_err(req, ENOSYS);}static void do_init(fuse_req_t req, struct fuse_init_in *arg){ struct fuse_init_out outarg; struct fuse_ll *f = req->f; size_t bufsize = fuse_chan_bufsize(req->ch); if (f->debug) { printf("INIT: %u.%u\n", arg->major, arg->minor); fflush(stdout); } f->got_init = 1; if (f->op.init) f->op.init(f->userdata); f->major = FUSE_KERNEL_VERSION; f->minor = arg->minor; if (bufsize < FUSE_MIN_READ_BUFFER) { fprintf(stderr, "fuse: warning: buffer size too small: %i\n", bufsize); bufsize = FUSE_MIN_READ_BUFFER; } memset(&outarg, 0, sizeof(outarg)); outarg.major = f->major; outarg.minor = FUSE_KERNEL_MINOR_VERSION; outarg.max_write = bufsize - 4096; if (f->debug) { printf(" INIT: %u.%u\n", outarg.major, outarg.minor); fflush(stdout); } send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));}void *fuse_req_userdata(fuse_req_t req){ return req->f->userdata;}const struct fuse_ctx *fuse_req_ctx(fuse_req_t req){ return &req->ctx;}static void fuse_ll_process(void *data, const char *buf, size_t len, struct fuse_chan *ch){ struct fuse_ll *f = (struct fuse_ll *) data; struct fuse_in_header *in = (struct fuse_in_header *) buf; const void *inarg = buf + sizeof(struct fuse_in_header); struct fuse_req *req; if (f->debug) { printf("unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %i\n", in->unique, opname((enum fuse_opcode) in->opcode), in->opcode, (unsigned long) in->nodeid, len); fflush(stdout); } req = (struct fuse_req *) malloc(sizeof(struct fuse_req)); if (req == NULL) { fprintf(stderr, "fuse: failed to allocate request\n"); return; } req->f = f; req->unique = in->unique; req->ctx.uid = in->uid; req->ctx.gid = in->gid; req->ctx.pid = in->pid; req->ch = ch; if (!f->got_init && in->opcode != FUSE_INIT) fuse_reply_err(req, EIO); else if (f->allow_root && in->uid != f->owner && in->uid != 0 && in->opcode != FUSE_INIT && in->opcode != FUSE_READ && in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) { fuse_reply_err(req, EACCES); } else switch (in->opcode) { case FUSE_INIT: do_init(req, (struct fuse_init_in *) inarg); break; case FUSE_LOOKUP: do_lookup(req, in->nodeid, (char *) inarg); break; case FUSE_FORGET: do_forget(req, in->nodeid, (struct fuse_forget_in *) inarg); break; case FUSE_GETATTR: do_getattr(req, in->nodeid); break; case FUSE_SETATTR: do_setattr(req, in->nodeid, (struct fuse_setattr_in *) inarg); break; case FUSE_READLINK: do_readlink(req, in->nodeid); break; case FUSE_MKNOD: do_mknod(req, in->nodeid, (struct fuse_mknod_in *) inarg); break; case FUSE_MKDIR: do_mkdir(req, in->nodeid, (struct fuse_mkdir_in *) inarg); break; case FUSE_UNLINK: do_unlink(req, in->nodeid, (char *) inarg); break; case FUSE_RMDIR: do_rmdir(req, in->nodeid, (char *) inarg); break; case FUSE_SYMLINK: do_symlink(req, in->nodeid, (char *) inarg, ((char *) inarg) + strlen((char *) inarg) + 1); break; case FUSE_RENAME: do_rename(req, in->nodeid, (struct fuse_rename_in *) inarg); break; case FUSE_LINK: do_link(req, in->nodeid, (struct fuse_link_in *) inarg); break; case FUSE_OPEN: do_open(req, in->nodeid, (struct fuse_open_in *) inarg); break; case FUSE_FLUSH: do_flush(req, in->nodeid, (struct fuse_flush_in *) inarg); break; case FUSE_RELEASE: do_release(req, in->nodeid, (struct fuse_release_in *) inarg); break; case FUSE_READ: do_read(req, in->nodeid, (struct fuse_read_in *) inarg); break; case FUSE_WRITE: do_write(req, in->nodeid, (struct fuse_write_in *) inarg); break; case FUSE_STATFS: do_statfs(req); break; case FUSE_FSYNC: do_fsync(req, in->nodeid, (struct fuse_fsync_in *) inarg); break; case FUSE_SETXATTR: do_setxattr(req, in->nodeid, (struct fuse_setxattr_in *) inarg); break; case FUSE_GETXATTR: do_getxattr(req, in->nodeid, (struct fuse_getxattr_in *) inarg); break; case FUSE_LISTXATTR: do_listxattr(req, in->nodeid, (struct fuse_getxattr_in *) inarg); break; case FUSE_REMOVEXATTR: do_removexattr(req, in->nodeid, (char *) inarg); break; case FUSE_OPENDIR: do_opendir(req, in->nodeid, (struct fuse_open_in *) inarg); break; case FUSE_READDIR: do_readdir(req, in->nodeid, (struct fuse_read_in *) inarg); break; case FUSE_RELEASEDIR: do_releasedir(req, in->nodeid, (struct fuse_release_in *) inarg); break; case FUSE_FSYNCDIR: do_fsyncdir(req, in->nodeid, (struct fuse_fsync_in *) inarg); break; case FUSE_ACCESS: do_access(req, in->nodeid, (struct fuse_access_in *) inarg); break; case FUSE_CREATE: do_create(req, in->nodeid, (struct fuse_open_in *) inarg); break; default: fuse_reply_err(req, ENOSYS); }}enum { KEY_HELP, KEY_VERSION,};static struct fuse_opt fuse_ll_opts[] = { { "debug", offsetof(struct fuse_ll, debug), 1 }, { "-d", offsetof(struct fuse_ll, debug), 1 }, { "allow_root", offsetof(struct fuse_ll, allow_root), 1 }, FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), FUSE_OPT_KEY("-V", KEY_VERSION), FUSE_OPT_KEY("--version", KEY_VERSION), FUSE_OPT_END};static void fuse_ll_version(void){ fprintf(stderr, "using FUSE kernel interface version %i.%i\n", FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);}static int fuse_ll_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs){ (void) data; (void) outargs; switch (key) { case KEY_HELP: break; case KEY_VERSION: fuse_ll_version(); break; default: fprintf(stderr, "fuse: unknown option `%s'\n", arg); } return -1;}int fuse_lowlevel_is_lib_option(const char *opt){ return fuse_opt_match(fuse_ll_opts, opt);}static void fuse_ll_destroy(void *data){ struct fuse_ll *f = (struct fuse_ll *) data; if (f->op.destroy) f->op.destroy(f->userdata); free(f);}struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata){ struct fuse_ll *f; struct fuse_session *se; struct fuse_session_ops sop = { .process = fuse_ll_process, .destroy = fuse_ll_destroy, }; if (sizeof(struct fuse_lowlevel_ops) < op_size) { fprintf(stderr, "fuse: warning: library too old, some operations may not work\n"); op_size = sizeof(struct fuse_lowlevel_ops); } f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll)); if (f == NULL) { fprintf(stderr, "fuse: failed to allocate fuse object\n"); goto out; } if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1) goto out_free; memcpy(&f->op, op, op_size); f->owner = getuid(); f->userdata = userdata; se = fuse_session_new(&sop, f); if (!se) goto out_free; return se; out_free: free(f); out: return NULL;}#ifndef __FreeBSD__#include "fuse_lowlevel_compat.h"static void fill_open_compat(struct fuse_open_out *arg, const struct fuse_file_info_compat *f){ arg->fh = f->fh; if (f->direct_io) arg->open_flags |= FOPEN_DIRECT_IO; if (f->keep_cache) arg->open_flags |= FOPEN_KEEP_CACHE;}static void convert_statfs_compat(const struct statfs *compatbuf, struct statvfs *buf){ buf->f_bsize = compatbuf->f_bsize; buf->f_blocks = compatbuf->f_blocks; buf->f_bfree = compatbuf->f_bfree; buf->f_bavail = compatbuf->f_bavail; buf->f_files = compatbuf->f_files; buf->f_ffree = compatbuf->f_ffree; buf->f_namemax = compatbuf->f_namelen;}int fuse_reply_open_compat(fuse_req_t req, const struct fuse_file_info_compat *f){ struct fuse_open_out arg; memset(&arg, 0, sizeof(arg)); fill_open_compat(&arg, f); return send_reply_ok(req, &arg, sizeof(arg));}int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf){ struct statvfs newbuf; memset(&newbuf, 0, sizeof(newbuf)); convert_statfs_compat(stbuf, &newbuf); return fuse_reply_statfs(req, &newbuf);}struct fuse_session *fuse_lowlevel_new_compat(const char *opts, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata){ struct fuse_session *se; struct fuse_args args = FUSE_ARGS_INIT(0, NULL); if (opts && (fuse_opt_add_arg(&args, "") == -1 || fuse_opt_add_arg(&args, "-o") == -1 || fuse_opt_add_arg(&args, opts) == -1)) { fuse_opt_free_args(&args); return NULL; } se = fuse_lowlevel_new(&args, op, op_size, userdata); fuse_opt_free_args(&args); return se;}__asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");__asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");__asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");#endif /* __FreeBSD__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -