Skip to content

Instantly share code, notes, and snippets.

@ilwsm
Created March 28, 2015 11:50
Show Gist options
  • Save ilwsm/d0d770cdb85e5b80a552 to your computer and use it in GitHub Desktop.
Save ilwsm/d0d770cdb85e5b80a552 to your computer and use it in GitHub Desktop.
/*
* 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