Home | History | Annotate | Download | only in wrapsim
      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  */
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 }
    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  */
    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  */
    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 }
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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