/* * Fundamental C definitions. * * No copyright is claimed. This code is in the public domain; do with * it what you wish. */ #ifndef UTIL_LINUX_C_H #define UTIL_LINUX_C_H #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ERR_H # include #endif #ifdef HAVE_SYS_SYSMACROS_H # include /* for major, minor */ #endif #ifndef LOGIN_NAME_MAX # define LOGIN_NAME_MAX 256 #endif #ifndef NAME_MAX # define NAME_MAX PATH_MAX #endif /* * __GNUC_PREREQ is deprecated in favour of __has_attribute() and * __has_feature(). The __has macros are supported by clang and gcc>=5. */ #ifndef __GNUC_PREREQ # if defined __GNUC__ && defined __GNUC_MINOR__ # define __GNUC_PREREQ(maj, min) \ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) # else # define __GNUC_PREREQ(maj, min) 0 # endif #endif #ifdef __GNUC__ /* &a[0] degrades to a pointer: a different type from an array */ # define __must_be_array(a) \ UL_BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0]))) # define ignore_result(x) __extension__ ({ \ __typeof__(x) __dummy __attribute__((__unused__)) = (x); (void) __dummy; \ }) #else /* !__GNUC__ */ # define __must_be_array(a) 0 # define __attribute__(_arg_) # define ignore_result(x) ((void) (x)) #endif /* !__GNUC__ */ /* "restrict" keyword fallback */ #if __STDC__ != 1 # define restrict __restrict /* use implementation __ format */ #else # ifndef __STDC_VERSION__ # define restrict __restrict /* use implementation __ format */ # else # if __STDC_VERSION__ < 199901L # define restrict __restrict /* use implementation __ format */ # endif # endif #endif /* * It evaluates to 1 if the attribute/feature is supported by the current * compilation target. Fallback for old compilers. */ #ifndef __has_attribute #define __has_attribute(x) 0 #endif #ifndef __has_feature #define __has_feature(x) 0 #endif /* * Function attributes */ #ifndef __ul_alloc_size # if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3) # define __ul_alloc_size(s) __attribute__((alloc_size(s), warn_unused_result)) # else # define __ul_alloc_size(s) # endif #endif #ifndef __ul_calloc_size # if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3) # define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s), warn_unused_result)) # else # define __ul_calloc_size(n, s) # endif #endif #if __has_attribute(returns_nonnull) || __GNUC_PREREQ (4, 9) # define __ul_returns_nonnull __attribute__((returns_nonnull)) #else # define __ul_returns_nonnull #endif /* * Force a compilation error if condition is true, but also produce a * result (of value 0 and type size_t), so the expression can be used * e.g. in a structure initializer (or wherever else comma expressions * aren't permitted). */ #define UL_BUILD_BUG_ON_ZERO(e) __extension__ (sizeof(struct { int:-!!(e); })) #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) #ifndef ARRAY_SIZE # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) #endif #ifndef PATH_MAX # define PATH_MAX 4096 #endif #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #ifndef min # define min(x, y) __extension__ ({ \ __typeof__(x) _min1 = (x); \ __typeof__(y) _min2 = (y); \ (void) (&_min1 == &_min2); \ _min1 < _min2 ? _min1 : _min2; }) #endif #ifndef max # define max(x, y) __extension__ ({ \ __typeof__(x) _max1 = (x); \ __typeof__(y) _max2 = (y); \ (void) (&_max1 == &_max2); \ _max1 > _max2 ? _max1 : _max2; }) #endif #ifndef abs_diff # define abs_diff(x, y) __extension__ ({ \ __typeof__(x) _a = (x); \ __typeof__(y) _b = (y); \ (void) (&_a == &_b); \ _a > _b ? _a - _b : _b - _a; }) #endif #ifndef cmp_numbers # define cmp_numbers(x, y) __extension__ ({ \ __typeof__(x) _a = (x); \ __typeof__(y) _b = (y); \ (void) (&_a == &_b); \ _a == _b ? 0 : _a > _b ? 1 : -1; }) #endif #ifndef cmp_timespec # define cmp_timespec(a, b, CMP) \ (((a)->tv_sec == (b)->tv_sec) \ ? ((a)->tv_nsec CMP (b)->tv_nsec) \ : ((a)->tv_sec CMP (b)->tv_sec)) #endif #ifndef cmp_stat_mtime # ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC # define cmp_stat_mtime(_a, _b, CMP) cmp_timespec(&(_a)->st_mtim, &(_b)->st_mtim, CMP) # else # define cmp_stat_mtime(_a, _b, CMP) ((_a)->st_mtime CMP (_b)->st_mtime) # endif #endif #ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #endif /* * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. */ #ifndef container_of #define container_of(ptr, type, member) __extension__ ({ \ const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #endif #ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME # ifdef HAVE___PROGNAME extern char *__progname; # define program_invocation_short_name __progname # else # ifdef HAVE_GETEXECNAME # define program_invocation_short_name \ prog_inv_sh_nm_from_file(getexecname(), 0) # else # define program_invocation_short_name \ prog_inv_sh_nm_from_file(__FILE__, 1) # endif static char prog_inv_sh_nm_buf[256]; static inline char * prog_inv_sh_nm_from_file(char *f, char stripext) { char *t; if ((t = strrchr(f, '/')) != NULL) t++; else t = f; strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1); prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0'; if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL) *t = '\0'; return prog_inv_sh_nm_buf; } # endif #endif #ifndef HAVE_ERR_H static inline void __attribute__ ((__format__ (__printf__, 4, 5))) errmsg(char doexit, int excode, char adderr, const char *fmt, ...) { fprintf(stderr, "%s: ", program_invocation_short_name); if (fmt != NULL) { va_list argp; va_start(argp, fmt); vfprintf(stderr, fmt, argp); va_end(argp); if (adderr) fprintf(stderr, ": "); } if (adderr) fprintf(stderr, "%m"); fprintf(stderr, "\n"); if (doexit) exit(excode); } #ifndef HAVE_ERR # define err(E, FMT...) errmsg(1, E, 1, FMT) #endif #ifndef HAVE_ERRX # define errx(E, FMT...) errmsg(1, E, 0, FMT) #endif #ifndef HAVE_WARN # define warn(FMT...) errmsg(0, 0, 1, FMT) #endif #ifndef HAVE_WARNX # define warnx(FMT...) errmsg(0, 0, 0, FMT) #endif #endif /* !HAVE_ERR_H */ /* Don't use inline function to avoid '#include "nls.h"' in c.h */ #define errtryhelp(eval) __extension__ ({ \ fprintf(stderr, _("Try '%s --help' for more information.\n"), \ program_invocation_short_name); \ exit(eval); \ }) /* After failed execvp() */ #define EX_EXEC_FAILED 126 /* Program located, but not usable. */ #define EX_EXEC_ENOENT 127 /* Could not find program to exec. */ #define errexec(name) err(errno == ENOENT ? EX_EXEC_ENOENT : EX_EXEC_FAILED, \ _("failed to execute %s"), name) static inline __attribute__((const)) int is_power_of_2(unsigned long num) { return (num != 0 && ((num & (num - 1)) == 0)); } #ifndef HAVE_LOFF_T typedef int64_t loff_t; #endif #if !defined(HAVE_DIRFD) && (!defined(HAVE_DECL_DIRFD) || HAVE_DECL_DIRFD == 0) && defined(HAVE_DIR_DD_FD) #include #include static inline int dirfd(DIR *d) { return d->dd_fd; } #endif /* * Fallback defines for old versions of glibc */ #include #ifdef O_CLOEXEC #define UL_CLOEXECSTR "e" #else #define UL_CLOEXECSTR "" #endif #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif #ifdef __FreeBSD_kernel__ #ifndef F_DUPFD_CLOEXEC #define F_DUPFD_CLOEXEC 17 /* Like F_DUPFD, but FD_CLOEXEC is set */ #endif #endif #ifndef AI_ADDRCONFIG #define AI_ADDRCONFIG 0x0020 #endif #ifndef IUTF8 #define IUTF8 0040000 #endif /* * MAXHOSTNAMELEN replacement */ static inline size_t get_hostname_max(void) { long len = sysconf(_SC_HOST_NAME_MAX); if (0 < len) return len; #ifdef MAXHOSTNAMELEN return MAXHOSTNAMELEN; #elif HOST_NAME_MAX return HOST_NAME_MAX; #endif return 64; } static inline int drop_permissions(void) { errno = 0; /* drop GID */ if (setgid(getgid()) < 0) goto fail; /* drop UID */ if (setuid(getuid()) < 0) goto fail; return 0; fail: return errno ? -errno : -1; } /* * The usleep function was marked obsolete in POSIX.1-2001 and was removed * in POSIX.1-2008. It was replaced with nanosleep() that provides more * advantages (like no interaction with signals and other timer functions). */ #include static inline int xusleep(useconds_t usec) { #ifdef HAVE_NANOSLEEP struct timespec waittime = { .tv_sec = usec / 1000000L, .tv_nsec = (usec % 1000000L) * 1000 }; return nanosleep(&waittime, NULL); #elif defined(HAVE_USLEEP) return usleep(usec); #else # error "System with usleep() or nanosleep() required!" #endif } /* * Constant strings for usage() functions. For more info see * Documentation/{howto-usage-function.txt,boilerplate.c} */ #define USAGE_HEADER _("\nUsage:\n") #define USAGE_OPTIONS _("\nOptions:\n") #define USAGE_FUNCTIONS _("\nFunctions:\n") #define USAGE_COMMANDS _("\nCommands:\n") #define USAGE_ARGUMENTS _("\nArguments:\n") #define USAGE_COLUMNS _("\nAvailable output columns:\n") #define USAGE_SEPARATOR "\n" #define USAGE_OPTSTR_HELP _("display this help") #define USAGE_OPTSTR_VERSION _("display version") #define USAGE_HELP_OPTIONS(marg_dsc) \ "%-" #marg_dsc "s%s\n" \ "%-" #marg_dsc "s%s\n" \ , " -h, --help", USAGE_OPTSTR_HELP \ , " -V, --version", USAGE_OPTSTR_VERSION #define USAGE_ARG_SEPARATOR "\n" #define USAGE_ARG_SIZE(_name) \ _(" %s arguments may be followed by the suffixes for\n" \ " GiB, TiB, PiB, EiB, ZiB, and YiB (the \"iB\" is optional)\n"), _name #define USAGE_MAN_TAIL(_man) _("\nFor more details see %s.\n"), _man #define UTIL_LINUX_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING #define print_version(eval) __extension__ ({ \ printf(UTIL_LINUX_VERSION); \ exit(eval); \ }) /* * seek stuff */ #ifndef SEEK_DATA # define SEEK_DATA 3 #endif #ifndef SEEK_HOLE # define SEEK_HOLE 4 #endif /* * Macros to convert #define'itions to strings, for example * #define XYXXY 42 * printf ("%s=%s\n", stringify(XYXXY), stringify_value(XYXXY)); */ #define stringify_value(s) stringify(s) #define stringify(s) #s /* Detect if we're compiled with Address Sanitizer * - gcc (__SANITIZE_ADDRESS__) * - clang (__has_feature(address_sanitizer)) */ #if !defined(HAS_FEATURE_ADDRESS_SANITIZER) # ifdef __SANITIZE_ADDRESS__ # define HAS_FEATURE_ADDRESS_SANITIZER 1 # elif defined(__has_feature) # if __has_feature(address_sanitizer) # define HAS_FEATURE_ADDRESS_SANITIZER 1 # endif # endif # if !defined(HAS_FEATURE_ADDRESS_SANITIZER) # define HAS_FEATURE_ADDRESS_SANITIZER 0 # endif #endif /* * UL_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time * instrumentation shipped with Clang and GCC) to not instrument the * annotated function. Furthermore, it will prevent the compiler from * inlining the function because inlining currently breaks the blacklisting * mechanism of AddressSanitizer. */ #if __has_feature(address_sanitizer) && __has_attribute(no_sanitize_memory) && __has_attribute(no_sanitize_address) # define UL_ASAN_BLACKLIST __attribute__((noinline)) __attribute__((no_sanitize_memory)) __attribute__((no_sanitize_address)) #else # define UL_ASAN_BLACKLIST /* nothing */ #endif /* * Note that sysconf(_SC_GETPW_R_SIZE_MAX) returns *initial* suggested size for * pwd buffer and in some cases it is not large enough. See POSIX and * getpwnam_r man page for more details. */ #define UL_GETPW_BUFSIZ (16 * 1024) /* * Darwin or other BSDs may only have MAP_ANON. To get it on Darwin we must * define _DARWIN_C_SOURCE before including sys/mman.h. We do this in config.h. */ #if !defined MAP_ANONYMOUS && defined MAP_ANON # define MAP_ANONYMOUS (MAP_ANON) #endif #endif /* UTIL_LINUX_C_H */