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