The iteration order of opendir/readdir depends on filesystem implementation. Hence, even with the same contents, the filesystem of the input directory affects the output.
In this change, opendir/readdir is replaced with scandir for stable order of iteration. This produces the same output regardless of the filesystem of the input directory. Test: mkfs.erofs ... inputdir(ext3) Test: mkfs.erofs ... inputdir(tmpfs) # should generate the same output Signed-off-by: Jooyung Han <jooy...@google.com> --- v1: https://lore.kernel.org/linux-erofs/20241202232620.3604736-1-jooy...@google.com/ change since v1: - modify commit msg (no change-id/bug/typo) - rename the label to err_cleanup lib/inode.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/lib/inode.c b/lib/inode.c index f553bec..097deef 100644 --- a/lib/inode.c +++ b/lib/inode.c @@ -1422,37 +1422,25 @@ static void erofs_mkfs_flushjobs(struct erofs_sb_info *sbi) static int erofs_mkfs_handle_directory(struct erofs_inode *dir) { struct erofs_sb_info *sbi = dir->sbi; - DIR *_dir; - struct dirent *dp; + struct dirent *dp, **dent; + int i, num_entries; struct erofs_dentry *d; unsigned int nr_subdirs, i_nlink; int ret; - _dir = opendir(dir->i_srcpath); - if (!_dir) { - erofs_err("failed to opendir at %s: %s", + num_entries = scandir(dir->i_srcpath, &dent, NULL, alphasort); + if (num_entries == -1) { + erofs_err("failed to scandir at %s: %s", dir->i_srcpath, erofs_strerror(-errno)); return -errno; } nr_subdirs = 0; i_nlink = 0; - while (1) { + for (i = 0; i < num_entries; free(dent[i]), i++) { char buf[PATH_MAX]; struct erofs_inode *inode; - - /* - * set errno to 0 before calling readdir() in order to - * distinguish end of stream and from an error. - */ - errno = 0; - dp = readdir(_dir); - if (!dp) { - if (!errno) - break; - ret = -errno; - goto err_closedir; - } + dp = dent[i]; if (is_dot_dotdot(dp->d_name)) { ++i_nlink; @@ -1466,17 +1454,17 @@ static int erofs_mkfs_handle_directory(struct erofs_inode *dir) d = erofs_d_alloc(dir, dp->d_name); if (IS_ERR(d)) { ret = PTR_ERR(d); - goto err_closedir; + goto err_cleanup; } ret = snprintf(buf, PATH_MAX, "%s/%s", dir->i_srcpath, d->name); if (ret < 0 || ret >= PATH_MAX) - goto err_closedir; + goto err_cleanup; inode = erofs_iget_from_srcpath(sbi, buf); if (IS_ERR(inode)) { ret = PTR_ERR(inode); - goto err_closedir; + goto err_cleanup; } d->inode = inode; d->type = erofs_mode_to_ftype(inode->i_mode); @@ -1484,7 +1472,7 @@ static int erofs_mkfs_handle_directory(struct erofs_inode *dir) erofs_dbg("file %s added (type %u)", buf, d->type); nr_subdirs++; } - closedir(_dir); + free(dent); ret = erofs_init_empty_dir(dir); if (ret) @@ -1506,8 +1494,9 @@ static int erofs_mkfs_handle_directory(struct erofs_inode *dir) return erofs_mkfs_go(sbi, EROFS_MKFS_JOB_DIR, &dir, sizeof(dir)); -err_closedir: - closedir(_dir); +err_cleanup: + for (; i < num_entries; free(dent[i]), i++); + free(dent); return ret; } -- 2.47.0.338.g60cca15819-goog