[git commit] libpwdgrp: use getpwent() instead of getpwent_r()

Denys Vlasenko vda.linux at googlemail.com
Sat Feb 7 20:21:02 UTC 2015


commit: http://git.busybox.net/busybox/commit/?id=23cfaab47de7392c1ba7d601a05fb36da3629b28
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
massage_data_for_non_r_func                            -      90     +90
bb_internal_getpwent                                   -      69     +69
getXXnam_r                                            94     162     +68
fill_bounds                                          131     128      -3
deluser_main                                         355     310     -45
complete_username                                    123      78     -45
getXXnam                                             163      90     -73
massage_data_for_r_func                              103       -    -103
bb_internal_getpwent_r                               121       -    -121
------------------------------------------------------------------------------
(add/remove: 2/2 grow/shrink: 1/5 up/down: 227/-407)         Total: -163 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 include/pwd_.h       |   16 +-------------
 libbb/lineedit.c     |   13 ++++-------
 libpwdgrp/pwd_grp.c  |   58 +++++++++++++++++++++++++++++++++++++-------------
 loginutils/deluser.c |    9 +++----
 4 files changed, 53 insertions(+), 43 deletions(-)

diff --git a/include/pwd_.h b/include/pwd_.h
index 32b5b36..1734829 100644
--- a/include/pwd_.h
+++ b/include/pwd_.h
@@ -36,7 +36,6 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
 #define getpwent    bb_internal_getpwent
 #define getpwuid    bb_internal_getpwuid
 #define getpwnam    bb_internal_getpwnam
-#define getpwent_r  bb_internal_getpwent_r
 #define getpwnam_r  bb_internal_getpwnam_r
 
 /* All function names below should be remapped by #defines above
@@ -48,10 +47,8 @@ void FAST_FUNC setpwent(void);
 /* Close the password-file stream.  */
 void FAST_FUNC endpwent(void);
 
-#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
 /* Read an entry from the password-file stream, opening it if necessary.  */
 struct passwd* FAST_FUNC getpwent(void);
-#endif
 
 /* Search for an entry with a matching user ID.  */
 struct passwd* FAST_FUNC getpwuid(uid_t __uid);
@@ -59,18 +56,7 @@ struct passwd* FAST_FUNC getpwuid(uid_t __uid);
 /* Search for an entry with a matching username.  */
 struct passwd* FAST_FUNC getpwnam(const char *__name);
 
-/* Reentrant versions of some of the functions above.
-
-   PLEASE NOTE: the `getpwent_r' function is not (yet) standardized.
-   The interface may change in later versions of this library.  But
-   the interface is designed following the principals used for the
-   other reentrant functions so the chances are good this is what the
-   POSIX people would choose.  */
-
-int FAST_FUNC getpwent_r(struct passwd *__restrict __resultbuf,
-		char *__restrict __buffer, size_t __buflen,
-		struct passwd **__restrict __result);
-
+/* Reentrant versions of some of the functions above. */
 int FAST_FUNC getpwnam_r(const char *__restrict __name,
 		struct passwd *__restrict __resultbuf,
 		char *__restrict __buffer, size_t __buflen,
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 720a495..249b401 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -672,23 +672,20 @@ static char *username_path_completion(char *ud)
  */
 static NOINLINE unsigned complete_username(const char *ud)
 {
-	/* Using _r function to avoid pulling in static buffers */
-	char line_buff[256];
-	struct passwd pwd;
-	struct passwd *result;
+	struct passwd *pw;
 	unsigned userlen;
 
 	ud++; /* skip ~ */
 	userlen = strlen(ud);
 
 	setpwent();
-	while (!getpwent_r(&pwd, line_buff, sizeof(line_buff), &result)) {
+	while ((pw = getpwent()) != NULL) {
 		/* Null usernames should result in all users as possible completions. */
-		if (/*!userlen || */ strncmp(ud, pwd.pw_name, userlen) == 0) {
-			add_match(xasprintf("~%s/", pwd.pw_name));
+		if (/*!userlen || */ strncmp(ud, pw->pw_name, userlen) == 0) {
+			add_match(xasprintf("~%s/", pw->pw_name));
 		}
 	}
-	endpwent();
+	endpwent(); /* don't keep password file open */
 
 	return 1 + userlen;
 }
diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c
index 90647e9..7ec704e 100644
--- a/libpwdgrp/pwd_grp.c
+++ b/libpwdgrp/pwd_grp.c
@@ -336,6 +336,22 @@ static int massage_data_for_r_func(struct passdb *db,
 	return errno;
 }
 
+static void* massage_data_for_non_r_func(struct passdb *db, char *buf)
+{
+	if (!buf)
+		return NULL;
+
+	free(db->malloced);
+	/* We enlarge buf and move string data up, freeing space
+	 * for struct passwd/group/spwd at the beginning. This way,
+	 * entire result of getXXnam is in a single malloced block.
+	 * This enables easy creation of xmalloc_getpwnam() API.
+	 */
+	db->malloced = buf = xrealloc(buf, db->size_of + S.string_size);
+	memmove(buf + db->size_of, buf, S.string_size);
+	return convert_to_struct(db, buf + db->size_of, buf);
+}
+
 /****** getXXnam/id_r */
 
 static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos,
@@ -372,6 +388,7 @@ int FAST_FUNC getspnam_r(const char *name, struct spwd *struct_buf, char *buffer
 }
 #endif
 
+#ifdef UNUSED
 /****** getXXent_r */
 
 static int FAST_FUNC getXXent_r(uintptr_t db_idx, char *buffer, size_t buflen,
@@ -400,17 +417,39 @@ int FAST_FUNC getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen,
 	*result = struct_buf;
 	return getXXent_r(0, buffer, buflen, result);
 }
+#endif
+
+/****** getXXent */
+
+static void* FAST_FUNC getXXent(uintptr_t db_idx)
+{
+	char *buf;
+	struct passdb *db = &get_S()->db[db_idx];
+
+	if (!db->fp) {
+		db->fp = fopen_for_read(db->filename);
+		if (!db->fp) {
+			return NULL;
+		}
+		close_on_exec_on(fileno(db->fp));
+	}
+
+	buf = parse_common(db->fp, db, /*no search key:*/ NULL, -1);
+	return massage_data_for_non_r_func(db, buf);
+}
+
+struct passwd* FAST_FUNC getpwent(void)
+{
+	return getXXent(0);
+}
 
 /****** getXXnam/id */
 
 static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos)
 {
 	char *buf;
-	void *result;
 	struct passdb *db = &get_S()->db[db_and_field_pos >> 2];
 
-	result = NULL;
-
 	if (!db->fp) {
 		db->fp = fopen_for_read(db->filename);
 		if (!db->fp) {
@@ -420,18 +459,7 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos)
 	}
 
 	buf = parse_common(db->fp, db, name, db_and_field_pos & 3);
-	if (buf) {
-		free(db->malloced);
-		/* We enlarge buf and move string data up, freeing space
-		 * for struct passwd/group/spwd at the beginning. This way,
-		 * entire result of getXXnam is in a single malloced block.
-		 * This enables easy creation of xmalloc_getpwnam() API.
-		 */
-		db->malloced = buf = xrealloc(buf, db->size_of + S.string_size);
-		memmove(buf + db->size_of, buf, S.string_size);
-		result = convert_to_struct(db, buf + db->size_of, buf);
-	}
-	return result;
+	return massage_data_for_non_r_func(db, buf);
 }
 
 struct passwd* FAST_FUNC getpwnam(const char *name)
diff --git a/loginutils/deluser.c b/loginutils/deluser.c
index 2d98ecc..01a9386 100644
--- a/loginutils/deluser.c
+++ b/loginutils/deluser.c
@@ -91,12 +91,11 @@ int deluser_main(int argc, char **argv)
 			if (!member) {
 				/* "delgroup GROUP" */
 				struct passwd *pw;
-				struct passwd pwent;
 				/* Check if the group is in use */
-#define passwd_buf bb_common_bufsiz1
-				while (!getpwent_r(&pwent, passwd_buf, sizeof(passwd_buf), &pw)) {
-					if (pwent.pw_gid == gr->gr_gid)
-						bb_error_msg_and_die("'%s' still has '%s' as their primary group!", pwent.pw_name, name);
+				while ((pw = getpwent()) != NULL) {
+					if (pw->pw_gid == gr->gr_gid)
+						bb_error_msg_and_die("'%s' still has '%s' as their primary group!",
+							pw->pw_name, name);
 				}
 				//endpwent();
 			}


More information about the busybox-cvs mailing list