From patchwork Sun Jan 5 05:57:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Eggert X-Patchwork-Id: 104073 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D66693858D21 for ; Sun, 5 Jan 2025 06:26:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D66693858D21 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=cs.ucla.edu header.i=@cs.ucla.edu header.a=rsa-sha256 header.s=9D0B346E-2AEB-11ED-9476-E14B719DCE6C header.b=TahbdRSw X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail.cs.ucla.edu (mail.cs.ucla.edu [131.179.128.66]) by sourceware.org (Postfix) with ESMTPS id 2D00A3858405 for ; Sun, 5 Jan 2025 05:59:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2D00A3858405 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=cs.ucla.edu Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cs.ucla.edu ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2D00A3858405 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=131.179.128.66 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1736056771; cv=none; b=xsJLYclQSwFFW1w93OaHP8jnaP3d58tYfxnLsCnWm7FT261mjlZ8+KXPjwVeegr3qcc163SVz2oIkERnSFqFvWCPBM0NEvEGPY/bCMHfGygOFY28HChdri7CzUxfJCSLvJ2RyHCwK1ntlKA8Q2MVPtfSgz7XZHfx5WPrgx2JdNY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1736056771; c=relaxed/simple; bh=z2xkbZl7NqJZH5akYn3Cy/YE2HqYLx2cfje2fjp5VZM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=L3NZnFtQwC7i094QzMOaqunT8m/a96I/hLOlKWuvKWR/oZu7HZToaHke1X8fLQzh3aHhlQeYBKtPbVa197G994XbT4br92S1i26ct26/A9MxCx/9Izw6SYsHHAZnpf0rwegbu3W4Adr4MpXCjkhqD4YAnDHa+8tiLu4fGUyYYNY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2D00A3858405 Received: from localhost (localhost [127.0.0.1]) by mail.cs.ucla.edu (Postfix) with ESMTP id A693B3C123844 for ; Sat, 4 Jan 2025 21:59:30 -0800 (PST) Received: from mail.cs.ucla.edu ([127.0.0.1]) by localhost (mail.cs.ucla.edu [127.0.0.1]) (amavis, port 10032) with ESMTP id vX6dn_DiWPs2; Sat, 4 Jan 2025 21:59:30 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by mail.cs.ucla.edu (Postfix) with ESMTP id 3C5DB3C123843; Sat, 4 Jan 2025 21:59:30 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.cs.ucla.edu 3C5DB3C123843 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cs.ucla.edu; s=9D0B346E-2AEB-11ED-9476-E14B719DCE6C; t=1736056770; bh=0k6555OtSTcALgN5JJCkvxT1gpzJCJotW0YfnXoDORQ=; h=From:To:Date:Message-ID:MIME-Version; b=TahbdRSwogNMRuBshhJY6uIkMgZqhwZMWj3gZSz9ixiypzFQk5GOgfz7xvPQLhhCC d0QZ3Pw861cSwyVXh99ikcTHAkWJOhAKl3UEUNxZvvD4CHQQ8nWdX/w/l/h7EltlJP rxj9zFr48rN+OwHfDrfsOfAMzGSPMDn5RNtNSJDHBcHWrnHPy8cJNkMgISO8itM++T nzo+Va2/ZLg5CcSfS5vg4vxoDSUyJ+xxb9LE/TJpIwQv9yAQjyQc+W7ZE3KxhLAOAa A6S3BZw4+lCxPufQfTPiTVW70bWSQJWbgSTj8BVviZ/bXlKoJIYj/cxJpMm1D1J/5B bXPxokVUlHFiA== X-Virus-Scanned: amavis at mail.cs.ucla.edu Received: from mail.cs.ucla.edu ([127.0.0.1]) by localhost (mail.cs.ucla.edu [127.0.0.1]) (amavis, port 10026) with ESMTP id SEQtEXhpQJWN; Sat, 4 Jan 2025 21:59:30 -0800 (PST) Received: from wing.home (unknown [47.154.28.214]) by mail.cs.ucla.edu (Postfix) with ESMTPSA id 2411B3C082EB9; Sat, 4 Jan 2025 21:59:30 -0800 (PST) From: Paul Eggert To: libc-alpha@sourceware.org Cc: Paul Eggert Subject: [PATCH 30/59] Update tzname etc. even if TZ is unchanged Date: Sat, 4 Jan 2025 21:57:05 -0800 Message-ID: <20250105055750.1668721-31-eggert@cs.ucla.edu> X-Mailer: git-send-email 2.45.2 In-Reply-To: <01207110-bd60-46ae-9c08-fb39c2011067@cs.ucla.edu> References: <01207110-bd60-46ae-9c08-fb39c2011067@cs.ucla.edu> MIME-Version: 1.0 X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org POSIX says that external variables like tzname[0] are updated by tzset even if TZ has not changed. * time/tst-tzname.c: Include limits.h. (do_test): Test this. * time/tzset.c (tzset_internal): Update external vars even if TZ has not changed. When __tzfile_read succeeds, save its results. (__tzset_unlocked): Do not set __tzname here, as tzset_internal has already done it. --- time/tst-tzname.c | 85 ++++++++++++++++++++++++++++++++++++++++++++--- time/tzset.c | 30 +++++++++++------ 2 files changed, 100 insertions(+), 15 deletions(-) diff --git a/time/tst-tzname.c b/time/tst-tzname.c index b9b4aea35e..a70d5aee6a 100644 --- a/time/tst-tzname.c +++ b/time/tst-tzname.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -29,13 +30,87 @@ do_test (void) setenv ("TZ", TZDEFRULES, 1); tzset (); const char *stdtz = strdup (tzname[0]); - setenv ("TZ", "STD-1DST", 1); - tzset (); - if (strcmp (tzname[0], "STD") != 0) + + /* Test that proleptic TZ settings set tzname and other external vars. + Do not test geographic or empty settings, as POSIX does not require + external vars to be set for those cases. */ + struct tz_test + { + char const *tz; + int daylight; + long int timezone; + char const *tzname[2]; + } const tzs_to_test[] = { - printf ("FAIL: TZ=STD-1DST, tzname[0] = %s\n", tzname[0]); - result = 1; + { ":STD-1DST", 1, - 1 * 60 * 60, { "STD", "DST" } }, + { ":AST4ADT", 1, 4 * 60 * 60, { "AST", "ADT" } }, + { ":QQQ5RRR5", 1, 5 * 60 * 60, { "QQQ", "RRR" } }, + { ":NZST-12NZDT,M9.5.0,M4.1.0/3", 1, -12 * 60 * 60, { "NZST", "NZDT" } }, + { ":<-02>2<-01>,M3.5.0/-1,M10.5.0/0", 1, 2 * 60 * 60, { "-02", "-01" } }, + { ":UTC0", 0, 0, { "UTC", } }, + }; + for (int i = 0; i < sizeof tzs_to_test / sizeof *tzs_to_test; i++) + { + for (int j = 0; j < 2; j++) + { + char const *tz = tzs_to_test[i].tz + j; + if (setenv ("TZ", tz, 1) < 0) + { + printf ("FAIL: setenv (\"TZ\", \"%s\", 1)\n", tz); + result = 1; + continue; + } + + struct tm *tm; + for (int k = 0; k < 5; k++) + { + time_t t = 0; + daylight = INT_MIN; + timezone = LONG_MIN; + tzname[0] = tzname[1] = (char *) "XYZ"; + + char const *method; + switch (k) + { + case 0: + case 1: method = "tzset"; tzset (); break; + case 2: method = "localtime"; tm = localtime (&t); break; + case 3: method = "mktime", mktime (tm); break; + case 4: method = "ctime"; ctime (&t); break; + } + + if (daylight < 0 + || (daylight != 0) != tzs_to_test[i].daylight) + { + printf ("FAIL: TZ=%s, %s, daylight = %d\n", + tz, method, daylight); + result = 1; + } + if (timezone != tzs_to_test[i].timezone) + { + printf ("FAIL: TZ=%s, %s, timezone = %ld\n", + tz, method, timezone); + result = 1; + } + if (tzname[0] == NULL + || strcmp (tzname[0], tzs_to_test[i].tzname[0]) != 0) + { + printf ("FAIL: TZ=%s, %s, tzname[0] = %s\n", + tz, method, tzname[0] == NULL ? "(NULL)" : tzname[0]); + result = 1; + } + if (tzs_to_test[i].tzname[1] != NULL + && (tzname[1] == NULL + || strcmp (tzname[1], tzs_to_test[i].tzname[1]) != 0)) + { + printf ("FAIL: TZ=%s, %s, tzname[1] = %s\n", + tz, method, tzname[1] == NULL ? "(NULL)" : tzname[0]); + result = 1; + } + } + } } + setenv ("TZ", TZDEFRULES, 1); tzset (); if (strcmp (tzname[0], stdtz) != 0) diff --git a/time/tzset.c b/time/tzset.c index 1873ad205b..270383e383 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -125,6 +125,7 @@ __tzstring (const char *s) static char *old_tz; +/* Update POSIX-required external variables to their saved values. */ static void update_vars (void) { @@ -407,8 +408,11 @@ tzset_internal (int always) /* Check whether the value changed since the last run. */ if (old_tz != NULL && strcmp (tz, old_tz) == 0) - /* No change, simply return. */ - return; + { + /* No change, simply update external vars. */ + update_vars (); + return; + } /* Save the value of `tz'. */ free (old_tz); @@ -417,7 +421,20 @@ tzset_internal (int always) /* Try to read a data file. */ __tzfile_read (tz); if (__use_tzfile) - return; + { + /* Save equivalent of 'daylight' for later use by update_vars. + Although the other external variables have unspecified values + and so need not be saved in the usual case, save them anyway, + as POSIX requires this for the rare case of file-backed proleptic + TZ strings like "EST5EDT", and it is more likely to match user + expectations for geographical TZ strings. */ + enum tz_rule_type some_DST = J0; /* anything but NO_DST */ + tz_rules[1].type = NO_DST + __daylight * (some_DST - NO_DST); + tz_rules[0].offset = -__timezone; + tz_rules[0].name = __tzname[0]; + tz_rules[1].name = __tzname[1]; + return; + } /* No data file found. Default to UTC without leap seconds if TZDEFAULT is broken. */ @@ -545,13 +562,6 @@ void __tzset_unlocked (void) { tzset_internal (1); - - if (!__use_tzfile) - { - /* Set `tzname'. */ - __tzname[0] = (char *) tz_rules[0].name; - __tzname[1] = (char *) tz_rules[1].name; - } } void