From 04a5cb58b62598b86173a03af8e900d58f2bfed1 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 27 Nov 2015 13:56:01 +0100 Subject: [PATCH] namei: move icache to lib/ Signed-off-by: Karel Zak --- include/idcache.h | 28 ++++++++++ lib/Makemodule.am | 1 + lib/idcache.c | 113 +++++++++++++++++++++++++++++++++++++++ misc-utils/Makemodule.am | 2 +- misc-utils/namei.c | 111 +++++--------------------------------- 5 files changed, 156 insertions(+), 99 deletions(-) create mode 100644 include/idcache.h create mode 100644 lib/idcache.c diff --git a/include/idcache.h b/include/idcache.h new file mode 100644 index 000000000..912edd58f --- /dev/null +++ b/include/idcache.h @@ -0,0 +1,28 @@ +#ifndef UTIL_LINUX_IDCACHE_H +#define UTIL_LINUX_IDCACHE_H + +#include +#include + +#define IDCACHE_FLAGS_NAMELEN (1 << 1) + +struct identry { + unsigned long int id; + char *name; + struct identry *next; +}; + +struct idcache { + struct identry *ent; /* first entry */ + int width; /* name width */ +}; + + +extern struct idcache *new_idcache(void); +extern void add_gid(struct idcache *cache, unsigned long int id); +extern void add_uid(struct idcache *cache, unsigned long int id); + +extern void free_idcache(struct idcache *ic); +extern struct identry *get_id(struct idcache *ic, unsigned long int id); + +#endif /* UTIL_LINUX_IDCACHE_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index ae0443ea7..8e1fea25e 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -8,6 +8,7 @@ libcommon_la_SOURCES = \ lib/crc32.c \ lib/crc64.c \ lib/env.c \ + lib/idcache.c \ lib/fileutils.c \ lib/ismounted.c \ lib/color-names.c \ diff --git a/lib/idcache.c b/lib/idcache.c new file mode 100644 index 000000000..4cb20fd2d --- /dev/null +++ b/lib/idcache.c @@ -0,0 +1,113 @@ + +#include +#include +#include +#include + +#include "c.h" +#include "idcache.h" + +struct identry *get_id(struct idcache *ic, unsigned long int id) +{ + struct identry *ent; + + if (!ic) + return NULL; + + for (ent = ic->ent; ent; ent = ent->next) { + if (ent->id == id) + return ent; + } + + return NULL; +} + +struct idcache *new_idcache() +{ + return calloc(1, sizeof(struct idcache)); +} + +void free_idcache(struct idcache *ic) +{ + struct identry *ent = ic->ent; + + while (ent) { + struct identry *next = ent->next; + free(ent->name); + free(ent); + ent = next; + } + + free(ic); +} + +static void add_id(struct idcache *ic, char *name, unsigned long int id) +{ + struct identry *ent, *x; + int w = 0; + + ent = calloc(1, sizeof(struct identry)); + if (!ent) + return; + ent->id = id; + + if (name) { +#ifdef HAVE_WIDECHAR + wchar_t wc[LOGIN_NAME_MAX + 1]; + + if (mbstowcs(wc, name, LOGIN_NAME_MAX) > 0) { + wc[LOGIN_NAME_MAX] = '\0'; + w = wcswidth(wc, LOGIN_NAME_MAX); + } + else +#endif + w = strlen(name); + } + + /* note, we ignore names with non-printable widechars */ + if (w > 0) { + ent->name = strdup(name); + if (!ent->name) { + free(ent); + return; + } + } else { + if (asprintf(&ent->name, "%lu", id) < 0) { + free(ent); + return; + } + } + + for (x = ic->ent; x && x->next; x = x->next); + + if (x) + x->next = ent; + else + ic->ent = ent; + + if (w <= 0) + w = ent->name ? strlen(ent->name) : 0; + ic->width = ic->width < w ? w : ic->width; + return; +} + +void add_uid(struct idcache *cache, unsigned long int id) +{ + struct identry *ent= get_id(cache, id); + + if (!ent) { + struct passwd *pw = getpwuid((uid_t) id); + add_id(cache, pw ? pw->pw_name : NULL, id); + } +} + +void add_gid(struct idcache *cache, unsigned long int id) +{ + struct identry *ent = get_id(cache, id); + + if (!ent) { + struct group *gr = getgrgid((gid_t) id); + add_id(cache, gr ? gr->gr_name : NULL, id); + } +} + diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am index e7949d053..f2aa881df 100644 --- a/misc-utils/Makemodule.am +++ b/misc-utils/Makemodule.am @@ -50,7 +50,7 @@ endif if BUILD_NAMEI usrbin_exec_PROGRAMS += namei dist_man_MANS += misc-utils/namei.1 -namei_SOURCES = misc-utils/namei.c lib/strutils.c +namei_SOURCES = misc-utils/namei.c lib/strutils.c lib/idcache.c endif if BUILD_WHEREIS diff --git a/misc-utils/namei.c b/misc-utils/namei.c index 15bec9960..41557cac3 100644 --- a/misc-utils/namei.c +++ b/misc-utils/namei.c @@ -38,6 +38,7 @@ #include "widechar.h" #include "strutils.h" #include "closestream.h" +#include "idcache.h" #ifndef MAXSYMLINKS #define MAXSYMLINKS 256 @@ -65,103 +66,10 @@ struct namei { int noent; /* is this item not existing */ }; -struct idcache { - unsigned long int id; - char *name; - struct idcache *next; -}; - static int flags; -static int uwidth; /* maximal width of username */ -static int gwidth; /* maximal width of groupname */ static struct idcache *gcache; /* groupnames */ static struct idcache *ucache; /* usernames */ -static struct idcache * -get_id(struct idcache *ic, unsigned long int id) -{ - while(ic) { - if (ic->id == id) - return ic; - ic = ic->next; - } - return NULL; -} - -static void -free_idcache(struct idcache *ic) -{ - while(ic) { - struct idcache *next = ic->next; - free(ic->name); - free(ic); - ic = next; - } -} - -static void -add_id(struct idcache **ic, char *name, unsigned long int id, int *width) -{ - struct idcache *nc, *x; - int w = 0; - - nc = xcalloc(1, sizeof(*nc)); - nc->id = id; - - if (name) { -#ifdef HAVE_WIDECHAR - wchar_t wc[LOGIN_NAME_MAX + 1]; - - if (mbstowcs(wc, name, LOGIN_NAME_MAX) > 0) { - wc[LOGIN_NAME_MAX] = '\0'; - w = wcswidth(wc, LOGIN_NAME_MAX); - } - else -#endif - w = strlen(name); - } - /* note, we ignore names with non-printable widechars */ - if (w > 0) - nc->name = xstrdup(name); - else - xasprintf(&nc->name, "%lu", id); - - for (x = *ic; x && x->next; x = x->next); - - /* add 'nc' at end of the 'ic' list */ - if (x) - x->next = nc; - else - *ic = nc; - if (w <= 0) - w = nc->name ? strlen(nc->name) : 0; - - *width = *width < w ? w : *width; - return; -} - -static void -add_uid(unsigned long int id) -{ - struct idcache *ic = get_id(ucache, id); - - if (!ic) { - struct passwd *pw = getpwuid((uid_t) id); - add_id(&ucache, pw ? pw->pw_name : NULL, id, &uwidth); - } -} - -static void -add_gid(unsigned long int id) -{ - struct idcache *ic = get_id(gcache, id); - - if (!ic) { - struct group *gr = getgrgid((gid_t) id); - add_id(&gcache, gr ? gr->gr_name : NULL, id, &gwidth); - } -} - static void free_namei(struct namei *nm) { @@ -254,8 +162,8 @@ new_namei(struct namei *parent, const char *path, const char *fname, int lev) if (S_ISLNK(nm->st.st_mode)) readlink_to_namei(nm, path); if (flags & NAMEI_OWNERS) { - add_uid(nm->st.st_uid); - add_gid(nm->st.st_gid); + add_uid(ucache, nm->st.st_uid); + add_gid(gcache, nm->st.st_gid); } if ((flags & NAMEI_MNTS) && S_ISDIR(nm->st.st_mode)) { @@ -371,7 +279,7 @@ print_namei(struct namei *nm, char *path) if (flags & NAMEI_MODES) blanks += 9; if (flags & NAMEI_OWNERS) - blanks += uwidth + gwidth + 2; + blanks += ucache->width + gcache->width + 2; if (!(flags & NAMEI_VERTICAL)) blanks += 1; blanks += nm->level * 2; @@ -397,9 +305,9 @@ print_namei(struct namei *nm, char *path) printf("%c", md[0]); if (flags & NAMEI_OWNERS) { - printf(" %-*s", uwidth, + printf(" %-*s", ucache->width, get_id(ucache, nm->st.st_uid)->name); - printf(" %-*s", gwidth, + printf(" %-*s", gcache->width, get_id(gcache, nm->st.st_gid)->name); } @@ -505,6 +413,13 @@ main(int argc, char **argv) usage(EXIT_FAILURE); } + ucache = new_idcache(); + if (!ucache) + err(EXIT_FAILURE, _("failed to allocate UID cache")); + gcache = new_idcache(); + if (!gcache) + err(EXIT_FAILURE, _("failed to allocate GID cache")); + for(; optind < argc; optind++) { char *path = argv[optind]; struct namei *nm = NULL;