Browse Source

dpkg-split: Make the deb-split(5) generation reproducible

Honor SOURCE_DATE_EPOCH, so that we can control the output and generate
reproducible split packages.
Guillem Jover 7 years ago
parent
commit
6e5862ef6e
3 changed files with 32 additions and 0 deletions
  1. 2 0
      debian/changelog
  2. 24 0
      dpkg-split/split.c
  3. 6 0
      man/dpkg-split.man

+ 2 - 0
debian/changelog

@@ -13,6 +13,8 @@ dpkg (1.18.11) UNRELEASED; urgency=medium
     name affected.
   * Do not emit epochs for unambiguous versions in deb-split package header.
     Regression introduced in dpkg 1.18.0.
+  * Make the deb-split(5) generation in dpkg-split reproducible, by using the
+    timestamp from SOURCE_DATE_EPOCH.
   * Perl modules:
     - Obsolete Source-Version substvar in Dpkg::Substvars by emitting errors.
   * Packaging:

+ 24 - 0
dpkg-split/split.c

@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 
+#include <errno.h>
 #include <limits.h>
 #include <fcntl.h>
 #include <libgen.h>
@@ -89,6 +90,20 @@ deb_parse_control(const char *filename)
 	return pkg;
 }
 
+static time_t
+parse_timestamp(const char *value)
+{
+	time_t timestamp;
+	char *end;
+
+	errno = 0;
+	timestamp = strtol(value, &end, 10);
+	if (value == end || *end || errno != 0)
+		ohshite(_("unable to parse timestamp '%.255s'"), value);
+
+	return timestamp;
+}
+
 /* Cleanup filename for use in crippled msdos systems. */
 static char *
 clean_msdos_filename(char *filename)
@@ -117,6 +132,8 @@ mksplit(const char *file_src, const char *prefix, off_t maxpartsize,
 	struct dpkg_error err;
 	int fd_src;
 	struct stat st;
+	time_t timestamp;
+	const char *timestamp_str;
 	const char *version;
 	char hash[MD5HASHLEN + 1];
 	int nparts, curpart;
@@ -143,6 +160,12 @@ mksplit(const char *file_src, const char *prefix, off_t maxpartsize,
 	pkg  = deb_parse_control(file_src);
 	version = versiondescribe(&pkg->available.version, vdew_nonambig);
 
+	timestamp_str = getenv("SOURCE_DATE_EPOCH");
+	if (timestamp_str)
+		timestamp = parse_timestamp(timestamp_str);
+	else
+		timestamp = time(NULL);
+
 	partsize = maxpartsize - HEADERALLOWANCE;
 	last_partsize = st.st_size % partsize;
 	if (last_partsize == 0)
@@ -197,6 +220,7 @@ mksplit(const char *file_src, const char *prefix, off_t maxpartsize,
 
 		/* Split the data. */
 		ar = dpkg_ar_create(file_dst.buf, 0644);
+		dpkg_ar_set_mtime(ar, timestamp);
 
 		/* Write the ar header. */
 		dpkg_ar_put_magic(ar);

+ 6 - 0
man/dpkg-split.man

@@ -215,6 +215,12 @@ a file that looked like a package part file but was corrupted, or
 interactions with the system, such as accesses to the database,
 memory allocations, etc.
 .
+.SH ENVIRONMENT
+.TP
+.B SOURCE_DATE_EPOCH
+If set, it will be used as the timestamp (as seconds since the epoch) in
+the \fBdeb\-split\fP(5)'s \fBar\fP(5) container.
+.
 .SH FILES
 .TP
 .I %ADMINDIR%/parts