On Sat, Mar 12, 2016 at 02:14:36AM -0500, Theodore Ts'o wrote: > Use libfuse's command line parsing, which is much more powerful and > flexible than what we had before, and to allow the user to have more > fine-grained control over FUSE's run-time options. Looks reasonable enough to me, Reviewed-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --D > > Signed-off-by: Theodore Ts'o <tytso@xxxxxxx> > --- > misc/fuse2fs.c | 185 +++++++++++++++++++++++++++++++++++++-------------------- > 1 file changed, 120 insertions(+), 65 deletions(-) > > diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c > index 1cbdcb7..4412fe3 100644 > --- a/misc/fuse2fs.c > +++ b/misc/fuse2fs.c > @@ -36,6 +36,8 @@ > #include "ext2fs/ext2fs.h" > #include "ext2fs/ext2_fs.h" > > +#include "../version.h" > + > #ifdef ENABLE_NLS > #include <libintl.h> > #include <locale.h> > @@ -303,6 +305,10 @@ struct fuse2fs { > unsigned long magic; > ext2_filsys fs; > pthread_mutex_t bfl; > + char *device; > + int ro; > + int debug; > + int no_default_opts; > int panic_on_error; > int minixdf; > int alloc_all_blocks; > @@ -3624,49 +3630,100 @@ static int get_random_bytes(void *p, size_t sz) > return (size_t) r == sz; > } > > -static void print_help(const char *progname) > +enum { > + FUSE2FS_VERSION, > + FUSE2FS_HELP, > + FUSE2FS_HELPFULL, > +}; > + > +#define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v } > + > +static struct fuse_opt fuse2fs_opts[] = { > + FUSE2FS_OPT("ro", ro, 1), > + FUSE2FS_OPT("errors=panic", panic_on_error, 1), > + FUSE2FS_OPT("minixdf", minixdf, 1), > + FUSE2FS_OPT("fuse2fs_debug", debug, 1), > + FUSE2FS_OPT("no_default_opts", no_default_opts, 1), > + > + FUSE_OPT_KEY("-V", FUSE2FS_VERSION), > + FUSE_OPT_KEY("--version", FUSE2FS_VERSION), > + FUSE_OPT_KEY("-h", FUSE2FS_HELP), > + FUSE_OPT_KEY("--help", FUSE2FS_HELP), > + FUSE_OPT_KEY("--helpfull", FUSE2FS_HELPFULL), > + FUSE_OPT_END > +}; > + > + > +static int fuse2fs_opt_proc(void *data, const char *arg, > + int key, struct fuse_args *outargs) > { > - printf(_("Usage: %s dev mntpt [-o options] [fuse_args]\n"), progname); > + struct fuse2fs *ff = data; > + > + switch (key) { > + case FUSE_OPT_KEY_NONOPT: > + if (!ff->device) { > + ff->device = strdup(arg); > + return 0; > + } > + return 1; > + case FUSE2FS_HELP: > + case FUSE2FS_HELPFULL: > + fprintf(stderr, > + "usage: %s device/image mountpoint [options]\n" > + "\n" > + "general options:\n" > + " -o opt,[opt...] mount options\n" > + " -h --help print help\n" > + " -V --version print version\n" > + "\n" > + "fuse2fs options:\n" > + " -o ro read-only mount\n" > + " -o errors=panic dump core on error\n" > + " -o minixdf minix-style df\n" > + " -o no_default_opts do not include default fuse options\n" > + " -o fuse2fs_debug enable fuse2fs debugging\n" > + "\n", > + outargs->argv[0]); > + if (key == FUSE2FS_HELPFULL) { > + fuse_opt_add_arg(outargs, "-ho"); > + fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL); > + } else { > + fprintf(stderr, "Try --helpfull to get a list of " > + "all flags, including the FUSE options.\n"); > + } > + exit(1); > + > + case FUSE2FS_VERSION: > + fprintf(stderr, "fuse2fs %s (%s)\n", E2FSPROGS_VERSION, > + E2FSPROGS_DATE); > + fuse_opt_add_arg(outargs, "--version"); > + fuse_main(outargs->argc, outargs->argv, &fs_ops, NULL); > + exit(0); > + } > + return 1; > } > > int main(int argc, char *argv[]) > { > + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); > + struct fuse2fs fctx; > errcode_t err; > char *tok, *arg, *logfile; > int i; > - int readwrite = 1, panic_on_error = 0, minixdf = 0; > - struct fuse2fs *ff; > char extra_args[BUFSIZ]; > int ret = 0, flags = EXT2_FLAG_64BITS | EXT2_FLAG_EXCLUSIVE; > > - if (argc < 2) { > - print_help(argv[0]); > - return 1; > - } > + memset(&fctx, 0, sizeof(fctx)); > + fctx.magic = FUSE2FS_MAGIC; > > - for (i = 1; i < argc; i++) { > - if (strcmp(argv[i], "--help") == 0) { > - print_help(argv[0]); > - return 1; > - } > - } > - > - for (i = 1; i < argc - 1; i++) { > - if (strcmp(argv[i], "-o")) > - continue; > - arg = argv[i + 1]; > - while ((tok = strtok(arg, ","))) { > - arg = NULL; > - if (!strcmp(tok, "ro")) > - readwrite = 0; > - else if (!strcmp(tok, "errors=panic")) > - panic_on_error = 1; > - else if (!strcmp(tok, "minixdf")) > - minixdf = 1; > - } > + fuse_opt_parse(&args, &fctx, fuse2fs_opts, fuse2fs_opt_proc); > + if (fctx.device == NULL) { > + fprintf(stderr, "Missing ext4 device/image\n"); > + fprintf(stderr, "See '%s -h' for usage\n", argv[0]); > + exit(1); > } > > - if (!readwrite) > + if (fctx.ro) > printf("%s", _("Mounting read-only.\n")); > > #ifdef ENABLE_NLS > @@ -3678,57 +3735,48 @@ int main(int argc, char *argv[]) > #endif > add_error_table(&et_ext2_error_table); > > - ff = calloc(1, sizeof(*ff)); > - if (!ff) { > - perror("init"); > - return 1; > - } > - ff->magic = FUSE2FS_MAGIC; > - ff->panic_on_error = panic_on_error; > - ff->minixdf = minixdf; > - > /* Set up error logging */ > logfile = getenv("FUSE2FS_LOGFILE"); > if (logfile) { > - ff->err_fp = fopen(logfile, "a"); > - if (!ff->err_fp) { > + fctx.err_fp = fopen(logfile, "a"); > + if (!fctx.err_fp) { > perror(logfile); > goto out_nofs; > } > } else > - ff->err_fp = stderr; > + fctx.err_fp = stderr; > > /* Will we allow users to allocate every last block? */ > if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) { > printf(_("%s: Allowing users to allocate all blocks. " > - "This is dangerous!\n"), argv[1]); > - ff->alloc_all_blocks = 1; > + "This is dangerous!\n"), fctx.device); > + fctx.alloc_all_blocks = 1; > } > > /* Start up the fs (while we still can use stdout) */ > ret = 2; > - if (readwrite) > + if (!fctx.ro) > flags |= EXT2_FLAG_RW; > - err = ext2fs_open2(argv[1], NULL, flags, 0, 0, unix_io_manager, > + err = ext2fs_open2(fctx.device, NULL, flags, 0, 0, unix_io_manager, > &global_fs); > if (err) { > - printf(_("%s: %s.\n"), argv[1], error_message(err)); > - printf(_("Please run e2fsck -fy %s.\n"), argv[1]); > + printf(_("%s: %s.\n"), fctx.device, error_message(err)); > + printf(_("Please run e2fsck -fy %s.\n"), fctx.device); > goto out_nofs; > } > - ff->fs = global_fs; > - global_fs->priv_data = ff; > + fctx.fs = global_fs; > + global_fs->priv_data = &fctx; > > ret = 3; > if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) { > - if (readwrite) { > - printf(_("%s: recovering journal\n"), argv[1]); > + if (!fctx.ro) { > + printf(_("%s: recovering journal\n"), fctx.device); > err = ext2fs_run_ext3_journal(&global_fs); > if (err) { > - printf(_("%s: %s.\n"), argv[1], > + printf(_("%s: %s.\n"), fctx.device, > error_message(err)); > printf(_("Please run e2fsck -fy %s.\n"), > - argv[1]); > + fctx.device); > goto out; > } > ext2fs_clear_feature_journal_needs_recovery(global_fs->super); > @@ -3740,10 +3788,10 @@ int main(int argc, char *argv[]) > } > } > > - if (readwrite) { > + if (!fctx.ro) { > if (ext2fs_has_feature_journal(global_fs->super)) > printf(_("%s: Writing to the journal is not supported.\n"), > - argv[1]); > + fctx.device); > err = ext2fs_read_inode_bitmap(global_fs); > if (err) { > translate_error(global_fs, 0, err); > @@ -3779,19 +3827,27 @@ int main(int argc, char *argv[]) > } > > /* Initialize generation counter */ > - get_random_bytes(&ff->next_generation, sizeof(unsigned int)); > + get_random_bytes(&fctx.next_generation, sizeof(unsigned int)); > > - /* Stuff in some fuse parameters of our own */ > + /* Set up default fuse parameters */ > snprintf(extra_args, BUFSIZ, "-okernel_cache,subtype=ext4,use_ino," > - "fsname=%s,attr_timeout=0,allow_other" FUSE_PLATFORM_OPTS, > + "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS, > argv[1]); > - argv[0] = argv[1]; > - argv[1] = argv[2]; > - argv[2] = extra_args; > + if (fctx.no_default_opts == 0) > + fuse_opt_add_arg(&args, extra_args); > + > + if (fctx.debug) { > + int i; > + > + printf("fuse arguments:"); > + for (i = 0; i < args.argc; i++) > + printf(" '%s'", args.argv[i]); > + printf("\n"); > + } > > - pthread_mutex_init(&ff->bfl, NULL); > - fuse_main(argc, argv, &fs_ops, ff); > - pthread_mutex_destroy(&ff->bfl); > + pthread_mutex_init(&fctx.bfl, NULL); > + fuse_main(args.argc, args.argv, &fs_ops, &fctx); > + pthread_mutex_destroy(&fctx.bfl); > > ret = 0; > out: > @@ -3800,7 +3856,6 @@ out: > com_err(argv[0], err, "while closing fs"); > global_fs = NULL; > out_nofs: > - free(ff); > > return ret; > } > -- > 2.5.0 > -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html