]> git.ipfire.org Git - thirdparty/util-linux.git/blob - include/c.h
Merge branch 'PR/lscpu-caches-sep' of github.com:karelzak/util-linux-work
[thirdparty/util-linux.git] / include / c.h
1 /*
2 * Fundamental C definitions.
3 *
4 * No copyright is claimed. This code is in the public domain; do with
5 * it what you wish.
6 */
7 #ifndef UTIL_LINUX_C_H
8 #define UTIL_LINUX_C_H
9
10 #include <limits.h>
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <stdarg.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <sys/types.h>
20 #include <grp.h>
21
22 #include <assert.h>
23
24 #ifdef HAVE_ERR_H
25 # include <err.h>
26 #endif
27
28 #ifdef HAVE_SYS_SYSMACROS_H
29 # include <sys/sysmacros.h> /* for major, minor */
30 #endif
31
32 #ifndef LOGIN_NAME_MAX
33 # define LOGIN_NAME_MAX 256
34 #endif
35
36 #ifndef NAME_MAX
37 # define NAME_MAX PATH_MAX
38 #endif
39
40 /*
41 * __GNUC_PREREQ is deprecated in favour of __has_attribute() and
42 * __has_feature(). The __has macros are supported by clang and gcc>=5.
43 */
44 #ifndef __GNUC_PREREQ
45 # if defined __GNUC__ && defined __GNUC_MINOR__
46 # define __GNUC_PREREQ(maj, min) \
47 ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
48 # else
49 # define __GNUC_PREREQ(maj, min) 0
50 # endif
51 #endif
52
53 #ifdef __GNUC__
54
55 /* &a[0] degrades to a pointer: a different type from an array */
56 # define __must_be_array(a) \
57 UL_BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0])))
58
59 # define ignore_result(x) __extension__ ({ \
60 __typeof__(x) __dummy __attribute__((__unused__)) = (x); (void) __dummy; \
61 })
62
63 #else /* !__GNUC__ */
64 # define __must_be_array(a) 0
65 # define __attribute__(_arg_)
66 # define ignore_result(x) ((void) (x))
67 #endif /* !__GNUC__ */
68
69
70 /* "restrict" keyword fallback */
71 #if __STDC__ != 1
72 # define restrict __restrict /* use implementation __ format */
73 #else
74 # ifndef __STDC_VERSION__
75 # define restrict __restrict /* use implementation __ format */
76 # else
77 # if __STDC_VERSION__ < 199901L
78 # define restrict __restrict /* use implementation __ format */
79 # endif
80 # endif
81 #endif
82
83
84 /*
85 * It evaluates to 1 if the attribute/feature is supported by the current
86 * compilation target. Fallback for old compilers.
87 */
88 #ifndef __has_attribute
89 #define __has_attribute(x) 0
90 #endif
91
92 #ifndef __has_feature
93 #define __has_feature(x) 0
94 #endif
95
96 /*
97 * Function attributes
98 */
99 #ifndef __ul_alloc_size
100 # if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3)
101 # define __ul_alloc_size(s) __attribute__((alloc_size(s), warn_unused_result))
102 # else
103 # define __ul_alloc_size(s)
104 # endif
105 #endif
106
107 #ifndef __ul_calloc_size
108 # if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3)
109 # define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s), warn_unused_result))
110 # else
111 # define __ul_calloc_size(n, s)
112 # endif
113 #endif
114
115 #if __has_attribute(returns_nonnull) || __GNUC_PREREQ (4, 9)
116 # define __ul_returns_nonnull __attribute__((returns_nonnull))
117 #else
118 # define __ul_returns_nonnull
119 #endif
120
121 /*
122 * Force a compilation error if condition is true, but also produce a
123 * result (of value 0 and type size_t), so the expression can be used
124 * e.g. in a structure initializer (or wherever else comma expressions
125 * aren't permitted).
126 */
127 #define UL_BUILD_BUG_ON_ZERO(e) __extension__ (sizeof(struct { int:-!!(e); }))
128 #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
129
130 #ifndef ARRAY_SIZE
131 # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
132 #endif
133
134 #ifndef PATH_MAX
135 # define PATH_MAX 4096
136 #endif
137
138 #ifndef TRUE
139 # define TRUE 1
140 #endif
141
142 #ifndef FALSE
143 # define FALSE 0
144 #endif
145
146 #ifndef min
147 # define min(x, y) __extension__ ({ \
148 __typeof__(x) _min1 = (x); \
149 __typeof__(y) _min2 = (y); \
150 (void) (&_min1 == &_min2); \
151 _min1 < _min2 ? _min1 : _min2; })
152 #endif
153
154 #ifndef max
155 # define max(x, y) __extension__ ({ \
156 __typeof__(x) _max1 = (x); \
157 __typeof__(y) _max2 = (y); \
158 (void) (&_max1 == &_max2); \
159 _max1 > _max2 ? _max1 : _max2; })
160 #endif
161
162 #ifndef abs_diff
163 # define abs_diff(x, y) __extension__ ({ \
164 __typeof__(x) _a = (x); \
165 __typeof__(y) _b = (y); \
166 (void) (&_a == &_b); \
167 _a > _b ? _a - _b : _b - _a; })
168 #endif
169
170 #ifndef cmp_numbers
171 # define cmp_numbers(x, y) __extension__ ({ \
172 __typeof__(x) _a = (x); \
173 __typeof__(y) _b = (y); \
174 (void) (&_a == &_b); \
175 _a == _b ? 0 : _a > _b ? 1 : -1; })
176 #endif
177
178
179 #ifndef cmp_timespec
180 # define cmp_timespec(a, b, CMP) \
181 (((a)->tv_sec == (b)->tv_sec) \
182 ? ((a)->tv_nsec CMP (b)->tv_nsec) \
183 : ((a)->tv_sec CMP (b)->tv_sec))
184 #endif
185
186
187 #ifndef cmp_stat_mtime
188 # ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
189 # define cmp_stat_mtime(_a, _b, CMP) cmp_timespec(&(_a)->st_mtim, &(_b)->st_mtim, CMP)
190 # else
191 # define cmp_stat_mtime(_a, _b, CMP) ((_a)->st_mtime CMP (_b)->st_mtime)
192 # endif
193 #endif
194
195
196 #ifndef offsetof
197 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
198 #endif
199
200 #ifndef sizeof_member
201 #define sizeof_member(TYPE, MEMBER) sizeof(((TYPE *)0)->MEMBER)
202 #endif
203
204 /*
205 * container_of - cast a member of a structure out to the containing structure
206 * @ptr: the pointer to the member.
207 * @type: the type of the container struct this is embedded in.
208 * @member: the name of the member within the struct.
209 */
210 #ifndef container_of
211 #define container_of(ptr, type, member) __extension__ ({ \
212 const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
213 (type *)( (char *)__mptr - offsetof(type,member) );})
214 #endif
215
216 #define read_unaligned_member(p, m) __extension__ ({ \
217 size_t offset = offsetof(__typeof__(* p), m); \
218 __typeof__(p->m) v; \
219 memcpy(&v, ((unsigned char *)p) + offset, sizeof(v)); \
220 v; })
221
222 #define member_ptr(p, m) (((unsigned char *)p) + offsetof(__typeof__(*p), m))
223
224 #ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
225 # ifdef HAVE___PROGNAME
226 extern char *__progname;
227 # define program_invocation_short_name __progname
228 # else
229 # ifdef HAVE_GETEXECNAME
230 # define program_invocation_short_name \
231 prog_inv_sh_nm_from_file(getexecname(), 0)
232 # else
233 # define program_invocation_short_name \
234 prog_inv_sh_nm_from_file(__FILE__, 1)
235 # endif
236 static char prog_inv_sh_nm_buf[256];
237 static inline char *
238 prog_inv_sh_nm_from_file(char *f, char stripext)
239 {
240 char *t;
241
242 if ((t = strrchr(f, '/')) != NULL)
243 t++;
244 else
245 t = f;
246
247 strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1);
248 prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0';
249
250 if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL)
251 *t = '\0';
252
253 return prog_inv_sh_nm_buf;
254 }
255 # endif
256 #endif
257
258
259 #ifndef HAVE_ERR_H
260 static inline void __attribute__ ((__format__ (__printf__, 4, 5)))
261 errmsg(char doexit, int excode, char adderr, const char *fmt, ...)
262 {
263 fprintf(stderr, "%s: ", program_invocation_short_name);
264 if (fmt != NULL) {
265 va_list argp;
266 va_start(argp, fmt);
267 vfprintf(stderr, fmt, argp);
268 va_end(argp);
269 if (adderr)
270 fprintf(stderr, ": ");
271 }
272 if (adderr)
273 fprintf(stderr, "%m");
274 fprintf(stderr, "\n");
275 if (doexit)
276 exit(excode);
277 }
278
279 #ifndef HAVE_ERR
280 # define err(E, FMT...) errmsg(1, E, 1, FMT)
281 #endif
282
283 #ifndef HAVE_ERRX
284 # define errx(E, FMT...) errmsg(1, E, 0, FMT)
285 #endif
286
287 #ifndef HAVE_WARN
288 # define warn(FMT...) errmsg(0, 0, 1, FMT)
289 #endif
290
291 #ifndef HAVE_WARNX
292 # define warnx(FMT...) errmsg(0, 0, 0, FMT)
293 #endif
294 #endif /* !HAVE_ERR_H */
295
296
297 static inline
298 __attribute__((__noreturn__))
299 void __err_oom(const char *file, unsigned int line)
300 {
301 err(EXIT_FAILURE, "%s: %u: cannot allocate memory", file, line);
302 }
303 #define err_oom() __err_oom(__FILE__, __LINE__)
304
305 #define err_nosys(exitcode, ...) \
306 err(errno == ENOSYS ? EXIT_NOTSUPP : exitcode, __VA_ARGS__)
307
308
309 /* Don't use inline function to avoid '#include "nls.h"' in c.h
310 */
311 #define errtryhelp(eval) __extension__ ({ \
312 fprintf(stderr, _("Try '%s --help' for more information.\n"), \
313 program_invocation_short_name); \
314 exit(eval); \
315 })
316
317 /* After failed execvp() */
318 #define EX_EXEC_FAILED 126 /* Program located, but not usable. */
319 #define EX_EXEC_ENOENT 127 /* Could not find program to exec. */
320 #define errexec(name) err(errno == ENOENT ? EX_EXEC_ENOENT : EX_EXEC_FAILED, \
321 _("failed to execute %s"), name)
322
323 static inline __attribute__((const)) int is_power_of_2(unsigned long num)
324 {
325 return (num != 0 && ((num & (num - 1)) == 0));
326 }
327
328 #ifndef HAVE_LOFF_T
329 typedef int64_t loff_t;
330 #endif
331
332 #if !defined(HAVE_DIRFD) \
333 && (!defined(HAVE_DECL_DIRFD) || HAVE_DECL_DIRFD == 0) \
334 && defined(HAVE_DIR_DD_FD)
335 #include <dirent.h>
336 static inline int dirfd(DIR *d)
337 {
338 return d->dd_fd;
339 }
340 #endif
341
342 /*
343 * Fallback defines for old versions of glibc
344 */
345 #include <fcntl.h>
346
347 #ifdef O_CLOEXEC
348 #define UL_CLOEXECSTR "e"
349 #else
350 #define UL_CLOEXECSTR ""
351 #endif
352
353 #ifndef O_CLOEXEC
354 #define O_CLOEXEC 0
355 #endif
356
357 #ifdef __FreeBSD_kernel__
358 #ifndef F_DUPFD_CLOEXEC
359 #define F_DUPFD_CLOEXEC 17 /* Like F_DUPFD, but FD_CLOEXEC is set */
360 #endif
361 #endif
362
363
364 #ifndef AI_ADDRCONFIG
365 #define AI_ADDRCONFIG 0x0020
366 #endif
367
368 #ifndef IUTF8
369 #define IUTF8 0040000
370 #endif
371
372 /*
373 * MAXHOSTNAMELEN replacement
374 */
375 static inline size_t get_hostname_max(void)
376 {
377 long len = sysconf(_SC_HOST_NAME_MAX);
378
379 if (0 < len)
380 return len;
381
382 #ifdef MAXHOSTNAMELEN
383 return MAXHOSTNAMELEN;
384 #elif HOST_NAME_MAX
385 return HOST_NAME_MAX;
386 #endif
387 return 64;
388 }
389
390
391 static inline int drop_permissions(void)
392 {
393 errno = 0;
394
395 /* drop GID */
396 if (setgid(getgid()) < 0)
397 goto fail;
398
399 /* drop UID */
400 if (setuid(getuid()) < 0)
401 goto fail;
402
403 return 0;
404 fail:
405 return errno ? -errno : -1;
406 }
407
408 /*
409 * The usleep function was marked obsolete in POSIX.1-2001 and was removed
410 * in POSIX.1-2008. It was replaced with nanosleep() that provides more
411 * advantages (like no interaction with signals and other timer functions).
412 */
413 #include <time.h>
414
415 static inline int xusleep(useconds_t usec)
416 {
417 #ifdef HAVE_NANOSLEEP
418 struct timespec waittime = {
419 .tv_sec = usec / 1000000L,
420 .tv_nsec = (usec % 1000000L) * 1000
421 };
422 return nanosleep(&waittime, NULL);
423 #elif defined(HAVE_USLEEP)
424 return usleep(usec);
425 #else
426 # error "System with usleep() or nanosleep() required!"
427 #endif
428 }
429
430
431 #define ul_err_write(_m) ignore_result( write(STDERR_FILENO, _m, strlen(_m)) )
432
433 /*
434 * warn() for signal handlers
435 */
436 static inline void ul_sig_warn(const char *mesg)
437 {
438 ul_err_write(program_invocation_short_name);
439 ul_err_write(": ");
440 ul_err_write(mesg);
441 ul_err_write("\n");
442 }
443
444 /*
445 * err() for signal handlers
446 */
447 static inline void __attribute__((__noreturn__)) ul_sig_err(int excode, const char *mesg)
448 {
449 ul_sig_warn(mesg);
450 _exit(excode);
451 }
452
453 /*
454 * Constant strings for usage() functions. For more info see
455 * Documentation/{howto-usage-function.txt,boilerplate.c}
456 */
457 #define USAGE_HEADER _("\nUsage:\n")
458 #define USAGE_OPTIONS _("\nOptions:\n")
459 #define USAGE_FUNCTIONS _("\nFunctions:\n")
460 #define USAGE_COMMANDS _("\nCommands:\n")
461 #define USAGE_ARGUMENTS _("\nArguments:\n")
462 #define USAGE_COLUMNS _("\nAvailable output columns:\n")
463 #define USAGE_DEFAULT_COLUMNS _("\nDefault columns:\n")
464 #define USAGE_SEPARATOR "\n"
465
466 #define USAGE_OPTSTR_HELP _("display this help")
467 #define USAGE_OPTSTR_VERSION _("display version")
468
469 #define USAGE_HELP_OPTIONS(marg_dsc) \
470 "%-" #marg_dsc "s%s\n" \
471 "%-" #marg_dsc "s%s\n" \
472 , " -h, --help", USAGE_OPTSTR_HELP \
473 , " -V, --version", USAGE_OPTSTR_VERSION
474
475 #define USAGE_ARG_SEPARATOR "\n"
476 #define USAGE_ARG_SIZE(_name) \
477 _(" %s arguments may be followed by the suffixes for\n" \
478 " GiB, TiB, PiB, EiB, ZiB, and YiB (the \"iB\" is optional)\n"), _name
479
480 #define USAGE_MAN_TAIL(_man) _("\nFor more details see %s.\n"), _man
481
482 #define UTIL_LINUX_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING
483
484 #define print_version(eval) __extension__ ({ \
485 printf(UTIL_LINUX_VERSION); \
486 exit(eval); \
487 })
488
489 static inline void print_features(const char **features, const char *prefix)
490 {
491 if (features && *features) {
492 const char **p = features;
493 while (p && *p) {
494 if (prefix && p == features)
495 printf(" (%s ", prefix);
496 else
497 fputs(p == features ? " (" : ", ", stdout);
498 fputs(*p++, stdout);
499 }
500 fputc(')', stdout);
501 }
502 }
503
504 #define UTIL_LINUX_VERSION_NOBREAK _("%s from %s"), program_invocation_short_name, PACKAGE_STRING
505
506 #define print_version_with_features(eval, features) __extension__ ({ \
507 printf(UTIL_LINUX_VERSION_NOBREAK); \
508 print_features(features, _("features:")); \
509 fputc('\n', stdout); \
510 exit(eval); \
511 })
512
513 /*
514 * seek stuff
515 */
516 #ifndef SEEK_DATA
517 # define SEEK_DATA 3
518 #endif
519 #ifndef SEEK_HOLE
520 # define SEEK_HOLE 4
521 #endif
522
523
524 /*
525 * Macros to convert #define'itions to strings, for example
526 * #define XYXXY 42
527 * printf ("%s=%s\n", stringify(XYXXY), stringify_value(XYXXY));
528 */
529 #define stringify_value(s) stringify(s)
530 #define stringify(s) #s
531
532 /* Detect if we're compiled with Address Sanitizer
533 * - gcc (__SANITIZE_ADDRESS__)
534 * - clang (__has_feature(address_sanitizer))
535 */
536 #if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
537 # ifdef __SANITIZE_ADDRESS__
538 # define HAS_FEATURE_ADDRESS_SANITIZER 1
539 # elif defined(__has_feature)
540 # if __has_feature(address_sanitizer)
541 # define HAS_FEATURE_ADDRESS_SANITIZER 1
542 # endif
543 # endif
544 # if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
545 # define HAS_FEATURE_ADDRESS_SANITIZER 0
546 # endif
547 #endif
548
549 /*
550 * UL_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
551 * instrumentation shipped with Clang and GCC) to not instrument the
552 * annotated function. Furthermore, it will prevent the compiler from
553 * inlining the function because inlining currently breaks the blacklisting
554 * mechanism of AddressSanitizer.
555 */
556 #if __has_feature(address_sanitizer) && __has_attribute(no_sanitize_memory) && __has_attribute(no_sanitize_address)
557 # define UL_ASAN_BLACKLIST __attribute__((noinline)) __attribute__((no_sanitize_memory)) __attribute__((no_sanitize_address))
558 #else
559 # define UL_ASAN_BLACKLIST /* nothing */
560 #endif
561
562 /*
563 * Note that sysconf(_SC_GETPW_R_SIZE_MAX) returns *initial* suggested size for
564 * pwd buffer and in some cases it is not large enough. See POSIX and
565 * getpwnam_r man page for more details.
566 */
567 #define UL_GETPW_BUFSIZ (16 * 1024)
568
569 /*
570 * Darwin or other BSDs may only have MAP_ANON. To get it on Darwin we must
571 * define _DARWIN_C_SOURCE before including sys/mman.h. We do this in config.h.
572 */
573 #if !defined MAP_ANONYMOUS && defined MAP_ANON
574 # define MAP_ANONYMOUS (MAP_ANON)
575 #endif
576
577 #define SINT_MAX(t) (((t)1 << (sizeof(t) * 8 - 2)) - (t)1 + ((t)1 << (sizeof(t) * 8 - 2)))
578
579 #endif /* UTIL_LINUX_C_H */