summaryrefslogtreecommitdiff
path: root/src/libc-stdio.c
blob: 34fe40d5d6055b0d37cd799444182420cb9929a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#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;
}

int
bionic_fflush(FILE *f)
{
   return fflush(bionic_file_to_glibc_file(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);
}