Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

erofs: improve reproducibility of podvm images #964

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions overlays/erofs-utils-reproducibility.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
diff --git a/lib/inode.c b/lib/inode.c
index b9dbbd6..385d5b2 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -1413,69 +1413,63 @@ 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 **entries;
+ int i;
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",
+ i = scandir(dir->i_srcpath, &entries, NULL, alphasort);
+ if (i == -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) {
+ while (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 = entries[i];

if (is_dot_dotdot(dp->d_name)) {
++i_nlink;
+ free(dp);
continue;
}

/* skip if it's a exclude file */
- if (erofs_is_exclude_path(dir->i_srcpath, dp->d_name))
+ if (erofs_is_exclude_path(dir->i_srcpath, dp->d_name)) {
+ free(dp);
continue;
+ }

d = erofs_d_alloc(dir, dp->d_name);
if (IS_ERR(d)) {
ret = PTR_ERR(d);
- goto err_closedir;
+ goto err_free;
}

ret = snprintf(buf, PATH_MAX, "%s/%s", dir->i_srcpath, d->name);
if (ret < 0 || ret >= PATH_MAX)
- goto err_closedir;
+ goto err_free;

inode = erofs_iget_from_srcpath(sbi, buf);
if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
- goto err_closedir;
+ goto err_free;
}
d->inode = inode;
d->type = erofs_mode_to_ftype(inode->i_mode);
i_nlink += S_ISDIR(inode->i_mode);
erofs_dbg("file %s added (type %u)", buf, d->type);
nr_subdirs++;
+ free(dp);
}
- closedir(_dir);
+ free(entries);

ret = erofs_init_empty_dir(dir);
if (ret)
@@ -1497,8 +1491,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_free:
+ free(dp);
+ free(entries);
return ret;
}
17 changes: 17 additions & 0 deletions overlays/nixpkgs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,21 @@ in
hash = "sha256-MsZ4Bl8sW1dZUB9cYPsaLtc8P8RRx4hafSbNB4vXqi4=";
};
});

erofs-utils = prev.erofs-utils.overrideAttrs (prev: {
patches = final.lib.optionals (prev ? patches) prev.patches ++ [
./erofs-utils-reproducibility.patch
];
# The build environment sets SOURCE_DATE_EPOCH to 1980, but as mkfs.erofs
# implements timestamp clamping, and files from the store have a 1970
# timestamp, we end up with different file metadata in the image
# (in addition, it is not reproducible which files are touched during
# the build). We cannot use the -T flag as env has precedence over
# the flag. We therefore wrap the binary to set SOURCE_DATE_EPOCH to 0.
nativeBuildInputs = prev.nativeBuildInputs ++ [ final.makeWrapper ];
postFixup = ''
wrapProgram $out/bin/mkfs.erofs \
--set SOURCE_DATE_EPOCH 0
'';
});
}