do yet more path wrapping
[ginge.git] / loader / override.c
... / ...
CommitLineData
1/*
2 * GINGE - GINGE Is Not Gp2x Emulator
3 * (C) notaz, 2010-2011,2016
4 *
5 * This work is licensed under the MAME license, see COPYING file for details.
6 */
7#include <stdio.h>
8#include <stdlib.h>
9#include <stdarg.h>
10#include <string.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <sys/mman.h>
15#include <unistd.h>
16#include <sys/ioctl.h>
17#include <signal.h>
18#include <termios.h>
19#include <errno.h>
20
21#include "realfuncs.h"
22#include "syscalls.h"
23#include "llibc.h"
24#include "header.h"
25
26#if (DBG & 1)
27#define strace g_printf
28#else
29#define strace(...)
30#endif
31
32#define UNUSED __attribute__((unused))
33
34static const struct dev_fd_t takeover_devs[] = {
35 { "/dev/mem", FAKEDEV_MEM },
36 { "/dev/GPIO", FAKEDEV_GPIO },
37 { "/dev/fb0", FAKEDEV_FB0 },
38 { "/dev/fb/0", FAKEDEV_FB0 },
39 { "/dev/fb1", FAKEDEV_FB1 },
40 { "/dev/fb/1", FAKEDEV_FB1 },
41 { "/dev/mmuhack", FAKEDEV_MMUHACK },
42 { "/dev/tty", FAKEDEV_TTY0 },
43 { "/dev/tty0", FAKEDEV_TTY0 },
44 { "/dev/touchscreen/wm97xx", FAKEDEV_WM97XX },
45 { "/etc/pointercal", FAKEDEV_WM97XX_P },
46#ifdef PND
47 { "/dev/input/event*", -1 }, // hide for now, may cause dupe events
48#endif
49};
50
51long w_open_raw(const char *pathname, int flags, mode_t mode)
52{
53 long ret;
54 int i;
55
56 for (i = 0; i < ARRAY_SIZE(takeover_devs); i++) {
57 const char *p, *oname;
58 int len;
59
60 oname = takeover_devs[i].name;
61 p = strchr(oname, '*');
62 if (p != NULL)
63 len = p - oname;
64 else
65 len = strlen(oname) + 1;
66
67 if (strncmp(pathname, oname, len) == 0) {
68 ret = takeover_devs[i].fd;
69 break;
70 }
71 }
72
73 if (i == ARRAY_SIZE(takeover_devs)) {
74 const char *w_path = emu_wrap_path(pathname);
75 ret = g_open_raw(w_path, flags, mode);
76 emu_wrap_path_free(w_path, pathname);
77 }
78
79 if (ret >= 0) {
80 for (i = 0; emu_interesting_fds[i].name != NULL; i++) {
81 struct dev_fd_t *eifd = &emu_interesting_fds[i];
82 if (strcmp(pathname, eifd->name) == 0) {
83 eifd->fd = ret;
84 if (eifd->open_cb != NULL)
85 eifd->open_cb(ret);
86 break;
87 }
88 }
89 }
90
91 strace("open(%s) = %ld\n", pathname, ret);
92 return ret;
93}
94
95static int w_open(const char *pathname, int flags, mode_t mode)
96{
97 long ret = w_open_raw(pathname, flags, mode);
98 return g_syscall_error(ret);
99}
100
101static long w_mmap_raw(void *addr, size_t length, int prot, int flags,
102 int fd, off_t offset)
103{
104 long ret;
105
106 if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY)
107 ret = emu_do_mmap(length, prot, flags, fd, offset);
108 else
109 ret = g_mmap2_raw(addr, length, prot, flags, fd, offset >> 12);
110
111 strace("mmap(%p, %x, %x, %x, %d, %lx) = %lx\n",
112 addr, length, prot, flags, fd, (long)offset, ret);
113 return ret;
114}
115
116static long w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
117{
118 long ret = w_mmap_raw(addr, length, prot, flags, fd, offset);
119 return g_syscall_error(ret);
120}
121#define w_mmap2 w_mmap
122
123static long w_munmap_raw(void *addr, size_t length)
124{
125 long ret;
126
127 ret = emu_do_munmap(addr, length);
128 if (ret == -EAGAIN)
129 ret = g_munmap_raw(addr, length);
130
131 strace("munmap(%p, %x) = %ld\n", addr, length, ret);
132 return ret;
133}
134
135static int w_munmap(void *addr, size_t length)
136{
137 long ret = w_munmap_raw(addr, length);
138 return g_syscall_error(ret);
139}
140
141long w_read_raw(int fd, void *buf, size_t count)
142{
143 long ret;
144
145 if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY)
146 ret = emu_do_read(fd, buf, count);
147 else
148 ret = g_read_raw(fd, buf, count);
149
150 //strace("read(%d, %p, %zd) = %ld\n", fd, buf, count, ret);
151 return ret;
152}
153
154static ssize_t w_read(int fd, void *buf, size_t count)
155{
156 long ret = w_read_raw(fd, buf, count);
157 return g_syscall_error(ret);
158}
159
160long w_ioctl_raw(int fd, int request, void *argp)
161{
162 long ret;
163
164 if ((FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) ||
165 fd == emu_interesting_fds[IFD_SOUND].fd)
166 ret = emu_do_ioctl(fd, request, argp);
167 else
168 ret = g_ioctl_raw(fd, request, argp);
169
170 strace("ioctl(%d, %08x, %p) = %ld\n", fd, request, argp, ret);
171 return ret;
172}
173
174static int w_ioctl(int fd, int request, void *argp)
175{
176 long ret = w_ioctl_raw(fd, request, argp);
177 return g_syscall_error(ret);
178}
179
180static int w_sigaction(int signum, const void *act, void *oldact)
181{
182 strace("sigaction(%d, %p, %p) = %d\n", signum, act, oldact, 0);
183 return 0;
184}
185
186/* dynamic only */
187static UNUSED int w_tcgetattr(int fd, struct termios *termios_p)
188{
189 int ret;
190 if (fd != FAKEDEV_TTY0)
191 ret = tcgetattr(fd, termios_p);
192 else
193 ret = 0;
194
195 strace("tcgetattr(%d, %p) = %d\n", fd, termios_p, ret);
196 return ret;
197}
198
199static UNUSED int w_tcsetattr(int fd, int optional_actions,
200 const struct termios *termios_p)
201{
202 int ret;
203 if (fd != FAKEDEV_TTY0)
204 ret = tcsetattr(fd, optional_actions, termios_p);
205 else
206 ret = 0;
207
208 strace("tcsetattr(%d, %x, %p) = %d\n", fd, optional_actions, termios_p, ret);
209 return ret;
210}
211
212static UNUSED FILE *w_fopen(const char *path, const char *mode)
213{
214 FILE *ret = emu_do_fopen(path, mode);
215 strace("fopen(%s, %s) = %p\n", path, mode, ret);
216 return ret;
217}
218
219static UNUSED int w_system(const char *command)
220{
221 int ret = emu_do_system(command);
222 strace("system(%s) = %d\n", command, ret);
223 return ret;
224}
225
226extern char **environ;
227
228static UNUSED int w_execl(const char *path, const char *arg, ...)
229{
230 // don't allow exec (for now)
231 strace("execl(%s, %s, ...) = ?\n", path, arg);
232 exit(1);
233}
234
235static UNUSED int w_execlp(const char *file, const char *arg, ...)
236{
237 strace("execlp(%s, %s, ...) = ?\n", file, arg);
238 exit(1);
239}
240
241static UNUSED int w_execle(const char *path, const char *arg, ...)
242{
243 strace("execle(%s, %s, ...) = ?\n", path, arg);
244 exit(1);
245}
246
247static UNUSED int w_execv(const char *path, char *const argv[])
248{
249 strace("execv(%s, %p) = ?\n", path, argv);
250 return emu_do_execve(path, argv, environ);
251}
252
253static UNUSED int w_execvp(const char *file, char *const argv[])
254{
255 strace("execvp(%s, %p) = ?\n", file, argv);
256 return emu_do_execve(file, argv, environ);
257}
258
259long w_execve_raw(const char *filename, char * const argv[],
260 char * const envp[])
261{
262 strace("execve(%s, %p, %p) = ?\n", filename, argv, envp);
263 return emu_do_execve(filename, argv, envp);
264}
265
266static UNUSED int w_execve(const char *filename, char * const argv[],
267 char * const envp[])
268{
269 long ret = w_execve_raw(filename, argv, envp);
270 return g_syscall_error(ret);
271}
272
273static int w_chdir(const char *path)
274{
275 long ret;
276
277 if (path != NULL && strstr(path, "/usr/gp2x") != NULL)
278 ret = 0;
279 else
280 ret = g_chdir_raw(path);
281
282 strace("chdir(%s) = %ld\n", path, ret);
283 return g_syscall_error(ret);
284}
285
286static ssize_t w_readlink(const char *path, char *buf, size_t bufsiz)
287{
288 long ret;
289
290#ifndef DL
291 if (path != NULL && strncmp(path, "/proc/", 6) == 0
292 && strcmp(strrchr(path, '/'), "/exe") == 0)
293 {
294 ret = snprintf(buf, bufsiz, "%s", bin_path);
295 if (ret > bufsiz)
296 ret = bufsiz;
297 }
298 else
299#endif
300 ret = g_readlink_raw(path, buf, bufsiz);
301
302 strace("readlink(%s, %s, %zd) = %ld\n", path, buf, bufsiz, ret);
303 return g_syscall_error(ret);
304}
305
306#undef open
307#undef fopen
308#undef mmap
309#undef munmap
310#undef read
311#undef ioctl
312#undef close
313#undef sigaction
314#undef tcgetattr
315#undef tcsetattr
316#undef system
317#undef execl
318#undef execlp
319#undef execle
320#undef execv
321#undef execvp
322#undef execve
323#undef chdir
324#undef readlink
325
326#ifdef DL
327
328#define MAKE_WRAP_SYM_N(sym) \
329 /* alias wrap symbols to real names */ \
330 typeof(sym) sym __attribute__((alias("w_" #sym)))
331
332#define MAKE_WRAP_SYM(sym) \
333 MAKE_WRAP_SYM_N(sym); \
334 /* wrapper to real functions, to be set up on load */ \
335 static typeof(sym) *p_real_##sym
336
337// note: update symver too
338MAKE_WRAP_SYM_N(open);
339MAKE_WRAP_SYM(fopen);
340MAKE_WRAP_SYM_N(mmap);
341MAKE_WRAP_SYM_N(munmap);
342MAKE_WRAP_SYM_N(read);
343MAKE_WRAP_SYM_N(ioctl);
344MAKE_WRAP_SYM(sigaction);
345MAKE_WRAP_SYM(tcgetattr);
346MAKE_WRAP_SYM(tcsetattr);
347MAKE_WRAP_SYM(system);
348MAKE_WRAP_SYM_N(execl);
349MAKE_WRAP_SYM_N(execlp);
350MAKE_WRAP_SYM_N(execle);
351MAKE_WRAP_SYM_N(execv);
352MAKE_WRAP_SYM_N(execvp);
353MAKE_WRAP_SYM_N(execve);
354MAKE_WRAP_SYM_N(chdir);
355MAKE_WRAP_SYM_N(readlink);
356typeof(mmap) mmap2 __attribute__((alias("w_mmap")));
357
358#define REAL_FUNC_NP(name) \
359 { #name, (void **)&p_real_##name }
360
361static const struct {
362 const char *name;
363 void **func_ptr;
364} real_funcs_np[] = {
365 //REAL_FUNC_NP(open),
366 REAL_FUNC_NP(fopen),
367 //REAL_FUNC_NP(mmap),
368 //REAL_FUNC_NP(munmap),
369 //REAL_FUNC_NP(read),
370 //REAL_FUNC_NP(ioctl),
371 REAL_FUNC_NP(sigaction),
372 REAL_FUNC_NP(tcgetattr),
373 REAL_FUNC_NP(tcsetattr),
374 REAL_FUNC_NP(system),
375 // exec* - skipped
376 //REAL_FUNC_NP(execve),
377 //REAL_FUNC_NP(chdir),
378};
379
380//#define open p_real_open
381#define fopen p_real_fopen
382//#define mmap p_real_mmap
383//#define munmap p_real_munmap
384//#define read p_real_read
385//#define ioctl p_real_ioctl
386#define sigaction p_real_sigaction
387#define tcgetattr p_real_tcgetattr
388#define tcsetattr p_real_tcsetattr
389#define system p_real_system
390//#define execve p_real_execve
391//#define chdir p_real_chdir
392
393#undef MAKE_WRAP_SYM
394#undef REAL_FUNC_NP
395
396#endif
397
398// just call real funcs for static, pointer for dynamic
399int real_open(const char *pathname, int flags, ...)
400{
401 va_list ap;
402 mode_t mode;
403 long ret;
404
405 va_start(ap, flags);
406 mode = va_arg(ap, mode_t);
407 va_end(ap);
408 ret = g_open_raw(pathname, flags, mode);
409 return g_syscall_error(ret);
410}
411
412FILE *real_fopen(const char *path, const char *mode)
413{
414 return fopen(path, mode);
415}
416
417void *real_mmap(void *addr, size_t length, int prot, int flags,
418 int fd, off_t offset)
419{
420 long ret = g_mmap2_raw(addr, length, prot, flags, fd, offset >> 12);
421 return (void *)g_syscall_error(ret);
422}
423
424int real_munmap(void *addr, size_t length)
425{
426 return g_syscall_error(g_munmap_raw(addr, length));
427}
428
429int real_read(int fd, void *buf, size_t count)
430{
431 long ret = g_read_raw(fd, buf, count);
432 return g_syscall_error(ret);
433}
434
435int real_ioctl(int fd, int request, void *argp)
436{
437 long ret = g_ioctl_raw(fd, request, argp);
438 return g_syscall_error(ret);
439}
440
441int real_close(int fd)
442{
443 long ret = g_close_raw(fd);
444 return g_syscall_error(ret);
445}
446
447int real_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
448{
449 return sigaction(signum, act, oldact);
450}
451
452int real_tcgetattr(int fd, struct termios *termios_p)
453{
454 return tcgetattr(fd, termios_p);
455}
456
457int real_tcsetattr(int fd, int optional_actions,
458 const struct termios *termios_p)
459{
460 return tcsetattr(fd, optional_actions, termios_p);
461}
462
463int real_system(const char *command)
464{
465 return system(command);
466}
467
468// real_exec* is missing intentionally - we don't need them
469
470int real_execve(const char *filename, char *const argv[],
471 char *const envp[])
472{
473 long ret = g_execve_raw(filename, argv, envp);
474 return g_syscall_error(ret);
475}
476
477int real_chdir(const char *path)
478{
479 long ret = g_chdir_raw(path);
480 return g_syscall_error(ret);
481}
482
483ssize_t real_readlink(const char *path, char *buf, size_t bufsiz)
484{
485 long ret = g_readlink_raw(path, buf, bufsiz);
486 return g_syscall_error(ret);
487}
488
489void real_sleep(unsigned int seconds)
490{
491 struct timespec ts = { seconds, 0 };
492 g_nanosleep_raw(&ts, NULL);
493}
494
495void real_usleep(unsigned int usec)
496{
497 struct timespec ts = { usec / 1000000, usec % 1000000 };
498 g_nanosleep_raw(&ts, NULL);
499}
500
501void real_exit(int status)
502{
503 g_exit_group_raw(status);
504}
505
506// vim:shiftwidth=2:expandtab