From a4e70ef7ba3b5e2c050cce5ed2bbf58807505596 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 23 Oct 2021 00:28:24 +0200 Subject: [PATCH] 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) --- src/basic/dirent-util.h | 5 +++++ src/basic/recurse-dir.c | 13 ++++--------- src/basic/recurse-dir.h | 2 +- 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);