Add ability to read /etc/passwd and /etc/group
Add the capability to read /etc/passwd and /etc/group for getpw* and
getgr* functions.
Bug: 27999086
Test: pwd, grp, grp_pwd_file unit tests
Test: Read in custom users/groups from /etc/{passwd,group}
Change-Id: Idc1f054af8a7ca34743a90493495f0ccc775a0d8
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index 43a5032..952058f 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -44,6 +44,10 @@
// Generated android_ids array
#include "generated_android_ids.h"
+#include "grp_pwd_file.h"
+
+static PasswdFile vendor_passwd("/vendor/etc/passwd");
+static GroupFile vendor_group("/vendor/etc/group");
// POSIX seems to envisage an implementation where the <pwd.h> functions are
// implemented by brute-force searching with getpwent(3), and the <grp.h>
@@ -422,7 +426,11 @@
static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) {
if (!is_oem_id(uid)) {
- return NULL;
+ return nullptr;
+ }
+
+ if (vendor_passwd.FindById(uid, state)) {
+ return &state->passwd_;
}
snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", uid);
@@ -440,7 +448,11 @@
static group* oem_id_to_group(gid_t gid, group_state_t* state) {
if (!is_oem_id(gid)) {
- return NULL;
+ return nullptr;
+ }
+
+ if (vendor_group.FindById(gid, state)) {
+ return &state->group_;
}
snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_),
@@ -530,6 +542,13 @@
if (pw != NULL) {
return pw;
}
+
+ if (vendor_passwd.FindByName(login, state)) {
+ if (is_oem_id(state->passwd_.pw_uid)) {
+ return &state->passwd_;
+ }
+ }
+
// Handle OEM range.
pw = oem_id_to_passwd(oem_id_from_name(login), state);
if (pw != NULL) {
@@ -640,6 +659,13 @@
if (grp != NULL) {
return grp;
}
+
+ if (vendor_group.FindByName(name, state)) {
+ if (is_oem_id(state->group_.gr_gid)) {
+ return &state->group_;
+ }
+ }
+
// Handle OEM range.
grp = oem_id_to_group(oem_id_from_name(name), state);
if (grp != NULL) {