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#ifndef REG_STARTEND 10#define REG_STARTEND 0 11#endif 12 13#ifdef __APPLE__ 14// macOS 10.13 doesn't have the POSIX 2008 direct access to timespec in 15// struct stat, but we can ask it to give us something equivalent... 16// (This must come before any #include!) 17#define _DARWIN_C_SOURCE 18// ...and then use macros to paper over the difference. 19#define st_atim st_atimespec 20#define st_ctim st_ctimespec 21#define st_mtim st_mtimespec 22#endif 23 24// Test for gcc (using compiler builtin #define) 25 26#ifdef __GNUC__ 27#ifndef __clang__ 28#define QUIET = 0 // shut up false positive "may be used uninitialized" warning 29#else 30#define QUIET 31#endif 32#define printf_format __attribute__((format(printf, 1, 2))) 33#else 34#define printf_format 35#endif 36 37// Always use long file support. 38#define _FILE_OFFSET_BITS 64 39 40// This isn't in the spec, but it's how we determine what libc we're using. 41 42// Types various replacement prototypes need. 43// This also lets us determine what libc we're using. Systems that 44// have <features.h> will transitively include it, and ones that don't -- 45// macOS -- won't break. 46#include <sys/types.h> 47 48// Various constants old build environments might not have even if kernel does 49 50#ifndef AT_FDCWD 51#define AT_FDCWD -100 52#endif 53 54#ifndef AT_SYMLINK_NOFOLLOW 55#define AT_SYMLINK_NOFOLLOW 0x100 56#endif 57 58#ifndef AT_REMOVEDIR 59#define AT_REMOVEDIR 0x200 60#endif 61 62#ifndef RLIMIT_RTTIME 63#define RLIMIT_RTTIME 15 64#endif 65 66// Introduced in Linux 3.1 67#ifndef SEEK_DATA 68#define SEEK_DATA 3 69#endif 70#ifndef SEEK_HOLE 71#define SEEK_HOLE 4 72#endif 73 74// We don't define GNU_dammit because we're not part of the gnu project, and 75// don't want to get any FSF on us. Unfortunately glibc (gnu libc) 76// won't give us Linux syscall wrappers without claiming to be part of the 77// gnu project (because Stallman's "GNU owns Linux" revisionist history 78// crusade includes the kernel, even though Linux was inspired by Minix). 79 80// We use most non-posix Linux syscalls directly through the syscall() wrapper, 81// but even many posix-2008 functions aren't provided by glibc unless you 82// claim it's in the name of Gnu. 83 84#if defined(__GLIBC__) 85// "Function prototypes shall be provided." but aren't. 86// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html 87char *crypt(const char *key, const char *salt); 88 89// According to posix, #include header, get a function definition. But glibc... 90// http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcwidth.html 91#include <wchar.h> 92int wcwidth(wchar_t wc); 93 94// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html 95#include <time.h> 96char *strptime(const char *buf, const char *format, struct tm *tm); 97 98// They didn't like posix basename so they defined another function with the 99// same name and if you include libgen.h it #defines basename to something 100// else (where they implemented the real basename), and that define breaks 101// the table entry for the basename command. They didn't make a new function 102// with a different name for their new behavior because gnu. 103// 104// Solution: don't use their broken header, provide an inline to redirect the 105// correct name to the broken name. 106 107char *dirname(char *path); 108char *__xpg_basename(char *path); 109static inline char *basename(char *path) { return __xpg_basename(path); } 110char *strcasestr(const char *haystack, const char *needle); 111#endif // defined(glibc) 112 113#if !defined(__GLIBC__) 114// POSIX basename. 115#include <libgen.h> 116#endif 117 118// Work out how to do endianness 119 120#ifdef __APPLE__ 121 122#include <libkern/OSByteOrder.h> 123 124#ifdef __BIG_ENDIAN__ 125#define IS_BIG_ENDIAN 1 126#else 127#define IS_BIG_ENDIAN 0 128#endif 129 130#define bswap_16(x) OSSwapInt16(x) 131#define bswap_32(x) OSSwapInt32(x) 132#define bswap_64(x) OSSwapInt64(x) 133 134#elif defined(__FreeBSD__) 135 136#include <sys/endian.h> 137 138#if _BYTE_ORDER == _BIG_ENDIAN 139#define IS_BIG_ENDIAN 1 140#else 141#define IS_BIG_ENDIAN 0 142#endif 143 144#else 145 146#include <byteswap.h> 147#include <endian.h> 148 149#if __BYTE_ORDER == __BIG_ENDIAN 150#define IS_BIG_ENDIAN 1 151#else 152#define IS_BIG_ENDIAN 0 153#endif 154 155#endif 156 157#if IS_BIG_ENDIAN 158#define IS_LITTLE_ENDIAN 0 159#define SWAP_BE16(x) (x) 160#define SWAP_BE32(x) (x) 161#define SWAP_BE64(x) (x) 162#define SWAP_LE16(x) bswap_16(x) 163#define SWAP_LE32(x) bswap_32(x) 164#define SWAP_LE64(x) bswap_64(x) 165#else 166#define IS_LITTLE_ENDIAN 1 167#define SWAP_BE16(x) bswap_16(x) 168#define SWAP_BE32(x) bswap_32(x) 169#define SWAP_BE64(x) bswap_64(x) 170#define SWAP_LE16(x) (x) 171#define SWAP_LE32(x) (x) 172#define SWAP_LE64(x) (x) 173#endif 174 175// Linux headers not listed by POSIX or LSB 176#include <sys/mount.h> 177#ifdef __linux__ 178#include <sys/statfs.h> 179#include <sys/swap.h> 180#include <sys/sysinfo.h> 181#endif 182 183#ifdef __APPLE__ 184#include <util.h> 185#elif !defined(__FreeBSD__) 186#include <pty.h> 187#else 188#include <termios.h> 189#ifndef IUTF8 190#define IUTF8 0 191#endif 192#endif 193 194#if defined(__APPLE__) || defined(__linux__) 195// Linux and macOS has both have getxattr and friends in <sys/xattr.h>, but 196// they aren't compatible. 197#include <sys/xattr.h> 198ssize_t xattr_get(const char *, const char *, void *, size_t); 199ssize_t xattr_lget(const char *, const char *, void *, size_t); 200ssize_t xattr_fget(int fd, const char *, void *, size_t); 201ssize_t xattr_list(const char *, char *, size_t); 202ssize_t xattr_llist(const char *, char *, size_t); 203ssize_t xattr_flist(int, char *, size_t); 204ssize_t xattr_set(const char*, const char*, const void*, size_t, int); 205ssize_t xattr_lset(const char*, const char*, const void*, size_t, int); 206ssize_t xattr_fset(int, const char*, const void*, size_t, int); 207#endif 208 209// macOS doesn't have mknodat, but we can fake it. 210#ifdef __APPLE__ 211int mknodat(int, const char*, mode_t, dev_t); 212#endif 213 214// Android is missing some headers and functions 215// "generated/config.h" is included first 216#if CFG_TOYBOX_SHADOW 217#include <shadow.h> 218#endif 219#if CFG_TOYBOX_UTMPX 220#include <utmpx.h> 221#else 222struct utmpx {int ut_type;}; 223#define USER_PROCESS 0 224static inline struct utmpx *getutxent(void) {return 0;} 225static inline void setutxent(void) {;} 226static inline void endutxent(void) {;} 227#endif 228 229// Some systems don't define O_NOFOLLOW, and it varies by architecture, so... 230#include <fcntl.h> 231#ifndef O_NOFOLLOW 232#define O_NOFOLLOW 0 233#endif 234#ifndef O_NOATIME 235#define O_NOATIME 01000000 236#endif 237#ifndef O_CLOEXEC 238#define O_CLOEXEC 02000000 239#endif 240#ifndef O_PATH 241#define O_PATH 010000000 242#endif 243#ifndef SCHED_RESET_ON_FORK 244#define SCHED_RESET_ON_FORK (1<<30) 245#endif 246 247// Glibc won't give you linux-kernel constants unless you say "no, a BUD lite" 248// even though linux has nothing to do with the FSF and never has. 249#ifndef F_SETPIPE_SZ 250#define F_SETPIPE_SZ 1031 251#endif 252 253#ifndef F_GETPIPE_SZ 254#define F_GETPIPE_SZ 1032 255#endif 256 257#if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \ 258 && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__ 259typedef double FLOAT; 260#else 261typedef float FLOAT; 262#endif 263 264#ifndef __uClinux__ 265pid_t xfork(void); 266#endif 267 268//#define strncpy(...) @@strncpyisbadmmkay@@ 269//#define strncat(...) @@strncatisbadmmkay@@ 270 271// Support building the Android tools on glibc, so hermetic AOSP builds can 272// use toybox before they're ready to switch to host bionic. 273#ifdef __BIONIC__ 274#include <android/log.h> 275#else 276typedef enum android_LogPriority { 277 ANDROID_LOG_UNKNOWN = 0, 278 ANDROID_LOG_DEFAULT, 279 ANDROID_LOG_VERBOSE, 280 ANDROID_LOG_DEBUG, 281 ANDROID_LOG_INFO, 282 ANDROID_LOG_WARN, 283 ANDROID_LOG_ERROR, 284 ANDROID_LOG_FATAL, 285 ANDROID_LOG_SILENT, 286} android_LogPriority; 287static inline int __android_log_write(int pri, const char *tag, const char *msg) 288{ 289 return -1; 290} 291#endif 292 293// libprocessgroup is an Android platform library not included in the NDK. 294#if defined(__BIONIC__) && __has_include(<processgroup/sched_policy.h>) 295#include <processgroup/sched_policy.h> 296#else 297static inline int get_sched_policy(int tid, void *policy) {return 0;} 298static inline char *get_sched_policy_name(int policy) {return "unknown";} 299#endif 300 301// Android NDKv18 has liblog.so but not liblog.c for static builds, 302// stub it out for now. 303#ifdef __ANDROID_NDK__ 304#define __android_log_write(a, b, c) (0) 305#define adjtime(x, y) (0) 306#endif 307 308#ifndef SYSLOG_NAMES 309typedef struct {char *c_name; int c_val;} CODE; 310extern CODE prioritynames[], facilitynames[]; 311#endif 312 313#if CFG_TOYBOX_GETRANDOM 314#include <sys/random.h> 315#endif 316int xgetrandom(void *buf, unsigned len, unsigned flags); 317 318// Android's bionic libc doesn't have confstr. 319#ifdef __BIONIC__ 320#define _CS_PATH 0 321#define _CS_V7_ENV 1 322#include <string.h> 323static inline void confstr(int a, char *b, int c) {strcpy(b, a ? "POSIXLY_CORRECT=1" : "/bin:/usr/bin");} 324#endif 325 326// Paper over the differences between BSD kqueue and Linux inotify for tail. 327 328struct xnotify { 329 char **paths; 330 int max, *fds, count, kq; 331}; 332 333struct xnotify *xnotify_init(int max); 334int xnotify_add(struct xnotify *not, int fd, char *path); 335int xnotify_wait(struct xnotify *not, char **path); 336 337#ifdef __APPLE__ 338#define f_frsize f_iosize 339#endif 340 341int sig_to_num(char *s); 342char *num_to_sig(int sig); 343 344struct signame { 345 int num; 346 char *name; 347}; 348void xsignal_all_killers(void *handler); 349