From c40748abd7f911b3c622600bd23b8517bd8f09c4 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 20 Feb 2004 16:38:45 +0000 Subject: [PATCH] fix --- ChangeLog | 6 ++++ include/linux/fuse.h | 6 ++-- kernel/dev.c | 45 ++++++++++++++++------------- kernel/inode.c | 5 ---- lib/fuse.c | 37 ++++++++++++++++++++++++ lib/fuse_i.h | 2 ++ lib/fuse_mt.c | 3 ++ lib/helper.c | 43 +++++---------------------- util/fusermount.c | 69 +++++++------------------------------------- 9 files changed, 94 insertions(+), 122 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd1da1d..162916e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,15 @@ 2004-02-20 Miklos Szeredi + * removed old way of mounting (fusermount mountpoint program) + * more kernel interface changes: * added nanosecond precision to file times + * removed interface version from mount data + + * added /proc/fs/fuse/version which contains MAJOR.MINOR + 2004-02-19 Miklos Szeredi * statfs library API changed to match other methods. Since this diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 10ef186..834c1be 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -20,11 +20,11 @@ /** Opening this will yield a new control file */ #define FUSE_DEV "/proc/fs/fuse/dev" +/** The file containing the version in the form MAJOR.MINOR */ +#define FUSE_VERSION_FILE "/proc/fs/fuse/version" + /** Data passed to mount */ struct fuse_mount_data { - /** Must be set to FUSE_KERNEL_VERSION */ - int version; - /** The control file descriptor */ int fd; diff --git a/kernel/dev.c b/kernel/dev.c index a31615d..43af356 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -611,10 +611,17 @@ static struct file_operations fuse_dev_operations = { .release = fuse_dev_release, }; -int fuse_dev_init() +static int read_version(char *page, char **start, off_t off, int count, + int *eof, void *data) { - int ret; + char *s = page; + s += sprintf(s, "%i.%i\n", FUSE_KERNEL_VERSION, + FUSE_KERNEL_MINOR_VERSION); + return s - page; +} +int fuse_dev_init() +{ proc_fs_fuse = NULL; proc_fuse_dev = NULL; @@ -624,33 +631,31 @@ int fuse_dev_init() if(!fuse_req_cachep) return -ENOMEM; - ret = -ENOMEM; proc_fs_fuse = proc_mkdir("fuse", proc_root_fs); - if(!proc_fs_fuse) { - printk("fuse: failed to create directory in /proc/fs\n"); - goto err; - } - - proc_fs_fuse->owner = THIS_MODULE; - proc_fuse_dev = create_proc_entry("dev", S_IFSOCK | 0666, proc_fs_fuse); - if(!proc_fuse_dev) { - printk("fuse: failed to create entry in /proc/fs/fuse\n"); - goto err; + if(proc_fs_fuse) { + struct proc_dir_entry *de; + + proc_fs_fuse->owner = THIS_MODULE; + proc_fuse_dev = create_proc_entry("dev", S_IFSOCK | 0666, + proc_fs_fuse); + if(proc_fuse_dev) { + proc_fuse_dev->owner = THIS_MODULE; + proc_fuse_dev->proc_fops = &fuse_dev_operations; + } + de = create_proc_entry("version", S_IFREG | 0444, proc_fs_fuse); + if (de) { + de->owner = THIS_MODULE; + de->read_proc = read_version; + } } - - proc_fuse_dev->proc_fops = &fuse_dev_operations; - return 0; - - err: - fuse_dev_cleanup(); - return ret; } void fuse_dev_cleanup() { if(proc_fs_fuse) { remove_proc_entry("dev", proc_fs_fuse); + remove_proc_entry("version", proc_fs_fuse); remove_proc_entry("fuse", proc_root_fs); } diff --git a/kernel/inode.c b/kernel/inode.c index 08bf3c9..8f82029 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -119,11 +119,6 @@ static struct fuse_conn *get_conn(struct fuse_mount_data *d) return NULL; } - if(d->version != FUSE_KERNEL_VERSION) { - printk("fuse_read_super: Bad version: %i\n", d->version); - return NULL; - } - file = fget(d->fd); ino = NULL; if(file) diff --git a/lib/fuse.c b/lib/fuse.c index 2e6950d..9d0783d 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -1106,6 +1106,9 @@ struct fuse_cmd *__fuse_read_cmd(struct fuse *f) void fuse_loop(struct fuse *f) { + if(f == NULL) + return; + while(1) { struct fuse_cmd *cmd; @@ -1133,6 +1136,35 @@ struct fuse_context *fuse_get_context(struct fuse *f) return &f->context; } +static int check_version(struct fuse *f) +{ + int res; + FILE *vf = fopen(FUSE_VERSION_FILE, "r"); + if(vf == NULL) { + fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n", + FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); + return -1; + } + res = fscanf(vf, "%i.%i", &f->majorver, &f->minorver); + fclose(vf); + if(res != 2) { + fprintf(stderr, "fuse: error reading %s\n", FUSE_VERSION_FILE); + return -1; + } + if(f->majorver != FUSE_KERNEL_VERSION) { + fprintf(stderr, "fuse: bad kernel interface major version: needs %i\n", + FUSE_KERNEL_VERSION); + return -1; + } + if(f->minorver < FUSE_KERNEL_MINOR_VERSION) { + fprintf(stderr, "fuse: kernel interface too old: need >= %i.%i", + FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); + return -1; + } + + return 0; +} + struct fuse *fuse_new(int fd, int flags, const struct fuse_operations *op) { struct fuse *f; @@ -1140,6 +1172,11 @@ struct fuse *fuse_new(int fd, int flags, const struct fuse_operations *op) f = (struct fuse *) calloc(1, sizeof(struct fuse)); + if(check_version(f) == -1) { + free(f); + return NULL; + } + f->flags = flags; f->fd = fd; f->ctr = 0; diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 4eaa5ba..ce81604 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -41,6 +41,8 @@ struct fuse { struct fuse_context context; pthread_key_t context_key; volatile int exited; + int majorver; + int minorver; }; struct fuse_dirhandle { diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c index f1a2e5c..40da6ed 100644 --- a/lib/fuse_mt.c +++ b/lib/fuse_mt.c @@ -114,5 +114,8 @@ void __fuse_loop_mt(struct fuse *f, fuse_processor_t proc, void *data) void fuse_loop_mt(struct fuse *f) { + if(f == NULL) + return; + __fuse_loop_mt(f, (fuse_processor_t) __fuse_process_cmd, NULL); } diff --git a/lib/helper.c b/lib/helper.c index d417d90..7cbb9eb 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -15,9 +15,6 @@ #include #include -#define FUSE_MOUNTED_ENV "_FUSE_MOUNTED" -#define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD" - static struct fuse *fuse; static void usage(char *progname) @@ -73,21 +70,14 @@ static void set_signal_handlers() void fuse_main(int argc, char *argv[], const struct fuse_operations *op) { - int argctr = 1; + int argctr = 2; int flags; int multithreaded; - char *isreexec = getenv(FUSE_MOUNTED_ENV); int fuse_fd; char *fuse_mountpoint = NULL; char umount_cmd[1024] = ""; char **fusermount_args = NULL; - if(!isreexec) { - if(argc < 2 || argv[1][0] == '-') - usage(argv[0]); - argctr ++; - } - flags = 0; multithreaded = 1; for(; argctr < argc && !fusermount_args; argctr ++) { @@ -106,10 +96,7 @@ void fuse_main(int argc, char *argv[], const struct fuse_operations *op) break; case '-': - if(!isreexec) - fusermount_args = &argv[argctr+1]; - else - invalid_option(argv, argctr); + fusermount_args = &argv[argctr+1]; break; default: @@ -119,30 +106,16 @@ void fuse_main(int argc, char *argv[], const struct fuse_operations *op) invalid_option(argv, argctr); } - if(!isreexec) { - fuse_mountpoint = strdup(argv[1]); - fuse_fd = fuse_mount(fuse_mountpoint, (const char **) fusermount_args); - if(fuse_fd == -1) - exit(1); - } else { - char *tmpstr; - - /* Old (obsolescent) way of doing the mount: - - fusermount [options] mountpoint [program [args ...]] - - fusermount execs this program and passes the control file - descriptor dup()-ed to stdin */ - fuse_fd = 0; - - tmpstr = getenv(FUSE_UMOUNT_CMD_ENV); - if(tmpstr != NULL) - strncpy(umount_cmd, tmpstr, sizeof(umount_cmd) - 1); - } + fuse_mountpoint = strdup(argv[1]); + fuse_fd = fuse_mount(fuse_mountpoint, (const char **) fusermount_args); + if(fuse_fd == -1) + exit(1); set_signal_handlers(); fuse = fuse_new(fuse_fd, flags, op); + if(fuse == NULL) + exit(1); if(multithreaded) fuse_loop_mt(fuse); diff --git a/util/fusermount.c b/util/fusermount.c index ee4c005..6d27372 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -37,9 +37,6 @@ #define FUSE_DEV "/proc/fs/fuse/dev" -#define FUSE_MOUNTED_ENV "_FUSE_MOUNTED" -#define FUSE_UMOUNT_CMD_ENV "_FUSE_UNMOUNT_CMD" -#define FUSE_KERNEL_VERSION_ENV "_FUSE_KERNEL_VERSION" #define FUSE_COMMFD_ENV "_FUSE_COMMFD" const char *progname; @@ -303,7 +300,6 @@ static int do_mount(const char *dev, const char *mnt, const char *type, return -1; } - data.version = FUSE_KERNEL_VERSION; data.fd = fd; data.rootmode = rootmode; data.uid = getuid(); @@ -476,7 +472,7 @@ static int send_fd(int sock_fd, int fd) static void usage() { fprintf(stderr, - "%s: [options] mountpoint [program [args ...]]\n" + "%s: [options] mountpoint\n" "Options:\n" " -h print help\n" " -u unmount\n" @@ -498,15 +494,11 @@ int main(int argc, char *argv[]) char *origmnt; char *mnt; int unmount = 0; - char **userprog; - int numargs; - char mypath[PATH_MAX]; - char *unmount_cmd; char *commfd; const char *fsname = NULL; - char verstr[128]; int flags = 0; int quiet = 0; + int cfd; progname = argv[0]; @@ -599,60 +591,19 @@ int main(int argc, char *argv[]) } commfd = getenv(FUSE_COMMFD_ENV); - - if(a == argc && commfd == NULL) { - fprintf(stderr, "%s: Missing program argument\n", progname); + if(commfd == NULL) { + fprintf(stderr, "%s: old style mounting not supported\n", progname); exit(1); } - - userprog = argv + a; - numargs = argc - a; - + fd = mount_fuse(mnt, flags, fsname); if(fd == -1) exit(1); - if(commfd != NULL) { - int cfd = atoi(commfd); - res = send_fd(cfd, fd); - if(res == -1) - exit(1); - exit(0); - } - - /* Dup the file descriptor to stdin */ - if(fd != 0) { - dup2(fd, 0); - close(fd); - } + cfd = atoi(commfd); + res = send_fd(cfd, fd); + if(res == -1) + exit(1); - /* Strangely this doesn't work after dropping permissions... */ - res = readlink("/proc/self/exe", mypath, sizeof(mypath) - 1); - if(res == -1) { - fprintf(stderr, "%s: failed to determine self path: %s\n", - progname, strerror(errno)); - strcpy(mypath, "fusermount"); - fprintf(stderr, "using %s as the default\n", mypath); - } - else - mypath[res] = '\0'; - - /* Drop setuid/setgid permissions */ - setuid(getuid()); - setgid(getgid()); - - unmount_cmd = (char *) malloc(strlen(mypath) + strlen(mnt) + 64); - sprintf(unmount_cmd, "%s -u -q %s", mypath, mnt); - setenv(FUSE_UMOUNT_CMD_ENV, unmount_cmd, 1); - sprintf(verstr, "%i", FUSE_KERNEL_VERSION); - setenv(FUSE_KERNEL_VERSION_ENV, verstr, 1); - setenv(FUSE_MOUNTED_ENV, "", 1); - - execvp(userprog[0], userprog); - fprintf(stderr, "%s: failed to exec %s: %s\n", progname, userprog[0], - strerror(errno)); - - close(0); - system(unmount_cmd); - return 1; + return 0; } -- 2.30.2