diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2007-12-12 14:25:40 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2007-12-12 14:25:40 +0000 |
commit | cdb8b79bad5fea81b74931a9027f1d5ca344af8e (patch) | |
tree | 11ab550f265dc3eb546b7c26f3745e6d139b1fcc /util/fusermount.c | |
parent | 918f0ad95b73e506d20488cb8ddd35d1a2524c7c (diff) |
change indenting
Diffstat (limited to 'util/fusermount.c')
-rw-r--r-- | util/fusermount.c | 1533 |
1 files changed, 781 insertions, 752 deletions
diff --git a/util/fusermount.c b/util/fusermount.c index 716caff..e3c98c5 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -1,9 +1,9 @@ /* - FUSE: Filesystem in Userspace - Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> - This program can be distributed under the terms of the GNU GPL. - See the file COPYING. + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. */ /* This program does the mounting and unmounting of FUSE filesystems */ @@ -27,7 +27,7 @@ #include <sys/socket.h> #include <sys/utsname.h> -#define FUSE_COMMFD_ENV "_FUSE_COMMFD" +#define FUSE_COMMFD_ENV "_FUSE_COMMFD" #define FUSE_DEV_OLD "/proc/fs/fuse/dev" #define FUSE_DEV_NEW "/dev/fuse" @@ -45,13 +45,13 @@ static int mount_max = 1000; static const char *get_user_name(void) { - struct passwd *pw = getpwuid(getuid()); - if (pw != NULL && pw->pw_name != NULL) - return pw->pw_name; - else { - fprintf(stderr, "%s: could not determine username\n", progname); - return NULL; - } + struct passwd *pw = getpwuid(getuid()); + if (pw != NULL && pw->pw_name != NULL) + return pw->pw_name; + else { + fprintf(stderr, "%s: could not determine username\n", progname); + return NULL; + } } static uid_t oldfsuid; @@ -59,868 +59,897 @@ static gid_t oldfsgid; static void drop_privs(void) { - if (getuid() != 0) { - oldfsuid = setfsuid(getuid()); - oldfsgid = setfsgid(getgid()); - } + if (getuid() != 0) { + oldfsuid = setfsuid(getuid()); + oldfsgid = setfsgid(getgid()); + } } static void restore_privs(void) { - if (getuid() != 0) { - setfsuid(oldfsuid); - setfsgid(oldfsgid); - } + if (getuid() != 0) { + setfsuid(oldfsuid); + setfsgid(oldfsgid); + } } #ifndef IGNORE_MTAB static int add_mount(const char *source, const char *mnt, const char *type, - const char *opts) + const char *opts) { - return fuse_mnt_add_mount(progname, source, mnt, type, opts); + return fuse_mnt_add_mount(progname, source, mnt, type, opts); } static int unmount_fuse(const char *mnt, int quiet, int lazy) { - if (getuid() != 0) { - struct mntent *entp; - FILE *fp; - const char *user = NULL; - char uidstr[32]; - unsigned uidlen = 0; - int found; - const char *mtab = _PATH_MOUNTED; - - user = get_user_name(); - if (user == NULL) - return -1; - - fp = setmntent(mtab, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab, - strerror(errno)); - return -1; - } - - uidlen = sprintf(uidstr, "%u", getuid()); - - found = 0; - while ((entp = getmntent(fp)) != NULL) { - if (!found && strcmp(entp->mnt_dir, mnt) == 0 && - (strcmp(entp->mnt_type, "fuse") == 0 || - strcmp(entp->mnt_type, "fuseblk") == 0 || - strncmp(entp->mnt_type, "fuse.", 5) == 0 || - strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) { - char *p = strstr(entp->mnt_opts, "user="); - if (p && (p == entp->mnt_opts || *(p-1) == ',') && - strcmp(p + 5, user) == 0) { - found = 1; - break; - } - /* /etc/mtab is a link pointing to /proc/mounts: */ - else if ((p = strstr(entp->mnt_opts, "user_id=")) && - (p == entp->mnt_opts || *(p-1) == ',') && - strncmp(p + 8, uidstr, uidlen) == 0 && - (*(p+8+uidlen) == ',' || *(p+8+uidlen) == '\0')) { - found = 1; - break; - } - } - } - endmntent(fp); - - if (!found) { - if (!quiet) - fprintf(stderr, "%s: entry for %s not found in %s\n", progname, - mnt, mtab); - return -1; - } - } - - return fuse_mnt_umount(progname, mnt, lazy); + if (getuid() != 0) { + struct mntent *entp; + FILE *fp; + const char *user = NULL; + char uidstr[32]; + unsigned uidlen = 0; + int found; + const char *mtab = _PATH_MOUNTED; + + user = get_user_name(); + if (user == NULL) + return -1; + + fp = setmntent(mtab, "r"); + if (fp == NULL) { + fprintf(stderr, + "%s: failed to open %s: %s\n", progname, mtab, + strerror(errno)); + return -1; + } + + uidlen = sprintf(uidstr, "%u", getuid()); + + found = 0; + while ((entp = getmntent(fp)) != NULL) { + if (!found && strcmp(entp->mnt_dir, mnt) == 0 && + (strcmp(entp->mnt_type, "fuse") == 0 || + strcmp(entp->mnt_type, "fuseblk") == 0 || + strncmp(entp->mnt_type, "fuse.", 5) == 0 || + strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) { + char *p = strstr(entp->mnt_opts, "user="); + if (p && + (p == entp->mnt_opts || *(p-1) == ',') && + strcmp(p + 5, user) == 0) { + found = 1; + break; + } + /* /etc/mtab is a link pointing to + /proc/mounts: */ + else if ((p = + strstr(entp->mnt_opts, "user_id=")) && + (p == entp->mnt_opts || + *(p-1) == ',') && + strncmp(p + 8, uidstr, uidlen) == 0 && + (*(p+8+uidlen) == ',' || + *(p+8+uidlen) == '\0')) { + found = 1; + break; + } + } + } + endmntent(fp); + + if (!found) { + if (!quiet) + fprintf(stderr, + "%s: entry for %s not found in %s\n", + progname, mnt, mtab); + return -1; + } + } + + return fuse_mnt_umount(progname, mnt, lazy); } static int count_fuse_fs(void) { - struct mntent *entp; - int count = 0; - const char *mtab = _PATH_MOUNTED; - FILE *fp = setmntent(mtab, "r"); - if (fp == NULL) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab, - strerror(errno)); - return -1; - } - while ((entp = getmntent(fp)) != NULL) { - if (strcmp(entp->mnt_type, "fuse") == 0 || - strncmp(entp->mnt_type, "fuse.", 5) == 0) - count ++; - } - endmntent(fp); - return count; + struct mntent *entp; + int count = 0; + const char *mtab = _PATH_MOUNTED; + FILE *fp = setmntent(mtab, "r"); + if (fp == NULL) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab, + strerror(errno)); + return -1; + } + while ((entp = getmntent(fp)) != NULL) { + if (strcmp(entp->mnt_type, "fuse") == 0 || + strncmp(entp->mnt_type, "fuse.", 5) == 0) + count ++; + } + endmntent(fp); + return count; } #else /* IGNORE_MTAB */ static int count_fuse_fs() { - return 0; + return 0; } static int add_mount(const char *source, const char *mnt, const char *type, - const char *opts) + const char *opts) { - (void) source; - (void) mnt; - (void) type; - (void) opts; - return 0; + (void) source; + (void) mnt; + (void) type; + (void) opts; + return 0; } static int unmount_fuse(const char *mnt, int quiet, int lazy) { - return fuse_mnt_umount(progname, mnt, lazy); + return fuse_mnt_umount(progname, mnt, lazy); } #endif /* IGNORE_MTAB */ static void strip_line(char *line) { - char *s = strchr(line, '#'); - if (s != NULL) - s[0] = '\0'; - for (s = line + strlen(line) - 1; s >= line && isspace((unsigned char) *s); s--); - s[1] = '\0'; - for (s = line; isspace((unsigned char) *s); s++); - if (s != line) - memmove(line, s, strlen(s)+1); + char *s = strchr(line, '#'); + if (s != NULL) + s[0] = '\0'; + for (s = line + strlen(line) - 1; + s >= line && isspace((unsigned char) *s); s--); + s[1] = '\0'; + for (s = line; isspace((unsigned char) *s); s++); + if (s != line) + memmove(line, s, strlen(s)+1); } static void parse_line(char *line, int linenum) { - int tmp; - if (strcmp(line, "user_allow_other") == 0) - user_allow_other = 1; - else if (sscanf(line, "mount_max = %i", &tmp) == 1) - mount_max = tmp; - else if(line[0]) - fprintf(stderr, "%s: unknown parameter in %s at line %i: '%s'\n", - progname, FUSE_CONF, linenum, line); + int tmp; + if (strcmp(line, "user_allow_other") == 0) + user_allow_other = 1; + else if (sscanf(line, "mount_max = %i", &tmp) == 1) + mount_max = tmp; + else if(line[0]) + fprintf(stderr, + "%s: unknown parameter in %s at line %i: '%s'\n", + progname, FUSE_CONF, linenum, line); } static void read_conf(void) { - FILE *fp = fopen(FUSE_CONF, "r"); - if (fp != NULL) { - int linenum = 1; - char line[256]; - int isnewline = 1; - while (fgets(line, sizeof(line), fp) != NULL) { - if (isnewline) { - if (line[strlen(line)-1] == '\n') { - strip_line(line); - parse_line(line, linenum); - } else { - fprintf(stderr, "%s: reading %s: line %i too long\n", - progname, FUSE_CONF, linenum); - isnewline = 0; - } - } else if(line[strlen(line)-1] == '\n') - isnewline = 1; - if (isnewline) - linenum ++; - } - fclose(fp); - } else if (errno != ENOENT) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, FUSE_CONF, - strerror(errno)); - } + FILE *fp = fopen(FUSE_CONF, "r"); + if (fp != NULL) { + int linenum = 1; + char line[256]; + int isnewline = 1; + while (fgets(line, sizeof(line), fp) != NULL) { + if (isnewline) { + if (line[strlen(line)-1] == '\n') { + strip_line(line); + parse_line(line, linenum); + } else { + fprintf(stderr, "%s: reading %s: line %i too long\n", + progname, FUSE_CONF, linenum); + isnewline = 0; + } + } else if(line[strlen(line)-1] == '\n') + isnewline = 1; + if (isnewline) + linenum ++; + } + fclose(fp); + } else if (errno != ENOENT) { + fprintf(stderr, "%s: failed to open %s: %s\n", + progname, FUSE_CONF, strerror(errno)); + } } static int begins_with(const char *s, const char *beg) { - if (strncmp(s, beg, strlen(beg)) == 0) - return 1; - else - return 0; + if (strncmp(s, beg, strlen(beg)) == 0) + return 1; + else + return 0; } struct mount_flags { - const char *opt; - unsigned long flag; - int on; - int safe; + const char *opt; + unsigned long flag; + int on; + int safe; }; static struct mount_flags mount_flags[] = { - {"rw", MS_RDONLY, 0, 1}, - {"ro", MS_RDONLY, 1, 1}, - {"suid", MS_NOSUID, 0, 0}, - {"nosuid", MS_NOSUID, 1, 1}, - {"dev", MS_NODEV, 0, 0}, - {"nodev", MS_NODEV, 1, 1}, - {"exec", MS_NOEXEC, 0, 1}, - {"noexec", MS_NOEXEC, 1, 1}, - {"async", MS_SYNCHRONOUS, 0, 1}, - {"sync", MS_SYNCHRONOUS, 1, 1}, - {"atime", MS_NOATIME, 0, 1}, - {"noatime", MS_NOATIME, 1, 1}, - {"dirsync", MS_DIRSYNC, 1, 1}, - {NULL, 0, 0, 0} + {"rw", MS_RDONLY, 0, 1}, + {"ro", MS_RDONLY, 1, 1}, + {"suid", MS_NOSUID, 0, 0}, + {"nosuid", MS_NOSUID, 1, 1}, + {"dev", MS_NODEV, 0, 0}, + {"nodev", MS_NODEV, 1, 1}, + {"exec", MS_NOEXEC, 0, 1}, + {"noexec", MS_NOEXEC, 1, 1}, + {"async", MS_SYNCHRONOUS, 0, 1}, + {"sync", MS_SYNCHRONOUS, 1, 1}, + {"atime", MS_NOATIME, 0, 1}, + {"noatime", MS_NOATIME, 1, 1}, + {"dirsync", MS_DIRSYNC, 1, 1}, + {NULL, 0, 0, 0} }; static int find_mount_flag(const char *s, unsigned len, int *on, int *flag) { - int i; - - for (i = 0; mount_flags[i].opt != NULL; i++) { - const char *opt = mount_flags[i].opt; - if (strlen(opt) == len && strncmp(opt, s, len) == 0) { - *on = mount_flags[i].on; - *flag = mount_flags[i].flag; - if (!mount_flags[i].safe && getuid() != 0) { - *flag = 0; - fprintf(stderr, "%s: unsafe option %s ignored\n", - progname, opt); - } - return 1; - } - } - return 0; + int i; + + for (i = 0; mount_flags[i].opt != NULL; i++) { + const char *opt = mount_flags[i].opt; + if (strlen(opt) == len && strncmp(opt, s, len) == 0) { + *on = mount_flags[i].on; + *flag = mount_flags[i].flag; + if (!mount_flags[i].safe && getuid() != 0) { + *flag = 0; + fprintf(stderr, + "%s: unsafe option %s ignored\n", + progname, opt); + } + return 1; + } + } + return 0; } static int add_option(char **optsp, const char *opt, unsigned expand) { - char *newopts; - if (*optsp == NULL) - newopts = strdup(opt); - else { - unsigned oldsize = strlen(*optsp); - unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1; - newopts = (char *) realloc(*optsp, newsize); - if (newopts) - sprintf(newopts + oldsize, ",%s", opt); - } - if (newopts == NULL) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - return -1; - } - *optsp = newopts; - return 0; + char *newopts; + if (*optsp == NULL) + newopts = strdup(opt); + else { + unsigned oldsize = strlen(*optsp); + unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1; + newopts = (char *) realloc(*optsp, newsize); + if (newopts) + sprintf(newopts + oldsize, ",%s", opt); + } + if (newopts == NULL) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return -1; + } + *optsp = newopts; + return 0; } static int get_mnt_opts(int flags, char *opts, char **mnt_optsp) { - int i; - int l; - - if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1) - return -1; - - for (i = 0; mount_flags[i].opt != NULL; i++) { - if (mount_flags[i].on && (flags & mount_flags[i].flag) && - add_option(mnt_optsp, mount_flags[i].opt, 0) == -1) - return -1; - } - - if (add_option(mnt_optsp, opts, 0) == -1) - return -1; - /* remove comma from end of opts*/ - l = strlen(*mnt_optsp); - if ((*mnt_optsp)[l-1] == ',') - (*mnt_optsp)[l-1] = '\0'; - if (getuid() != 0) { - const char *user = get_user_name(); - if (user == NULL) - return -1; - - if (add_option(mnt_optsp, "user=", strlen(user)) == -1) - return -1; - strcat(*mnt_optsp, user); - } - return 0; + int i; + int l; + + if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1) + return -1; + + for (i = 0; mount_flags[i].opt != NULL; i++) { + if (mount_flags[i].on && (flags & mount_flags[i].flag) && + add_option(mnt_optsp, mount_flags[i].opt, 0) == -1) + return -1; + } + + if (add_option(mnt_optsp, opts, 0) == -1) + return -1; + /* remove comma from end of opts*/ + l = strlen(*mnt_optsp); + if ((*mnt_optsp)[l-1] == ',') + (*mnt_optsp)[l-1] = '\0'; + if (getuid() != 0) { + const char *user = get_user_name(); + if (user == NULL) + return -1; + + if (add_option(mnt_optsp, "user=", strlen(user)) == -1) + return -1; + strcat(*mnt_optsp, user); + } + return 0; } static int opt_eq(const char *s, unsigned len, const char *opt) { - if(strlen(opt) == len && strncmp(s, opt, len) == 0) - return 1; - else - return 0; + if(strlen(opt) == len && strncmp(s, opt, len) == 0) + return 1; + else + return 0; } static int get_string_opt(const char *s, unsigned len, const char *opt, - char **val) + char **val) { - unsigned opt_len = strlen(opt); - - if (*val) - free(*val); - *val = (char *) malloc(len - opt_len + 1); - if (!*val) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - return 0; - } - - memcpy(*val, s + opt_len, len - opt_len); - (*val)[len - opt_len] = '\0'; - return 1; + unsigned opt_len = strlen(opt); + + if (*val) + free(*val); + *val = (char *) malloc(len - opt_len + 1); + if (!*val) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return 0; + } + + memcpy(*val, s + opt_len, len - opt_len); + (*val)[len - opt_len] = '\0'; + return 1; } static int do_mount(const char *mnt, char **typep, mode_t rootmode, - int fd, const char *opts, const char *dev, char **sourcep, - char **mnt_optsp, off_t rootsize) + int fd, const char *opts, const char *dev, char **sourcep, + char **mnt_optsp, off_t rootsize) { - int res; - int flags = MS_NOSUID | MS_NODEV; - char *optbuf; - char *mnt_opts = NULL; - const char *s; - char *d; - char *fsname = NULL; - char *subtype = NULL; - char *source = NULL; - char *type = NULL; - int check_empty = 1; - int blkdev = 0; - - optbuf = (char *) malloc(strlen(opts) + 128); - if (!optbuf) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - return -1; - } - - for (s = opts, d = optbuf; *s;) { - unsigned len; - const char *fsname_str = "fsname="; - const char *subtype_str = "subtype="; - for (len = 0; s[len] && s[len] != ','; len++); - if (begins_with(s, fsname_str)) { - if (!get_string_opt(s, len, fsname_str, &fsname)) - goto err; - } else if (begins_with(s, subtype_str)) { - if (!get_string_opt(s, len, subtype_str, &subtype)) - goto err; - } else if (opt_eq(s, len, "blkdev")) { - if (getuid() != 0) { - fprintf(stderr, "%s: option blkdev is privileged\n", progname); - goto err; - } - blkdev = 1; - } else if (opt_eq(s, len, "nonempty")) { - check_empty = 0; - } else if (!begins_with(s, "fd=") && - !begins_with(s, "rootmode=") && - !begins_with(s, "user_id=") && - !begins_with(s, "group_id=")) { - int on; - int flag; - int skip_option = 0; - if (opt_eq(s, len, "large_read")) { - struct utsname utsname; - unsigned kmaj, kmin; - res = uname(&utsname); - if (res == 0 && - sscanf(utsname.release, "%u.%u", &kmaj, &kmin) == 2 && - (kmaj > 2 || (kmaj == 2 && kmin > 4))) { - fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin); - skip_option = 1; - } - } - if (getuid() != 0 && !user_allow_other && - (opt_eq(s, len, "allow_other") || - opt_eq(s, len, "allow_root"))) { - fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in /etc/fuse.conf\n", progname, len, s); - goto err; - } - if (!skip_option) { - if (find_mount_flag(s, len, &on, &flag)) { - if (on) - flags |= flag; - else - flags &= ~flag; - } else { - memcpy(d, s, len); - d += len; - *d++ = ','; - } - } - } - s += len; - if (*s) - s++; - } - *d = '\0'; - res = get_mnt_opts(flags, optbuf, &mnt_opts); - if (res == -1) - goto err; - - sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i", - fd, rootmode, getuid(), getgid()); - - if (check_empty && - fuse_mnt_check_empty(progname, mnt, rootmode, rootsize) == -1) - goto err; - - source = malloc((fsname ? strlen(fsname) : 0) + - (subtype ? strlen(subtype) : 0) + strlen(dev) + 32); - - type = malloc((subtype ? strlen(subtype) : 0) + 32); - if (!type || !source) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - goto err; - } - - if (subtype) - sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype); - else - strcpy(type, blkdev ? "fuseblk" : "fuse"); - - if (fsname) - strcpy(source, fsname); - else - strcpy(source, subtype ? subtype : dev); - - res = mount(source, mnt, type, flags, optbuf); - if (res == -1 && errno == ENODEV && subtype) { - /* Probably missing subtype support */ - strcpy(type, blkdev ? "fuseblk" : "fuse"); - if (fsname) { - if (!blkdev) - sprintf(source, "%s#%s", subtype, fsname); - } else { - strcpy(source, type); - } - - res = mount(source, mnt, type, flags, optbuf); - } - if (res == -1 && errno == EINVAL) { - /* It could be an old version not supporting group_id */ - sprintf(d, "fd=%i,rootmode=%o,user_id=%i", fd, rootmode, getuid()); - res = mount(source, mnt, type, flags, optbuf); - } - if (res == -1) { - int errno_save = errno; - if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk()) - fprintf(stderr, "%s: 'fuseblk' support missing\n", progname); - else - fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save)); - goto err; - } else { - *sourcep = source; - *typep = type; - *mnt_optsp = mnt_opts; - } - free(optbuf); - - return res; - - err: - free(fsname); - free(subtype); - free(source); - free(type); - free(mnt_opts); - free(optbuf); - return -1; + int res; + int flags = MS_NOSUID | MS_NODEV; + char *optbuf; + char *mnt_opts = NULL; + const char *s; + char *d; + char *fsname = NULL; + char *subtype = NULL; + char *source = NULL; + char *type = NULL; + int check_empty = 1; + int blkdev = 0; + + optbuf = (char *) malloc(strlen(opts) + 128); + if (!optbuf) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return -1; + } + + for (s = opts, d = optbuf; *s;) { + unsigned len; + const char *fsname_str = "fsname="; + const char *subtype_str = "subtype="; + for (len = 0; s[len] && s[len] != ','; len++); + if (begins_with(s, fsname_str)) { + if (!get_string_opt(s, len, fsname_str, &fsname)) + goto err; + } else if (begins_with(s, subtype_str)) { + if (!get_string_opt(s, len, subtype_str, &subtype)) + goto err; + } else if (opt_eq(s, len, "blkdev")) { + if (getuid() != 0) { + fprintf(stderr, + "%s: option blkdev is privileged\n", + progname); + goto err; + } + blkdev = 1; + } else if (opt_eq(s, len, "nonempty")) { + check_empty = 0; + } else if (!begins_with(s, "fd=") && + !begins_with(s, "rootmode=") && + !begins_with(s, "user_id=") && + !begins_with(s, "group_id=")) { + int on; + int flag; + int skip_option = 0; + if (opt_eq(s, len, "large_read")) { + struct utsname utsname; + unsigned kmaj, kmin; + res = uname(&utsname); + if (res == 0 && + sscanf(utsname.release, "%u.%u", + &kmaj, &kmin) == 2 && + (kmaj > 2 || (kmaj == 2 && kmin > 4))) { + fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin); + skip_option = 1; + } + } + if (getuid() != 0 && !user_allow_other && + (opt_eq(s, len, "allow_other") || + opt_eq(s, len, "allow_root"))) { + fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in /etc/fuse.conf\n", progname, len, s); + goto err; + } + if (!skip_option) { + if (find_mount_flag(s, len, &on, &flag)) { + if (on) + flags |= flag; + else + flags &= ~flag; + } else { + memcpy(d, s, len); + d += len; + *d++ = ','; + } + } + } + s += len; + if (*s) + s++; + } + *d = '\0'; + res = get_mnt_opts(flags, optbuf, &mnt_opts); + if (res == -1) + goto err; + + sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i", + fd, rootmode, getuid(), getgid()); + + if (check_empty && + fuse_mnt_check_empty(progname, mnt, rootmode, rootsize) == -1) + goto err; + + source = malloc((fsname ? strlen(fsname) : 0) + + (subtype ? strlen(subtype) : 0) + strlen(dev) + 32); + + type = malloc((subtype ? strlen(subtype) : 0) + 32); + if (!type || !source) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + goto err; + } + + if (subtype) + sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype); + else + strcpy(type, blkdev ? "fuseblk" : "fuse"); + + if (fsname) + strcpy(source, fsname); + else + strcpy(source, subtype ? subtype : dev); + + res = mount(source, mnt, type, flags, optbuf); + if (res == -1 && errno == ENODEV && subtype) { + /* Probably missing subtype support */ + strcpy(type, blkdev ? "fuseblk" : "fuse"); + if (fsname) { + if (!blkdev) + sprintf(source, "%s#%s", subtype, fsname); + } else { + strcpy(source, type); + } + + res = mount(source, mnt, type, flags, optbuf); + } + if (res == -1 && errno == EINVAL) { + /* It could be an old version not supporting group_id */ + sprintf(d, "fd=%i,rootmode=%o,user_id=%i", + fd, rootmode, getuid()); + res = mount(source, mnt, type, flags, optbuf); + } + if (res == -1) { + int errno_save = errno; + if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk()) + fprintf(stderr, "%s: 'fuseblk' support missing\n", + progname); + else + fprintf(stderr, "%s: mount failed: %s\n", progname, + strerror(errno_save)); + goto err; + } else { + *sourcep = source; + *typep = type; + *mnt_optsp = mnt_opts; + } + free(optbuf); + + return res; + +err: + free(fsname); + free(subtype); + free(source); + free(type); + free(mnt_opts); + free(optbuf); + return -1; } static int check_version(const char *dev) { - int res; - int majorver; - int minorver; - const char *version_file; - FILE *vf; - - if (strcmp(dev, FUSE_DEV_OLD) != 0) - return 0; - - version_file = FUSE_VERSION_FILE_OLD; - vf = fopen(version_file, "r"); - if (vf == NULL) { - fprintf(stderr, "%s: kernel interface too old\n", progname); - return -1; - } - res = fscanf(vf, "%i.%i", &majorver, &minorver); - fclose(vf); - if (res != 2) { - fprintf(stderr, "%s: error reading %s\n", progname, version_file); - return -1; - } - if (majorver < 3) { - fprintf(stderr, "%s: kernel interface too old\n", progname); - return -1; - } - return 0; + int res; + int majorver; + int minorver; + const char *version_file; + FILE *vf; + + if (strcmp(dev, FUSE_DEV_OLD) != 0) + return 0; + + version_file = FUSE_VERSION_FILE_OLD; + vf = fopen(version_file, "r"); + if (vf == NULL) { + fprintf(stderr, "%s: kernel interface too old\n", progname); + return -1; + } + res = fscanf(vf, "%i.%i", &majorver, &minorver); + fclose(vf); + if (res != 2) { + fprintf(stderr, "%s: error reading %s\n", progname, + version_file); + return -1; + } + if (majorver < 3) { + fprintf(stderr, "%s: kernel interface too old\n", progname); + return -1; + } + return 0; } static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd, - int *mountpoint_fd) + int *mountpoint_fd) { - int res; - const char *mnt = *mntp; - const char *origmnt = mnt; - - res = lstat(mnt, stbuf); - if (res == -1) { - fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", - progname, mnt, strerror(errno)); - return -1; - } - - /* No permission checking is done for root */ - if (getuid() == 0) - return 0; - - if (S_ISDIR(stbuf->st_mode)) { - *currdir_fd = open(".", O_RDONLY); - if (*currdir_fd == -1) { - fprintf(stderr, "%s: failed to open current directory: %s\n", - progname, strerror(errno)); - return -1; - } - res = chdir(mnt); - if (res == -1) { - fprintf(stderr, "%s: failed to chdir to mountpoint: %s\n", - progname, strerror(errno)); - return -1; - } - mnt = *mntp = "."; - res = lstat(mnt, stbuf); - if (res == -1) { - fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", - progname, origmnt, strerror(errno)); - return -1; - } - - if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) { - fprintf(stderr, "%s: mountpoint %s not owned by user\n", - progname, origmnt); - return -1; - } - - res = access(mnt, W_OK); - if (res == -1) { - fprintf(stderr, "%s: user has no write access to mountpoint %s\n", - progname, origmnt); - return -1; - } - } else if (S_ISREG(stbuf->st_mode)) { - static char procfile[256]; - *mountpoint_fd = open(mnt, O_WRONLY); - if (*mountpoint_fd == -1) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, mnt, - strerror(errno)); - return -1; - } - res = fstat(*mountpoint_fd, stbuf); - if (res == -1) { - fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", - progname, mnt, strerror(errno)); - return -1; - } - if (!S_ISREG(stbuf->st_mode)) { - fprintf(stderr, "%s: mountpoint %s is no longer a regular file\n", - progname, mnt); - return -1; - } - - sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd); - *mntp = procfile; - } else { - fprintf(stderr, - "%s: mountpoint %s is not a directory or a regular file\n", - progname, mnt); - return -1; - } - - - return 0; + int res; + const char *mnt = *mntp; + const char *origmnt = mnt; + + res = lstat(mnt, stbuf); + if (res == -1) { + fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", + progname, mnt, strerror(errno)); + return -1; + } + + /* No permission checking is done for root */ + if (getuid() == 0) + return 0; + + if (S_ISDIR(stbuf->st_mode)) { + *currdir_fd = open(".", O_RDONLY); + if (*currdir_fd == -1) { + fprintf(stderr, + "%s: failed to open current directory: %s\n", + progname, strerror(errno)); + return -1; + } + res = chdir(mnt); + if (res == -1) { + fprintf(stderr, + "%s: failed to chdir to mountpoint: %s\n", + progname, strerror(errno)); + return -1; + } + mnt = *mntp = "."; + res = lstat(mnt, stbuf); + if (res == -1) { + fprintf(stderr, + "%s: failed to access mountpoint %s: %s\n", + progname, origmnt, strerror(errno)); + return -1; + } + + if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) { + fprintf(stderr, "%s: mountpoint %s not owned by user\n", + progname, origmnt); + return -1; + } + + res = access(mnt, W_OK); + if (res == -1) { + fprintf(stderr, "%s: user has no write access to mountpoint %s\n", + progname, origmnt); + return -1; + } + } else if (S_ISREG(stbuf->st_mode)) { + static char procfile[256]; + *mountpoint_fd = open(mnt, O_WRONLY); + if (*mountpoint_fd == -1) { + fprintf(stderr, "%s: failed to open %s: %s\n", + progname, mnt, strerror(errno)); + return -1; + } + res = fstat(*mountpoint_fd, stbuf); + if (res == -1) { + fprintf(stderr, + "%s: failed to access mountpoint %s: %s\n", + progname, mnt, strerror(errno)); + return -1; + } + if (!S_ISREG(stbuf->st_mode)) { + fprintf(stderr, + "%s: mountpoint %s is no longer a regular file\n", + progname, mnt); + return -1; + } + + sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd); + *mntp = procfile; + } else { + fprintf(stderr, + "%s: mountpoint %s is not a directory or a regular file\n", + progname, mnt); + return -1; + } + + + return 0; } static int try_open(const char *dev, char **devp, int silent) { - int fd = open(dev, O_RDWR); - if (fd != -1) { - *devp = strdup(dev); - if (*devp == NULL) { - fprintf(stderr, "%s: failed to allocate memory\n", progname); - close(fd); - fd = -1; - } - } else if (errno == ENODEV || - errno == ENOENT) /* check for ENOENT too, for the udev case */ - return -2; - else if (!silent) { - fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev, - strerror(errno)); - } - return fd; + int fd = open(dev, O_RDWR); + if (fd != -1) { + *devp = strdup(dev); + if (*devp == NULL) { + fprintf(stderr, "%s: failed to allocate memory\n", + progname); + close(fd); + fd = -1; + } + } else if (errno == ENODEV || + errno == ENOENT)/* check for ENOENT too, for the udev case */ + return -2; + else if (!silent) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev, + strerror(errno)); + } + return fd; } static int try_open_fuse_device(char **devp) { - int fd; - int err; + int fd; + int err; - drop_privs(); - fd = try_open(FUSE_DEV_NEW, devp, 0); - restore_privs(); - if (fd >= 0) - return fd; + drop_privs(); + fd = try_open(FUSE_DEV_NEW, devp, 0); + restore_privs(); + if (fd >= 0) + return fd; - err = fd; - fd = try_open(FUSE_DEV_OLD, devp, 1); - if (fd >= 0) - return fd; + err = fd; + fd = try_open(FUSE_DEV_OLD, devp, 1); + if (fd >= 0) + return fd; - return err; + return err; } static int open_fuse_device(char **devp) { - int fd = try_open_fuse_device(devp); - if (fd >= -1) - return fd; + int fd = try_open_fuse_device(devp); + if (fd >= -1) + return fd; - fprintf(stderr, "%s: fuse device not found, try 'modprobe fuse' first\n", - progname); + fprintf(stderr, + "%s: fuse device not found, try 'modprobe fuse' first\n", + progname); - return -1; + return -1; } static int mount_fuse(const char *mnt, const char *opts) { - int res; - int fd; - char *dev; - struct stat stbuf; - char *type = NULL; - char *source = NULL; - char *mnt_opts = NULL; - const char *real_mnt = mnt; - int currdir_fd = -1; - int mountpoint_fd = -1; - - fd = open_fuse_device(&dev); - if (fd == -1) - return -1; - - drop_privs(); - read_conf(); - - if (getuid() != 0 && mount_max != -1) { - int mount_count = count_fuse_fs(); - if (mount_count >= mount_max) { - fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname); - close(fd); - return -1; - } - } - - res = check_version(dev); - if (res != -1) { - res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd); - restore_privs(); - if (res != -1) - res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts, - dev, &source, &mnt_opts, stbuf.st_size); - } else - restore_privs(); - - if (currdir_fd != -1) { - fchdir(currdir_fd); - close(currdir_fd); - } - if (mountpoint_fd != -1) - close(mountpoint_fd); - - if (res == -1) { - close(fd); - return -1; - } - - if (geteuid() == 0) { - res = add_mount(source, mnt, type, mnt_opts); - if (res == -1) { - umount2(mnt, 2); /* lazy umount */ - close(fd); - return -1; - } - } - - free(source); - free(type); - free(mnt_opts); - free(dev); - - return fd; + int res; + int fd; + char *dev; + struct stat stbuf; + char *type = NULL; + char *source = NULL; + char *mnt_opts = NULL; + const char *real_mnt = mnt; + int currdir_fd = -1; + int mountpoint_fd = -1; + + fd = open_fuse_device(&dev); + if (fd == -1) + return -1; + + drop_privs(); + read_conf(); + + if (getuid() != 0 && mount_max != -1) { + int mount_count = count_fuse_fs(); + if (mount_count >= mount_max) { + fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname); + close(fd); + return -1; + } + } + + res = check_version(dev); + if (res != -1) { + res = check_perm(&real_mnt, &stbuf, &currdir_fd, + &mountpoint_fd); + restore_privs(); + if (res != -1) + res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, + fd, opts, dev, &source, &mnt_opts, + stbuf.st_size); + } else + restore_privs(); + + if (currdir_fd != -1) { + fchdir(currdir_fd); + close(currdir_fd); + } + if (mountpoint_fd != -1) + close(mountpoint_fd); + + if (res == -1) { + close(fd); + return -1; + } + + if (geteuid() == 0) { + res = add_mount(source, mnt, type, mnt_opts); + if (res == -1) { + umount2(mnt, 2); /* lazy umount */ + close(fd); + return -1; + } + } + + free(source); + free(type); + free(mnt_opts); + free(dev); + + return fd; } static int send_fd(int sock_fd, int fd) { - int retval; - struct msghdr msg; - struct cmsghdr *p_cmsg; - struct iovec vec; - size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)]; - int *p_fds; - char sendchar = 0; - - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); - p_cmsg = CMSG_FIRSTHDR(&msg); - p_cmsg->cmsg_level = SOL_SOCKET; - p_cmsg->cmsg_type = SCM_RIGHTS; - p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); - p_fds = (int *) CMSG_DATA(p_cmsg); - *p_fds = fd; - msg.msg_controllen = p_cmsg->cmsg_len; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - /* "To pass file descriptors or credentials you need to send/read at - * least one byte" (man 7 unix) */ - vec.iov_base = &sendchar; - vec.iov_len = sizeof(sendchar); - while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR); - if (retval != 1) { - perror("sending file descriptor"); - return -1; - } - return 0; + int retval; + struct msghdr msg; + struct cmsghdr *p_cmsg; + struct iovec vec; + size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)]; + int *p_fds; + char sendchar = 0; + + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + p_cmsg = CMSG_FIRSTHDR(&msg); + p_cmsg->cmsg_level = SOL_SOCKET; + p_cmsg->cmsg_type = SCM_RIGHTS; + p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + p_fds = (int *) CMSG_DATA(p_cmsg); + *p_fds = fd; + msg.msg_controllen = p_cmsg->cmsg_len; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + /* "To pass file descriptors or credentials you need to send/read at + * least one byte" (man 7 unix) */ + vec.iov_base = &sendchar; + vec.iov_len = sizeof(sendchar); + while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR); + if (retval != 1) { + perror("sending file descriptor"); + return -1; + } + return 0; } static void usage(void) { - fprintf(stderr, - "%s: [options] mountpoint\n" - "Options:\n" - " -h print help\n" - " -V print version\n" - " -o opt[,opt...] mount options\n" - " -u unmount\n" - " -q quiet\n" - " -z lazy unmount\n", - progname); - exit(1); + fprintf(stderr, + "%s: [options] mountpoint\n" + "Options:\n" + " -h print help\n" + " -V print version\n" + " -o opt[,opt...] mount options\n" + " -u unmount\n" + " -q quiet\n" + " -z lazy unmount\n", + progname); + exit(1); } static void show_version(void) { - printf("fusermount version: %s\n", PACKAGE_VERSION); - exit(0); + printf("fusermount version: %s\n", PACKAGE_VERSION); + exit(0); } int main(int argc, char *argv[]) { - int ch; - int fd; - int res; - char *origmnt; - char *mnt; - static int unmount = 0; - static int lazy = 0; - static int quiet = 0; - char *commfd; - int cfd; - const char *opts = ""; - - static const struct option long_opts[] = { - {"unmount", no_argument, NULL, 'u'}, - {"lazy", no_argument, NULL, 'z'}, - {"quiet", no_argument, NULL, 'q'}, - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {0, 0, 0, 0}}; - - progname = strdup(argv[0]); - if (progname == NULL) { - fprintf(stderr, "%s: failed to allocate memory\n", argv[0]); - exit(1); - } - - while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts, NULL)) != -1) { - switch (ch) { - case 'h': - usage(); - break; - - case 'V': - show_version(); - break; - - case 'o': - opts = optarg; - break; - - case 'u': - unmount = 1; - break; - - case 'z': - lazy = 1; - break; - - case 'q': - quiet = 1; - break; - - default: - exit(1); - } - } - - if (lazy && !unmount) { - fprintf(stderr, "%s: -z can only be used with -u\n", progname); - exit(1); - } - - if (optind >= argc) { - fprintf(stderr, "%s: missing mountpoint argument\n", progname); - exit(1); - } - - origmnt = argv[optind]; - - drop_privs(); - mnt = fuse_mnt_resolve_path(progname, origmnt); - restore_privs(); - if (mnt == NULL) - exit(1); - - umask(033); - if (unmount) { - if (geteuid() == 0) - res = unmount_fuse(mnt, quiet, lazy); - else { - res = umount2(mnt, lazy ? 2 : 0); - if (res == -1 && !quiet) - fprintf(stderr, "%s: failed to unmount %s: %s\n", progname, - mnt, strerror(errno)); - } - if (res == -1) - exit(1); - return 0; - } - - commfd = getenv(FUSE_COMMFD_ENV); - if (commfd == NULL) { - fprintf(stderr, "%s: old style mounting not supported\n", progname); - exit(1); - } - - fd = mount_fuse(mnt, opts); - if (fd == -1) - exit(1); - - cfd = atoi(commfd); - res = send_fd(cfd, fd); - if (res == -1) - exit(1); - - return 0; + int ch; + int fd; + int res; + char *origmnt; + char *mnt; + static int unmount = 0; + static int lazy = 0; + static int quiet = 0; + char *commfd; + int cfd; + const char *opts = ""; + + static const struct option long_opts[] = { + {"unmount", no_argument, NULL, 'u'}, + {"lazy", no_argument, NULL, 'z'}, + {"quiet", no_argument, NULL, 'q'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {0, 0, 0, 0}}; + + progname = strdup(argv[0]); + if (progname == NULL) { + fprintf(stderr, "%s: failed to allocate memory\n", argv[0]); + exit(1); + } + + while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts, + NULL)) != -1) { + switch (ch) { + case 'h': + usage(); + break; + + case 'V': + show_version(); + break; + + case 'o': + opts = optarg; + break; + + case 'u': + unmount = 1; + break; + + case 'z': + lazy = 1; + break; + + case 'q': + quiet = 1; + break; + + default: + exit(1); + } + } + + if (lazy && !unmount) { + fprintf(stderr, "%s: -z can only be used with -u\n", progname); + exit(1); + } + + if (optind >= argc) { + fprintf(stderr, "%s: missing mountpoint argument\n", progname); + exit(1); + } + + origmnt = argv[optind]; + + drop_privs(); + mnt = fuse_mnt_resolve_path(progname, origmnt); + restore_privs(); + if (mnt == NULL) + exit(1); + + umask(033); + if (unmount) { + if (geteuid() == 0) + res = unmount_fuse(mnt, quiet, lazy); + else { + res = umount2(mnt, lazy ? 2 : 0); + if (res == -1 && !quiet) + fprintf(stderr, + "%s: failed to unmount %s: %s\n", + progname, mnt, strerror(errno)); + } + if (res == -1) + exit(1); + return 0; + } + + commfd = getenv(FUSE_COMMFD_ENV); + if (commfd == NULL) { + fprintf(stderr, "%s: old style mounting not supported\n", + progname); + exit(1); + } + + fd = mount_fuse(mnt, opts); + if (fd == -1) + exit(1); + + cfd = atoi(commfd); + res = send_fd(cfd, fd); + if (res == -1) + exit(1); + + return 0; } |