portability.h revision 46ddf0e34b03f7711a9c80f7a70dc8cbf732f782
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// The tendency of gcc to produce stupid warnings continues with 8// warn_unused_result, which warns about things like ignoring the return code 9// of nice(2) (which is completely useless since -1 is a legitimate return 10// value on success and even the man page tells you to use errno instead). 11 12// This makes it stop. 13 14#undef _FORTIFY_SOURCE 15 16// For musl 17#define _ALL_SOURCE 18 19// Test for gcc (using compiler builtin #define) 20 21#ifdef __GNUC__ 22#define noreturn __attribute__((noreturn)) 23#else 24#define noreturn 25#endif 26 27// Always use long file support. 28#define _FILE_OFFSET_BITS 64 29 30// This isn't in the spec, but it's how we determine what libc we're using. 31 32#include <features.h> 33 34// Various constants old build environments might not have even if kernel does 35 36#ifndef AT_FDCWD 37#define AT_FDCWD -100 38#endif 39 40#ifndef AT_SYMLINK_NOFOLLOW 41#define AT_SYMLINK_NOFOLLOW 0x100 42#endif 43 44#ifndef AT_REMOVEDIR 45#define AT_REMOVEDIR 0x200 46#endif 47 48// We don't define GNU_dammit because we're not part of the gnu project, and 49// don't want to get any FSF on us. Unfortunately glibc (gnu libc) 50// won't give us Linux syscall wrappers without claiming to be part of the 51// gnu project (because Stallman's "GNU owns Linux" revisionist history 52// crusade includes the kernel, even though Linux was inspired by Minix). 53 54// We use most non-posix Linux syscalls directly through the syscall() wrapper, 55// but even many posix-2008 functions aren't provided by glibc unless you 56// claim it's in the name of Gnu. 57 58#if defined(__GLIBC__) 59// "Function prototypes shall be provided." but aren't. 60// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html 61char *crypt(const char *key, const char *salt); 62 63// According to posix, #include header, get a function definition. But glibc... 64// http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcwidth.html 65#include <wchar.h> 66int wcwidth(wchar_t wc); 67 68// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html 69#include <time.h> 70char *strptime(const char *buf, const char *format, struct tm *tm); 71 72// uClibc pretends to be glibc and copied a lot of its bugs, but has a few more 73#if defined(__UCLIBC__) 74#include <unistd.h> 75#include <stdio.h> 76ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 77char *stpcpy(char *dest, const char *src); 78pid_t getsid(pid_t pid); 79 80// uClibc's last-ever release was in 2012, so of course it doesn't define 81// any flag newer than MS_MOVE, which was added in 2001 (linux 2.5.0.5), 82// eleven years earlier. 83 84#define MS_MOVE (1<<13) 85#define MS_REC (1<<14) 86#define MS_SILENT (1<<15) 87#define MS_UNBINDABLE (1<<17) 88#define MS_PRIVATE (1<<18) 89#define MS_SLAVE (1<<19) 90#define MS_SHARED (1<<20) 91 92// When building under obsolete glibc (Ubuntu 8.04-ish), hold its hand a bit. 93#elif __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 94#define fstatat fstatat64 95int fstatat64(int dirfd, const char *pathname, void *buf, int flags); 96int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); 97char *stpcpy(char *dest, const char *src); 98#include <sys/stat.h> 99int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); 100int openat(int dirfd, const char *pathname, int flags, ...); 101#include <dirent.h> 102DIR *fdopendir(int fd); 103#include <unistd.h> 104int fchownat(int dirfd, const char *pathname, 105 uid_t owner, gid_t group, int flags); 106int isblank(int c); 107int unlinkat(int dirfd, const char *pathname, int flags); 108#include <stdio.h> 109ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 110 111// Straight from posix-2008, things old glibc had but didn't prototype 112 113int faccessat(int fd, const char *path, int amode, int flag); 114int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); 115int mkdirat(int fd, const char *path, mode_t mode); 116int symlinkat(const char *path1, int fd, const char *path2); 117int mknodat(int fd, const char *path, mode_t mode, dev_t dev); 118#include <sys/time.h> 119int futimens(int fd, const struct timespec times[2]); 120int utimensat(int fd, const char *path, const struct timespec times[2], int flag); 121 122#ifndef MNT_DETACH 123#define MNT_DETACH 2 124#endif 125#endif 126 127#endif 128 129#ifdef __MUSL__ 130#include <unistd.h> 131// Without this "rm -r dir" fails with "is directory". 132#define faccessat(A, B, C, D) faccessat(A, B, C, 0) 133#endif 134 135// Work out how to do endianness 136 137#ifndef __APPLE__ 138#include <byteswap.h> 139#include <endian.h> 140 141#if __BYTE_ORDER == __BIG_ENDIAN 142#define IS_BIG_ENDIAN 1 143#else 144#define IS_BIG_ENDIAN 0 145#endif 146 147int clearenv(void); 148#else 149 150#ifdef __BIG_ENDIAN__ 151#define IS_BIG_ENDIAN 1 152#else 153#define IS_BIG_ENDIAN 0 154#endif 155 156#endif 157 158#if IS_BIG_ENDIAN 159#define IS_LITTLE_ENDIAN 0 160#define SWAP_BE16(x) (x) 161#define SWAP_BE32(x) (x) 162#define SWAP_BE64(x) (x) 163#define SWAP_LE16(x) bswap_16(x) 164#define SWAP_LE32(x) bswap_32(x) 165#define SWAP_LE64(x) bswap_64(x) 166#else 167#define IS_LITTLE_ENDIAN 1 168#define SWAP_BE16(x) bswap_16(x) 169#define SWAP_BE32(x) bswap_32(x) 170#define SWAP_BE64(x) bswap_64(x) 171#define SWAP_LE16(x) (x) 172#define SWAP_LE32(x) (x) 173#define SWAP_LE64(x) (x) 174#endif 175 176#if defined(__APPLE__) || defined(__ANDROID__) \ 177 || (defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 10) 178ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 179ssize_t getline(char **lineptr, size_t *n, FILE *stream); 180#endif 181 182// Linux headers not listed by POSIX or LSB 183#include <sys/mount.h> 184#include <sys/swap.h> 185 186// Android is missing some headers and functions 187#if defined(__ANDROID__) 188int sethostname(const char *name, size_t len); 189#endif 190// "generated/config.h" is included first 191#if defined(CFG_TOYBOX_SHADOW) && CFG_TOYBOX_SHADOW 192#include <shadow.h> 193#endif 194#if defined(CFG_TOYBOX_UTMPX) && CFG_TOYBOX_UTMPX 195#include <utmpx.h> 196#endif 197#if defined(CFG_TOYBOX_PTY) && CFG_TOYBOX_PTY 198#include <pty.h> 199#endif 200 201 202// Some systems don't define O_NOFOLLOW, and it varies by architecture, so... 203#include <fcntl.h> 204#ifndef O_NOFOLLOW 205#define O_NOFOLLOW 0 206#endif 207 208#ifndef O_CLOEXEC 209#define O_CLOEXEC 02000000 210#endif 211 212#if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \ 213 && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__ 214typedef double FLOAT; 215#else 216typedef float FLOAT; 217#endif 218 219