blob: 1f76bba15618f9090e28a580aa867eeba707046d [file] [log] [blame]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28#include <grp.h>
29#include <stdio.h>
30#include <unistd.h>
31#include <pwd.h>
32#include <netdb.h>
33#include <mntent.h>
34#include <private/android_filesystem_config.h>
35#include <pthread.h>
36#include <stdlib.h>
37#include <errno.h>
38
39/** Thread-specific state for the stubs functions
40 **/
41
42pthread_once_t the_once = PTHREAD_ONCE_INIT;
43pthread_key_t the_key;
44
45typedef struct {
46 struct passwd passwd;
47 struct group group;
48 char* group_members[2];
49 char app_name_buffer[32];
50 char group_name_buffer[32];
51} stubs_state_t;
52
53static void
54stubs_state_free( void* _s )
55{
56 stubs_state_t* s = _s;
57 free(s);
58}
59
60static stubs_state_t*
61stubs_state_alloc( void )
62{
63 stubs_state_t* s = calloc(1, sizeof *s);
64
65 if (s != NULL) {
66 s->group.gr_mem = s->group_members;
67 }
68 return s;
69}
70
71static void __stubs_key_init(void)
72{
73 pthread_key_create( &the_key, stubs_state_free );
74}
75
76static stubs_state_t*
77__stubs_state(void)
78{
79 stubs_state_t* s;
80
81 pthread_once(&the_once, __stubs_key_init);
82 s = pthread_getspecific(the_key);
83 if (s == NULL) {
84 s = stubs_state_alloc();
85 if (s == NULL) {
86 errno = ENOMEM; /* just in case */
87 } else {
88 if ( pthread_setspecific(the_key, s) != 0 ) {
89 stubs_state_free(s);
90 errno = ENOMEM;
91 s = NULL;
92 }
93 }
94 }
95 return s;
96}
97
98static struct passwd *android_iinfo_to_passwd(
99 struct passwd *pw, struct android_id_info *iinfo)
100{
101 pw->pw_name = (char*)iinfo->name;
102 pw->pw_uid = iinfo->aid;
103 pw->pw_gid = iinfo->aid;
104 pw->pw_dir = "/";
105 pw->pw_shell = "/system/bin/sh";
106 return pw;
107}
108
109static struct group *android_iinfo_to_group(
110 struct group *gr, struct android_id_info *iinfo)
111{
112 gr->gr_name = (char*) iinfo->name;
113 gr->gr_gid = iinfo->aid;
114 gr->gr_mem[0] = gr->gr_name;
115 gr->gr_mem[1] = NULL;
116 return gr;
117}
118
119static struct passwd *android_id_to_passwd(
120 struct passwd *pw, unsigned id)
121{
122 struct android_id_info *iinfo = android_ids;
123 unsigned n;
124 for (n = 0; n < android_id_count; n++) {
125 if (iinfo[n].aid == id) {
126 return android_iinfo_to_passwd(pw, iinfo + n);
127 }
128 }
129 return 0;
130}
131
132static struct passwd *android_name_to_passwd(
133 struct passwd *pw, const char *name)
134{
135 struct android_id_info *iinfo = android_ids;
136 unsigned n;
137 for (n = 0; n < android_id_count; n++) {
138 if (!strcmp(iinfo[n].name, name)) {
139 return android_iinfo_to_passwd(pw, iinfo + n);
140 }
141 }
142 return 0;
143}
144
145static struct group *android_id_to_group(
146 struct group *gr, unsigned id)
147{
148 struct android_id_info *iinfo = android_ids;
149 unsigned n;
150 for (n = 0; n < android_id_count; n++) {
151 if (iinfo[n].aid == id) {
152 return android_iinfo_to_group(gr, iinfo + n);
153 }
154 }
155 return 0;
156}
157
158static struct group *android_name_to_group(
159 struct group *gr, const char *name)
160{
161 struct android_id_info *iinfo = android_ids;
162 unsigned n;
163 for (n = 0; n < android_id_count; n++) {
164 if (!strcmp(iinfo[n].name, name)) {
165 return android_iinfo_to_group(gr, iinfo + n);
166 }
167 }
168 return 0;
169}
170
171struct passwd* getpwuid(uid_t uid)
172{
173 stubs_state_t* state = __stubs_state();
174 struct passwd* pw;
175
176 if (state == NULL)
177 return NULL;
178
179 pw = &state->passwd;
180
181 if ( android_id_to_passwd(pw, uid) != NULL )
182 return pw;
183
184 if (uid < AID_APP) {
185 errno = ENOENT;
186 return NULL;
187 }
188
189 snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
190 "app_%d", uid - AID_APP );
191
192 pw->pw_name = state->app_name_buffer;
193 pw->pw_dir = "/data";
194 pw->pw_shell = "/system/bin/sh";
195 pw->pw_uid = uid;
196 pw->pw_gid = uid;
197
198 return pw;
199}
200
201struct passwd* getpwnam(const char *login)
202{
203 stubs_state_t* state = __stubs_state();
204
205 if (state == NULL)
206 return NULL;
207
208 return android_name_to_passwd(&state->passwd, login);
209}
210
211int getgrouplist (const char *user, gid_t group,
212 gid_t *groups, int *ngroups) {
213 if (*ngroups < 1) {
214 *ngroups = 1;
215 return -1;
216 }
217 groups[0] = group;
218 return (*ngroups = 1);
219}
220
221char* getlogin(void)
222{
223 struct passwd *pw = getpwuid(getuid());
224
225 if(pw) {
226 return pw->pw_name;
227 } else {
228 return 0;
229 }
230}
231
232struct group* getgrgid(gid_t gid)
233{
234 stubs_state_t* state = __stubs_state();
235 struct group* gr;
236
237 if (state == NULL)
238 return NULL;
239
240 gr = android_id_to_group(&state->group, gid);
241 if (gr != NULL)
242 return gr;
243
244 if (gid < AID_APP) {
245 errno = ENOENT;
246 return NULL;
247 }
248
249 snprintf(state->group_name_buffer, sizeof state->group_name_buffer,
250 "app_%d", gid - AID_APP);
251
252 gr = &state->group;
253
254 gr->gr_name = state->group_name_buffer;
255 gr->gr_gid = gid;
256 gr->gr_mem[0] = gr->gr_name;
257 gr->gr_mem[1] = NULL;
258
259 return gr;
260}
261
262struct group* getgrnam(const char *name)
263{
264 stubs_state_t* state = __stubs_state();
265
266 if (state == NULL)
267 return NULL;
268
269 return android_name_to_group(&state->group, name);
270}
271
272struct netent* getnetbyname(const char *name)
273{
274 fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__);
275 return NULL;
276}
277
278void endpwent(void)
279{
280}
281
282struct mntent* getmntent(FILE* f)
283{
284 fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
285 return NULL;
286}
287
288char* ttyname(int fd)
289{
290 fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
291 return NULL;
292}
293
294struct netent *getnetbyaddr(uint32_t net, int type)
295{
296 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
297 return NULL;
298}
299
300struct protoent *getprotobyname(const char *name)
301{
302 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
303 return NULL;
304}
305
306struct protoent *getprotobynumber(int proto)
307{
308 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
309 return NULL;
310}
311
312