]>
Commit | Line | Data |
---|---|---|
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 |
11 | bool dirent_is_file(const struct dirent *de) _pure_; |
12 | bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; | |
06da125e | 13 | int dirent_ensure_type(int dir_fd, struct dirent *de); |
a0956174 | 14 | |
98f7a4c8 YW |
15 | struct dirent *readdir_ensure_type(DIR *d); |
16 | struct 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. */ |
38 | assert_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 |
42 | assert_cc(sizeof(struct dirent) == sizeof(struct dirent64)); |
43 | assert_cc(offsetof(struct dirent, d_ino) == offsetof(struct dirent64, d_ino)); | |
44 | assert_cc(sizeof_field(struct dirent, d_ino) == sizeof_field(struct dirent64, d_ino)); | |
45 | assert_cc(offsetof(struct dirent, d_off) == offsetof(struct dirent64, d_off)); | |
46 | assert_cc(sizeof_field(struct dirent, d_off) == sizeof_field(struct dirent64, d_off)); | |
47 | assert_cc(offsetof(struct dirent, d_reclen) == offsetof(struct dirent64, d_reclen)); | |
48 | assert_cc(sizeof_field(struct dirent, d_reclen) == sizeof_field(struct dirent64, d_reclen)); | |
49 | assert_cc(offsetof(struct dirent, d_type) == offsetof(struct dirent64, d_type)); | |
50 | assert_cc(sizeof_field(struct dirent, d_type) == sizeof_field(struct dirent64, d_type)); | |
51 | assert_cc(offsetof(struct dirent, d_name) == offsetof(struct dirent64, d_name)); | |
52 | assert_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 |