[Reproducible-commits] [dpkg] 100/105: dpkg-deb: Use the common build timestamp for all files created at a later time

Niko Tyni ntyni at moszumanska.debian.org
Mon May 2 13:50:00 UTC 2016


This is an automated email from the git hooks/post-receive script.

ntyni pushed a commit to branch ntyni/reproducible_builds
in repository dpkg.

commit 98d25dcc98139af243756cb24298518ced55abed
Author: Jérémy Bobbio <lunar at debian.org>
Date:   Fri Jan 15 17:00:37 2016 +0000

    dpkg-deb: Use the common build timestamp for all files created at a later time
    
    In order to make build reproducible in the future, we now set the mtime of
    archived files that has been create during the build to the common build
    timestamp when tar supports the --clamp-mtime option.
    
    The latter is available in Debian since tar/1.28-1 but has not been accepted
    upstream yet.
    
    Address: #759886
---
 dpkg-deb/build.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 52 insertions(+), 4 deletions(-)

diff --git a/dpkg-deb/build.c b/dpkg-deb/build.c
index 9578894..fc29b59 100644
--- a/dpkg-deb/build.c
+++ b/dpkg-deb/build.c
@@ -421,6 +421,7 @@ typedef void filenames_feed_func(const char *dir, int fd_out);
  */
 static void
 tarball_pack(const char *dir, filenames_feed_func *tar_filenames_feeder,
+             time_t build_timestamp, int tar_supports_clamp_mtime,
              struct compress_params *tar_compress_params, int fd_out)
 {
   int pipe_filenames[2], pipe_tarball[2];
@@ -441,8 +442,17 @@ tarball_pack(const char *dir, filenames_feed_func *tar_filenames_feeder,
     if (chdir(dir))
       ohshite(_("failed to chdir to '%.255s'"), dir);
 
-    execlp(TAR, "tar", "-cf", "-", "--format=gnu", "--null", "--no-unquote",
-                       "--no-recursion", "-T", "-", NULL);
+    if (tar_supports_clamp_mtime) {
+      char mtime_option[30];
+      snprintf(mtime_option, sizeof(mtime_option), "--mtime=@%ld", build_timestamp);
+      mtime_option[29] = '\0';
+      execlp(TAR, "tar", "-cf", "-", "--format=gnu", "--null", "--no-unquote",
+                         mtime_option, "--clamp-mtime", "--no-recursion",
+                         "-T", "-", NULL);
+    } else {
+      execlp(TAR, "tar", "-cf", "-", "--format=gnu", "--null", "--no-unquote",
+                         "--no-recursion", "-T", "-", NULL);
+    }
     ohshite(_("unable to execute %s (%s)"), "tar -cf", TAR);
   }
   close(pipe_filenames[0]);
@@ -468,6 +478,40 @@ tarball_pack(const char *dir, filenames_feed_func *tar_filenames_feeder,
 }
 
 /**
+ * Parse `tar --help` output to see if it supports the given option.
+ */
+static int
+does_tar_support(const char *option)
+{
+  int pipe_tar_output[2];
+  pid_t pid_tar;
+  FILE *tar_output;
+  char line_buf[80];
+  int found = 0;
+
+  m_pipe(pipe_tar_output);
+  pid_tar = subproc_fork();
+  if (pid_tar == 0) {
+    m_dup2(pipe_tar_output[1], 1);
+    close(pipe_tar_output[0]);
+    close(pipe_tar_output[1]);
+    execlp(TAR, "tar", "--help", NULL);
+    ohshite(_("unable to execute %s (%s)"), "tar --help", TAR);
+  }
+  close(pipe_tar_output[1]);
+  tar_output = fdopen(pipe_tar_output[0], "r");
+  while (fgets(line_buf, sizeof(line_buf), tar_output)) {
+    if (strstr(line_buf, option)) {
+      found = 1;
+      /* we don't break to consume all output and avoid getting a SIGPIPE. */
+    }
+  }
+  close(pipe_tar_output[0]);
+  subproc_reap(pid_tar, "tar --help", 0);
+  return found;
+}
+
+/**
  * Overly complex function that builds a .deb file.
  */
 int
@@ -481,6 +525,7 @@ do_build(const char *const *argv)
   char *tfbuf;
   int arfd;
   int gzfd;
+  int tar_supports_clamp_mtime;
   time_t build_timestamp;
 
   /* Decode our arguments. */
@@ -511,6 +556,8 @@ do_build(const char *const *argv)
   }
   m_output(stdout, _("<standard output>"));
 
+  tar_supports_clamp_mtime = does_tar_support("--clamp-mtime");
+
   build_timestamp = time(NULL);
 
   /* Now that we have verified everything its time to actually
@@ -544,7 +591,8 @@ do_build(const char *const *argv)
   }
 
   /* Fork a tar to package the control-section of the package. */
-  tarball_pack(ctrldir, control_treewalk_feed, &control_compress_params, gzfd);
+  tarball_pack(ctrldir, control_treewalk_feed, build_timestamp,
+               tar_supports_clamp_mtime, &control_compress_params, gzfd);
 
   free(ctrldir);
 
@@ -605,7 +653,7 @@ do_build(const char *const *argv)
   }
 
   /* Pack the directory into a tarball, feeding files from the callback. */
-  tarball_pack(dir, file_treewalk_feed, &compress_params, gzfd);
+  tarball_pack(dir, file_treewalk_feed, build_timestamp, tar_supports_clamp_mtime, &compress_params, gzfd);
 
   /* Okay, we have data.tar as well now, add it to the ar wrapper. */
   if (deb_format.major == 2) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/dpkg.git



More information about the Reproducible-commits mailing list