From 552c2816d7c3f5ac4a909108c13bdbddf7c2fc48 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 8 Nov 2001 14:56:53 +0000 Subject: [PATCH] fusermount --- Makefile.am | 2 +- configure.in | 2 +- include/fuse.h | 1 + util/.cvsignore | 4 + util/Makefile.am | 5 + util/fusermount.c | 244 ++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 218 insertions(+), 40 deletions(-) create mode 100644 util/.cvsignore create mode 100644 util/Makefile.am diff --git a/Makefile.am b/Makefile.am index dc26145..027dd8a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,3 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = kernel lib example include +SUBDIRS = kernel lib util example include diff --git a/configure.in b/configure.in index 8f3b279..247d1cf 100644 --- a/configure.in +++ b/configure.in @@ -49,6 +49,6 @@ AC_SUBST(KERNINCLUDE) kmoduledir=/lib/modules/$kernsrcver AC_SUBST(kmoduledir) -AC_OUTPUT([Makefile kernel/Makefile lib/Makefile example/Makefile include/Makefile include/linux/Makefile]) +AC_OUTPUT([Makefile kernel/Makefile lib/Makefile util/Makefile example/Makefile include/Makefile include/linux/Makefile]) diff --git a/include/fuse.h b/include/fuse.h index 14b6451..8407f26 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -27,6 +27,7 @@ struct fuse_cred { uid_t uid; gid_t gid; /* FIXME: supplementary groups should also be included */ + /* (And capabilities???) */ }; /** diff --git a/util/.cvsignore b/util/.cvsignore new file mode 100644 index 0000000..5f7d28d --- /dev/null +++ b/util/.cvsignore @@ -0,0 +1,4 @@ +Makefile.in +Makefile +.deps +fusermount diff --git a/util/Makefile.am b/util/Makefile.am new file mode 100644 index 0000000..e40103e --- /dev/null +++ b/util/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to produce Makefile.in + +bin_PROGRAMS = fusermount + +fusermount_SOURCES = fusermount.c diff --git a/util/fusermount.c b/util/fusermount.c index 784fd47..df38307 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,164 @@ #define FUSE_DEV "/proc/fs/fuse/dev" const char *progname; +const char *fusermnt = "/etc/fusermnt"; +const char *fusermnt_temp = "/etc/fusermnt~"; + +#define FUSE_USERNAME_MAX 256 +#define FUSE_PATH_MAX 4096 +#define FUSEMNT_LINE_MAX (FUSE_USERNAME_MAX + 1 + FUSE_PATH_MAX + 1) + +static const char *get_user_name() +{ + 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 int fusermnt_lock() +{ + int res; + const char *lockfile = fusermnt; + int fd = open(lockfile, O_WRONLY | O_CREAT, 0644); + if(fd == -1) { + fprintf(stderr, "%s: failed to open lockfile %s: %s\n", progname, + lockfile, strerror(errno)); + return -1; + } + res = lockf(fd, F_LOCK, 0); + if(res == -1) { + fprintf(stderr, "%s: failed to lock file %s: %s\n", progname, + lockfile, strerror(errno)); + close(fd); + return -1; + } + + return fd; +} + +static void fusermnt_unlock(int fd) +{ + lockf(fd, F_UNLCK, 0); + close(fd); +} + + +static int add_mount(const char *mnt) +{ + FILE *fp; + int lockfd; + const char *user = get_user_name(); + if(user == NULL) + return -1; + + lockfd = fusermnt_lock(); + if(lockfd == -1) + return -1; + + fp = fopen(fusermnt, "a"); + if(fp == NULL) { + fprintf(stderr, "%s: could not open %s for writing: %s\n", progname, + fusermnt, strerror(errno)); + return -1; + } + fprintf(fp, "%s %s\n", user, mnt); + fclose(fp); + + fusermnt_unlock(lockfd); + return 0; +} + +static int remove_mount(const char *mnt) +{ + FILE *fp; + FILE *newfp; + int lockfd; + int found; + char buf[FUSEMNT_LINE_MAX + 1]; + const char *user = get_user_name(); + if(user == NULL) + return -1; + + lockfd = fusermnt_lock(); + if(lockfd == -1) + return -1; + + fp = fopen(fusermnt, "r"); + if(fp == NULL) { + fprintf(stderr, "%s: could not open %s for reading: %s\n", progname, + fusermnt, strerror(errno)); + fusermnt_unlock(lockfd); + return -1; + } + + newfp = fopen(fusermnt_temp, "w"); + if(newfp == NULL) { + fprintf(stderr, "%s: could not open %s for writing: %s\n", progname, + fusermnt_temp, strerror(errno)); + fclose(fp); + fusermnt_unlock(lockfd); + return -1; + } + + found = 0; + while(fgets(buf, sizeof(buf), fp) != NULL) { + char *end = buf + strlen(buf) - 1; + char *p; + if(*end != '\n') { + fprintf(stderr, "%s: line too long in file %s\n", progname, + fusermnt); + while(fgets(buf, sizeof(buf), fp) != NULL) { + char *end = buf + strlen(buf) - 1; + if(*end == '\n') + break; + } + continue; + } + *end = '\0'; + + for(p = buf; *p != '\0' && *p != ' '; p++); + if(*p == '\0') { + fprintf(stderr, "%s: malformed line in file %s\n", progname, + fusermnt); + continue; + } + *p = '\0'; + p++; + if(strcmp(user, buf) == 0 && strcmp(mnt, p) == 0) + found = 1; + else + fprintf(newfp, "%s %s\n", buf, p); + } + + fclose(fp); + fclose(newfp); + + if(found) { + int res; + res = rename(fusermnt_temp, fusermnt); + if(res == -1) { + fprintf(stderr, "%s: failed to rename %s to %s: %s\n", + progname, fusermnt_temp, fusermnt, strerror(errno)); + fusermnt_unlock(lockfd); + return -1; + } + } + else { + fprintf(stderr, "%s: entry for %s not found in %s\n", progname, mnt, + fusermnt); + unlink(fusermnt_temp); + fusermnt_unlock(lockfd); + return -1; + } + + fusermnt_unlock(lockfd); + return 0; +} + static int do_mount(const char *dev, const char *mnt, const char *type, mode_t rootmode, int fd) @@ -99,15 +258,34 @@ static int mount_fuse(const char *mnt) if(res == -1) return -1; + res = add_mount(mnt); + if(res == -1) { + umount(mnt); + return -1; + } + return fd; } +static int do_umount(const char *mnt) +{ + int res; + + res = remove_mount(mnt); + if(res == -1) + return -1; + + umount(mnt); + return 0; +} + static void usage() { fprintf(stderr, - "%s: [options] mountpoint program [args ...]\n" + "%s: [options] mountpoint [program [args ...]]\n" "Options:\n" - " -h print help\n", + " -h print help\n" + " -u umount\n", progname); exit(1); } @@ -115,12 +293,11 @@ static void usage() int main(int argc, char *argv[]) { int a; - const char *mnt = NULL; - char **userprog; - pid_t pid; int fd; - int status; int res; + const char *mnt = NULL; + int umount = 0; + char **userprog; progname = argv[0]; @@ -132,6 +309,10 @@ int main(int argc, char *argv[]) case 'h': usage(); break; + + case 'u': + umount = 1; + break; default: fprintf(stderr, "%s: Unknown option %s\n", progname, argv[a]); @@ -146,6 +327,14 @@ int main(int argc, char *argv[]) mnt = argv[a++]; + if(umount) { + res = do_umount(mnt); + if(res == -1) + exit(1); + + return 0; + } + if(a == argc) { fprintf(stderr, "%s: Missing program argument\n", progname); exit(1); @@ -162,38 +351,17 @@ int main(int argc, char *argv[]) dup2(fd, 0); close(fd); } - - pid = fork(); - if(pid == -1) { - fprintf(stderr, "%s: Unable to fork: %s\n", progname, strerror(errno)); - umount(mnt); - exit(1); - } - - if(pid == 0) { - /* Drop setuid/setgid permissions */ - setuid(getuid()); - setgid(getgid()); - - execv(userprog[0], userprog); - fprintf(stderr, "%s: failed to exec %s: %s\n", progname, userprog[0], - strerror(errno)); - exit(1); - } - close(0); - res = waitpid(pid, &status, 0); - if(res == -1) { - fprintf(stderr, "%s: failed to wait for child: %s\n", progname, - strerror(errno)); - exit(1); - } - res = umount(mnt); - if(res == -1) { - fprintf(stderr, "%s: failed to unmount %s: %s\n", progname, mnt, - strerror(errno)); - exit(1); - } + /* Drop setuid/setgid permissions */ + setuid(getuid()); + setgid(getgid()); - return 0; + execv(userprog[0], userprog); + fprintf(stderr, "%s: failed to exec %s: %s\n", progname, userprog[0], + strerror(errno)); + + execl("/proc/self/exe", progname, "-u", mnt, NULL); + fprintf(stderr, "%s: failed to exec self: %s\n", progname, + strerror(errno)); + exit(1); } -- 2.30.2