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.

Bug: 381793828
Test: make_erofs ... inputdir(ext3)
Test: make_erofs ... inputdir(tmpfs)
  # should generate the same output
Change-Id: I629834031634e3575490e3ded4385f666ee4fde9
---
 lib/inode.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/lib/inode.c b/lib/inode.c
index b9dbbd6..a460a8f 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -1413,37 +1413,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;
@@ -1475,7 +1463,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)
@@ -1498,7 +1486,8 @@ 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);
+       for (; i < num_entries; free(dent[i]), i++);
+       free(dent);
        return ret;
 }
 
-- 
2.47.0.338.g60cca15819-goog

Reply via email to