Whamcloud - gitweb
fuse2fs: fix fsname option in some cases
[tools/e2fsprogs.git] / misc / fuse2fs.c
index 7d8bb60..3214be4 100644 (file)
@@ -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>
@@ -93,6 +95,10 @@ static ext2_filsys global_fs; /* Try not to use this directly */
 
 errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
 
+#ifdef CONFIG_JBD_DEBUG                /* Enabled by configure --enable-jbd-debug */
+int journal_enable_debug = -1;
+#endif
+
 /* ACL translation stuff */
 #ifdef TRANSLATE_LINUX_ACLS
 /*
@@ -112,7 +118,14 @@ typedef struct {
 
 typedef struct {
        u_int32_t       a_version;
+#if __GNUC_PREREQ (4, 8)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
        acl_ea_entry    a_entries[0];
+#if __GNUC_PREREQ (4, 8)
+#pragma GCC diagnostic pop
+#endif
 } acl_ea_header;
 
 static inline size_t acl_ea_size(int count)
@@ -303,6 +316,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;
@@ -853,8 +870,9 @@ static int op_readlink(const char *path, char *buf, size_t len)
        len--;
        if (inode.i_size < len)
                len = inode.i_size;
-       if (ext2fs_inode_data_blocks2(fs, &inode) ||
-           (inode.i_flags & EXT4_INLINE_DATA_FL)) {
+       if (ext2fs_is_fast_symlink(&inode))
+               memcpy(buf, (char *)inode.i_block, len);
+       else {
                /* big/inline symlink */
 
                err = ext2fs_file_open(fs, ino, 0, &file);
@@ -878,9 +896,7 @@ out2:
                        ret = translate_error(fs, ino, err);
                        goto out;
                }
-       } else
-               /* inline symlink */
-               memcpy(buf, (char *)inode.i_block, len);
+       }
        buf[len] = 0;
 
        if (fs_writeable(fs)) {
@@ -900,7 +916,7 @@ static int op_mknod(const char *path, mode_t mode, dev_t dev)
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
        ext2_filsys fs;
        ext2_ino_t parent, child;
-       char *temp_path = strdup(path);
+       char *temp_path;
        errcode_t err;
        char *node_name, a;
        int filetype;
@@ -911,6 +927,7 @@ static int op_mknod(const char *path, mode_t mode, dev_t dev)
        fs = ff->fs;
        dbg_printf("%s: path=%s mode=0%o dev=0x%x\n", __func__, path, mode,
                   (unsigned int)dev);
+       temp_path = strdup(path);
        if (!temp_path) {
                ret = -ENOMEM;
                goto out;
@@ -994,6 +1011,8 @@ static int op_mknod(const char *path, mode_t mode, dev_t dev)
        inode.i_links_count = 1;
        inode.i_extra_isize = sizeof(struct ext2_inode_large) -
                EXT2_GOOD_OLD_INODE_SIZE;
+       inode.i_uid = ctxt->uid;
+       inode.i_gid = ctxt->gid;
 
        err = ext2fs_write_new_inode(fs, child, (struct ext2_inode *)&inode);
        if (err) {
@@ -1025,7 +1044,7 @@ static int op_mkdir(const char *path, mode_t mode)
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
        ext2_filsys fs;
        ext2_ino_t parent, child;
-       char *temp_path = strdup(path);
+       char *temp_path;
        errcode_t err;
        char *node_name, a;
        struct ext2_inode_large inode;
@@ -1037,6 +1056,7 @@ static int op_mkdir(const char *path, mode_t mode)
        FUSE2FS_CHECK_CONTEXT(ff);
        fs = ff->fs;
        dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
+       temp_path = strdup(path);
        if (!temp_path) {
                ret = -ENOMEM;
                goto out;
@@ -1412,7 +1432,7 @@ static int op_symlink(const char *src, const char *dest)
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
        ext2_filsys fs;
        ext2_ino_t parent, child;
-       char *temp_path = strdup(dest);
+       char *temp_path;
        errcode_t err;
        char *node_name, a;
        struct ext2_inode_large inode;
@@ -1421,6 +1441,7 @@ static int op_symlink(const char *src, const char *dest)
        FUSE2FS_CHECK_CONTEXT(ff);
        fs = ff->fs;
        dbg_printf("%s: symlink %s to %s\n", __func__, src, dest);
+       temp_path = strdup(dest);
        if (!temp_path) {
                ret = -ENOMEM;
                goto out;
@@ -1757,7 +1778,7 @@ static int op_link(const char *src, const char *dest)
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
        ext2_filsys fs;
-       char *temp_path = strdup(dest);
+       char *temp_path;
        errcode_t err;
        char *node_name, a;
        ext2_ino_t parent, ino;
@@ -1767,6 +1788,7 @@ static int op_link(const char *src, const char *dest)
        FUSE2FS_CHECK_CONTEXT(ff);
        fs = ff->fs;
        dbg_printf("%s: src=%s dest=%s\n", __func__, src, dest);
+       temp_path = strdup(dest);
        if (!temp_path) {
                ret = -ENOMEM;
                goto out;
@@ -2113,7 +2135,7 @@ static int __op_open(struct fuse2fs *ff, const char *path,
                } else
                        goto out;
        }
-       fp->fh = (uint64_t)file;
+       fp->fh = (uintptr_t)file;
 
 out:
        if (ret)
@@ -2140,7 +2162,8 @@ static int op_read(const char *path EXT2FS_ATTR((unused)), char *buf,
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        ext2_file_t efp;
        errcode_t err;
@@ -2196,7 +2219,8 @@ static int op_write(const char *path EXT2FS_ATTR((unused)),
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        ext2_file_t efp;
        errcode_t err;
@@ -2267,7 +2291,8 @@ static int op_release(const char *path EXT2FS_ATTR((unused)),
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        errcode_t err;
        int ret = 0;
@@ -2296,7 +2321,8 @@ static int op_fsync(const char *path EXT2FS_ATTR((unused)),
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        errcode_t err;
        int ret = 0;
@@ -2521,7 +2547,7 @@ static int op_listxattr(const char *path, char *names, size_t len)
 
        ret = check_inum_access(fs, ino, R_OK);
        if (ret)
-               goto out2;
+               goto out;
 
        err = ext2fs_xattrs_open(fs, ino, &h);
        if (err) {
@@ -2634,12 +2660,6 @@ static int op_setxattr(const char *path EXT2FS_ATTR((unused)),
                goto out3;
        }
 
-       err = ext2fs_xattrs_write(h);
-       if (err) {
-               ret = translate_error(fs, ino, err);
-               goto out3;
-       }
-
        ret = update_ctime(fs, ino, NULL);
 out3:
        if (cvalue != value)
@@ -2706,12 +2726,6 @@ static int op_removexattr(const char *path, const char *key)
                goto out2;
        }
 
-       err = ext2fs_xattrs_write(h);
-       if (err) {
-               ret = translate_error(fs, ino, err);
-               goto out2;
-       }
-
        ret = update_ctime(fs, ino, NULL);
 out2:
        err = ext2fs_xattrs_close(&h);
@@ -2755,7 +2769,8 @@ static int op_readdir(const char *path EXT2FS_ATTR((unused)),
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        errcode_t err;
        struct readdir_iter i;
@@ -2818,7 +2833,7 @@ static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
        ext2_filsys fs;
        ext2_ino_t parent, child;
-       char *temp_path = strdup(path);
+       char *temp_path;
        errcode_t err;
        char *node_name, a;
        int filetype;
@@ -2828,6 +2843,7 @@ static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
        FUSE2FS_CHECK_CONTEXT(ff);
        fs = ff->fs;
        dbg_printf("%s: path=%s mode=0%o\n", __func__, path, mode);
+       temp_path = strdup(path);
        if (!temp_path) {
                ret = -ENOMEM;
                goto out;
@@ -2895,6 +2911,8 @@ static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
        inode.i_links_count = 1;
        inode.i_extra_isize = sizeof(struct ext2_inode_large) -
                EXT2_GOOD_OLD_INODE_SIZE;
+       inode.i_uid = ctxt->uid;
+       inode.i_gid = ctxt->gid;
        if (ext2fs_has_feature_extents(fs->super)) {
                ext2_extent_handle_t handle;
 
@@ -2938,7 +2956,8 @@ static int op_ftruncate(const char *path EXT2FS_ATTR((unused)),
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        ext2_file_t efp;
        errcode_t err;
@@ -2991,7 +3010,8 @@ static int op_fgetattr(const char *path EXT2FS_ATTR((unused)),
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
        ext2_filsys fs;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        int ret = 0;
 
        FUSE2FS_CHECK_CONTEXT(ff);
@@ -3244,7 +3264,8 @@ static int op_ioctl(const char *path EXT2FS_ATTR((unused)), int cmd,
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        int ret = 0;
 
@@ -3319,7 +3340,8 @@ static int fallocate_helper(struct fuse_file_info *fp, int mode, off_t offset,
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        struct ext2_inode_large inode;
        blk64_t start, end;
@@ -3454,7 +3476,8 @@ static int punch_helper(struct fuse_file_info *fp, int mode, off_t offset,
 {
        struct fuse_context *ctxt = fuse_get_context();
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
-       struct fuse2fs_file_handle *fh = (struct fuse2fs_file_handle *)fp->fh;
+       struct fuse2fs_file_handle *fh =
+               (struct fuse2fs_file_handle *)(uintptr_t)fp->fh;
        ext2_filsys fs;
        struct ext2_inode_large inode;
        blk64_t start, end;
@@ -3620,49 +3643,99 @@ 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 *logfile;
        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;
-               }
+       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 - 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
@@ -3674,57 +3747,49 @@ 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;
+                       goto out;
                }
        } 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]);
-               goto out_nofs;
+               printf(_("%s: %s.\n"), fctx.device, error_message(err));
+               printf(_("Please run e2fsck -fy %s.\n"), fctx.device);
+               goto out;
        }
-       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);
@@ -3736,10 +3801,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);
@@ -3760,8 +3825,8 @@ int main(int argc, char *argv[])
                printf("%s", _("Warning: Maximal mount count reached, running "
                       "e2fsck is recommended.\n"));
        if (global_fs->super->s_checkinterval > 0 &&
-           global_fs->super->s_lastcheck +
-           global_fs->super->s_checkinterval <= time(0))
+           (time_t) (global_fs->super->s_lastcheck +
+                     global_fs->super->s_checkinterval) <= time(0))
                printf("%s", _("Warning: Check time reached; running e2fsck "
                       "is recommended.\n"));
        if (global_fs->super->s_last_orphan)
@@ -3775,29 +3840,36 @@ 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,
-                argv[1]);
-       argv[0] = argv[1];
-       argv[1] = argv[2];
-       argv[2] = extra_args;
+                "fsname=%s,attr_timeout=0" FUSE_PLATFORM_OPTS,
+                fctx.device);
+       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:
-       err = ext2fs_close(global_fs);
-       if (err)
-               com_err(argv[0], err, "while closing fs");
-       global_fs = NULL;
-out_nofs:
-       free(ff);
-
+       if (global_fs) {
+               err = ext2fs_close(global_fs);
+               if (err)
+                       com_err(argv[0], err, "while closing fs");
+               global_fs = NULL;
+       }
        return ret;
 }
 
@@ -3829,6 +3901,7 @@ static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
                break;
        case EXT2_ET_DIR_NO_SPACE:
                is_err = 1;
+               /* fallthrough */
        case EXT2_ET_TOOSMALL:
        case EXT2_ET_BLOCK_ALLOC_FAIL:
        case EXT2_ET_INODE_ALLOC_FAIL:
@@ -3875,11 +3948,11 @@ no_translation:
 
        if (ino)
                fprintf(ff->err_fp, "FUSE2FS (%s): %s (inode #%d) at %s:%d.\n",
-                       fs && fs->device_name ? fs->device_name : "???",
+                       fs->device_name ? fs->device_name : "???",
                        error_message(err), ino, file, line);
        else
                fprintf(ff->err_fp, "FUSE2FS (%s): %s at %s:%d.\n",
-                       fs && fs->device_name ? fs->device_name : "???",
+                       fs->device_name ? fs->device_name : "???",
                        error_message(err), file, line);
        fflush(ff->err_fp);