mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
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)
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user