X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=lib%2Fportability.h;h=ff22fa590b70ca2d0ee6574f7b5e551024bd4bf7;hb=c067539d3093d7d946116c1c9a590a2909d23107;hp=34f7994fbdd9bf17fd86a1443959c3e801d71321;hpb=efa93b987a355385d0b1a1ac4e3a0e25db63b494;p=android-x86%2Fexternal-toybox.git diff --git a/lib/portability.h b/lib/portability.h index 34f7994f..ff22fa59 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -1,13 +1,173 @@ -// Humor glibc to get dprintf, then #define it to something more portable. -#define _GNU_SOURCE -#include -#define fdprintf(...) dprintf(__VA_ARGS__) +// Workarounds for horrible build environment idiosyncrasies. + +// Instead of polluting the code with strange #ifdefs to work around bugs +// in specific compiler, library, or OS versions, localize all that here +// and in portability.c + +// For musl +#define _ALL_SOURCE + +// Test for gcc (using compiler builtin #define) #ifdef __GNUC__ #define noreturn __attribute__((noreturn)) +#if CFG_TOYBOX_DEBUG +#define printf_format __attribute__((format(printf, 1, 2))) +#else +#define printf_format +#endif #else #define noreturn +#define printf_format +#endif + +// Always use long file support. +#define _FILE_OFFSET_BITS 64 + +// This isn't in the spec, but it's how we determine what libc we're using. + +#include + +// Types various replacement prototypes need +#include + +// Various constants old build environments might not have even if kernel does + +#ifndef AT_FDCWD +#define AT_FDCWD -100 +#endif + +#ifndef AT_SYMLINK_NOFOLLOW +#define AT_SYMLINK_NOFOLLOW 0x100 +#endif + +#ifndef AT_REMOVEDIR +#define AT_REMOVEDIR 0x200 +#endif + +// We don't define GNU_dammit because we're not part of the gnu project, and +// don't want to get any FSF on us. Unfortunately glibc (gnu libc) +// won't give us Linux syscall wrappers without claiming to be part of the +// gnu project (because Stallman's "GNU owns Linux" revisionist history +// crusade includes the kernel, even though Linux was inspired by Minix). + +// We use most non-posix Linux syscalls directly through the syscall() wrapper, +// but even many posix-2008 functions aren't provided by glibc unless you +// claim it's in the name of Gnu. + +#if defined(__GLIBC__) +// "Function prototypes shall be provided." but aren't. +// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html +char *crypt(const char *key, const char *salt); + +// According to posix, #include header, get a function definition. But glibc... +// http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcwidth.html +#include +int wcwidth(wchar_t wc); + +// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html +#include +char *strptime(const char *buf, const char *format, struct tm *tm); + +// They didn't like posix basename so they defined another function with the +// same name and if you include libgen.h it #defines basename to something +// else (where they implemented the real basename), and that define breaks +// the table entry for the basename command. They didn't make a new function +// with a different name for their new behavior because gnu. +// +// Solution: don't use their broken header, provide an inline to redirect the +// correct name to the broken name. + +char *dirname(char *path); +char *__xpg_basename(char *path); +static inline char *basename(char *path) { return __xpg_basename(path); } + +// uClibc pretends to be glibc and copied a lot of its bugs, but has a few more +#if defined(__UCLIBC__) +#include +#include +ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); +char *stpcpy(char *dest, const char *src); +pid_t getsid(pid_t pid); + +// uClibc's last-ever release was in 2012, so of course it doesn't define +// any flag newer than MS_MOVE, which was added in 2001 (linux 2.5.0.5), +// eleven years earlier. + +#include +#ifndef MS_MOVE +#define MS_MOVE (1<<13) +#endif +#ifndef MS_REC +#define MS_REC (1<<14) +#endif +#ifndef MS_SILENT +#define MS_SILENT (1<<15) +#endif +#ifndef MS_UNBINDABLE +#define MS_UNBINDABLE (1<<17) #endif +#ifndef MS_PRIVATE +#define MS_PRIVATE (1<<18) +#endif +#ifndef MS_SLAVE +#define MS_SLAVE (1<<19) +#endif +#ifndef MS_SHARED +#define MS_SHARED (1<<20) +#endif + +// When building under obsolete glibc (Ubuntu 8.04-ish), hold its hand a bit. +#elif __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 +#define fstatat fstatat64 +int fstatat64(int dirfd, const char *pathname, void *buf, int flags); +int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); +char *stpcpy(char *dest, const char *src); +#include +int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); +int openat(int dirfd, const char *pathname, int flags, ...); +#include +DIR *fdopendir(int fd); +#include +int fchownat(int dirfd, const char *pathname, + uid_t owner, gid_t group, int flags); +int isblank(int c); +int unlinkat(int dirfd, const char *pathname, int flags); +#include +ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); + +// Straight from posix-2008, things old glibc had but didn't prototype + +int faccessat(int fd, const char *path, int amode, int flag); +int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); +int mkdirat(int fd, const char *path, mode_t mode); +int symlinkat(const char *path1, int fd, const char *path2); +int mknodat(int fd, const char *path, mode_t mode, dev_t dev); +#include +int futimens(int fd, const struct timespec times[2]); +int utimensat(int fd, const char *path, const struct timespec times[2], int flag); + +#ifndef MNT_DETACH +#define MNT_DETACH 2 +#endif +#endif // Old glibc + +#endif // glibc in general + +#if !defined(__GLIBC__) && !defined(__BIONIC__) +// POSIX basename. +#include +#endif + +// glibc was handled above; for 32-bit bionic we need to avoid a collision +// with toybox's basename_r so we can't include even though that +// would give us a POSIX basename(3). +#if defined(__BIONIC__) +char *basename(char *path); +char *dirname(char *path); +#endif + +// Work out how to do endianness #ifndef __APPLE__ #include @@ -19,6 +179,7 @@ #define IS_BIG_ENDIAN 0 #endif +int clearenv(void); #else #ifdef __BIG_ENDIAN__ @@ -47,14 +208,54 @@ #define SWAP_LE64(x) (x) #endif -// Some versions of gcc produce spurious "may be uninitialized" warnings in -// cases where it provably can't happen. Unfortunately, although this warning -// is calculated and produced separately from the "is definitely used -// uninitialized" warnings, there's no way to turn off the broken spurious "may -// be" warnings without also turning off the non-broken "is" warnings. +#if defined(__APPLE__) \ + || (defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 10) +ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); +ssize_t getline(char **lineptr, size_t *n, FILE *stream); +#endif -#if CFG_TOYBOX_DEBUG -#define GCC_BUG =0 +// Linux headers not listed by POSIX or LSB +#include +#include + +// Android is missing some headers and functions +// "generated/config.h" is included first +#if CFG_TOYBOX_SHADOW +#include +#endif +#if CFG_TOYBOX_UTMPX +#include +#endif + +// Some systems don't define O_NOFOLLOW, and it varies by architecture, so... +#include +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +#ifndef O_NOATIME +#define O_NOATIME 01000000 +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 02000000 +#endif + +#ifndef O_PATH +#define O_PATH 010000000 +#endif + +#if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_LONG__) \ + && __SIZEOF_DOUBLE__ <= __SIZEOF_LONG__ +typedef double FLOAT; #else -#define GCC_BUG +typedef float FLOAT; #endif + +#ifndef __uClinux__ +pid_t xfork(void); +#endif + +//#define strncpy(...) @@strncpyisbadmmkay@@ +//#define strncat(...) @@strncatisbadmmkay@@ +