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