diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:28:35 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:28:35 -0800 |
commit | 1dc9e472e19acfe6dc7f41e429236e7eef7ceda1 (patch) | |
tree | 3be0c520fae17689bbf5584e1136fb820caef26f /libc/bionic/stubs.c | |
parent | 1767f908af327fa388b1c66883760ad851267013 (diff) | |
download | bionic-1dc9e472e19acfe6dc7f41e429236e7eef7ceda1.zip bionic-1dc9e472e19acfe6dc7f41e429236e7eef7ceda1.tar.gz bionic-1dc9e472e19acfe6dc7f41e429236e7eef7ceda1.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libc/bionic/stubs.c')
-rw-r--r-- | libc/bionic/stubs.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/libc/bionic/stubs.c b/libc/bionic/stubs.c new file mode 100644 index 0000000..365f21a --- /dev/null +++ b/libc/bionic/stubs.c @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <grp.h> +#include <stdio.h> +#include <unistd.h> +#include <pwd.h> +#include <netdb.h> +#include <mntent.h> +#include <private/android_filesystem_config.h> +#include <pthread.h> +#include <stdlib.h> +#include <errno.h> +#include <ctype.h> + +/** Thread-specific state for the stubs functions + **/ + +pthread_once_t the_once = PTHREAD_ONCE_INIT; +pthread_key_t the_key; + +typedef struct { + struct passwd passwd; + struct group group; + char* group_members[2]; + char app_name_buffer[32]; + char group_name_buffer[32]; +} stubs_state_t; + +static void +stubs_state_free( void* _s ) +{ + stubs_state_t* s = _s; + free(s); +} + +static stubs_state_t* +stubs_state_alloc( void ) +{ + stubs_state_t* s = calloc(1, sizeof *s); + + if (s != NULL) { + s->group.gr_mem = s->group_members; + } + return s; +} + +static void __stubs_key_init(void) +{ + pthread_key_create( &the_key, stubs_state_free ); +} + +static stubs_state_t* +__stubs_state(void) +{ + stubs_state_t* s; + + pthread_once(&the_once, __stubs_key_init); + s = pthread_getspecific(the_key); + if (s == NULL) { + s = stubs_state_alloc(); + if (s == NULL) { + errno = ENOMEM; /* just in case */ + } else { + if ( pthread_setspecific(the_key, s) != 0 ) { + stubs_state_free(s); + errno = ENOMEM; + s = NULL; + } + } + } + return s; +} + +static struct passwd* +android_iinfo_to_passwd( struct passwd *pw, + struct android_id_info *iinfo ) +{ + pw->pw_name = (char*)iinfo->name; + pw->pw_uid = iinfo->aid; + pw->pw_gid = iinfo->aid; + pw->pw_dir = "/"; + pw->pw_shell = "/system/bin/sh"; + return pw; +} + +static struct group* +android_iinfo_to_group( struct group *gr, + struct android_id_info *iinfo ) +{ + gr->gr_name = (char*) iinfo->name; + gr->gr_gid = iinfo->aid; + gr->gr_mem[0] = gr->gr_name; + gr->gr_mem[1] = NULL; + return gr; +} + +static struct passwd * +android_id_to_passwd( struct passwd *pw, unsigned id) +{ + struct android_id_info *iinfo = android_ids; + unsigned n; + for (n = 0; n < android_id_count; n++) { + if (iinfo[n].aid == id) { + return android_iinfo_to_passwd(pw, iinfo + n); + } + } + return NULL; +} + +static struct passwd* +android_name_to_passwd(struct passwd *pw, const char *name) +{ + struct android_id_info *iinfo = android_ids; + unsigned n; + for (n = 0; n < android_id_count; n++) { + if (!strcmp(iinfo[n].name, name)) { + return android_iinfo_to_passwd(pw, iinfo + n); + } + } + return NULL; +} + +static struct group* +android_id_to_group( struct group *gr, unsigned id ) +{ + struct android_id_info *iinfo = android_ids; + unsigned n; + for (n = 0; n < android_id_count; n++) { + if (iinfo[n].aid == id) { + return android_iinfo_to_group(gr, iinfo + n); + } + } + return NULL; +} + +static struct group* +android_name_to_group( struct group *gr, const char *name ) +{ + struct android_id_info *iinfo = android_ids; + unsigned n; + for (n = 0; n < android_id_count; n++) { + if (!strcmp(iinfo[n].name, name)) { + return android_iinfo_to_group(gr, iinfo + n); + } + } + return NULL; +} + +/* translate a user/group name like app_1234 into the + * corresponding user/group id (AID_APP + 1234) + * returns 0 and sets errno to ENOENT in case of error + */ +static unsigned +app_id_from_name( const char* name ) +{ + unsigned long id; + char* end; + + if (memcmp(name, "app_", 4) != 0 || !isdigit(name[4])) + goto FAIL; + + id = strtoul(name+4, &end, 10); + if (id == 0 || *end != '\0') + goto FAIL; + + id += AID_APP; + + /* check for overflow and that the value can be + * stored in our 32-bit uid_t/gid_t */ + if (id < AID_APP || (unsigned)id != id) + goto FAIL; + + return (unsigned)id; + +FAIL: + errno = ENOENT; + return 0; +} + +/* translate a uid into the corresponding app_<uid> + * passwd structure (sets errno to ENOENT on failure) + */ +static struct passwd* +app_id_to_passwd(uid_t uid, stubs_state_t* state) +{ + struct passwd* pw = &state->passwd; + + if (uid < AID_APP) { + errno = ENOENT; + return NULL; + } + + snprintf( state->app_name_buffer, sizeof state->app_name_buffer, + "app_%u", uid - AID_APP ); + + pw->pw_name = state->app_name_buffer; + pw->pw_dir = "/data"; + pw->pw_shell = "/system/bin/sh"; + pw->pw_uid = uid; + pw->pw_gid = uid; + + return pw; +} + +/* translate a gid into the corresponding app_<gid> + * group structure (sets errno to ENOENT on failure) + */ +static struct group* +app_id_to_group(gid_t gid, stubs_state_t* state) +{ + struct group* gr = &state->group; + + if (gid < AID_APP) { + errno = ENOENT; + return NULL; + } + + snprintf(state->group_name_buffer, sizeof state->group_name_buffer, + "app_%u", gid - AID_APP); + + gr->gr_name = state->group_name_buffer; + gr->gr_gid = gid; + gr->gr_mem[0] = gr->gr_name; + gr->gr_mem[1] = NULL; + + return gr; +} + + +struct passwd* +getpwuid(uid_t uid) +{ + stubs_state_t* state = __stubs_state(); + struct passwd* pw; + + if (state == NULL) + return NULL; + + pw = &state->passwd; + + if ( android_id_to_passwd(pw, uid) != NULL ) + return pw; + + return app_id_to_passwd(uid, state); +} + +struct passwd* +getpwnam(const char *login) +{ + stubs_state_t* state = __stubs_state(); + + if (state == NULL) + return NULL; + + if (android_name_to_passwd(&state->passwd, login) != NULL) + return &state->passwd; + + return app_id_to_passwd( app_id_from_name(login), state ); +} + +int +getgrouplist (const char *user, gid_t group, + gid_t *groups, int *ngroups) +{ + if (*ngroups < 1) { + *ngroups = 1; + return -1; + } + groups[0] = group; + return (*ngroups = 1); +} + +char* +getlogin(void) +{ + struct passwd *pw = getpwuid(getuid()); + + if(pw) { + return pw->pw_name; + } else { + return NULL; + } +} + +struct group* +getgrgid(gid_t gid) +{ + stubs_state_t* state = __stubs_state(); + struct group* gr; + + if (state == NULL) + return NULL; + + gr = android_id_to_group(&state->group, gid); + if (gr != NULL) + return gr; + + return app_id_to_group(gid, state); +} + +struct group* +getgrnam(const char *name) +{ + stubs_state_t* state = __stubs_state(); + unsigned id; + + if (state == NULL) + return NULL; + + if (android_name_to_group(&state->group, name) != 0) + return &state->group; + + return app_id_to_group( app_id_from_name(name), state ); +} + + +struct netent* getnetbyname(const char *name) +{ + fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__); + return NULL; +} + +void endpwent(void) +{ +} + +struct mntent* getmntent(FILE* f) +{ + fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__); + return NULL; +} + +char* ttyname(int fd) +{ + fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__); + return NULL; +} + +struct netent *getnetbyaddr(uint32_t net, int type) +{ + fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); + return NULL; +} + +struct protoent *getprotobyname(const char *name) +{ + fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); + return NULL; +} + +struct protoent *getprotobynumber(int proto) +{ + fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); + return NULL; +} |