124 lines
3.3 KiB
Diff
124 lines
3.3 KiB
Diff
|
From e72a9d017742366cba636d783ea121279bfb7d6c Mon Sep 17 00:00:00 2001
|
|||
|
From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
|
|||
|
Date: Thu, 9 Mar 2023 19:19:51 +0100
|
|||
|
Subject: [PATCH] Make ModDate and CreationDate in PDF reproducible
|
|||
|
|
|||
|
Ghostscript ignores the date in the preamble and uses the current
|
|||
|
time instead. This notably breaks the SOURCE_DATE_EPOCH support
|
|||
|
for reproducible builds.
|
|||
|
|
|||
|
Passing the creation time as DOCINFO pdfmark forces gs to use the
|
|||
|
specified date/time. Although ghostscript still adds the unreproducible
|
|||
|
DocumentUUID and trailer ID, it is sufficient when including the PDF
|
|||
|
figure with pdflatex.
|
|||
|
|
|||
|
Reuse the SOURCE_DATE_EPOCH code from creation_date for determining
|
|||
|
the wanted timestamp, and return the formatted time via the new
|
|||
|
`creation_date_pdfmark` function.
|
|||
|
---
|
|||
|
fig2dev/creationdate.c | 38 +++++++++++++++++++++++++++++++++-----
|
|||
|
fig2dev/creationdate.h | 1 +
|
|||
|
fig2dev/dev/genps.c | 8 ++++++++
|
|||
|
3 files changed, 42 insertions(+), 5 deletions(-)
|
|||
|
|
|||
|
diff --git a/fig2dev/creationdate.c b/fig2dev/creationdate.c
|
|||
|
index a51bfd4..de914a5 100644
|
|||
|
--- a/fig2dev/creationdate.c
|
|||
|
+++ b/fig2dev/creationdate.c
|
|||
|
@@ -36,8 +36,8 @@
|
|||
|
#include "creationdate.h"
|
|||
|
|
|||
|
|
|||
|
-int
|
|||
|
-creation_date(char *buf)
|
|||
|
+static struct tm*
|
|||
|
+parse_time()
|
|||
|
{
|
|||
|
time_t now;
|
|||
|
|
|||
|
@@ -70,15 +70,43 @@ creation_date(char *buf)
|
|||
|
} else {
|
|||
|
/* no errors, epoch is valid */
|
|||
|
now = epoch;
|
|||
|
- strftime(buf, CREATION_TIME_LEN, "%F %H:%M:%S", gmtime(&now));
|
|||
|
- return true;
|
|||
|
+ return gmtime(&now);
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
/* fall trough on errors or !source_date_epoch */
|
|||
|
time(&now);
|
|||
|
- if (strftime(buf, CREATION_TIME_LEN, "%F %H:%M:%S", localtime(&now)))
|
|||
|
+ return localtime(&now);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static struct tm*
|
|||
|
+get_time()
|
|||
|
+{
|
|||
|
+ static struct tm time = { 0 };
|
|||
|
+ static int initialized = 0;
|
|||
|
+ if (!initialized) {
|
|||
|
+ time = *parse_time();
|
|||
|
+ initialized = 1;
|
|||
|
+ }
|
|||
|
+ return &time;
|
|||
|
+}
|
|||
|
+
|
|||
|
+int
|
|||
|
+creation_date(char *buf)
|
|||
|
+{
|
|||
|
+ if (strftime(buf, CREATION_TIME_LEN, "%F %H:%M:%S", get_time()))
|
|||
|
+ return true;
|
|||
|
+ else
|
|||
|
+ return false;
|
|||
|
+}
|
|||
|
+
|
|||
|
+int
|
|||
|
+creation_date_pdfmark(char *buf)
|
|||
|
+{
|
|||
|
+ // Pdfmark format should be D:YYYYMMDDHHmmSSOHH’mm’.
|
|||
|
+ // Timezone offset (O...) may be omitted
|
|||
|
+ if (strftime(buf, CREATION_TIME_LEN, "D:%Y%m%d%H%M%S", get_time()))
|
|||
|
return true;
|
|||
|
else
|
|||
|
return false;
|
|||
|
diff --git a/fig2dev/creationdate.h b/fig2dev/creationdate.h
|
|||
|
index 048508a..199d985 100644
|
|||
|
--- a/fig2dev/creationdate.h
|
|||
|
+++ b/fig2dev/creationdate.h
|
|||
|
@@ -21,3 +21,4 @@
|
|||
|
|
|||
|
#define CREATION_TIME_LEN 36
|
|||
|
extern int creation_date(char *buf);
|
|||
|
+extern int creation_date_pdfmark(char *buf);
|
|||
|
diff --git a/fig2dev/dev/genps.c b/fig2dev/dev/genps.c
|
|||
|
index 5bea35c..48e05a6 100644
|
|||
|
--- a/fig2dev/dev/genps.c
|
|||
|
+++ b/fig2dev/dev/genps.c
|
|||
|
@@ -1181,6 +1181,7 @@ genps_end(void)
|
|||
|
const int h = pageheight, w = pagewidth;
|
|||
|
int epslen, tiflen;
|
|||
|
struct stat fstat;
|
|||
|
+ char date_buf[CREATION_TIME_LEN];
|
|||
|
|
|||
|
/* for multipage, translate and output objects for each page */
|
|||
|
if (multi_page) {
|
|||
|
@@ -1368,6 +1369,13 @@ genps_end(void)
|
|||
|
/* final DSC comment for eps output (EOF = end of document) */
|
|||
|
fputs("%EOF\n", tfp);
|
|||
|
|
|||
|
+ if (pdfflag) {
|
|||
|
+ if (creation_date_pdfmark(date_buf))
|
|||
|
+ fprintf(tfp,
|
|||
|
+ "[ /ModDate (%s)\n /CreationDate (%s)\n /DOCINFO pdfmark\n",
|
|||
|
+ date_buf, date_buf);
|
|||
|
+ }
|
|||
|
+
|
|||
|
/* all ok */
|
|||
|
return 0;
|
|||
|
}
|
|||
|
--
|
|||
|
2.39.2
|
|||
|
|