]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/recurse-dir: modernize readdir_all()
authorMike Yuan <me@yhndnzj.com>
Mon, 16 Dec 2024 15:41:58 +0000 (16:41 +0100)
committerMike Yuan <me@yhndnzj.com>
Mon, 30 Dec 2024 22:52:19 +0000 (23:52 +0100)
src/basic/recurse-dir.c
src/basic/recurse-dir.h

index 378fd92b06175a1f16973de12135d30b5a23539e..389a784c4059153ee9c0fe3c7101a3f3054c50a9 100644 (file)
@@ -26,14 +26,9 @@ static bool ignore_dirent(const struct dirent *de, RecurseDirFlags flags) {
                 dot_or_dot_dot(de->d_name);
 }
 
-int readdir_all(int dir_fd,
-                RecurseDirFlags flags,
-                DirectoryEntries **ret) {
-
+int readdir_all(int dir_fd, RecurseDirFlags flags, DirectoryEntries **ret) {
         _cleanup_free_ DirectoryEntries *de = NULL;
-        struct dirent *entry;
         DirectoryEntries *nde;
-        size_t add, sz, j;
         int r;
 
         assert(dir_fd >= 0);
@@ -77,11 +72,11 @@ int readdir_all(int dir_fd,
                 nde = realloc(de, bs);
                 if (!nde)
                         return -ENOMEM;
-
                 de = nde;
         }
 
         de->n_entries = 0;
+        struct dirent *entry;
         FOREACH_DIRENT_IN_BUFFER(entry, de->buffer, de->buffer_size) {
                 if (ignore_dirent(entry, flags))
                         continue;
@@ -98,16 +93,17 @@ int readdir_all(int dir_fd,
                 de->n_entries++;
         }
 
+        size_t sz, j;
+
         sz = ALIGN(offsetof(DirectoryEntries, buffer) + de->buffer_size);
-        add = sizeof(struct dirent*) * de->n_entries;
-        if (add > SIZE_MAX - add)
+        if (!INC_SAFE(&sz, sizeof(struct dirent*) * de->n_entries))
                 return -ENOMEM;
 
-        nde = realloc(de, sz + add);
+        nde = realloc(de, sz);
         if (!nde)
                 return -ENOMEM;
-
         de = nde;
+
         de->entries = (struct dirent**) ((uint8_t*) de + ALIGN(offsetof(DirectoryEntries, buffer) + de->buffer_size));
 
         j = 0;
index aaeae950fe5a87d03af4c376581c6cc56809bf80..f1b740ff838620f8c6c807d0ccebb40e50144732 100644 (file)
@@ -8,6 +8,28 @@
 #include "stat-util.h"
 #include "macro.h"
 
+typedef enum RecurseDirFlags {
+        /* Interpreted by readdir_all() */
+        RECURSE_DIR_SORT         = 1 << 0,  /* sort file directory entries before processing them */
+        RECURSE_DIR_IGNORE_DOT   = 1 << 1,  /* ignore all dot files ("." and ".." are always ignored) */
+        RECURSE_DIR_ENSURE_TYPE  = 1 << 2,  /* guarantees that 'd_type' field of 'de' is not DT_UNKNOWN */
+
+        /* Interpreted by recurse_dir() */
+        RECURSE_DIR_SAME_MOUNT   = 1 << 3,  /* skips over subdirectories that are submounts */
+        RECURSE_DIR_INODE_FD     = 1 << 4,  /* passes an opened inode fd (O_DIRECTORY fd in case of dirs, O_PATH otherwise) */
+        RECURSE_DIR_TOPLEVEL     = 1 << 5,  /* call RECURSE_DIR_ENTER/RECURSE_DIR_LEAVE once for top-level dir, too, with dir_fd=-1 and NULL dirent */
+} RecurseDirFlags;
+
+typedef struct DirectoryEntries {
+        size_t n_entries;
+        struct dirent **entries;
+        size_t buffer_size;
+        struct dirent buffer[];
+} DirectoryEntries;
+
+int readdir_all(int dir_fd, RecurseDirFlags flags, DirectoryEntries **ret);
+int readdir_all_at(int fd, const char *path, RecurseDirFlags flags, DirectoryEntries **ret);
+
 typedef enum RecurseDirEvent {
         RECURSE_DIR_ENTER,      /* only for dir inodes */
         RECURSE_DIR_LEAVE,      /* only for dir inodes */
@@ -56,27 +78,5 @@ typedef int (*recurse_dir_func_t)(
                 const struct statx *sx,  /* statx data (only if statx_mask was non-zero) */
                 void *userdata);
 
-typedef enum RecurseDirFlags {
-        /* Interpreted by readdir_all() */
-        RECURSE_DIR_SORT         = 1 << 0,  /* sort file directory entries before processing them */
-        RECURSE_DIR_IGNORE_DOT   = 1 << 1,  /* ignore all dot files ("." and ".." are always ignored) */
-        RECURSE_DIR_ENSURE_TYPE  = 1 << 2,  /* guarantees that 'd_type' field of 'de' is not DT_UNKNOWN */
-
-        /* Interpreted by recurse_dir() */
-        RECURSE_DIR_SAME_MOUNT   = 1 << 3,  /* skips over subdirectories that are submounts */
-        RECURSE_DIR_INODE_FD     = 1 << 4,  /* passes an opened inode fd (O_DIRECTORY fd in case of dirs, O_PATH otherwise) */
-        RECURSE_DIR_TOPLEVEL     = 1 << 5,  /* call RECURSE_DIR_ENTER/RECURSE_DIR_LEAVE once for top-level dir, too, with dir_fd=-1 and NULL dirent */
-} RecurseDirFlags;
-
-typedef struct DirectoryEntries {
-        size_t n_entries;
-        struct dirent** entries;
-        size_t buffer_size;
-        struct dirent buffer[];
-} DirectoryEntries;
-
-int readdir_all(int dir_fd, RecurseDirFlags flags, DirectoryEntries **ret);
-int readdir_all_at(int fd, const char *path, RecurseDirFlags flags, DirectoryEntries **ret);
-
 int recurse_dir(int dir_fd, const char *path, unsigned statx_mask, unsigned n_depth_max, RecurseDirFlags flags, recurse_dir_func_t func, void *userdata);
 int recurse_dir_at(int atfd, const char *path, unsigned statx_mask, unsigned n_depth_max, RecurseDirFlags flags, recurse_dir_func_t func, void *userdata);