portability.h revision a1a83e671fdd91dcb763651ac86295c217574e6e
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// Work out how to do endianness 130 131#ifndef __APPLE__ 132#include <byteswap.h> 133#include <endian.h> 134 135#if __BYTE_ORDER == __BIG_ENDIAN 136#define IS_BIG_ENDIAN 1 137#else 138#define IS_BIG_ENDIAN 0 139#endif 140 141int clearenv(void); 142#else 143 144#ifdef __BIG_ENDIAN__ 145#define IS_BIG_ENDIAN 1 146#else 147#define IS_BIG_ENDIAN 0 148#endif 149 150#endif 151 152#if IS_BIG_ENDIAN 153#define IS_LITTLE_ENDIAN 0 154#define SWAP_BE16(x) (x) 155#define SWAP_BE32(x) (x) 156#define SWAP_BE64(x) (x) 157#define SWAP_LE16(x) bswap_16(x) 158#define SWAP_LE32(x) bswap_32(x) 159#define SWAP_LE64(x) bswap_64(x) 160#else 161#define IS_LITTLE_ENDIAN 1 162#define SWAP_BE16(x) bswap_16(x) 163#define SWAP_BE32(x) bswap_32(x) 164#define SWAP_BE64(x) bswap_64(x) 165#define SWAP_LE16(x) (x) 166#define SWAP_LE32(x) (x) 167#define SWAP_LE64(x) (x) 168#endif 169 170#if defined(__APPLE__) || defined(__ANDROID__) \ 171 || (defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 10) 172ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 173ssize_t getline(char **lineptr, size_t *n, FILE *stream); 174#endif 175 176// Linux headers not listed by POSIX or LSB 177#include <shadow.h> 178#include <sys/mount.h> 179#include <sys/swap.h> 180 181// Some systems don't define O_NOFOLLOW, and it varies by architecture, so... 182#include <fcntl.h> 183#ifndef O_NOFOLLOW 184#define O_NOFOLLOW 0 185#endif 186 187#ifndef O_CLOEXEC 188#define O_CLOEXEC 02000000 189#endif 190 191#if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \ 192 && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__ 193typedef double FLOAT; 194#else 195typedef float FLOAT; 196#endif 197 198