Source: colord Version: 1.2.12-1 Severity: wishlist Tags: patch User: reproducible-bui...@lists.alioth.debian.org Usertags: timestamps Control: block -1 by 814883
Hi! While working on the “reproducible builds” effort [1], we have noticed that colord could not be built reproducibly. The attached patches remove extra timestamps when generating CMF and spectra and implement support for SOURCE_DATE_EPOCH. Together with a patched lcms2, they make colord reproducible in our current experimental framework. [1]: https://wiki.debian.org/ReproducibleBuilds -- Lunar .''`. lu...@debian.org : :Ⓐ : # apt-get install anarchism `. `'` `-
From 97d54abbf3240a14b271ac7f8f79331adbf1a219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Bobbio?= <lu...@debian.org> Date: Sat, 20 Feb 2016 12:48:47 +0100 Subject: [PATCH 1/2] Stop writing a CREATED header in CMF and spectra For the same input `cd-it8 create-cmf` and `cd-it8 create-sp` will create the exact same output except for the creation time. As the header is optional and prevents CMF and spectra to be built reproducibly, we use cd_it8_set_enable_created() to remove it from the output. --- client/cd-it8.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/cd-it8.c b/client/cd-it8.c index 987776a..26bc26d 100644 --- a/client/cd-it8.c +++ b/client/cd-it8.c @@ -303,6 +303,7 @@ cd_util_create_cmf (CdUtilPrivate *priv, if (dot != NULL) *dot = '\0'; cd_it8_set_title (cmf, title); + cd_it8_set_enable_created (cmf, FALSE); /* save */ file = g_file_new_for_path (values[0]); @@ -464,6 +465,7 @@ cd_util_create_sp (CdUtilPrivate *priv, if (dot != NULL) *dot = '\0'; cd_it8_set_title (cmf, title); + cd_it8_set_enable_created (cmf, FALSE); /* save */ file = g_file_new_for_path (values[0]); -- 2.7.0
From fc72fa8fe89e1eae4cbda2f4eed806756e1fb88a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Bobbio?= <lu...@debian.org> Date: Sat, 20 Feb 2016 12:55:57 +0100 Subject: [PATCH 2/2] cd-create-profile: Add support for SOURCE_DATE_EPOCH When creating profiles, the current time used to be written in the generated header as the creation date/time. This prevents cd-create-profile from generating the same bytes, despite getting the same input. Also, as cd-create-profile transforms an XML description into a binary ICC profile, the current time does not reflect will when the profile was actually created. So we now use the modification time of the source file as the creation date/time. However, if the SOURCE_DATE_EPOCH environment variable is specified, its value will be used instead to ease reproducible builds. For more details about SOURCE_DATE_EPOCH, see https://reproducible-builds.org/specs/source-date-epoch/ This uses cmsSetHeaderCreationDateTime() and thus requires a version of lcms2 with this feature. --- client/cd-create-profile.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/client/cd-create-profile.c b/client/cd-create-profile.c index d9159a3..f0edee9 100644 --- a/client/cd-create-profile.c +++ b/client/cd-create-profile.c @@ -22,10 +22,14 @@ #include "config.h" #include <glib/gi18n.h> +#include <glib/gstdio.h> #include <gio/gio.h> #include <locale.h> #include <lcms2.h> #include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> #include <math.h> #include <colord-private.h> @@ -686,6 +690,55 @@ cd_util_icc_set_metadata_coverage (CdIcc *icc, GError **error) } /** + * cd_util_adjust_creation_time: + **/ +static gboolean +cd_util_adjust_creation_time (CdUtilPrivate *priv, const char *source_filename, GError **error) +{ + GStatBuf st; + struct tm *creation_time; + time_t build_date = 0; + char *source_date_epoch_string; + unsigned long long source_date_epoch; + char *endptr; + + /* adjust creation time to match the XML one or SOURCE_DATE_EPOCH if specified and older */ + source_date_epoch_string = getenv ("SOURCE_DATE_EPOCH"); + if (source_date_epoch_string) { + errno = 0; + source_date_epoch = strtoull (source_date_epoch_string, &endptr, 10); + if ((source_date_epoch == ERANGE && (source_date_epoch == ULLONG_MAX || source_date_epoch == 0)) + || (errno != 0 && source_date_epoch == 0)) { + g_set_error (error, 1, 0, "Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n", g_strerror (errno)); + return FALSE; + } + if (endptr == source_date_epoch_string) { + g_set_error (error, 1, 0, "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n", endptr); + return FALSE; + } + if (*endptr != '\0') { + g_set_error (error, 1, 0, "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n", endptr); + return FALSE; + } + if (source_date_epoch > ULONG_MAX) { + g_set_error (error, 1, 0, "Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to: %lu but was found to be: %llu \n", ULONG_MAX, source_date_epoch); + return FALSE; + } + build_date = source_date_epoch; + } + + if (g_stat (source_filename, &st) >= 0) { + if (!build_date || st.st_mtime <= build_date) { + build_date = st.st_mtime; + } + } + if ((creation_time = gmtime (&build_date)) != NULL) { + cmsSetHeaderCreationDateTime (priv->lcms_profile, creation_time); + } + return TRUE; +} + +/** * cd_util_create_from_xml: **/ static gboolean @@ -764,6 +817,10 @@ cd_util_create_from_xml (CdUtilPrivate *priv, cd_dom_get_node_data (tmp)); } + ret = cd_util_adjust_creation_time(priv, filename, error); + if (!ret) + return FALSE; + /* add CMS defines */ cd_icc_add_metadata (priv->icc, CD_PROFILE_METADATA_CMF_PRODUCT, -- 2.7.0
signature.asc
Description: Digital signature