fix
authorMiklos Szeredi <miklos@szeredi.hu>
Fri, 20 Feb 2004 16:38:45 +0000 (16:38 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Fri, 20 Feb 2004 16:38:45 +0000 (16:38 +0000)
ChangeLog
include/linux/fuse.h
kernel/dev.c
kernel/inode.c
lib/fuse.c
lib/fuse_i.h
lib/fuse_mt.c
lib/helper.c
util/fusermount.c

index cd1da1d2ce9756cb0436a43821773c30b2f8c730..162916e3b1763af3acd9b58a2b3916844001f4b8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,15 @@
 2004-02-20  Miklos Szeredi <mszeredi@inf.bme.hu>
 
+       * 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 <mszeredi@inf.bme.hu>
 
        * statfs library API changed to match other methods.  Since this
index 10ef1864f3f91c34bd3dbf9257cf8f7467752b80..834c1be1cac8a56e9020dfc177f3187e82b1cd13 100644 (file)
 /** 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;
        
index a31615d7d27ac210e0042a3b27b6a2990485b3a2..43af356aaee3340d8849c47bea75b1ca03327041 100644 (file)
@@ -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);
        }
        
index 08bf3c982c3b8365730e78ce5ce03e82f506dcfb..8f82029faca94a20765d078f6f81e9f03c9c65e0 100644 (file)
@@ -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)
index 2e6950d7c1a98ca77cad53012d430e078751b959..9d0783d57907ee882b46f950bfc8d8f4479c28de 100644 (file)
@@ -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;
index 4eaa5bad5208916054b82e62d4c12ff2066485f3..ce816046d967235bff5af59cc292694f9c0c7634 100644 (file)
@@ -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 {
index f1a2e5ccbd5cd6668796a52fdaf1fcf8259cf148..40da6eddc36b8c2feee05555beeb7b133aacf5ca 100644 (file)
@@ -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);
 }
index d417d90398a0cb5c0cd5b9761a8489532bada85a..7cbb9eb3cb7a0fb173d9ba771ef24b28aa390def 100644 (file)
@@ -15,9 +15,6 @@
 #include <limits.h>
 #include <signal.h>
 
-#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);
index ee4c0054bca8328b55e5e5dc54dc53ca775d3bff..6d27372b4be68c9bb25f17f75d174e38c1f5dc91 100644 (file)
@@ -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;
 }