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