From c68ca945dc13e36566be04d30b8c45129c925b9e Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 29 Nov 2004 23:28:04 +0000 Subject: [PATCH] fix --- ChangeLog | 13 +++++++ kernel/dir.c | 9 ++++- kernel/file.c | 5 +-- lib/fuse.c | 20 +++++++--- lib/helper.c | 7 ++++ util/fusermount.c | 111 +++++++++++++++++++++++------------------------------- 6 files changed, 92 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index da2b471..53675e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2004-11-29 Miklos Szeredi + + * 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 * Make libfuse and fusermount compatible with future versions diff --git a/kernel/dir.c b/kernel/dir.c index d485f49..3efd702 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -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, diff --git a/kernel/file.c b/kernel/file.c index 84e75ad..c2a1338 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -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; diff --git a/lib/fuse.c b/lib/fuse.c index bf345b6..2fa6032 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -17,6 +17,10 @@ #include #include +#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); diff --git a/lib/helper.c b/lib/helper.c index b8c73be..b4d437f 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -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; diff --git a/util/fusermount.c b/util/fusermount.c index 98a705b..c8c17b6 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -39,7 +39,10 @@ #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) -- 2.11.4.GIT