1// Workarounds for horrible build environment idiosyncrasies.
2
3// Instead of polluting the code with strange #ifdefs to work around bugs
4// in specific compiler, library, or OS versions, localize all that here
5// and in portability.c
6
7// For musl
8#define _ALL_SOURCE
9
10// Test for gcc (using compiler builtin #define)
11
12#ifdef __GNUC__
13#define noreturn	__attribute__((noreturn))
14#define printf_format	__attribute__((format(printf, 1, 2)))
15#else
16#define noreturn
17#define printf_format
18#endif
19
20// Always use long file support.
21#define _FILE_OFFSET_BITS 64
22
23// This isn't in the spec, but it's how we determine what libc we're using.
24
25#include <features.h>
26
27// Types various replacement prototypes need
28#include <sys/types.h>
29
30// Various constants old build environments might not have even if kernel does
31
32#ifndef AT_FDCWD
33#define AT_FDCWD -100
34#endif
35
36#ifndef AT_SYMLINK_NOFOLLOW
37#define AT_SYMLINK_NOFOLLOW 0x100
38#endif
39
40#ifndef AT_REMOVEDIR
41#define AT_REMOVEDIR 0x200
42#endif
43
44#ifndef RLIMIT_RTTIME
45#define RLIMIT_RTTIME 15
46#endif
47
48#ifndef SEEK_DATA
49#define SEEK_DATA 3
50#endif
51
52// We don't define GNU_dammit because we're not part of the gnu project, and
53// don't want to get any FSF on us. Unfortunately glibc (gnu libc)
54// won't give us Linux syscall wrappers without claiming to be part of the
55// gnu project (because Stallman's "GNU owns Linux" revisionist history
56// crusade includes the kernel, even though Linux was inspired by Minix).
57
58// We use most non-posix Linux syscalls directly through the syscall() wrapper,
59// but even many posix-2008 functions aren't provided by glibc unless you
60// claim it's in the name of Gnu.
61
62#if defined(__GLIBC__)
63// "Function prototypes shall be provided." but aren't.
64// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html
65char *crypt(const char *key, const char *salt);
66
67// According to posix, #include header, get a function definition. But glibc...
68// http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcwidth.html
69#include <wchar.h>
70int wcwidth(wchar_t wc);
71
72// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html
73#include <time.h>
74char *strptime(const char *buf, const char *format, struct tm *tm);
75
76// They didn't like posix basename so they defined another function with the
77// same name and if you include libgen.h it #defines basename to something
78// else (where they implemented the real basename), and that define breaks
79// the table entry for the basename command. They didn't make a new function
80// with a different name for their new behavior because gnu.
81//
82// Solution: don't use their broken header, provide an inline to redirect the
83// correct name to the broken name.
84
85char *dirname(char *path);
86char *__xpg_basename(char *path);
87static inline char *basename(char *path) { return __xpg_basename(path); }
88
89// uClibc pretends to be glibc and copied a lot of its bugs, but has a few more
90#if defined(__UCLIBC__)
91#include <unistd.h>
92#include <stdio.h>
93ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
94char *stpcpy(char *dest, const char *src);
95pid_t getsid(pid_t pid);
96
97// uClibc's last-ever release was in 2012, so of course it doesn't define
98// any flag newer than MS_MOVE, which was added in 2001 (linux 2.5.0.5),
99// eleven years earlier.
100
101#include <sys/mount.h>
102#ifndef MS_MOVE
103#define MS_MOVE       (1<<13)
104#endif
105#ifndef MS_REC
106#define MS_REC        (1<<14)
107#endif
108#ifndef MS_SILENT
109#define MS_SILENT     (1<<15)
110#endif
111#ifndef MS_UNBINDABLE
112#define MS_UNBINDABLE (1<<17)
113#endif
114#ifndef MS_PRIVATE
115#define MS_PRIVATE    (1<<18)
116#endif
117#ifndef MS_SLAVE
118#define MS_SLAVE      (1<<19)
119#endif
120#ifndef MS_SHARED
121#define MS_SHARED     (1<<20)
122#endif
123#ifndef MS_RELATIME
124#define MS_RELATIME (1<<21)
125#endif
126
127// When building under obsolete glibc (Ubuntu 8.04-ish), hold its hand a bit.
128#elif __GLIBC__ == 2 && __GLIBC_MINOR__ < 10
129#define fstatat fstatat64
130int fstatat64(int dirfd, const char *pathname, void *buf, int flags);
131int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
132char *stpcpy(char *dest, const char *src);
133#include <sys/stat.h>
134int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
135int openat(int dirfd, const char *pathname, int flags, ...);
136#include <dirent.h>
137DIR *fdopendir(int fd);
138#include <unistd.h>
139int fchownat(int dirfd, const char *pathname,
140                    uid_t owner, gid_t group, int flags);
141int isblank(int c);
142int unlinkat(int dirfd, const char *pathname, int flags);
143#include <stdio.h>
144ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
145
146// Straight from posix-2008, things old glibc had but didn't prototype
147
148int faccessat(int fd, const char *path, int amode, int flag);
149int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag);
150int mkdirat(int fd, const char *path, mode_t mode);
151int symlinkat(const char *path1, int fd, const char *path2);
152int mknodat(int fd, const char *path, mode_t mode, dev_t dev);
153#include <sys/time.h>
154int futimens(int fd, const struct timespec times[2]);
155int utimensat(int fd, const char *path, const struct timespec times[2], int flag);
156
157#ifndef MNT_DETACH
158#define MNT_DETACH 2
159#endif
160#endif // Old glibc
161
162#endif // glibc in general
163
164#if !defined(__GLIBC__)
165// POSIX basename.
166#include <libgen.h>
167#endif
168
169// Work out how to do endianness
170
171#ifndef __APPLE__
172#include <byteswap.h>
173#include <endian.h>
174
175#if __BYTE_ORDER == __BIG_ENDIAN
176#define IS_BIG_ENDIAN 1
177#else
178#define IS_BIG_ENDIAN 0
179#endif
180
181int clearenv(void);
182#else
183
184#ifdef __BIG_ENDIAN__
185#define IS_BIG_ENDIAN 1
186#else
187#define IS_BIG_ENDIAN 0
188#endif
189
190#endif
191
192#if IS_BIG_ENDIAN
193#define IS_LITTLE_ENDIAN 0
194#define SWAP_BE16(x) (x)
195#define SWAP_BE32(x) (x)
196#define SWAP_BE64(x) (x)
197#define SWAP_LE16(x) bswap_16(x)
198#define SWAP_LE32(x) bswap_32(x)
199#define SWAP_LE64(x) bswap_64(x)
200#else
201#define IS_LITTLE_ENDIAN 1
202#define SWAP_BE16(x) bswap_16(x)
203#define SWAP_BE32(x) bswap_32(x)
204#define SWAP_BE64(x) bswap_64(x)
205#define SWAP_LE16(x) (x)
206#define SWAP_LE32(x) (x)
207#define SWAP_LE64(x) (x)
208#endif
209
210#if defined(__APPLE__) \
211    || (defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 10)
212ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
213ssize_t getline(char **lineptr, size_t *n, FILE *stream);
214#endif
215
216// Linux headers not listed by POSIX or LSB
217#include <sys/mount.h>
218#include <sys/swap.h>
219
220// Android is missing some headers and functions
221// "generated/config.h" is included first
222#if CFG_TOYBOX_SHADOW
223#include <shadow.h>
224#endif
225#if CFG_TOYBOX_UTMPX
226#include <utmpx.h>
227#else
228struct utmpx {int ut_type;};
229#define USER_PROCESS 0
230static inline struct utmpx *getutxent(void) {return 0;}
231static inline void setutxent(void) {;}
232static inline void endutxent(void) {;}
233#endif
234
235// Some systems don't define O_NOFOLLOW, and it varies by architecture, so...
236#include <fcntl.h>
237#ifndef O_NOFOLLOW
238#define O_NOFOLLOW 0
239#endif
240
241#ifndef O_NOATIME
242#define O_NOATIME 01000000
243#endif
244
245#ifndef O_CLOEXEC
246#define O_CLOEXEC 02000000
247#endif
248
249#ifndef O_PATH
250#define O_PATH   010000000
251#endif
252
253// Glibc won't give you linux-kernel constants unless you say "no, a BUD lite"
254// even though linux has nothing to do with the FSF and never has.
255#ifndef F_SETPIPE_SZ
256#define F_SETPIPE_SZ 1031
257#endif
258
259#ifndef F_GETPIPE_SZ
260#define F_GETPIPE_SZ 1032
261#endif
262
263#if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \
264    && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__
265typedef double FLOAT;
266#else
267typedef float FLOAT;
268#endif
269
270#ifndef __uClinux__
271pid_t xfork(void);
272#endif
273
274//#define strncpy(...) @@strncpyisbadmmkay@@
275//#define strncat(...) @@strncatisbadmmkay@@
276
277#ifdef __ANDROID__
278#include <cutils/sched_policy.h>
279#else
280static inline int get_sched_policy(int tid, void *policy) {return 0;}
281static inline char *get_sched_policy_name(int policy) {return "unknown";}
282#endif
283