]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dirent-util: add FOREACH macro for iterating through getdents64() buffers
authorLennart Poettering <lennart@poettering.net>
Fri, 22 Oct 2021 22:28:24 +0000 (00:28 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 25 Oct 2021 19:51:37 +0000 (21:51 +0200)
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
src/basic/recurse-dir.c
src/basic/recurse-dir.h

index 73e78102a595ef69ef047035a7d9c5079acf6f09..768cc1de61e1ffd9c9b95748bdb889c7bb109f65 100644 (file)
@@ -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))
index adc855955a6e3263991a24d35c05a803d6167b04..dbada8243150b9d01b8e055ae5ae109336451e05 100644 (file)
@@ -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;
 
index 93b00f0d974323f6995aa2df928afd024508e612..779c91e90522bc266ded51a82db9adc848387397 100644 (file)
@@ -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);