please make PDF ID field more deterministic
Nicolas Boulenguez <[email protected]>
| Newsgroups | gmane.comp.tex.pdftex |
|---|---|
| Message-ID | <20150517190945.GA16387@pegase> |
Hello.
It would be convenient that, by default or with appropriate options,
PDFTeX produces reproducible results from given input files. You may
find some motivations at
https://wiki.debian.org/ReproducibleBuilds/About#Why_do_we_want_reproducible_builds.3F
Despite the wording, few problems are specific to Debian.
By default, the CreationDate and ModDate fields reflect the build
date, but this can be overriden with
\ifpdf\pdfinfo{/CreationDate($DATE)/ModDate($DATE)}\fi
or
pdftex '\pdfinfo{/CreationDate($DATE)/ModDate($DATE)}\input{source.tex}'
Unfortunately, the implementation of the ID field is an MD5 hash of
the build date, the output directory path and the output file name.
A first suggestion is to avoid generating the ID field, which is
optional and not widely used.
A less intrusive option would provide a new primitive like
\pdfsetoutputfileid{}.
My favorite suggestion would let the default ID depend on
- the configurable CreationDate instead of a random gmtime().
- the output file name only, ignoring its directory path.
Even if everybody starts to use the ID field, I hardly imagine how
these changes could create a collision.
The attached patch demonstrates the idea on
https://foundry.supelec.fr/scm/viewvc.php/*checkout*/trunk/source/src/texk/web2c/pdftexdir/utils.c?revision=463&root=pdftex
It requires a trivial, but less readable change, in order to actually
compile: swap the declarations of the start_time_str global variable
and the printID() procedure.
--
Please CC me, I do not read this list permanently.
utils.c.diff
(text/x-diff, 1.1 KB)
--- utils.c.old 2015-05-17 19:42:26.237342143 +0200
+++ utils.c 2015-05-17 19:56:05.821406233 +0200
@@ -747,26 +747,17 @@
*/
void printID(strnumber filename)
{
- time_t t;
- size_t size;
- char time_str[32];
md5_state_t state;
md5_byte_t digest[16];
char id[64];
char *file_name;
- char pwd[4096];
/* start md5 */
md5_init(&state);
/* get the time */
- t = time(NULL);
- size = strftime(time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t));
- md5_append(&state, (const md5_byte_t *) time_str, size);
+ initstarttime();
+ md5_append(&state, (const md5_byte_t *) start_time_str, strlen(start_time_str));
/* get the file name */
- if (getcwd(pwd, sizeof(pwd)) == NULL)
- pdftex_fail("getcwd() failed (%s), path too long?", strerror(errno));
file_name = makecstring(filename);
- md5_append(&state, (const md5_byte_t *) pwd, strlen(pwd));
- md5_append(&state, (const md5_byte_t *) "/", 1);
md5_append(&state, (const md5_byte_t *) file_name, strlen(file_name));
/* finish md5 */
md5_finish(&state, digest);