diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2009-06-19 10:27:38 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2009-06-19 10:27:38 +0000 |
commit | ecd073bd7054c9e13516041e3ef930e39270c8df (patch) | |
tree | bb36abf9662bec5c5027363f6d0d902d00f40815 /lib | |
parent | 17d1cf6956d08de9aa79b4a7691fb50a2446fa18 (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.c | 6 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 68 | ||||
-rw-r--r-- | lib/fuse_versionscript | 2 |
3 files changed, 76 insertions, 0 deletions
@@ -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: *; |