From: Mike Yuan Date: Mon, 16 Dec 2024 15:41:58 +0000 (+0100) Subject: basic/recurse-dir: modernize readdir_all() X-Git-Tag: v258-rc1~1752^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=90761f7f68f6fce3f4d8673ad6c7d435a90052c7;p=thirdparty%2Fsystemd.git basic/recurse-dir: modernize readdir_all() --- diff --git a/src/basic/recurse-dir.c b/src/basic/recurse-dir.c index 378fd92b061..389a784c405 100644 --- a/src/basic/recurse-dir.c +++ b/src/basic/recurse-dir.c @@ -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; diff --git a/src/basic/recurse-dir.h b/src/basic/recurse-dir.h index aaeae950fe5..f1b740ff838 100644 --- a/src/basic/recurse-dir.h +++ b/src/basic/recurse-dir.h @@ -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);