fix
diff --git a/ChangeLog b/ChangeLog
index 005f652..c0b8679 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,8 @@
* lib: simplify 'readdir_ino' handling
+ * lib: add mount options 'umask=M', 'uid=N', 'gid=N'
+
2005-07-03 Miklos Szeredi <miklos@szeredi.hu>
* kernel: clean up 'direct_io' code
diff --git a/README b/README
index 5006b3e..7d8a746 100644
--- a/README
+++ b/README
@@ -216,3 +216,17 @@
mounts are rejected (from version 2.3.1) to prevent accidental
covering up of data, which could for example prevent automatic
backup.
+
+umask=M
+
+ Override the permission bits in 'st_mode' set by the filesystem.
+ The resulting permission bits are the ones missing from the given
+ umask value. The value is given in octal representation.
+
+uid=N
+
+ Override the 'st_uid' field set by the filesystem.
+
+gid=N
+
+ Override the 'st_gid' field set by the filesystem.
diff --git a/lib/fuse.c b/lib/fuse.c
index 317b27d..45ea1b3 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -40,6 +40,19 @@
/** Make a best effort to fill in inode number in a readdir **/
#define FUSE_READDIR_INO (1 << 5)
+/** Ignore file mode supplied by the filesystem, and create one based
+ on the 'umask' option */
+#define FUSE_SET_MODE (1 << 6)
+
+/** Ignore st_uid supplied by the filesystem and set it based on the
+ 'uid' option*/
+#define FUSE_SET_UID (1 << 7)
+
+/** Ignore st_gid supplied by the filesystem and set it based on the
+ 'gid' option*/
+#define FUSE_SET_GID (1 << 8)
+
+
#define FUSE_MAX_PATH 4096
#define PARAM_T(inarg, type) (((char *)(inarg)) + sizeof(type))
#define PARAM(inarg) PARAM_T(inarg, *(inarg))
@@ -294,29 +307,19 @@
}
static struct node *find_node(struct fuse *f, nodeid_t parent, char *name,
- struct fuse_attr *attr, uint64_t version)
+ uint64_t version)
{
struct node *node;
- int mode = attr->mode & S_IFMT;
- int rdev = 0;
-
- if (S_ISCHR(mode) || S_ISBLK(mode))
- rdev = attr->rdev;
pthread_mutex_lock(&f->lock);
node = lookup_node(f, parent, name);
- if (node != NULL) {
- if (!(f->flags & FUSE_USE_INO))
- attr->ino = node->nodeid;
- } else {
+ if (node == NULL) {
node = (struct node *) calloc(1, sizeof(struct node));
if (node == NULL)
goto out_err;
node->refctr = 1;
node->nodeid = next_id(f);
- if (!(f->flags & FUSE_USE_INO))
- attr->ino = node->nodeid;
node->open_count = 0;
node->is_hidden = 0;
node->generation = f->generation;
@@ -475,13 +478,16 @@
return err;
}
-static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
+static void convert_stat(struct fuse *f, nodeid_t nodeid, struct stat *stbuf,
+ struct fuse_attr *attr)
{
- attr->ino = stbuf->st_ino;
+ attr->ino = (f->flags & FUSE_USE_INO) ? stbuf->st_ino : nodeid;
attr->mode = stbuf->st_mode;
+ if (f->flags & FUSE_SET_MODE)
+ attr->mode = (attr->mode & S_IFMT) | (0777 & ~f->umask);
attr->nlink = stbuf->st_nlink;
- attr->uid = stbuf->st_uid;
- attr->gid = stbuf->st_gid;
+ attr->uid = (f->flags & FUSE_SET_UID) ? f->uid : stbuf->st_uid;
+ attr->gid = (f->flags & FUSE_SET_GID) ? f->gid : stbuf->st_gid;
attr->rdev = stbuf->st_rdev;
attr->size = stbuf->st_size;
attr->blocks = stbuf->st_blocks;
@@ -643,12 +649,12 @@
if (res == 0) {
struct node *node;
- memset(arg, 0, sizeof(struct fuse_entry_out));
- convert_stat(&buf, &arg->attr);
- node = find_node(f, nodeid, name, &arg->attr, version);
+ node = find_node(f, nodeid, name, version);
if (node == NULL)
res = -ENOMEM;
else {
+ memset(arg, 0, sizeof(struct fuse_entry_out));
+ convert_stat(f, node->nodeid, &buf, &arg->attr);
arg->nodeid = node->nodeid;
arg->generation = node->generation;
arg->entry_valid = ENTRY_REVALIDATE_TIME;
@@ -726,9 +732,7 @@
memset(&arg, 0, sizeof(struct fuse_attr_out));
arg.attr_valid = ATTR_REVALIDATE_TIME;
arg.attr_valid_nsec = 0;
- convert_stat(&buf, &arg.attr);
- if (!(f->flags & FUSE_USE_INO))
- arg.attr.ino = in->nodeid;
+ convert_stat(f, in->nodeid, &buf, &arg.attr);
}
send_reply(f, in, res, &arg, sizeof(arg));
@@ -816,9 +820,7 @@
memset(&outarg, 0, sizeof(struct fuse_attr_out));
outarg.attr_valid = ATTR_REVALIDATE_TIME;
outarg.attr_valid_nsec = 0;
- convert_stat(&buf, &outarg.attr);
- if (!(f->flags & FUSE_USE_INO))
- outarg.attr.ino = in->nodeid;
+ convert_stat(f, in->nodeid, &buf, &outarg.attr);
}
}
}
@@ -2102,13 +2104,24 @@
fuse_getcontext = func;
}
+static int begins_with(const char *s, const char *beg)
+{
+ if (strncmp(s, beg, strlen(beg)) == 0)
+ return 1;
+ else
+ return 0;
+}
+
int fuse_is_lib_option(const char *opt)
{
if (strcmp(opt, "debug") == 0 ||
strcmp(opt, "hard_remove") == 0 ||
strcmp(opt, "use_ino") == 0 ||
strcmp(opt, "allow_root") == 0 ||
- strcmp(opt, "readdir_ino") == 0)
+ strcmp(opt, "readdir_ino") == 0 ||
+ begins_with(opt, "umask=") ||
+ begins_with(opt, "uid=") ||
+ begins_with(opt, "gid="))
return 1;
else
return 0;
@@ -2137,6 +2150,12 @@
f->flags |= FUSE_ALLOW_ROOT;
else if (strcmp(opt, "readdir_ino") == 0)
f->flags |= FUSE_READDIR_INO;
+ else if (sscanf(opt, "umask=%o", &f->umask) == 1)
+ f->flags |= FUSE_SET_MODE;
+ else if (sscanf(opt, "uid=%u", &f->uid) == 1)
+ f->flags |= FUSE_SET_UID;
+ else if(sscanf(opt, "gid=%u", &f->gid) == 1)
+ f->flags |= FUSE_SET_GID;
else
fprintf(stderr, "fuse: warning: unknown option `%s'\n", opt);
}
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 99a35de..43680d9 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -38,6 +38,9 @@
int major;
int minor;
uid_t owner;
+ uid_t uid;
+ gid_t gid;
+ mode_t umask;
};
struct fuse *fuse_new_common(int fd, const char *opts,
diff --git a/lib/helper.c b/lib/helper.c
index 460bea2..0d6e5b2 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -47,6 +47,9 @@
" use_ino let filesystem set inode numbers\n"
" readdir_ino try to fill in d_ino in readdir\n"
" nonempty allow mounts over non-empty file/dir\n"
+ " umask=M set file permissions (octal)\n"
+ " uid=N set file owner\n"
+ " gid=N set file group\n"
);
}