am 2565492d: Merge "Add getgrgid_r/getgrnam_r."
* commit '2565492db0d67b95348cd1c3026ed338ca59aa37': Add getgrgid_r/getgrnam_r.
This commit is contained in:
commit
c0c9704e11
@ -39,6 +39,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "private/android_filesystem_config.h"
|
#include "private/android_filesystem_config.h"
|
||||||
|
#include "private/bionic_macros.h"
|
||||||
#include "private/ErrnoRestorer.h"
|
#include "private/ErrnoRestorer.h"
|
||||||
#include "private/libc_logging.h"
|
#include "private/libc_logging.h"
|
||||||
#include "private/ThreadLocalBuffer.h"
|
#include "private/ThreadLocalBuffer.h"
|
||||||
@ -66,11 +67,15 @@ struct passwd_state_t {
|
|||||||
static ThreadLocalBuffer<group_state_t> g_group_tls_buffer;
|
static ThreadLocalBuffer<group_state_t> g_group_tls_buffer;
|
||||||
static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer;
|
static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer;
|
||||||
|
|
||||||
|
static void init_group_state(group_state_t* state) {
|
||||||
|
memset(state, 0, sizeof(group_state_t));
|
||||||
|
state->group_.gr_mem = state->group_members_;
|
||||||
|
}
|
||||||
|
|
||||||
static group_state_t* __group_state() {
|
static group_state_t* __group_state() {
|
||||||
group_state_t* result = g_group_tls_buffer.get();
|
group_state_t* result = g_group_tls_buffer.get();
|
||||||
if (result != nullptr) {
|
if (result != nullptr) {
|
||||||
memset(result, 0, sizeof(group_state_t));
|
init_group_state(result);
|
||||||
result->group_.gr_mem = result->group_members_;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -397,17 +402,28 @@ char* getlogin() { // NOLINT: implementing bad function.
|
|||||||
return (pw != NULL) ? pw->pw_name : NULL;
|
return (pw != NULL) ? pw->pw_name : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static group* getgrgid_internal(gid_t gid, group_state_t* state) {
|
||||||
|
group* grp = android_id_to_group(state, gid);
|
||||||
|
if (grp != NULL) {
|
||||||
|
return grp;
|
||||||
|
}
|
||||||
|
return app_id_to_group(gid, state);
|
||||||
|
}
|
||||||
|
|
||||||
group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
|
group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
|
||||||
group_state_t* state = __group_state();
|
group_state_t* state = __group_state();
|
||||||
if (state == NULL) {
|
if (state == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return getgrgid_internal(gid, state);
|
||||||
|
}
|
||||||
|
|
||||||
group* gr = android_id_to_group(state, gid);
|
static group* getgrnam_internal(const char* name, group_state_t* state) {
|
||||||
if (gr != NULL) {
|
group* grp = android_name_to_group(state, name);
|
||||||
return gr;
|
if (grp != NULL) {
|
||||||
|
return grp;
|
||||||
}
|
}
|
||||||
return app_id_to_group(gid, state);
|
return app_id_to_group(app_id_from_name(name, true), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
group* getgrnam(const char* name) { // NOLINT: implementing bad function.
|
group* getgrnam(const char* name) { // NOLINT: implementing bad function.
|
||||||
@ -415,11 +431,36 @@ group* getgrnam(const char* name) { // NOLINT: implementing bad function.
|
|||||||
if (state == NULL) {
|
if (state == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return getgrnam_internal(name, state);
|
||||||
|
}
|
||||||
|
|
||||||
if (android_name_to_group(state, name) != 0) {
|
static int getgroup_r(bool by_name, const char* name, gid_t gid, struct group* grp, char* buf,
|
||||||
return &state->group_;
|
size_t buflen, struct group** result) {
|
||||||
|
ErrnoRestorer errno_restorer;
|
||||||
|
*result = NULL;
|
||||||
|
char* p = reinterpret_cast<char*>(
|
||||||
|
BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
|
||||||
|
if (p + sizeof(group_state_t) > buf + buflen) {
|
||||||
|
return ERANGE;
|
||||||
}
|
}
|
||||||
return app_id_to_group(app_id_from_name(name, true), state);
|
group_state_t* state = reinterpret_cast<group_state_t*>(p);
|
||||||
|
init_group_state(state);
|
||||||
|
group* retval = (by_name ? getgrnam_internal(name, state) : getgrgid_internal(gid, state));
|
||||||
|
if (retval != NULL) {
|
||||||
|
*grp = *retval;
|
||||||
|
*result = grp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
|
||||||
|
return getgroup_r(false, NULL, gid, grp, buf, buflen, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getgrnam_r(const char* name, struct group* grp, char* buf, size_t buflen,
|
||||||
|
struct group **result) {
|
||||||
|
return getgroup_r(true, name, 0, grp, buf, buflen, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't have an /etc/networks, so all inputs return NULL.
|
// We don't have an /etc/networks, so all inputs return NULL.
|
||||||
|
@ -1332,6 +1332,12 @@ LIBC {
|
|||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LIBC_N {
|
||||||
|
global:
|
||||||
|
getgrgid_r;
|
||||||
|
getgrnam_r;
|
||||||
|
} LIBC;
|
||||||
|
|
||||||
LIBC_PRIVATE {
|
LIBC_PRIVATE {
|
||||||
global:
|
global:
|
||||||
___Unwind_Backtrace; # arm
|
___Unwind_Backtrace; # arm
|
||||||
@ -1453,4 +1459,4 @@ LIBC_PRIVATE {
|
|||||||
SHA1Init; # arm x86 mips
|
SHA1Init; # arm x86 mips
|
||||||
SHA1Transform; # arm x86 mips
|
SHA1Transform; # arm x86 mips
|
||||||
SHA1Update; # arm x86 mips
|
SHA1Update; # arm x86 mips
|
||||||
} LIBC;
|
} LIBC_N;
|
||||||
|
@ -163,8 +163,6 @@ TEST(getpwnam, app_id_u1_i0) {
|
|||||||
check_get_passwd("u1_i0", 199000, TYPE_APP);
|
check_get_passwd("u1_i0", 199000, TYPE_APP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__BIONIC__)
|
|
||||||
|
|
||||||
static void check_group(const group* grp, const char* group_name, gid_t gid) {
|
static void check_group(const group* grp, const char* group_name, gid_t gid) {
|
||||||
ASSERT_TRUE(grp != NULL);
|
ASSERT_TRUE(grp != NULL);
|
||||||
ASSERT_STREQ(group_name, grp->gr_name);
|
ASSERT_STREQ(group_name, grp->gr_name);
|
||||||
@ -174,6 +172,8 @@ static void check_group(const group* grp, const char* group_name, gid_t gid) {
|
|||||||
ASSERT_TRUE(grp->gr_mem[1] == NULL);
|
ASSERT_TRUE(grp->gr_mem[1] == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__BIONIC__)
|
||||||
|
|
||||||
static void check_getgrgid(const char* group_name, gid_t gid) {
|
static void check_getgrgid(const char* group_name, gid_t gid) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
group* grp = getgrgid(gid);
|
group* grp = getgrgid(gid);
|
||||||
@ -190,17 +190,49 @@ static void check_getgrnam(const char* group_name, gid_t gid) {
|
|||||||
check_group(grp, group_name, gid);
|
check_group(grp, group_name, gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_getgrgid_r(const char* group_name, gid_t gid) {
|
||||||
|
group grp_storage;
|
||||||
|
char buf[512];
|
||||||
|
group* grp;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
|
||||||
|
ASSERT_EQ(0, result);
|
||||||
|
ASSERT_EQ(0, errno);
|
||||||
|
SCOPED_TRACE("getgrgid_r");
|
||||||
|
check_group(grp, group_name, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_getgrnam_r(const char* group_name, gid_t gid) {
|
||||||
|
group grp_storage;
|
||||||
|
char buf[512];
|
||||||
|
group* grp;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
|
||||||
|
ASSERT_EQ(0, result);
|
||||||
|
ASSERT_EQ(0, errno);
|
||||||
|
SCOPED_TRACE("getgrnam_r");
|
||||||
|
check_group(grp, group_name, gid);
|
||||||
|
}
|
||||||
|
|
||||||
static void check_get_group(const char* group_name, gid_t gid) {
|
static void check_get_group(const char* group_name, gid_t gid) {
|
||||||
check_getgrgid(group_name, gid);
|
check_getgrgid(group_name, gid);
|
||||||
check_getgrnam(group_name, gid);
|
check_getgrnam(group_name, gid);
|
||||||
|
check_getgrgid_r(group_name, gid);
|
||||||
|
check_getgrnam_r(group_name, gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !defined(__BIONIC__)
|
#else // !defined(__BIONIC__)
|
||||||
|
|
||||||
static void check_get_group(const char* /* group_name */, gid_t /* gid */) {
|
static void print_no_getgrnam_test_info() {
|
||||||
GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
|
GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_get_group(const char*, gid_t) {
|
||||||
|
print_no_getgrnam_test_info();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(getgrnam, system_id_root) {
|
TEST(getgrnam, system_id_root) {
|
||||||
@ -259,3 +291,53 @@ TEST(getgrnam, app_id_u1_a40000) {
|
|||||||
TEST(getgrnam, app_id_u1_i0) {
|
TEST(getgrnam, app_id_u1_i0) {
|
||||||
check_get_group("u1_i0", 199000);
|
check_get_group("u1_i0", 199000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(getgrnam_r, reentrancy) {
|
||||||
|
#if defined(__BIONIC__)
|
||||||
|
group grp_storage[2];
|
||||||
|
char buf[2][512];
|
||||||
|
group* grp[3];
|
||||||
|
int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
|
||||||
|
ASSERT_EQ(0, result);
|
||||||
|
check_group(grp[0], "root", 0);
|
||||||
|
grp[1] = getgrnam("system");
|
||||||
|
check_group(grp[1], "system", 1000);
|
||||||
|
result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
|
||||||
|
ASSERT_EQ(0, result);
|
||||||
|
check_group(grp[2], "radio", 1001);
|
||||||
|
check_group(grp[0], "root", 0);
|
||||||
|
check_group(grp[1], "system", 1000);
|
||||||
|
#else
|
||||||
|
print_no_getgrnam_test_info();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(getgrgid_r, reentrancy) {
|
||||||
|
#if defined(__BIONIC__)
|
||||||
|
group grp_storage[2];
|
||||||
|
char buf[2][512];
|
||||||
|
group* grp[3];
|
||||||
|
int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
|
||||||
|
ASSERT_EQ(0, result);
|
||||||
|
check_group(grp[0], "root", 0);
|
||||||
|
grp[1] = getgrgid(1000);
|
||||||
|
check_group(grp[1], "system", 1000);
|
||||||
|
result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
|
||||||
|
ASSERT_EQ(0, result);
|
||||||
|
check_group(grp[2], "radio", 1001);
|
||||||
|
check_group(grp[0], "root", 0);
|
||||||
|
check_group(grp[1], "system", 1000);
|
||||||
|
#else
|
||||||
|
print_no_getgrnam_test_info();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(getgrnam_r, large_enough_suggested_buffer_size) {
|
||||||
|
long size = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||||
|
ASSERT_GT(size, 0);
|
||||||
|
char buf[size];
|
||||||
|
group grp_storage;
|
||||||
|
group* grp;
|
||||||
|
ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
|
||||||
|
check_group(grp, "root", 0);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user