[tex-k] Reproducible builds using pdftex

Norbert Preining preining at logic.at
Tue May 3 09:50:45 CEST 2016


Hi all,

> there can't be any case where we will want to set SOURCE_DATE_EPOCH but
> not SOURCE_DATE_EPOCH_TEX_PRIMITIVES.

I would suggest the following:
SOURCE_DATE_EPOCH is used to define the date/epoch and is evaluated
	for pdf output etc
SOURCE_DATE_EPOCH_FIXUP_TEX_PRIMITIVES = 0|1
	if non-0 then also \today is fixed.

It does not make sense to set the same value in two variables, and
complicates the code, but it *does* make sense to install an
additional safeguard not to redefine TeX primitives.

I attach a *suggestion* for a patch against current svn (some changes
have already been included in dvipdfmx, those are dropped).

All the best

Norbert

------------------------------------------------------------------------
PREINING, Norbert                               http://www.preining.info
JAIST, Japan                                 TeX Live & Debian Developer
GPG: 0x860CDC13   fp: F7D8 A928 26E3 16A1 9FA0  ACF0 6CAC A448 860C DC13
------------------------------------------------------------------------
-------------- next part --------------
---
 texk/web2c/lib/texmfmp.c          |   60 ++++++++++++++++++++++++--------------
 texk/web2c/luatexdir/luatex.c     |   12 ++++++-
 texk/web2c/luatexdir/pdf/pdfgen.w |   20 ++++++++++--
 3 files changed, 64 insertions(+), 28 deletions(-)

--- texlive-bin.orig/texk/web2c/lib/texmfmp.c
+++ texlive-bin/texk/web2c/lib/texmfmp.c
@@ -2200,6 +2200,30 @@
 }
 #endif /* not WIN32 */
 
+static boolean start_time_set = false;
+static time_t start_time = 0;
+
+void init_start_time() {
+    char *source_date_epoch;
+    unsigned long long epoch;
+    char *endptr;
+    if (!start_time_set) {
+        start_time_set = true;
+        source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+        if (source_date_epoch) {
+            errno = 0;
+            epoch = strtoull(source_date_epoch, &endptr, 10);
+            if (epoch < 0 || *endptr != '\0' || errno != 0) {
+              FATAL1 ("invalid value for environment variable $SOURCE_DATE_EPOCH: %s",
+                      source_date_epoch);
+            }
+            start_time = epoch;
+        } else {
+            start_time = time((time_t *) NULL);
+        }
+    }
+}
+
 /* Besides getting the date and time here, we also set up the interrupt
    handler, for no particularly good reason.  It's just that since the
    `fix_date_and_time' routine is called early on (section 1337 in TeX,
@@ -2210,8 +2234,14 @@
 get_date_and_time (integer *minutes,  integer *day,
                    integer *month,  integer *year)
 {
-  time_t myclock = time ((time_t *) 0);
-  struct tm *tmptr = localtime (&myclock);
+  struct tm *tmptr;
+  if(getenv("SOURCE_DATE_EPOCH_FIXUP_TEX_PRIMITIVES")) {
+    init_start_time();
+    tmptr = gmtime (&start_time);
+  } else {
+    time_t myclock = time ((time_t *) 0);
+    tmptr = localtime (&myclock);
+  }
 
   *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
   *day = tmptr->tm_mday;
@@ -2930,8 +2960,7 @@
 #endif /* not pdfTeX */
 
 #if !defined(XeTeX)
-static boolean start_time_set = false;
-static time_t start_time = 0;
+
 #define TIME_STR_SIZE 30
 char start_time_str[TIME_STR_SIZE];
 static char time_str[TIME_STR_SIZE];
@@ -2996,25 +3025,12 @@
 
 void initstarttime(void)
 {
-    char *source_date_epoch;
-    int64_t epoch;
-    char *endptr;
     if (!start_time_set) {
-        start_time_set = true;
-        source_date_epoch = getenv("SOURCE_DATE_EPOCH");
-        if (source_date_epoch) {
-            errno = 0;
-            epoch = strtoll(source_date_epoch, &endptr, 10);
-            if (epoch < 0 || *endptr != '\0' || errno != 0) {
-       FATAL1 ("invalid value for environment variable $SOURCE_DATE_EPOCH: %s",
-                source_date_epoch);
-            }
-            start_time = epoch;
-            makepdftime(start_time, start_time_str, /* utc= */true);
-        }
-        else {
-            start_time = time((time_t *) NULL);
-            makepdftime(start_time, start_time_str, /* utc= */false);
+        init_start_time ();
+        if (getenv ("SOURCE_DATE_EPOCH")) {
+            makepdftime (start_time, start_time_str, /* utc= */true);
+        } else {
+            makepdftime (start_time, start_time_str,  /* utc= */false);
         }
     }
 }
--- texlive-bin.orig/texk/web2c/luatexdir/luatex.c
+++ texlive-bin/texk/web2c/luatexdir/luatex.c
@@ -858,8 +858,16 @@
 
 void get_date_and_time(int *minutes, int *day, int *month, int *year)
 {
-    time_t myclock = time((time_t *) 0);
-    struct tm *tmptr = localtime(&myclock);
+    char *source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+    struct tm *tmptr;
+    time_t myclock;
+    if(source_date_epoch) {
+        myclock = strtoull(source_date_epoch, NULL, 10);
+        tmptr = gmtime (&myclock);
+    } else {
+        myclock = time((time_t *) 0);
+        tmptr = localtime(&myclock);
+    }
 
     *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
     *day = tmptr->tm_mday;
--- texlive-bin.orig/texk/web2c/luatexdir/pdf/pdfgen.w
+++ texlive-bin/texk/web2c/luatexdir/pdf/pdfgen.w
@@ -1534,7 +1534,7 @@
 @c
 #define TIME_STR_SIZE 30 /* minimum size for |time_str| is 24: |"D:YYYYmmddHHMMSS+HH'MM'"| */
 
-static void makepdftime(PDF pdf)
+static void makepdftime(PDF pdf, int utc)
 {
     struct tm lt, gmt;
     size_t size;
@@ -1542,7 +1542,12 @@
     time_t t = pdf->start_time;
     char *time_str = pdf->start_time_str;
     /* get the time */
-    lt = *localtime(&t);
+    if (utc) {
+        lt = *gmtime(&t);
+    }
+    else {
+        lt = *localtime(&t);
+    }
     size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
     /* expected format: "YYYYmmddHHMMSS" */
     if (size == 0) {
@@ -1584,10 +1589,17 @@
 @ @c
 void init_start_time(PDF pdf)
 {
+    char *source_date_epoch;
     if (pdf->start_time == 0) {
-        pdf->start_time = time((time_t *) NULL);
         pdf->start_time_str = xtalloc(TIME_STR_SIZE, char);
-        makepdftime(pdf);
+        source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+        if(source_date_epoch) {
+            pdf->start_time = strtoull(source_date_epoch, NULL, 10);
+            makepdftime(pdf,true);
+        } else {
+            pdf->start_time = time((time_t *) NULL);
+            makepdftime(pdf,false);
+        }
     }
 }
 


More information about the tex-k mailing list