Module Name: src Committed By: rillig Date: Sat Aug 19 11:13:36 UTC 2023
Modified Files: src/usr.bin/make: var.c src/usr.bin/make/unit-tests: varmod-gmtime.mk Log Message: make: work around bugs in gmtime on several platforms To generate a diff of this commit: cvs rdiff -u -r1.1061 -r1.1062 src/usr.bin/make/var.c cvs rdiff -u -r1.17 -r1.18 src/usr.bin/make/unit-tests/varmod-gmtime.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/var.c diff -u src/usr.bin/make/var.c:1.1061 src/usr.bin/make/var.c:1.1062 --- src/usr.bin/make/var.c:1.1061 Thu Aug 17 19:06:51 2023 +++ src/usr.bin/make/var.c Sat Aug 19 11:13:35 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.1061 2023/08/17 19:06:51 rillig Exp $ */ +/* $NetBSD: var.c,v 1.1062 2023/08/19 11:13:35 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -139,7 +139,7 @@ #include "metachar.h" /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: var.c,v 1.1061 2023/08/17 19:06:51 rillig Exp $"); +MAKE_RCSID("$NetBSD: var.c,v 1.1062 2023/08/19 11:13:35 rillig Exp $"); /* * Variables are defined using one of the VAR=value assignments. Their @@ -1886,7 +1886,24 @@ FormatTime(const char *fmt, time_t t, bo time(&t); if (*fmt == '\0') fmt = "%c"; - strftime(buf, sizeof buf, fmt, gmt ? gmtime(&t) : localtime(&t)); + if (gmt) { + /* + * Work around a buggy 'strftime' implementation on at least + * NetBSD 10 and Linux/glibc-2.31, on which the value of '%s' + * depends on the timezone from TZ; see varmod-gmtime.mk. + */ + const char *prev_tz_env = getenv("TZ"); + char *prev_tz = prev_tz_env != NULL + ? bmake_strdup(prev_tz_env) : NULL; + setenv("TZ", "UTC", 1); + strftime(buf, sizeof buf, fmt, localtime(&t)); + if (prev_tz != NULL) { + setenv("TZ", prev_tz, 1); + free(prev_tz); + } else + unsetenv("TZ"); + } else + strftime(buf, sizeof buf, fmt, localtime(&t)); buf[sizeof buf - 1] = '\0'; return bmake_strdup(buf); Index: src/usr.bin/make/unit-tests/varmod-gmtime.mk diff -u src/usr.bin/make/unit-tests/varmod-gmtime.mk:1.17 src/usr.bin/make/unit-tests/varmod-gmtime.mk:1.18 --- src/usr.bin/make/unit-tests/varmod-gmtime.mk:1.17 Sat Aug 19 10:33:32 2023 +++ src/usr.bin/make/unit-tests/varmod-gmtime.mk Sat Aug 19 11:13:36 2023 @@ -1,4 +1,4 @@ -# $NetBSD: varmod-gmtime.mk,v 1.17 2023/08/19 10:33:32 rillig Exp $ +# $NetBSD: varmod-gmtime.mk,v 1.18 2023/08/19 11:13:36 rillig Exp $ # # Tests for the :gmtime variable modifier, which formats a timestamp # using strftime(3) in UTC. @@ -146,13 +146,13 @@ .endif -# As of 2023-08-19, ':gmtime' but not ':localtime' reports wrong values for -# '%s', depending on the operating system and the timezone, as demonstrated by -# the following test program: +# Before var.c 1.1062 from 2023-08-19, ':gmtime' but not ':localtime' reported +# wrong values for '%s', depending on the operating system and the timezone, +# as demonstrated by the following test program: # # for mod in gmtime localtime; do # for tz in UTC Europe/Berlin America/Los_Angeles; do -# TZ=$tz bmake -r -v "\${%F %T %z %s $mod $tz:L:$mod}" +# TZ=$tz ./make -r -f /dev/null -v "\${%F %T %z %s $mod $tz:L:$mod}" # done # done # @@ -194,33 +194,30 @@ # * ':gmtime' reports the correct timezone offset '+0000'. # * ':gmtime' reports different seconds since the Epoch, and the '%s' # value cannot be derived from the '%F %T %z' values. -.if 0 # only for reference, due to platform differences export TZ=UTC -. for t in ${%s:L:gmtime} ${%s:L:localtime} +.for t in ${%s:L:gmtime} ${%s:L:localtime} TIMESTAMPS+= $t -. endfor +.endfor export TZ=Europe/Berlin -. for t in ${%s:L:gmtime} ${%s:L:localtime} +.for t in ${%s:L:gmtime} ${%s:L:localtime} TIMESTAMPS+= $t -. endfor +.endfor export TZ=UTC -. for t in ${%s:L:gmtime} ${%s:L:localtime} +.for t in ${%s:L:gmtime} ${%s:L:localtime} TIMESTAMPS+= $t -. endfor +.endfor export TZ=America/Los_Angeles -. for t in ${%s:L:gmtime} ${%s:L:localtime} +.for t in ${%s:L:gmtime} ${%s:L:localtime} TIMESTAMPS+= $t -. endfor +.endfor export TZ=UTC -. for t in ${%s:L:gmtime} ${%s:L:localtime} +.for t in ${%s:L:gmtime} ${%s:L:localtime} TIMESTAMPS+= $t -. endfor -. info ${TIMESTAMPS:u} -. for a b in ${TIMESTAMPS:[1]} ${TIMESTAMPS:@t@$t $t@} ${TIMESTAMPS:[-1]} -. if $a > $b -. warning timestamp $a > $b -. endif -. endfor -.endif +.endfor +.for a b in ${TIMESTAMPS:[1]} ${TIMESTAMPS:@t@$t $t@} ${TIMESTAMPS:[-1]} +. if $a > $b +. warning timestamp $a > $b +. endif +.endfor all: