[PATCH 2/4] erofs-utils: support $SOURCE_DATE_EPOCH
Gao Xiang
hsiangkao at redhat.com
Fri Oct 30 23:30:18 AEDT 2020
Currently, we use -T to set a given UNIX timestamp for all
files, yet reproducible builds [1] requires what is called
"timestamp clamping", IOW, a timestamp must be used no later
than the value of this variable.
Let's support $SOURCE_DATE_EPOCH as well.
[1] https://reproducible-builds.org/specs/source-date-epoch/
Suggested-by: nl6720 <nl6720 at gmail.com>
Signed-off-by: Gao Xiang <hsiangkao at redhat.com>
---
include/erofs/config.h | 7 +++++++
lib/inode.c | 15 +++++++++++++--
mkfs/main.c | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/include/erofs/config.h b/include/erofs/config.h
index e425ce2..02ddf59 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -29,11 +29,18 @@ enum {
FORCE_INODE_EXTENDED,
};
+enum {
+ TIMESTAMP_NONE,
+ TIMESTAMP_FIXED,
+ TIMESTAMP_CLAMPING,
+};
+
struct erofs_configure {
const char *c_version;
int c_dbg_lvl;
bool c_dry_run;
bool c_legacy_compress;
+ char c_timeinherit;
#ifdef HAVE_LIBSELINUX
struct selabel_handle *sehnd;
diff --git a/lib/inode.c b/lib/inode.c
index 5695bbc..fee5c96 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -729,8 +729,19 @@ int erofs_fill_inode(struct erofs_inode *inode,
inode->i_mode = st->st_mode;
inode->i_uid = st->st_uid;
inode->i_gid = st->st_gid;
- inode->i_ctime = sbi.build_time;
- inode->i_ctime_nsec = sbi.build_time_nsec;
+ inode->i_ctime = st->st_ctime;
+ inode->i_ctime_nsec = st->st_ctim.tv_nsec;
+
+ switch (cfg.c_timeinherit) {
+ case TIMESTAMP_CLAMPING:
+ if (st->st_ctime < sbi.build_time)
+ break;
+ case TIMESTAMP_FIXED:
+ inode->i_ctime = sbi.build_time;
+ inode->i_ctime_nsec = sbi.build_time_nsec;
+ default:
+ break;
+ }
inode->i_nlink = 1; /* fix up later if needed */
switch (inode->i_mode & S_IFMT) {
diff --git a/mkfs/main.c b/mkfs/main.c
index 6dda9e3..5c41fc0 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -198,6 +198,7 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
erofs_err("invalid UNIX timestamp %s", optarg);
return -EINVAL;
}
+ cfg.c_timeinherit = TIMESTAMP_FIXED;
break;
case 2:
opt = erofs_parse_exclude_path(optarg, false);
@@ -381,6 +382,33 @@ static void erofs_mkfs_generate_uuid(void)
erofs_info("filesystem UUID: %s", uuid_str);
}
+/* https://reproducible-builds.org/specs/source-date-epoch/ for more details */
+int parse_source_date_epoch(void)
+{
+ char *source_date_epoch;
+ unsigned long long epoch = -1ULL;
+ char *endptr;
+
+ source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+ if (!source_date_epoch)
+ return 0;
+
+ epoch = strtoull(source_date_epoch, &endptr, 10);
+ if (epoch == -1ULL || *endptr != '\0') {
+ erofs_err("Environment variable $SOURCE_DATE_EPOCH %s is invalid",
+ source_date_epoch);
+ return -EINVAL;
+ }
+
+ if (cfg.c_force_inodeversion != FORCE_INODE_EXTENDED)
+ erofs_info("SOURCE_DATE_EPOCH is set, forcely generate extended inodes instead");
+
+ cfg.c_force_inodeversion = FORCE_INODE_EXTENDED;
+ cfg.c_unix_timestamp = epoch;
+ cfg.c_timeinherit = TIMESTAMP_CLAMPING;
+ return 0;
+}
+
int main(int argc, char **argv)
{
int err = 0;
@@ -405,6 +433,12 @@ int main(int argc, char **argv)
return 1;
}
+ err = parse_source_date_epoch();
+ if (err) {
+ usage();
+ return 1;
+ }
+
err = lstat64(cfg.c_src_path, &st);
if (err)
return 1;
--
2.18.1
More information about the Linux-erofs
mailing list