--- nss_updatedb-4/main.c.fred 2005-05-22 10:21:27.000000000 +0200 +++ nss_updatedb-4/main.c 2005-11-29 15:00:22.000000000 +0100 @@ -14,7 +14,7 @@ static void usage(void) { - fprintf(stderr, "Usage: nss_updatedb [nameservice] [passwd|group]\n"); + fprintf(stderr, "Usage: nss_updatedb <nameservice> [passwd|group|both] [<user>|<group>]\n"); exit(NSS_STATUS_UNAVAIL); } @@ -49,8 +49,9 @@ unsigned maps = 0; char *dbname; enum nss_status status; - - if (argc < 2 || argc > 3) { + char *key = NULL; + + if (argc < 2) { usage(); } @@ -60,7 +61,7 @@ exit(NSS_STATUS_UNAVAIL); } - if (argc == 3) { + if (argc == 3 || argc == 4) { char *mapname; mapname = argv[2]; @@ -69,8 +70,12 @@ maps = MAP_PASSWD; else if (strcmp(mapname, "group") == 0) maps = MAP_GROUP; + else if (strcmp(mapname, "both") == 0) + maps = MAP_ALL; else usage(); + + key = argv[3]; } else { maps = MAP_ALL; } @@ -82,7 +87,7 @@ if (maps & MAP_PASSWD) { printf("passwd... "); - status = nss_update_db(handle, MAP_PASSWD, DB_PASSWD); + status = nss_update_db(handle, MAP_PASSWD, DB_PASSWD, key); if (status != NSS_STATUS_SUCCESS) { printf("%s.\n", nss_err2string(status)); exit(status); @@ -92,7 +97,7 @@ if (maps & MAP_GROUP) { printf("group... "); - status = nss_update_db(handle, MAP_GROUP, DB_GROUP); + status = nss_update_db(handle, MAP_GROUP, DB_GROUP, key); if (status != NSS_STATUS_SUCCESS) { printf("%s.\n", nss_err2string(status)); exit(status); --- nss_updatedb-4/updatedb.c.fred 2005-05-22 10:21:27.000000000 +0200 +++ nss_updatedb-4/updatedb.c 2005-11-29 15:57:45.000000000 +0100 @@ -36,6 +36,7 @@ enum nss_status (*setent)(void); enum nss_status (*getent)(void *, char *, size_t, int *); enum nss_status (*endent)(void); + enum nss_status (*getnam)(const char *, void *, char *, size_t, void **); } nss_vtable_t; @@ -122,6 +123,15 @@ return NSS_STATUS_UNAVAIL; } + snprintf(function, sizeof(function), "_nss_%s_get%snam_r", + handle->dbname, prefix); + vtable->getnam = dlsym(handle->dlhandle, function); + if (vtable->endent == NULL) { + fprintf(stderr, "Failed to find symbol %s: %s\n", + function, dlerror()); + return NSS_STATUS_UNAVAIL; + } + return NSS_STATUS_SUCCESS; } @@ -192,9 +202,41 @@ return (status == NSS_STATUS_NOTFOUND) ? NSS_STATUS_SUCCESS : status; } +static enum nss_status _nss_entry(const char *key, + nss_backend_handle_t *handle, + nss_vtable_t *vtable, + enum nss_status (*callback)(nss_backend_handle_t *, void *, void *), + void *private) +{ + enum nss_status status; + union { + struct passwd pw; + struct group gr; + } result; + void *presult; + long len = sysconf(_SC_GETPW_R_SIZE_MAX); + char * buf = malloc(len); + + if (buf == NULL) { + return NSS_STATUS_TRYAGAIN; + } + + status = vtable->getnam(key, &result, buf, len, &presult); + + if (status != NSS_STATUS_SUCCESS) { + fprintf(stderr, "Unable to get entry for %s\n", key); + goto end; + } + status = callback(handle, (void *)&result, private); + end: + free(buf); + return status; +} + enum nss_status nss_update_db(nss_backend_handle_t *handle, unsigned map, - const char *filename) + const char *filename, + const char *key) { enum nss_status (*callback)(nss_backend_handle_t *, void *, void *); nss_vtable_t vtable; @@ -220,7 +262,12 @@ return status; } - status = _nss_enumerate(handle, &vtable, callback, cache); + if (key) { + status = _nss_entry(key, handle, &vtable, callback, cache); + } else { + status = _nss_enumerate(handle, &vtable, callback, cache); + } + if (status == NSS_STATUS_SUCCESS) { status = nss_cache_commit(cache); } else { --- nss_updatedb-4/updatedb.h.fred 2005-05-22 10:21:27.000000000 +0200 +++ nss_updatedb-4/updatedb.h 2005-11-29 14:46:23.000000000 +0100 @@ -36,7 +36,8 @@ enum nss_status nss_update_db(nss_backend_handle_t *handle, unsigned dbname, - const char *filename); + const char *filename, + const char *key); enum nss_status nss_backend_close(nss_backend_handle_t **handle);