From patchwork Tue Oct 1 12:14:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1991446 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Detos+jm; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XHxhw145Nz1xtY for ; Tue, 1 Oct 2024 22:15:12 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5787438425A5 for ; Tue, 1 Oct 2024 12:15:10 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id BFC4D386F472 for ; Tue, 1 Oct 2024 12:14:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BFC4D386F472 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BFC4D386F472 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784888; cv=none; b=oIYrFbf6cQ1Q47om1vnwubPBs2DTk9KNUlEo/shOf+8E4av9X3fLIVrSTEWiqxZuxcXhh76AFCXHo7u0/MeccD199fpP7vImOq+GKSIDSk6daoJrdyBAQQjcZm9JJm46SMohFbJgHWsLIX+LzDVJWMse7QCV+osBlAUBTjJbex8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784888; c=relaxed/simple; bh=oI3q/LLdIR/uu86imdn88+vTBSn5UOeI5/I1jauZb8c=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=hlWwPUk95KhTzbn54lHfLL6n+PWk5+AB+rbErvEqFGB4jpdNorHZ6kqfUSGa5S8EHU5cqaXKFKzMqWttIuyRAhSJ+oP7wrqd0Y2GWtFvLreLc2JCZ5fJPA1cC2v5r0sHqm5FOy3p8mi96aUP2PdeD9IcrXYvaMZGEyotsSo3bF0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1727784886; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=ems1+kHuptyniIwHPa33tBFKQBL1ZLNH+eyUaLh1Zn8=; b=Detos+jmabHbwBHILUBBk71RsDmyG7dpBbHCGBeuB6nkcptbptUaA1ffK8xstNx8M3sOEv 0atuMyMIcv/8kftXERWZUKyvltQ39jRYvXMzb/DYx3lCSvheUrIBFfVJDoM/HMV4Pp0Kf6 ObA1N5eRq91mLqPqFFUWChFkUi2MX2E= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-127-5gUO-rIAO4u2ANMjM6u9Wg-1; Tue, 01 Oct 2024 08:14:45 -0400 X-MC-Unique: 5gUO-rIAO4u2ANMjM6u9Wg-1 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (unknown [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 87567196A438 for ; Tue, 1 Oct 2024 12:14:44 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.45.224.151]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AECC81954B10 for ; Tue, 1 Oct 2024 12:14:43 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 1/4] time: Use a flag for localtime/gmtime operation in __mktime_internal In-Reply-To: Message-ID: <2730aa37cf1e652bccef60f100e72f5cf22eac03.1727784647.git.fweimer@redhat.com> References: X-From-Line: 2730aa37cf1e652bccef60f100e72f5cf22eac03 Mon Sep 17 00:00:00 2001 Date: Tue, 01 Oct 2024 14:14:40 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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~incoming=patchwork.ozlabs.org@sourceware.org This permits changing the implementation to an incompatible prototype by updating convert_time in mktime.c. --- time/mktime-internal.h | 9 +++--- time/mktime.c | 71 +++++++++++++++++++++--------------------- time/timegm.c | 2 +- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/time/mktime-internal.h b/time/mktime-internal.h index 0693aaf140..3e2848c121 100644 --- a/time/mktime-internal.h +++ b/time/mktime-internal.h @@ -71,9 +71,8 @@ typedef int mktime_offset_t; #endif /* Subroutine of mktime. Return the time_t representation of TP and - normalize TP, given that a struct tm * maps to a time_t as performed - by FUNC. Record next guess for localtime-gmtime offset in *OFFSET. */ -extern __time64_t __mktime_internal (struct tm *tp, - struct tm *(*func) (__time64_t const *, - struct tm *), + normalize TP, given that a struct tm * maps to a time_t. If + LOCAL, the mapping is performed by localtime_r, otherwise by gmtime_r. + Record next guess for localtime-gmtime offset in *OFFSET. */ +extern __time64_t __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset) attribute_hidden; diff --git a/time/mktime.c b/time/mktime.c index 7db1fd1aba..8196faa49c 100644 --- a/time/mktime.c +++ b/time/mktime.c @@ -250,29 +250,31 @@ tm_diff (long_int year, long_int yday, int hour, int min, int sec, tp->tm_hour, tp->tm_min, tp->tm_sec); } -/* Use CONVERT to convert T to a struct tm value in *TM. T must be in - range for __time64_t. Return TM if successful, NULL (setting errno) on - failure. */ +/* Convert T to a struct tm value in *TM. Use localtime64_r if LOCAL, + otherwise gmtime64_r. T must be in range for __time64_t. Return + TM if successful, NULL (setting errno) on failure. */ static struct tm * -convert_time (struct tm *(*convert) (const __time64_t *, struct tm *), - long_int t, struct tm *tm) +convert_time (bool local, long_int t, struct tm *tm) { __time64_t x = t; - return convert (&x, tm); + if (local) + return __localtime64_r (&x, tm); + else + return __gmtime64_r (&x, tm); } -/* Use CONVERT to convert *T to a broken down time in *TP. - If *T is out of range for conversion, adjust it so that - it is the nearest in-range value and then convert that. - A value is in range if it fits in both __time64_t and long_int. - Return TP on success, NULL (setting errno) on failure. */ +/* Convert *T to a broken down time in *TP (as if by localtime if + LOCAL, otherwise as if by gmtime). If *T is out of range for + conversion, adjust it so that it is the nearest in-range value and + then convert that. A value is in range if it fits in both + __time64_t and long_int. Return TP on success, NULL (setting + errno) on failure. */ static struct tm * -ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *), - long_int *t, struct tm *tp) +ranged_convert (bool local, long_int *t, struct tm *tp) { long_int t1 = (*t < mktime_min ? mktime_min : *t <= mktime_max ? *t : mktime_max); - struct tm *r = convert_time (convert, t1, tp); + struct tm *r = convert_time (local, t1, tp); if (r) { *t = t1; @@ -293,7 +295,7 @@ ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *), long_int mid = long_int_avg (ok, bad); if (mid == ok || mid == bad) break; - if (convert_time (convert, mid, tp)) + if (convert_time (local, mid, tp)) ok = mid, oktm = *tp; else if (errno != EOVERFLOW) return NULL; @@ -309,29 +311,28 @@ ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *), } -/* Convert *TP to a __time64_t value, inverting - the monotonic and mostly-unit-linear conversion function CONVERT. - Use *OFFSET to keep track of a guess at the offset of the result, +/* Convert *TP to a __time64_t value. If LOCAL, the reverse mapping + is performed as if localtime, otherwise as if by gmtime. Use + *OFFSET to keep track of a guess at the offset of the result, compared to what the result would be for UTC without leap seconds. - If *OFFSET's guess is correct, only one CONVERT call is needed. - If successful, set *TP to the canonicalized struct tm; + If *OFFSET's guess is correct, only one reverse mapping call is + needed. If successful, set *TP to the canonicalized struct tm; otherwise leave *TP alone, return ((time_t) -1) and set errno. This function is external because it is used also by timegm.c. */ __time64_t -__mktime_internal (struct tm *tp, - struct tm *(*convert) (const __time64_t *, struct tm *), - mktime_offset_t *offset) +__mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset) { struct tm tm; - /* The maximum number of probes (calls to CONVERT) should be enough - to handle any combinations of time zone rule changes, solar time, - leap seconds, and oscillations around a spring-forward gap. - POSIX.1 prohibits leap seconds, but some hosts have them anyway. */ + /* The maximum number of probes should be enough to handle any + combinations of time zone rule changes, solar time, leap seconds, + and oscillations around a spring-forward gap. POSIX.1 prohibits + leap seconds, but some hosts have them anyway. */ int remaining_probes = 6; - /* Time requested. Copy it in case CONVERT modifies *TP; this can - occur if TP is localtime's returned value and CONVERT is localtime. */ + /* Time requested. Copy it in case gmtime/localtime modify *TP; + this can occur if TP is localtime's returned value and CONVERT is + localtime. */ int sec = tp->tm_sec; int min = tp->tm_min; int hour = tp->tm_hour; @@ -389,7 +390,7 @@ __mktime_internal (struct tm *tp, while (true) { - if (! ranged_convert (convert, &t, &tm)) + if (! ranged_convert (local, &t, &tm)) return -1; long_int dt = tm_diff (year, yday, hour, min, sec, &tm); if (dt == 0) @@ -468,7 +469,7 @@ __mktime_internal (struct tm *tp, if (! INT_ADD_WRAPV (t, delta * direction, &ot)) { struct tm otm; - if (! ranged_convert (convert, &ot, &otm)) + if (! ranged_convert (local, &ot, &otm)) return -1; if (! isdst_differ (isdst, otm.tm_isdst)) { @@ -478,7 +479,7 @@ __mktime_internal (struct tm *tp, &otm); if (mktime_min <= gt && gt <= mktime_max) { - if (convert_time (convert, gt, &tm)) + if (convert_time (local, gt, &tm)) { t = gt; goto offset_found; @@ -492,7 +493,7 @@ __mktime_internal (struct tm *tp, /* No unusual DST offset was found nearby. Assume one-hour DST. */ t += 60 * 60 * dst_difference; - if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm)) + if (mktime_min <= t && t <= mktime_max && convert_time (local, t, &tm)) goto offset_found; __set_errno (EOVERFLOW); @@ -519,7 +520,7 @@ __mktime_internal (struct tm *tp, __set_errno (EOVERFLOW); return -1; } - if (! convert_time (convert, t, &tm)) + if (! convert_time (local, t, &tm)) return -1; } @@ -542,7 +543,7 @@ __mktime64 (struct tm *tp) # if defined _LIBC || NEED_MKTIME_WORKING static mktime_offset_t localtime_offset; - return __mktime_internal (tp, __localtime64_r, &localtime_offset); + return __mktime_internal (tp, true, &localtime_offset); # else # undef mktime return mktime (tp); diff --git a/time/timegm.c b/time/timegm.c index e5cf30c019..1f1f66c61b 100644 --- a/time/timegm.c +++ b/time/timegm.c @@ -31,7 +31,7 @@ __timegm64 (struct tm *tmp) { static mktime_offset_t gmtime_offset; tmp->tm_isdst = 0; - return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset); + return __mktime_internal (tmp, false, &gmtime_offset); } #if defined _LIBC && __TIMESIZE != 64 From patchwork Tue Oct 1 12:14:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1991447 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=HvkX1Tsq; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XHxj94nSkz1xtY for ; Tue, 1 Oct 2024 22:15:25 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 79462386F464 for ; Tue, 1 Oct 2024 12:15:23 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 3FB9F386D60B for ; Tue, 1 Oct 2024 12:14:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3FB9F386D60B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3FB9F386D60B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784899; cv=none; b=UGpauFG6fU++s10O9n3VlQTkaJLGxUEYiYyUeuYaQBkfGYhK6kYxQSjs8/Hbm0v4hzZs87iiJO0u80hSnVxKHtPALFoIHzOfeWt0Wi5Kd84fyEtQ8mzjB3FaAIew7Kruh2d1SHFREqqmOIIr/IXxCsg8yZNwJk8Wu4iJDGVzx7A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784899; c=relaxed/simple; bh=LZWftjp30i5unpc2jGd03sikZuHquHYMmB/DSEKTwyc=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=OAbjfIvxyHVCJjAzF4XnPoNCYcygpYvUcxPp/4US5SbuUcGkX3D+NYYFVq0yxuh2wnUpwfYaDYXr37p22JrUhYOqClbABnML0EUNsIJQr0wczGon9yS/d1SyQ3MMKvTdV/PczfhLtiKUCa9Gu/JgwFppDNhpwh8Zz3zF57KtiHs= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1727784896; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=UuFkKTfJYMW3UkTiDtzbOw7UkH6blNh/WPKXRRlPpV0=; b=HvkX1TsqQF6KDOoYpu9jZ9BbriWFD8LG+DL3VjhJyfGHWHCv9gXqBHeSytvbJx8f1dob+f oSHZvFdeoEgdPkKh+ITlpTqJT0u3gJtS7g+zFthBT4hjH7TyQLXEKsxPU3sOQKcoV8QSMz 0OCeFKSdWo9dstGWJvcjS3T8R56/Hb4= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-214-Y6Uuwi7tMVWwuoygmO9FjA-1; Tue, 01 Oct 2024 08:14:54 -0400 X-MC-Unique: Y6Uuwi7tMVWwuoygmO9FjA-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (unknown [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BCDE0196D199 for ; Tue, 1 Oct 2024 12:14:53 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.45.224.151]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CA1F71979066 for ; Tue, 1 Oct 2024 12:14:52 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 2/4] time: Push tzset lock into callers of time functions In-Reply-To: Message-ID: <1bd8c60cfeecff73b7183c7dc3699f55c71c629c.1727784647.git.fweimer@redhat.com> References: X-From-Line: 1bd8c60cfeecff73b7183c7dc3699f55c71c629c Mon Sep 17 00:00:00 2001 Date: Tue, 01 Oct 2024 14:14:49 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-22.9 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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~incoming=patchwork.ozlabs.org@sourceware.org This fixes a harmless data race on the cached offset used by __mktime_internal. --- include/time.h | 23 ----------------------- time/gmtime.c | 8 ++++++-- time/localtime.c | 8 ++++++-- time/mktime-internal.h | 4 +++- time/mktime.c | 36 +++++++++++++++++++++++++++++------- time/strftime_l.c | 1 + time/timegm.c | 11 +++++++++++ time/tzfile.c | 1 + time/tzset.c | 20 ++++++++++++-------- time/tzset.h | 34 ++++++++++++++++++++++++++++++++++ 10 files changed, 103 insertions(+), 43 deletions(-) create mode 100644 time/tzset.h diff --git a/include/time.h b/include/time.h index f599eeed4e..e9c083646a 100644 --- a/include/time.h +++ b/include/time.h @@ -49,24 +49,6 @@ extern const unsigned short int __mon_yday[2][13] attribute_hidden; /* Defined in localtime.c. */ extern struct tm _tmbuf attribute_hidden; -/* Defined in tzset.c. */ -extern char *__tzstring (const char *string) attribute_hidden; - -extern int __use_tzfile attribute_hidden; - -extern void __tzfile_read (const char *file, size_t extra, - char **extrap) attribute_hidden; -extern void __tzfile_compute (__time64_t timer, int use_localtime, - long int *leap_correct, int *leap_hit, - struct tm *tp) attribute_hidden; -extern void __tzfile_default (const char *std, const char *dst, - int stdoff, int dstoff) - attribute_hidden; -extern void __tzset_parse_tz (const char *tz) attribute_hidden; -extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime) - __THROW attribute_hidden; - - #if __TIMESIZE == 64 # define __itimerspec64 itimerspec #else @@ -275,11 +257,6 @@ extern int __offtime (__time64_t __timer, extern char *__asctime_r (const struct tm *__tp, char *__buf) attribute_hidden; -extern void __tzset (void) attribute_hidden; - -/* Prototype for the internal function to get information based on TZ. */ -extern struct tm *__tz_convert (__time64_t timer, int use_localtime, - struct tm *tp) attribute_hidden; extern int __nanosleep (const struct timespec *__requested_time, struct timespec *__remaining); diff --git a/time/gmtime.c b/time/gmtime.c index 9f39c36bd8..ad8fc48966 100644 --- a/time/gmtime.c +++ b/time/gmtime.c @@ -17,13 +17,17 @@ . */ #include +#include /* Return the `struct tm' representation of *T in UTC, using *TP to store the result. */ struct tm * __gmtime64_r (const __time64_t *t, struct tm *tp) { - return __tz_convert (*t, 0, tp); + __libc_lock_lock (__tzset_lock); + struct tm *result = __tz_convert (*t, 0, tp); + __libc_lock_unlock (__tzset_lock); + return result; } /* Provide a 32-bit variant if needed. */ @@ -48,7 +52,7 @@ weak_alias (__gmtime_r, gmtime_r) struct tm * __gmtime64 (const __time64_t *t) { - return __tz_convert (*t, 0, &_tmbuf); + return __gmtime64_r (t, &_tmbuf); } /* Provide a 32-bit variant if needed. */ diff --git a/time/localtime.c b/time/localtime.c index 77d19ff5e7..f19d552673 100644 --- a/time/localtime.c +++ b/time/localtime.c @@ -17,6 +17,7 @@ . */ #include +#include /* C89 says that localtime and gmtime return the same pointer. Although C99 and later relax this to let localtime and gmtime @@ -30,7 +31,10 @@ struct tm _tmbuf; struct tm * __localtime64_r (const __time64_t *t, struct tm *tp) { - return __tz_convert (*t, 1, tp); + __libc_lock_lock (__tzset_lock); + struct tm *result = __tz_convert (*t, 1, tp); + __libc_lock_unlock (__tzset_lock); + return result; } /* Provide a 32-bit variant if needed. */ @@ -54,7 +58,7 @@ weak_alias (__localtime_r, localtime_r) struct tm * __localtime64 (const __time64_t *t) { - return __tz_convert (*t, 1, &_tmbuf); + return __localtime64_r (t, &_tmbuf); } libc_hidden_def (__localtime64) diff --git a/time/mktime-internal.h b/time/mktime-internal.h index 3e2848c121..93299effc3 100644 --- a/time/mktime-internal.h +++ b/time/mktime-internal.h @@ -73,6 +73,8 @@ typedef int mktime_offset_t; /* Subroutine of mktime. Return the time_t representation of TP and normalize TP, given that a struct tm * maps to a time_t. If LOCAL, the mapping is performed by localtime_r, otherwise by gmtime_r. - Record next guess for localtime-gmtime offset in *OFFSET. */ + Record next guess for localtime-gmtime offset in *OFFSET. + + If _LIBC, the caller must lock __tzset_lock. */ extern __time64_t __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset) attribute_hidden; diff --git a/time/mktime.c b/time/mktime.c index 8196faa49c..669bc46c34 100644 --- a/time/mktime.c +++ b/time/mktime.c @@ -42,6 +42,9 @@ #endif #include +#ifdef _LIBC +# include +#endif #include #include @@ -256,11 +259,15 @@ tm_diff (long_int year, long_int yday, int hour, int min, int sec, static struct tm * convert_time (bool local, long_int t, struct tm *tm) { +#ifdef _LIBC + return __tz_convert (t, local, tm); +#else __time64_t x = t; if (local) return __localtime64_r (&x, tm); else return __gmtime64_r (&x, tm); +#endif } /* Convert *T to a broken down time in *TP (as if by localtime if @@ -318,7 +325,9 @@ ranged_convert (bool local, long_int *t, struct tm *tp) If *OFFSET's guess is correct, only one reverse mapping call is needed. If successful, set *TP to the canonicalized struct tm; otherwise leave *TP alone, return ((time_t) -1) and set errno. - This function is external because it is used also by timegm.c. */ + This function is external because it is used also by timegm.c. + + If _LIBC, the caller must lock __tzset_lock. */ __time64_t __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset) { @@ -530,7 +539,19 @@ __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset) #endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */ -#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS +#ifdef _LIBC +__time64_t +__mktime64 (struct tm *tp) +{ + __libc_lock_lock (__tzset_lock); + __tzset_unlocked (); + static mktime_offset_t localtime_offset; + __time64_t result = __mktime_internal (tp, true, &localtime_offset); + __libc_lock_unlock (__tzset_lock); + return result; +} +#else /* !_LIBC */ +# if defined NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS /* Convert *TP to a __time64_t value. */ __time64_t @@ -541,15 +562,16 @@ __mktime64 (struct tm *tp) be set as if the tzset() function had been called. */ __tzset (); -# if defined _LIBC || NEED_MKTIME_WORKING +# ifdef NEED_MKTIME_WORKING static mktime_offset_t localtime_offset; return __mktime_internal (tp, true, &localtime_offset); -# else -# undef mktime +# else +# undef mktime return mktime (tp); -# endif +# endif } -#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */ +# endif /* NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */ +#endif /* !_LIBC */ #if defined _LIBC && __TIMESIZE != 64 diff --git a/time/strftime_l.c b/time/strftime_l.c index 77adec9050..e5c5d5fc60 100644 --- a/time/strftime_l.c +++ b/time/strftime_l.c @@ -33,6 +33,7 @@ # define MULTIBYTE_IS_FORMAT_SAFE 1 # define STDC_HEADERS 1 # include "../locale/localeinfo.h" +# include #endif #if defined emacs && !defined HAVE_BCOPY diff --git a/time/timegm.c b/time/timegm.c index 1f1f66c61b..4dda728ae3 100644 --- a/time/timegm.c +++ b/time/timegm.c @@ -24,6 +24,10 @@ #include #include +#ifdef _LIBC +# include +#endif + #include "mktime-internal.h" __time64_t @@ -31,7 +35,14 @@ __timegm64 (struct tm *tmp) { static mktime_offset_t gmtime_offset; tmp->tm_isdst = 0; +#ifdef _LIBC + __libc_lock_lock (__tzset_lock); + __time64_t result = __mktime_internal (tmp, false, &gmtime_offset); + __libc_lock_unlock (__tzset_lock); + return result; +#else return __mktime_internal (tmp, false, &gmtime_offset); +#endif } #if defined _LIBC && __TIMESIZE != 64 diff --git a/time/tzfile.c b/time/tzfile.c index 964a9b7f12..5d4a6054df 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -27,6 +27,7 @@ #include #include #include +#include #include diff --git a/time/tzset.c b/time/tzset.c index 98a7064970..b0a0bcf68f 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -16,13 +16,13 @@ . */ #include -#include #include #include #include #include #include #include +#include #include @@ -37,7 +37,7 @@ weak_alias (__daylight, daylight) weak_alias (__timezone, timezone) /* This locks all the state variables in tzfile.c and this file. */ -__libc_lock_define_initialized (static, tzset_lock) +__libc_lock_define_initialized (, __tzset_lock) /* This structure contains all the information about a timezone given in the POSIX standard TZ envariable. */ @@ -544,9 +544,8 @@ __tz_compute (__time64_t timer, struct tm *tm, int use_localtime) #undef tzset void -__tzset (void) +__tzset_unlocked (void) { - __libc_lock_lock (tzset_lock); tzset_internal (1); @@ -557,8 +556,16 @@ __tzset (void) __tzname[1] = (char *) tz_rules[1].name; } - __libc_lock_unlock (tzset_lock); } + +void +__tzset (void) +{ + __libc_lock_lock (__tzset_lock); + __tzset_unlocked (); + __libc_lock_unlock (__tzset_lock); +} + weak_alias (__tzset, tzset) /* Return the `struct tm' representation of TIMER in the local timezone. @@ -569,7 +576,6 @@ __tz_convert (__time64_t timer, int use_localtime, struct tm *tp) long int leap_correction; int leap_extra_secs; - __libc_lock_lock (tzset_lock); /* Update internal database according to current TZ setting. POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname. @@ -589,8 +595,6 @@ __tz_convert (__time64_t timer, int use_localtime, struct tm *tp) leap_extra_secs = 0; } - __libc_lock_unlock (tzset_lock); - if (tp) { if (! use_localtime) diff --git a/time/tzset.h b/time/tzset.h new file mode 100644 index 0000000000..254540aa05 --- /dev/null +++ b/time/tzset.h @@ -0,0 +1,34 @@ +#ifndef _TZSET_H +#define _TZSET_H + +#include +#include + +/* Defined in tzset.c. */ +extern char *__tzstring (const char *string) attribute_hidden; + +extern int __use_tzfile attribute_hidden; + +extern void __tzfile_read (const char *file, size_t extra, + char **extrap) attribute_hidden; +extern void __tzfile_compute (__time64_t timer, int use_localtime, + long int *leap_correct, int *leap_hit, + struct tm *tp) attribute_hidden; +extern void __tzfile_default (const char *std, const char *dst, + int stdoff, int dstoff) + attribute_hidden; +extern void __tzset_parse_tz (const char *tz) attribute_hidden; +extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime) + __THROW attribute_hidden; + +__libc_lock_define (extern, __tzset_lock attribute_hidden); + +extern void __tzset (void) attribute_hidden; +extern void __tzset_unlocked (void) attribute_hidden; + +/* Prototype for the internal function to get information based on TZ. + Caller needs to lock __tzset_lock. */ +extern struct tm *__tz_convert (__time64_t timer, int use_localtime, + struct tm *tp) attribute_hidden; + +#endif /* _TZSET_H */ From patchwork Tue Oct 1 12:14:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1991448 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=E811d9cN; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XHxkC290Lz1xtY for ; Tue, 1 Oct 2024 22:16:19 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1F2B03842FEF for ; Tue, 1 Oct 2024 12:16:17 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 1360F3842FEF for ; Tue, 1 Oct 2024 12:15:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1360F3842FEF Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1360F3842FEF Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784909; cv=none; b=sR/U0dqo2DJ948KiodtSMTGVdFizJoX0g5O+jhbWWtaXUSbLcrIJTnht509AE7705agTNdsXcW/Z/IIdDAw/XvIGuKaZ0pcXc0ZaP1Rdn8c+UgNSMWxe90JC21HuczPi6Jxo3u5QsmmeG0MxcstcrtxNjRlu+NuPdkgHfNfBXgc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784909; c=relaxed/simple; bh=fZBf1Z/DdcCTXSmADwKYsycEKQDnNxeye/iXqXG7zH8=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=rWAP5K4PHeq7fH9DFQS1ibD7+zQn4OoBXGwRS/vVyvzCVoUDodCdpfkOUQslvE2oyey9I2MQk+fFjenq4gpRa5mf7kmlaxuMnUvhIPwmrZ62Ju3V9ZKHQdJGyYtTVQJMwdSKwfEPwT9QOi+10e8K1rzuvHC9sTAJupxbX4YXb5s= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1727784904; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=SQaQCQie7AEJu7IB7m//X1lz211LAw6bsrBdyDA6OpA=; b=E811d9cNXNWKF9C72w46yb7wxd/3BMTFNuyeV3PJ/xKRS2jMYNF9tMKrK842MYylYeGics Rlm3rirG582b1NujCD0+H2EIe7jEBakVa6gV9vsY+aX1tgXmQ98ktmXN8VbaO/zwkqPUKD FKmiEkNno5C8V1J5wH9VoaP2uLOpSJg= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-475-iAfmMXBTNMaUdCAY_iNr1Q-1; Tue, 01 Oct 2024 08:15:03 -0400 X-MC-Unique: iAfmMXBTNMaUdCAY_iNr1Q-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (unknown [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C084119626E2 for ; Tue, 1 Oct 2024 12:15:02 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.45.224.151]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DF9F13003E4D for ; Tue, 1 Oct 2024 12:15:01 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 3/4] time: Do not perform forced DST adjustment for DST-less zones In-Reply-To: Message-ID: <435ebea3d916f61759f8f3f3424365e2ccd5e810.1727784647.git.fweimer@redhat.com> References: X-From-Line: 435ebea3d916f61759f8f3f3424365e2ccd5e810 Mon Sep 17 00:00:00 2001 Date: Tue, 01 Oct 2024 14:14:58 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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~incoming=patchwork.ozlabs.org@sourceware.org For zones such as UTC, it does not really make sense to perform the forced adjustment. The timezone/testdata/IST file is the compiled Asia/Kolkata zone from tz 2024a. --- manual/time.texi | 41 ++++++++- time/Makefile | 1 + time/mktime.c | 8 +- time/tst-mktime-dst-adjust.c | 156 +++++++++++++++++++++++++++++++++++ timezone/testdata/IST | Bin 0 -> 285 bytes 5 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 time/tst-mktime-dst-adjust.c create mode 100644 timezone/testdata/IST GIT binary patch literal 285 zcmWHE%1kq2zzf(I7#LU>7#M^a7#JAZ=kD2c>UNLD8P-CHGgFOLTq+To!N|nS#LUFN z5Of1%j<*{~wQmFi2LnTN1|yG;ZwQ00ZwP~Da0r98ftj%ZLkM9z*%=rZSQ!`?#Qy*P z|6gsFga(Lqe*W43M1$M_qCxHe(IB^g>8VC5Ks3}%EX*v-Fh>Pl06EIr4df`_2nHUo W(*!_H^T2Q(muGN@uBnx=0T%#v+DeN6 literal 0 HcmV?d00001 diff --git a/manual/time.texi b/manual/time.texi index 64aad8fdc5..c72febc7c6 100644 --- a/manual/time.texi +++ b/manual/time.texi @@ -1075,9 +1075,16 @@ This is a flag that indicates whether daylight saving time is (or was, or will be) in effect at the time described. The value is positive if daylight saving time is in effect, zero if it is not, and negative if the information is not available. -Although this flag is useful when passing a broken-down time to the -@code{mktime} function, for other uses this flag should be ignored and -the @code{tm_gmtoff} and @code{tm_zone} fields should be inspected instead. + +It is recommended to set this field to a negative value when calling +@code{mktime} unless the application has access to the correct value of +the daylight saving time status at the specified time. This instructs +@code{mktime} to use time zone data to determine whether or not to apply +daylight saving time. + +Reading the @code{tm_isdst} field after calling @code{localtime} +and similar functions is not recommended. Instead inspect the +the @code{tm_gmtoff} and @code{tm_zone} fields. @item long int tm_gmtoff This field describes the time zone that was used to compute this @@ -1292,6 +1299,33 @@ simple time representation. It also normalizes the contents of the broken-down time structure, and fills in some components based on the values of the others. +In general, it is recommended to set the @code{tm_isdst} member of +@var{brokentime} to a negative value prior to calling this function. +However, if @code{*@var{brokentime}} was produced by @code{localtime} or +similar functions, a correct value of @code{tm_isdst} allows to +disambiguate broken-down time representations during the overlapping +window after time jumped back during a daylight saving time transition. +This is a scenario where @code{tm_isdst} can be helpful, and the +adjustment described below does not produce unexpected @code{mktime} +results. + +If @code{tm_isdst} is negative, @code{mktime} uses time zone data to +determine whether daylight saving time is in effect at the requested +time. + +In the other case, @code{tm_isdst} is not negative: the value zero +indicates that no daylight saving time is in effect, and positive value +means it is in effect. If time zone data and the @code{tm_isdst} flag +disagree, @code{mktime} will forcefully adjust the returned value, using +an unspecified heuristic to obtain the daylight saving time offset. +Typically, this means that @code{mktime} adds one hour if +@code{tm_isdst} is zero, or subtracts one hour if @code{tm_isdst} is +positive. This forced adjustment only happens if time zone data +indicates that there is at least one daylight saving transition (at any +time). For zones such as @samp{UTC} which never use daylight saving +time, the adjustment does not happen even if @code{tm_isdst} is +positive. + The @code{mktime} function ignores the specified contents of the @code{tm_wday}, @code{tm_yday}, @code{tm_gmtoff}, and @code{tm_zone} members of the broken-down time @@ -1342,6 +1376,7 @@ available. @code{timelocal} is rather rare. @c tzfile_compute(!use_localtime) ok @code{timegm} is functionally identical to @code{mktime} except it +sets @code{@var{brokentime}->tm_isdst} to zero and always takes the input values to be UTC regardless of any local time zone setting. diff --git a/time/Makefile b/time/Makefile index d06797b06c..0cfc4c9d51 100644 --- a/time/Makefile +++ b/time/Makefile @@ -64,6 +64,7 @@ tests := \ tst-gmtime \ tst-itimer \ tst-mktime \ + tst-mktime-dst-adjust \ tst-mktime2 \ tst-mktime3 \ tst-mktime4 \ diff --git a/time/mktime.c b/time/mktime.c index 669bc46c34..ad371ba57f 100644 --- a/time/mktime.c +++ b/time/mktime.c @@ -433,7 +433,13 @@ __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset) /* We have a match. Check whether tm.tm_isdst has the requested value, if any. */ - if (isdst_differ (isdst, tm.tm_isdst)) + if (isdst_differ (isdst, tm.tm_isdst) +#if _LIBC + /* Only perform the adjustment if the time zone ever uses DST. + This skips the adjustment for UTC, for example. */ + && __daylight +#endif + ) { /* tm.tm_isdst has the wrong value. Look for a neighboring time with the right value, and use its UTC offset. diff --git a/time/tst-mktime-dst-adjust.c b/time/tst-mktime-dst-adjust.c new file mode 100644 index 0000000000..416ef2abcd --- /dev/null +++ b/time/tst-mktime-dst-adjust.c @@ -0,0 +1,156 @@ +/* Test mktime DST adjustment special cases. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +static int +do_test (void) +{ + TEST_COMPARE (setenv ("TZ", "UTC", 1), 0); + + { + struct tm t = + { + .tm_year = 124, + .tm_mon = 9, + .tm_mday = 1, + .tm_hour = 9, + .tm_min = 20, + .tm_sec = 53, + .tm_isdst = 1, /* Not actually true. */ + }; + TEST_COMPARE (mktime (&t), 1727774453); + } + + /* IST used DST at one point, but no longer does. */ + { + char *path = realpath ("../timezone/testdata/IST", NULL); + TEST_VERIFY (path != NULL); + TEST_COMPARE (setenv ("TZ", path, 1), 0); + free (path); + } + + { + struct tm t = + { + .tm_year = 124, + .tm_mon = 9, + .tm_mday = 1, + .tm_hour = 9, + .tm_min = 20, + .tm_sec = 53, + .tm_isdst = 0, /* Correct value. */ + }; + TEST_COMPARE (mktime (&t), 1727774453 - (int) (5.5 * 3600)); + TEST_COMPARE (t.tm_gmtoff, (int) (5.5 * 3600)); + TEST_COMPARE (t.tm_isdst, 0); + } + + /* This value is incorrect, but the heuristic ignores historic + DST changes. */ + { + struct tm t = + { + .tm_year = 124, + .tm_mon = 9, + .tm_mday = 1, + .tm_hour = 9, + .tm_min = 20, + .tm_sec = 53, + .tm_isdst = 1, /* Incorrect value. */ + }; + TEST_COMPARE (mktime (&t), 1727774453 - (int) (5.5 * 3600)); + TEST_COMPARE (t.tm_gmtoff, (int) (5.5 * 3600)); + TEST_COMPARE (t.tm_isdst, 0); + } + + /* Test using correct DST. */ + { + struct tm t = + { + .tm_year = 42, + .tm_mon = 9, + .tm_mday = 1, + .tm_hour = 9, + .tm_min = 20, + .tm_sec = 53, + .tm_isdst = 1, /* Correct value, DST was in effect. */ + }; + TEST_COMPARE (mktime (&t), -860015347); + TEST_COMPARE (t.tm_gmtoff, (int) (6.5 * 3600)); + TEST_COMPARE (t.tm_isdst, 1); + } + + /* Mismatch: DST incorrectly claimed not in effect. */ + + { + struct tm t = + { + .tm_year = 42, + .tm_mon = 9, + .tm_mday = 1, + .tm_hour = 9, + .tm_min = 20, + .tm_sec = 53, + .tm_isdst = 0, /* Incorrect value. */ + }; + TEST_COMPARE (mktime (&t), -860015347 + 3600); /* One hour added. */ + TEST_COMPARE (t.tm_gmtoff, (int) (6.5 * 3600)); + TEST_COMPARE (t.tm_isdst, 1); + } + + /* Test using correct standard time. */ + { + struct tm t = + { + .tm_year = 42, + .tm_mon = 7, + .tm_mday = 1, + .tm_hour = 9, + .tm_min = 20, + .tm_sec = 53, + .tm_isdst = 0, /* Correct value, standard time in effect. */ + }; + TEST_COMPARE (mktime (&t), -865282147); + TEST_COMPARE (t.tm_gmtoff, (int) (5.5 * 3600)); + TEST_COMPARE (t.tm_isdst, 0); + } + + /* Test using standard time with mismatch. */ + { + struct tm t = + { + .tm_year = 42, + .tm_mon = 7, + .tm_mday = 1, + .tm_hour = 9, + .tm_min = 20, + .tm_sec = 53, + .tm_isdst = 1, /* Incorrect value. */ + }; + TEST_COMPARE (mktime (&t), -865282147 - 3600); /* One hour subtracted. */ + TEST_COMPARE (t.tm_gmtoff, (int) (5.5 * 3600)); + TEST_COMPARE (t.tm_isdst, 0); + } + + return 0; +} + +#include diff --git a/timezone/testdata/IST b/timezone/testdata/IST new file mode 100644 index 0000000000000000000000000000000000000000..0014046d29a38e9b8006f746fea794d7f71eb479 From patchwork Tue Oct 1 12:15:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1991449 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Im6FNyF8; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XHxkx2lNHz1xtY for ; Tue, 1 Oct 2024 22:16:57 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 28655386D626 for ; Tue, 1 Oct 2024 12:16:55 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id D0084386D600 for ; Tue, 1 Oct 2024 12:15:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D0084386D600 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D0084386D600 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784921; cv=none; b=Z3/t1KRx6V9dFJfaoFka/a3Yd4/MT5o9zYBsO+8yJJod+HDDxrRoFeUr58Tga2v2AGThi+mfIMCvBQuGsUP4VLhagevJVJo12qavqfGpJqKWXyzlSLP65Ah0Bf98+v/C9yipj+nruktFtqiEoIXxMF7kumYp1qNL6RHqory1aXg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727784921; c=relaxed/simple; bh=6/spxjblpTA7VSuxy1n2UbYR4JpjZFNe/0XAqjR3uRg=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=cmz7mgyso54y+6iYfKX+tmOA5D+cLSIRCqvuk/xANnBjON+tA3LN7p9UIy+Uq9SAmXsu0VeKOqzfRoaRV2xERcY9JbkpXkRG+kYYjLSu83fBLMw1eU2K2ObbtNYz/KGR3MpG6j5ahVTVnZ8l5anCduVQX1j5k6plmgm9zLZ6q+Q= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1727784917; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=m4KjOQYzUegdv8iQVSs4eNw4ehmznF5atY4DiTEmoo8=; b=Im6FNyF85Adv1cPZlYjzH5ZdbrwqxOzlzsbniIhM/4bdl5TFuapxZKwMSkLAEHb6RN+Nba 7WpNcohu962ZNz+2Aqb98EPDOTbXVGJ3ELRT3kUhyzAc45AM+A2QZphDXAi+x1otKgtPlY lttbou/v/eAXmeKE4Og3RXNfcEPgeoQ= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-606-QPAlzWCjPpqEGCDIfX4Flg-1; Tue, 01 Oct 2024 08:15:15 -0400 X-MC-Unique: QPAlzWCjPpqEGCDIfX4Flg-1 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (unknown [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1CA3C1943CCC for ; Tue, 1 Oct 2024 12:15:15 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.45.224.151]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3A7321944B2B for ; Tue, 1 Oct 2024 12:15:13 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 4/4] time: Implement the glibc.time.mktime_dst_adjustment tunable In-Reply-To: Message-ID: <4b54ff2cd98520b5e1bf31da5b3ec0a2713ad3b3.1727784647.git.fweimer@redhat.com> References: X-From-Line: 4b54ff2cd98520b5e1bf31da5b3ec0a2713ad3b3 Mon Sep 17 00:00:00 2001 Date: Tue, 01 Oct 2024 14:15:11 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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~incoming=patchwork.ozlabs.org@sourceware.org It helps with upgrades from older glibc versions (prior to 2.29) which performed DST adjustments in fewer cases. --- elf/dl-tunables.list | 9 ++ elf/libc_early_init.c | 3 + manual/time.texi | 3 +- manual/tunables.texi | 12 +++ time/Makefile | 7 +- time/mktime.c | 8 +- time/time-tunables.c | 29 +++++++ time/tst-mktime-dst-adjust-0.c | 154 +++++++++++++++++++++++++++++++++ time/tst-mktime-dst-adjust-1.c | 2 + time/tzset.h | 6 ++ 10 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 time/time-tunables.c create mode 100644 time/tst-mktime-dst-adjust-0.c create mode 100644 time/tst-mktime-dst-adjust-1.c diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list index 40ac5b3776..af3eb4a37c 100644 --- a/elf/dl-tunables.list +++ b/elf/dl-tunables.list @@ -84,6 +84,15 @@ glibc { } } + time { + mktime_dst_adjustment { + type: INT_32 + minval: 0 + maxval: 1 + default: 1 + } + } + elision { enable { type: INT_32 diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c index 575b837f8f..f99f12b6c8 100644 --- a/elf/libc_early_init.c +++ b/elf/libc_early_init.c @@ -23,6 +23,7 @@ #include #include #include +#include