| /* | 
 |  * Copyright 2007 The Android Open Source Project | 
 |  * | 
 |  * Initialize the intercepts. | 
 |  */ | 
 | #include "Common.h" | 
 |  | 
 | #define __USE_GNU       /* need RTLD_NEXT */ | 
 | #include <dlfcn.h> | 
 |  | 
 | #include <stdlib.h> | 
 | #include <pthread.h> | 
 | #include <string.h> | 
 | #include <errno.h> | 
 | #include <assert.h> | 
 | #include <sys/stat.h> | 
 | #include <sys/types.h> | 
 |  | 
 |  | 
 | /* | 
 |  * Global state. | 
 |  */ | 
 | struct WrapSimGlobals gWrapSim; | 
 | pthread_once_t gWrapSimInitialized = PTHREAD_ONCE_INIT; | 
 |  | 
 | /* | 
 |  * Initialize our global state. | 
 |  */ | 
 | static void initGlobals(void) | 
 | { | 
 |     memset(&gWrapSim, 0xdd, sizeof(gWrapSim)); | 
 |     gWrapSim.logFd = -1; | 
 |     gWrapSim.keyMap = NULL; | 
 |  | 
 |     /* | 
 |      * Find the original version of functions we override. | 
 |      */ | 
 |     _ws_access = dlsym(RTLD_NEXT, "access"); | 
 |     _ws_open = dlsym(RTLD_NEXT, "open"); | 
 |     _ws_open64 = dlsym(RTLD_NEXT, "open64"); | 
 |  | 
 |     _ws_close = dlsym(RTLD_NEXT, "close"); | 
 |     _ws_read = dlsym(RTLD_NEXT, "read"); | 
 |     _ws_readv = dlsym(RTLD_NEXT, "readv"); | 
 |     _ws_write = dlsym(RTLD_NEXT, "write"); | 
 |     _ws_writev = dlsym(RTLD_NEXT, "writev"); | 
 |     _ws_mmap = dlsym(RTLD_NEXT, "mmap"); | 
 |     _ws_mmap64 = dlsym(RTLD_NEXT, "mmap64"); | 
 |     _ws_ioctl = dlsym(RTLD_NEXT, "ioctl"); | 
 |  | 
 |     _ws_chdir = dlsym(RTLD_NEXT, "chdir"); | 
 |     _ws_chmod = dlsym(RTLD_NEXT, "chmod"); | 
 |     _ws_chown = dlsym(RTLD_NEXT, "chown"); | 
 |     _ws_creat = dlsym(RTLD_NEXT, "creat"); | 
 |     _ws_execve = dlsym(RTLD_NEXT, "execve"); | 
 |     _ws_getcwd = dlsym(RTLD_NEXT, "getcwd"); | 
 |     _ws_lchown = dlsym(RTLD_NEXT, "lchown"); | 
 |     _ws_link = dlsym(RTLD_NEXT, "link"); | 
 |     _ws_lstat = dlsym(RTLD_NEXT, "lstat"); | 
 |     _ws_lstat64 = dlsym(RTLD_NEXT, "lstat64"); | 
 |     _ws___lxstat = dlsym(RTLD_NEXT, "__lxstat"); | 
 |     _ws___lxstat64 = dlsym(RTLD_NEXT, "__lxstat64"); | 
 |     _ws_mkdir = dlsym(RTLD_NEXT, "mkdir"); | 
 |     _ws_readlink = dlsym(RTLD_NEXT, "readlink"); | 
 |     _ws_rename = dlsym(RTLD_NEXT, "rename"); | 
 |     _ws_rmdir = dlsym(RTLD_NEXT, "rmdir"); | 
 |     _ws_stat = dlsym(RTLD_NEXT, "stat"); | 
 |     _ws_stat64 = dlsym(RTLD_NEXT, "stat64"); | 
 |     _ws___xstat = dlsym(RTLD_NEXT, "__xstat"); | 
 |     _ws___xstat64 = dlsym(RTLD_NEXT, "__xstat64"); | 
 |     _ws_statfs = dlsym(RTLD_NEXT, "statfs"); | 
 |     _ws_statfs64 = dlsym(RTLD_NEXT, "statfs64"); | 
 |     _ws_symlink = dlsym(RTLD_NEXT, "symlink"); | 
 |     _ws_unlink = dlsym(RTLD_NEXT, "unlink"); | 
 |     _ws_utime = dlsym(RTLD_NEXT, "utime"); | 
 |     _ws_utimes = dlsym(RTLD_NEXT, "utimes"); | 
 |  | 
 |     _ws_execl = dlsym(RTLD_NEXT, "execl"); | 
 |     _ws_execle = dlsym(RTLD_NEXT, "execle"); | 
 |     _ws_execlp = dlsym(RTLD_NEXT, "execlp"); | 
 |     _ws_execv = dlsym(RTLD_NEXT, "execv"); | 
 |     _ws_execvp = dlsym(RTLD_NEXT, "execvp"); | 
 |     _ws_fopen = dlsym(RTLD_NEXT, "fopen"); | 
 |     _ws_fopen64 = dlsym(RTLD_NEXT, "fopen64"); | 
 |     _ws_freopen = dlsym(RTLD_NEXT, "freopen"); | 
 |     _ws_ftw = dlsym(RTLD_NEXT, "ftw"); | 
 |     _ws_opendir = dlsym(RTLD_NEXT, "opendir"); | 
 |     _ws_dlopen = dlsym(RTLD_NEXT, "dlopen"); | 
 |  | 
 |     _ws_setpriority = dlsym(RTLD_NEXT, "setpriority"); | 
 |     //_ws_pipe = dlsym(RTLD_NEXT, "pipe"); | 
 |  | 
 |     const char* logFileName = getenv("WRAPSIM_LOG"); | 
 |     if (logFileName != NULL ){ | 
 |         gWrapSim.logFd = _ws_open(logFileName, O_WRONLY|O_APPEND|O_CREAT, 0664); | 
 |     } | 
 |  | 
 |     /* log messages now work; say hello */ | 
 |     wsLog("--- initializing sim wrapper ---\n"); | 
 |  | 
 |     gWrapSim.simulatorFd = -1; | 
 |  | 
 |     pthread_mutex_init(&gWrapSim.startLock, NULL); | 
 |     pthread_cond_init(&gWrapSim.startCond, NULL); | 
 |     gWrapSim.startReady = 0; | 
 |  | 
 |     pthread_mutex_init(&gWrapSim.fakeFdLock, NULL); | 
 |     gWrapSim.fakeFdMap = wsAllocBitVector(kMaxFakeFdCount, 0); | 
 |     memset(gWrapSim.fakeFdList, 0, sizeof(gWrapSim.fakeFdList)); | 
 |  | 
 |     gWrapSim.numDisplays = 0; | 
 |  | 
 |     gWrapSim.keyInputDevice = NULL; | 
 |  | 
 |     /* | 
 |      * Get target for remapped "/system" and "/data". | 
 |      * | 
 |      * The ANDROID_PRODUCT_OUT env var *must* be set for rewriting to work. | 
 |      */ | 
 |     const char* outEnv = getenv("ANDROID_PRODUCT_OUT"); | 
 |     if (outEnv == NULL) { | 
 |         gWrapSim.remapBaseDir = NULL; | 
 |         wsLog("--- $ANDROID_PRODUCT_OUT not set, " | 
 |                 "filename remapping disabled\n"); | 
 |     } else { | 
 |         /* grab string and append '/' -- note this never gets freed */ | 
 |         gWrapSim.remapBaseDirLen = strlen(outEnv); | 
 |         gWrapSim.remapBaseDir = strdup(outEnv); | 
 |         wsLog("--- name remap to %s\n", gWrapSim.remapBaseDir); | 
 |     } | 
 |  | 
 |     gWrapSim.initialized = 1; | 
 | } | 
 |  | 
 | /* | 
 |  * Creates a directory, or prints a log message if it fails. | 
 |  */ | 
 | static int createTargetDirectory(const char *path, mode_t mode) | 
 | { | 
 |     int ret; | 
 |  | 
 |     ret = mkdir(path, mode); | 
 |     if (ret == 0 || errno == EEXIST) { | 
 |         return 0; | 
 |     } | 
 |     wsLog("--- could not create target directory %s: %s\n", | 
 |             path, strerror(errno)); | 
 |     return ret; | 
 | } | 
 |  | 
 | /* | 
 |  * Any setup that would normally be done by init(8). | 
 |  * Note that since the syscall redirects have been installed | 
 |  * at this point, we are effectively operating within the | 
 |  * simulation context. | 
 |  */ | 
 | static void initGeneral(void) | 
 | { | 
 |     wsLog("--- preparing system\n"); | 
 |  | 
 |     /* Try to make sure that certain directories exist. | 
 |      * If we fail to create them, the errors will show up in the log, | 
 |      * but we keep going. | 
 |      */ | 
 |     createTargetDirectory("/data", 0777); | 
 |     createTargetDirectory("/data/dalvik-cache", 0777); | 
 | } | 
 |  | 
 | /* | 
 |  * Initialize all necessary state, and indicate that we're ready to go. | 
 |  */ | 
 | static void initOnce(void) | 
 | { | 
 |     initGlobals(); | 
 |     initGeneral(); | 
 | } | 
 |  | 
 | /* | 
 |  * Shared object initializer.  glibc guarantees that this function is | 
 |  * called before dlopen() returns.  It may be called multiple times. | 
 |  */ | 
 | __attribute__((constructor)) | 
 | static void initialize(void) | 
 | { | 
 |     pthread_once(&gWrapSimInitialized, initOnce); | 
 | } | 
 |  | 
 |  |