+typedef struct unsigned_to_name_map_t {
+ long id;
+ char name[USERNAME_MAX_SIZE];
+} unsigned_to_name_map_t;
+
+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 FAST_FUNC clear_username_cache(void)
+{
+ clear_cache(&username);
+ clear_cache(&groupname);
+}
+
+#if 0 /* more generic, but we don't need that yet */
+/* 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 < cp->size; i++)
+ if (cp->cache[i].id == id)
+ return i;
+ i = cp->size++;
+ cp->cache = xrealloc_vector(cp->cache, 2, i);
+ cp->cache[i++].id = id;
+ return -i;
+}
+#endif
+
+static char* get_cached(cache_t *cp, long id,
+ char* FAST_FUNC x2x_utoa(long id))
+{
+ int i;
+ for (i = 0; i < cp->size; i++)
+ if (cp->cache[i].id == id)
+ return cp->cache[i].name;
+ i = cp->size++;
+ cp->cache = xrealloc_vector(cp->cache, 2, i);
+ cp->cache[i].id = id;
+ /* Never fails. Generates numeric string if name isn't found */
+ safe_strncpy(cp->cache[i].name, x2x_utoa(id), sizeof(cp->cache[i].name));
+ return cp->cache[i].name;
+}
+const char* FAST_FUNC get_cached_username(uid_t uid)
+{
+ return get_cached(&username, uid, uid2uname_utoa);
+}
+const char* FAST_FUNC get_cached_groupname(gid_t gid)
+{
+ return get_cached(&groupname, gid, gid2group_utoa);
+}
+
+