Module Name: src Committed By: pho Date: Sun Nov 20 13:28:32 UTC 2016
Modified Files: src/lib/librefuse: fuse.h refuse.3 refuse.c Log Message: fuse_main(3): Support general fuse options via fuse_parse_cmdline(3) * Prototypes for fuse_new(3), fuse_mount(3), and fuse_unmount(3) now matches to the original fuse interface. * Add fuse_daemonize(3): needs to have a different prototype, otherwise we can't use puffs_daemon(3). * Remove fuse_setup(3) and fuse_teardown(3). These obsolete functions has already been removed from the original interface. * fuse_main(3) now supports the following command-line options compatible with the original fuse: -h, --help print help message -V, --version print library version (currently does nothing) -d, -o debug enable debug output (PUFFS_FLAG_OPDUMP), implies -f -f foreground mode -s single threaded mode (always enabled for now) -o fsname=NAME explicitly set the name of the file system * fuse_main(3) now daemonizes the process by default. This is for the compatibility with the original fuse. To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/lib/librefuse/fuse.h cvs rdiff -u -r1.12 -r1.13 src/lib/librefuse/refuse.3 cvs rdiff -u -r1.97 -r1.98 src/lib/librefuse/refuse.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/librefuse/fuse.h diff -u src/lib/librefuse/fuse.h:1.21 src/lib/librefuse/fuse.h:1.22 --- src/lib/librefuse/fuse.h:1.21 Fri Aug 1 15:54:09 2008 +++ src/lib/librefuse/fuse.h Sun Nov 20 13:28:32 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: fuse.h,v 1.21 2008/08/01 15:54:09 dillo Exp $ */ +/* $NetBSD: fuse.h,v 1.22 2016/11/20 13:28:32 pho Exp $ */ /* * Copyright © 2007 Alistair Crooks. All rights reserved. @@ -150,22 +150,20 @@ struct fuse_operations { }; -struct fuse_chan *fuse_mount(const char *, struct fuse_args *); -struct fuse *fuse_new(struct fuse_chan *, struct fuse_args *, +struct fuse *fuse_new(struct fuse_args *, const struct fuse_operations *, size_t, void *); +int fuse_mount(struct fuse *, const char *); +void fuse_unmount(struct fuse *); + +int fuse_daemonize(struct fuse *); + int fuse_main_real(int, char **, const struct fuse_operations *, size_t, void *); int fuse_loop(struct fuse *); struct fuse_context *fuse_get_context(void); void fuse_exit(struct fuse *); void fuse_destroy(struct fuse *); -void fuse_unmount(const char *, struct fuse_chan *); - -struct fuse *fuse_setup(int, char **, const struct fuse_operations *, - size_t, char **, int *, int *); -void fuse_teardown(struct fuse *, char *); - #if FUSE_USE_VERSION == 22 #define fuse_unmount fuse_unmount_compat22 #endif @@ -173,17 +171,13 @@ void fuse_teardown(struct fuse *, char * void fuse_unmount_compat22(const char *); #if FUSE_USE_VERSION >= 26 -#define fuse_main(argc, argv, op, arg) \ - fuse_main_real(argc, argv, op, sizeof(*(op)), arg) -#define fuse_setup fuse_setup26 +#define fuse_main(argc, argv, op, user_data) \ + fuse_main_real(argc, argv, op, sizeof(*(op)), user_data) #else #define fuse_main(argc, argv, op) \ fuse_main_real(argc, argv, op, sizeof(*(op)), NULL) #endif -struct fuse *fuse_setup26(int, char **, const struct fuse_operations *, - size_t, char **, int *, void *); - #ifdef __cplusplus } #endif Index: src/lib/librefuse/refuse.3 diff -u src/lib/librefuse/refuse.3:1.12 src/lib/librefuse/refuse.3:1.13 --- src/lib/librefuse/refuse.3:1.12 Tue Nov 15 00:34:19 2016 +++ src/lib/librefuse/refuse.3 Sun Nov 20 13:28:32 2016 @@ -1,4 +1,4 @@ -.\" $NetBSD: refuse.3,v 1.12 2016/11/15 00:34:19 pho Exp $ +.\" $NetBSD: refuse.3,v 1.13 2016/11/20 13:28:32 pho Exp $ .\" .\" Copyright © 2007 Alistair Crooks. All rights reserved. .\" @@ -83,13 +83,21 @@ .Fa "const struct fuse_opt *descriptions" "fuse_opt_proc_t processingfunc" .Fc .Ft int -.Fo fuse_teardown -.Fa "struct fuse *fuse" "char *mountpoint" +.Fo fuse_new +.Fa "struct fuse_args *args" "const struct fuse_operations *ops" +.Fa "size_t opssize" "void *userdata" .Fc -.Ft struct fuse * -.Fo fuse_setup -.Fa "int argc" "char **argv" "const struct fuse_operations *ops" -.Fa "size_t opssize" "char **mountpoint" "int *multithreaded" "int *fd" +.Ft int +.Fo fuse_mount +.Fa "struct fuse *fuse" "const char *mountpoint" +.Fc +.Ft int +.Fo fuse_unmount +.Fa "struct fuse* fuse" +.Fc +.Ft int +.Fo fuse_daemonize +.Fa "struct fuse *fuse" .Fc .Ft int .Fo puffs_fuse_node_getattr Index: src/lib/librefuse/refuse.c diff -u src/lib/librefuse/refuse.c:1.97 src/lib/librefuse/refuse.c:1.98 --- src/lib/librefuse/refuse.c:1.97 Thu Nov 17 14:20:25 2016 +++ src/lib/librefuse/refuse.c Sun Nov 20 13:28:32 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: refuse.c,v 1.97 2016/11/17 14:20:25 pho Exp $ */ +/* $NetBSD: refuse.c,v 1.98 2016/11/20 13:28:32 pho Exp $ */ /* * Copyright © 2007 Alistair Crooks. All rights reserved. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #if !defined(lint) -__RCSID("$NetBSD: refuse.c,v 1.97 2016/11/17 14:20:25 pho Exp $"); +__RCSID("$NetBSD: refuse.c,v 1.98 2016/11/20 13:28:32 pho Exp $"); #endif /* !lint */ #include <sys/types.h> @@ -40,7 +40,10 @@ __RCSID("$NetBSD: refuse.c,v 1.97 2016/1 #include <err.h> #include <errno.h> #include <fuse.h> +#include <fuse_lowlevel.h> +#include <fuse_opt.h> #include <paths.h> +#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -51,39 +54,24 @@ __RCSID("$NetBSD: refuse.c,v 1.97 2016/1 typedef uint64_t fuse_ino_t; -struct fuse_config { - uid_t uid; - gid_t gid; - mode_t umask; - double entry_timeout; - double negative_timeout; - double attr_timeout; - double ac_attr_timeout; - int ac_attr_timeout_set; - int debug; - int hard_remove; - int use_ino; - int readdir_ino; - int set_mode; - int set_uid; - int set_gid; - int direct_io; - int kernel_cache; - int auto_cache; - int intr; - int intr_signal; +struct refuse_config { + int debug; + char *fsname; }; -struct fuse_chan { - const char *dir; - struct fuse_args *args; - struct puffs_usermount *pu; - int dead; +#define REFUSE_OPT(t, p, v) \ + { t, offsetof(struct refuse_config, p), v } + +static struct fuse_opt refuse_opts[] = { + REFUSE_OPT("debug" , debug , 1), + REFUSE_OPT("fsname=%s", fsname, 0), + FUSE_OPT_END }; /* this is the private fuse structure */ struct fuse { - struct fuse_chan *fc; /* fuse channel pointer */ + struct puffs_usermount *pu; + int dead; struct fuse_operations op; /* switch table of operations */ int compat; /* compat level - * not used in puffs_fuse */ @@ -97,7 +85,6 @@ struct fuse { pthread_mutex_t lock; pthread_rwlock_t tree_lock; void *user_data; - struct fuse_config conf; int intr_installed; }; @@ -339,103 +326,6 @@ puffs_fuse_dirfil(fuse_dirh_t h, const c return fill_dirbuf(h, name, dino, dtype); } -/* place the refuse file system name into `name' */ -static void -set_refuse_mount_name(char **argv, char *name, size_t size) -{ - char *slash; - - if (argv == NULL || *argv == NULL) { - (void) strlcpy(name, "refuse", size); - } else { - if ((slash = strrchr(*argv, '/')) == NULL) { - slash = *argv; - } else { - slash += 1; - } - if (strncmp(*argv, "refuse:", 7) == 0) { - /* we've already done this */ - (void) strlcpy(name, *argv, size); - } else { - (void) snprintf(name, size, "refuse:%s", slash); - } - } -} - - -/* this function exposes struct fuse to userland */ -static struct fuse * -fuse_setup_real(int argc, char **argv, const struct fuse_operations *ops, - size_t size, char **mountpoint, int *multithreaded, int *fd, - void *user_data) -{ - struct fuse_chan *fc; - struct fuse_args *args; - struct fuse *fuse; - char name[64]; - int i; - - /* set up the proper name */ - set_refuse_mount_name(argv, name, sizeof(name)); - - /* grab the pthread context key */ - if (!create_context_key()) { - return NULL; - } - - /* stuff name into fuse_args */ - args = fuse_opt_deep_copy_args(argc, argv); - if (args->argc > 0) { - free(args->argv[0]); - } - if ((args->argv[0] = strdup(name)) == NULL) { - fuse_opt_free_args(args); - return NULL; - } - - /* count back from the end over arguments starting with '-' */ - for (i = argc - 1 ; i > 0 && *argv[i] == '-' ; --i) { - } - - fc = fuse_mount(*mountpoint = argv[i], args); - fuse = fuse_new(fc, args, ops, size, user_data); - - fuse_opt_free_args(args); - free(args); - - /* XXX - wait for puffs to become multi-threaded */ - if (multithreaded) { - *multithreaded = 0; - } - - /* XXX - this is unused */ - if (fd) { - *fd = 0; - } - - return fuse; -} - -#ifdef fuse_setup -#undef fuse_setup -#endif - -struct fuse * -fuse_setup(int argc, char **argv, const struct fuse_operations *ops, - size_t size, char **mountpoint, int *multithreaded, int *fd) -{ - return fuse_setup_real(argc, argv, ops, size, mountpoint, - multithreaded, fd, NULL); -} - -struct fuse * -fuse_setup26(int argc, char **argv, const struct fuse_operations *ops, - size_t size, char **mountpoint, int *multithreaded, void *user_data) -{ - return fuse_setup_real(argc, argv, ops, size, mountpoint, - multithreaded, NULL, user_data); -} - #define FUSE_ERR_UNLINK(fuse, file) if (fuse->op.unlink) fuse->op.unlink(file) #define FUSE_ERR_RMDIR(fuse, dir) if (fuse->op.rmdir) fuse->op.rmdir(dir) @@ -1232,73 +1122,136 @@ puffs_fuse_fs_statvfs(struct puffs_userm /* ARGSUSED3 */ int fuse_main_real(int argc, char **argv, const struct fuse_operations *ops, - size_t size, void *userdata) + size_t size, void *user_data) { - struct fuse *fuse; - char *mountpoint; - int multithreaded; - int fd; + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse_cmdline_opts opts; + struct fuse *fuse; + int rv; + + /* parse low-level options */ + if (fuse_parse_cmdline(&args, &opts) == -1) { + return 1; + } + + if (opts.show_version) { + fuse_lowlevel_version(); + rv = 0; + goto free_args; + } + + if (opts.show_help) { + if (args.argv[0] != NULL && args.argv[0][0] != '\0') { + /* argv[0] being empty means that the application doesn't + * want us to print the usage string. + */ + printf("Usage: %s [options] mountpoint\n\n", args.argv[0]); + } + fuse_cmdline_help(); + rv = 0; + goto free_args; + } - fuse = fuse_setup_real(argc, argv, ops, size, &mountpoint, - &multithreaded, &fd, userdata); + if (opts.mountpoint == NULL) { + fprintf(stderr, "fuse: no mountpoint specified\n"); + rv = 1; + goto free_args; + } - return fuse_loop(fuse); -} + if (opts.debug) { + if (fuse_opt_add_arg(&args, "-odebug") == -1) { + rv = 1; + goto free_args; + } + } -/* - * XXX: just defer the operation until fuse_new() when we have more - * info on our hands. The real beef is why's this separate in fuse in - * the first place? - */ -/* ARGSUSED1 */ -struct fuse_chan * -fuse_mount(const char *dir, struct fuse_args *args) -{ - struct fuse_chan *fc; - char name[64]; + fuse = fuse_new(&args, ops, size, user_data); + if (fuse == NULL) { + rv = 1; + goto free_args; + } - if ((fc = calloc(1, sizeof(*fc))) == NULL) { - err(EXIT_FAILURE, "fuse_mount"); + if (!opts.foreground) { + if (fuse_daemonize(fuse) == -1) { + rv = 1; + goto destroy; + } } - fc->dead = 0; - if ((fc->dir = strdup(dir)) == NULL) { - err(EXIT_FAILURE, "fuse_mount"); + if (fuse_mount(fuse, opts.mountpoint) == -1) { + rv = 1; + goto destroy; } - /* - * we need to deep copy the args struct - some fuse file - * systems "clean up" the argument vector for "security - * reasons" - */ - fc->args = fuse_opt_deep_copy_args(args->argc, args->argv); + rv = fuse_loop(fuse); - if (args->argc > 0) { - set_refuse_mount_name(args->argv, name, sizeof(name)); - if ((args->argv[0] = strdup(name)) == NULL) - err(1, "fuse_mount"); + fuse_unmount(fuse); +destroy: + fuse_destroy(fuse); +free_args: + free(opts.mountpoint); + fuse_opt_free_args(&args); + return rv; +} + +int fuse_mount(struct fuse *fuse, const char *mountpoint) +{ + struct puffs_pathobj *po_root; + struct puffs_node *pn_root; + struct refusenode *rn_root; + struct stat st; + struct statvfs svfsb; + + pn_root = newrn(fuse->pu); + puffs_setroot(fuse->pu, pn_root); + rn_root = pn_root->pn_data; + rn_root->flags |= RN_ROOT; + + po_root = puffs_getrootpathobj(fuse->pu); + if ((po_root->po_path = strdup("/")) == NULL) + err(1, "fuse_mount"); + po_root->po_len = 1; + puffs_path_buildhash(fuse->pu, po_root); + + /* sane defaults */ + puffs_vattr_null(&pn_root->pn_va); + pn_root->pn_va.va_type = VDIR; + pn_root->pn_va.va_mode = 0755; + if (fuse->op.getattr) + if (fuse->op.getattr(po_root->po_path, &st) == 0) + puffs_stat2vattr(&pn_root->pn_va, &st); + assert(pn_root->pn_va.va_type == VDIR); + + puffs_set_prepost(fuse->pu, set_fuse_context_pid, NULL); + + puffs_zerostatvfs(&svfsb); + if (puffs_mount(fuse->pu, mountpoint, MNT_NODEV | MNT_NOSUID, pn_root) == -1) { + err(EXIT_FAILURE, "puffs_mount: directory \"%s\"", mountpoint); } - - return fc; + + return 0; +} + +int fuse_daemonize(struct fuse *fuse) +{ + return puffs_daemon(fuse->pu, 0, 0); } /* ARGSUSED1 */ struct fuse * -fuse_new(struct fuse_chan *fc, struct fuse_args *args, +fuse_new(struct fuse_args *args, const struct fuse_operations *ops, size_t size, void *userdata) { + struct refuse_config config; struct puffs_usermount *pu; struct fuse_context *fusectx; - struct puffs_pathobj *po_root; - struct puffs_node *pn_root; struct puffs_ops *pops; - struct refusenode *rn_root; - struct statvfs svfsb; - struct stat st; struct fuse *fuse; - extern int puffs_fakecc; - char name[64]; - char *argv0; + int puffs_flags; + + /* parse refuse options */ + if (fuse_opt_parse(args, &config, refuse_opts, NULL) == -1) + return NULL; if ((fuse = calloc(1, sizeof(*fuse))) == NULL) { err(EXIT_FAILURE, "fuse_new"); @@ -1307,6 +1260,13 @@ fuse_new(struct fuse_chan *fc, struct fu /* copy fuse ops to their own structure */ (void) memcpy(&fuse->op, ops, sizeof(fuse->op)); + /* grab the pthread context key */ + if (!create_context_key()) { + free(config.fsname); + free(fuse); + return NULL; + } + fusectx = fuse_get_context(); fusectx->fuse = fuse; fusectx->uid = 0; @@ -1314,8 +1274,6 @@ fuse_new(struct fuse_chan *fc, struct fu fusectx->pid = 0; fusectx->private_data = userdata; - fuse->fc = fc; - if (fuse->op.init != NULL) fusectx->private_data = fuse->op.init(NULL); /* XXX */ @@ -1349,54 +1307,26 @@ fuse_new(struct fuse_chan *fc, struct fu PUFFSOP_SET(pops, puffs_fuse, node, write); PUFFSOP_SET(pops, puffs_fuse, node, reclaim); - argv0 = (*args->argv[0] == 0x0) ? fc->args->argv[0] : args->argv[0]; - set_refuse_mount_name(&argv0, name, sizeof(name)); + puffs_flags = PUFFS_FLAG_BUILDPATH + | PUFFS_FLAG_HASHPATH + | PUFFS_KFLAG_NOCACHE; + if (config.debug) + puffs_flags |= PUFFS_FLAG_OPDUMP; - puffs_fakecc = 1; /* XXX */ - pu = puffs_init(pops, _PATH_PUFFS, name, fuse, - PUFFS_FLAG_BUILDPATH - | PUFFS_FLAG_HASHPATH - | PUFFS_KFLAG_NOCACHE); + pu = puffs_init(pops, _PATH_PUFFS, config.fsname, fuse, puffs_flags); if (pu == NULL) { err(EXIT_FAILURE, "puffs_init"); } - fc->pu = pu; - - pn_root = newrn(pu); - puffs_setroot(pu, pn_root); - rn_root = pn_root->pn_data; - rn_root->flags |= RN_ROOT; - - po_root = puffs_getrootpathobj(pu); - if ((po_root->po_path = strdup("/")) == NULL) - err(1, "fuse_new"); - po_root->po_len = 1; - puffs_path_buildhash(pu, po_root); - - /* sane defaults */ - puffs_vattr_null(&pn_root->pn_va); - pn_root->pn_va.va_type = VDIR; - pn_root->pn_va.va_mode = 0755; - if (fuse->op.getattr) - if (fuse->op.getattr(po_root->po_path, &st) == 0) - puffs_stat2vattr(&pn_root->pn_va, &st); - assert(pn_root->pn_va.va_type == VDIR); - - puffs_set_prepost(pu, set_fuse_context_pid, NULL); - - puffs_zerostatvfs(&svfsb); - if (puffs_mount(pu, fc->dir, MNT_NODEV | MNT_NOSUID, pn_root) == -1) { - err(EXIT_FAILURE, "puffs_mount: directory \"%s\"", fc->dir); - } + fuse->pu = pu; + free(config.fsname); return fuse; } int fuse_loop(struct fuse *fuse) { - - return puffs_mainloop(fuse->fc->pu); + return puffs_mainloop(fuse->pu); } void @@ -1416,11 +1346,10 @@ fuse_destroy(struct fuse *fuse) void fuse_exit(struct fuse *fuse) { - /* XXX: puffs_exit() is WRONG */ - if (fuse->fc->dead == 0) - puffs_exit(fuse->fc->pu, 1); - fuse->fc->dead = 1; + if (fuse->dead == 0) + puffs_exit(fuse->pu, 1); + fuse->dead = 1; } /* @@ -1429,13 +1358,12 @@ fuse_exit(struct fuse *fuse) */ /*ARGSUSED*/ void -fuse_unmount(const char *mp, struct fuse_chan *fc) +fuse_unmount(struct fuse* fuse) { - /* XXX: puffs_exit() is WRONG */ - if (fc->dead == 0) - puffs_exit(fc->pu, 1); - fc->dead = 1; + if (fuse->dead == 0) + puffs_exit(fuse->pu, 1); + fuse->dead = 1; } /*ARGSUSED*/ @@ -1445,14 +1373,3 @@ fuse_unmount_compat22(const char *mp) return; } - -/* The next function "exposes" struct fuse to userland. Not much -* that we can do about this, as we're conforming to a defined -* interface. */ - -void -fuse_teardown(struct fuse *fuse, char *mountpoint) -{ - fuse_unmount(mountpoint, fuse->fc); - fuse_destroy(fuse); -}