• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007 The Android Open Source Project
3  *
4  * Syscall and library intercepts.
5  */
6 
7 /* don't remap open() to open64() */
8 #undef _FILE_OFFSET_BITS
9 
10 #define CREATE_FUNC_STORAGE
11 #include "Common.h"
12 
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdarg.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <sys/uio.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 #include <utime.h>
24 #include <limits.h>
25 #include <ftw.h>
26 #include <assert.h>
27 
28 
29 #if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
30 #warning "big"
31 #endif
32 
33 //#define CALLTRACE(format, ...)   wsLog(format, ##__VA_ARGS__)
34 #define CALLTRACE(format, ...)   ((void)0)
35 
36 //#define CALLTRACEV(format, ...)  wsLog(format, ##__VA_ARGS__)
37 #define CALLTRACEV(format, ...)  ((void)0)
38 
39 /*
40 When opening certain files, we need to simulate the contents.  For example,
41 we can pretend to open the frame buffer, and respond to ioctl()s by
42 returning fake data or telling the front-end to render new data.
43 
44 We want to intercept specific files in /dev.  In some cases we want to
45 intercept and reject, e.g. to indicate that a standard Linux device does
46 not exist.
47 
48 Some things we're not going to intercept:
49   /etc/... (e.g. /etc/timezone) -- std. Linux version should be okay
50   /proc/... (e.g. /proc/stat) -- we're showing real pid, so real proc will work
51 
52 For the device drivers we need to intercept:
53 
54   close(), ioctl(), mmap(), open()/open64(), read(), readv(), write(),
55   writev()
56 
57 May also need stat().  We don't need all fd calls, e.g. fchdir() is
58 not likely to succeed on a device driver.  The expected uses of mmap()
59 shouldn't require intercepting related calls like madvise() -- we will
60 provide an actual mapping of the requested size.  In some cases we will
61 want to return a "real" fd so the app can poll() or select() on it.
62 
63 
64 We also need to consider:
65   getuid/setuid + variations -- fake out multi-user-id stuff
66 
67 
68 We also want to translate filenames, effectively performing a "chroot"
69 without all the baggage that comes with it.  The mapping looks like:
70 
71   /system/... --> $ANDROID_PRODUCT_OUT/system/...
72   /data/... --> $ANDROID_PRODUCT_OUT/data/...
73 
74 Translating pathnames requires interception of additional system calls,
75 substituting a new path.  Calls include:
76 
77   access(), chdir(), chmod(), chown(), creat(), execve(), getcwd(),
78   lchown(), link(), lstat()/lstat64(), mkdir(), open()/open64(),
79   readlink(), rename(), rmdir(), stat()/stat64(), statfs/statfs64(),
80   symlink(), unlink(), utimes(),
81 
82 Possibly also mknod(), mount(), umount().
83 
84 The "at" family, notably openat(), should just work since the root comes
85 from an open directory fd.
86 
87 We also need these libc calls, because LD_LIBRARY_PATH substitutes at
88 the libc link level, not the syscall layer:
89 
90   execl(), execlp(), execle(), execv(), execvp(), fopen(), ftw(), getwd(),
91   opendir(), dlopen()
92 
93 It is possible for the cwd to leak out.  Some possible leaks:
94   - /proc/[self]/exe
95   - /proc/[self]/cwd
96   - LD_LIBRARY_PATH (which may be awkward to work around)
97 
98 
99 To provide a replacement for the dirent functions -- only required if we
100 want to show "fake" directory contents -- we would need:
101 
102   closedir(), dirfd() readdir(), rewinddir(), scandir(), seekdir(),
103   telldir()
104 
105 
106 */
107 
108 
109 /*
110  * ===========================================================================
111  *      Filename remapping
112  * ===========================================================================
113  */
114 
115 /*
116  * If appropriate, rewrite the path to point to a different location.
117  *
118  * Returns either "pathBuf" or "origPath" depending on whether or not we
119  * chose to rewrite the path.  "origPath" must be a buffer capable of
120  * holding an extended pathname; for best results use PATH_MAX.
121  */
rewritePath(const char * func,char * pathBuf,const char * origPath)122 static const char* rewritePath(const char* func, char* pathBuf,
123     const char* origPath)
124 {
125     /*
126      * Rewrite paths that start with "/system/" or "/data/"
127      */
128     if (origPath[0] != '/')
129         goto skip_rewrite;
130     while (origPath[1] == '/') origPath++; // some apps like to use paths like '//data/data/....'
131     if (memcmp(origPath+1, "system", 6) == 0 &&
132         (origPath[7] == '/' || origPath[7] == '\0'))
133             goto do_rewrite;
134     if (memcmp(origPath+1, "data", 4) == 0 &&
135         (origPath[5] == '/' || origPath[5] == '\0'))
136             goto do_rewrite;
137 
138 skip_rewrite:
139     /* check to see if something is side-stepping the rewrite */
140     if (memcmp(origPath, gWrapSim.remapBaseDir, gWrapSim.remapBaseDirLen) == 0)
141     {
142         wsLog("NOTE: full path used: %s(%s)\n", func, origPath);
143     }
144 
145     CALLTRACE("rewrite %s('%s') --> (not rewritten)\n", func, origPath);
146     return origPath;
147 
148 do_rewrite:
149     memcpy(pathBuf, gWrapSim.remapBaseDir, gWrapSim.remapBaseDirLen);
150     strcpy(pathBuf + gWrapSim.remapBaseDirLen, origPath);
151     CALLTRACE("rewrite %s('%s') --> '%s'\n", func, origPath, pathBuf);
152     return pathBuf;
153 }
154 
155 /*
156  * This works if the pathname is the first argument to the function, and
157  * the function returns "int".
158  */
159 #define PASS_THROUGH_DECL(_fname, _rtype, ...)                              \
160     _rtype _fname( __VA_ARGS__ )
161 #define PASS_THROUGH_BODY(_fname, _patharg, ...)                            \
162     {                                                                       \
163         CALLTRACEV("%s(%s)\n", __FUNCTION__, _patharg);                     \
164         char pathBuf[PATH_MAX];                                             \
165         return _ws_##_fname(rewritePath(#_fname, pathBuf, _patharg),        \
166             ##__VA_ARGS__);                                                 \
167     }
168 
169 
PASS_THROUGH_DECL(chdir,int,const char * path)170 PASS_THROUGH_DECL(chdir, int, const char* path)
171 PASS_THROUGH_BODY(chdir, path)
172 
173 PASS_THROUGH_DECL(chmod, int, const char* path, mode_t mode)
174 PASS_THROUGH_BODY(chmod, path, mode)
175 
176 PASS_THROUGH_DECL(chown, int, const char* path, uid_t owner, gid_t group)
177 PASS_THROUGH_BODY(chown, path, owner, group)
178 
179 PASS_THROUGH_DECL(creat, int, const char* path, mode_t mode)
180 PASS_THROUGH_BODY(creat, path, mode)
181 
182 PASS_THROUGH_DECL(execve, int, const char* path, char* const argv[],
183     char* const envp[])
184 PASS_THROUGH_BODY(execve, path, argv, envp)
185 
186 PASS_THROUGH_DECL(lchown, int, const char* path, uid_t owner, gid_t group)
187 PASS_THROUGH_BODY(lchown, path, owner, group)
188 
189 PASS_THROUGH_DECL(lstat, int, const char* path, struct stat* buf)
190 PASS_THROUGH_BODY(lstat, path, buf)
191 
192 PASS_THROUGH_DECL(lstat64, int, const char* path, struct stat* buf)
193 PASS_THROUGH_BODY(lstat64, path, buf)
194 
195 PASS_THROUGH_DECL(mkdir, int, const char* path, mode_t mode)
196 PASS_THROUGH_BODY(mkdir, path, mode)
197 
198 PASS_THROUGH_DECL(readlink, ssize_t, const char* path, char* buf, size_t bufsiz)
199 PASS_THROUGH_BODY(readlink, path, buf, bufsiz)
200 
201 PASS_THROUGH_DECL(rmdir, int, const char* path)
202 PASS_THROUGH_BODY(rmdir, path)
203 
204 PASS_THROUGH_DECL(stat, int, const char* path, struct stat* buf)
205 PASS_THROUGH_BODY(stat, path, buf)
206 
207 PASS_THROUGH_DECL(stat64, int, const char* path, struct stat* buf)
208 PASS_THROUGH_BODY(stat64, path, buf)
209 
210 PASS_THROUGH_DECL(statfs, int, const char* path, struct statfs* buf)
211 PASS_THROUGH_BODY(statfs, path, buf)
212 
213 PASS_THROUGH_DECL(statfs64, int, const char* path, struct statfs* buf)
214 PASS_THROUGH_BODY(statfs64, path, buf)
215 
216 PASS_THROUGH_DECL(unlink, int, const char* path)
217 PASS_THROUGH_BODY(unlink, path)
218 
219 PASS_THROUGH_DECL(utime, int, const char* path, const struct utimbuf* buf)
220 PASS_THROUGH_BODY(utime, path, buf)
221 
222 PASS_THROUGH_DECL(utimes, int, const char* path, const struct timeval times[2])
223 PASS_THROUGH_BODY(utimes, path, times)
224 
225 
226 PASS_THROUGH_DECL(fopen, FILE*, const char* path, const char* mode)
227 PASS_THROUGH_BODY(fopen, path, mode)
228 
229 PASS_THROUGH_DECL(fopen64, FILE*, const char* path, const char* mode)
230 PASS_THROUGH_BODY(fopen64, path, mode)
231 
232 PASS_THROUGH_DECL(freopen, FILE*, const char* path, const char* mode,
233     FILE* stream)
234 PASS_THROUGH_BODY(freopen, path, mode, stream)
235 
236 PASS_THROUGH_DECL(ftw, int, const char* dirpath,
237           int (*fn) (const char* fpath, const struct stat* sb, int typeflag),
238           int nopenfd)
239 PASS_THROUGH_BODY(ftw, dirpath, fn, nopenfd)
240 
241 PASS_THROUGH_DECL(opendir, DIR*, const char* path)
242 PASS_THROUGH_BODY(opendir, path)
243 
244 PASS_THROUGH_DECL(dlopen, void*, const char* path, int flag)
245 PASS_THROUGH_BODY(dlopen, path, flag)
246 
247 /*
248  * Opposite of path translation -- remove prefix.
249  *
250  * It looks like BSD allows you to pass a NULL value for "buf" to inspire
251  * getcwd to allocate storage with malloc() (as an extension to the POSIX
252  * definition, which doesn't specify this).  getcwd() is a system call
253  * under Linux, so this doesn't work, but that doesn't stop gdb from
254  * trying to use it anyway.
255  */
256 char* getcwd(char* buf, size_t size)
257 {
258     CALLTRACEV("%s %p %d\n", __FUNCTION__, buf, size);
259 
260     char* result = _ws_getcwd(buf, size);
261     if (buf != NULL && result != NULL) {
262         if (memcmp(buf, gWrapSim.remapBaseDir,
263                     gWrapSim.remapBaseDirLen) == 0)
264         {
265             memmove(buf, buf + gWrapSim.remapBaseDirLen,
266                 strlen(buf + gWrapSim.remapBaseDirLen)+1);
267             CALLTRACE("rewrite getcwd() -> %s\n", result);
268         } else {
269             CALLTRACE("not rewriting getcwd(%s)\n", result);
270         }
271     }
272     return result;
273 }
274 
275 /*
276  * Need to tweak both pathnames.
277  */
link(const char * oldPath,const char * newPath)278 int link(const char* oldPath, const char* newPath)
279 {
280     CALLTRACEV("%s\n", __FUNCTION__);
281 
282     char pathBuf1[PATH_MAX];
283     char pathBuf2[PATH_MAX];
284     return _ws_link(rewritePath("link-1", pathBuf1, oldPath),
285                     rewritePath("link-2", pathBuf2, newPath));
286 }
287 
288 /*
289  * Need to tweak both pathnames.
290  */
rename(const char * oldPath,const char * newPath)291 int rename(const char* oldPath, const char* newPath)
292 {
293     CALLTRACEV("%s\n", __FUNCTION__);
294 
295     char pathBuf1[PATH_MAX];
296     char pathBuf2[PATH_MAX];
297     return _ws_rename(rewritePath("rename-1", pathBuf1, oldPath),
298                       rewritePath("rename-2", pathBuf2, newPath));
299 }
300 
301 /*
302  * Need to tweak both pathnames.
303  */
symlink(const char * oldPath,const char * newPath)304 int symlink(const char* oldPath, const char* newPath)
305 {
306     CALLTRACEV("%s\n", __FUNCTION__);
307 
308     char pathBuf1[PATH_MAX];
309     char pathBuf2[PATH_MAX];
310     return _ws_symlink(rewritePath("symlink-1", pathBuf1, oldPath),
311                        rewritePath("symlink-2", pathBuf2, newPath));
312 }
313 
314 /*
315  * glibc stat turns into this (32-bit).
316  */
__xstat(int version,const char * path,struct stat * sbuf)317 int __xstat(int version, const char* path, struct stat* sbuf)
318 {
319     CALLTRACEV("%s\n", __FUNCTION__);
320     char pathBuf[PATH_MAX];
321     return _ws___xstat(version, rewritePath("__xstat", pathBuf, path),
322         sbuf);
323 }
324 
325 /*
326  * glibc stat turns into this (64-bit).
327  */
__xstat64(int version,const char * path,struct stat * sbuf)328 int __xstat64(int version, const char* path, struct stat* sbuf)
329 {
330     CALLTRACEV("%s\n", __FUNCTION__);
331     char pathBuf[PATH_MAX];
332     return _ws___xstat64(version, rewritePath("__xstat64", pathBuf, path),
333         sbuf);
334 }
335 
336 /*
337  * glibc lstat turns into this (32-bit).
338  */
__lxstat(int version,const char * path,struct stat * sbuf)339 int __lxstat(int version, const char* path, struct stat* sbuf)
340 {
341     CALLTRACEV("%s\n", __FUNCTION__);
342     char pathBuf[PATH_MAX];
343     return _ws___lxstat(version, rewritePath("__lxstat", pathBuf, path),
344         sbuf);
345 }
346 
347 /*
348  * glibc lstat turns into this (64-bit).
349  */
__lxstat64(int version,const char * path,struct stat * sbuf)350 int __lxstat64(int version, const char* path, struct stat* sbuf)
351 {
352     CALLTRACEV("%s\n", __FUNCTION__);
353     char pathBuf[PATH_MAX];
354     return _ws___lxstat64(version, rewritePath("__lxstat64", pathBuf, path),
355         sbuf);
356 }
357 
358 /*
359  * Copy the argument list out of varargs for execl/execlp/execle.  This
360  * leaves the argc value in _argc, and a NULL-terminated array of character
361  * pointers in _argv.  We stop at the first NULL argument, so we shouldn't
362  * end up copying "envp" out.
363  *
364  * We could use gcc __builtin_apply_args to just pass stuff through,
365  * but that may not get along with the path rewriting.  It's unclear
366  * whether we want to rewrite the first argument (i.e. the string that
367  * becomes argv[0]); it only makes sense if the exec'ed program is also
368  * getting remapped.
369  */
370 #define COPY_EXEC_ARGLIST(_first, _argc, _argv)                             \
371     int _argc = 0;                                                          \
372     {                                                                       \
373         va_list vargs;                                                      \
374         va_start(vargs, _first);                                            \
375         while (1) {                                                         \
376             _argc++;                                                        \
377             const char* val = va_arg(vargs, const char*);                   \
378             if (val == NULL)                                                \
379                 break;                                                      \
380         }                                                                   \
381         va_end(vargs);                                                      \
382     }                                                                       \
383     const char* _argv[_argc+1];                                             \
384     _argv[0] = _first;                                                      \
385     {                                                                       \
386         va_list vargs;                                                      \
387         int i;                                                              \
388         va_start(vargs, _first);                                            \
389         for (i = 1; i < _argc; i++) {                                       \
390             _argv[i] = va_arg(vargs, const char*);                          \
391         }                                                                   \
392         va_end(vargs);                                                      \
393     }                                                                       \
394     _argv[_argc] = NULL;
395 
396 /*
397  * Debug dump.
398  */
dumpExecArgs(const char * callName,const char * path,int argc,const char * argv[],char * const envp[])399 static void dumpExecArgs(const char* callName, const char* path,
400     int argc, const char* argv[], char* const envp[])
401 {
402     int i;
403 
404     CALLTRACE("Calling %s '%s' (envp=%p)\n", callName, path, envp);
405     for (i = 0; i <= argc; i++)
406         CALLTRACE("  %d: %s\n", i, argv[i]);
407 }
408 
409 /*
410  * Extract varargs, convert paths, hand off to execv.
411  */
execl(const char * path,const char * arg,...)412 int execl(const char* path, const char* arg, ...)
413 {
414     CALLTRACEV("%s\n", __FUNCTION__);
415 
416     char pathBuf[PATH_MAX];
417 
418     COPY_EXEC_ARGLIST(arg, argc, argv);
419     dumpExecArgs("execl", path, argc, argv, NULL);
420     path = rewritePath("execl", pathBuf, path);
421     return _ws_execv(path, (char* const*) argv);
422 }
423 
424 /*
425  * Extract varargs, convert paths, hand off to execve.
426  *
427  * The execle prototype in the man page isn't valid C -- it shows the
428  * "envp" argument after the "...".  We have to pull it out with the rest
429  * of the varargs.
430  */
execle(const char * path,const char * arg,...)431 int execle(const char* path, const char* arg, ...)
432 {
433     CALLTRACEV("%s\n", __FUNCTION__);
434 
435     char pathBuf[PATH_MAX];
436 
437     COPY_EXEC_ARGLIST(arg, argc, argv);
438 
439     /* run through again and find envp */
440     char* const* envp;
441 
442     va_list vargs;
443     va_start(vargs, arg);
444     while (1) {
445         const char* val = va_arg(vargs, const char*);
446         if (val == NULL) {
447             envp = va_arg(vargs, char* const*);
448             break;
449         }
450     }
451     va_end(vargs);
452 
453     dumpExecArgs("execle", path, argc, argv, envp);
454     path = rewritePath("execl", pathBuf, path);
455 
456     return _ws_execve(path, (char* const*) argv, envp);
457 }
458 
459 /*
460  * Extract varargs, convert paths, hand off to execvp.
461  */
execlp(const char * file,const char * arg,...)462 int execlp(const char* file, const char* arg, ...)
463 {
464     CALLTRACEV("%s\n", __FUNCTION__);
465 
466     char pathBuf[PATH_MAX];
467 
468     COPY_EXEC_ARGLIST(arg, argc, argv);
469     dumpExecArgs("execlp", file, argc, argv, NULL);
470     file = rewritePath("execlp", pathBuf, file);
471     return _ws_execvp(file, (char* const*) argv);
472 }
473 
474 /*
475  * Update path, forward to execv.
476  */
execv(const char * path,char * const argv[])477 int execv(const char* path, char* const argv[])
478 {
479     CALLTRACEV("%s\n", __FUNCTION__);
480 
481     char pathBuf[PATH_MAX];
482 
483     path = rewritePath("execv", pathBuf, path);
484     return _ws_execv(path, argv);
485 }
486 
487 /*
488  * Shouldn't need to do anything unless they specified a full path to execvp.
489  */
execvp(const char * file,char * const argv[])490 int execvp(const char* file, char* const argv[])
491 {
492     CALLTRACEV("%s\n", __FUNCTION__);
493 
494     char pathBuf[PATH_MAX];
495 
496     file = rewritePath("execvp", pathBuf, file);
497     return _ws_execvp(file, argv);
498 }
499 
500 
501 /*
502  * ===========================================================================
503  *      Device fakery
504  * ===========================================================================
505  */
506 
507 /*
508  * Need to do filesystem translation and show fake devices.
509  */
access(const char * pathName,int mode)510 int access(const char* pathName, int mode)
511 {
512     CALLTRACEV("%s\n", __FUNCTION__);
513 
514     int status = wsInterceptDeviceAccess(pathName, mode);
515     if (status == 0)
516         return 0;
517     else if (status == -2)
518         return -1;          // errno already set
519     else {
520         char pathBuf[PATH_MAX];
521         return _ws_access(rewritePath("access", pathBuf, pathName), mode);
522     }
523 }
524 
525 /*
526  * Common handler for open().
527  */
openCommon(const char * pathName,int flags,mode_t mode)528 int openCommon(const char* pathName, int flags, mode_t mode)
529 {
530     char pathBuf[PATH_MAX];
531     int fd;
532 
533     assert(gWrapSim.initialized);
534 
535     fd = wsInterceptDeviceOpen(pathName, flags);
536     if (fd >= 0) {
537         return fd;
538     } else if (fd == -2) {
539         /* errno should be set */
540         return -1;
541     }
542 
543     if ((flags & O_CREAT) != 0) {
544         fd = _ws_open(rewritePath("open", pathBuf, pathName), flags, mode);
545         CALLTRACE("open(%s, 0x%x, 0%o) = %d\n", pathName, flags, mode, fd);
546     } else {
547         fd = _ws_open(rewritePath("open", pathBuf, pathName), flags, 0);
548         CALLTRACE("open(%s, 0x%x) = %d\n", pathName, flags, fd);
549     }
550     return fd;
551 }
552 
553 /*
554  * Replacement open() and variants.
555  *
556  * We have to use the vararg decl for the standard call so it matches
557  * the definition in fcntl.h.
558  */
open(const char * pathName,int flags,...)559 int open(const char* pathName, int flags, ...)
560 {
561     CALLTRACEV("%s\n", __FUNCTION__);
562 
563     mode_t mode = 0;
564     if ((flags & O_CREAT) != 0) {
565         va_list args;
566 
567         va_start(args, flags);
568         mode = va_arg(args, mode_t);
569         va_end(args);
570     }
571 
572     return openCommon(pathName, flags, mode);
573 }
__open(const char * pathName,int flags,mode_t mode)574 int __open(const char* pathName, int flags, mode_t mode)
575 {
576     CALLTRACEV("%s\n", __FUNCTION__);
577 
578     return openCommon(pathName, flags, mode);
579 }
580 
581 /*
582  * Common handler for open64().
583  */
open64Common(const char * pathName,int flags,mode_t mode)584 int open64Common(const char* pathName, int flags, mode_t mode)
585 {
586     char pathBuf[PATH_MAX];
587     int fd;
588 
589     assert(gWrapSim.initialized);
590 
591     fd = wsInterceptDeviceOpen(pathName, flags);
592     if (fd >= 0) {
593         return fd;
594     }
595 
596     if ((flags & O_CREAT) != 0) {
597         fd = _ws_open64(rewritePath("open64", pathBuf, pathName), flags, mode);
598         CALLTRACE("open64(%s, 0x%x, 0%o) = %d\n", pathName, flags, mode, fd);
599     } else {
600         fd = _ws_open64(rewritePath("open64", pathBuf, pathName), flags, 0);
601         CALLTRACE("open64(%s, 0x%x) = %d\n", pathName, flags, fd);
602     }
603     return fd;
604 }
605 
606 /*
607  * Replacement open64() and variants.
608  *
609  * We have to use the vararg decl for the standard call so it matches
610  * the definition in fcntl.h.
611  */
open64(const char * pathName,int flags,...)612 int open64(const char* pathName, int flags, ...)
613 {
614     CALLTRACEV("%s\n", __FUNCTION__);
615 
616     mode_t mode = 0;
617     if ((flags & O_CREAT) != 0) {
618         va_list args;
619 
620         va_start(args, flags);
621         mode = va_arg(args, mode_t);
622         va_end(args);
623     }
624     return open64Common(pathName, flags, mode);
625 }
__open64(const char * pathName,int flags,mode_t mode)626 int __open64(const char* pathName, int flags, mode_t mode)
627 {
628     CALLTRACEV("%s\n", __FUNCTION__);
629 
630     return open64Common(pathName, flags, mode);
631 }
632 
633 
dup(int fd)634 int dup(int fd)
635 {
636     CALLTRACEV("%s(%d)\n", __FUNCTION__, fd);
637 
638     FakeDev* dev = wsFakeDevFromFd(fd);
639     if (dev != NULL) {
640         FakeDev* newDev = dev->dup(dev, fd);
641         if (newDev != NULL) {
642             /*
643              * Now that the device entry is ready, add it to the list.
644              */
645             wsLog("## dup'ed fake dev %d: '%s' %p\n",
646                 newDev->fd, newDev->debugName, newDev->state);
647             gWrapSim.fakeFdList[newDev->fd - kFakeFdBase] = newDev;
648             return newDev->fd;
649         }
650         return -1;
651     } else {
652         CALLTRACE("dup(%d)\n", fd);
653         return _ws_dup(fd);
654     }
655 }
656 
657 
658 /*
659  * Close a file descriptor.
660  */
close(int fd)661 int close(int fd)
662 {
663     CALLTRACEV("%s(%d)\n", __FUNCTION__, fd);
664 
665     FakeDev* dev = wsFakeDevFromFd(fd);
666     if (dev != NULL) {
667         int result = dev->close(dev, fd);
668         wsFreeFakeDev(dev);
669         return result;
670     } else {
671         CALLTRACE("close(%d)\n", fd);
672         return _ws_close(fd);
673     }
674 }
675 
676 /*
677  * Map a region.
678  */
mmap(void * start,size_t length,int prot,int flags,int fd,__off_t offset)679 void* mmap(void* start, size_t length, int prot, int flags, int fd,
680     __off_t offset)
681 {
682     CALLTRACEV("%s\n", __FUNCTION__);
683 
684     FakeDev* dev = wsFakeDevFromFd(fd);
685     if (dev != NULL) {
686         return dev->mmap(dev, start, length, prot, flags, fd, offset);
687     } else {
688         CALLTRACE("mmap(%p, %d, %d, %d, %d, %d)\n",
689             start, (int) length, prot, flags, fd, (int) offset);
690         return _ws_mmap(start, length, prot, flags, fd, offset);
691     }
692 }
693 
694 /*
695  * Map a region.
696  */
mmap64(void * start,size_t length,int prot,int flags,int fd,__off64_t offset)697 void* mmap64(void* start, size_t length, int prot, int flags, int fd,
698     __off64_t offset)
699 {
700     CALLTRACEV("%s\n", __FUNCTION__);
701 
702     FakeDev* dev = wsFakeDevFromFd(fd);
703     if (dev != NULL) {
704         return dev->mmap(dev, start, length, prot, flags, fd, (__off_t) offset);
705     } else {
706         CALLTRACE("mmap64(%p, %d, %d, %d, %d, %d)\n",
707             start, (int) length, prot, flags, fd, (int) offset);
708         return _ws_mmap(start, length, prot, flags, fd, offset);
709     }
710 }
711 
712 /*
713  * The Linux headers show this with a vararg header, but as far as I can
714  * tell the kernel always expects 3 args.
715  */
ioctl(int fd,int request,...)716 int ioctl(int fd, int request, ...)
717 {
718     CALLTRACEV("%s(%d, %d, ...)\n", __FUNCTION__, fd, request);
719 
720     FakeDev* dev = wsFakeDevFromFd(fd);
721     va_list args;
722     void* argp;
723 
724     /* extract argp from varargs */
725     va_start(args, request);
726     argp = va_arg(args, void*);
727     va_end(args);
728 
729     if (dev != NULL) {
730         return dev->ioctl(dev, fd, request, argp);
731     } else {
732         CALLTRACE("ioctl(%d, 0x%x, %p)\n", fd, request, argp);
733         return _ws_ioctl(fd, request, argp);
734     }
735 }
736 
737 /*
738  * Read data.
739  */
read(int fd,void * buf,size_t count)740 ssize_t read(int fd, void* buf, size_t count)
741 {
742     CALLTRACEV("%s\n", __FUNCTION__);
743 
744     FakeDev* dev = wsFakeDevFromFd(fd);
745     if (dev != NULL) {
746         return dev->read(dev, fd, buf, count);
747     } else {
748         CALLTRACE("read(%d, %p, %u)\n", fd, buf, count);
749         return _ws_read(fd, buf, count);
750     }
751 }
752 
753 /*
754  * Write data.
755  */
write(int fd,const void * buf,size_t count)756 ssize_t write(int fd, const void* buf, size_t count)
757 {
758     CALLTRACEV("%s\n", __FUNCTION__);
759 
760     FakeDev* dev = wsFakeDevFromFd(fd);
761     if (dev != NULL) {
762         return dev->write(dev, fd, buf, count);
763     } else {
764         CALLTRACE("write(%d, %p, %u)\n", fd, buf, count);
765         return _ws_write(fd, buf, count);
766     }
767 }
768 
769 /*
770  * Read a data vector.
771  */
readv(int fd,const struct iovec * vector,int count)772 ssize_t readv(int fd, const struct iovec* vector, int count)
773 {
774     CALLTRACEV("%s\n", __FUNCTION__);
775 
776     FakeDev* dev = wsFakeDevFromFd(fd);
777     if (dev != NULL) {
778         return dev->readv(dev, fd, vector, count);
779     } else {
780         CALLTRACE("readv(%d, %p, %u)\n", fd, vector, count);
781         return _ws_readv(fd, vector, count);
782     }
783 }
784 
785 /*
786  * Write a data vector.
787  */
writev(int fd,const struct iovec * vector,int count)788 ssize_t writev(int fd, const struct iovec* vector, int count)
789 {
790     CALLTRACEV("%s\n", __FUNCTION__);
791 
792     FakeDev* dev = wsFakeDevFromFd(fd);
793     if (dev != NULL) {
794         return dev->writev(dev, fd, vector, count);
795     } else {
796         CALLTRACE("writev(%d, %p, %u)\n", fd, vector, count);
797         return _ws_writev(fd, vector, count);
798     }
799 }
800 
801 /*
802  * Set the scheduling priority.  The sim doesn't run as root, so we have
803  * to fake this out.
804  *
805  * For now, do some basic verification of the which and who parameters,
806  * but otherwise return success.  In the future we may want to track
807  * these so getpriority works.
808  */
setpriority(__priority_which_t which,id_t who,int what)809 int setpriority(__priority_which_t which, id_t who, int what)
810 {
811     CALLTRACEV("%s\n", __FUNCTION__);
812 
813     if (which != PRIO_PROCESS &&
814         which != PRIO_PGRP &&
815         which != PRIO_USER) {
816         return EINVAL;
817     }
818 
819     if ((int)who < 0) {
820         return ESRCH;
821     }
822 
823     return 0;
824 }
825 
826 /*
827  * Pretend to be running as root, so the Android framework
828  * doesn't complain about permission problems all over the
829  * place.
830  */
getuid(void)831 uid_t getuid(void)
832 {
833     return 0;
834 }
835 
836 #if 0
837 /*
838  * Create a pipe.  (Only needed for debugging an fd leak.)
839  */
840 int pipe(int filedes[2])
841 {
842     CALLTRACEV("%s\n", __FUNCTION__);
843 
844     int result = _ws_pipe(filedes);
845     if (result == 0)
846         CALLTRACE("pipe(%p) -> %d,%d\n", filedes, filedes[0], filedes[1]);
847     if (filedes[0] == 83)
848         abort();
849     return result;
850 }
851 #endif
852