From 13e9b94279bd249566de3097636d6a72d8f6f769 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Wed, 4 Sep 2024 19:38:52 +0200 Subject: [PATCH] Resolve conflicts for functions introduced in Android API level 35. Reported by Po Lu in . * lib/time.in.h (timezone_t, tzalloc, tzfree): Don't require _GNU_SOURCE to be defined. Define depending on HAVE_TZALLOC, not HAVE_TIMEZONE_T. (localtime_rz, mktime_z): Likewise. Override if REPLACE_LOCALTIME_RZ or REPLACE_MKTIME_Z is 1, respectively. * lib/time_rz.c: If NEED_TIMEZONE_NULL_SUPPORT, define only localtime_rz and mktime_z and only as wrappers around the system function. * m4/time_h.m4 (gl_TIME_H_DEFAULTS): Initialize HAVE_TZALLOC, REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. * m4/time_rz.m4 (gl_TIME_RZ): Conditionally set HAVE_TZALLOC, REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. Conditionally define NEED_TIMEZONE_NULL_SUPPORT. * modules/time-h (Makefile.am): Substitute HAVE_TZALLOC, REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. * modules/time_rz (Depends-on, configure.ac): Consider HAVE_TZALLOC, REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. Ignore HAVE_TIMEZONE_T. --- ChangeLog | 18 ++++++++++++ lib/time.in.h | 45 +++++++++++++++++++++++++++++- lib/time_rz.c | 73 +++++++++++++++++++++++++++++++++---------------- m4/time_h.m4 | 7 +++-- m4/time_rz.m4 | 28 ++++++++++++++++++- modules/time-h | 3 ++ modules/time_rz | 19 +++++++------ 7 files changed, 157 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index f70472d1ed..c37edcf497 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,24 @@ Resolve conflicts for functions introduced in Android API level 35. + Reported by Po Lu in + . + * lib/time.in.h (timezone_t, tzalloc, tzfree): Don't require _GNU_SOURCE + to be defined. Define depending on HAVE_TZALLOC, not HAVE_TIMEZONE_T. + (localtime_rz, mktime_z): Likewise. Override if REPLACE_LOCALTIME_RZ or + REPLACE_MKTIME_Z is 1, respectively. + * lib/time_rz.c: If NEED_TIMEZONE_NULL_SUPPORT, define only localtime_rz + and mktime_z and only as wrappers around the system function. + * m4/time_h.m4 (gl_TIME_H_DEFAULTS): Initialize HAVE_TZALLOC, + REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. + * m4/time_rz.m4 (gl_TIME_RZ): Conditionally set HAVE_TZALLOC, + REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. Conditionally define + NEED_TIMEZONE_NULL_SUPPORT. + * modules/time-h (Makefile.am): Substitute HAVE_TZALLOC, + REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. + * modules/time_rz (Depends-on, configure.ac): Consider HAVE_TZALLOC, + REPLACE_LOCALTIME_RZ, REPLACE_MKTIME_Z. Ignore HAVE_TIMEZONE_T. + * m4/strerrorname_np.m4 (gl_CHECK_STRERRORNAME_NP): Test for strerrorname_np using gl_CHECK_FUNCS_ANDROID instead of AC_CHECK_FUNCS. diff --git a/lib/time.in.h b/lib/time.in.h index b91018937a..f4829ffe2f 100644 --- a/lib/time.in.h +++ b/lib/time.in.h @@ -488,14 +488,24 @@ _GL_WARN_ON_USE (strftime, "strftime has portability problems - " # endif # endif -# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@ +# if @GNULIB_TIME_RZ@ /* Functions that use a first-class time zone data type, instead of relying on an implicit global time zone. Inspired by NetBSD. */ /* Represents a time zone. (timezone_t) NULL stands for UTC. */ +# if !@HAVE_TZALLOC@ +# if !GNULIB_defined_timezone_t +# if !@HAVE_TIMEZONE_T@ typedef struct tm_zone *timezone_t; +# else +typedef struct tm_zone *rpl_timezone_t; +# define timezone_t rpl_timezone_t +# endif +# define GNULIB_defined_timezone_t 1 +# endif +# endif /* tzalloc (name) Returns a time zone object for the given time zone NAME. This object @@ -505,37 +515,70 @@ typedef struct tm_zone *timezone_t; would use it the TZ environment variable was unset. May return NULL if NAME is invalid (this is platform dependent) or upon memory allocation failure. */ +# if !@HAVE_TZALLOC@ _GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name)); _GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name)); +# endif /* tzfree (tz) Frees a time zone object. The argument must have been returned by tzalloc(). */ +# if !@HAVE_TZALLOC@ _GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz)); _GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz)); +# endif /* localtime_rz (tz, &t, &result) Converts an absolute time T to a broken-down time RESULT, assuming the time zone TZ. This function is like 'localtime_r', but relies on the argument TZ instead of an implicit global time zone. */ +# if @REPLACE_LOCALTIME_RZ@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localtime_rz +# define localtime_rz rpl_localtime_rz +# endif +_GL_FUNCDECL_RPL (localtime_rz, struct tm *, + (timezone_t __tz, time_t const *restrict __timer, + struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (localtime_rz, struct tm *, + (timezone_t __tz, time_t const *restrict __timer, + struct tm *restrict __result)); +# else +# if !@HAVE_TZALLOC@ _GL_FUNCDECL_SYS (localtime_rz, struct tm *, (timezone_t __tz, time_t const *restrict __timer, struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3))); +# endif _GL_CXXALIAS_SYS (localtime_rz, struct tm *, (timezone_t __tz, time_t const *restrict __timer, struct tm *restrict __result)); +# endif /* mktime_z (tz, &tm) Normalizes the broken-down time TM and converts it to an absolute time, assuming the time zone TZ. Returns the absolute time. This function is like 'mktime', but relies on the argument TZ instead of an implicit global time zone. */ +# if @REPLACE_MKTIME_Z@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mktime_z +# define mktime_z rpl_mktime_z +# endif +_GL_FUNCDECL_RPL (mktime_z, time_t, + (timezone_t __tz, struct tm *restrict __tm) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mktime_z, time_t, + (timezone_t __tz, struct tm *restrict __tm)); +# else +# if !@HAVE_TZALLOC@ _GL_FUNCDECL_SYS (mktime_z, time_t, (timezone_t __tz, struct tm *restrict __tm) _GL_ARG_NONNULL ((2))); +# endif _GL_CXXALIAS_SYS (mktime_z, time_t, (timezone_t __tz, struct tm *restrict __tm)); +# endif /* Time zone abbreviation strings (returned by 'localtime_rz' or 'mktime_z' in the 'tm_zone' member of 'struct tm') are valid as long as diff --git a/lib/time_rz.c b/lib/time_rz.c index b28d55c2fd..e057ee9703 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c @@ -24,16 +24,41 @@ #include +/* Specification. */ #include -#include -#include -#include -#include +#if NEED_TIMEZONE_NULL_SUPPORT /* Android API level >= 35 */ -#include "flexmember.h" -#include "idx.h" -#include "time-internal.h" +struct tm * +localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) +# undef localtime_rz +{ + if (!tz) + return gmtime_r (t, tm); + else + return localtime_rz (tz, t, tm); +} + +time_t +mktime_z (timezone_t tz, struct tm *tm) +# undef mktime_z +{ + if (!tz) + return timegm (tm); + else + return mktime_z (tz, tm); +} + +#else + +# include +# include +# include +# include + +# include "flexmember.h" +# include "idx.h" +# include "time-internal.h" /* The approximate size to use for small allocation requests. This is the largest "small" request for the GNU C library malloc. */ @@ -89,25 +114,25 @@ tzalloc (char const *name) static bool save_abbr (timezone_t tz, struct tm *tm) { -#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME_ARRAY +# if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME_ARRAY char const *zone = NULL; char *zone_copy = (char *) ""; -# if HAVE_TZNAME_ARRAY +# if HAVE_TZNAME_ARRAY int tzname_index = -1; -# endif +# endif -# if HAVE_STRUCT_TM_TM_ZONE +# if HAVE_STRUCT_TM_TM_ZONE zone = tm->tm_zone; -# endif +# endif -# if HAVE_TZNAME_ARRAY +# if HAVE_TZNAME_ARRAY if (! (zone && *zone) && 0 <= tm->tm_isdst) { tzname_index = tm->tm_isdst != 0; zone = tzname[tzname_index]; } -# endif +# endif /* No need to replace null zones, or zones within the struct tm. */ if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1))) @@ -145,13 +170,13 @@ save_abbr (timezone_t tz, struct tm *tm) } /* Replace the zone name so that its lifetime matches that of TZ. */ -# if HAVE_STRUCT_TM_TM_ZONE +# if HAVE_STRUCT_TM_TM_ZONE tm->tm_zone = zone_copy; -# else +# else if (0 <= tzname_index) tz->tzname_copy[tzname_index] = zone_copy; +# endif # endif -#endif return true; } @@ -172,21 +197,21 @@ tzfree (timezone_t tz) /* Get and set the TZ environment variable. These functions can be overridden by programs like Emacs that manage their own environment. */ -#ifndef getenv_TZ +# ifndef getenv_TZ static char * getenv_TZ (void) { return getenv ("TZ"); } -#endif +# endif -#ifndef setenv_TZ +# ifndef setenv_TZ static int setenv_TZ (char const *tz) { return tz ? setenv ("TZ", tz, 1) : unsetenv ("TZ"); } -#endif +# endif /* Change the environment to match the specified timezone_t value. Return true if successful, false (setting errno) otherwise. */ @@ -251,7 +276,7 @@ revert_tz (timezone_t tz) struct tm * localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) { -#ifdef HAVE_LOCALTIME_INFLOOP_BUG +# ifdef HAVE_LOCALTIME_INFLOOP_BUG /* The -67768038400665599 comes from: https://lists.gnu.org/r/bug-gnulib/2017-07/msg00142.html On affected platforms the greatest POSIX-compatible time_t value @@ -264,7 +289,7 @@ localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) errno = EOVERFLOW; return NULL; } -#endif +# endif if (!tz) return gmtime_r (t, tm); @@ -315,3 +340,5 @@ mktime_z (timezone_t tz, struct tm *tm) return -1; } } + +#endif diff --git a/m4/time_h.m4 b/m4/time_h.m4 index 4f2e927a29..5e0f125932 100644 --- a/m4/time_h.m4 +++ b/m4/time_h.m4 @@ -2,7 +2,7 @@ # Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software Foundation, Inc. -# serial 26 +# serial 27 # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -164,13 +164,16 @@ AC_DEFUN([gl_TIME_H_DEFAULTS], HAVE_TIMEGM=1; AC_SUBST([HAVE_TIMEGM]) HAVE_TIMESPEC_GET=1; AC_SUBST([HAVE_TIMESPEC_GET]) HAVE_TIMESPEC_GETRES=1; AC_SUBST([HAVE_TIMESPEC_GETRES]) - dnl Even GNU libc does not have timezone_t yet. + dnl Even GNU libc does not have timezone_t and tzalloc() yet. HAVE_TIMEZONE_T=0; AC_SUBST([HAVE_TIMEZONE_T]) + HAVE_TZALLOC=0; AC_SUBST([HAVE_TZALLOC]) REPLACE_CTIME=0; AC_SUBST([REPLACE_CTIME]) REPLACE_GMTIME=0; AC_SUBST([REPLACE_GMTIME]) REPLACE_LOCALTIME=0; AC_SUBST([REPLACE_LOCALTIME]) REPLACE_LOCALTIME_R=0; AC_SUBST([REPLACE_LOCALTIME_R]) + REPLACE_LOCALTIME_RZ=0; AC_SUBST([REPLACE_LOCALTIME_RZ]) REPLACE_MKTIME=0; AC_SUBST([REPLACE_MKTIME]) + REPLACE_MKTIME_Z=0; AC_SUBST([REPLACE_MKTIME_Z]) REPLACE_NANOSLEEP=0; AC_SUBST([REPLACE_NANOSLEEP]) REPLACE_STRFTIME=0; AC_SUBST([REPLACE_STRFTIME]) REPLACE_TIME=0; AC_SUBST([REPLACE_TIME]) diff --git a/m4/time_rz.m4 b/m4/time_rz.m4 index c7387ca9a2..d699dd786b 100644 --- a/m4/time_rz.m4 +++ b/m4/time_rz.m4 @@ -9,8 +9,9 @@ dnl Written by Paul Eggert. AC_DEFUN([gl_TIME_RZ], [ - AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_REQUIRE([gl_TIME_H_DEFAULTS]) + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + AC_REQUIRE([AC_CANONICAL_HOST]) # On Mac OS X 10.6, localtime loops forever with some time_t values. # See Bug#27706, Bug#27736, and @@ -49,4 +50,29 @@ AC_DEFUN([gl_TIME_RZ], if test "$ac_cv_type_timezone_t" = yes; then HAVE_TIMEZONE_T=1 fi + + gl_CHECK_FUNCS_ANDROID([tzalloc], [[#include ]]) + if test $ac_cv_func_tzalloc = yes; then + HAVE_TZALLOC=1 + fi + dnl Assume that tzalloc, localtime_rz, mktime_z are all defined together. + case "$gl_cv_onwards_func_tzalloc" in + yes) + case "$host_os" in + *-android*) + dnl The Android libc functions localtime_rz, mktime_z don't support + dnl a NULL timezone_t argument. + AC_DEFINE([NEED_TIMEZONE_NULL_SUPPORT], [1], + [Define to 1 if localtime_rz, mktime_z exist and can be used with + non-NULL timezone_t values.]) + REPLACE_LOCALTIME_RZ=1 + REPLACE_MKTIME_Z=1 + ;; + esac + ;; + future*) + REPLACE_LOCALTIME_RZ=1 + REPLACE_MKTIME_Z=1 + ;; + esac ]) diff --git a/modules/time-h b/modules/time-h index e84100bf93..76921979f0 100644 --- a/modules/time-h +++ b/modules/time-h @@ -54,11 +54,14 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's|@''HAVE_TIMESPEC_GET''@|$(HAVE_TIMESPEC_GET)|g' \ -e 's|@''HAVE_TIMESPEC_GETRES''@|$(HAVE_TIMESPEC_GETRES)|g' \ -e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \ + -e 's|@''HAVE_TZALLOC''@|$(HAVE_TZALLOC)|g' \ -e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \ -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \ + -e 's|@''REPLACE_LOCALTIME_RZ''@|$(REPLACE_LOCALTIME_RZ)|g' \ -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ + -e 's|@''REPLACE_MKTIME_Z''@|$(REPLACE_MKTIME_Z)|g' \ -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \ -e 's|@''REPLACE_TIME''@|$(REPLACE_TIME)|g' \ diff --git a/modules/time_rz b/modules/time_rz index da621684f5..bcf29788e3 100644 --- a/modules/time_rz +++ b/modules/time_rz @@ -11,18 +11,19 @@ c99 extensions time-h tzname -flexmember [test $HAVE_TIMEZONE_T = 0] -idx [test $HAVE_TIMEZONE_T = 0] -setenv [test $HAVE_TIMEZONE_T = 0] -stdbool [test $HAVE_TIMEZONE_T = 0] -time_r [test $HAVE_TIMEZONE_T = 0] -timegm [test $HAVE_TIMEZONE_T = 0] -tzset [test $HAVE_TIMEZONE_T = 0] -unsetenv [test $HAVE_TIMEZONE_T = 0] +flexmember [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] +idx [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] +setenv [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] +stdbool [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] +time_r [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] +timegm [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] +tzset [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] +unsetenv [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1] configure.ac: gl_TIME_RZ -gl_CONDITIONAL([GL_COND_OBJ_TIME_RZ], [test $HAVE_TIMEZONE_T = 0]) +gl_CONDITIONAL([GL_COND_OBJ_TIME_RZ], + [test $HAVE_TZALLOC = 0 || test $REPLACE_LOCALTIME_RZ = 1 || test $REPLACE_MKTIME_Z = 1]) gl_TIME_MODULE_INDICATOR([time_rz]) Makefile.am: -- 2.39.5