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// For musl
   8#define _ALL_SOURCE
   9
  10// Test for gcc (using compiler builtin #define)
  11
  12#ifdef __GNUC__
  13#define noreturn        __attribute__((noreturn))
  14#define printf_format   __attribute__((format(printf, 1, 2)))
  15#else
  16#define noreturn
  17#define printf_format
  18#endif
  19
  20// Always use long file support.
  21#define _FILE_OFFSET_BITS 64
  22
  23// This isn't in the spec, but it's how we determine what libc we're using.
  24
  25#include <features.h>
  26
  27// Types various replacement prototypes need
  28#include <sys/types.h>
  29
  30// Various constants old build environments might not have even if kernel does
  31
  32#ifndef AT_FDCWD
  33#define AT_FDCWD -100
  34#endif
  35
  36#ifndef AT_SYMLINK_NOFOLLOW
  37#define AT_SYMLINK_NOFOLLOW 0x100
  38#endif
  39
  40#ifndef AT_REMOVEDIR
  41#define AT_REMOVEDIR 0x200
  42#endif
  43
  44#ifndef RLIMIT_RTTIME
  45#define RLIMIT_RTTIME 15
  46#endif
  47
  48// Introduced in Linux 3.1
  49#ifndef SEEK_DATA
  50#define SEEK_DATA 3
  51#endif
  52#ifndef SEEK_HOLE
  53#define SEEK_HOLE 4
  54#endif
  55
  56// We don't define GNU_dammit because we're not part of the gnu project, and
  57// don't want to get any FSF on us. Unfortunately glibc (gnu libc)
  58// won't give us Linux syscall wrappers without claiming to be part of the
  59// gnu project (because Stallman's "GNU owns Linux" revisionist history
  60// crusade includes the kernel, even though Linux was inspired by Minix).
  61
  62// We use most non-posix Linux syscalls directly through the syscall() wrapper,
  63// but even many posix-2008 functions aren't provided by glibc unless you
  64// claim it's in the name of Gnu.
  65
  66#if defined(__GLIBC__)
  67// "Function prototypes shall be provided." but aren't.
  68// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html
  69char *crypt(const char *key, const char *salt);
  70
  71// According to posix, #include header, get a function definition. But glibc...
  72// http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcwidth.html
  73#include <wchar.h>
  74int wcwidth(wchar_t wc);
  75
  76// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html
  77#include <time.h>
  78char *strptime(const char *buf, const char *format, struct tm *tm);
  79
  80// They didn't like posix basename so they defined another function with the
  81// same name and if you include libgen.h it #defines basename to something
  82// else (where they implemented the real basename), and that define breaks
  83// the table entry for the basename command. They didn't make a new function
  84// with a different name for their new behavior because gnu.
  85//
  86// Solution: don't use their broken header, provide an inline to redirect the
  87// correct name to the broken name.
  88
  89char *dirname(char *path);
  90char *__xpg_basename(char *path);
  91static inline char *basename(char *path) { return __xpg_basename(path); }
  92
  93// When building under obsolete glibc (Ubuntu 8.04-ish), hold its hand a bit.
  94#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 10
  95#define fstatat fstatat64
  96int fstatat64(int dirfd, const char *pathname, void *buf, int flags);
  97int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
  98char *stpcpy(char *dest, const char *src);
  99#include <sys/stat.h>
 100int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
 101int openat(int dirfd, const char *pathname, int flags, ...);
 102#include <dirent.h>
 103DIR *fdopendir(int fd);
 104#include <unistd.h>
 105int fchownat(int dirfd, const char *pathname,
 106                    uid_t owner, gid_t group, int flags);
 107int isblank(int c);
 108int unlinkat(int dirfd, const char *pathname, int flags);
 109#include <stdio.h>
 110ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
 111
 112// Straight from posix-2008, things old glibc had but didn't prototype
 113
 114int faccessat(int fd, const char *path, int amode, int flag);
 115int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag);
 116int mkdirat(int fd, const char *path, mode_t mode);
 117int symlinkat(const char *path1, int fd, const char *path2);
 118int mknodat(int fd, const char *path, mode_t mode, dev_t dev);
 119#include <sys/time.h>
 120int futimens(int fd, const struct timespec times[2]);
 121int utimensat(int fd, const char *path, const struct timespec times[2], int flag);
 122
 123#ifndef MNT_DETACH
 124#define MNT_DETACH 2
 125#endif
 126#endif // Old glibc
 127
 128#endif // glibc in general
 129
 130#if !defined(__GLIBC__)
 131// POSIX basename.
 132#include <libgen.h>
 133#endif
 134
 135// Work out how to do endianness
 136
 137#ifndef __APPLE__
 138#include <byteswap.h>
 139#include <endian.h>
 140
 141#if __BYTE_ORDER == __BIG_ENDIAN
 142#define IS_BIG_ENDIAN 1
 143#else
 144#define IS_BIG_ENDIAN 0
 145#endif
 146
 147int clearenv(void);
 148#else
 149
 150#ifdef __BIG_ENDIAN__
 151#define IS_BIG_ENDIAN 1
 152#else
 153#define IS_BIG_ENDIAN 0
 154#endif
 155
 156#endif
 157
 158#if IS_BIG_ENDIAN
 159#define IS_LITTLE_ENDIAN 0
 160#define SWAP_BE16(x) (x)
 161#define SWAP_BE32(x) (x)
 162#define SWAP_BE64(x) (x)
 163#define SWAP_LE16(x) bswap_16(x)
 164#define SWAP_LE32(x) bswap_32(x)
 165#define SWAP_LE64(x) bswap_64(x)
 166#else
 167#define IS_LITTLE_ENDIAN 1
 168#define SWAP_BE16(x) bswap_16(x)
 169#define SWAP_BE32(x) bswap_32(x)
 170#define SWAP_BE64(x) bswap_64(x)
 171#define SWAP_LE16(x) (x)
 172#define SWAP_LE32(x) (x)
 173#define SWAP_LE64(x) (x)
 174#endif
 175
 176#if defined(__APPLE__) \
 177    || (defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 10)
 178ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
 179ssize_t getline(char **lineptr, size_t *n, FILE *stream);
 180#endif
 181
 182// Linux headers not listed by POSIX or LSB
 183#include <sys/mount.h>
 184#include <sys/swap.h>
 185
 186// Android is missing some headers and functions
 187// "generated/config.h" is included first
 188#if CFG_TOYBOX_SHADOW
 189#include <shadow.h>
 190#endif
 191#if CFG_TOYBOX_UTMPX
 192#include <utmpx.h>
 193#else
 194struct utmpx {int ut_type;};
 195#define USER_PROCESS 0
 196static inline struct utmpx *getutxent(void) {return 0;}
 197static inline void setutxent(void) {;}
 198static inline void endutxent(void) {;}
 199#endif
 200
 201// Some systems don't define O_NOFOLLOW, and it varies by architecture, so...
 202#include <fcntl.h>
 203#ifndef O_NOFOLLOW
 204#define O_NOFOLLOW 0
 205#endif
 206#ifndef O_NOATIME
 207#define O_NOATIME 01000000
 208#endif
 209#ifndef O_CLOEXEC
 210#define O_CLOEXEC 02000000
 211#endif
 212#ifndef O_PATH
 213#define O_PATH   010000000
 214#endif
 215#ifndef SCHED_RESET_ON_FORK
 216#define SCHED_RESET_ON_FORK (1<<30)
 217#endif
 218
 219// Glibc won't give you linux-kernel constants unless you say "no, a BUD lite"
 220// even though linux has nothing to do with the FSF and never has.
 221#ifndef F_SETPIPE_SZ
 222#define F_SETPIPE_SZ 1031
 223#endif
 224
 225#ifndef F_GETPIPE_SZ
 226#define F_GETPIPE_SZ 1032
 227#endif
 228
 229#if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \
 230    && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__
 231typedef double FLOAT;
 232#else
 233typedef float FLOAT;
 234#endif
 235
 236#ifndef __uClinux__
 237pid_t xfork(void);
 238#endif
 239
 240//#define strncpy(...) @@strncpyisbadmmkay@@
 241//#define strncat(...) @@strncatisbadmmkay@@
 242
 243// Support building the Android tools on glibc, so hermetic AOSP builds can
 244// use toybox before they're ready to switch to host bionic.
 245#ifdef __BIONIC__
 246#include <android/log.h>
 247#include <sys/system_properties.h>
 248#else
 249typedef enum android_LogPriority {
 250  ANDROID_LOG_UNKNOWN = 0,
 251  ANDROID_LOG_DEFAULT,
 252  ANDROID_LOG_VERBOSE,
 253  ANDROID_LOG_DEBUG,
 254  ANDROID_LOG_INFO,
 255  ANDROID_LOG_WARN,
 256  ANDROID_LOG_ERROR,
 257  ANDROID_LOG_FATAL,
 258  ANDROID_LOG_SILENT,
 259} android_LogPriority;
 260static inline int __android_log_write(int pri, const char *tag, const char *msg)
 261{
 262  return -1;
 263}
 264#define PROP_VALUE_MAX 92
 265static inline int __system_property_set(const char *key, const char *value)
 266{
 267  return -1;
 268}
 269#endif
 270
 271// libcutils is in AOSP but not Android NDK r18
 272#if defined(__BIONIC__) && !defined(__ANDROID_NDK__)
 273#include <cutils/sched_policy.h>
 274#else
 275static inline int get_sched_policy(int tid, void *policy) {return 0;}
 276static inline char *get_sched_policy_name(int policy) {return "unknown";}
 277#endif
 278
 279// Android NDKv18 has liblog.so but not liblog.c for static builds,
 280// stub it out for now.
 281#ifdef __ANDROID_NDK__
 282#define __android_log_write(a, b, c) (0)
 283#endif
 284
 285#ifndef SYSLOG_NAMES
 286typedef struct {char *c_name; int c_val;} CODE;
 287extern CODE prioritynames[], facilitynames[];
 288#endif
 289
 290#if CFG_TOYBOX_GETRANDOM
 291#include <sys/random.h>
 292#endif
 293void xgetrandom(void *buf, unsigned len, unsigned flags);
 294
 295// Android's bionic libc doesn't have confstr.
 296#ifdef __BIONIC__
 297#define _CS_PATH        0
 298#define _CS_V7_ENV      1
 299#include <string.h>
 300static inline void confstr(int a, char *b, int c) {strcpy(b, a ? "POSIXLY_CORRECT=1" : "/bin:/usr/bin");}
 301#endif
 302