diff options
author | Jari Vetoniemi <mailroxas@gmail.com> | 2018-06-02 22:00:18 +0300 |
---|---|---|
committer | Jari Vetoniemi <mailroxas@gmail.com> | 2018-06-02 22:03:58 +0300 |
commit | 9edd4a9979f520abc6a3f5c0029966b5cc0f280e (patch) | |
tree | c94fe900e1e7b3987fe4794163e62a06a18b5af4 /src/libc-stdio.c | |
parent | 6e5e3de6214bb792b126d481598e3e9313ea3bbb (diff) |
libc: Wrap low level glibc io calls for stdio
This is much less work and actually works better.
Diffstat (limited to 'src/libc-stdio.c')
-rw-r--r-- | src/libc-stdio.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/libc-stdio.c b/src/libc-stdio.c new file mode 100644 index 0000000..713497b --- /dev/null +++ b/src/libc-stdio.c @@ -0,0 +1,42 @@ +#include <stdio.h> + +struct bionic___sFILE { +#if defined(__LP64__) + char __private[152]; +#else + char __private[84]; +#endif +} __attribute__((aligned(sizeof(void*)))); + +// Bionic standard stream support pre-M Android +// Post-M it's saner and they point to stdin/stdout/stderr symbols instead +const struct bionic___sFILE bionic___sF[3] = { + {{ 's', 't', 'd', 'i', 'n' }}, + {{ 's', 't', 'd', 'o', 'u', 't' }}, + {{ 's', 't', 'd', 'e', 'r', 'r' }} +}; + +static inline FILE* +bionic_file_to_glibc_file(FILE *f) +{ + if (f == (void*)&bionic___sF[0]) + return stdin; + else if (f == (void*)&bionic___sF[1]) + return stdout; + else if (f == (void*)&bionic___sF[2]) + return stderr; + return f; +} + +// Wrapping internal glibc VTABLE functions to handle bionic's pre-M crap +// We define __real_IO_file_xsputn in libc.c so linker will link our library, +// it's not used however for anything. + +extern size_t +__real_IO_file_xsputn(FILE *f, const void *buf, size_t n); + +size_t +__wrap_IO_file_xsputn(FILE *f, const void *buf, size_t n) +{ + return __real_IO_file_xsputn(bionic_file_to_glibc_file(f), buf, n); +} |