portability.h revision de699accf6804e8b1d8042b46c85500ee8c672c6
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#else 15#define noreturn 16#endif 17 18// Always use long file support. 19#define _FILE_OFFSET_BITS 64 20 21// This isn't in the spec, but it's how we determine what libc we're using. 22 23#include <features.h> 24 25// Various constants old build environments might not have even if kernel does 26 27#ifndef AT_FDCWD 28#define AT_FDCWD -100 29#endif 30 31#ifndef AT_SYMLINK_NOFOLLOW 32#define AT_SYMLINK_NOFOLLOW 0x100 33#endif 34 35#ifndef AT_REMOVEDIR 36#define AT_REMOVEDIR 0x200 37#endif 38 39// We don't define GNU_dammit because we're not part of the gnu project, and 40// don't want to get any FSF on us. Unfortunately glibc (gnu libc) 41// won't give us Linux syscall wrappers without claiming to be part of the 42// gnu project (because Stallman's "GNU owns Linux" revisionist history 43// crusade includes the kernel, even though Linux was inspired by Minix). 44 45// We use most non-posix Linux syscalls directly through the syscall() wrapper, 46// but even many posix-2008 functions aren't provided by glibc unless you 47// claim it's in the name of Gnu. 48 49#if defined(__GLIBC__) 50// "Function prototypes shall be provided." but aren't. 51// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html 52char *crypt(const char *key, const char *salt); 53 54// According to posix, #include header, get a function definition. But glibc... 55// http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcwidth.html 56#include <wchar.h> 57int wcwidth(wchar_t wc); 58 59// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html 60#include <time.h> 61char *strptime(const char *buf, const char *format, struct tm *tm); 62 63// They didn't like posix basename so they defined another function with the 64// same name and if you include libgen.h it #defines basename to something 65// else (where they implemented the real basename), and that define breaks 66// the table entry for the basename command. They didn't make a new function 67// with a different name for their new behavior because gnu. 68// 69// Implement our own in portability.c and don't use their broken header. 70char *basename(char *path); 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#include <sys/mount.h> 85#ifndef MS_MOVE 86#define MS_MOVE (1<<13) 87#endif 88#ifndef MS_REC 89#define MS_REC (1<<14) 90#endif 91#ifndef MS_SILENT 92#define MS_SILENT (1<<15) 93#endif 94#ifndef MS_UNBINDABLE 95#define MS_UNBINDABLE (1<<17) 96#endif 97#ifndef MS_PRIVATE 98#define MS_PRIVATE (1<<18) 99#endif 100#ifndef MS_SLAVE 101#define MS_SLAVE (1<<19) 102#endif 103#ifndef MS_SHARED 104#define MS_SHARED (1<<20) 105#endif 106 107// When building under obsolete glibc (Ubuntu 8.04-ish), hold its hand a bit. 108#elif __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 109#define fstatat fstatat64 110int fstatat64(int dirfd, const char *pathname, void *buf, int flags); 111int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); 112char *stpcpy(char *dest, const char *src); 113#include <sys/stat.h> 114int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); 115int openat(int dirfd, const char *pathname, int flags, ...); 116#include <dirent.h> 117DIR *fdopendir(int fd); 118#include <unistd.h> 119int fchownat(int dirfd, const char *pathname, 120 uid_t owner, gid_t group, int flags); 121int isblank(int c); 122int unlinkat(int dirfd, const char *pathname, int flags); 123#include <stdio.h> 124ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 125 126// Straight from posix-2008, things old glibc had but didn't prototype 127 128int faccessat(int fd, const char *path, int amode, int flag); 129int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); 130int mkdirat(int fd, const char *path, mode_t mode); 131int symlinkat(const char *path1, int fd, const char *path2); 132int mknodat(int fd, const char *path, mode_t mode, dev_t dev); 133#include <sys/time.h> 134int futimens(int fd, const struct timespec times[2]); 135int utimensat(int fd, const char *path, const struct timespec times[2], int flag); 136 137#ifndef MNT_DETACH 138#define MNT_DETACH 2 139#endif 140#endif 141 142#endif 143 144#ifdef __MUSL__ 145#include <unistd.h> 146// Without this "rm -r dir" fails with "is directory". 147#define faccessat(A, B, C, D) faccessat(A, B, C, 0) 148#endif 149 150// Work out how to do endianness 151 152#ifndef __APPLE__ 153#include <byteswap.h> 154#include <endian.h> 155 156#if __BYTE_ORDER == __BIG_ENDIAN 157#define IS_BIG_ENDIAN 1 158#else 159#define IS_BIG_ENDIAN 0 160#endif 161 162int clearenv(void); 163#else 164 165#ifdef __BIG_ENDIAN__ 166#define IS_BIG_ENDIAN 1 167#else 168#define IS_BIG_ENDIAN 0 169#endif 170 171#endif 172 173#if IS_BIG_ENDIAN 174#define IS_LITTLE_ENDIAN 0 175#define SWAP_BE16(x) (x) 176#define SWAP_BE32(x) (x) 177#define SWAP_BE64(x) (x) 178#define SWAP_LE16(x) bswap_16(x) 179#define SWAP_LE32(x) bswap_32(x) 180#define SWAP_LE64(x) bswap_64(x) 181#else 182#define IS_LITTLE_ENDIAN 1 183#define SWAP_BE16(x) bswap_16(x) 184#define SWAP_BE32(x) bswap_32(x) 185#define SWAP_BE64(x) bswap_64(x) 186#define SWAP_LE16(x) (x) 187#define SWAP_LE32(x) (x) 188#define SWAP_LE64(x) (x) 189#endif 190 191#if defined(__APPLE__) \ 192 || (defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 10) 193ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 194ssize_t getline(char **lineptr, size_t *n, FILE *stream); 195#endif 196 197// Linux headers not listed by POSIX or LSB 198#include <sys/mount.h> 199#include <sys/swap.h> 200 201// Android is missing some headers and functions 202// "generated/config.h" is included first 203#if CFG_TOYBOX_SHADOW 204#include <shadow.h> 205#endif 206#if CFG_TOYBOX_UTMPX 207#include <utmpx.h> 208#endif 209#if CFG_TOYBOX_PTY 210#include <pty.h> 211#else 212pid_t forkpty(int *amaster, char *name, void *termp, void *winp); 213#endif 214 215 216// Some systems don't define O_NOFOLLOW, and it varies by architecture, so... 217#include <fcntl.h> 218#ifndef O_NOFOLLOW 219#define O_NOFOLLOW 0 220#endif 221 222#ifndef O_CLOEXEC 223#define O_CLOEXEC 02000000 224#endif 225 226#if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \ 227 && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__ 228typedef double FLOAT; 229#else 230typedef float FLOAT; 231#endif 232 233#ifndef __uClinux__ 234pid_t xfork(void); 235#endif 236 237//#define strncpy(...) @@strncpyisbadmmkay@@ 238//#define strncat(...) @@strcatisbadmmkay@@ 239