]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Make lib/dns/gen.c compatible with reproducible builds.
authorOndřej Surý <ondrej@sury.org>
Fri, 29 Mar 2019 15:17:00 +0000 (16:17 +0100)
committerOndřej Surý <ondrej@sury.org>
Thu, 9 May 2019 08:10:01 +0000 (15:10 +0700)
The gen.c will now use SOURCE_DATE_EPOCH[1] if found in environment
to make the build more reproducible build friendly.

1. https://reproducible-builds.org/specs/source-date-epoch/

lib/dns/gen.c

index 4e5aae341c9260df5c65df3e6df834d082d98537..bee27d0ed47134a0b65502f0514d2978340b3ed4 100644 (file)
@@ -34,6 +34,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+#include <errno.h>
+#include <limits.h>
 
 #ifdef WIN32
 #include "gen-win32.h"
@@ -533,7 +535,6 @@ main(int argc, char **argv) {
        struct cc *cc;
        struct ttnam *ttn, *ttn2;
        unsigned int hash;
-       struct tm *tm;
        time_t now;
        char year[11];
        int lasttype;
@@ -549,6 +550,9 @@ main(int argc, char **argv) {
        char *prefix = NULL;
        char *suffix = NULL;
        char *file = NULL;
+       char *source_date_epoch;
+       unsigned long long epoch;
+       char *endptr;
        isc_dir_t dir;
 
        for (i = 0; i < TYPENAMES; i++)
@@ -645,8 +649,46 @@ main(int argc, char **argv) {
        INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
        sd(0, "", buf, filetype);
 
-       if (time(&now) != -1) {
-               if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) {
+       source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+       if (source_date_epoch) {
+               errno = 0;
+               epoch = strtoull(source_date_epoch, &endptr, 10);
+               if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+                               || (errno != 0 && epoch == 0)) {
+                       fprintf(stderr, "Environment variable "
+                               "$SOURCE_DATE_EPOCH: strtoull: %s\n",
+                               strerror(errno));
+                       exit (EXIT_FAILURE);
+               }
+               if (endptr == source_date_epoch) {
+                       fprintf(stderr, "Environment variable "
+                               "$SOURCE_DATE_EPOCH: "
+                               "No digits were found: %s\n",
+                               endptr);
+                       exit (EXIT_FAILURE);
+               }
+               if (*endptr != '\0') {
+                       fprintf(stderr, "Environment variable "
+                               "$SOURCE_DATE_EPOCH: Trailing garbage: %s\n",
+                               endptr);
+                       exit (EXIT_FAILURE);
+               }
+               if (epoch > ULONG_MAX) {
+                       fprintf(stderr, "Environment variable "
+                               "$SOURCE_DATE_EPOCH: value must be "
+                               "smaller than or equal to: %lu but "
+                               "was found to be: %llu \n",
+                               ULONG_MAX, epoch);
+                       exit (EXIT_FAILURE);
+               }
+               now = epoch;
+       } else {
+               time(&now);
+       }
+
+       if (now != -1) {
+               struct tm *tm = gmtime(&now);
+               if (tm != NULL && tm->tm_year > 104) {
                        n = snprintf(year, sizeof(year), "-%d",
                                     tm->tm_year + 1900);
                        INSIST(n > 0 && (unsigned)n < sizeof(year));