-
-
Save ilwsm/d0d770cdb85e5b80a552 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * getgrnam_r() implementation for Android NDK | |
| * | |
| * Copyright (c) 2015 may safely be consumed by a BSD or GPL license. | |
| * Written by: Vladimir Oleynik <[email protected]> | |
| * | |
| */ | |
| #include <sys/types.h> | |
| #include <grp.h> | |
| #include <string.h> | |
| #include <errno.h> | |
| static size_t add_aligned(size_t sz) | |
| { | |
| if((sz & (sizeof(char *) - 1)) == 0) | |
| return sz; | |
| sz |= sizeof(char *) - 1; | |
| return sz + 1; | |
| } | |
| static size_t gav(const char *val) | |
| { | |
| if(val != NULL) | |
| return add_aligned(strlen(val) + 1); | |
| return 0; | |
| } | |
| static void *set_field(char **pf, const char *val, char *buf) | |
| { | |
| if(val != NULL) { | |
| size_t sz = strlen(val) + 1; | |
| return memcpy(*pf = buf, val, sz) + add_aligned(sz); | |
| } else { | |
| *pf = NULL; | |
| return buf; | |
| } | |
| } | |
| int getgrnam_r(const char *name, struct group *grp, | |
| char *buf, size_t buflen, struct group **result) | |
| { | |
| size_t real_sz; | |
| struct group *r, *g = getgrnam(name); | |
| char **gm; | |
| void *v; | |
| int membr; | |
| if(g == NULL) | |
| return -1; | |
| real_sz = sizeof(struct group) + gav(g->gr_name) + gav(g->gr_passwd); | |
| membr = 0; | |
| if(g->gr_mem != NULL) { | |
| for(gm = g->gr_mem; ; gm++) { | |
| size_t sz1 = gav(*gm); | |
| membr++; /* need NULL always */ | |
| if(sz1 == 0) | |
| break; | |
| real_sz += sz1; | |
| } | |
| real_sz += membr * sizeof(char *); | |
| } | |
| if(real_sz > buflen) { | |
| errno = ERANGE; | |
| return -1; | |
| } | |
| r = v = buf; | |
| v = set_field(&r->gr_name, g->gr_name, (char *)(r + 1)); | |
| v = set_field(&r->gr_passwd, g->gr_passwd, v); | |
| r->gr_gid = g->gr_gid; | |
| if(g->gr_mem != NULL) { | |
| r->gr_mem = v; | |
| v = ((char *)v) + (membr * sizeof(char *)); | |
| for(membr = 0, gm = g->gr_mem; ; gm++, membr++) { | |
| void *v2; | |
| if((v2 = set_field(&r->gr_mem[membr], *gm, v)) == v) | |
| break; | |
| v = v2; | |
| } | |
| } else { | |
| r->gr_mem = NULL; | |
| } | |
| *result = memcpy(grp, r, sizeof(struct group)); | |
| return 0; | |
| } | |
| #ifdef TEST | |
| #include <stdio.h> | |
| int main(int argc, char **argv) | |
| { | |
| struct group g, *r; | |
| char buf[1024]; | |
| char **gm; | |
| int m = 0; | |
| if(argc != 2) { | |
| printf("Usage: %s group\n", argv[0]); | |
| return 2; | |
| } | |
| if(getgrnam_r(argv[1], &g, buf, sizeof(buf), &r) != 0) { | |
| perror("getgrnam_r"); | |
| return 1; | |
| } | |
| printf("group = %s\n", g.gr_name); | |
| printf("group_pass = %s\n", g.gr_passwd); | |
| for(gm = r->gr_mem; *gm != NULL; gm++) { | |
| printf("member[%d] = %s\n", m, *gm); | |
| m++; | |
| } | |
| return 0; | |
| } | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment