Index: fusl/src/passwd/getgrouplist.c |
diff --git a/fusl/src/passwd/getgrouplist.c b/fusl/src/passwd/getgrouplist.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..43e518245f8e6bfdafdbdb2ff5aec92a247798e4 |
--- /dev/null |
+++ b/fusl/src/passwd/getgrouplist.c |
@@ -0,0 +1,80 @@ |
+#define _GNU_SOURCE |
+#include "pwf.h" |
+#include <grp.h> |
+#include <string.h> |
+#include <limits.h> |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <byteswap.h> |
+#include <errno.h> |
+#include "nscd.h" |
+ |
+int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) |
+{ |
+ int rv, nlim, ret = -1; |
+ ssize_t i, n = 1; |
+ struct group gr; |
+ struct group *res; |
+ FILE *f; |
+ int swap = 0; |
+ int32_t resp[INITGR_LEN]; |
+ uint32_t *nscdbuf = 0; |
+ char *buf = 0; |
+ char **mem = 0; |
+ size_t nmem = 0; |
+ size_t size; |
+ nlim = *ngroups; |
+ if (nlim >= 1) *groups++ = gid; |
+ |
+ f = __nscd_query(GETINITGR, user, resp, sizeof resp, &swap); |
+ if (!f) goto cleanup; |
+ if (resp[INITGRFOUND]) { |
+ nscdbuf = calloc(resp[INITGRNGRPS], sizeof(uint32_t)); |
+ if (!nscdbuf) goto cleanup; |
+ if (!fread(nscdbuf, sizeof(*nscdbuf)*resp[INITGRNGRPS], 1, f)) { |
+ if (!ferror(f)) errno = EIO; |
+ goto cleanup; |
+ } |
+ if (swap) { |
+ for (i = 0; i < resp[INITGRNGRPS]; i++) |
+ nscdbuf[i] = bswap_32(nscdbuf[i]); |
+ } |
+ } |
+ fclose(f); |
+ |
+ f = fopen("/etc/group", "rbe"); |
+ if (!f && errno != ENOENT && errno != ENOTDIR) |
+ goto cleanup; |
+ |
+ if (f) { |
+ while (!(rv = __getgrent_a(f, &gr, &buf, &size, &mem, &nmem, &res)) && res) { |
+ if (nscdbuf) |
+ for (i=0; i < resp[INITGRNGRPS]; i++) { |
+ if (nscdbuf[i] == gr.gr_gid) nscdbuf[i] = gid; |
+ } |
+ for (i=0; gr.gr_mem[i] && strcmp(user, gr.gr_mem[i]); i++); |
+ if (!gr.gr_mem[i]) continue; |
+ if (++n <= nlim) *groups++ = gr.gr_gid; |
+ } |
+ if (rv) { |
+ errno = rv; |
+ goto cleanup; |
+ } |
+ } |
+ if (nscdbuf) { |
+ for(i=0; i < resp[INITGRNGRPS]; i++) { |
+ if (nscdbuf[i] != gid) |
+ if(++n <= nlim) *groups++ = nscdbuf[i]; |
+ } |
+ } |
+ |
+ ret = n > nlim ? -1 : n; |
+ *ngroups = n; |
+ |
+cleanup: |
+ if (f) fclose(f); |
+ free(nscdbuf); |
+ free(buf); |
+ free(mem); |
+ return ret; |
+} |