portability.h revision 10d55b112963406dec3164396b9e8378f6d63961
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// Test for gcc (using compiler builtin #define) 17 18#ifdef __GNUC__ 19#define noreturn __attribute__((noreturn)) 20#else 21#define noreturn 22#endif 23 24// Always use long file support. 25#define _FILE_OFFSET_BITS 64 26 27// This isn't in the spec, but it's how we determine what libc we're using. 28 29#include <features.h> 30 31// Various constants old build environments might not have even if kernel does 32 33#ifndef AT_FDCWD 34#define AT_FDCWD -100 35#endif 36 37#ifndef AT_SYMLINK_NOFOLLOW 38#define AT_SYMLINK_NOFOLLOW 0x100 39#endif 40 41#ifndef AT_REMOVEDIR 42#define AT_REMOVEDIR 0x200 43#endif 44 45// We don't define GNU_dammit because we're not part of the gnu project, and 46// don't want to get any FSF on us. Unfortunately glibc (gnu libc) 47// won't give us Linux syscall wrappers without claiming to be part of the 48// gnu project (because Stallman's "GNU owns Linux" revisionist history 49// crusade includes the kernel, even though Linux was inspired by Minix). 50 51// We use most non-posix Linux syscalls directly through the syscall() wrapper, 52// but even many posix-2008 functions aren't provided by glibc unless you 53// claim it's in the name of Gnu. 54 55#if defined(__GLIBC__) 56// "Function prototypes shall be provided." but aren't. 57// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html 58char *crypt(const char *key, const char *salt); 59 60// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html 61#include <time.h> 62char *strptime(const char *buf, const char *format, struct tm *tm); 63 64// uClibc pretends to be glibc and copied a lot of its bugs, but has a few more 65#if defined(__UCLIBC__) 66#include <unistd.h> 67#include <stdio.h> 68ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 69 70// When building under obsolete glibc (Ubuntu 8.04-ish), hold its hand a bit. 71#elif __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 72#define fstatat fstatat64 73int fstatat64(int dirfd, const char *pathname, void *buf, int flags); 74int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); 75char *stpcpy(char *dest, const char *src); 76#include <sys/stat.h> 77int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); 78int openat(int dirfd, const char *pathname, int flags, ...); 79#include <dirent.h> 80DIR *fdopendir(int fd); 81#include <unistd.h> 82int fchownat(int dirfd, const char *pathname, 83 uid_t owner, gid_t group, int flags); 84int isblank(int c); 85int unlinkat(int dirfd, const char *pathname, int flags); 86#include <stdio.h> 87ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 88 89// Straight from posix-2008, things old glibc had but didn't prototype 90 91int faccessat(int fd, const char *path, int amode, int flag); 92int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); 93int mkdirat(int fd, const char *path, mode_t mode); 94int symlinkat(const char *path1, int fd, const char *path2); 95int mknodat(int fd, const char *path, mode_t mode, dev_t dev); 96#include <sys/time.h> 97int futimens(int fd, const struct timespec times[2]); 98int utimensat(int fd, const char *path, const struct timespec times[2], int flag); 99 100#ifndef MNT_DETACH 101#define MNT_DETACH 2 102#endif 103#endif 104 105#endif 106 107// Work out how to do endianness 108 109#ifndef __APPLE__ 110#include <byteswap.h> 111#include <endian.h> 112 113#if __BYTE_ORDER == __BIG_ENDIAN 114#define IS_BIG_ENDIAN 1 115#else 116#define IS_BIG_ENDIAN 0 117#endif 118 119int clearenv(void); 120#else 121 122#ifdef __BIG_ENDIAN__ 123#define IS_BIG_ENDIAN 1 124#else 125#define IS_BIG_ENDIAN 0 126#endif 127 128#endif 129 130#if IS_BIG_ENDIAN 131#define IS_LITTLE_ENDIAN 0 132#define SWAP_BE16(x) (x) 133#define SWAP_BE32(x) (x) 134#define SWAP_BE64(x) (x) 135#define SWAP_LE16(x) bswap_16(x) 136#define SWAP_LE32(x) bswap_32(x) 137#define SWAP_LE64(x) bswap_64(x) 138#else 139#define IS_LITTLE_ENDIAN 1 140#define SWAP_BE16(x) bswap_16(x) 141#define SWAP_BE32(x) bswap_32(x) 142#define SWAP_BE64(x) bswap_64(x) 143#define SWAP_LE16(x) (x) 144#define SWAP_LE32(x) (x) 145#define SWAP_LE64(x) (x) 146#endif 147 148#if defined(__APPLE__) || defined(__ANDROID__) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 10) 149ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); 150ssize_t getline(char **lineptr, size_t *n, FILE *stream); 151#endif 152 153// compile time probes for stuff libc didn't provide 154#include "generated/portability.h" 155