diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2007-06-20 21:37:58 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2007-06-20 21:37:58 +0000 |
commit | 62c24a8e4b10d77e08ee4a40c6f6b6a8d1eafeab (patch) | |
tree | a94336f70cf1199760a84089c8e83dfe1fe01167 /lib | |
parent | 2b3a22fea0509681d9e86d5131a0008165bbf6ba (diff) |
Add fs subtype support to libfuse and fusermount
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fuse_versionscript | 1 | ||||
-rw-r--r-- | lib/helper.c | 29 | ||||
-rw-r--r-- | lib/mount.c | 101 | ||||
-rw-r--r-- | lib/mount_util.c | 17 | ||||
-rw-r--r-- | lib/mount_util.h | 1 |
5 files changed, 127 insertions, 22 deletions
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index cbce074..6125f20 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -150,6 +150,7 @@ FUSE_2.7 { fuse_fs_utimens; fuse_fs_write; fuse_register_module; + fuse_version; local: *; diff --git a/lib/helper.c b/lib/helper.c index 1de088f..d7cc9b7 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -29,7 +29,7 @@ enum { struct helper_opts { int singlethread; int foreground; - int fsname; + int nodefault_subtype; char *mountpoint; }; @@ -40,7 +40,8 @@ static const struct fuse_opt fuse_helper_opts[] = { FUSE_HELPER_OPT("debug", foreground), FUSE_HELPER_OPT("-f", foreground), FUSE_HELPER_OPT("-s", singlethread), - FUSE_HELPER_OPT("fsname=", fsname), + FUSE_HELPER_OPT("fsname=", nodefault_subtype), + FUSE_HELPER_OPT("subtype=", nodefault_subtype), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -50,6 +51,7 @@ static const struct fuse_opt fuse_helper_opts[] = { FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP), FUSE_OPT_END }; @@ -117,24 +119,24 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key, } } -static int add_default_fsname(const char *progname, struct fuse_args *args) +static int add_default_subtype(const char *progname, struct fuse_args *args) { int res; - char *fsname_opt; + char *subtype_opt; const char *basename = strrchr(progname, '/'); if (basename == NULL) basename = progname; else if (basename[1] != '\0') basename++; - fsname_opt = (char *) malloc(strlen(basename) + 64); - if (fsname_opt == NULL) { + subtype_opt = (char *) malloc(strlen(basename) + 64); + if (subtype_opt == NULL) { fprintf(stderr, "fuse: memory allocation failed\n"); return -1; } - sprintf(fsname_opt, "-ofsname=%s", basename); - res = fuse_opt_add_arg(args, fsname_opt); - free(fsname_opt); + sprintf(subtype_opt, "-osubtype=%s", basename); + res = fuse_opt_add_arg(args, subtype_opt); + free(subtype_opt); return res; } @@ -149,8 +151,8 @@ int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, if (res == -1) return -1; - if (!hopts.fsname) { - res = add_default_fsname(args->argv[0], args); + if (!hopts.nodefault_subtype) { + res = add_default_subtype(args->argv[0], args); if (res == -1) goto err; } @@ -331,6 +333,11 @@ int fuse_main(void) return -1; } +int fuse_version(void) +{ + return FUSE_VERSION; +} + #include "fuse_compat.h" #ifndef __FreeBSD__ diff --git a/lib/mount.c b/lib/mount.c index 24bcf8c..aa0c0cb 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -39,6 +39,7 @@ enum { KEY_KERN_FLAG, KEY_KERN_OPT, KEY_FUSERMOUNT_OPT, + KEY_SUBTYPE_OPT, KEY_MTAB_OPT, KEY_ALLOW_ROOT, KEY_RO, @@ -54,6 +55,8 @@ struct mount_opts { int nonempty; int blkdev; char *fsname; + char *subtype; + char *subtype_opt; char *mtab_opts; char *fusermount_opts; char *kernel_opts; @@ -67,11 +70,13 @@ static const struct fuse_opt fuse_mount_opts[] = { FUSE_MOUNT_OPT("nonempty", nonempty), FUSE_MOUNT_OPT("blkdev", blkdev), FUSE_MOUNT_OPT("fsname=%s", fsname), + FUSE_MOUNT_OPT("subtype=%s", subtype), FUSE_OPT_KEY("allow_other", KEY_KERN_OPT), FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT), FUSE_OPT_KEY("nonempty", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("blkdev", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT), + FUSE_OPT_KEY("subtype=", KEY_SUBTYPE_OPT), FUSE_OPT_KEY("large_read", KEY_KERN_OPT), FUSE_OPT_KEY("blksize=", KEY_KERN_OPT), FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT), @@ -107,6 +112,7 @@ static void mount_help(void) " -o nonempty allow mounts over non-empty file/dir\n" " -o default_permissions enable permission checking by kernel\n" " -o fsname=NAME set filesystem name\n" + " -o subtype=NAME set filesystem type\n" " -o large_read issue large read requests (2.4 only)\n" " -o max_read=N set maximum size of read requests\n" "\n" @@ -196,6 +202,9 @@ static int fuse_mount_opt_proc(void *data, const char *arg, int key, case KEY_FUSERMOUNT_OPT: return fuse_opt_add_opt(&mo->fusermount_opts, arg); + case KEY_SUBTYPE_OPT: + return fuse_opt_add_opt(&mo->subtype_opt, arg); + case KEY_MTAB_OPT: return fuse_opt_add_opt(&mo->mtab_opts, arg); @@ -304,7 +313,8 @@ void fuse_unmount_compat22(const char *mountpoint) fuse_kern_unmount(mountpoint, -1); } -int fuse_mount_compat22(const char *mountpoint, const char *opts) +static int fuse_mount_fusermount(const char *mountpoint, const char *opts, + int quiet) { int fds[2], pid; int res; @@ -334,6 +344,12 @@ int fuse_mount_compat22(const char *mountpoint, const char *opts) const char *argv[32]; int a = 0; + if (quiet) { + int fd = open("/dev/null", O_RDONLY); + dup2(fd, 1); + dup2(fd, 2); + } + argv[a++] = FUSERMOUNT_PROG; if (opts) { argv[a++] = "-o"; @@ -360,13 +376,18 @@ int fuse_mount_compat22(const char *mountpoint, const char *opts) return rv; } +int fuse_mount_compat22(const char *mountpoint, const char *opts) +{ + return fuse_mount_fusermount(mountpoint, opts, 0); +} static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, const char *mnt_opts) { - const char *type = mo->blkdev ? "fuseblk" : "fuse"; char tmp[128]; const char *devname = "/dev/fuse"; + char *source = NULL; + char *type = NULL; struct stat stbuf; int fd; int res; @@ -395,9 +416,6 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, return -1; } - if (mo->fsname) - devname = mo->fsname; - snprintf(tmp, sizeof(tmp), "fd=%i,rootmode=%o,user_id=%i,group_id=%i", fd, stbuf.st_mode & S_IFMT, getuid(), getgid()); @@ -405,16 +423,52 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, if (res == -1) goto out_close; - res = mount(devname, mnt, type, mo->flags, mo->kernel_opts); + source = malloc((mo->fsname ? strlen(mo->fsname) : 0) + + (mo->subtype ? strlen(mo->subtype) : 0) + + strlen(devname) + 32); + + type = malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32); + if (!type || !source) { + fprintf(stderr, "fuse: failed to allocate memory\n"); + goto out_close; + } + + strcpy(type, mo->blkdev ? "fuseblk" : "fuse"); + if (mo->subtype) { + strcat(type, "."); + strcat(type, mo->subtype); + } + strcpy(source, + mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname)); + + res = mount(source, mnt, type, mo->flags, mo->kernel_opts); + if (res == -1 && errno == ENODEV && mo->subtype) { + /* Probably missing subtype support */ + strcpy(type, mo->blkdev ? "fuseblk" : "fuse"); + if (mo->fsname) { + if (!mo->blkdev) + sprintf(source, "%s#%s", mo->subtype, mo->fsname); + } else { + strcpy(source, type); + } + res = mount(source, mnt, type, mo->flags, mo->kernel_opts); + } if (res == -1) { /* * Maybe kernel doesn't support unprivileged mounts, in this * case try falling back to fusermount */ - if (errno == EPERM) + if (errno == EPERM) { res = -2; - else - perror("fuse: mount failed"); + } else { + int errno_save = errno; + if (mo->blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk()) + fprintf(stderr, "fuse: 'fuseblk' support missing\n"); + else + fprintf(stderr, "fuse: mount failed: %s\n", + strerror(errno_save)); + } + goto out_close; } @@ -424,7 +478,7 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, if (!newmnt) goto out_umount; - res = fuse_mnt_add_mount("fuse", devname, newmnt, type, mnt_opts); + res = fuse_mnt_add_mount("fuse", source, newmnt, type, mnt_opts); free(newmnt); if (res == -1) goto out_umount; @@ -435,6 +489,8 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, out_umount: umount2(mnt, 2); /* lazy umount */ out_close: + free(type); + free(source); close(fd); return res; } @@ -460,6 +516,11 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args) int res = -1; char *mnt_opts = NULL; + if (!mountpoint) { + fprintf(stderr, "fuse: missing mountpoint\n"); + return -1; + } + memset(&mo, 0, sizeof(mo)); mo.flags = MS_NOSUID | MS_NODEV; @@ -489,12 +550,30 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args) fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) == -1) goto out; - res = fuse_mount_compat22(mountpoint, mnt_opts); + if (mo.subtype) { + char *tmp_opts = NULL; + + res = -1; + if (fuse_opt_add_opt(&tmp_opts, mnt_opts) == -1 || + fuse_opt_add_opt(&tmp_opts, mo.subtype_opt) == -1) { + free(tmp_opts); + goto out; + } + + res = fuse_mount_fusermount(mountpoint, tmp_opts, 1); + free(tmp_opts); + if (res == -1) + res = fuse_mount_fusermount(mountpoint, mnt_opts, 0); + } else { + res = fuse_mount_fusermount(mountpoint, mnt_opts, 0); + } } out: free(mnt_opts); free(mo.fsname); + free(mo.subtype); free(mo.fusermount_opts); + free(mo.subtype_opt); free(mo.kernel_opts); free(mo.mtab_opts); return res; diff --git a/lib/mount_util.c b/lib/mount_util.c index 02b2731..dccecdf 100644 --- a/lib/mount_util.c +++ b/lib/mount_util.c @@ -193,3 +193,20 @@ int fuse_mnt_check_empty(const char *progname, const char *mnt, } return 0; } + +int fuse_mnt_check_fuseblk(void) +{ + char buf[256]; + FILE *f = fopen("/proc/filesystems", "r"); + if (!f) + return 1; + + while (fgets(buf, sizeof(buf), f)) + if (strstr(buf, "fuseblk\n")) { + fclose(f); + return 1; + } + + fclose(f); + return 0; +} diff --git a/lib/mount_util.h b/lib/mount_util.h index 106a6f8..f9f6cbe 100644 --- a/lib/mount_util.h +++ b/lib/mount_util.h @@ -14,3 +14,4 @@ int fuse_mnt_umount(const char *progname, const char *mnt, int lazy); char *fuse_mnt_resolve_path(const char *progname, const char *orig); int fuse_mnt_check_empty(const char *progname, const char *mnt, mode_t rootmode, off_t rootsize); +int fuse_mnt_check_fuseblk(void); |