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