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