5411aff6bb
Upstream has renamed tzsetlcl to tzset_unlocked. As bionic's implementation of tzset_unlock differs from upstream, these changes were skipped. Also, upstream has removed constants (SECSPERMIN, etc) from tzfile.h. As they are used in strptime.c, I've decided to leave them in tzfile.h and to not bring them into strptime.c. HAVE_TZNAME and USG_COMPAT flags semantics were updated, thus setting their values to 2 in Android.bp file. See1a27ec76bc
*4742526b7e
and0e8f0b06ac
were picked up, which are not part of 2022a. Changes were applied using following commands: 1) Checkout tzcode repo 2) Prepare patches for all tzcode file using git diff 2016g 2021e -- <file-name> > <file-name-patch> 3) Apply these patches to files in bionic using patch -p1 <file-name> <file-name-patch> Bug: 25413083 Test: CtsLibcoreTestCases Test: CtsLibcoreOjTestCases Test: CtsBionicTestCases Change-Id: I9aba4cbeab30171a32f94d20c8e4057804a4c01f
122 lines
4.1 KiB
C
122 lines
4.1 KiB
C
/* 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.
|
|
*/
|
|
|
|
/*
|
|
** Avoid the temptation to punt entirely to strftime;
|
|
** the output of strftime is supposed to be locale specific
|
|
** whereas the output of asctime is supposed to be constant.
|
|
*/
|
|
|
|
/*LINTLIBRARY*/
|
|
|
|
#include "private.h"
|
|
#include <stdio.h>
|
|
|
|
/*
|
|
** Some systems only handle "%.2d"; others only handle "%02d";
|
|
** "%02.2d" makes (most) everybody happy.
|
|
** At least some versions of gcc warn about the %02.2d;
|
|
** we conditionalize below to avoid the warning.
|
|
*/
|
|
/*
|
|
** All years associated with 32-bit time_t values are exactly four digits long;
|
|
** some years associated with 64-bit time_t values are not.
|
|
** Vintage programs are coded for years that are always four digits long
|
|
** and may assume that the newline always lands in the same place.
|
|
** For years that are less than four digits, we pad the output with
|
|
** 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 and POSIX standards prohibit padding the year,
|
|
** but many implementations pad anyway; most likely the standards are buggy.
|
|
*/
|
|
#ifdef __GNUC__
|
|
#define ASCTIME_FMT "%s %s%3d %2.2d:%2.2d:%2.2d %-4s\n"
|
|
#else /* !defined __GNUC__ */
|
|
#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
|
|
** so that code trying to overwrite the newline won't end up overwriting
|
|
** a digit within a year and truncating the year (operating on the assumption
|
|
** that no output is better than wrong output).
|
|
*/
|
|
#ifdef __GNUC__
|
|
#define ASCTIME_FMT_B "%s %s%3d %2.2d:%2.2d:%2.2d %s\n"
|
|
#else /* !defined __GNUC__ */
|
|
#define ASCTIME_FMT_B "%s %s%3d %02.2d:%02.2d:%02.2d %s\n"
|
|
#endif /* !defined __GNUC__ */
|
|
|
|
#define STD_ASCTIME_BUF_SIZE 26
|
|
/*
|
|
** Big enough for something such as
|
|
** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
|
|
** (two three-character abbreviations, five strings denoting integers,
|
|
** seven explicit spaces, two explicit colons, a newline,
|
|
** and a trailing NUL byte).
|
|
** The values above are for systems where an int is 32 bits and are provided
|
|
** as an example; the define below calculates the maximum for the system at
|
|
** hand.
|
|
*/
|
|
#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1)
|
|
|
|
static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
|
|
|
|
char *
|
|
asctime_r(register const struct tm *timeptr, char *buf)
|
|
{
|
|
static const char wday_name[][4] = {
|
|
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
|
};
|
|
static const char mon_name[][4] = {
|
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|
};
|
|
register const char * wn;
|
|
register const char * mn;
|
|
char year[INT_STRLEN_MAXIMUM(int) + 2];
|
|
char result[MAX_ASCTIME_BUF_SIZE];
|
|
|
|
if (timeptr == NULL) {
|
|
errno = EINVAL;
|
|
return strcpy(buf, "??? ??? ?? ??:??:?? ????\n");
|
|
}
|
|
if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
|
|
wn = "???";
|
|
else wn = wday_name[timeptr->tm_wday];
|
|
if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
|
|
mn = "???";
|
|
else mn = mon_name[timeptr->tm_mon];
|
|
/*
|
|
** Use strftime's %Y to generate the year, to avoid overflow problems
|
|
** when computing timeptr->tm_year + TM_YEAR_BASE.
|
|
** Assume that strftime is unaffected by other out-of-range members
|
|
** (e.g., timeptr->tm_mday) when processing "%Y".
|
|
*/
|
|
strftime(year, sizeof year, "%Y", timeptr);
|
|
/*
|
|
** We avoid using snprintf since it's not available on all systems.
|
|
*/
|
|
snprintf(result, sizeof(result), /* Android change: use snprintf. */
|
|
((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
|
|
wn, mn,
|
|
timeptr->tm_mday, timeptr->tm_hour,
|
|
timeptr->tm_min, timeptr->tm_sec,
|
|
year);
|
|
if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
|
|
return strcpy(buf, result);
|
|
else {
|
|
errno = EOVERFLOW;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
char *
|
|
asctime(register const struct tm *timeptr)
|
|
{
|
|
return asctime_r(timeptr, buf_asctime);
|
|
}
|