aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2009-06-19 10:27:38 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2009-06-19 10:27:38 +0000
commitecd073bd7054c9e13516041e3ef930e39270c8df (patch)
treebb36abf9662bec5c5027363f6d0d902d00f40815 /lib
parent17d1cf6956d08de9aa79b4a7691fb50a2446fa18 (diff)
Add fuse_getgroups (high level lib) and fuse_req_getgroups (low
level lib) functions to query the supplementary group IDs for the current request. Currently this is implemented on Linux by reading from the /proc filesystem.
Diffstat (limited to 'lib')
-rw-r--r--lib/fuse.c6
-rw-r--r--lib/fuse_lowlevel.c68
-rw-r--r--lib/fuse_versionscript2
3 files changed, 76 insertions, 0 deletions
diff --git a/lib/fuse.c b/lib/fuse.c
index 9267ca6..dad9a71 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -3450,6 +3450,12 @@ struct fuse_context *fuse_get_context(void)
return &fuse_get_context_internal()->ctx;
}
+int fuse_getgroups(int size, gid_t list[])
+{
+ fuse_req_t req = fuse_get_context_internal()->req;
+ return fuse_req_getgroups(req, size, list);
+}
+
int fuse_interrupted(void)
{
return fuse_req_interrupted(fuse_get_context_internal()->req);
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index a60c5b8..89e8f2f 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -1575,6 +1575,74 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
return fuse_lowlevel_new_common(args, op, op_size, userdata);
}
+#ifdef linux
+int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
+{
+ char *buf;
+ size_t bufsize = 1024;
+ char path[128];
+ int ret;
+ int fd;
+ unsigned long pid = req->ctx.pid;
+ char *s;
+
+ sprintf(path, "/proc/%lu/task/%lu/status", pid, pid);
+
+retry:
+ buf = malloc(bufsize);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ ret = -EIO;
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ goto out_free;
+
+ ret = read(fd, buf, bufsize);
+ close(fd);
+ if (ret == -1) {
+ ret = -EIO;
+ goto out_free;
+ }
+
+ if (ret == bufsize) {
+ free(buf);
+ bufsize *= 4;
+ goto retry;
+ }
+
+ ret = -EIO;
+ s = strstr(buf, "\nGroups:");
+ if (s == NULL)
+ goto out_free;
+
+ s += 8;
+ ret = 0;
+ while (1) {
+ char *end;
+ unsigned long val = strtoul(s, &end, 0);
+ if (end == s)
+ break;
+
+ s = end;
+ if (ret < size)
+ list[ret] = val;
+ ret++;
+ }
+
+out_free:
+ free(buf);
+ return ret;
+}
+#else /* linux */
+/*
+ * This is currently not implemented on other than Linux...
+ */
+int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]);
+{
+ return -ENOSYS;
+}
+#endif
#ifndef __FreeBSD__
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 4cd09aa..463c74f 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -174,6 +174,8 @@ FUSE_2.8 {
fuse_reply_ioctl_iov;
fuse_reply_ioctl_retry;
fuse_reply_poll;
+ fuse_req_getgroups;
+ fuse_getgroups;
local:
*;