diff options
author | Rob Landley <rob@landley.net> | 2018-06-30 21:41:11 -0500 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2018-06-30 21:41:11 -0500 |
commit | 5a6179f8c3674792b680cf6ab23b7550acc2ed34 (patch) | |
tree | d65eeeec888b419d05548b3885b47980bd19305f /lib | |
parent | de365c8a091ac758f83de68d8986a54959063067 (diff) | |
download | toybox-5a6179f8c3674792b680cf6ab23b7550acc2ed34.tar.gz |
Loop retrying larger allocation sizes for bufgetpwuid/bufgetgrgid.
Slightly tweaked version of Elliott's patch. We probably only need to do this
for groups (struct group * has a list of users that belong to it, but
struct passwd doesn't, getgrouplist() is separate) but keeping the code of
the two similar in case there's a way to merge them later.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lib.c | 30 |
1 files changed, 19 insertions, 11 deletions
@@ -1217,23 +1217,28 @@ struct passwd *bufgetpwuid(uid_t uid) struct pwuidbuf_list { struct pwuidbuf_list *next; struct passwd pw; - } *list; + } *list = 0; struct passwd *temp; static struct pwuidbuf_list *pwuidbuf; + int size = 0; + // If we already have this one, return it. for (list = pwuidbuf; list; list = list->next) if (list->pw.pw_uid == uid) return &(list->pw); - list = xmalloc(512); - list->next = pwuidbuf; + for (;;) { + list = xrealloc(list, size += 512); + errno = getpwuid_r(uid, &list->pw, sizeof(*list)+(char *)list, + size-sizeof(*list), &temp); + if (errno != ERANGE) break; + } - errno = getpwuid_r(uid, &list->pw, sizeof(*list)+(char *)list, - 512-sizeof(*list), &temp); if (!temp) { free(list); return 0; } + list->next = pwuidbuf; pwuidbuf = list; return &list->pw; @@ -1245,23 +1250,26 @@ struct group *bufgetgrgid(gid_t gid) struct grgidbuf_list { struct grgidbuf_list *next; struct group gr; - } *list; + } *list = 0; struct group *temp; static struct grgidbuf_list *grgidbuf; + int size = 0; for (list = grgidbuf; list; list = list->next) if (list->gr.gr_gid == gid) return &(list->gr); - list = xmalloc(512); - list->next = grgidbuf; - - errno = getgrgid_r(gid, &list->gr, sizeof(*list)+(char *)list, - 512-sizeof(*list), &temp); + for (;;) { + list = xrealloc(temp, size += 512); + errno = getgrgid_r(gid, &list->gr, sizeof(*list)+(char *)list, + 4096-sizeof(*list), &temp); + if (errno != ERANGE) break; + } if (!temp) { free(list); return 0; } + list->next = grgidbuf; grgidbuf = list; return &list->gr; |