summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-10-23 00:28:24 +0200
committerLennart Poettering <lennart@poettering.net>2021-10-25 21:51:37 +0200
commita4e70ef7ba3b5e2c050cce5ed2bbf58807505596 (patch)
treef48de09715f7a30cf786a9b7a3b4c5e9e555bba9
parentca664db25860d7fcd581380e24ad74f510c1f40f (diff)
downloadsystemd-a4e70ef7ba3b5e2c050cce5ed2bbf58807505596.tar.gz
dirent-util: add FOREACH macro for iterating through getdents64() buffers
We already have a similar loop twice, let's make it easier to read via an iteration macro. (The new macro is a bit more careful even, as it verifies the full dirent fits into the remaining buffer when returning it)
-rw-r--r--src/basic/dirent-util.h5
-rw-r--r--src/basic/recurse-dir.c13
-rw-r--r--src/basic/recurse-dir.h2
3 files changed, 10 insertions, 10 deletions
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
index 73e78102a5..768cc1de61 100644
--- a/src/basic/dirent-util.h
+++ b/src/basic/dirent-util.h
@@ -51,3 +51,8 @@ assert_cc(offsetof(struct dirent, d_type) == offsetof(struct dirent64, d_type));
assert_cc(sizeof_field(struct dirent, d_type) == sizeof_field(struct dirent64, d_type));
assert_cc(offsetof(struct dirent, d_name) == offsetof(struct dirent64, d_name));
assert_cc(sizeof_field(struct dirent, d_name) == sizeof_field(struct dirent64, d_name));
+
+#define FOREACH_DIRENT_IN_BUFFER(de, buf, sz) \
+ for (void *_end = (uint8_t*) ({ (de) = (buf); }) + (sz); \
+ (uint8_t*) (de) < (uint8_t*) _end; \
+ (de) = (struct dirent*) ((uint8_t*) (de) + (de)->d_reclen))
diff --git a/src/basic/recurse-dir.c b/src/basic/recurse-dir.c
index adc855955a..dbada82431 100644
--- a/src/basic/recurse-dir.c
+++ b/src/basic/recurse-dir.c
@@ -30,6 +30,7 @@ int readdir_all(int dir_fd,
DirectoryEntries **ret) {
_cleanup_free_ DirectoryEntries *de = NULL;
+ struct dirent *entry;
DirectoryEntries *nde;
size_t add, sz, j;
@@ -53,7 +54,7 @@ int readdir_all(int dir_fd,
bs = MIN(MALLOC_SIZEOF_SAFE(de) - offsetof(DirectoryEntries, buffer), (size_t) SSIZE_MAX);
assert(bs > de->buffer_size);
- n = getdents64(dir_fd, de->buffer + de->buffer_size, bs - de->buffer_size);
+ n = getdents64(dir_fd, (uint8_t*) de->buffer + de->buffer_size, bs - de->buffer_size);
if (n < 0)
return -errno;
if (n == 0)
@@ -77,10 +78,7 @@ int readdir_all(int dir_fd,
}
de->n_entries = 0;
- for (struct dirent *entry = (struct dirent*) de->buffer;
- (uint8_t*) entry < de->buffer + de->buffer_size;
- entry = (struct dirent*) ((uint8_t*) entry + entry->d_reclen)) {
-
+ FOREACH_DIRENT_IN_BUFFER(entry, de->buffer, de->buffer_size) {
if (ignore_dirent(entry, flags))
continue;
@@ -100,10 +98,7 @@ int readdir_all(int dir_fd,
de->entries = (struct dirent**) ((uint8_t*) de + ALIGN(offsetof(DirectoryEntries, buffer) + de->buffer_size));
j = 0;
- for (struct dirent *entry = (struct dirent*) de->buffer;
- (uint8_t*) entry < de->buffer + de->buffer_size;
- entry = (struct dirent*) ((uint8_t*) entry + entry->d_reclen)) {
-
+ FOREACH_DIRENT_IN_BUFFER(entry, de->buffer, de->buffer_size) {
if (ignore_dirent(entry, flags))
continue;
diff --git a/src/basic/recurse-dir.h b/src/basic/recurse-dir.h
index 93b00f0d97..779c91e905 100644
--- a/src/basic/recurse-dir.h
+++ b/src/basic/recurse-dir.h
@@ -71,7 +71,7 @@ typedef struct DirectoryEntries {
size_t n_entries;
struct dirent** entries;
size_t buffer_size;
- uint8_t buffer[] _alignas_(struct dirent);
+ struct dirent buffer[];
} DirectoryEntries;
int readdir_all(int dir_fd, RecurseDirFlags flags, DirectoryEntries **ret);