From: Lennart Poettering Date: Fri, 22 Oct 2021 22:28:24 +0000 (+0200) Subject: dirent-util: add FOREACH macro for iterating through getdents64() buffers X-Git-Tag: v250-rc1~426^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a4e70ef7ba3b5e2c050cce5ed2bbf58807505596;p=thirdparty%2Fsystemd.git 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) --- diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h index 73e78102a59..768cc1de61e 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 adc855955a6..dbada824315 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 93b00f0d974..779c91e9052 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);