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
This commit is contained in:
parent
fe88a194a3
commit
1f8e2672a8
@ -37,6 +37,78 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.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
|
/** 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__);
|
fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user