summaryrefslogtreecommitdiff
path: root/src/libc-stdio.c
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2018-06-02 22:00:18 +0300
committerJari Vetoniemi <mailroxas@gmail.com>2018-06-02 22:03:58 +0300
commit9edd4a9979f520abc6a3f5c0029966b5cc0f280e (patch)
treec94fe900e1e7b3987fe4794163e62a06a18b5af4 /src/libc-stdio.c
parent6e5e3de6214bb792b126d481598e3e9313ea3bbb (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.c42
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);
+}