#ifndef SYSTEM_H #define SYSTEM_H #define _GNU_SOURCE #include /* freebsd */ #include #include /* linux */ #include #include #define STAT_BLOCKSIZE(s) ((s).st_blksize) #define EXIT_TROUBLE 2 #include #define MIN(a, b) ((a) <= (b) ? (a) : (b)) #define MAX(a, b) ((a) >= (b) ? (a) : /**/(b)) /* Return 1 if an array of |n| objects, each of size |s|, cannot exist reliably due to size or |ptrdiff_t| arithmetic overflow. |s| must be positive and N must be nonnegative. This is a macro, not a function, so that it works correctly even when |SIZE_MAX < n|. True if |n * s| would overflow in a |size_t| calculation, or would generate a value larger than |PTRDIFF_MAX|. This expands to a constant expression if |n| and |s| are both constants. By gnulib convention, |SIZE_MAX| represents overflow in size calculations, so the conservative |size_t|-based dividend to use here is |SIZE_MAX - 1|. */ #define xalloc_oversized(n, s) \ ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n)) #include /* Type used for fast comparison of several bytes at a time. This used to be |uintmax_t|, but changing it to |size_t| made plain 'cmp' 90\% faster (|GCC 4.8.1|, |x86|). */ #ifndef word # define word size_t #endif #include /* SA_RESTART */ #include #ifndef SSIZE_MAX # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif /* The signed integer type of a line number. Since files are read into main memory, |ptrdiff_t| should be wide enough. */ typedef ptrdiff_t lin; #define LIN_MAX PTRDIFF_MAX /* The signed integer type for printing line numbers, and its printf length modifier. This is not simply |ptrdiff_t|, to cater to older and/or nonstandard C libraries where |"l"| works but |"ll"| and |"t"| do not, or where |long| is too narrow and |"ll"| works but |"t"| does not. */ #if LIN_MAX <= LONG_MAX typedef long int printint; # define pI "l" #elif LIN_MAX <= LLONG_MAX typedef long long int printint; # define pI "ll" #else typedef ptrdiff_t printint; # define pI "t" #endif /* Limit so that |2 * context + 1| does not overflow. */ #define CONTEXT_MAX ((LIN_MAX - 1) / 2) #define file_name_cmp strcmp /* Do struct stat |*s|, |*t| describe the same special file? */ #ifndef same_special_file # if HAVE_STRUCT_STAT_ST_RDEV && defined S_ISBLK && defined S_ISCHR # define same_special_file(s, t) \ (((S_ISBLK ((s)->st_mode) && S_ISBLK ((t)->st_mode)) \ || (S_ISCHR ((s)->st_mode) && S_ISCHR ((t)->st_mode))) \ && (s)->st_rdev == (t)->st_rdev) # else # define same_special_file(s, t) 0 # endif #endif /* Do |struct stat *s, *t| describe the same file? Answer -1 if unknown. */ #ifndef same_file # define same_file(s, t) \ ((((s)->st_ino == (t)->st_ino) && ((s)->st_dev == (t)->st_dev)) \ || same_special_file (s, t)) #endif /* Do |struct stat *s, *t| have the same file attributes? POSIX says that two files are identical if |st_ino| and |st_dev| are the same, but many file systems incorrectly assign the same (device, inode) pair to two distinct files, including: - GNU/Linux NFS servers that export all local file systems as a single NFS file system, if a local device number |(st_dev)| exceeds 255, or if a local inode number |(st_ino)| exceeds 16777215. - Network Appliance NFS servers in snapshot directories; see Network Appliance bug \#195. - ClearCase MVFS; see bug id ATRia04618. Check whether two files that purport to be the same have the same attributes, to work around instances of this common bug. Do not inspect all attributes, only attributes useful in checking for this bug. It's possible for two distinct files on a buggy file system to have the same attributes, but it's not worth slowing down all implementations (or complicating the configuration) to cater to these rare cases in buggy implementations. */ #ifndef same_file_attributes # define same_file_attributes(s, t) \ ((s)->st_mode == (t)->st_mode \ && (s)->st_nlink == (t)->st_nlink \ && (s)->st_uid == (t)->st_uid \ && (s)->st_gid == (t)->st_gid \ && (s)->st_size == (t)->st_size \ && (s)->st_mtime == (t)->st_mtime \ && (s)->st_ctime == (t)->st_ctime) #endif #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) #define BB_LITTLE_ENDIAN 1 #ifdef __APPLE__ #include #define SWAP_BE64(x) OSSwapInt64(x) #elif __FreeBSD__ #include #define SWAP_BE64(x) bswap64(x) #elif __linux__ #include #define SWAP_BE64(x) bswap_64(x) #endif #endif