From 254780ab3b0db398447150251332916598d3b9f4 Mon Sep 17 00:00:00 2001
From: Richard Purdie <richard.purdie@linuxfoundation.org>
Date: Fri, 11 Nov 2011 17:17:01 +0000
Subject: [PATCH 2/7] Ensure we use the uname/gname fields when extracting
 tarballs

When updating packages on the target device we ideally want to match
user and group numbers from the existing file system. This patch encourages
opkg to lookup the uname/gname fields first and only use the hardcoded
numerical values if that fails.

Upstream-Status: Submitted
http://code.google.com/p/opkg/issues/detail?id=93

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
---
 libbb/unarchive.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/libbb/unarchive.c b/libbb/unarchive.c
index 5d4464f..d583767 100644
--- a/libbb/unarchive.c
+++ b/libbb/unarchive.c
@@ -22,10 +22,13 @@
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
 #include <utime.h>
 #include <libgen.h>
+#include <grp.h>
+#include <pwd.h>
 
 #include "libbb.h"
 
@@ -436,6 +439,42 @@ free_header_ar(file_header_t *ar_entry)
 	free(ar_entry);
 }
 
+static char uname_cache[32] = "";
+static uid_t uid_cache;
+
+static bool update_unamecache(char *uname) {
+	struct passwd *passwd;
+	if (!uname)
+		return FALSE;
+	if (!uname_cache[0] && strcmp(uname_cache, uname) == 0)
+		return TRUE;
+	passwd = getpwnam(uname);
+	if (passwd) {
+		uid_cache = passwd->pw_uid;
+		strncpy(uname, uname_cache, 32);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static char gname_cache[32] = "";
+static gid_t gid_cache;
+
+static bool update_gnamecache(char *gname) {
+	struct group *group;
+	if (!gname)
+		return FALSE;
+	if (!gname_cache[0] && strcmp(gname_cache, gname) == 0)
+		return TRUE;
+	group = getgrnam(gname);
+	if (group) {
+		gid_cache = group->gr_gid;
+		strncpy(gname, gname_cache, 32);
+		return TRUE;
+	}
+	return FALSE;
+}
+
 
 static file_header_t *
 get_header_tar(FILE *tar_stream)
@@ -515,8 +554,14 @@ get_header_tar(FILE *tar_stream)
 */
         tar_entry->mode = 07777 & strtol(tar.formated.mode, NULL, 8);
 
-	tar_entry->uid   = strtol(tar.formated.uid, NULL, 8);
-	tar_entry->gid   = strtol(tar.formated.gid, NULL, 8);
+	if (update_unamecache(tar.formated.uname))
+		tar_entry->uid = uid_cache;
+	else
+		tar_entry->uid = strtol(tar.formated.uid, NULL, 8);
+	if (update_gnamecache(tar.formated.gname))
+		tar_entry->gid = gid_cache;
+	else
+		tar_entry->gid = strtol(tar.formated.gid, NULL, 8);
 	tar_entry->size  = strtol(tar.formated.size, NULL, 8);
 	tar_entry->mtime = strtol(tar.formated.mtime, NULL, 8);
 
-- 
1.7.12

