summaryrefslogtreecommitdiff
path: root/elsie.nci.nih.gov/src/localtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'elsie.nci.nih.gov/src/localtime.c')
-rw-r--r--elsie.nci.nih.gov/src/localtime.c389
1 files changed, 224 insertions, 165 deletions
diff --git a/elsie.nci.nih.gov/src/localtime.c b/elsie.nci.nih.gov/src/localtime.c
index 622f7d4..63a1816 100644
--- a/elsie.nci.nih.gov/src/localtime.c
+++ b/elsie.nci.nih.gov/src/localtime.c
@@ -18,12 +18,10 @@
#if THREAD_SAFE
# include <pthread.h>
-# define VOLATILE volatile
static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
static int lock(void) { return pthread_mutex_lock(&locallock); }
static void unlock(void) { pthread_mutex_unlock(&locallock); }
#else
-# define VOLATILE
static int lock(void) { return 0; }
static void unlock(void) { }
#endif
@@ -176,7 +174,7 @@ static struct state gmtmem;
#endif /* !defined TZ_STRLEN_MAX */
static char lcl_TZname[TZ_STRLEN_MAX + 1];
-static int VOLATILE lcl_is_set;
+static int lcl_is_set;
char * tzname[2] = {
(char *) wildabbr,
@@ -202,6 +200,17 @@ int daylight = 0;
long altzone = 0;
#endif /* defined ALTZONE */
+/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
+static void
+init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
+{
+ s->tt_gmtoff = gmtoff;
+ s->tt_isdst = isdst;
+ s->tt_abbrind = abbrind;
+ s->tt_ttisstd = false;
+ s->tt_ttisgmt = false;
+}
+
static int_fast32_t
detzcode(const char *const codep)
{
@@ -298,67 +307,64 @@ differ_by_repeat(const time_t t1, const time_t t0)
return t1 - t0 == SECSPERREPEAT;
}
-static bool
-tzload(register const char *name, register struct state *const sp,
- bool doextend)
+/* Input buffer for data read from a compiled tz file. */
+union input_buffer {
+ /* The first part of the buffer, interpreted as a header. */
+ struct tzhead tzhead;
+
+ /* The entire buffer. */
+ char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
+ + 4 * TZ_MAX_TIMES];
+};
+
+/* Local storage needed for 'tzloadbody'. */
+union local_storage {
+ /* The file name to be opened. */
+ char fullname[FILENAME_MAX + 1];
+
+ /* The results of analyzing the file's contents after it is opened. */
+ struct {
+ /* The input buffer. */
+ union input_buffer u;
+
+ /* A temporary state used for parsing a TZ string in the file. */
+ struct state st;
+ } u;
+};
+
+/* Load tz data from the file named NAME into *SP. Read extended
+ format if DOEXTEND. Use *LSP for temporary storage. Return 0 on
+ success, an errno value on failure. */
+static int
+tzloadbody(char const *name, struct state *sp, bool doextend,
+ union local_storage *lsp)
{
- register const char * p;
register int i;
register int fid;
register int stored;
- register int nread;
- typedef union {
- struct tzhead tzhead;
- char buf[2 * sizeof(struct tzhead) +
- 2 * sizeof *sp +
- 4 * TZ_MAX_TIMES];
- } u_t;
- union local_storage {
- /*
- ** Section 4.9.1 of the C standard says that
- ** "FILENAME_MAX expands to an integral constant expression
- ** that is the size needed for an array of char large enough
- ** to hold the longest file name string that the implementation
- ** guarantees can be opened."
- */
- char fullname[FILENAME_MAX + 1];
-
- /* The main part of the storage for this function. */
- struct {
- u_t u;
- struct state st;
- } u;
- };
- register char *fullname;
- register u_t *up;
+ register ssize_t nread;
register bool doaccess;
- register union local_storage *lsp;
-#ifdef ALL_STATE
- lsp = malloc(sizeof *lsp);
- if (!lsp)
- return false;
-#else /* !defined ALL_STATE */
- union local_storage ls;
- lsp = &ls;
-#endif /* !defined ALL_STATE */
- fullname = lsp->fullname;
- up = &lsp->u.u;
+ register char *fullname = lsp->fullname;
+ register union input_buffer *up = &lsp->u.u;
+ register int tzheadsize = sizeof (struct tzhead);
sp->goback = sp->goahead = false;
if (! name) {
name = TZDEFAULT;
if (! name)
- goto oops;
+ return EINVAL;
}
if (name[0] == ':')
++name;
doaccess = name[0] == '/';
if (!doaccess) {
- p = TZDIR;
- if (! p || sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
- goto oops;
+ char const *p = TZDIR;
+ if (! p)
+ return EINVAL;
+ if (sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
+ return ENAMETOOLONG;
strcpy(fullname, p);
strcat(fullname, "/");
strcat(fullname, name);
@@ -368,14 +374,19 @@ tzload(register const char *name, register struct state *const sp,
name = fullname;
}
if (doaccess && access(name, R_OK) != 0)
- goto oops;
+ return errno;
fid = open(name, OPEN_MODE);
if (fid < 0)
- goto oops;
+ return errno;
nread = read(fid, up->buf, sizeof up->buf);
- if (close(fid) < 0 || nread <= 0)
- goto oops;
+ if (nread < tzheadsize) {
+ int err = nread < 0 ? errno : EINVAL;
+ close(fid);
+ return err;
+ }
+ if (close(fid) < 0)
+ return errno;
for (stored = 4; stored <= 8; stored *= 2) {
int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
int_fast32_t ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
@@ -383,23 +394,24 @@ tzload(register const char *name, register struct state *const sp,
int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
- p = up->tzhead.tzh_charcnt + sizeof up->tzhead.tzh_charcnt;
+ char const *p = up->buf + tzheadsize;
if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
&& 0 < typecnt && typecnt < TZ_MAX_TYPES
&& 0 <= timecnt && timecnt < TZ_MAX_TIMES
&& 0 <= charcnt && charcnt < TZ_MAX_CHARS
&& (ttisstdcnt == typecnt || ttisstdcnt == 0)
&& (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
- goto oops;
- if (nread - (p - up->buf)
- < (timecnt * stored /* ats */
+ return EINVAL;
+ if (nread
+ < (tzheadsize /* struct tzhead */
+ + timecnt * stored /* ats */
+ timecnt /* types */
+ typecnt * 6 /* ttinfos */
+ charcnt /* chars */
+ leapcnt * (stored + 4) /* lsinfos */
+ ttisstdcnt /* ttisstds */
+ ttisgmtcnt)) /* ttisgmts */
- goto oops;
+ return EINVAL;
sp->leapcnt = leapcnt;
sp->timecnt = timecnt;
sp->typecnt = typecnt;
@@ -419,7 +431,7 @@ tzload(register const char *name, register struct state *const sp,
? time_t_min : at);
if (timecnt && attime <= sp->ats[timecnt - 1]) {
if (attime < sp->ats[timecnt - 1])
- goto oops;
+ return EINVAL;
sp->types[i - 1] = 0;
timecnt--;
}
@@ -432,7 +444,7 @@ tzload(register const char *name, register struct state *const sp,
for (i = 0; i < sp->timecnt; ++i) {
unsigned char typ = *p++;
if (sp->typecnt <= typ)
- goto oops;
+ return EINVAL;
if (sp->types[i])
sp->types[timecnt++] = typ;
}
@@ -446,11 +458,11 @@ tzload(register const char *name, register struct state *const sp,
p += 4;
isdst = *p++;
if (! (isdst < 2))
- goto oops;
+ return EINVAL;
ttisp->tt_isdst = isdst;
abbrind = *p++;
if (! (abbrind < sp->charcnt))
- goto oops;
+ return EINVAL;
ttisp->tt_abbrind = abbrind;
}
for (i = 0; i < sp->charcnt; ++i)
@@ -469,7 +481,7 @@ tzload(register const char *name, register struct state *const sp,
? time_t_min : tr);
if (leapcnt && trans <= sp->lsis[leapcnt - 1].ls_trans) {
if (trans < sp->lsis[leapcnt - 1].ls_trans)
- goto oops;
+ return EINVAL;
leapcnt--;
}
sp->lsis[leapcnt].ls_trans = trans;
@@ -487,7 +499,7 @@ tzload(register const char *name, register struct state *const sp,
ttisp->tt_ttisstd = false;
else {
if (*p != true && *p != false)
- goto oops;
+ return EINVAL;
ttisp->tt_ttisstd = *p++;
}
}
@@ -499,7 +511,7 @@ tzload(register const char *name, register struct state *const sp,
ttisp->tt_ttisgmt = false;
else {
if (*p != true && *p != false)
- goto oops;
+ return EINVAL;
ttisp->tt_ttisgmt = *p++;
}
}
@@ -509,8 +521,7 @@ tzload(register const char *name, register struct state *const sp,
if (up->tzhead.tzh_version[0] == '\0')
break;
nread -= p - up->buf;
- for (i = 0; i < nread; ++i)
- up->buf[i] = p[i];
+ memmove(up->buf, p, nread);
/*
** If this is a signed narrow time_t system, we're done.
*/
@@ -571,10 +582,10 @@ tzload(register const char *name, register struct state *const sp,
** If type 0 is is unused in transitions,
** it's the type to use for early times.
*/
- for (i = 0; i < sp->typecnt; ++i)
+ for (i = 0; i < sp->timecnt; ++i)
if (sp->types[i] == 0)
break;
- i = (i >= sp->typecnt) ? 0 : -1;
+ i = i < sp->timecnt ? -1 : 0;
/*
** Absent the above,
** if there are transition times
@@ -601,15 +612,27 @@ tzload(register const char *name, register struct state *const sp,
}
}
sp->defaulttype = i;
+ return 0;
+}
+
+/* Load tz data from the file named NAME into *SP. Read extended
+ format if DOEXTEND. Return 0 on success, an errno value on failure. */
+static int
+tzload(char const *name, struct state *sp, bool doextend)
+{
#ifdef ALL_STATE
- free(up);
-#endif /* defined ALL_STATE */
- return true;
-oops:
-#ifdef ALL_STATE
- free(up);
-#endif /* defined ALL_STATE */
- return false;
+ union local_storage *lsp = malloc(sizeof *lsp);
+ if (!lsp)
+ return errno;
+ else {
+ int err = tzloadbody(name, sp, doextend, lsp);
+ free(lsp);
+ return err;
+ }
+#else
+ union local_storage ls;
+ return tzloadbody(name, sp, doextend, &ls);
+#endif
}
static bool
@@ -934,7 +957,6 @@ tzparse(const char *name, register struct state *const sp,
int_fast32_t dstoffset;
register char * cp;
register bool load_ok;
- static struct ttinfo zttinfo;
stdname = name;
if (lastditch) {
@@ -962,7 +984,7 @@ tzparse(const char *name, register struct state *const sp,
if (name == NULL)
return false;
}
- load_ok = tzload(TZDEFRULES, sp, false);
+ load_ok = tzload(TZDEFRULES, sp, false) == 0;
if (!load_ok)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
@@ -1006,13 +1028,8 @@ tzparse(const char *name, register struct state *const sp,
/*
** Two transitions per year, from EPOCH_YEAR forward.
*/
- sp->ttis[0] = sp->ttis[1] = zttinfo;
- sp->ttis[0].tt_gmtoff = -dstoffset;
- sp->ttis[0].tt_isdst = true;
- sp->ttis[0].tt_abbrind = stdlen + 1;
- sp->ttis[1].tt_gmtoff = -stdoffset;
- sp->ttis[1].tt_isdst = false;
- sp->ttis[1].tt_abbrind = 0;
+ init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
+ init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
sp->defaulttype = 0;
timecnt = 0;
janfirst = 0;
@@ -1131,13 +1148,8 @@ tzparse(const char *name, register struct state *const sp,
/*
** Finally, fill in ttis.
*/
- sp->ttis[0] = sp->ttis[1] = zttinfo;
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = false;
- sp->ttis[0].tt_abbrind = 0;
- sp->ttis[1].tt_gmtoff = -dstoffset;
- sp->ttis[1].tt_isdst = true;
- sp->ttis[1].tt_abbrind = stdlen + 1;
+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+ init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
sp->typecnt = 2;
sp->defaulttype = 0;
}
@@ -1145,10 +1157,7 @@ tzparse(const char *name, register struct state *const sp,
dstlen = 0;
sp->typecnt = 1; /* only standard time */
sp->timecnt = 0;
- sp->ttis[0] = zttinfo;
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = false;
- sp->ttis[0].tt_abbrind = 0;
+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
sp->defaulttype = 0;
}
sp->charcnt = stdlen + 1;
@@ -1170,47 +1179,55 @@ tzparse(const char *name, register struct state *const sp,
static void
gmtload(struct state *const sp)
{
- if (! tzload(gmt, sp, true))
+ if (tzload(gmt, sp, true) != 0)
tzparse(gmt, sp, true);
}
-static struct state *
+/* Initialize *SP to a value appropriate for the TZ setting NAME.
+ Return 0 on success, an errno value on failure. */
+static int
zoneinit(struct state *sp, char const *name)
{
- if (sp) {
- if (name && ! name[0]) {
- /*
- ** User wants it fast rather than right.
- */
- sp->leapcnt = 0; /* so, we're off a little */
- sp->timecnt = 0;
- sp->typecnt = 0;
- sp->ttis[0].tt_isdst = 0;
- sp->ttis[0].tt_gmtoff = 0;
- sp->ttis[0].tt_abbrind = 0;
- strcpy(sp->chars, gmt);
- } else if (! (tzload(name, sp, true)
- || (name && name[0] != ':' && tzparse(name, sp, false))))
- return NULL;
+ if (name && ! name[0]) {
+ /*
+ ** User wants it fast rather than right.
+ */
+ sp->leapcnt = 0; /* so, we're off a little */
+ sp->timecnt = 0;
+ sp->typecnt = 0;
+ sp->charcnt = 0;
+ sp->goback = sp->goahead = false;
+ init_ttinfo(&sp->ttis[0], 0, false, 0);
+ strcpy(sp->chars, gmt);
+ sp->defaulttype = 0;
+ return 0;
+ } else {
+ int err = tzload(name, sp, true);
+ if (err != 0 && name && name[0] != ':' && tzparse(name, sp, false))
+ return 0;
+ return err;
}
- return sp;
}
static void
tzsetlcl(char const *name)
{
+ struct state *sp = lclptr;
int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
if (lcl < 0
? lcl_is_set < 0
: 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
return;
- if (0 < lcl)
- strcpy(lcl_TZname, name);
#ifdef ALL_STATE
- if (! lclptr)
- lclptr = malloc(sizeof *lclptr);
+ if (! sp)
+ lclptr = sp = malloc(sizeof *lclptr);
#endif /* defined ALL_STATE */
- zoneinit(lclptr, name);
+ if (sp) {
+ if (zoneinit(sp, name) != 0)
+ zoneinit(sp, "");
+ if (0 < lcl)
+ strcpy(lcl_TZname, name);
+ }
settzname();
lcl_is_set = lcl;
}
@@ -1244,17 +1261,17 @@ tzset(void)
static void
gmtcheck(void)
{
- static bool VOLATILE gmt_is_set;
- if (gmt_is_set)
- return;
+ static bool gmt_is_set;
if (lock() != 0)
return;
+ if (! gmt_is_set) {
#ifdef ALL_STATE
- gmtptr = malloc(sizeof *gmtptr);
+ gmtptr = malloc(sizeof *gmtptr);
#endif
- if (gmtptr)
- gmtload(gmtptr);
- gmt_is_set = true;
+ if (gmtptr)
+ gmtload(gmtptr);
+ gmt_is_set = true;
+ }
unlock();
}
@@ -1264,10 +1281,15 @@ timezone_t
tzalloc(char const *name)
{
timezone_t sp = malloc(sizeof *sp);
- timezone_t tp = sp ? zoneinit(sp, name) : sp;
- if (!tp)
- free(sp);
- return tp;
+ if (sp) {
+ int err = zoneinit(sp, name);
+ if (err != 0) {
+ free(sp);
+ errno = err;
+ return NULL;
+ }
+ }
+ return sp;
}
void
@@ -1294,7 +1316,11 @@ tzfree(timezone_t sp)
** freely called. (And no, the PANS doesn't require the above behavior,
** but it *is* desirable.)
**
-** The unused offset argument is for the benefit of mktime variants.
+** If successful and OFFSET is nonzero,
+** set the applicable parts of tzname, timezone and altzone;
+** however, it's OK to omit this step if the time zone is POSIX-compatible,
+** since in that case tzset should have already done this step correctly.
+** OFFSET's type is intfast32_t for compatibility with gmtsub.
*/
/*ARGSUSED*/
@@ -1307,8 +1333,10 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t offset,
register struct tm * result;
const time_t t = *timep;
- if (sp == NULL)
- return gmtsub(gmtptr, timep, offset, tmp);
+ if (sp == NULL) {
+ /* Don't bother to set tzname etc.; tzset has already done it. */
+ return gmtsub(gmtptr, timep, 0, tmp);
+ }
if ((sp->goback && t < sp->ats[0]) ||
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
time_t newt = t;
@@ -1328,16 +1356,16 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t offset,
newt > sp->ats[sp->timecnt - 1])
return NULL; /* "cannot happen" */
result = localsub(sp, &newt, offset, tmp);
- if (result == tmp) {
+ if (result) {
register int_fast64_t newy;
- newy = tmp->tm_year;
+ newy = result->tm_year;
if (t < sp->ats[0])
newy -= years;
else newy += years;
if (! (INT_MIN <= newy && newy <= INT_MAX))
return NULL;
- tmp->tm_year = newy;
+ result->tm_year = newy;
}
return result;
}
@@ -1364,30 +1392,52 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t offset,
** timesub(&t, 0L, sp, tmp);
*/
result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
- tmp->tm_isdst = ttisp->tt_isdst;
+ if (result) {
+ bool tm_isdst = ttisp->tt_isdst;
+ char *tm_zone = (char *) &sp->chars[ttisp->tt_abbrind];
+ result->tm_isdst = tm_isdst;
#ifdef TM_ZONE
- tmp->TM_ZONE = (char *) &sp->chars[ttisp->tt_abbrind];
+ result->TM_ZONE = tm_zone;
#endif /* defined TM_ZONE */
+ if (offset) {
+ /* Always set the tzname etc. vars whose values can easily
+ be determined, as it's too much trouble to tell whether
+ tzset has already done it correctly. */
+ tzname[tm_isdst] = tm_zone;
+#ifdef USG_COMPAT
+ if (!tm_isdst)
+ timezone = - ttisp->tt_gmtoff;
+#endif
+#ifdef ALTZONE
+ if (tm_isdst)
+ altzone = - ttisp->tt_gmtoff;
+#endif
+ }
+ }
return result;
}
-NETBSD_INSPIRED_EXTERN struct tm *
+#if NETBSD_INSPIRED
+
+struct tm *
localtime_rz(struct state *sp, time_t const *timep, struct tm *tmp)
{
return localsub(sp, timep, 0, tmp);
}
+#endif
+
static struct tm *
-localtime_tzset(time_t const *timep, struct tm *tmp, bool skip_tzset)
+localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
{
int err = lock();
if (err) {
errno = err;
return NULL;
}
- if (!skip_tzset)
+ if (setname || !lcl_is_set)
tzset_unlocked();
- tmp = localtime_rz(lclptr, timep, tmp);
+ tmp = localsub(lclptr, timep, setname, tmp);
unlock();
return tmp;
}
@@ -1395,13 +1445,13 @@ localtime_tzset(time_t const *timep, struct tm *tmp, bool skip_tzset)
struct tm *
localtime(const time_t *const timep)
{
- return localtime_tzset(timep, &tm, 0);
+ return localtime_tzset(timep, &tm, true);
}
struct tm *
localtime_r(const time_t *const timep, struct tm *tmp)
{
- return localtime_tzset(timep, tmp, lcl_is_set != 0);
+ return localtime_tzset(timep, tmp, false);
}
/*
@@ -1441,8 +1491,7 @@ struct tm *
gmtime_r(const time_t *const timep, struct tm *tmp)
{
gmtcheck();
- tmp = gmtsub(gmtptr, timep, 0, tmp);
- return tmp;
+ return gmtsub(gmtptr, timep, 0, tmp);
}
#ifdef STD_INSPIRED
@@ -1450,10 +1499,8 @@ gmtime_r(const time_t *const timep, struct tm *tmp)
struct tm *
offtime(const time_t *const timep, const long offset)
{
- struct tm *tmp;
gmtcheck();
- tmp = gmtsub(gmtptr, timep, offset, &tm);
- return tmp;
+ return gmtsub(gmtptr, timep, offset, &tm);
}
#endif /* defined STD_INSPIRED */
@@ -1520,13 +1567,13 @@ timesub(const time_t *const timep, const int_fast32_t offset,
tdelta = tdays / DAYSPERLYEAR;
if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
&& tdelta <= INT_MAX))
- return NULL;
+ goto out_of_range;
idelta = tdelta;
if (idelta == 0)
idelta = (tdays < 0) ? -1 : 1;
newy = y;
if (increment_overflow(&newy, idelta))
- return NULL;
+ goto out_of_range;
leapdays = leaps_thru_end_of(newy - 1) -
leaps_thru_end_of(y - 1);
tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
@@ -1555,17 +1602,17 @@ timesub(const time_t *const timep, const int_fast32_t offset,
}
while (idays < 0) {
if (increment_overflow(&y, -1))
- return NULL;
+ goto out_of_range;
idays += year_lengths[isleap(y)];
}
while (idays >= year_lengths[isleap(y)]) {
idays -= year_lengths[isleap(y)];
if (increment_overflow(&y, 1))
- return NULL;
+ goto out_of_range;
}
tmp->tm_year = y;
if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
- return NULL;
+ goto out_of_range;
tmp->tm_yday = idays;
/*
** The "extra" mods below avoid overflow problems.
@@ -1596,6 +1643,10 @@ timesub(const time_t *const timep, const int_fast32_t offset,
tmp->TM_GMTOFF = offset;
#endif /* defined TM_GMTOFF */
return tmp;
+
+ out_of_range:
+ errno = EOVERFLOW;
+ return NULL;
}
char *
@@ -1607,15 +1658,16 @@ ctime(const time_t *const timep)
** to local time in the form of a string. It is equivalent to
** asctime(localtime(timer))
*/
- return asctime(localtime(timep));
+ struct tm *tmp = localtime(timep);
+ return tmp ? asctime(tmp) : NULL;
}
char *
ctime_r(const time_t *const timep, char *buf)
{
- struct tm mytm;
-
- return asctime_r(localtime_r(timep, &mytm), buf);
+ struct tm mytm;
+ struct tm *tmp = localtime_r(timep, &mytm);
+ return tmp ? asctime_r(tmp, buf) : NULL;
}
/*
@@ -2015,17 +2067,27 @@ time1(struct tm *const tmp,
return WRONG;
}
-NETBSD_INSPIRED_EXTERN time_t
-mktime_z(struct state *sp, struct tm *tmp)
+static time_t
+mktime_tzname(struct state *sp, struct tm *tmp, bool setname)
{
if (sp)
- return time1(tmp, localsub, sp, 0);
+ return time1(tmp, localsub, sp, setname);
else {
gmtcheck();
return time1(tmp, gmtsub, gmtptr, 0);
}
}
+#if NETBSD_INSPIRED
+
+time_t
+mktime_z(struct state *sp, struct tm *tmp)
+{
+ return mktime_tzname(sp, tmp, false);
+}
+
+#endif
+
time_t
mktime(struct tm *const tmp)
{
@@ -2036,7 +2098,7 @@ mktime(struct tm *const tmp)
return -1;
}
tzset_unlocked();
- t = mktime_z(lclptr, tmp);
+ t = mktime_tzname(lclptr, tmp, true);
unlock();
return t;
}
@@ -2060,12 +2122,10 @@ timegm(struct tm *const tmp)
time_t
timeoff(struct tm *const tmp, const long offset)
{
- time_t t;
if (tmp)
tmp->tm_isdst = 0;
gmtcheck();
- t = time1(tmp, gmtsub, gmtptr, offset);
- return t;
+ return time1(tmp, gmtsub, gmtptr, offset);
}
#endif /* defined STD_INSPIRED */
@@ -2090,7 +2150,6 @@ leapcorr(struct state const *sp, time_t t)
register struct lsinfo const * lp;
register int i;
- sp = lclptr;
i = sp->leapcnt;
while (--i >= 0) {
lp = &sp->lsis[i];