fix fuse_2_0_merge4
authorMiklos Szeredi <miklos@szeredi.hu>
Mon, 29 Nov 2004 23:28:04 +0000 (23:28 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Mon, 29 Nov 2004 23:28:04 +0000 (23:28 +0000)
ChangeLog
kernel/dir.c
kernel/file.c
lib/fuse.c
lib/helper.c
util/fusermount.c

index da2b47113aa449ce64aeb745ded61c9589aaf92b..53675e6331853a705979c8609195f56b597af56f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2004-11-29  Miklos Szeredi <miklos@szeredi.hu>
+
+       * kernel: make readpage() uninterruptible
+
+       * kernel: check readonly filesystem flag in fuse_permission
+
+       * lib: don't die if version file not found and new style device
+       exists
+
+       * lib: add '-r' option, which is short for '-o ro'
+
+       * fusermount: simplify device opening
+
 2004-11-19  Miklos Szeredi <miklos@szeredi.hu>
 
        * Make libfuse and fusermount compatible with future versions
index d485f49a6e1be7155e1b9631aa26cbfdd2f72fcd..3efd702420d9264598947e94febd661897eecdb4 100644 (file)
@@ -560,8 +560,15 @@ static int _fuse_permission(struct inode *inode, int mask)
                   keeping it open... */
 
                return err;
-       } else
+       } else {
+               int mode = inode->i_mode;
+               if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+                    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+                        return -EROFS;
+               if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
+                       return -EACCES;
                return 0;
+       }
 }
 
 static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
index 84e75ad198f44674dab23112c062826653fa2789..c2a13389646d8424ea6238855db66e51f44638f4 100644 (file)
@@ -233,10 +233,7 @@ static ssize_t fuse_send_read(struct file *file, struct inode *inode,
        struct fuse_read_in inarg;
        ssize_t res;
        
-       req = fuse_get_request(fc);
-       if (!req)
-               return -ERESTARTSYS;
-       
+       req = fuse_get_request_nonint(fc);
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
        inarg.offset = pos;
index bf345b62bd91466eccac86500ba82d2c1716e214..2fa60327cecd9d1809dd621d412396fd46c12059 100644 (file)
 #include <errno.h>
 #include <sys/param.h>
 
+#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
+#define FUSE_VERSION_FILE_NEW "/sys/fs/fuse/version"
+#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
+
 #define FUSE_MAX_PATH 4096
 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg))
 
@@ -1689,15 +1693,21 @@ void __fuse_set_getcontext_func(struct fuse_context *(*func)(void))
 static int check_version(struct fuse *f)
 {
     int res;
-    const char *version_file = FUSE_VERSION_FILE;
+    const char *version_file = FUSE_VERSION_FILE_NEW;
     FILE *vf = fopen(version_file, "r");
     if (vf == NULL) {
-        version_file = "/sys/fs/fuse/version";
+        version_file = FUSE_VERSION_FILE_OLD;
         vf = fopen(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;
+            struct stat tmp;
+            if (stat(FUSE_DEV_OLD, &tmp) != -1) {
+                fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n",
+                        FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
+                return -1;
+            } else {
+                fprintf(stderr, "fuse: warning: version of kernel interface unknown\n");
+                return 0;
+            }
         }
     }
     res = fscanf(vf, "%i.%i", &f->majorver, &f->minorver);
index b8c73be95e3a76d89326515242e40f4cf526ae31..b4d437fd6abaf0997ee7c43ea4e9c50f309950f5 100644 (file)
@@ -25,6 +25,7 @@ static void usage(const char *progname)
             "    -d                  enable debug output (implies -f)\n"
             "    -f                  foreground operation\n"
             "    -s                  disable multithreaded operation\n"
+            "    -r                  mount read only (equivalent to '-o ro')\n"
             "    -o opt,[opt...]     mount options\n"
             "    -h                  print help\n"
             "\n"
@@ -187,6 +188,12 @@ static int fuse_parse_cmdline(int argc, const char *argv[], char **kernel_opts,
                     *background = 0;
                     break;
                     
+                case 'r':
+                    res = add_options(lib_opts, kernel_opts, "ro");
+                    if (res == -1)
+                        goto err;
+                    break;
+
                 case 'f':
                     *background = 0;
                     break;
index 98a705b448ef2015532985ce2dd2cad19bf3c3a6..c8c17b61570db8ab7a39d1351300f47232a2d348 100644 (file)
 
 #define FUSE_DEV_OLD "/proc/fs/fuse/dev"
 #define FUSE_DEV_NEW "/dev/fuse"
-#define FUSE_SYS_DEV "/sys/class/misc/fuse/dev"
+#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
+#define FUSE_VERSION_FILE_NEW "/sys/fs/fuse/version"
+#define FUSE_MAJOR 10
+#define FUSE_MINOR 229
 
 const char *progname;
 
@@ -475,19 +478,29 @@ static int do_mount(const char *mnt, const char *type, mode_t rootmode,
     return res;
 }
 
-static int check_version(void)
+static int check_version(const char *dev)
 {
     int res;
     int majorver;
     int minorver;
-    const char *version_file = FUSE_VERSION_FILE;
-    FILE *vf = fopen(version_file, "r");
+    const char *version_file;
+    int isold = 0;
+    FILE *vf;
+
+    if (strcmp(dev, FUSE_DEV_OLD) == 0)
+        isold = 1;
+
+    version_file = FUSE_VERSION_FILE_OLD;
+    vf = fopen(version_file, "r");
     if (vf == NULL) {
-        version_file = "/sys/fs/fuse/version";
+        version_file = FUSE_VERSION_FILE_NEW;
         vf = fopen(version_file, "r");
         if (vf == NULL) {
-            fprintf(stderr, "%s: kernel interface too old\n", progname);
-            return -1;
+            if (isold) {
+                fprintf(stderr, "%s: kernel interface too old\n", progname);
+                return -1;
+            } else
+                return 0;
         }
     }
     res = fscanf(vf, "%i.%i", &majorver, &minorver);
@@ -571,7 +584,9 @@ static int try_open(const char *dev, char **devp, int silent)
             close(fd);
             fd = -1;
         }
-    } else if (!silent) {
+    } else if (errno == ENODEV)
+        return -2;
+    else if (!silent) {
         fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
                 strerror(errno));
     }
@@ -606,67 +621,42 @@ static int try_open_new_temp(unsigned devnum, char **devp)
     return fd;
 }
 
-static int try_open_new(char **devp)
+static int try_open_fuse_device(char **devp)
 {
-    const char *dev;
-    unsigned minor;
-    unsigned major;
-    int res;
-    struct stat stbuf;
-    unsigned devnum;
-    char buf[256];
-    int fd = open(FUSE_SYS_DEV, O_RDONLY);
-    if (fd == -1)
-        return -2;
-
-    res = read(fd, buf, sizeof(buf)-1);
-    close(fd);
-    if (res == -1) {
-        fprintf(stderr, "%s: failed to read from %s: %s\n", progname,
-                FUSE_SYS_DEV, strerror(errno));
-        return -1;
-    }
+    int fd = try_open(FUSE_DEV_NEW, devp, 1);
+    if (fd >= 0)
+        return fd;
     
-    buf[res] = '\0';
-    if (sscanf(buf, "%u:%u", &major, &minor) != 2) {
-        fprintf(stderr, "%s: parse error reading from %s\n", progname,
-                FUSE_SYS_DEV);
-        return -1;
+    if (fd == -1) {
+        fd = try_open_new_temp(FUSE_MAJOR << 8 | FUSE_MINOR, devp);
+        if (fd != -2)
+            return fd;
     }
-
-    devnum = (major << 8) + (minor & 0xff) + ((minor & 0xff00) << 12);
-    dev = FUSE_DEV_NEW;
-    res = stat(dev, &stbuf);
-    if (res == -1)
-        return try_open_new_temp(devnum, devp);
     
-    if ((stbuf.st_mode & S_IFMT) != S_IFCHR || stbuf.st_rdev != devnum) {
-        fprintf(stderr, "%s: %s exists but has wrong attributes\n", progname,
-                dev);
-        return -1;
-    }
-    return try_open(dev, devp, 0);
+    fd = try_open(FUSE_DEV_OLD, devp, 1);
+    if (fd >= 0)
+        return fd;
+
+    return -1;
 }
 
 static int open_fuse_device(char **devp)
 {
     int fd;
 
-    fd = try_open_new(devp);
-    if (fd != -2)
-        return fd;
-
-    fd = try_open(FUSE_DEV_OLD, devp, 1);
-    if (fd != -1)
-        return fd;
-
     if (1
 #ifndef AUTO_MODPROBE
         && getuid() == 0
 #endif
         ) {
         int status;
-        pid_t pid = fork();
+        pid_t pid;
+
+        fd = try_open_fuse_device(devp);
+        if (fd >= 0)
+            return fd;
+        
+        pid = fork();
         if (pid == 0) {
             setuid(0);
             execl("/sbin/modprobe", "/sbin/modprobe", "fuse", NULL);
@@ -674,17 +664,12 @@ static int open_fuse_device(char **devp)
         }
         if (pid != -1)
             waitpid(pid, &status, 0);
-
-        fd = try_open_new(devp);
-        if (fd != -2)
-            return fd;
-
-        fd = try_open(FUSE_DEV_OLD, devp, 1);
-        if (fd != -1)
-            return fd;
-        
     }
 
+    fd = try_open_fuse_device(devp);
+    if (fd >= 0)
+        return fd;
+    
     fprintf(stderr, "fuse device not found, try 'modprobe fuse' first\n");
     return -1;
 }
@@ -713,7 +698,7 @@ static int mount_fuse(const char *mnt, const char *opts)
             return -1;
     }
 
-    res = check_version();
+    res = check_version(dev);
     if (res != -1) {
         res = check_perm(&real_mnt, &stbuf, &currdir_fd);
         if (res != -1)