about summary refs log tree commit diff
path: root/lr.c
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2015-10-23 00:24:30 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2015-10-23 00:24:30 +0200
commit1ddb887fac3e7d36f09e094c722240414ccdd7f0 (patch)
treea8ee26cc6d442f51a9cf1abb59d51b297eb0f89b /lr.c
parent9d4a399a29f1eb97bb6495e09adc0c3168eb15d8 (diff)
downloadlr-1ddb887fac3e7d36f09e094c722240414ccdd7f0.tar.gz
lr-1ddb887fac3e7d36f09e094c722240414ccdd7f0.tar.xz
lr-1ddb887fac3e7d36f09e094c722240414ccdd7f0.zip
cache user/group lookups
Diffstat (limited to 'lr.c')
-rw-r--r--lr.c101
1 files changed, 85 insertions, 16 deletions
diff --git a/lr.c b/lr.c
index aab2d90..f6d3a94 100644
--- a/lr.c
+++ b/lr.c
@@ -12,6 +12,7 @@ TODO:
 - avoid stat in recurse
 - multiple -t
 - don't default to ./ prefix
+- %m %y
 */
 
 #define _GNU_SOURCE
@@ -46,7 +47,15 @@ struct expr *e;
 void *root = NULL; // tree
 static int prune;
 
-int maxlinks, maxsize, uwid = 8, gwid = 8;
+void *users;
+void *groups;
+
+struct idmap {
+	long id;
+	char *name;
+};
+
+int maxlinks, maxsize, uwid, gwid;
 
 struct fileinfo {
 	char *fpath;
@@ -531,6 +540,75 @@ order(const void *a, const void *b)
 	return strcmp(fa->fpath, fb->fpath);
 }
 
+int
+idorder(const void *a, const void *b)
+{
+	struct idmap *ia = (struct idmap *) a;
+	struct idmap *ib = (struct idmap *) b;
+
+	if (ia->id == ib->id)
+		return 0;
+	else if (ia->id < ib->id)
+		return -1;
+	else
+		return 1;
+}
+
+char *
+groupname(gid_t gid)
+{
+	struct idmap key, **result;
+	key.id = gid;
+	key.name = 0;
+
+	if (!(result = tfind(&key, &groups, idorder))) {
+		struct group *g = getgrgid(gid);
+		if (g) {
+			struct idmap *newkey = malloc (sizeof (struct idmap));
+			newkey->id = gid;
+			newkey->name = strdup(g->gr_name);
+			if (strlen(g->gr_name) > gwid)
+				gwid = strlen(g->gr_name);
+			tsearch(newkey, &groups, idorder);
+			return newkey->name;
+		}
+	}
+
+	return (*result)->name;
+}
+
+char *
+username(uid_t uid)
+{
+	struct idmap key, **result;
+	key.id = uid;
+	key.name = 0;
+
+	if (!(result = tfind(&key, &users, idorder))) {
+		struct passwd *p = getpwuid(uid);
+		if (p) {
+			struct idmap *newkey = malloc (sizeof (struct idmap));
+			newkey->id = uid;
+			newkey->name = strdup(p->pw_name);
+			if (strlen(p->pw_name) > uwid)
+				uwid = strlen(p->pw_name);
+			tsearch(newkey, &users, idorder);
+			return newkey->name;
+		}
+	}
+
+	return (*result)->name;
+}
+
+int
+intlen(int i)
+{
+	int s;
+	for (s = 1; i > 9; i /= 10)
+		s++;
+	return s;
+}
+
 void
 print(const void *nodep, const VISIT which, const int depth)
 {
@@ -603,9 +681,9 @@ print(const void *nodep, const VISIT which, const int depth)
 
 				case 'g':
 					{
-						struct group *g = getgrgid(fi->sb.st_gid);
-						if (g) {
-							printf("%*s", -gwid, g->gr_name);
+						char *s = groupname(fi->sb.st_gid);
+						if (s) {
+							printf("%*s", -gwid, s);
 							break;
 						}
 						/* FALLTHRU */
@@ -616,9 +694,9 @@ print(const void *nodep, const VISIT which, const int depth)
 
 				case 'u':
 					{
-						struct passwd *p = getpwuid(fi->sb.st_uid);
-						if (p) {
-							printf("%*s", -uwid, p->pw_name);
+						char *s = username(fi->sb.st_uid);
+						if (s) {
+							printf("%*s", -uwid, s);
 							break;
 						}
 						/* FALLTHRU */
@@ -639,15 +717,6 @@ print(const void *nodep, const VISIT which, const int depth)
 }
 
 int
-intlen (int i)
-{
-  int s;
-  for (s = 1; i > 9; i /= 10)
-	  s++;
-  return s;
-}
-
-int
 callback(const char *fpath, const struct stat *sb, int depth)
 {
 	struct fileinfo *fi = malloc (sizeof (struct fileinfo));