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