]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/util.h
util-lib: introduce dirent-util.[ch] for directory entry calls
[thirdparty/systemd.git] / src / basic / util.h
CommitLineData
03467c88 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
c2f1db8f 3#pragma once
60918275 4
a7334b09
LP
5/***
6 This file is part of systemd.
7
8 Copyright 2010 Lennart Poettering
9
10 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 18 Lesser General Public License for more details.
a7334b09 19
5430f7f2 20 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22***/
23
31885cd5 24#include <alloca.h>
370c860f 25#include <fcntl.h>
60918275 26#include <inttypes.h>
f6c2284a
LP
27#include <limits.h>
28#include <locale.h>
ec2002f8 29#include <stdarg.h>
60918275 30#include <stdbool.h>
f6c2284a 31#include <stddef.h>
80876c20 32#include <stdio.h>
f6c2284a
LP
33#include <stdlib.h>
34#include <sys/inotify.h>
2c35d880 35#include <sys/socket.h>
00dc5d76 36#include <sys/stat.h>
c6878637 37#include <sys/statfs.h>
f6c2284a
LP
38#include <sys/types.h>
39#include <time.h>
40#include <unistd.h>
60918275 41
f6c2284a 42#include "formats-util.h"
a838e6a1 43#include "macro.h"
dced1557 44#include "missing.h"
9a98c7a1 45#include "time-util.h"
871d7de4 46
44d8db9e 47/* What is interpreted as whitespace? */
4a72ff34 48#define WHITESPACE " \t\n\r"
e3e0314b
ZJS
49#define NEWLINE "\n\r"
50#define QUOTES "\"\'"
51#define COMMENTS "#;"
52#define GLOB_CHARS "*?["
44d8db9e 53
2e857429 54size_t page_size(void) _pure_;
37f85e66 55#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
56
4b8772bf 57#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
60918275
LP
58
59#define new0(t, n) ((t*) calloc((n), sizeof(t)))
60
0f0dbc46
LP
61#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
62
7629889c
LP
63#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
64
4b8772bf 65#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
888c7102 66
f80bb1f7 67#define malloc0(n) (calloc(1, (n)))
60918275 68
97b11eed
DH
69static inline void *mfree(void *memory) {
70 free(memory);
71 return NULL;
72}
73
60918275
LP
74static inline const char* yes_no(bool b) {
75 return b ? "yes" : "no";
76}
77
5232c42e
LS
78static inline const char* true_false(bool b) {
79 return b ? "true" : "false";
80}
81
769d324c
LP
82static inline const char* one_zero(bool b) {
83 return b ? "1" : "0";
84}
85
849958d1 86int readlinkat_malloc(int fd, const char *p, char **ret);
87f0e418 87int readlink_malloc(const char *p, char **r);
9a67bcf2 88int readlink_value(const char *p, char **ret);
2c7108c4 89int readlink_and_make_absolute(const char *p, char **r);
83096483 90int readlink_and_canonicalize(const char *p, char **r);
87f0e418 91
c32dd69b
LP
92int rmdir_parents(const char *path, const char *stop);
93
f8b69d1d 94/* For basic lookup tables with strictly enumerated entries */
b9a5f858 95#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
4e240ab0 96 scope const char *name##_to_string(type i) { \
1dccbe19
LP
97 if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \
98 return NULL; \
99 return name##_table[i]; \
b9a5f858
LP
100 }
101
9cad100e
BB
102ssize_t string_table_lookup(const char * const *table, size_t len, const char *key);
103
8c721f2b
LP
104#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
105 scope type name##_from_string(const char *s) { \
106 return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
b9a5f858
LP
107 }
108
109#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
110 _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
111 _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
1dccbe19
LP
112 struct __useless_struct_to_allow_trailing_semicolon__
113
b9a5f858
LP
114#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
115#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
116#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
117#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
1dccbe19 118
f8b69d1d
MS
119/* For string conversions where numbers are also acceptable */
120#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
121 int name##_to_string_alloc(type i, char **str) { \
122 char *s; \
f8b69d1d
MS
123 if (i < 0 || i > max) \
124 return -ERANGE; \
125 if (i < (type) ELEMENTSOF(name##_table)) { \
126 s = strdup(name##_table[i]); \
127 if (!s) \
8c721f2b 128 return -ENOMEM; \
f8b69d1d 129 } else { \
8c721f2b
LP
130 if (asprintf(&s, "%i", i) < 0) \
131 return -ENOMEM; \
f8b69d1d
MS
132 } \
133 *str = s; \
134 return 0; \
135 } \
136 type name##_from_string(const char *s) { \
137 type i; \
138 unsigned u = 0; \
8c721f2b
LP
139 if (!s) \
140 return (type) -1; \
141 for (i = 0; i < (type) ELEMENTSOF(name##_table); i++) \
142 if (streq_ptr(name##_table[i], s)) \
f8b69d1d 143 return i; \
8511dd18 144 if (safe_atou(s, &u) >= 0 && u <= max) \
f8b69d1d
MS
145 return (type) u; \
146 return (type) -1; \
147 } \
148 struct __useless_struct_to_allow_trailing_semicolon__
149
42856c10
LP
150bool fstype_is_network(const char *fstype);
151
01f78473
LP
152int dir_is_empty(const char *path);
153
ac7edd91
LP
154static inline int dir_is_populated(const char *path) {
155 int r;
156 r = dir_is_empty(path);
157 if (r < 0)
158 return r;
159 return !r;
160}
161
8c6db833 162int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
f4b47811 163int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
8c6db833 164
d1678248
ILG
165typedef long statfs_f_type_t;
166
167bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
168int fd_check_fstype(int fd, statfs_f_type_t magic_value);
169int path_check_fstype(const char *path, statfs_f_type_t magic_value);
170
c6878637
LP
171bool is_temporary_fs(const struct statfs *s) _pure_;
172int fd_is_temporary_fs(int fd);
ef2f1067 173
a8b62610
MS
174#define xsprintf(buf, fmt, ...) \
175 assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), \
176 "xsprintf: " #buf "[] must be big enough")
5ffa8c81 177
9d9951a4
HH
178int files_same(const char *filea, const char *fileb);
179
b4f10a5e
LP
180int running_in_chroot(void);
181
c38dfac9 182int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
f6144808
LP
183int touch(const char *path);
184
919ce0b7 185noreturn void freeze(void);
3c14d26c 186
44a6b1b6 187bool null_or_empty(struct stat *st) _pure_;
83096483 188int null_or_empty_path(const char *fn);
ed88bcfb 189int null_or_empty_fd(int fd);
00dc5d76 190
e801700e 191void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
83cc030f 192
a88c8750
TG
193bool plymouth_running(void);
194
875e1014 195int symlink_idempotent(const char *from, const char *to);
6ea832a2 196
424a19f8 197int symlink_atomic(const char *from, const char *to);
1554afae
LP
198int mknod_atomic(const char *path, mode_t mode, dev_t dev);
199int mkfifo_atomic(const char *path, mode_t mode);
34ca941c
LP
200
201int fchmod_umask(int fd, mode_t mode);
202
44a6b1b6 203bool display_is_local(const char *display) _pure_;
4d6d6518
LP
204int socket_from_display(const char *display, char **path);
205
8092a428 206int glob_exists(const char *path);
8d98da3f 207int glob_extend(char ***strv, const char *path);
8092a428 208
034a2a52 209int get_files_in_directory(const char *path, char ***list);
83096483 210
b636465b
LP
211bool is_main_thread(void);
212
94959f0f
LP
213int block_get_whole_disk(dev_t d, dev_t *ret);
214
e23a0ce8 215#define NULSTR_FOREACH(i, l) \
c4e2ceae
LP
216 for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
217
5c0532d1
LP
218#define NULSTR_FOREACH_PAIR(i, j, l) \
219 for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i))
220
f8b69d1d 221int ioprio_class_to_string_alloc(int i, char **s);
1dccbe19
LP
222int ioprio_class_from_string(const char *s);
223
44a6b1b6
ZJS
224const char *sigchld_code_to_string(int i) _const_;
225int sigchld_code_from_string(const char *s) _pure_;
1dccbe19 226
f8b69d1d 227int log_facility_unshifted_to_string_alloc(int i, char **s);
7d76f312 228int log_facility_unshifted_from_string(const char *s);
adb8ec96 229bool log_facility_unshifted_is_valid(int faciliy);
1dccbe19 230
f8b69d1d 231int log_level_to_string_alloc(int i, char **s);
1dccbe19 232int log_level_from_string(const char *s);
adb8ec96 233bool log_level_is_valid(int level);
1dccbe19 234
f8b69d1d 235int sched_policy_to_string_alloc(int i, char **s);
1dccbe19
LP
236int sched_policy_from_string(const char *s);
237
9a0e6896
LP
238extern int saved_argc;
239extern char **saved_argv;
240
65457142
FC
241bool kexec_loaded(void);
242
44a6b1b6 243int prot_from_flags(int flags) _const_;
87d2c1ff 244
750ef272 245void* memdup(const void *p, size_t l) _alloc_(2);
55d7bfc1 246
9bdc770c 247int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
6bb92a16 248
a2e03378
LP
249bool http_url_is_valid(const char *url) _pure_;
250bool documentation_url_is_valid(const char *url) _pure_;
49dbfa7b 251
3d7415f4
LP
252bool http_etag_is_valid(const char *etag);
253
9be346c9 254bool in_initrd(void);
069cfc85 255
a740c14c
MS
256static inline void freep(void *p) {
257 free(*(void**) p);
258}
259
dfb33a97
LP
260static inline void umaskp(mode_t *u) {
261 umask(*u);
763c7aa2
ZJS
262}
263
dfb33a97 264#define _cleanup_free_ _cleanup_(freep)
dfb33a97
LP
265#define _cleanup_umask_ _cleanup_(umaskp)
266#define _cleanup_globfree_ _cleanup_(globfree)
c84a9488 267
750ef272 268_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
368504f4 269 if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
4b8772bf
LP
270 return NULL;
271
272 return malloc(a * b);
273}
274
9489490a
DH
275_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
276 if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
277 return NULL;
278
279 return realloc(p, a * b);
280}
281
750ef272 282_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
368504f4 283 if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
4b8772bf
LP
284 return NULL;
285
286 return memdup(p, a * b);
287}
0b507b17 288
44a6b1b6 289bool string_is_safe(const char *p) _pure_;
cfbc22ab 290
e3e0314b
ZJS
291/**
292 * Check if a string contains any glob patterns.
293 */
294_pure_ static inline bool string_is_glob(const char *p) {
295 return !!strpbrk(p, GLOB_CHARS);
296}
297
a9e12476
KS
298void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
299 int (*compar) (const void *, const void *, void *),
300 void *arg);
09017585 301
20f56fdd 302#define _(String) gettext (String)
88ced61b 303#define N_(String) String
20f56fdd 304void init_gettext(void);
09017585 305bool is_locale_utf8(void);
c339d977
MS
306
307typedef enum DrawSpecialChar {
6b01f1d3 308 DRAW_TREE_VERTICAL,
45a5ff0d
MS
309 DRAW_TREE_BRANCH,
310 DRAW_TREE_RIGHT,
55c0b89c 311 DRAW_TREE_SPACE,
c339d977 312 DRAW_TRIANGULAR_BULLET,
3deadb91 313 DRAW_BLACK_CIRCLE,
6b01f1d3 314 DRAW_ARROW,
13f8b8cb 315 DRAW_DASH,
c339d977
MS
316 _DRAW_SPECIAL_CHAR_MAX
317} DrawSpecialChar;
6b01f1d3 318
c339d977 319const char *draw_special_char(DrawSpecialChar ch);
409bc9c3 320
240dbaa4 321int on_ac_power(void);
f74e605f 322
6282c859
MS
323static inline void *mempset(void *s, int c, size_t n) {
324 memset(s, c, n);
dfb33a97 325 return (uint8_t*)s + n;
6282c859 326}
66e35261 327
ca2d3784
ZJS
328void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
329void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
330#define GREEDY_REALLOC(array, allocated, need) \
331 greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
332
333#define GREEDY_REALLOC0(array, allocated, need) \
334 greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
a1937e67 335
5c0d398d 336static inline void _reset_errno_(int *saved_errno) {
5c0aa72a
LP
337 errno = *saved_errno;
338}
339
2a371001 340#define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno
5c0d398d 341
44dd2c6e
DH
342static inline int negative_errno(void) {
343 /* This helper should be used to shut up gcc if you know 'errno' is
344 * negative. Instead of "return -errno;", use "return negative_errno();"
345 * It will suppress bogus gcc warnings in case it assumes 'errno' might
346 * be 0 and thus the caller's error-handling might not be triggered. */
347 assert_return(errno > 0, -EINVAL);
348 return -errno;
349}
350
d6dd604b 351struct _umask_struct_ {
5c0d398d
LP
352 mode_t mask;
353 bool quit;
354};
355
d6dd604b 356static inline void _reset_umask_(struct _umask_struct_ *s) {
5c0d398d
LP
357 umask(s->mask);
358};
359
360#define RUN_WITH_UMASK(mask) \
d6dd604b 361 for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
5c0d398d
LP
362 !_saved_umask_.quit ; \
363 _saved_umask_.quit = true)
144e51ec
CR
364
365static inline unsigned u64log2(uint64_t n) {
ec417ccc 366#if __SIZEOF_LONG_LONG__ == 8
693eb9a2 367 return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0;
ec417ccc
LP
368#else
369#error "Wut?"
370#endif
371}
372
373static inline unsigned u32ctz(uint32_t n) {
374#if __SIZEOF_INT__ == 4
375 return __builtin_ctz(n);
376#else
377#error "Wut?"
378#endif
144e51ec 379}
79d860fe 380
7d328b54 381static inline unsigned log2i(int x) {
8fe90522
ZJS
382 assert(x > 0);
383
384 return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1;
385}
386
b5de6d98
MS
387static inline unsigned log2u(unsigned x) {
388 assert(x > 0);
389
390 return sizeof(unsigned) * 8 - __builtin_clz(x) - 1;
391}
392
393static inline unsigned log2u_round_up(unsigned x) {
394 assert(x > 0);
395
396 if (x == 1)
397 return 0;
398
399 return log2u(x - 1) + 1;
400}
401
82da66fb
LP
402#define DECIMAL_STR_WIDTH(x) \
403 ({ \
404 typeof(x) _x_ = (x); \
405 unsigned ans = 1; \
406 while (_x_ /= 10) \
407 ans++; \
408 ans; \
409 })
75add28a 410
4b73a0c0 411int unlink_noerrno(const char *path);
ed5c5dbd 412
82da66fb
LP
413#define alloca0(n) \
414 ({ \
415 char *_new_; \
416 size_t _len_ = n; \
417 _new_ = alloca(_len_); \
418 (void *) memset(_new_, 0, _len_); \
ed5c5dbd 419 })
95d78c7e 420
257224b0 421/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
95d78c7e
DH
422#define alloca_align(size, align) \
423 ({ \
424 void *_ptr_; \
425 size_t _mask_ = (align) - 1; \
426 _ptr_ = alloca((size) + _mask_); \
427 (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
428 })
429
430#define alloca0_align(size, align) \
431 ({ \
432 void *_new_; \
433 size_t _size_ = (size); \
434 _new_ = alloca_align(_size_, (align)); \
435 (void*)memset(_new_, 0, _size_); \
436 })
66060897 437
44a6b1b6 438bool id128_is_valid(const char *s) _pure_;
d4ac85c6 439
74df0fca 440int shall_restore_state(void);
295edddf 441
7ff7394d
ZJS
442/**
443 * Normal qsort requires base to be nonnull. Here were require
444 * that only if nmemb > 0.
445 */
aeb24f30 446static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
1dbd13d8 447 if (nmemb <= 1)
aeb24f30
LP
448 return;
449
450 assert(base);
451 qsort(base, nmemb, size, compar);
7ff7394d 452}
74df0fca
LP
453
454int proc_cmdline(char **ret);
059cb385 455int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value));
1a299299 456int get_proc_cmdline_key(const char *parameter, char **value);
bc9fd78c
LP
457
458int container_get_leader(const char *machine, pid_t *pid);
459
671c3419
RM
460int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
461int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
bf108e55 462
fdb9161c 463int fd_warn_permissions(const char *path, int fd);
6afc95b7 464
050f7277
LP
465#ifndef PERSONALITY_INVALID
466/* personality(7) documents that 0xffffffffUL is used for querying the
467 * current personality, hence let's use that here as error
468 * indicator. */
469#define PERSONALITY_INVALID 0xffffffffLU
470#endif
471
ac45f971
LP
472unsigned long personality_from_string(const char *p);
473const char *personality_to_string(unsigned long);
1c231f56
LP
474
475uint64_t physical_memory(void);
6db615c1 476
370c860f 477union file_handle_union {
c5220a94
MO
478 struct file_handle handle;
479 char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
370c860f 480};
2695c5c4 481#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
c5220a94
MO
482
483int update_reboot_param_file(const char *param);
6d313367 484
7629889c 485int is_symlink(const char *path);
be57e297 486int is_dir(const char *path, bool follow);
ce5b3ad4 487int is_device_node(const char *path);
7629889c 488
f7c1ad4f
LP
489#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
490
491#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
0254e944
SL
492 for ((e) = &buffer.ev; \
493 (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \
f7c1ad4f 494 (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len))
72648326 495
0254e944
SL
496union inotify_event_buffer {
497 struct inotify_event ev;
498 uint8_t raw[INOTIFY_EVENT_MAX];
499};
500
72648326 501#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW)
ee451d76 502
10f9c755
LP
503ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags);
504
4a4d89b6
LP
505int fd_setcrtime(int fd, usec_t usec);
506int fd_getcrtime(int fd, usec_t *usec);
507int path_getcrtime(const char *p, usec_t *usec);
10f9c755 508int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags);
a354329f 509
1ed8f8c1
LP
510int chattr_fd(int fd, unsigned value, unsigned mask);
511int chattr_path(const char *p, unsigned value, unsigned mask);
de45d726 512
01b72568
LP
513int read_attr_fd(int fd, unsigned *ret);
514int read_attr_path(const char *p, unsigned *ret);
515
3d7415f4 516int syslog_parse_priority(const char **p, int *priority, bool with_facility);
1c8da044 517
f85ef957 518int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
019c7fba 519
7b9c9ab8
WC
520int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
521int fgetxattr_malloc(int fd, const char *name, char **value);
d9603714 522
3f6fd1ba 523int version(void);
8dd4c05b
LP
524
525bool fdname_is_valid(const char *s);
257b0719
EV
526
527bool oom_score_adjust_is_valid(int oa);