libpwdgrp: use getpwent() instead of getpwent_r()
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 7 Feb 2015 20:21:02 +0000 (21:21 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 7 Feb 2015 20:21:02 +0000 (21:21 +0100)
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@googlemail.com>
include/pwd_.h
libbb/lineedit.c
libpwdgrp/pwd_grp.c
loginutils/deluser.c

index 32b5b366ea3e8fe5cd950cde615f234b1d763a8b..17348298a034edd600ebf425e965015fceeab750 100644 (file)
@@ -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,
index 720a4951e03d7f12deae3ce9751515501a7f44c8..249b401b4b6e36c37473d05dec912bd69ce3e6f7 100644 (file)
@@ -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;
 }
index 90647e9d3a22b838587f7adde96b07afc1c4dd07..7ec704ee4e8bd06b06f5d26d18be584f557d971e 100644 (file)
@@ -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)
index 2d98ecc58f43af3e06a6dcb0bb8cd4d727cc3c76..01a9386bc577377f8db866c2452b736178f0552d 100644 (file)
@@ -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();
                        }