From 6f2ad916ae98a8a463ae132d02b86c6c0529fab4 Mon Sep 17 00:00:00 2001
From: Thomas Deutschmann <whissi@gentoo.org>
Date: Thu, 30 Jul 2015 11:59:03 +0200
Subject: [PATCH 2/4] Allow the build timestamp to be externally set

In order to make Ghostscript output reproducible, we need a way to
set the build timestamp to other values than the current time.
We now consistently use gp_get_realtime() instead of directly calling
time() or gp_get_usertime() and make gp_get_realtime() use the value
found in the SOURCE_DATE_EPOCH environment variable if set. Also,
environment timezone is fixed to UTC if SOURCE_DATE_EPOCH is used to
avoid variations.

Origin: https://salsa.debian.org/printing-team/ghostscript/-/blob/e4280f77c6f710a8b98ebe41e564e5fef9d23964/debian/patches/2010_add_build_timestamp_setting.patch
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Signed-off-by: Sam James <sam@gentoo.org>
---
 base/gp_unix.c            | 22 ++++++++++++++++++++++
 devices/vector/gdevpdf.c  |  4 +++-
 devices/vector/gdevpdfe.c |  4 +++-
 devices/vector/gdevpsu.c  |  4 +++-
 4 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/base/gp_unix.c b/base/gp_unix.c
index 98db2ddf..8eee6a89 100644
--- a/base/gp_unix.c
+++ b/base/gp_unix.c
@@ -19,6 +19,7 @@
 #ifdef __MINGW32__
 #  include "windows_.h"
 #endif
+#include "errno_.h"
 #include "pipe_.h"
 #include "string_.h"
 #include "time_.h"
@@ -148,6 +149,7 @@ void
 gp_get_realtime(long *pdt)
 {
     struct timeval tp;
+    const char *env;
 
 #if gettimeofday_no_timezone    /* older versions of SVR4 */
     {
@@ -167,6 +169,26 @@ gp_get_realtime(long *pdt)
     }
 #endif
 
+    env = getenv("SOURCE_DATE_EPOCH");
+    if (env) {
+        char *end;
+        long timestamp;
+
+        errno = 0;
+        timestamp = strtol(env, &end, 10);
+        if (env == end || *end || errno != 0) {
+            lprintf("Ghostscript: SOURCE_DATE_EPOCH is not a number!\n");
+            timestamp = 0;
+        }
+
+        tp.tv_sec = timestamp;
+        tp.tv_usec = 0;
+
+        /* We need to fix the environment timezone to get reproducible */
+        /* results when parsing the result of gp_get_realtime. */
+        setenv("TZ", "UTC", 1);
+    }
+
     /* tp.tv_sec is #secs since Jan 1, 1970 */
     pdt[0] = tp.tv_sec;
 
diff --git a/devices/vector/gdevpdf.c b/devices/vector/gdevpdf.c
index 40beb06a..f34055cf 100644
--- a/devices/vector/gdevpdf.c
+++ b/devices/vector/gdevpdf.c
@@ -428,6 +428,7 @@ pdf_initialize_ids(gx_device_pdf * pdev)
     if (!pdev->OmitInfoDate)
     {
         struct tm tms;
+        long secs_ns[2];
         time_t t;
         char buf[1+2+4+2+2+2+2+2+1+2+1+2+1+1+1]; /* (D:yyyymmddhhmmssZhh'mm')\0 */
         int timeoffset;
@@ -439,7 +440,8 @@ pdf_initialize_ids(gx_device_pdf * pdev)
         timesign = 'Z';
         timeoffset = 0;
 #else
-        time(&t);
+        gp_get_realtime(secs_ns);
+        t = secs_ns[0];
         tms = *gmtime(&t);
         tms.tm_isdst = -1;
         timeoffset = (int)difftime(t, mktime(&tms)); /* tz+dst in seconds */
diff --git a/devices/vector/gdevpdfe.c b/devices/vector/gdevpdfe.c
index 66767bd9..23557fad 100644
--- a/devices/vector/gdevpdfe.c
+++ b/devices/vector/gdevpdfe.c
@@ -199,6 +199,7 @@ pdf_xmp_time(char *buf, int buf_length)
 {
     /* We don't write a day time because we don't have a time zone. */
     struct tm tms;
+    long secs_ns[2];
     time_t t;
     char buf1[4+1+2+1+2+1]; /* yyyy-mm-dd\0 */
 
@@ -206,7 +207,8 @@ pdf_xmp_time(char *buf, int buf_length)
     memset(&t, 0, sizeof(t));
     memset(&tms, 0, sizeof(tms));
 #else
-    time(&t);
+    gp_get_realtime(secs_ns);
+    t = secs_ns[0];
     tms = *localtime(&t);
 #endif
     gs_snprintf(buf1, sizeof(buf1),
diff --git a/devices/vector/gdevpsu.c b/devices/vector/gdevpsu.c
index 123dda69..3eaa49aa 100644
--- a/devices/vector/gdevpsu.c
+++ b/devices/vector/gdevpsu.c
@@ -187,6 +187,7 @@ psw_begin_file_header(gp_file *f, const gx_device *dev, const gs_rect *pbbox,
             dev->dname);
 #endif
     {
+        long secs_ns[2];
         time_t t;
         struct tm tms;
 
@@ -194,7 +195,8 @@ psw_begin_file_header(gp_file *f, const gx_device *dev, const gs_rect *pbbox,
         memset(&t, 0, sizeof(t));
         memset(&tms, 0, sizeof(tms));
 #else
-        time(&t);
+        gp_get_realtime(secs_ns);
+        t = secs_ns[0];
         tms = *localtime(&t);
 #endif
         fprintf(f, "%%%%CreationDate: %d/%02d/%02d %02d:%02d:%02d\n",
-- 
2.55.0

