diff options
author | Brian Carlstrom <bdc@google.com> | 2011-05-27 00:52:21 -0700 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2011-05-27 00:52:21 -0700 |
commit | 1f8e2672a8f261d5bb08e3ab26f026b30f5ff77b (patch) | |
tree | 45e6b8bf1abfb8ccacce27582c8563dd25f5101e | |
parent | fe88a194a308ae3753f90c9f7ecb99557fdbfcca (diff) | |
download | bionic-1f8e2672a8f261d5bb08e3ab26f026b30f5ff77b.zip bionic-1f8e2672a8f261d5bb08e3ab26f026b30f5ff77b.tar.gz bionic-1f8e2672a8f261d5bb08e3ab26f026b30f5ff77b.tar.bz2 |
Implement getpwnam_r(3) and getpwuid_r(3).
These functions were already declared in <pwd.h>, but hadn't been implemented
yet.
git cherry-pick --no-commit 081504af74826bad7035669ad34d457b4b439e8f
Change-Id: I316acf4cffb9f2c6788e8e342aa620f9a00886d5
-rw-r--r-- | libc/bionic/stubs.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/libc/bionic/stubs.c b/libc/bionic/stubs.c index a01d64c..5f63427 100644 --- a/libc/bionic/stubs.c +++ b/libc/bionic/stubs.c @@ -37,6 +37,78 @@ #include <errno.h> #include <ctype.h> +static int do_getpw_r(int by_name, const char* name, uid_t uid, + struct passwd* dst, char* buf, size_t byte_count, struct passwd** result) +{ + /* + * getpwnam_r and getpwuid_r don't modify errno, but library calls we + * make might. + */ + int old_errno = errno; + int rc = 0; + *result = NULL; + + const struct passwd* src = by_name ? getpwnam(name) : getpwuid(uid); + + /* + * POSIX allows failure to find a match to be considered a non-error. + * Reporting success (0) but with *result NULL is glibc's behavior. + */ + if (src == NULL) { + rc = (errno == ENOENT) ? 0 : errno; + goto failure; + } + + /* + * Work out where our strings will go in 'buf', and whether we've got + * enough space. + */ + size_t required_byte_count = 0; + dst->pw_name = buf; + required_byte_count += strlen(src->pw_name) + 1; + dst->pw_dir = buf + required_byte_count; + required_byte_count += strlen(src->pw_dir) + 1; + dst->pw_shell = buf + required_byte_count; + required_byte_count += strlen(src->pw_shell) + 1; + if (byte_count < required_byte_count) { + rc = ERANGE; + goto failure; + } + + /* Copy the strings. */ + snprintf(buf, byte_count, "%s%c%s%c%s", + src->pw_name, 0, src->pw_dir, 0, src->pw_shell); + + /* + * pw_passwd is non-POSIX and unused (always NULL) in bionic. + * pw_gecos is non-POSIX and missing in bionic. + */ + dst->pw_passwd = NULL; + + /* Copy the integral fields. */ + dst->pw_gid = src->pw_gid; + dst->pw_uid = src->pw_uid; + +success: + rc = 0; + *result = dst; +failure: + errno = old_errno; + return rc; +} + +int getpwnam_r(const char* name, struct passwd* pwd, + char* buf, size_t byte_count, struct passwd** result) +{ + return do_getpw_r(1, name, -1, pwd, buf, byte_count, result); +} + +int getpwuid_r(uid_t uid, struct passwd* pwd, + char* buf, size_t byte_count, struct passwd** result) +{ + return do_getpw_r(0, NULL, uid, pwd, buf, byte_count, result); +} + /** Thread-specific state for the stubs functions **/ @@ -400,4 +472,3 @@ void endusershell(void) { fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); } - |