blob: 586d4977e75fecde6515cd46adbce316e1d83928 [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*
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#include <ctype.h>
39
40/** Thread-specific state for the stubs functions
41 **/
42
43pthread_once_t the_once = PTHREAD_ONCE_INIT;
44pthread_key_t the_key;
45
46typedef struct {
47 struct passwd passwd;
48 struct group group;
49 char* group_members[2];
50 char app_name_buffer[32];
51 char group_name_buffer[32];
52} stubs_state_t;
53
54static void
55stubs_state_free( void* _s )
56{
57 stubs_state_t* s = _s;
58 free(s);
59}
60
61static stubs_state_t*
62stubs_state_alloc( void )
63{
64 stubs_state_t* s = calloc(1, sizeof *s);
65
66 if (s != NULL) {
67 s->group.gr_mem = s->group_members;
68 }
69 return s;
70}
71
72static void __stubs_key_init(void)
73{
74 pthread_key_create( &the_key, stubs_state_free );
75}
76
77static stubs_state_t*
78__stubs_state(void)
79{
80 stubs_state_t* s;
81
82 pthread_once(&the_once, __stubs_key_init);
83 s = pthread_getspecific(the_key);
84 if (s == NULL) {
85 s = stubs_state_alloc();
86 if (s == NULL) {
87 errno = ENOMEM; /* just in case */
88 } else {
89 if ( pthread_setspecific(the_key, s) != 0 ) {
90 stubs_state_free(s);
91 errno = ENOMEM;
92 s = NULL;
93 }
94 }
95 }
96 return s;
97}
98
99static struct passwd*
100android_iinfo_to_passwd( struct passwd *pw,
101 struct android_id_info *iinfo )
102{
103 pw->pw_name = (char*)iinfo->name;
104 pw->pw_uid = iinfo->aid;
105 pw->pw_gid = iinfo->aid;
106 pw->pw_dir = "/";
107 pw->pw_shell = "/system/bin/sh";
108 return pw;
109}
110
111static struct group*
112android_iinfo_to_group( struct group *gr,
113 struct android_id_info *iinfo )
114{
115 gr->gr_name = (char*) iinfo->name;
116 gr->gr_gid = iinfo->aid;
117 gr->gr_mem[0] = gr->gr_name;
118 gr->gr_mem[1] = NULL;
119 return gr;
120}
121
122static struct passwd *
123android_id_to_passwd( struct passwd *pw, unsigned id)
124{
125 struct android_id_info *iinfo = android_ids;
126 unsigned n;
127 for (n = 0; n < android_id_count; n++) {
128 if (iinfo[n].aid == id) {
129 return android_iinfo_to_passwd(pw, iinfo + n);
130 }
131 }
132 return NULL;
133}
134
135static struct passwd*
136android_name_to_passwd(struct passwd *pw, const char *name)
137{
138 struct android_id_info *iinfo = android_ids;
139 unsigned n;
140 for (n = 0; n < android_id_count; n++) {
141 if (!strcmp(iinfo[n].name, name)) {
142 return android_iinfo_to_passwd(pw, iinfo + n);
143 }
144 }
145 return NULL;
146}
147
148static struct group*
149android_id_to_group( struct group *gr, unsigned id )
150{
151 struct android_id_info *iinfo = android_ids;
152 unsigned n;
153 for (n = 0; n < android_id_count; n++) {
154 if (iinfo[n].aid == id) {
155 return android_iinfo_to_group(gr, iinfo + n);
156 }
157 }
158 return NULL;
159}
160
161static struct group*
162android_name_to_group( struct group *gr, const char *name )
163{
164 struct android_id_info *iinfo = android_ids;
165 unsigned n;
166 for (n = 0; n < android_id_count; n++) {
167 if (!strcmp(iinfo[n].name, name)) {
168 return android_iinfo_to_group(gr, iinfo + n);
169 }
170 }
171 return NULL;
172}
173
174/* translate a user/group name like app_1234 into the
175 * corresponding user/group id (AID_APP + 1234)
176 * returns 0 and sets errno to ENOENT in case of error
177 */
178static unsigned
179app_id_from_name( const char* name )
180{
181 unsigned long id;
182 char* end;
183
184 if (memcmp(name, "app_", 4) != 0 || !isdigit(name[4]))
185 goto FAIL;
186
187 id = strtoul(name+4, &end, 10);
188 if (id == 0 || *end != '\0')
189 goto FAIL;
190
191 id += AID_APP;
192
193 /* check for overflow and that the value can be
194 * stored in our 32-bit uid_t/gid_t */
195 if (id < AID_APP || (unsigned)id != id)
196 goto FAIL;
197
198 return (unsigned)id;
199
200FAIL:
201 errno = ENOENT;
202 return 0;
203}
204
205/* translate a uid into the corresponding app_<uid>
206 * passwd structure (sets errno to ENOENT on failure)
207 */
208static struct passwd*
209app_id_to_passwd(uid_t uid, stubs_state_t* state)
210{
211 struct passwd* pw = &state->passwd;
212
213 if (uid < AID_APP) {
214 errno = ENOENT;
215 return NULL;
216 }
217
218 snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
219 "app_%u", uid - AID_APP );
220
221 pw->pw_name = state->app_name_buffer;
222 pw->pw_dir = "/data";
223 pw->pw_shell = "/system/bin/sh";
224 pw->pw_uid = uid;
225 pw->pw_gid = uid;
226
227 return pw;
228}
229
230/* translate a gid into the corresponding app_<gid>
231 * group structure (sets errno to ENOENT on failure)
232 */
233static struct group*
234app_id_to_group(gid_t gid, stubs_state_t* state)
235{
236 struct group* gr = &state->group;
237
238 if (gid < AID_APP) {
239 errno = ENOENT;
240 return NULL;
241 }
242
243 snprintf(state->group_name_buffer, sizeof state->group_name_buffer,
244 "app_%u", gid - AID_APP);
245
246 gr->gr_name = state->group_name_buffer;
247 gr->gr_gid = gid;
248 gr->gr_mem[0] = gr->gr_name;
249 gr->gr_mem[1] = NULL;
250
251 return gr;
252}
253
254
255struct passwd*
256getpwuid(uid_t uid)
257{
258 stubs_state_t* state = __stubs_state();
259 struct passwd* pw;
260
261 if (state == NULL)
262 return NULL;
263
264 pw = &state->passwd;
265
266 if ( android_id_to_passwd(pw, uid) != NULL )
267 return pw;
268
269 return app_id_to_passwd(uid, state);
270}
271
272struct passwd*
273getpwnam(const char *login)
274{
275 stubs_state_t* state = __stubs_state();
276
277 if (state == NULL)
278 return NULL;
279
280 if (android_name_to_passwd(&state->passwd, login) != NULL)
281 return &state->passwd;
282
283 return app_id_to_passwd( app_id_from_name(login), state );
284}
285
286int
287getgrouplist (const char *user, gid_t group,
288 gid_t *groups, int *ngroups)
289{
290 if (*ngroups < 1) {
291 *ngroups = 1;
292 return -1;
293 }
294 groups[0] = group;
295 return (*ngroups = 1);
296}
297
298char*
299getlogin(void)
300{
301 struct passwd *pw = getpwuid(getuid());
302
303 if(pw) {
304 return pw->pw_name;
305 } else {
306 return NULL;
307 }
308}
309
310struct group*
311getgrgid(gid_t gid)
312{
313 stubs_state_t* state = __stubs_state();
314 struct group* gr;
315
316 if (state == NULL)
317 return NULL;
318
319 gr = android_id_to_group(&state->group, gid);
320 if (gr != NULL)
321 return gr;
322
323 return app_id_to_group(gid, state);
324}
325
326struct group*
327getgrnam(const char *name)
328{
329 stubs_state_t* state = __stubs_state();
330 unsigned id;
331
332 if (state == NULL)
333 return NULL;
334
335 if (android_name_to_group(&state->group, name) != 0)
336 return &state->group;
337
338 return app_id_to_group( app_id_from_name(name), state );
339}
340
341
342struct netent* getnetbyname(const char *name)
343{
344 fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__);
345 return NULL;
346}
347
348void endpwent(void)
349{
350}
351
352struct mntent* getmntent(FILE* f)
353{
354 fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__);
355 return NULL;
356}
357
358char* ttyname(int fd)
359{
360 fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__);
361 return NULL;
362}
363
Colin Crossfc10b242010-01-13 17:48:34 -0800364int ttyname_r(int fd, char *buf, size_t buflen)
365{
366 fprintf(stderr, "FIX ME! implement ttyname_r() %s:%d\n", __FILE__, __LINE__);
367 return -ERANGE;
368}
369
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800370struct netent *getnetbyaddr(uint32_t net, int type)
371{
372 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
373 return NULL;
374}
375
376struct protoent *getprotobyname(const char *name)
377{
378 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
379 return NULL;
380}
381
382struct protoent *getprotobynumber(int proto)
383{
384 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
385 return NULL;
386}
Colin Crossfc10b242010-01-13 17:48:34 -0800387
388char* getusershell(void)
389{
390 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
391 return NULL;
392}
393
394void setusershell(void)
395{
396 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
397}
398
399void endusershell(void)
400{
401 fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
402}
403