summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2022-11-24 13:13:21 +0100
committerDaan De Meyer <daan.j.demeyer@gmail.com>2022-11-24 14:02:19 +0100
commita0a4c57818ac9137e7fe2903b6f2a032fca9292e (patch)
tree602b418609fddbe2eb880f675449285cdc4f5b11 /src
parent06da125ea19284a5200e206e704a37c17dbbab5e (diff)
downloadsystemd-a0a4c57818ac9137e7fe2903b6f2a032fca9292e.tar.gz
recurse-dir: Handle RECURSE_DIR_ENSURE_TYPE in readdir_all()
Diffstat (limited to 'src')
-rw-r--r--src/basic/recurse-dir.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/basic/recurse-dir.c b/src/basic/recurse-dir.c
index 908e833501..fe18b98d5b 100644
--- a/src/basic/recurse-dir.c
+++ b/src/basic/recurse-dir.c
@@ -33,6 +33,7 @@ int readdir_all(int dir_fd,
struct dirent *entry;
DirectoryEntries *nde;
size_t add, sz, j;
+ int r;
assert(dir_fd >= 0);
@@ -84,6 +85,15 @@ int readdir_all(int dir_fd,
if (ignore_dirent(entry, flags))
continue;
+ if (FLAGS_SET(flags, RECURSE_DIR_ENSURE_TYPE)) {
+ r = dirent_ensure_type(dir_fd, entry);
+ if (r == -ENOENT)
+ /* dentry gone by now? no problem, let's just suppress it */
+ continue;
+ if (r < 0)
+ return r;
+ }
+
de->n_entries++;
}
@@ -104,8 +114,14 @@ int readdir_all(int dir_fd,
if (ignore_dirent(entry, flags))
continue;
+ /* If d_type == DT_UNKNOWN that means we failed to ensure the type in the earlier loop and
+ * didn't include the dentry in de->n_entries and as such should skip it here as well. */
+ if (FLAGS_SET(flags, RECURSE_DIR_ENSURE_TYPE) && entry->d_type == DT_UNKNOWN)
+ continue;
+
de->entries[j++] = entry;
}
+ assert(j == de->n_entries);
if (FLAGS_SET(flags, RECURSE_DIR_SORT))
typesafe_qsort(de->entries, de->n_entries, sort_func);
@@ -160,7 +176,8 @@ int recurse_dir(
return r;
}
- r = readdir_all(dir_fd, flags, &de);
+ /* Mask out RECURSE_DIR_ENSURE_TYPE so we can do it ourselves and avoid an extra statx() call. */
+ r = readdir_all(dir_fd, flags & ~RECURSE_DIR_ENSURE_TYPE, &de);
if (r < 0)
return r;