]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/dirent-util.h
hexdecoct: make unbase64mem and unhexmem always use SIZE_MAX
[thirdparty/systemd.git] / src / basic / dirent-util.h
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
a0956174
LP
2#pragma once
3
a0956174 4#include <dirent.h>
11c3a366
TA
5#include <errno.h>
6#include <stdbool.h>
a0956174 7
11c3a366 8#include "macro.h"
93cc7779 9#include "path-util.h"
a0956174 10
a0956174
LP
11bool dirent_is_file(const struct dirent *de) _pure_;
12bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
06da125e 13int dirent_ensure_type(int dir_fd, struct dirent *de);
a0956174 14
98f7a4c8
YW
15struct dirent *readdir_ensure_type(DIR *d);
16struct dirent *readdir_no_dot(DIR *dirp);
48d7c648 17
a0956174 18#define FOREACH_DIRENT_ALL(de, d, on_error) \
c7f0d9e5 19 for (struct dirent *(de) = readdir_ensure_type(d);; (de) = readdir_ensure_type(d)) \
a0956174
LP
20 if (!de) { \
21 if (errno > 0) { \
22 on_error; \
23 } \
24 break; \
25 } else
ca664db2 26
af3b864d
ZJS
27#define FOREACH_DIRENT(de, d, on_error) \
28 FOREACH_DIRENT_ALL(de, d, on_error) \
29 if (hidden_or_backup_file((de)->d_name)) \
30 continue; \
31 else
32
ca664db2
LP
33/* Maximum space one dirent structure might require at most */
34#define DIRENT_SIZE_MAX CONST_MAX(sizeof(struct dirent), offsetof(struct dirent, d_name) + NAME_MAX + 1)
35
da890466 36/* Only if 64-bit off_t is enabled struct dirent + struct dirent64 are actually the same. We require this, and
ca664db2
LP
37 * we want them to be interchangeable to make getdents64() work, hence verify that. */
38assert_cc(_FILE_OFFSET_BITS == 64);
0b4e0943
SJ
39/* These asserts would fail on musl where the LFS extensions don't exist. They should
40 * always be present on glibc however. */
eb292969 41#if HAVE_STRUCT_DIRENT64
ca664db2
LP
42assert_cc(sizeof(struct dirent) == sizeof(struct dirent64));
43assert_cc(offsetof(struct dirent, d_ino) == offsetof(struct dirent64, d_ino));
44assert_cc(sizeof_field(struct dirent, d_ino) == sizeof_field(struct dirent64, d_ino));
45assert_cc(offsetof(struct dirent, d_off) == offsetof(struct dirent64, d_off));
46assert_cc(sizeof_field(struct dirent, d_off) == sizeof_field(struct dirent64, d_off));
47assert_cc(offsetof(struct dirent, d_reclen) == offsetof(struct dirent64, d_reclen));
48assert_cc(sizeof_field(struct dirent, d_reclen) == sizeof_field(struct dirent64, d_reclen));
49assert_cc(offsetof(struct dirent, d_type) == offsetof(struct dirent64, d_type));
50assert_cc(sizeof_field(struct dirent, d_type) == sizeof_field(struct dirent64, d_type));
51assert_cc(offsetof(struct dirent, d_name) == offsetof(struct dirent64, d_name));
52assert_cc(sizeof_field(struct dirent, d_name) == sizeof_field(struct dirent64, d_name));
eb292969 53#endif
a4e70ef7
LP
54
55#define FOREACH_DIRENT_IN_BUFFER(de, buf, sz) \
56 for (void *_end = (uint8_t*) ({ (de) = (buf); }) + (sz); \
57 (uint8_t*) (de) < (uint8_t*) _end; \
58 (de) = (struct dirent*) ((uint8_t*) (de) + (de)->d_reclen))
a068acea
LP
59
60#define DEFINE_DIRENT_BUFFER(name, sz) \
61 union { \
62 struct dirent de; \
63 uint8_t data[(sz) * DIRENT_SIZE_MAX]; \
64 } name