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);
-}

Reply via email to