Merge "Bump tzcode from 2016g to 2022a*." am: 0219fe82c6

Original change: https://android-review.googlesource.com/c/platform/bionic/+/1985266

Change-Id: I46d908bd069f53544dfb89ed22a5eb37a294a166
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Almaz Mingaleev 2022-06-08 08:14:49 +00:00 committed by Automerger Merge Worker
commit 7902bfcf9d
9 changed files with 1063 additions and 593 deletions

View file

@ -259,18 +259,20 @@ cc_library_static {
// Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
"-DSTD_INSPIRED",
// Obviously, we want to be thread-safe.
"-DTHREAD_SAFE",
"-DTHREAD_SAFE=1",
// The name of the tm_gmtoff field in our struct tm.
"-DTM_GMTOFF=tm_gmtoff",
// Where we store our tzdata.
"-DTZDIR=\"/system/usr/share/zoneinfo\"",
// Include `tzname`, `timezone`, and `daylight` globals.
"-DHAVE_POSIX_DECLS=0",
"-DUSG_COMPAT=1",
"-DUSG_COMPAT=2",
"-DHAVE_TZNAME=2",
// stdbool.h is available
"-DHAVE_STDBOOL_H",
// Use the empty string (instead of " ") as the timezone abbreviation
// fallback.
"-DWILDABBR=\"\"",
"-DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU",
"-Dlint",
],

View file

@ -483,6 +483,11 @@ static Time64_T seconds_between_years(Year left_year, Year right_year) {
}
/* This implementation violates mktime specification, according to which
tm_yday, tm_wday, and tm_isdst fields should be updated. This function
leaves input_date unmodified. Given that there were no bug reports, fixing
it might cause more troubles than just leaving it as it is.
*/
Time64_T mktime64(const struct TM *input_date) {
struct tm safe_date;
struct TM date;

View file

@ -1,3 +1,5 @@
/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000. */
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
@ -12,7 +14,7 @@
/*LINTLIBRARY*/
#include "private.h"
#include "tzfile.h"
#include <stdio.h>
/*
** Some systems only handle "%.2d"; others only handle "%02d";
@ -29,13 +31,13 @@
** leading zeroes to get the newline in the traditional place.
** The -4 ensures that we get four characters of output even if
** we call a strftime variant that produces fewer characters for some years.
** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
** The ISO C and POSIX standards prohibit padding the year,
** but many implementations pad anyway; most likely the standards are buggy.
*/
#ifdef __GNUC__
#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
#define ASCTIME_FMT "%s %s%3d %2.2d:%2.2d:%2.2d %-4s\n"
#else /* !defined __GNUC__ */
#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
#define ASCTIME_FMT "%s %s%3d %02.2d:%02.2d:%02.2d %-4s\n"
#endif /* !defined __GNUC__ */
/*
** For years that are more than four digits we put extra spaces before the year
@ -44,9 +46,9 @@
** that no output is better than wrong output).
*/
#ifdef __GNUC__
#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n"
#define ASCTIME_FMT_B "%s %s%3d %2.2d:%2.2d:%2.2d %s\n"
#else /* !defined __GNUC__ */
#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n"
#define ASCTIME_FMT_B "%s %s%3d %02.2d:%02.2d:%02.2d %s\n"
#endif /* !defined __GNUC__ */
#define STD_ASCTIME_BUF_SIZE 26
@ -64,17 +66,13 @@
static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
/*
** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
*/
char *
asctime_r(register const struct tm *timeptr, char *buf)
{
static const char wday_name[][3] = {
static const char wday_name[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char mon_name[][3] = {
static const char mon_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
@ -117,10 +115,6 @@ asctime_r(register const struct tm *timeptr, char *buf)
}
}
/*
** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
*/
char *
asctime(register const struct tm *timeptr)
{

View file

@ -1,3 +1,5 @@
/* Return the difference between two timestamps. */
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
@ -14,14 +16,14 @@ dminus(double x)
return -x;
}
double ATTRIBUTE_CONST
double
difftime(time_t time1, time_t time0)
{
/*
** If double is large enough, simply convert and subtract
** (assuming that the larger type has more precision).
*/
if (sizeof (time_t) < sizeof (double)) {
if (sizeof(time_t) < sizeof(double)) {
double t1 = time1, t0 = time0;
return t1 - t0;
}
@ -34,7 +36,7 @@ difftime(time_t time1, time_t time0)
return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
/* Use uintmax_t if wide enough. */
if (sizeof (time_t) <= sizeof (uintmax_t)) {
if (sizeof(time_t) <= sizeof(uintmax_t)) {
uintmax_t t1 = time1, t0 = time0;
return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
}

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,5 @@
/* Private header for tzdb code. */
#ifndef PRIVATE_H
#define PRIVATE_H
@ -15,6 +17,17 @@
** Thank you!
*/
/*
** zdump has been made independent of the rest of the time
** conversion package to increase confidence in the verification it provides.
** You can use zdump to help in verifying other implementations.
** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
*/
#ifndef USE_LTZ
# define USE_LTZ 1
#endif
/* This string was in the Factory zone through version 2016f. */
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
/*
@ -26,26 +39,53 @@
#define HAVE_DECL_ASCTIME_R 1
#endif
#if !defined HAVE_GENERIC && defined __has_extension
# if __has_extension(c_generic_selections)
# define HAVE_GENERIC 1
# else
# define HAVE_GENERIC 0
# endif
#endif
/* _Generic is buggy in pre-4.9 GCC. */
#if !defined HAVE_GENERIC && defined __GNUC__
# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
#endif
#ifndef HAVE_GENERIC
# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
#endif
#ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */
#ifndef HAVE_INCOMPATIBLE_CTIME_R
#define HAVE_INCOMPATIBLE_CTIME_R 0
#endif /* !defined INCOMPATIBLE_CTIME_R */
#endif
#ifndef HAVE_LINK
#define HAVE_LINK 1
#endif /* !defined HAVE_LINK */
#ifndef HAVE_MALLOC_ERRNO
#define HAVE_MALLOC_ERRNO 1
#endif
#ifndef HAVE_POSIX_DECLS
#define HAVE_POSIX_DECLS 1
#endif
#ifndef HAVE_STDBOOL_H
#define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
#endif
#ifndef HAVE_STRDUP
#define HAVE_STRDUP 1
#endif
#ifndef HAVE_STRTOLL
#define HAVE_STRTOLL 1
#endif
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
@ -54,10 +94,6 @@
#define HAVE_SYS_STAT_H 1
#endif /* !defined HAVE_SYS_STAT_H */
#ifndef HAVE_SYS_WAIT_H
#define HAVE_SYS_WAIT_H 1
#endif /* !defined HAVE_SYS_WAIT_H */
#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H 1
#endif /* !defined HAVE_UNISTD_H */
@ -75,22 +111,37 @@
#define ctime_r _incompatible_ctime_r
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
/* Enable tm_gmtoff and tm_zone on GNUish systems. */
/* Enable tm_gmtoff, tm_zone, and environ on GNUish systems. */
#define _GNU_SOURCE 1
/* Fix asctime_r on Solaris 10. */
/* Fix asctime_r on Solaris 11. */
#define _POSIX_PTHREAD_SEMANTICS 1
/* Enable strtoimax on Solaris 10. */
/* Enable strtoimax on pre-C99 Solaris 11. */
#define __EXTENSIONS__ 1
/* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
enable large files on GNUish systems ... */
#ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
#endif
/* ... and on AIX ... */
#define _LARGE_FILES 1
/* ... and enable large inode numbers on Mac OS X 10.5 and later. */
#define _DARWIN_USE_64_BIT_INODE 1
/*
** Nested includes
*/
/* Avoid clashes with NetBSD by renaming NetBSD's declarations. */
/* Avoid clashes with NetBSD by renaming NetBSD's declarations.
If defining the 'timezone' variable, avoid a clash with FreeBSD's
'timezone' function by renaming its declaration. */
#define localtime_rz sys_localtime_rz
#define mktime_z sys_mktime_z
#define posix2time_z sys_posix2time_z
#define time2posix_z sys_time2posix_z
#if defined USG_COMPAT && USG_COMPAT == 2
# define timezone sys_timezone
#endif
#define timezone_t sys_timezone_t
#define tzalloc sys_tzalloc
#define tzfree sys_tzfree
@ -99,21 +150,30 @@
#undef mktime_z
#undef posix2time_z
#undef time2posix_z
#if defined USG_COMPAT && USG_COMPAT == 2
# undef timezone
#endif
#undef timezone_t
#undef tzalloc
#undef tzfree
#include "sys/types.h" /* for time_t */
#include "stdio.h"
#include "string.h"
#include "limits.h" /* for CHAR_BIT et al. */
#include "stdlib.h"
#include <sys/types.h> /* for time_t */
#include <string.h>
#include <limits.h> /* for CHAR_BIT et al. */
#include <stdlib.h>
#include "errno.h"
#include <errno.h>
#ifndef EINVAL
# define EINVAL ERANGE
#endif
#ifndef ENAMETOOLONG
# define ENAMETOOLONG EINVAL
#endif
#ifndef ENOMEM
# define ENOMEM EINVAL
#endif
#ifndef ENOTSUP
# define ENOTSUP EINVAL
#endif
@ -122,22 +182,11 @@
#endif
#if HAVE_GETTEXT
#include "libintl.h"
#include <libintl.h>
#endif /* HAVE_GETTEXT */
#if HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
#endif /* HAVE_SYS_WAIT_H */
#ifndef WIFEXITED
#define WIFEXITED(status) (((status) & 0xff) == 0)
#endif /* !defined WIFEXITED */
#ifndef WEXITSTATUS
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
#endif /* !defined WEXITSTATUS */
#if HAVE_UNISTD_H
#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */
#include <unistd.h> /* for R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
#ifndef HAVE_STRFTIME_L
@ -148,31 +197,49 @@
# endif
#endif
#ifndef F_OK
#define F_OK 0
#endif /* !defined F_OK */
#ifndef USG_COMPAT
# ifndef _XOPEN_VERSION
# define USG_COMPAT 0
# else
# define USG_COMPAT 1
# endif
#endif
#ifndef HAVE_TZNAME
# if _POSIX_VERSION < 198808 && !USG_COMPAT
# define HAVE_TZNAME 0
# else
# define HAVE_TZNAME 1
# endif
#endif
#ifndef ALTZONE
# if defined __sun || defined _M_XENIX
# define ALTZONE 1
# else
# define ALTZONE 0
# endif
#endif
#ifndef R_OK
#define R_OK 4
#endif /* !defined R_OK */
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
/*
** Define HAVE_STDINT_H's default value here, rather than at the
** start, since __GLIBC__'s value depends on previously-included
** files.
** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
** start, since __GLIBC__ and INTMAX_MAX's values depend on
** previously-included files. glibc 2.1 and Solaris 10 and later have
** stdint.h, even with pre-C99 compilers.
*/
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H \
(199901 <= __STDC_VERSION__ \
|| 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
|| __CYGWIN__)
|| __CYGWIN__ || INTMAX_MAX)
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
#include "stdint.h"
#include <stdint.h>
#endif /* !HAVE_STDINT_H */
#ifndef HAVE_INTTYPES_H
@ -208,14 +275,18 @@ typedef long int_fast64_t;
# endif
#endif
#ifndef SCNdFAST64
#ifndef PRIdFAST64
# if INT_FAST64_MAX == LLONG_MAX
# define SCNdFAST64 "lld"
# define PRIdFAST64 "lld"
# else
# define SCNdFAST64 "ld"
# define PRIdFAST64 "ld"
# endif
#endif
#ifndef SCNdFAST64
# define SCNdFAST64 PRIdFAST64
#endif
#ifndef INT_FAST32_MAX
# if INT_MAX >> 31 == 0
typedef long int_fast32_t;
@ -231,15 +302,19 @@ typedef int int_fast32_t;
#ifndef INTMAX_MAX
# ifdef LLONG_MAX
typedef long long intmax_t;
# define strtoimax strtoll
# if HAVE_STRTOLL
# define strtoimax strtoll
# endif
# define INTMAX_MAX LLONG_MAX
# define INTMAX_MIN LLONG_MIN
# else
typedef long intmax_t;
# define strtoimax strtol
# define INTMAX_MAX LONG_MAX
# define INTMAX_MIN LONG_MIN
# endif
# ifndef strtoimax
# define strtoimax strtol
# endif
#endif
#ifndef PRIdMAX
@ -250,6 +325,10 @@ typedef long intmax_t;
# endif
#endif
#ifndef UINT_FAST32_MAX
typedef unsigned long uint_fast32_t;
#endif
#ifndef UINT_FAST64_MAX
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
typedef unsigned long long uint_fast64_t;
@ -289,19 +368,21 @@ typedef unsigned long uintmax_t;
#define SIZE_MAX ((size_t) -1)
#endif
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
# define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#if 3 <= __GNUC__
# define ATTRIBUTE_CONST __attribute__((const))
# define ATTRIBUTE_MALLOC __attribute__((__malloc__))
# define ATTRIBUTE_PURE __attribute__((__pure__))
# define ATTRIBUTE_FORMAT(spec) __attribute__((__format__ spec))
#else
# define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_MALLOC /* empty */
# define ATTRIBUTE_PURE /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
#if !defined _Noreturn && __STDC_VERSION__ < 201112
# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
# define _Noreturn __attribute__ ((__noreturn__))
# define _Noreturn __attribute__((__noreturn__))
# else
# define _Noreturn
# endif
@ -315,6 +396,23 @@ typedef unsigned long uintmax_t;
** Workarounds for compilers/systems.
*/
#ifndef EPOCH_LOCAL
# define EPOCH_LOCAL 0
#endif
#ifndef EPOCH_OFFSET
# define EPOCH_OFFSET 0
#endif
#ifndef RESERVE_STD_EXT_IDS
# define RESERVE_STD_EXT_IDS 0
#endif
/* If standard C identifiers with external linkage (e.g., localtime)
are reserved and are not already being renamed anyway, rename them
as if compiling with '-Dtime_tz=time_t'. */
#if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
# define time_tz time_t
#endif
/*
** Compile with -Dtime_tz=T to build the tz package with a private
** time_t type equivalent to T rather than the system-supplied time_t.
@ -322,13 +420,24 @@ typedef unsigned long uintmax_t;
** (e.g., time_t wider than 'long', or unsigned time_t) even on
** typical platforms.
*/
#ifdef time_tz
# ifdef LOCALTIME_IMPLEMENTATION
#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
# define TZ_TIME_T 1
#else
# define TZ_TIME_T 0
#endif
#if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
static time_t sys_time(time_t *x) { return time(x); }
# endif
#endif
#if TZ_TIME_T
typedef time_tz tz_time_t;
# undef asctime
# define asctime tz_asctime
# undef asctime_r
# define asctime_r tz_asctime_r
# undef ctime
# define ctime tz_ctime
# undef ctime_r
@ -355,6 +464,8 @@ typedef time_tz tz_time_t;
# define posix2time tz_posix2time
# undef posix2time_z
# define posix2time_z tz_posix2time_z
# undef strftime
# define strftime tz_strftime
# undef time
# define time tz_time
# undef time2posix
@ -375,12 +486,36 @@ typedef time_tz tz_time_t;
# define tzfree tz_tzfree
# undef tzset
# define tzset tz_tzset
# undef tzsetwall
# define tzsetwall tz_tzsetwall
# if HAVE_STRFTIME_L
# undef strftime_l
# define strftime_l tz_strftime_l
# endif
# if HAVE_TZNAME
# undef tzname
# define tzname tz_tzname
# endif
# if USG_COMPAT
# undef daylight
# define daylight tz_daylight
# undef timezone
# define timezone tz_timezone
# endif
# if ALTZONE
# undef altzone
# define altzone tz_altzone
# endif
char *asctime(struct tm const *);
char *asctime_r(struct tm const *restrict, char *restrict);
char *ctime(time_t const *);
char *ctime_r(time_t const *, char *);
double difftime(time_t, time_t);
double difftime(time_t, time_t) ATTRIBUTE_CONST;
size_t strftime(char *restrict, size_t, char const *restrict,
struct tm const *restrict);
# if HAVE_STRFTIME_L
size_t strftime_l(char *restrict, size_t, char const *restrict,
struct tm const *restrict, locale_t);
# endif
struct tm *gmtime(time_t const *);
struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
struct tm *localtime(time_t const *);
@ -394,18 +529,26 @@ void tzset(void);
extern char *asctime_r(struct tm const *restrict, char *restrict);
#endif
#if !HAVE_POSIX_DECLS
# ifdef USG_COMPAT
# ifndef timezone
extern long timezone;
# endif
# ifndef daylight
extern int daylight;
# endif
#ifndef HAVE_DECL_ENVIRON
# if defined environ || defined __USE_GNU
# define HAVE_DECL_ENVIRON 1
# else
# define HAVE_DECL_ENVIRON 0
# endif
#endif
#if defined ALTZONE && !defined altzone
#if !HAVE_DECL_ENVIRON
extern char **environ;
#endif
#if 2 <= HAVE_TZNAME + (TZ_TIME_T || !HAVE_POSIX_DECLS)
extern char *tzname[];
#endif
#if 2 <= USG_COMPAT + (TZ_TIME_T || !HAVE_POSIX_DECLS)
extern long timezone;
extern int daylight;
#endif
#if 2 <= ALTZONE + (TZ_TIME_T || !HAVE_POSIX_DECLS)
extern long altzone;
#endif
@ -415,25 +558,22 @@ extern long altzone;
*/
#ifdef STD_INSPIRED
# if !defined tzsetwall || defined time_tz
void tzsetwall(void);
# endif
# if !defined offtime || defined time_tz
# if TZ_TIME_T || !defined offtime
struct tm *offtime(time_t const *, long);
# endif
# if !defined timegm || defined time_tz
# if TZ_TIME_T || !defined timegm
time_t timegm(struct tm *);
# endif
# if !defined timelocal || defined time_tz
# if TZ_TIME_T || !defined timelocal
time_t timelocal(struct tm *);
# endif
# if !defined timeoff || defined time_tz
# if TZ_TIME_T || !defined timeoff
time_t timeoff(struct tm *, long);
# endif
# if !defined time2posix || defined time_tz
# if TZ_TIME_T || !defined time2posix
time_t time2posix(time_t);
# endif
# if !defined posix2time || defined time_tz
# if TZ_TIME_T || !defined posix2time
time_t posix2time(time_t);
# endif
#endif
@ -467,10 +607,10 @@ time_t mktime_z(timezone_t restrict, struct tm *restrict);
timezone_t tzalloc(char const *);
void tzfree(timezone_t);
# ifdef STD_INSPIRED
# if !defined posix2time_z || defined time_tz
# if TZ_TIME_T || !defined posix2time_z
time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif
# if !defined time2posix_z || defined time_tz
# if TZ_TIME_T || !defined time2posix_z
time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif
# endif
@ -480,22 +620,16 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
** Finally, some convenience items.
*/
#if __STDC_VERSION__ < 199901
#if HAVE_STDBOOL_H
# include <stdbool.h>
#else
# define true 1
# define false 0
# define bool int
#else
# include <stdbool.h>
#endif
#ifndef TYPE_BIT
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
#endif /* !defined TYPE_BIT */
#ifndef TYPE_SIGNED
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
#define TYPE_SIGNED(type) (((type) -1) < 0)
#endif /* !defined TYPE_SIGNED */
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
/* Max and min values of the integer type T, of which only the bottom
@ -507,11 +641,34 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
#define MINVAL(t, b) \
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
/* The minimum and maximum finite time values. This assumes no padding. */
static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
/* The extreme time values, assuming no padding. */
#define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
#define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
/* The extreme time values. These are macros, not constants, so that
any portability problems occur only when compiling .c files that use
the macros, which is safer for applications that need only zdump and zic.
This implementation assumes no padding if time_t is signed and
either the compiler lacks support for _Generic or time_t is not one
of the standard signed integer types. */
#if HAVE_GENERIC
# define TIME_T_MIN \
_Generic((time_t) 0, \
signed char: SCHAR_MIN, short: SHRT_MIN, \
int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
default: TIME_T_MIN_NO_PADDING)
# define TIME_T_MAX \
(TYPE_SIGNED(time_t) \
? _Generic((time_t) 0, \
signed char: SCHAR_MAX, short: SHRT_MAX, \
int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
default: TIME_T_MAX_NO_PADDING) \
: (time_t) -1)
#else
# define TIME_T_MIN TIME_T_MIN_NO_PADDING
# define TIME_T_MAX TIME_T_MAX_NO_PADDING
#endif
#ifndef INT_STRLEN_MAXIMUM
/*
** 302 / 1000 is log10(2.0) rounded up.
** Subtract one for the sign bit if the type is signed;
@ -521,13 +678,12 @@ static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
1 + TYPE_SIGNED(type))
#endif /* !defined INT_STRLEN_MAXIMUM */
/*
** INITIALIZE(x)
*/
#ifdef lint
#ifdef GCC_LINT
# define INITIALIZE(x) ((x) = 0)
#else
# define INITIALIZE(x)
@ -537,19 +693,30 @@ static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
# define UNINIT_TRAP 0
#endif
#ifdef DEBUG
# define UNREACHABLE() abort()
#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
# define UNREACHABLE() __builtin_unreachable()
#elif defined __has_builtin
# if __has_builtin(__builtin_unreachable)
# define UNREACHABLE() __builtin_unreachable()
# endif
#endif
#ifndef UNREACHABLE
# define UNREACHABLE() ((void) 0)
#endif
/*
** For the benefit of GNU folk...
** '_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
#ifndef _
#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
#else /* !HAVE_GETTEXT */
#define _(msgid) msgid
#endif /* !HAVE_GETTEXT */
#endif /* !defined _ */
#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
# define TZ_DOMAIN "tz"
@ -562,24 +729,64 @@ char *asctime_r(struct tm const *, char *);
char *ctime_r(time_t const *, char *);
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
#ifndef YEARSPERREPEAT
/* Handy macros that are independent of tzfile implementation. */
#define SECSPERMIN 60
#define MINSPERHOUR 60
#define HOURSPERDAY 24
#define DAYSPERWEEK 7
#define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
#define MONSPERYEAR 12
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
#endif /* !defined YEARSPERREPEAT */
#define DAYSPERREPEAT ((int_fast32_t) 400 * 365 + 100 - 4 + 1)
#define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
#define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT)
#define TM_SUNDAY 0
#define TM_MONDAY 1
#define TM_TUESDAY 2
#define TM_WEDNESDAY 3
#define TM_THURSDAY 4
#define TM_FRIDAY 5
#define TM_SATURDAY 6
#define TM_JANUARY 0
#define TM_FEBRUARY 1
#define TM_MARCH 2
#define TM_APRIL 3
#define TM_MAY 4
#define TM_JUNE 5
#define TM_JULY 6
#define TM_AUGUST 7
#define TM_SEPTEMBER 8
#define TM_OCTOBER 9
#define TM_NOVEMBER 10
#define TM_DECEMBER 11
#define TM_YEAR_BASE 1900
#define TM_WDAY_BASE TM_MONDAY
#define EPOCH_YEAR 1970
#define EPOCH_WDAY TM_THURSDAY
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
/*
** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
** Since everything in isleap is modulo 400 (or a factor of 400), we know that
** isleap(y) == isleap(y % 400)
** and so
** isleap(a + b) == isleap((a + b) % 400)
** or
** isleap(a + b) == isleap(a % 400 + b % 400)
** This is true even if % means modulo rather than Fortran remainder
** (which is allowed by C89 but not by C99 or later).
** We use this to avoid addition overflow problems.
*/
#ifndef AVGSECSPERYEAR
#define AVGSECSPERYEAR 31556952L
#endif /* !defined AVGSECSPERYEAR */
#ifndef SECSPERREPEAT
#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
#endif /* !defined SECSPERREPEAT */
#ifndef SECSPERREPEAT_BITS
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#endif /* !defined SECSPERREPEAT_BITS */
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined PRIVATE_H */

View file

@ -1,4 +1,4 @@
/* Convert a broken-down time stamp to a string. */
/* Convert a broken-down timestamp to a string. */
/* Copyright 1989 The Regents of the University of California.
All rights reserved.
@ -35,9 +35,13 @@
#include "private.h"
#include "tzfile.h"
#include "fcntl.h"
#include "locale.h"
#include <fcntl.h>
#include <locale.h>
#include <stdio.h>
#ifndef DEPRECATE_TWO_DIGIT_YEARS
# define DEPRECATE_TWO_DIGIT_YEARS false
#endif
#if defined(__BIONIC__)
@ -45,6 +49,7 @@
#if defined(__LP64__)
#define time64_t time_t
#define mktime64 mktime
#define localtime64_r localtime_r
#else
#include <time64.h>
#endif
@ -88,7 +93,7 @@ static const struct lc_time_T C_time_locale = {
/*
** x_fmt
** C99 requires this format.
** C99 and later require this format.
** Using just numbers (as here) makes Quakers happier;
** it's also compatible with SVR4.
*/
@ -96,7 +101,7 @@ static const struct lc_time_T C_time_locale = {
/*
** c_fmt
** C99 requires this format.
** C99 and later require this format.
** Previously this code used "%D %X", but we now conform to C99.
** Note that
** "%a %b %d %H:%M:%S %Y"
@ -114,25 +119,18 @@ static const struct lc_time_T C_time_locale = {
"%a %b %e %H:%M:%S %Z %Y"
};
enum warn { IN_NONE, IN_SOME, IN_THIS, IN_ALL };
static char * _add(const char *, char *, const char *, int);
static char * _conv(int, const char *, char *, const char *);
static char * _fmt(const char *, const struct tm *, char *, const char *,
int *);
enum warn *);
static char * _yconv(int, int, bool, bool, char *, const char *, int);
#if !HAVE_POSIX_DECLS
extern char * tzname[];
#endif
#ifndef YEAR_2000_NAME
#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
#endif /* !defined YEAR_2000_NAME */
#define IN_NONE 0
#define IN_SOME 1
#define IN_THIS 2
#define IN_ALL 3
#if HAVE_STRFTIME_L
size_t
strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
@ -149,18 +147,19 @@ size_t
strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
{
char * p;
int warn;
int saved_errno = errno;
enum warn warn = IN_NONE;
tzset();
warn = IN_NONE;
p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
p = _fmt(format, t, s, s + maxsize, &warn);
if (!p) {
errno = EOVERFLOW;
return 0;
}
if (DEPRECATE_TWO_DIGIT_YEARS
&& warn != IN_NONE && getenv(YEAR_2000_NAME)) {
fprintf(stderr, "\n");
if (format == NULL)
fprintf(stderr, "NULL strftime format ");
else fprintf(stderr, "strftime format \"%s\" ",
format);
fprintf(stderr, "strftime format \"%s\" ", format);
fprintf(stderr, "yields only two digits of years in ");
if (warn == IN_SOME)
fprintf(stderr, "some locales");
@ -169,10 +168,12 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
else fprintf(stderr, "all locales");
fprintf(stderr, "\n");
}
#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
if (p == s + maxsize)
if (p == s + maxsize) {
errno = ERANGE;
return 0;
}
*p = '\0';
errno = saved_errno;
return p - s;
}
@ -191,7 +192,7 @@ static char *getformat(int modifier, char *normal, char *underscore,
static char *
_fmt(const char *format, const struct tm *t, char *pt,
const char *ptlim, int *warnp)
const char *ptlim, enum warn *warnp)
{
for ( ; *format; ++format) {
if (*format == '%') {
@ -239,7 +240,7 @@ label:
continue;
case 'c':
{
int warn2 = IN_SOME;
enum warn warn2 = IN_SOME;
pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
@ -257,12 +258,12 @@ label:
case 'E':
case 'O':
/*
** C99 locale modifiers.
** Locale modifiers of C99 and later.
** The sequences
** %Ec %EC %Ex %EX %Ey %EY
** %Od %oe %OH %OI %Om %OM
** %OS %Ou %OU %OV %Ow %OW %Oy
** are supposed to provide alternate
** are supposed to provide alternative
** representations.
*/
goto label;
@ -356,11 +357,17 @@ label:
tm = *t;
mkt = mktime64(&tm);
if (TYPE_SIGNED(time64_t))
snprintf(buf, sizeof(buf), "%"PRIdMAX,
(intmax_t) mkt);
else snprintf(buf, sizeof(buf), "%"PRIuMAX,
(uintmax_t) mkt);
/* There is no portable, definitive
test for whether whether mktime
succeeded, so treat (time_t) -1 as
the success that it might be. */
if (TYPE_SIGNED(time64_t)) {
intmax_t n = mkt;
sprintf(buf, "%"PRIdMAX, n);
} else {
uintmax_t n = mkt;
sprintf(buf, "%"PRIuMAX, n);
}
pt = _add(buf, pt, ptlim, modifier);
}
continue;
@ -392,7 +399,7 @@ label:
** (01-53)."
** (ado, 1993-05-24)
**
** From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
** From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
** "Week 01 of a year is per definition the first week which has the
** Thursday in this year, which is equivalent to the week which contains
** the fourth day of January. In other words, the first week of a new year
@ -494,7 +501,7 @@ label:
continue;
case 'x':
{
int warn2 = IN_SOME;
enum warn warn2 = IN_SOME;
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
@ -533,29 +540,30 @@ label:
pt = _add(zone, pt, ptlim, modifier);
}
// END: Android-changed.
#else
#elif HAVE_TZNAME
if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0],
pt, ptlim);
#endif
/*
** C99 says that %Z must be replaced by the
** empty string if the time zone is not
** C99 and later say that %Z must be
** replaced by the empty string if the
** time zone abbreviation is not
** determinable.
*/
continue;
case 'z':
#if defined TM_GMTOFF || USG_COMPAT || ALTZONE
{
long diff;
char const * sign;
bool negative;
if (t->tm_isdst < 0)
continue;
#ifdef TM_GMTOFF
# ifdef TM_GMTOFF
diff = t->TM_GMTOFF;
#else /* !defined TM_GMTOFF */
# else
/*
** C99 says that the UT offset must
** C99 and later say that the UT offset must
** be computed by looking only at
** tm_isdst. This requirement is
** incorrect, since it means the code
@ -563,30 +571,44 @@ label:
** altzone and timezone), and the
** magic might not have the correct
** offset. Doing things correctly is
** tricky and requires disobeying C99;
** tricky and requires disobeying the standard;
** see GNU C strftime for details.
** For now, punt and conform to the
** standard, even though it's incorrect.
**
** C99 says that %z must be replaced by the
** empty string if the time zone is not
** C99 and later say that %z must be replaced by
** the empty string if the time zone is not
** determinable, so output nothing if the
** appropriate variables are not available.
*/
if (t->tm_isdst < 0)
continue;
if (t->tm_isdst == 0)
#ifdef USG_COMPAT
# if USG_COMPAT
diff = -timezone;
#else /* !defined USG_COMPAT */
# else
continue;
#endif /* !defined USG_COMPAT */
# endif
else
#ifdef ALTZONE
# if ALTZONE
diff = -altzone;
#else /* !defined ALTZONE */
# else
continue;
#endif /* !defined ALTZONE */
#endif /* !defined TM_GMTOFF */
if (diff < 0) {
# endif
# endif
negative = diff < 0;
if (diff == 0) {
#ifdef TM_ZONE
negative = t->TM_ZONE[0] == '-';
#else
negative = t->tm_isdst < 0;
# if HAVE_TZNAME
if (tzname[t->tm_isdst != 0][0] == '-')
negative = true;
# endif
#endif
}
if (negative) {
sign = "-";
diff = -diff;
} else sign = "+";
@ -596,6 +618,7 @@ label:
(diff % MINSPERHOUR);
pt = _conv(diff, getformat(modifier, "04", " 4", " ", "04"), pt, ptlim);
}
#endif
continue;
case '+':
pt = _fmt(Locale->date_fmt, t, pt, ptlim,

View file

@ -1,3 +1,5 @@
/* Layout and location of TZif files. */
#ifndef TZFILE_H
#define TZFILE_H
@ -20,17 +22,20 @@
*/
#ifndef TZDIR
#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */
#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
#define TZDEFAULT "localtime"
#define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES
#define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */
/* See Internet RFC 8536 for more details about the following format. */
/*
** Each file begins with. . .
*/
@ -39,9 +44,9 @@
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */
char tzh_reserved[15]; /* reserved; must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
char tzh_timecnt[4]; /* coded number of transition times */
@ -64,14 +69,15 @@ struct tzhead {
** one (char [4]) total correction after above
** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
** time is standard time, if 0,
** transition time is wall clock time
** if absent, transition times are
** assumed to be wall clock time
** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
** time is UT, if 0,
** transition time is local time
** if absent, transition times are
** transition time is local (wall clock)
** time; if absent, transition times are
** assumed to be local time
** tzh_ttisutcnt (char)s indexed by type; if 1, transition
** time is UT, if 0, transition time is
** local time; if absent, transition
** times are assumed to be local time.
** When this is 1, the corresponding
** std/wall indicator must also be 1.
*/
/*

View file

@ -184,6 +184,24 @@ TEST(time, mktime_EOVERFLOW) {
ASSERT_EQ(EOVERFLOW, errno);
}
TEST(time, mktime_invalid_tm_TZ_combination) {
setenv("TZ", "UTC", 1);
struct tm t;
memset(&t, 0, sizeof(tm));
t.tm_year = 2022 - 1900;
t.tm_mon = 11;
t.tm_mday = 31;
// UTC does not observe DST
t.tm_isdst = 1;
errno = 0;
EXPECT_EQ(static_cast<time_t>(-1), mktime(&t));
// mktime sets errno to EOVERFLOW if result is unrepresentable.
EXPECT_EQ(EOVERFLOW, errno);
}
TEST(time, strftime) {
setenv("TZ", "UTC", 1);
@ -206,6 +224,24 @@ TEST(time, strftime) {
EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
}
TEST(time, strftime_second_before_epoch) {
setenv("TZ", "UTC", 1);
struct tm t;
memset(&t, 0, sizeof(tm));
t.tm_year = 1969 - 1900;
t.tm_mon = 11;
t.tm_mday = 31;
t.tm_hour = 23;
t.tm_min = 59;
t.tm_sec = 59;
char buf[64];
EXPECT_EQ(2U, strftime(buf, sizeof(buf), "%s", &t));
EXPECT_STREQ("-1", buf);
}
TEST(time, strftime_null_tm_zone) {
// Netflix on Nexus Player wouldn't start (http://b/25170306).
struct tm t;