libpwdgrp: use getpwent() instead of getpwent_r()

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>
This commit is contained in:
Denys Vlasenko 2015-02-07 21:21:02 +01:00
parent 68c048fb23
commit 23cfaab47d
4 changed files with 53 additions and 43 deletions

View File

@ -36,7 +36,6 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
#define getpwent bb_internal_getpwent #define getpwent bb_internal_getpwent
#define getpwuid bb_internal_getpwuid #define getpwuid bb_internal_getpwuid
#define getpwnam bb_internal_getpwnam #define getpwnam bb_internal_getpwnam
#define getpwent_r bb_internal_getpwent_r
#define getpwnam_r bb_internal_getpwnam_r #define getpwnam_r bb_internal_getpwnam_r
/* All function names below should be remapped by #defines above /* All function names below should be remapped by #defines above
@ -48,10 +47,8 @@ void FAST_FUNC setpwent(void);
/* Close the password-file stream. */ /* Close the password-file stream. */
void FAST_FUNC endpwent(void); void FAST_FUNC endpwent(void);
#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS
/* Read an entry from the password-file stream, opening it if necessary. */ /* Read an entry from the password-file stream, opening it if necessary. */
struct passwd* FAST_FUNC getpwent(void); struct passwd* FAST_FUNC getpwent(void);
#endif
/* Search for an entry with a matching user ID. */ /* Search for an entry with a matching user ID. */
struct passwd* FAST_FUNC getpwuid(uid_t __uid); 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. */ /* Search for an entry with a matching username. */
struct passwd* FAST_FUNC getpwnam(const char *__name); struct passwd* FAST_FUNC getpwnam(const char *__name);
/* Reentrant versions of some of the functions above. /* 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);
int FAST_FUNC getpwnam_r(const char *__restrict __name, int FAST_FUNC getpwnam_r(const char *__restrict __name,
struct passwd *__restrict __resultbuf, struct passwd *__restrict __resultbuf,
char *__restrict __buffer, size_t __buflen, char *__restrict __buffer, size_t __buflen,

View File

@ -672,23 +672,20 @@ static char *username_path_completion(char *ud)
*/ */
static NOINLINE unsigned complete_username(const char *ud) static NOINLINE unsigned complete_username(const char *ud)
{ {
/* Using _r function to avoid pulling in static buffers */ struct passwd *pw;
char line_buff[256];
struct passwd pwd;
struct passwd *result;
unsigned userlen; unsigned userlen;
ud++; /* skip ~ */ ud++; /* skip ~ */
userlen = strlen(ud); userlen = strlen(ud);
setpwent(); 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. */ /* Null usernames should result in all users as possible completions. */
if (/*!userlen || */ strncmp(ud, pwd.pw_name, userlen) == 0) { if (/*!userlen || */ strncmp(ud, pw->pw_name, userlen) == 0) {
add_match(xasprintf("~%s/", pwd.pw_name)); add_match(xasprintf("~%s/", pw->pw_name));
} }
} }
endpwent(); endpwent(); /* don't keep password file open */
return 1 + userlen; return 1 + userlen;
} }

View File

@ -336,6 +336,22 @@ static int massage_data_for_r_func(struct passdb *db,
return errno; 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 */ /****** getXXnam/id_r */
static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, 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 #endif
#ifdef UNUSED
/****** getXXent_r */ /****** getXXent_r */
static int FAST_FUNC getXXent_r(uintptr_t db_idx, char *buffer, size_t buflen, 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; *result = struct_buf;
return getXXent_r(0, buffer, buflen, result); 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 */ /****** getXXnam/id */
static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos)
{ {
char *buf; char *buf;
void *result;
struct passdb *db = &get_S()->db[db_and_field_pos >> 2]; struct passdb *db = &get_S()->db[db_and_field_pos >> 2];
result = NULL;
if (!db->fp) { if (!db->fp) {
db->fp = fopen_for_read(db->filename); db->fp = fopen_for_read(db->filename);
if (!db->fp) { 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); buf = parse_common(db->fp, db, name, db_and_field_pos & 3);
if (buf) { return massage_data_for_non_r_func(db, 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;
} }
struct passwd* FAST_FUNC getpwnam(const char *name) struct passwd* FAST_FUNC getpwnam(const char *name)

View File

@ -91,12 +91,11 @@ int deluser_main(int argc, char **argv)
if (!member) { if (!member) {
/* "delgroup GROUP" */ /* "delgroup GROUP" */
struct passwd *pw; struct passwd *pw;
struct passwd pwent;
/* Check if the group is in use */ /* Check if the group is in use */
#define passwd_buf bb_common_bufsiz1 while ((pw = getpwent()) != NULL) {
while (!getpwent_r(&pwent, passwd_buf, sizeof(passwd_buf), &pw)) { if (pw->pw_gid == gr->gr_gid)
if (pwent.pw_gid == gr->gr_gid) bb_error_msg_and_die("'%s' still has '%s' as their primary group!",
bb_error_msg_and_die("'%s' still has '%s' as their primary group!", pwent.pw_name, name); pw->pw_name, name);
} }
//endpwent(); //endpwent();
} }