#include #include #include #include #include #include "idmap.h" struct idMap_s { struct idElement * byId; int numEntries; }; typedef struct idMap_s * idMap; struct idElement { long int id; char * name; }; typedef void * (*iterFn)(void); typedef int (*infoFn)(void * item, struct idElement * el); static idMap uidMap = NULL; static idMap gidMap = NULL; static int idCmp(const void * a, const void * b) { const struct idElement * one = a; const struct idElement * two = b; if (one->id < two->id) return -1; else if (one->id > two->id) return 1; return 0; } static idMap readmap(iterFn fn, infoFn info) { idMap map; int alloced; void * res; struct idElement * newEntries; map = malloc(sizeof(*map)); if (!map) { return NULL; } alloced = 5; map->byId = malloc(sizeof(*map->byId) * alloced); if (!map->byId) { free(map); return NULL; } map->numEntries = 0; while ((res = fn())) { if (map->numEntries == alloced) { alloced += 5; newEntries = realloc(map->byId, sizeof(*map->byId) * alloced); if (!newEntries) { /* FIXME: this doesn't free the id names */ free(map->byId); free(map); return NULL; } map->byId = newEntries; } if (info(res, map->byId + map->numEntries++)) { /* FIXME: this doesn't free the id names */ free(map->byId); free(map); return NULL; } } map->byId = realloc(map->byId, sizeof(*map->byId) * map->numEntries); qsort(map->byId, map->numEntries, sizeof(*map->byId), idCmp); return map; } static int pwInfo(struct passwd * pw, struct idElement * el) { el->id = pw->pw_uid; el->name = strdup(pw->pw_name); return el->name == NULL; } static int grInfo(struct group * gr, struct idElement * el) { el->id = gr->gr_gid; el->name = strdup(gr->gr_name); return el->name == NULL; } idMap readUIDmap(void) { idMap result; result = readmap((void *) getpwent, (void *) pwInfo); endpwent(); return result; } idMap readGIDmap(void) { idMap result; result = readmap((void *) getgrent, (void *) grInfo); endgrent(); return result; } char * idSearchByUid(long int id) { struct idElement el = { id, NULL }; struct idElement * match; match = bsearch(&el, uidMap->byId, uidMap->numEntries, sizeof(*uidMap->byId), idCmp); if (match) return match->name; else return NULL; } char * idSearchByGid(long int id) { struct idElement el = { id, NULL }; struct idElement * match; match = bsearch(&el, gidMap->byId, gidMap->numEntries, sizeof(*gidMap->byId), idCmp); if (match) return match->name; else return NULL; } int idInit(void) { if (!(uidMap = readUIDmap())) return 1; if (!(gidMap = readGIDmap())) return 1; return 0; }