diff options
Diffstat (limited to 'contrib/fuse-util')
| -rw-r--r-- | contrib/fuse-util/Makefile.am | 8 | ||||
| -rw-r--r-- | contrib/fuse-util/fusermount.c | 184 | ||||
| -rw-r--r-- | contrib/fuse-util/mount_util.c | 64 | ||||
| -rw-r--r-- | contrib/fuse-util/mount_util.h | 18 |
4 files changed, 188 insertions, 86 deletions
diff --git a/contrib/fuse-util/Makefile.am b/contrib/fuse-util/Makefile.am index a72e3832b16..abbc10eb6d9 100644 --- a/contrib/fuse-util/Makefile.am +++ b/contrib/fuse-util/Makefile.am @@ -1,9 +1,11 @@ bin_PROGRAMS = fusermount-glusterfs -fusermount_glusterfs_SOURCES = fusermount.c $(CONTRIBDIR)/fuse-lib/mount.c -noinst_HEADERS = mount_util.h +fusermount_glusterfs_SOURCES = fusermount.c mount_util.c $(CONTRIBDIR)/fuse-lib/mount-common.c +noinst_HEADERS = $(CONTRIBDIR)/fuse-include/mount_util.h -AM_CFLAGS = -Wall -D_FILE_OFFSET_BITS=64 -DFUSE_UTIL $(GF_CFLAGS) -D_GNU_SOURCE +AM_CPPFLAGS = $(GF_CPPFLAGS) -DFUSE_UTIL -I$(CONTRIBDIR)/fuse-include -I$(CONTRIBDIR)/fuse-lib + +AM_CFLAGS = -Wall $(GF_CFLAGS) install-exec-hook: -chown root $(DESTDIR)$(bindir)/fusermount-glusterfs diff --git a/contrib/fuse-util/fusermount.c b/contrib/fuse-util/fusermount.c index 39da9b6a0b6..ff743f75a21 100644 --- a/contrib/fuse-util/fusermount.c +++ b/contrib/fuse-util/fusermount.c @@ -10,6 +10,11 @@ #include <config.h> #include "mount_util.h" + +#ifndef HAVE_UMOUNT2 +#include "mount-gluster-compat.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -19,15 +24,24 @@ #include <errno.h> #include <fcntl.h> #include <pwd.h> +#include <limits.h> +#if !defined(__NetBSD__) && !defined(GF_DARWIN_HOST_OS) #include <mntent.h> +#endif /* __NetBSD__ */ #include <sys/wait.h> #include <sys/stat.h> -#include <sys/mount.h> +#ifdef HAVE_SET_FSID #include <sys/fsuid.h> +#endif +#ifdef GF_DARWIN_HOST_OS +#include <sys/param.h> +#endif +#include <sys/mount.h> #include <sys/socket.h> #include <sys/utsname.h> #include <sched.h> +#define FUSE_DEVFD_ENV "_FUSE_DEVFD" #define FUSE_COMMFD_ENV "_FUSE_COMMFD" #define FUSE_DEV_OLD "/proc/fs/fuse/dev" @@ -61,22 +75,32 @@ static const char *get_user_name(void) } } +#ifdef HAVE_SET_FSID static uid_t oldfsuid; static gid_t oldfsgid; +#endif static void drop_privs(void) { if (getuid() != 0) { +#ifdef HAVE_SET_FSID oldfsuid = setfsuid(getuid()); oldfsgid = setfsgid(getgid()); +#else + fprintf(stderr, "%s: Implement alternative setfsuid/gid \n", progname); +#endif } } static void restore_privs(void) { if (getuid() != 0) { +#ifdef HAVE_SET_FSID setfsuid(oldfsuid); setfsgid(oldfsgid); +#else + fprintf(stderr, "%s: Implement alternative setfsuid/gid \n", progname); +#endif } } @@ -114,8 +138,16 @@ static int lock_umount(void) static void unlock_umount(int mtablock) { - lockf(mtablock, F_ULOCK, 0); - close(mtablock); + if (mtablock >= 0) { + int res; + + res = lockf(mtablock, F_ULOCK, 0); + if (res < 0) { + fprintf(stderr, "%s: error releasing lock: %s\n", + progname, strerror(errno)); + } + close(mtablock); + } } static int add_mount(const char *source, const char *mnt, const char *type, @@ -238,7 +270,7 @@ static int check_is_mount_child(void *p) } count = 0; - while ((entp = getmntent(fp)) != NULL) + while (getmntent(fp) != NULL) count++; endmntent(fp); @@ -325,7 +357,7 @@ static int check_is_mount(const char *last, const char *mnt) return 0; } -static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) +static int chdir_to_parent(char *copy, const char **lastp) { char *tmp; const char *parent; @@ -350,14 +382,6 @@ static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) parent = "/"; } - *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(parent); if (res == -1) { fprintf(stderr, "%s: failed to chdir to %s: %s\n", @@ -382,7 +406,6 @@ static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) { - int currdir_fd = -1; char *copy; const char *last; int res; @@ -399,7 +422,7 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) return -1; } - res = chdir_to_parent(copy, &last, &currdir_fd); + res = chdir_to_parent(copy, &last); if (res == -1) goto out; @@ -411,10 +434,6 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) out: free(copy); - if (currdir_fd != -1) { - fchdir(currdir_fd); - close(currdir_fd); - } return res; } @@ -501,20 +520,22 @@ static void parse_line(char *line, int linenum) static void read_conf(void) { + int len; 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) { + len = strlen (line); if (isnewline) { - if (line[strlen(line)-1] == '\n') { + if (len && line[len-1] == '\n') { strip_line(line); parse_line(line, linenum); } else { isnewline = 0; } - } else if(line[strlen(line)-1] == '\n') { + } else if (len && line[len-1] == '\n') { fprintf(stderr, "%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum); isnewline = 1; @@ -609,7 +630,7 @@ static int add_option(char **optsp, const char *opt, unsigned expand) static int get_mnt_opts(int flags, char *opts, char **mnt_optsp) { int i; - int l; + size_t l; if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1) return -1; @@ -624,7 +645,7 @@ static int get_mnt_opts(int flags, char *opts, char **mnt_optsp) return -1; /* remove comma from end of opts*/ l = strlen(*mnt_optsp); - if ((*mnt_optsp)[l-1] == ',') + if (l && (*mnt_optsp)[l-1] == ',') (*mnt_optsp)[l-1] = '\0'; if (getuid() != 0) { const char *user = get_user_name(); @@ -653,8 +674,7 @@ static int get_string_opt(const char *s, unsigned len, const char *opt, unsigned opt_len = strlen(opt); char *d; - if (*val) - free(*val); + free(*val); *val = (char *) malloc(len - opt_len + 1); if (!*val) { fprintf(stderr, "%s: failed to allocate memory\n", progname); @@ -823,15 +843,14 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode, fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save)); goto err; - } else { - *sourcep = source; - *typep = type; - *mnt_optsp = mnt_opts; } + *sourcep = source; + *typep = type; + *mnt_optsp = mnt_opts; free(fsname); free(optbuf); - return res; + return 0; err: free(fsname); @@ -874,8 +893,7 @@ static int check_version(const char *dev) return 0; } -static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd, - int *mountpoint_fd) +static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd) { int res; const char *mnt = *mntp; @@ -893,13 +911,6 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd, 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, @@ -1016,8 +1027,36 @@ static int open_fuse_device(char **devp) return -1; } +static int check_fuse_device(char *devfd, char **devp) +{ + int res; + char *devlink; -static int mount_fuse(const char *mnt, const char *opts) + res = asprintf(&devlink, "/proc/self/fd/%s", devfd); + if (res == -1) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return -1; + } + + *devp = (char *) calloc(1, PATH_MAX + 1); + if (!*devp) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + free(devlink); + return -1; + } + + res = readlink (devlink, *devp, PATH_MAX); + free (devlink); + if (res == -1) { + fprintf(stderr, "%s: specified fuse fd is invalid\n", + progname); + return -1; + } + + return atoi(devfd); +} + +static int mount_fuse(const char *mnt, const char *opts, char *devfd) { int res; int fd; @@ -1027,10 +1066,9 @@ static int mount_fuse(const char *mnt, const char *opts) 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); + fd = devfd ? check_fuse_device(devfd, &dev) : open_fuse_device(&dev); if (fd == -1) return -1; @@ -1041,15 +1079,13 @@ static int mount_fuse(const char *mnt, const char *opts) 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; + goto fail_close_fd; } } res = check_version(dev); if (res != -1) { - res = check_perm(&real_mnt, &stbuf, &currdir_fd, - &mountpoint_fd); + res = check_perm(&real_mnt, &stbuf, &mountpoint_fd); restore_privs(); if (res != -1) res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, @@ -1058,33 +1094,38 @@ static int mount_fuse(const char *mnt, const char *opts) } else restore_privs(); - if (currdir_fd != -1) { - fchdir(currdir_fd); - close(currdir_fd); - } if (mountpoint_fd != -1) close(mountpoint_fd); + if (res == -1) + goto fail_close_fd; + + res = chdir("/"); if (res == -1) { - close(fd); - return -1; + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + goto fail_close_fd; } if (geteuid() == 0) { res = add_mount(source, mnt, type, mnt_opts); if (res == -1) { - umount2(mnt, 2); /* lazy umount */ - close(fd); - return -1; + /* Can't clean up mount in a non-racy way */ + goto fail_close_fd; } } +out_free: free(source); free(type); free(mnt_opts); free(dev); return fd; + +fail_close_fd: + close(fd); + fd = -1; + goto out_free; } static int send_fd(int sock_fd, int fd) @@ -1154,6 +1195,7 @@ int main(int argc, char *argv[]) static int unmount = 0; static int lazy = 0; static int quiet = 0; + char *devfd; char *commfd; int cfd; const char *opts = ""; @@ -1222,6 +1264,13 @@ int main(int argc, char *argv[]) drop_privs(); mnt = fuse_mnt_resolve_path(progname, origmnt); + if (mnt != NULL) { + res = chdir("/"); + if (res == -1) { + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + exit(1); + } + } restore_privs(); if (mnt == NULL) exit(1); @@ -1242,21 +1291,26 @@ int main(int argc, char *argv[]) return 0; } - commfd = getenv(FUSE_COMMFD_ENV); - if (commfd == NULL) { - fprintf(stderr, "%s: old style mounting not supported\n", - progname); - exit(1); + devfd = getenv(FUSE_DEVFD_ENV); + if (devfd == NULL) { + 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); + fd = mount_fuse(mnt, opts, devfd); if (fd == -1) exit(1); - cfd = atoi(commfd); - res = send_fd(cfd, fd); - if (res == -1) - exit(1); + if (devfd == NULL) { + cfd = atoi(commfd); + res = send_fd(cfd, fd); + if (res == -1) + exit(1); + } return 0; } diff --git a/contrib/fuse-util/mount_util.c b/contrib/fuse-util/mount_util.c new file mode 100644 index 00000000000..911b84445e9 --- /dev/null +++ b/contrib/fuse-util/mount_util.c @@ -0,0 +1,64 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include <dirent.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +int fuse_mnt_check_empty(const char *progname, const char *mnt, + mode_t rootmode, off_t rootsize) +{ + int isempty = 1; + + if (S_ISDIR(rootmode)) { + struct dirent *ent; + DIR *dp = opendir(mnt); + if (dp == NULL) { + fprintf(stderr, + "%s: failed to open mountpoint for reading: %s\n", + progname, strerror(errno)); + return -1; + } + while ((ent = readdir(dp)) != NULL) { + if (strcmp(ent->d_name, ".") != 0 && + strcmp(ent->d_name, "..") != 0) { + isempty = 0; + break; + } + } + closedir(dp); + } else if (rootsize) + isempty = 0; + + if (!isempty) { + fprintf(stderr, "%s: mountpoint is not empty\n", progname); + fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname); + return -1; + } + 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/contrib/fuse-util/mount_util.h b/contrib/fuse-util/mount_util.h deleted file mode 100644 index f392f99f17a..00000000000 --- a/contrib/fuse-util/mount_util.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - FUSE: Filesystem in Userspace - Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> - - This program can be distributed under the terms of the GNU LGPLv2. - See the file COPYING.LIB. -*/ - -#include <sys/types.h> - -int fuse_mnt_add_mount(const char *progname, const char *fsname, - const char *mnt, const char *type, const char *opts); -int fuse_mnt_umount(const char *progname, const char *abs_mnt, - const char *rel_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); |
