From c50f370f98e5f5d24d18ca3df444770dacce1824 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 24 Nov 2006 14:57:31 +0000 Subject: tar: cache [ug]id->username/groupname mappings. Cuts down amount of open/read/close of /etc/passwd and /etc/group dramatically (we were rereading those for each untarred file!!!) --- archival/tar.c | 9 +++----- include/libbb.h | 1 + libbb/procps.c | 66 +++++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/archival/tar.c b/archival/tar.c index 99c4adb6a..51d34ea19 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -211,12 +211,9 @@ static int writeTarHeader(struct TarBallInfo *tbInfo, putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); strcpy(header.magic, "ustar "); - /* Enter the user and group names (default to root if it fails) */ -//cache!!! - if (bb_getpwuid(header.uname, statbuf->st_uid, sizeof(header.uname)) == NULL) - strcpy(header.uname, "root"); - if (bb_getgrgid(header.gname, statbuf->st_gid, sizeof(header.gname)) == NULL) - strcpy(header.gname, "root"); + /* Enter the user and group names */ + safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname)); + safe_strncpy(header.gname, get_cached_groupname(statbuf->st_gid), sizeof(header.gname)); if (tbInfo->hlInfo) { /* This is a hard link */ diff --git a/include/libbb.h b/include/libbb.h index 582e34f52..99a1928df 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -567,6 +567,7 @@ pid_t *find_pid_by_name(const char* procName); pid_t *pidlist_reverse(pid_t *pidList); void clear_username_cache(void); const char* get_cached_username(uid_t uid); +const char* get_cached_groupname(gid_t gid); extern const char bb_uuenc_tbl_base64[]; diff --git a/libbb/procps.c b/libbb/procps.c index dee5638e4..52203ee9a 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -11,32 +11,62 @@ #include "libbb.h" -typedef struct { - uid_t uid; - char username[12]; -} user_map_t; +typedef struct unsigned_to_name_map_t { + unsigned id; + char name[12]; +} unsigned_to_name_map_t; -static user_map_t *username_cache; -static int username_cache_size; +typedef struct cache_t { + unsigned_to_name_map_t *cache; + int size; +} cache_t; +static cache_t username, groupname; + +static void clear_cache(cache_t *cp) +{ + free(cp->cache); + cp->cache = NULL; + cp->size = 0; +} void clear_username_cache(void) { - free(username_cache); - username_cache = NULL; - username_cache_size = 0; + clear_cache(&username); + clear_cache(&groupname); } -const char* get_cached_username(uid_t uid) +/* Returns -N-1 if not found. */ +/* cp->cache[N] is allocated and must be filled in this case */ +static int get_cached(cache_t *cp, unsigned id) { int i; - for (i = 0; i < username_cache_size; i++) - if (username_cache[i].uid == uid) - return username_cache[i].username; - i = username_cache_size++; - username_cache = xrealloc(username_cache, username_cache_size * sizeof(*username_cache)); - username_cache[i].uid = uid; - bb_getpwuid(username_cache[i].username, uid, sizeof(username_cache[i].username)); - return username_cache[i].username; + for (i = 0; i < cp->size; i++) + if (cp->cache[i].id == id) + return i; + i = cp->size++; + cp->cache = xrealloc(cp->cache, cp->size * sizeof(*cp->cache)); + cp->cache[i++].id = id; + return -i; +} +const char* get_cached_username(uid_t uid) +{ + int i = get_cached(&username, uid); + if (i < 0) { + i = -i - 1; + bb_getpwuid(username.cache[i].name, uid, + sizeof(username.cache[i].name)); + } + return username.cache[i].name; +} +const char* get_cached_groupname(uid_t uid) +{ + int i = get_cached(&groupname, uid); + if (i < 0) { + i = -i - 1; + bb_getgrgid(groupname.cache[i].name, uid, + sizeof(groupname.cache[i].name)); + } + return username.cache[i].name; } -- cgit v1.2.3