summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2004-11-29 23:28:04 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2004-11-29 23:28:04 +0000
commitc68ca945dc13e36566be04d30b8c45129c925b9e (patch)
treefbdbed6bff2c7d9bbb31ce5a5ae4999092515ea7
parent08d408e24b3317746da82f670e701edab5fa7687 (diff)
downloadfuse_2_0_merge4.tar.gz
-rw-r--r--ChangeLog13
-rw-r--r--kernel/dir.c9
-rw-r--r--kernel/file.c5
-rw-r--r--lib/fuse.c20
-rw-r--r--lib/helper.c7
-rw-r--r--util/fusermount.c111
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 <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
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 <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);
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)