1 /* SPDX-License-Identifier: LGPL-2.1-or-later */ 2 #pragma once 3 4 #include <dirent.h> 5 #include <errno.h> 6 #include <stdbool.h> 7 8 #include "macro.h" 9 #include "path-util.h" 10 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_; 13 14 struct dirent *readdir_ensure_type(DIR *d); 15 struct dirent *readdir_no_dot(DIR *dirp); 16 17 #define FOREACH_DIRENT_ALL(de, d, on_error) \ 18 for (struct dirent *(de) = readdir_ensure_type(d);; (de) = readdir_ensure_type(d)) \ 19 if (!de) { \ 20 if (errno > 0) { \ 21 on_error; \ 22 } \ 23 break; \ 24 } else 25 26 #define FOREACH_DIRENT(de, d, on_error) \ 27 FOREACH_DIRENT_ALL(de, d, on_error) \ 28 if (hidden_or_backup_file((de)->d_name)) \ 29 continue; \ 30 else 31 32 /* Maximum space one dirent structure might require at most */ 33 #define DIRENT_SIZE_MAX CONST_MAX(sizeof(struct dirent), offsetof(struct dirent, d_name) + NAME_MAX + 1) 34 35 /* Only if 64bit off_t is enabled struct dirent + struct dirent64 are actually the same. We require this, and 36 * we want them to be interchangeable to make getdents64() work, hence verify that. */ 37 assert_cc(_FILE_OFFSET_BITS == 64); 38 assert_cc(sizeof(struct dirent) == sizeof(struct dirent64)); 39 assert_cc(offsetof(struct dirent, d_ino) == offsetof(struct dirent64, d_ino)); 40 assert_cc(sizeof_field(struct dirent, d_ino) == sizeof_field(struct dirent64, d_ino)); 41 assert_cc(offsetof(struct dirent, d_off) == offsetof(struct dirent64, d_off)); 42 assert_cc(sizeof_field(struct dirent, d_off) == sizeof_field(struct dirent64, d_off)); 43 assert_cc(offsetof(struct dirent, d_reclen) == offsetof(struct dirent64, d_reclen)); 44 assert_cc(sizeof_field(struct dirent, d_reclen) == sizeof_field(struct dirent64, d_reclen)); 45 assert_cc(offsetof(struct dirent, d_type) == offsetof(struct dirent64, d_type)); 46 assert_cc(sizeof_field(struct dirent, d_type) == sizeof_field(struct dirent64, d_type)); 47 assert_cc(offsetof(struct dirent, d_name) == offsetof(struct dirent64, d_name)); 48 assert_cc(sizeof_field(struct dirent, d_name) == sizeof_field(struct dirent64, d_name)); 49 50 #define FOREACH_DIRENT_IN_BUFFER(de, buf, sz) \ 51 for (void *_end = (uint8_t*) ({ (de) = (buf); }) + (sz); \ 52 (uint8_t*) (de) < (uint8_t*) _end; \ 53 (de) = (struct dirent*) ((uint8_t*) (de) + (de)->d_reclen)) 54 55 #define DEFINE_DIRENT_BUFFER(name, sz) \ 56 union { \ 57 struct dirent de; \ 58 uint8_t data[(sz) * DIRENT_SIZE_MAX]; \ 59 } name 60