599a615cb84799e1a50764ebecb27b459f629a3f — Silvan Jegen 2 months ago 2e2ccda
Don't use a GNU-extension for $SOURCE_DATE_EPOCH parsing

Code gratefully copied from the link below.

https://reproducible-builds.org/docs/source-date-epoch/#c
1 files changed, 33 insertions(+), 11 deletions(-)

M src/main.c
M src/main.c => src/main.c +33 -11
@@ 1,6 1,8 @@ #define _XOPEN_SOURCE 600
  #include <assert.h>
  #include <ctype.h>
+ #include <errno.h>
+ #include <limits.h>
  #include <stdbool.h>
  #include <stdio.h>
  #include <stdlib.h>


@@ 11,6 13,7 @@ #include "util.h"
  
  char *strstr(const char *haystack, const char *needle);
+ char *strerror(int errnum);
  
  static int parse_section(struct parser *p) {
  	str_t *section = str_create();


@@ 67,23 70,42 @@ str_t *extras[2] = { NULL };
  	int section = -1;
  	uint32_t ch;
+ 	time_t date_time;
  	char date[256];
  	char *source_date_epoch = getenv("SOURCE_DATE_EPOCH");
  	if (source_date_epoch != NULL) {
- 		struct tm source_date_epoch_tm;
- 		char *ret = strptime(source_date_epoch, "%s", &source_date_epoch_tm);
- 		if (ret == NULL || *ret != '\0') {
- 			fprintf(stderr,
- 					"Error: $SOURCE_DATE_EPOCH is set but malformed.\n");
- 			exit(1);
+ 		unsigned long long epoch;
+ 		char *endptr;
+ 		errno = 0;
+ 		epoch = strtoull(source_date_epoch, &endptr, 10);
+ 		if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+ 				|| (errno != 0 && epoch == 0)) {
+ 			fprintf(stderr, "$SOURCE_DATE_EPOCH: strtoull: %s\n",
+ 					strerror(errno));
+ 			exit(EXIT_FAILURE);
  		}
- 		strftime(date, sizeof(date), "%F", &source_date_epoch_tm);
+ 		if (endptr == source_date_epoch) {
+ 			fprintf(stderr, "$SOURCE_DATE_EPOCH: No digits were found: %s\n",
+ 					endptr);
+ 			exit(EXIT_FAILURE);
+ 		}
+ 		if (*endptr != '\0') {
+ 			fprintf(stderr, "$SOURCE_DATE_EPOCH: Trailing garbage: %s\n",
+ 					endptr);
+ 			exit(EXIT_FAILURE);
+ 		}
+ 		if (epoch > ULONG_MAX) {
+ 			fprintf(stderr, "$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);
+ 		}
+ 		date_time = epoch;
  	} else {
- 		time_t now;
- 		time(&now);
- 		struct tm *now_tm = localtime(&now);
- 		strftime(date, sizeof(date), "%F", now_tm);
+ 		date_time = time(NULL);
  	}
+ 	struct tm *date_tm = localtime(&date_time);
+ 	strftime(date, sizeof(date), "%F", date_tm);
  	while ((ch = parser_getch(p)) != UTF8_INVALID) {
  		if ((ch < 0x80 && isalnum(ch)) || ch == '_' || ch == '-' || ch == '.') {
  			int ret = str_append_ch(name, ch);