Changeset View
Changeset View
Standalone View
Standalone View
contrib/tzcode/localtime.c
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | static void unlock(void) { | ||||
if (__isthreaded) | if (__isthreaded) | ||||
_pthread_mutex_unlock(&locallock); | _pthread_mutex_unlock(&locallock); | ||||
} | } | ||||
#else | #else | ||||
static int lock(void) { return 0; } | static int lock(void) { return 0; } | ||||
static void unlock(void) { } | static void unlock(void) { } | ||||
#endif | #endif | ||||
#ifndef TZ_ABBR_MAX_LEN | |||||
# define TZ_ABBR_MAX_LEN 16 | |||||
#endif /* !defined TZ_ABBR_MAX_LEN */ | |||||
#ifndef TZ_ABBR_CHAR_SET | #ifndef TZ_ABBR_CHAR_SET | ||||
# define TZ_ABBR_CHAR_SET \ | # define TZ_ABBR_CHAR_SET \ | ||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" | ||||
#endif /* !defined TZ_ABBR_CHAR_SET */ | #endif /* !defined TZ_ABBR_CHAR_SET */ | ||||
#ifndef TZ_ABBR_ERR_CHAR | #ifndef TZ_ABBR_ERR_CHAR | ||||
# define TZ_ABBR_ERR_CHAR '_' | # define TZ_ABBR_ERR_CHAR '_' | ||||
#endif /* !defined TZ_ABBR_ERR_CHAR */ | #endif /* !defined TZ_ABBR_ERR_CHAR */ | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
static char const UNSPEC[] = "-00"; | static char const UNSPEC[] = "-00"; | ||||
/* How many extra bytes are needed at the end of struct state's chars array. | /* How many extra bytes are needed at the end of struct state's chars array. | ||||
This needs to be at least 1 for null termination in case the input | This needs to be at least 1 for null termination in case the input | ||||
data isn't properly terminated, and it also needs to be big enough | data isn't properly terminated, and it also needs to be big enough | ||||
for ttunspecified to work without crashing. */ | for ttunspecified to work without crashing. */ | ||||
enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 }; | enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 }; | ||||
#ifdef TZNAME_MAX | /* Limit to time zone abbreviation length in POSIX-style TZ strings. | ||||
# define MY_TZNAME_MAX TZNAME_MAX | This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */ | ||||
#endif /* defined TZNAME_MAX */ | #ifndef TZNAME_MAXIMUM | ||||
#ifndef TZNAME_MAX | # define TZNAME_MAXIMUM 255 | ||||
# define MY_TZNAME_MAX 255 | #endif | ||||
#endif /* !defined TZNAME_MAX */ | |||||
struct state { | struct state { | ||||
int leapcnt; | int leapcnt; | ||||
int timecnt; | int timecnt; | ||||
int typecnt; | int typecnt; | ||||
int charcnt; | int charcnt; | ||||
bool goback; | bool goback; | ||||
bool goahead; | bool goahead; | ||||
time_t ats[TZ_MAX_TIMES]; | time_t ats[TZ_MAX_TIMES]; | ||||
unsigned char types[TZ_MAX_TIMES]; | unsigned char types[TZ_MAX_TIMES]; | ||||
struct ttinfo ttis[TZ_MAX_TYPES]; | struct ttinfo ttis[TZ_MAX_TYPES]; | ||||
char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"), | char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"), | ||||
2 * (MY_TZNAME_MAX + 1))]; | 2 * (TZNAME_MAXIMUM + 1))]; | ||||
struct lsinfo lsis[TZ_MAX_LEAPS]; | struct lsinfo lsis[TZ_MAX_LEAPS]; | ||||
/* The time type to use for early times or if no transitions. | /* The time type to use for early times or if no transitions. | ||||
It is always zero for recent tzdb releases. | It is always zero for recent tzdb releases. | ||||
It might be nonzero for data from tzdb 2018e or earlier. */ | It might be nonzero for data from tzdb 2018e or earlier. */ | ||||
int defaulttype; | int defaulttype; | ||||
}; | }; | ||||
Show All 40 Lines | |||||
static char lcl_TZname[TZ_STRLEN_MAX + 1]; | static char lcl_TZname[TZ_STRLEN_MAX + 1]; | ||||
static int lcl_is_set; | static int lcl_is_set; | ||||
static pthread_once_t gmt_once = PTHREAD_ONCE_INIT; | static pthread_once_t gmt_once = PTHREAD_ONCE_INIT; | ||||
static pthread_once_t gmtime_once = PTHREAD_ONCE_INIT; | static pthread_once_t gmtime_once = PTHREAD_ONCE_INIT; | ||||
static pthread_key_t gmtime_key; | static pthread_key_t gmtime_key; | ||||
static int gmtime_key_error; | static int gmtime_key_error; | ||||
static pthread_once_t offtime_once = PTHREAD_ONCE_INIT; | |||||
static pthread_key_t offtime_key; | |||||
static int offtime_key_error; | |||||
static pthread_once_t localtime_once = PTHREAD_ONCE_INIT; | static pthread_once_t localtime_once = PTHREAD_ONCE_INIT; | ||||
static pthread_key_t localtime_key; | static pthread_key_t localtime_key; | ||||
static int localtime_key_error; | static int localtime_key_error; | ||||
/* | /* | ||||
** Section 4.12.3 of X3.159-1989 requires that | ** Section 4.12.3 of X3.159-1989 requires that | ||||
** Except for the strftime function, these functions [asctime, | ** Except for the strftime function, these functions [asctime, | ||||
** ctime, gmtime, localtime] return values in one of two static | ** ctime, gmtime, localtime] return values in one of two static | ||||
** objects: a broken-down time structure and an array of char. | ** objects: a broken-down time structure and an array of char. | ||||
** Thanks to Paul Eggert for noting this. | ** Thanks to Paul Eggert for noting this. | ||||
** | |||||
** This requirement was removed in C99, so support it only if requested, | |||||
** as support is more likely to lead to bugs in badly written programs. | |||||
*/ | */ | ||||
#if SUPPORT_C89 | |||||
static struct tm tm; | static struct tm tm; | ||||
#endif | |||||
#if 2 <= HAVE_TZNAME + TZ_TIME_T | #if 2 <= HAVE_TZNAME + TZ_TIME_T | ||||
char * tzname[2] = { | char * tzname[2] = { | ||||
(char *) wildabbr, | (char *) wildabbr, | ||||
(char *) wildabbr | (char *) wildabbr | ||||
}; | }; | ||||
#endif | #endif | ||||
#if 2 <= USG_COMPAT + TZ_TIME_T | #if 2 <= USG_COMPAT + TZ_TIME_T | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | if (sp) { | ||||
for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--) | for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--) | ||||
stddst_mask = may_update_tzname_etc(stddst_mask, sp, i); | stddst_mask = may_update_tzname_etc(stddst_mask, sp, i); | ||||
} | } | ||||
#if USG_COMPAT | #if USG_COMPAT | ||||
daylight = stddst_mask >> 1 ^ 1; | daylight = stddst_mask >> 1 ^ 1; | ||||
#endif | #endif | ||||
} | } | ||||
static void | /* Replace bogus characters in time zone abbreviations. | ||||
Return 0 on success, an errno value if a time zone abbreviation is | |||||
too long. */ | |||||
static int | |||||
scrub_abbrs(struct state *sp) | scrub_abbrs(struct state *sp) | ||||
{ | { | ||||
int i; | int i; | ||||
/* | |||||
** First, replace bogus characters. | /* Reject overlong abbreviations. */ | ||||
*/ | for (i = 0; i < sp->charcnt - (TZNAME_MAXIMUM + 1); ) { | ||||
int len = strlen(&sp->chars[i]); | |||||
if (TZNAME_MAXIMUM < len) | |||||
return EOVERFLOW; | |||||
i += len + 1; | |||||
} | |||||
/* Replace bogus characters. */ | |||||
for (i = 0; i < sp->charcnt; ++i) | for (i = 0; i < sp->charcnt; ++i) | ||||
if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL) | if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL) | ||||
sp->chars[i] = TZ_ABBR_ERR_CHAR; | sp->chars[i] = TZ_ABBR_ERR_CHAR; | ||||
/* | |||||
** Second, truncate long abbreviations. | |||||
*/ | |||||
for (i = 0; i < sp->typecnt; ++i) { | |||||
register const struct ttinfo * const ttisp = &sp->ttis[i]; | |||||
char *cp = &sp->chars[ttisp->tt_desigidx]; | |||||
if (strlen(cp) > TZ_ABBR_MAX_LEN && | return 0; | ||||
strcmp(cp, GRANDPARENTED) != 0) | |||||
*(cp + TZ_ABBR_MAX_LEN) = '\0'; | |||||
} | } | ||||
} | |||||
#ifdef DETECT_TZ_CHANGES | #ifdef DETECT_TZ_CHANGES | ||||
/* | /* | ||||
* Determine if there's a change in the timezone since the last time we checked. | * Determine if there's a change in the timezone since the last time we checked. | ||||
* Returns: -1 on error | * Returns: -1 on error | ||||
* 0 if the timezone has not changed | * 0 if the timezone has not changed | ||||
* 1 if the timezone has changed | * 1 if the timezone has changed | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 493 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
** Given a pointer into a timezone string, scan until a character that is not | ** Given a pointer into a timezone string, scan until a character that is not | ||||
** a valid character in a time zone abbreviation is found. | ** a valid character in a time zone abbreviation is found. | ||||
** Return a pointer to that character. | ** Return a pointer to that character. | ||||
*/ | */ | ||||
static ATTRIBUTE_REPRODUCIBLE const char * | ATTRIBUTE_REPRODUCIBLE static const char * | ||||
getzname(register const char *strp) | getzname(register const char *strp) | ||||
{ | { | ||||
register char c; | register char c; | ||||
while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && | while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && | ||||
c != '+') | c != '+') | ||||
++strp; | ++strp; | ||||
return strp; | return strp; | ||||
} | } | ||||
/* | /* | ||||
** Given a pointer into an extended timezone string, scan until the ending | ** Given a pointer into an extended timezone string, scan until the ending | ||||
** delimiter of the time zone abbreviation is located. | ** delimiter of the time zone abbreviation is located. | ||||
** Return a pointer to the delimiter. | ** Return a pointer to the delimiter. | ||||
** | ** | ||||
** As with getzname above, the legal character set is actually quite | ** As with getzname above, the legal character set is actually quite | ||||
** restricted, with other characters producing undefined results. | ** restricted, with other characters producing undefined results. | ||||
** We don't do any checking here; checking is done later in common-case code. | ** We don't do any checking here; checking is done later in common-case code. | ||||
*/ | */ | ||||
static ATTRIBUTE_REPRODUCIBLE const char * | ATTRIBUTE_REPRODUCIBLE static const char * | ||||
getqzname(register const char *strp, const int delim) | getqzname(register const char *strp, const int delim) | ||||
{ | { | ||||
register int c; | register int c; | ||||
while ((c = *strp) != '\0' && c != delim) | while ((c = *strp) != '\0' && c != delim) | ||||
++strp; | ++strp; | ||||
return strp; | return strp; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 263 Lines • ▼ Show 20 Lines | if (*name == '<') { | ||||
if (*name != '>') | if (*name != '>') | ||||
return false; | return false; | ||||
stdlen = name - stdname; | stdlen = name - stdname; | ||||
name++; | name++; | ||||
} else { | } else { | ||||
name = getzname(name); | name = getzname(name); | ||||
stdlen = name - stdname; | stdlen = name - stdname; | ||||
} | } | ||||
if (!stdlen) | if (! (0 < stdlen && stdlen <= TZNAME_MAXIMUM)) | ||||
return false; | return false; | ||||
name = getoffset(name, &stdoffset); | name = getoffset(name, &stdoffset); | ||||
if (name == NULL) | if (name == NULL) | ||||
return false; | return false; | ||||
charcnt = stdlen + 1; | charcnt = stdlen + 1; | ||||
if (sizeof sp->chars < charcnt) | |||||
return false; | |||||
if (basep) { | if (basep) { | ||||
if (0 < basep->timecnt) | if (0 < basep->timecnt) | ||||
atlo = basep->ats[basep->timecnt - 1]; | atlo = basep->ats[basep->timecnt - 1]; | ||||
load_ok = false; | load_ok = false; | ||||
sp->leapcnt = basep->leapcnt; | sp->leapcnt = basep->leapcnt; | ||||
memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis); | memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis); | ||||
} else { | } else { | ||||
load_ok = tzload(TZDEFRULES, sp, false) == 0; | load_ok = tzload(TZDEFRULES, sp, false) == 0; | ||||
Show All 10 Lines | if (*name == '<') { | ||||
return false; | return false; | ||||
dstlen = name - dstname; | dstlen = name - dstname; | ||||
name++; | name++; | ||||
} else { | } else { | ||||
dstname = name; | dstname = name; | ||||
name = getzname(name); | name = getzname(name); | ||||
dstlen = name - dstname; /* length of DST abbr. */ | dstlen = name - dstname; /* length of DST abbr. */ | ||||
} | } | ||||
if (!dstlen) | if (! (0 < dstlen && dstlen <= TZNAME_MAXIMUM)) | ||||
return false; | return false; | ||||
charcnt += dstlen + 1; | charcnt += dstlen + 1; | ||||
if (sizeof sp->chars < charcnt) | |||||
return false; | |||||
if (*name != '\0' && *name != ',' && *name != ';') { | if (*name != '\0' && *name != ',' && *name != ';') { | ||||
name = getoffset(name, &dstoffset); | name = getoffset(name, &dstoffset); | ||||
if (name == NULL) | if (name == NULL) | ||||
return false; | return false; | ||||
} else dstoffset = stdoffset - SECSPERHOUR; | } else dstoffset = stdoffset - SECSPERHOUR; | ||||
if (*name == '\0' && !load_ok) | if (*name == '\0' && !load_ok) | ||||
name = TZDEFRULESTRING; | name = TZDEFRULESTRING; | ||||
if (*name == ',' || *name == ';') { | if (*name == ',' || *name == ';') { | ||||
▲ Show 20 Lines • Show All 257 Lines • ▼ Show 20 Lines | if (name && ! name[0]) { | ||||
strcpy(sp->chars, utc); | strcpy(sp->chars, utc); | ||||
sp->defaulttype = 0; | sp->defaulttype = 0; | ||||
return 0; | return 0; | ||||
} else { | } else { | ||||
int err = tzload(name, sp, true); | int err = tzload(name, sp, true); | ||||
if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL)) | if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL)) | ||||
err = 0; | err = 0; | ||||
if (err == 0) | if (err == 0) | ||||
scrub_abbrs(sp); | err = scrub_abbrs(sp); | ||||
return err; | return err; | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
tzset_unlocked_name(char const *name) | tzset_unlocked_name(char const *name) | ||||
{ | { | ||||
struct state *sp = lclptr; | struct state *sp = lclptr; | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | if (setname) | ||||
update_tzname_etc(sp, ttisp); | update_tzname_etc(sp, ttisp); | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
#if NETBSD_INSPIRED | #if NETBSD_INSPIRED | ||||
struct tm * | struct tm * | ||||
localtime_rz(struct state *sp, time_t const *timep, struct tm *tmp) | localtime_rz(struct state *restrict sp, time_t const *restrict timep, | ||||
struct tm *restrict tmp) | |||||
{ | { | ||||
return localsub(sp, timep, 0, tmp); | return localsub(sp, timep, 0, tmp); | ||||
} | } | ||||
#endif | #endif | ||||
static struct tm * | static struct tm * | ||||
localtime_tzset(time_t const *timep, struct tm *tmp, bool setname) | localtime_tzset(time_t const *timep, struct tm *tmp, bool setname) | ||||
Show All 17 Lines | |||||
{ | { | ||||
localtime_key_error = _pthread_key_create(&localtime_key, free); | localtime_key_error = _pthread_key_create(&localtime_key, free); | ||||
} | } | ||||
struct tm * | struct tm * | ||||
localtime(const time_t *timep) | localtime(const time_t *timep) | ||||
{ | { | ||||
#if !SUPPORT_C89 | |||||
static struct tm tm; | |||||
#endif | |||||
struct tm *p_tm = &tm; | struct tm *p_tm = &tm; | ||||
if (__isthreaded != 0) { | if (__isthreaded != 0) { | ||||
_pthread_once(&localtime_once, localtime_key_init); | _pthread_once(&localtime_once, localtime_key_init); | ||||
if (localtime_key_error != 0) { | if (localtime_key_error != 0) { | ||||
errno = localtime_key_error; | errno = localtime_key_error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if ((p_tm = _pthread_getspecific(localtime_key)) == NULL) { | if ((p_tm = _pthread_getspecific(localtime_key)) == NULL) { | ||||
if ((p_tm = malloc(sizeof(*p_tm))) == NULL) { | if ((p_tm = malloc(sizeof(*p_tm))) == NULL) { | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if (_pthread_setspecific(localtime_key, p_tm) != 0) { | if (_pthread_setspecific(localtime_key, p_tm) != 0) { | ||||
free(p_tm); | free(p_tm); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return localtime_tzset(timep, p_tm, true); | return localtime_tzset(timep, p_tm, true); | ||||
} | } | ||||
struct tm * | struct tm * | ||||
localtime_r(const time_t *timep, struct tm *tmp) | localtime_r(const time_t *restrict timep, struct tm *restrict tmp) | ||||
{ | { | ||||
return localtime_tzset(timep, tmp, false); | return localtime_tzset(timep, tmp, false); | ||||
} | } | ||||
/* | /* | ||||
** gmtsub is to gmtime as localsub is to localtime. | ** gmtsub is to gmtime as localsub is to localtime. | ||||
*/ | */ | ||||
Show All 16 Lines | #endif /* defined TM_ZONE */ | ||||
return result; | return result; | ||||
} | } | ||||
/* | /* | ||||
* Re-entrant version of gmtime. | * Re-entrant version of gmtime. | ||||
*/ | */ | ||||
struct tm * | struct tm * | ||||
gmtime_r(const time_t *timep, struct tm *tmp) | gmtime_r(time_t const *restrict timep, struct tm *restrict tmp) | ||||
{ | { | ||||
_once(&gmt_once, gmtcheck); | _once(&gmt_once, gmtcheck); | ||||
return gmtsub(gmtptr, timep, 0, tmp); | return gmtsub(gmtptr, timep, 0, tmp); | ||||
} | } | ||||
static void | static void | ||||
gmtime_key_init(void) | gmtime_key_init(void) | ||||
{ | { | ||||
gmtime_key_error = _pthread_key_create(&gmtime_key, free); | gmtime_key_error = _pthread_key_create(&gmtime_key, free); | ||||
} | } | ||||
struct tm * | struct tm * | ||||
gmtime(const time_t *timep) | gmtime(const time_t *timep) | ||||
{ | { | ||||
#if !SUPPORT_C89 | |||||
static struct tm tm; | |||||
#endif | |||||
struct tm *p_tm = &tm; | struct tm *p_tm = &tm; | ||||
if (__isthreaded != 0) { | if (__isthreaded != 0) { | ||||
_pthread_once(&gmtime_once, gmtime_key_init); | _pthread_once(&gmtime_once, gmtime_key_init); | ||||
if (gmtime_key_error != 0) { | if (gmtime_key_error != 0) { | ||||
errno = gmtime_key_error; | errno = gmtime_key_error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) { | if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) { | ||||
if ((p_tm = malloc(sizeof(*p_tm))) == NULL) { | if ((p_tm = malloc(sizeof(*p_tm))) == NULL) { | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if (_pthread_setspecific(gmtime_key, p_tm) != 0) { | if (_pthread_setspecific(gmtime_key, p_tm) != 0) { | ||||
free(p_tm); | free(p_tm); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return gmtime_r(timep, p_tm); | return gmtime_r(timep, p_tm); | ||||
} | } | ||||
#ifdef STD_INSPIRED | #if STD_INSPIRED | ||||
struct tm * | struct tm * | ||||
offtime(const time_t *timep, long offset) | offtime_r(time_t const *restrict timep, long offset, struct tm *restrict tmp) | ||||
{ | { | ||||
_once(&gmt_once, gmtcheck); | _once(&gmt_once, gmtcheck); | ||||
return gmtsub(gmtptr, timep, offset, &tm); | return gmtsub(gmtptr, timep, offset, tmp); | ||||
} | } | ||||
#endif /* defined STD_INSPIRED */ | static void | ||||
offtime_key_init(void) | |||||
{ | |||||
offtime_key_error = _pthread_key_create(&offtime_key, free); | |||||
} | |||||
struct tm * | |||||
offtime(const time_t *timep, long offset) | |||||
{ | |||||
#if !SUPPORT_C89 | |||||
static struct tm tm; | |||||
#endif | |||||
struct tm *p_tm = &tm; | |||||
if (__isthreaded != 0) { | |||||
_pthread_once(&offtime_once, offtime_key_init); | |||||
if (offtime_key_error != 0) { | |||||
errno = offtime_key_error; | |||||
return (NULL); | |||||
} | |||||
if ((p_tm = _pthread_getspecific(offtime_key)) == NULL) { | |||||
if ((p_tm = malloc(sizeof(*p_tm))) == NULL) { | |||||
return (NULL); | |||||
} | |||||
if (_pthread_setspecific(offtime_key, p_tm) != 0) { | |||||
free(p_tm); | |||||
return (NULL); | |||||
} | |||||
} | |||||
} | |||||
return offtime_r(timep, offset, p_tm); | |||||
} | |||||
#endif | |||||
/* | /* | ||||
** Return the number of leap years through the end of the given year | ** Return the number of leap years through the end of the given year | ||||
** where, to make the math easy, the answer for year zero is defined as zero. | ** where, to make the math easy, the answer for year zero is defined as zero. | ||||
*/ | */ | ||||
static time_t | static time_t | ||||
leaps_thru_end_of_nonneg(time_t y) | leaps_thru_end_of_nonneg(time_t y) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | #endif | ||||
tmp->tm_mday = idays + 1; | tmp->tm_mday = idays + 1; | ||||
tmp->tm_isdst = 0; | tmp->tm_isdst = 0; | ||||
#ifdef TM_GMTOFF | #ifdef TM_GMTOFF | ||||
tmp->TM_GMTOFF = offset; | tmp->TM_GMTOFF = offset; | ||||
#endif /* defined TM_GMTOFF */ | #endif /* defined TM_GMTOFF */ | ||||
return tmp; | return tmp; | ||||
} | } | ||||
char * | |||||
ctime(const time_t *timep) | |||||
{ | |||||
/* | /* | ||||
** Section 4.12.3.2 of X3.159-1989 requires that | |||||
** The ctime function converts the calendar time pointed to by timer | |||||
** to local time in the form of a string. It is equivalent to | |||||
** asctime(localtime(timer)) | |||||
*/ | |||||
struct tm *tmp = localtime(timep); | |||||
return tmp ? asctime(tmp) : NULL; | |||||
} | |||||
char * | |||||
ctime_r(const time_t *timep, char *buf) | |||||
{ | |||||
struct tm mytm; | |||||
struct tm *tmp = localtime_r(timep, &mytm); | |||||
return tmp ? asctime_r(tmp, buf) : NULL; | |||||
} | |||||
/* | |||||
** Adapted from code provided by Robert Elz, who writes: | ** Adapted from code provided by Robert Elz, who writes: | ||||
** The "best" way to do mktime I think is based on an idea of Bob | ** The "best" way to do mktime I think is based on an idea of Bob | ||||
** Kridle's (so its said...) from a long time ago. | ** Kridle's (so its said...) from a long time ago. | ||||
** It does a binary search of the time_t space. Since time_t's are | ** It does a binary search of the time_t space. Since time_t's are | ||||
** just 32 bits, its a max of 32 iterations (even at 64 bits it | ** just 32 bits, its a max of 32 iterations (even at 64 bits it | ||||
** would still be very reasonable). | ** would still be very reasonable). | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 424 Lines • ▼ Show 20 Lines | else { | ||||
_once(&gmt_once, gmtcheck); | _once(&gmt_once, gmtcheck); | ||||
return time1(tmp, gmtsub, gmtptr, 0); | return time1(tmp, gmtsub, gmtptr, 0); | ||||
} | } | ||||
} | } | ||||
#if NETBSD_INSPIRED | #if NETBSD_INSPIRED | ||||
time_t | time_t | ||||
mktime_z(struct state *sp, struct tm *tmp) | mktime_z(struct state *restrict sp, struct tm *restrict tmp) | ||||
{ | { | ||||
return mktime_tzname(sp, tmp, false); | return mktime_tzname(sp, tmp, false); | ||||
} | } | ||||
#endif | #endif | ||||
time_t | time_t | ||||
mktime(struct tm *tmp) | mktime(struct tm *tmp) | ||||
{ | { | ||||
time_t t; | time_t t; | ||||
int err = lock(); | int err = lock(); | ||||
if (err) { | if (err) { | ||||
errno = err; | errno = err; | ||||
return -1; | return -1; | ||||
} | } | ||||
tzset_unlocked(); | tzset_unlocked(); | ||||
t = mktime_tzname(lclptr, tmp, true); | t = mktime_tzname(lclptr, tmp, true); | ||||
unlock(); | unlock(); | ||||
return t; | return t; | ||||
} | } | ||||
#ifdef STD_INSPIRED | #if STD_INSPIRED | ||||
time_t | time_t | ||||
timelocal(struct tm *tmp) | timelocal(struct tm *tmp) | ||||
{ | { | ||||
if (tmp != NULL) | if (tmp != NULL) | ||||
tmp->tm_isdst = -1; /* in case it wasn't initialized */ | tmp->tm_isdst = -1; /* in case it wasn't initialized */ | ||||
return mktime(tmp); | return mktime(tmp); | ||||
} | } | ||||
#else | #else | ||||
Show All 35 Lines | leapcorr(struct state const *sp, time_t t) | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
/* | /* | ||||
** XXX--is the below the right way to conditionalize?? | ** XXX--is the below the right way to conditionalize?? | ||||
*/ | */ | ||||
#ifdef STD_INSPIRED | #if STD_INSPIRED | ||||
/* NETBSD_INSPIRED_EXTERN functions are exported to callers if | /* NETBSD_INSPIRED_EXTERN functions are exported to callers if | ||||
NETBSD_INSPIRED is defined, and are private otherwise. */ | NETBSD_INSPIRED is defined, and are private otherwise. */ | ||||
# if NETBSD_INSPIRED | # if NETBSD_INSPIRED | ||||
# define NETBSD_INSPIRED_EXTERN | # define NETBSD_INSPIRED_EXTERN | ||||
# else | # else | ||||
# define NETBSD_INSPIRED_EXTERN static | # define NETBSD_INSPIRED_EXTERN static | ||||
# endif | # endif | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
tzset_unlocked(); | tzset_unlocked(); | ||||
if (lclptr) | if (lclptr) | ||||
t = posix2time_z(lclptr, t); | t = posix2time_z(lclptr, t); | ||||
unlock(); | unlock(); | ||||
return t; | return t; | ||||
} | } | ||||
#endif /* defined STD_INSPIRED */ | #endif /* STD_INSPIRED */ | ||||
#if TZ_TIME_T | #if TZ_TIME_T | ||||
# if !USG_COMPAT | # if !USG_COMPAT | ||||
# define daylight 0 | # define daylight 0 | ||||
# define timezone 0 | # define timezone 0 | ||||
# endif | # endif | ||||
# if !ALTZONE | # if !ALTZONE | ||||
Show All 32 Lines |