]>
Commit | Line | Data |
---|---|---|
4d0dbb8b KZ |
1 | /* |
2 | * Fundamental C definitions. | |
3 | */ | |
4 | ||
5 | #ifndef UTIL_LINUX_C_H | |
6 | #define UTIL_LINUX_C_H | |
7 | ||
8 | #include <limits.h> | |
aa1f95c3 | 9 | #include <stddef.h> |
eb76ca98 FG |
10 | #include <stdint.h> |
11 | #include <stdio.h> | |
9199f5cd | 12 | #include <unistd.h> |
eb76ca98 | 13 | #include <stdarg.h> |
4d498513 | 14 | #include <stdlib.h> |
eb76ca98 FG |
15 | #include <string.h> |
16 | #include <errno.h> | |
17 | ||
2c656779 KZ |
18 | #include <assert.h> |
19 | ||
eb76ca98 FG |
20 | #ifdef HAVE_ERR_H |
21 | # include <err.h> | |
22 | #endif | |
4d0dbb8b | 23 | |
075d2c07 KZ |
24 | #ifdef HAVE_SYS_SYSMACROS_H |
25 | # include <sys/sysmacros.h> /* for major, minor */ | |
26 | #endif | |
27 | ||
790119b8 KZ |
28 | #ifndef LOGIN_NAME_MAX |
29 | # define LOGIN_NAME_MAX 256 | |
30 | #endif | |
31 | ||
7d5976f8 SJ |
32 | #ifndef NAME_MAX |
33 | # define NAME_MAX PATH_MAX | |
34 | #endif | |
35 | ||
4d0dbb8b | 36 | /* |
34b0a305 KZ |
37 | * __GNUC_PREREQ is deprecated in favour of __has_attribute() and |
38 | * __has_feature(). The __has macros are supported by clang and gcc>=5. | |
4d0dbb8b | 39 | */ |
40084d0d KZ |
40 | #ifndef __GNUC_PREREQ |
41 | # if defined __GNUC__ && defined __GNUC_MINOR__ | |
42 | # define __GNUC_PREREQ(maj, min) \ | |
43 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) | |
44 | # else | |
45 | # define __GNUC_PREREQ(maj, min) 0 | |
46 | # endif | |
47 | #endif | |
48 | ||
4d0dbb8b KZ |
49 | #ifdef __GNUC__ |
50 | ||
51 | /* &a[0] degrades to a pointer: a different type from an array */ | |
52 | # define __must_be_array(a) \ | |
bfda68fd | 53 | UL_BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0]))) |
4d0dbb8b | 54 | |
2a0d2a8e | 55 | # define ignore_result(x) __extension__ ({ \ |
c764e1a4 | 56 | __typeof__(x) __dummy __attribute__((__unused__)) = (x); (void) __dummy; \ |
c25dc28d | 57 | }) |
2dd570ec | 58 | |
4d0dbb8b KZ |
59 | #else /* !__GNUC__ */ |
60 | # define __must_be_array(a) 0 | |
61 | # define __attribute__(_arg_) | |
2dd570ec | 62 | # define ignore_result(x) ((void) (x)) |
4d0dbb8b KZ |
63 | #endif /* !__GNUC__ */ |
64 | ||
34b0a305 KZ |
65 | /* |
66 | * It evaluates to 1 if the attribute/feature is supported by the current | |
67 | * compilation targed. Fallback for old compilers. | |
68 | */ | |
69 | #ifndef __has_attribute | |
70 | #define __has_attribute(x) 0 | |
71 | #endif | |
72 | ||
73 | #ifndef __has_feature | |
74 | #define __has_feature(x) 0 | |
75 | #endif | |
76 | ||
40084d0d KZ |
77 | /* |
78 | * Function attributes | |
79 | */ | |
80 | #ifndef __ul_alloc_size | |
34b0a305 | 81 | # if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3) |
c9678832 | 82 | # define __ul_alloc_size(s) __attribute__((alloc_size(s), warn_unused_result)) |
40084d0d KZ |
83 | # else |
84 | # define __ul_alloc_size(s) | |
85 | # endif | |
86 | #endif | |
87 | ||
88 | #ifndef __ul_calloc_size | |
34b0a305 | 89 | # if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3) |
c9678832 | 90 | # define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s), warn_unused_result)) |
40084d0d KZ |
91 | # else |
92 | # define __ul_calloc_size(n, s) | |
93 | # endif | |
94 | #endif | |
4d0dbb8b | 95 | |
34b0a305 | 96 | #if __has_attribute(returns_nonnull) || __GNUC_PREREQ (4, 9) |
f1b327f8 SK |
97 | # define __ul_returns_nonnull __attribute__((returns_nonnull)) |
98 | #else | |
99 | # define __ul_returns_nonnull | |
100 | #endif | |
101 | ||
68411ba2 BS |
102 | /* |
103 | * Force a compilation error if condition is true, but also produce a | |
4d0dbb8b | 104 | * result (of value 0 and type size_t), so the expression can be used |
68411ba2 | 105 | * e.g. in a structure initializer (or wherever else comma expressions |
4d0dbb8b KZ |
106 | * aren't permitted). |
107 | */ | |
2a0d2a8e | 108 | #define UL_BUILD_BUG_ON_ZERO(e) __extension__ (sizeof(struct { int:-!!(e); })) |
4d0dbb8b KZ |
109 | #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) |
110 | ||
111 | #ifndef ARRAY_SIZE | |
112 | # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) | |
113 | #endif | |
114 | ||
115 | #ifndef PATH_MAX | |
116 | # define PATH_MAX 4096 | |
117 | #endif | |
118 | ||
119 | #ifndef TRUE | |
120 | # define TRUE 1 | |
121 | #endif | |
122 | ||
123 | #ifndef FALSE | |
124 | # define FALSE 0 | |
125 | #endif | |
126 | ||
70502c52 | 127 | #ifndef min |
2a0d2a8e | 128 | # define min(x, y) __extension__ ({ \ |
c764e1a4 SK |
129 | __typeof__(x) _min1 = (x); \ |
130 | __typeof__(y) _min2 = (y); \ | |
1cb1641d KZ |
131 | (void) (&_min1 == &_min2); \ |
132 | _min1 < _min2 ? _min1 : _min2; }) | |
70502c52 | 133 | #endif |
1cb1641d | 134 | |
70502c52 | 135 | #ifndef max |
2a0d2a8e | 136 | # define max(x, y) __extension__ ({ \ |
c764e1a4 SK |
137 | __typeof__(x) _max1 = (x); \ |
138 | __typeof__(y) _max2 = (y); \ | |
1cb1641d KZ |
139 | (void) (&_max1 == &_max2); \ |
140 | _max1 > _max2 ? _max1 : _max2; }) | |
70502c52 | 141 | #endif |
1cb1641d | 142 | |
19ff8ff7 KZ |
143 | #ifndef cmp_numbers |
144 | # define cmp_numbers(x, y) __extension__ ({ \ | |
145 | __typeof__(x) _a = (x); \ | |
146 | __typeof__(y) _b = (y); \ | |
147 | (void) (&_a == &_b); \ | |
764b697c | 148 | _a == _b ? 0 : _a > _b ? 1 : -1; }) |
19ff8ff7 KZ |
149 | #endif |
150 | ||
5b9df028 DB |
151 | #ifndef offsetof |
152 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | |
153 | #endif | |
154 | ||
eb06d5d4 KZ |
155 | /* |
156 | * container_of - cast a member of a structure out to the containing structure | |
157 | * @ptr: the pointer to the member. | |
158 | * @type: the type of the container struct this is embedded in. | |
159 | * @member: the name of the member within the struct. | |
160 | */ | |
ae278c88 | 161 | #ifndef container_of |
eb06d5d4 | 162 | #define container_of(ptr, type, member) __extension__ ({ \ |
1866fa6a RM |
163 | const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ |
164 | (type *)( (char *)__mptr - offsetof(type,member) );}) | |
ae278c88 | 165 | #endif |
5b9df028 | 166 | |
4b2b6716 | 167 | #ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME |
168 | # ifdef HAVE___PROGNAME | |
169 | extern char *__progname; | |
170 | # define program_invocation_short_name __progname | |
171 | # else | |
172 | # ifdef HAVE_GETEXECNAME | |
4b2b6716 | 173 | # define program_invocation_short_name \ |
174 | prog_inv_sh_nm_from_file(getexecname(), 0) | |
175 | # else | |
176 | # define program_invocation_short_name \ | |
177 | prog_inv_sh_nm_from_file(__FILE__, 1) | |
178 | # endif | |
179 | static char prog_inv_sh_nm_buf[256]; | |
180 | static inline char * | |
181 | prog_inv_sh_nm_from_file(char *f, char stripext) | |
182 | { | |
183 | char *t; | |
184 | ||
185 | if ((t = strrchr(f, '/')) != NULL) | |
186 | t++; | |
187 | else | |
188 | t = f; | |
189 | ||
190 | strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1); | |
191 | prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0'; | |
192 | ||
193 | if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL) | |
194 | *t = '\0'; | |
195 | ||
196 | return prog_inv_sh_nm_buf; | |
197 | } | |
198 | # endif | |
199 | #endif | |
200 | ||
06ceeef8 | 201 | |
eb76ca98 FG |
202 | #ifndef HAVE_ERR_H |
203 | static inline void | |
204 | errmsg(char doexit, int excode, char adderr, const char *fmt, ...) | |
205 | { | |
206 | fprintf(stderr, "%s: ", program_invocation_short_name); | |
207 | if (fmt != NULL) { | |
208 | va_list argp; | |
209 | va_start(argp, fmt); | |
210 | vfprintf(stderr, fmt, argp); | |
211 | va_end(argp); | |
212 | if (adderr) | |
213 | fprintf(stderr, ": "); | |
214 | } | |
215 | if (adderr) | |
960cf573 | 216 | fprintf(stderr, "%m"); |
eb76ca98 FG |
217 | fprintf(stderr, "\n"); |
218 | if (doexit) | |
219 | exit(excode); | |
220 | } | |
221 | ||
222 | #ifndef HAVE_ERR | |
223 | # define err(E, FMT...) errmsg(1, E, 1, FMT) | |
224 | #endif | |
225 | ||
226 | #ifndef HAVE_ERRX | |
227 | # define errx(E, FMT...) errmsg(1, E, 0, FMT) | |
228 | #endif | |
229 | ||
230 | #ifndef HAVE_WARN | |
231 | # define warn(FMT...) errmsg(0, 0, 1, FMT) | |
232 | #endif | |
233 | ||
234 | #ifndef HAVE_WARNX | |
235 | # define warnx(FMT...) errmsg(0, 0, 0, FMT) | |
236 | #endif | |
237 | #endif /* !HAVE_ERR_H */ | |
238 | ||
239 | ||
3077b371 KZ |
240 | /* Don't use inline function to avoid '#include "nls.h"' in c.h |
241 | */ | |
242 | #define errtryhelp(eval) __extension__ ({ \ | |
243 | fprintf(stderr, _("Try '%s --help' for more information.\n"), \ | |
244 | program_invocation_short_name); \ | |
245 | exit(eval); \ | |
246 | }) | |
247 | ||
cf654e1c KZ |
248 | /* After failed execvp() */ |
249 | #define EX_EXEC_FAILED 126 /* Program located, but not usable. */ | |
250 | #define EX_EXEC_ENOENT 127 /* Could not find program to exec. */ | |
251 | #define errexec(name) err(errno == ENOENT ? EX_EXEC_ENOENT : EX_EXEC_FAILED, \ | |
252 | _("failed to execute %s"), name) | |
253 | ||
3077b371 | 254 | |
973af806 KZ |
255 | static inline __attribute__((const)) int is_power_of_2(unsigned long num) |
256 | { | |
257 | return (num != 0 && ((num & (num - 1)) == 0)); | |
258 | } | |
259 | ||
5be1c033 FG |
260 | #ifndef HAVE_LOFF_T |
261 | typedef int64_t loff_t; | |
262 | #endif | |
263 | ||
d58c47d9 FG |
264 | #if !defined(HAVE_DIRFD) && (!defined(HAVE_DECL_DIRFD) || HAVE_DECL_DIRFD == 0) && defined(HAVE_DIR_DD_FD) |
265 | #include <sys/types.h> | |
266 | #include <dirent.h> | |
267 | static inline int dirfd(DIR *d) | |
268 | { | |
269 | return d->dd_fd; | |
270 | } | |
271 | #endif | |
272 | ||
7cf78990 DB |
273 | /* |
274 | * Fallback defines for old versions of glibc | |
275 | */ | |
e9d00e66 | 276 | #include <fcntl.h> |
2ffad204 KZ |
277 | |
278 | #ifdef O_CLOEXEC | |
279 | #define UL_CLOEXECSTR "e" | |
280 | #else | |
281 | #define UL_CLOEXECSTR "" | |
282 | #endif | |
283 | ||
4799c95f KZ |
284 | #ifndef O_CLOEXEC |
285 | #define O_CLOEXEC 0 | |
286 | #endif | |
973af806 | 287 | |
f51275ee GJ |
288 | #ifdef __FreeBSD_kernel__ |
289 | #ifndef F_DUPFD_CLOEXEC | |
290 | #define F_DUPFD_CLOEXEC 17 /* Like F_DUPFD, but FD_CLOEXEC is set */ | |
291 | #endif | |
292 | #endif | |
293 | ||
2ffad204 | 294 | |
7cf78990 DB |
295 | #ifndef AI_ADDRCONFIG |
296 | #define AI_ADDRCONFIG 0x0020 | |
297 | #endif | |
298 | ||
299 | #ifndef IUTF8 | |
300 | #define IUTF8 0040000 | |
301 | #endif | |
302 | ||
1ee4dff7 SK |
303 | /* |
304 | * MAXHOSTNAMELEN replacement | |
305 | */ | |
306 | static inline size_t get_hostname_max(void) | |
307 | { | |
308 | long len = sysconf(_SC_HOST_NAME_MAX); | |
309 | ||
310 | if (0 < len) | |
311 | return len; | |
312 | ||
313 | #ifdef MAXHOSTNAMELEN | |
314 | return MAXHOSTNAMELEN; | |
315 | #elif HOST_NAME_MAX | |
316 | return HOST_NAME_MAX; | |
317 | #endif | |
318 | return 64; | |
319 | } | |
320 | ||
2a31396a | 321 | /* |
68411ba2 BS |
322 | * The usleep function was marked obsolete in POSIX.1-2001 and was removed |
323 | * in POSIX.1-2008. It was replaced with nanosleep() that provides more | |
324 | * advantages (like no interaction with signals and other timer functions). | |
2a31396a | 325 | */ |
a5bd7939 KZ |
326 | #include <time.h> |
327 | ||
328 | static inline int xusleep(useconds_t usec) | |
2a31396a | 329 | { |
a5bd7939 | 330 | #ifdef HAVE_NANOSLEEP |
2a31396a KZ |
331 | struct timespec waittime = { |
332 | .tv_sec = usec / 1000000L, | |
333 | .tv_nsec = (usec % 1000000L) * 1000 | |
b33f24b2 WF |
334 | }; |
335 | return nanosleep(&waittime, NULL); | |
a5bd7939 KZ |
336 | #elif defined(HAVE_USLEEP) |
337 | return usleep(usec); | |
338 | #else | |
339 | # error "System with usleep() or nanosleep() required!" | |
2a31396a | 340 | #endif |
a5bd7939 | 341 | } |
2a31396a | 342 | |
cd7accd4 SK |
343 | /* |
344 | * Constant strings for usage() functions. For more info see | |
6e2d5a44 | 345 | * Documentation/{howto-usage-function.txt,boilerplate.c} |
cd7accd4 SK |
346 | */ |
347 | #define USAGE_HEADER _("\nUsage:\n") | |
348 | #define USAGE_OPTIONS _("\nOptions:\n") | |
513bfbef | 349 | #define USAGE_FUNCTIONS _("\nFunctions:\n") |
6e2d5a44 | 350 | #define USAGE_COMMANDS _("\nCommands:\n") |
c3a4cfc5 | 351 | #define USAGE_COLUMNS _("\nAvailable output columns:\n") |
82b219f7 | 352 | #define USAGE_SEPARATOR "\n" |
b1a294c4 | 353 | |
551b9cd3 | 354 | #define USAGE_OPTSTR_HELP _("display this help") |
08e3c9e6 | 355 | #define USAGE_OPTSTR_VERSION _("display version") |
b1a294c4 | 356 | |
f45f3ec3 | 357 | #define USAGE_HELP_OPTIONS(marg_dsc) \ |
b1a294c4 RM |
358 | "%-" #marg_dsc "s%s\n" \ |
359 | "%-" #marg_dsc "s%s\n" \ | |
360 | , " -h, --help", USAGE_OPTSTR_HELP \ | |
f45f3ec3 | 361 | , " -V, --version", USAGE_OPTSTR_VERSION |
b1a294c4 | 362 | |
6f162034 | 363 | #define USAGE_MAN_TAIL(_man) _("\nFor more details see %s.\n"), _man |
cd7accd4 SK |
364 | |
365 | #define UTIL_LINUX_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING | |
366 | ||
2c308875 KZ |
367 | #define print_version(eval) __extension__ ({ \ |
368 | printf(UTIL_LINUX_VERSION); \ | |
369 | exit(eval); \ | |
370 | }) | |
371 | ||
640fc1b8 KZ |
372 | /* |
373 | * scanf modifiers for "strings allocation" | |
374 | */ | |
375 | #ifdef HAVE_SCANF_MS_MODIFIER | |
376 | #define UL_SCNsA "%ms" | |
377 | #elif defined(HAVE_SCANF_AS_MODIFIER) | |
378 | #define UL_SCNsA "%as" | |
379 | #endif | |
380 | ||
9199f5cd KZ |
381 | /* |
382 | * seek stuff | |
383 | */ | |
384 | #ifndef SEEK_DATA | |
385 | # define SEEK_DATA 3 | |
386 | #endif | |
387 | #ifndef SEEK_HOLE | |
388 | # define SEEK_HOLE 4 | |
389 | #endif | |
390 | ||
ff1aaf99 SK |
391 | |
392 | /* | |
393 | * Macros to convert #define'itions to strings, for example | |
394 | * #define XYXXY 42 | |
395 | * printf ("%s=%s\n", stringify(XYXXY), stringify_value(XYXXY)); | |
396 | */ | |
397 | #define stringify_value(s) stringify(s) | |
398 | #define stringify(s) #s | |
399 | ||
d763c230 SK |
400 | /* |
401 | * UL_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time | |
402 | * instrumentation shipped with Clang and GCC) to not instrument the | |
403 | * annotated function. Furthermore, it will prevent the compiler from | |
404 | * inlining the function because inlining currently breaks the blacklisting | |
405 | * mechanism of AddressSanitizer. | |
406 | */ | |
34b0a305 KZ |
407 | #if __has_feature(address_sanitizer) && __has_attribute(no_sanitize_memory) && __has_attribute(no_sanitize_address) |
408 | # define UL_ASAN_BLACKLIST __attribute__((noinline)) __attribute__((no_sanitize_memory)) __attribute__((no_sanitize_address)) | |
d763c230 SK |
409 | #else |
410 | # define UL_ASAN_BLACKLIST /* nothing */ | |
411 | #endif | |
412 | ||
f7ac9e71 KZ |
413 | /* |
414 | * Note that sysconf(_SC_GETPW_R_SIZE_MAX) returns *initial* suggested size for | |
415 | * pwd buffer and in some cases it is not large enough. See POSIX and | |
416 | * getpwnam_r man page for more details. | |
417 | */ | |
418 | #define UL_GETPW_BUFSIZ (16 * 1024) | |
419 | ||
40733239 RM |
420 | /* |
421 | * Darwin or other BSDs may only have MAP_ANON. To get it on Darwin we must | |
422 | * define _DARWIN_C_SOURCE before including sys/mman.h. We do this in config.h. | |
423 | */ | |
424 | #if !defined MAP_ANONYMOUS && defined MAP_ANON | |
425 | # define MAP_ANONYMOUS (MAP_ANON) | |
426 | #endif | |
427 | ||
4d0dbb8b | 428 | #endif /* UTIL_LINUX_C_H */ |