mirror of https://github.com/vitalif/e2fsprogs
fuse2fs: improve command-line parsing
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. Signed-off-by: Theodore Ts'o <tytso@mit.edu>debian
parent
5b7afaf181
commit
69df84967f
187
misc/fuse2fs.c
187
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
pthread_mutex_init(&ff->bfl, NULL);
|
||||
fuse_main(argc, argv, &fs_ops, ff);
|
||||
pthread_mutex_destroy(&ff->bfl);
|
||||
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(&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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue