summaryrefslogtreecommitdiffstats
path: root/include/c.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 19:10:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 19:10:49 +0000
commitcfe5e3905201349e9cf3f95d52ff4bd100bde37d (patch)
treed0baf160cbee3195249d095f85e52d20c21acf02 /include/c.h
parentInitial commit. (diff)
downloadutil-linux-cfe5e3905201349e9cf3f95d52ff4bd100bde37d.tar.xz
util-linux-cfe5e3905201349e9cf3f95d52ff4bd100bde37d.zip
Adding upstream version 2.39.3.upstream/2.39.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/c.h')
-rw-r--r--include/c.h567
1 files changed, 567 insertions, 0 deletions
diff --git a/include/c.h b/include/c.h
new file mode 100644
index 0000000..2b70e8d
--- /dev/null
+++ b/include/c.h
@@ -0,0 +1,567 @@
+/*
+ * 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 <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <grp.h>
+
+#include <assert.h>
+
+#ifdef HAVE_ERR_H
+# include <err.h>
+#endif
+
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* 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
+
+#ifndef sizeof_member
+#define sizeof_member(TYPE, MEMBER) sizeof(((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 */
+
+
+static inline
+__attribute__((__noreturn__))
+void __err_oom(const char *file, unsigned int line)
+{
+ err(EXIT_FAILURE, "%s: %u: cannot allocate memory", file, line);
+}
+#define err_oom() __err_oom(__FILE__, __LINE__)
+
+
+/* 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 <dirent.h>
+static inline int dirfd(DIR *d)
+{
+ return d->dd_fd;
+}
+#endif
+
+/*
+ * Fallback defines for old versions of glibc
+ */
+#include <fcntl.h>
+
+#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 <time.h>
+
+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
+}
+
+
+#define ul_err_write(_m) ignore_result( write(STDERR_FILENO, _m, strlen(_m)) )
+
+/*
+ * warn() for signal handlers
+ */
+static inline void ul_sig_warn(const char *mesg)
+{
+ ul_err_write(program_invocation_short_name);
+ ul_err_write(": ");
+ ul_err_write(mesg);
+ ul_err_write("\n");
+}
+
+/*
+ * err() for signal handlers
+ */
+static inline void __attribute__((__noreturn__)) ul_sig_err(int excode, const char *mesg)
+{
+ ul_sig_warn(mesg);
+ _exit(excode);
+}
+
+/*
+ * 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); \
+})
+
+static inline void print_features(const char **features, const char *prefix)
+{
+ if (features && *features) {
+ const char **p = features;
+ while (p && *p) {
+ if (prefix && p == features)
+ printf(" (%s ", prefix);
+ else
+ fputs(p == features ? " (" : ", ", stdout);
+ fputs(*p++, stdout);
+ }
+ fputc(')', stdout);
+ }
+}
+
+#define UTIL_LINUX_VERSION_NOBREAK _("%s from %s"), program_invocation_short_name, PACKAGE_STRING
+
+#define print_version_with_features(eval, features) __extension__ ({ \
+ printf(UTIL_LINUX_VERSION_NOBREAK); \
+ print_features(features, _("features:")); \
+ fputc('\n', stdout); \
+ 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
+
+#define SINT_MAX(t) (((t)1 << (sizeof(t) * 8 - 2)) - (t)1 + ((t)1 << (sizeof(t) * 8 - 2)))
+
+#endif /* UTIL_LINUX_C_H */