summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2011-05-27 00:52:21 -0700
committerBrian Carlstrom <bdc@google.com>2011-05-27 00:52:21 -0700
commit1f8e2672a8f261d5bb08e3ab26f026b30f5ff77b (patch)
tree45e6b8bf1abfb8ccacce27582c8563dd25f5101e
parentfe88a194a308ae3753f90c9f7ecb99557fdbfcca (diff)
downloadbionic-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.c73
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__);
}
-