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) {