localtime.c (1365bb722af1365baee6ea1e3d44917533908d53) localtime.c (a979394afeb5c20fc58c5f5b005d51eb8f92f666)
1/* Convert timestamp from time_t to struct tm. */
2
3/*
4** This file is in the public domain, so clarified as of
5** 1996-06-05 by Arthur David Olson.
6*/
7
8/*

--- 111 unchanged lines hidden (view full) ---

120static char const UNSPEC[] = "-00";
121
122/* How many extra bytes are needed at the end of struct state's chars array.
123 This needs to be at least 1 for null termination in case the input
124 data isn't properly terminated, and it also needs to be big enough
125 for ttunspecified to work without crashing. */
126enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
127
1/* Convert timestamp from time_t to struct tm. */
2
3/*
4** This file is in the public domain, so clarified as of
5** 1996-06-05 by Arthur David Olson.
6*/
7
8/*

--- 111 unchanged lines hidden (view full) ---

120static char const UNSPEC[] = "-00";
121
122/* How many extra bytes are needed at the end of struct state's chars array.
123 This needs to be at least 1 for null termination in case the input
124 data isn't properly terminated, and it also needs to be big enough
125 for ttunspecified to work without crashing. */
126enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
127
128/* Limit to time zone abbreviation length in POSIX.1-2017-style TZ strings.
128/* Limit to time zone abbreviation length in proleptic TZ strings.
129 This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */
130#ifndef TZNAME_MAXIMUM
131# define TZNAME_MAXIMUM 255
132#endif
133
134/* A representation of the contents of a TZif file. Ideally this
135 would have no size limits; the following sizes should suffice for
136 practical use. This struct should not be too large, as instances

--- 7 unchanged lines hidden (view full) ---

144 bool goback;
145 bool goahead;
146 time_t ats[TZ_MAX_TIMES];
147 unsigned char types[TZ_MAX_TIMES];
148 struct ttinfo ttis[TZ_MAX_TYPES];
149 char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"),
150 2 * (TZNAME_MAXIMUM + 1))];
151 struct lsinfo lsis[TZ_MAX_LEAPS];
129 This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */
130#ifndef TZNAME_MAXIMUM
131# define TZNAME_MAXIMUM 255
132#endif
133
134/* A representation of the contents of a TZif file. Ideally this
135 would have no size limits; the following sizes should suffice for
136 practical use. This struct should not be too large, as instances

--- 7 unchanged lines hidden (view full) ---

144 bool goback;
145 bool goahead;
146 time_t ats[TZ_MAX_TIMES];
147 unsigned char types[TZ_MAX_TIMES];
148 struct ttinfo ttis[TZ_MAX_TYPES];
149 char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"),
150 2 * (TZNAME_MAXIMUM + 1))];
151 struct lsinfo lsis[TZ_MAX_LEAPS];
152
153 /* The time type to use for early times or if no transitions.
154 It is always zero for recent tzdb releases.
155 It might be nonzero for data from tzdb 2018e or earlier. */
156 int defaulttype;
157};
158
159enum r_type {
160 JULIAN_DAY, /* Jn = Julian day */
161 DAY_OF_YEAR, /* n = day of year */
162 MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
163};
164

--- 47 unchanged lines hidden (view full) ---

212
213/*
214** Section 4.12.3 of X3.159-1989 requires that
215** Except for the strftime function, these functions [asctime,
216** ctime, gmtime, localtime] return values in one of two static
217** objects: a broken-down time structure and an array of char.
218** Thanks to Paul Eggert for noting this.
219**
152};
153
154enum r_type {
155 JULIAN_DAY, /* Jn = Julian day */
156 DAY_OF_YEAR, /* n = day of year */
157 MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
158};
159

--- 47 unchanged lines hidden (view full) ---

207
208/*
209** Section 4.12.3 of X3.159-1989 requires that
210** Except for the strftime function, these functions [asctime,
211** ctime, gmtime, localtime] return values in one of two static
212** objects: a broken-down time structure and an array of char.
213** Thanks to Paul Eggert for noting this.
214**
220** This requirement was removed in C99, so support it only if requested,
221** as support is more likely to lead to bugs in badly written programs.
215** Although this requirement was removed in C99 it is still present in POSIX.
216** Follow the requirement if SUPPORT_C89, even though this is more likely to
217** trigger latent bugs in programs.
222*/
223
224#if SUPPORT_C89
225static struct tm tm;
226#endif
227
228#if 2 <= HAVE_TZNAME + TZ_TIME_T
229char * tzname[2] = {

--- 538 unchanged lines hidden (view full) ---

768 for (i = 0; i < ts->typecnt; i++)
769 sp->ttis[sp->typecnt++] = ts->ttis[i];
770 }
771 }
772 }
773 if (sp->typecnt == 0)
774 return EINVAL;
775
218*/
219
220#if SUPPORT_C89
221static struct tm tm;
222#endif
223
224#if 2 <= HAVE_TZNAME + TZ_TIME_T
225char * tzname[2] = {

--- 538 unchanged lines hidden (view full) ---

764 for (i = 0; i < ts->typecnt; i++)
765 sp->ttis[sp->typecnt++] = ts->ttis[i];
766 }
767 }
768 }
769 if (sp->typecnt == 0)
770 return EINVAL;
771
776 /* Infer sp->defaulttype from the data. Although this default
777 type is always zero for data from recent tzdb releases,
778 things are trickier for data from tzdb 2018e or earlier.
779
780 The first set of heuristics work around bugs in 32-bit data
781 generated by tzdb 2013c or earlier. The workaround is for
782 zones like Australia/Macquarie where timestamps before the
783 first transition have a time type that is not the earliest
784 standard-time type. See:
785 https://mm.icann.org/pipermail/tz/2013-May/019368.html */
786 /*
787 ** If type 0 does not specify local time, or is unused in transitions,
788 ** it's the type to use for early times.
789 */
790 for (i = 0; i < sp->timecnt; ++i)
791 if (sp->types[i] == 0)
792 break;
793 i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0;
794 /*
795 ** Absent the above,
796 ** if there are transition times
797 ** and the first transition is to a daylight time
798 ** find the standard type less than and closest to
799 ** the type of the first transition.
800 */
801 if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
802 i = sp->types[0];
803 while (--i >= 0)
804 if (!sp->ttis[i].tt_isdst)
805 break;
806 }
807 /* The next heuristics are for data generated by tzdb 2018e or
808 earlier, for zones like EST5EDT where the first transition
809 is to DST. */
810 /*
811 ** If no result yet, find the first standard type.
812 ** If there is none, punt to type zero.
813 */
814 if (i < 0) {
815 i = 0;
816 while (sp->ttis[i].tt_isdst)
817 if (++i >= sp->typecnt) {
818 i = 0;
819 break;
820 }
821 }
822 /* A simple 'sp->defaulttype = 0;' would suffice here if we
823 didn't have to worry about 2018e-or-earlier data. Even
824 simpler would be to remove the defaulttype member and just
825 use 0 in its place. */
826 sp->defaulttype = i;
827
828 return 0;
829}
830
831/* Load tz data from the file named NAME into *SP. Read extended
832 format if DOEXTEND. Return 0 on success, an errno value on failure. */
833static int
834tzload(char const *name, struct state *sp, bool doextend)
835{

--- 29 unchanged lines hidden (view full) ---

865}
866
867/*
868** Given a pointer into a timezone string, scan until a character that is not
869** a valid character in a time zone abbreviation is found.
870** Return a pointer to that character.
871*/
872
772 return 0;
773}
774
775/* Load tz data from the file named NAME into *SP. Read extended
776 format if DOEXTEND. Return 0 on success, an errno value on failure. */
777static int
778tzload(char const *name, struct state *sp, bool doextend)
779{

--- 29 unchanged lines hidden (view full) ---

809}
810
811/*
812** Given a pointer into a timezone string, scan until a character that is not
813** a valid character in a time zone abbreviation is found.
814** Return a pointer to that character.
815*/
816
873ATTRIBUTE_REPRODUCIBLE static const char *
817ATTRIBUTE_PURE_114833 static const char *
874getzname(register const char *strp)
875{
876 register char c;
877
878 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
879 c != '+')
880 ++strp;
881 return strp;

--- 4 unchanged lines hidden (view full) ---

886** delimiter of the time zone abbreviation is located.
887** Return a pointer to the delimiter.
888**
889** As with getzname above, the legal character set is actually quite
890** restricted, with other characters producing undefined results.
891** We don't do any checking here; checking is done later in common-case code.
892*/
893
818getzname(register const char *strp)
819{
820 register char c;
821
822 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
823 c != '+')
824 ++strp;
825 return strp;

--- 4 unchanged lines hidden (view full) ---

830** delimiter of the time zone abbreviation is located.
831** Return a pointer to the delimiter.
832**
833** As with getzname above, the legal character set is actually quite
834** restricted, with other characters producing undefined results.
835** We don't do any checking here; checking is done later in common-case code.
836*/
837
894ATTRIBUTE_REPRODUCIBLE static const char *
838ATTRIBUTE_PURE_114833 static const char *
895getqzname(register const char *strp, const int delim)
896{
897 register int c;
898
899 while ((c = *strp) != '\0' && c != delim)
900 ++strp;
901 return strp;
902}

--- 235 unchanged lines hidden (view full) ---

1138 ** question. To get the year-relative time of the specified local
1139 ** time on that day, add the transition time and the current offset
1140 ** from UT.
1141 */
1142 return value + rulep->r_time + offset;
1143}
1144
1145/*
839getqzname(register const char *strp, const int delim)
840{
841 register int c;
842
843 while ((c = *strp) != '\0' && c != delim)
844 ++strp;
845 return strp;
846}

--- 235 unchanged lines hidden (view full) ---

1082 ** question. To get the year-relative time of the specified local
1083 ** time on that day, add the transition time and the current offset
1084 ** from UT.
1085 */
1086 return value + rulep->r_time + offset;
1087}
1088
1089/*
1146** Given a POSIX.1-2017-style TZ string, fill in the rule tables as
1090** Given a POSIX.1 proleptic TZ string, fill in the rule tables as
1147** appropriate.
1148*/
1149
1150static bool
1151tzparse(const char *name, struct state *sp, struct state const *basep)
1152{
1153 const char * stdname;
1154 const char * dstname;

--- 218 unchanged lines hidden (view full) ---

1373 ** the daylight saving time offset to
1374 ** the transition time; otherwise, add
1375 ** the standard time offset to the
1376 ** transition time.
1377 */
1378 /*
1379 ** Transitions from DST to DDST
1380 ** will effectively disappear since
1091** appropriate.
1092*/
1093
1094static bool
1095tzparse(const char *name, struct state *sp, struct state const *basep)
1096{
1097 const char * stdname;
1098 const char * dstname;

--- 218 unchanged lines hidden (view full) ---

1317 ** the daylight saving time offset to
1318 ** the transition time; otherwise, add
1319 ** the standard time offset to the
1320 ** transition time.
1321 */
1322 /*
1323 ** Transitions from DST to DDST
1324 ** will effectively disappear since
1381 ** POSIX.1-2017 provides for only one
1325 ** proleptic TZ strings have only one
1382 ** DST offset.
1383 */
1384 if (isdst && !sp->ttis[j].tt_ttisstd) {
1385 sp->ats[i] += dstoffset -
1386 theirdstoffset;
1387 } else {
1388 sp->ats[i] += stdoffset -
1389 theirstdoffset;

--- 12 unchanged lines hidden (view full) ---

1402 sp->typecnt = 2;
1403 }
1404 } else {
1405 dstlen = 0;
1406 sp->typecnt = 1; /* only standard time */
1407 sp->timecnt = 0;
1408 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1409 }
1326 ** DST offset.
1327 */
1328 if (isdst && !sp->ttis[j].tt_ttisstd) {
1329 sp->ats[i] += dstoffset -
1330 theirdstoffset;
1331 } else {
1332 sp->ats[i] += stdoffset -
1333 theirstdoffset;

--- 12 unchanged lines hidden (view full) ---

1346 sp->typecnt = 2;
1347 }
1348 } else {
1349 dstlen = 0;
1350 sp->typecnt = 1; /* only standard time */
1351 sp->timecnt = 0;
1352 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1353 }
1410 sp->defaulttype = 0;
1411 sp->charcnt = charcnt;
1412 cp = sp->chars;
1413 memcpy(cp, stdname, stdlen);
1414 cp += stdlen;
1415 *cp++ = '\0';
1416 if (dstlen != 0) {
1417 memcpy(cp, dstname, dstlen);
1418 *(cp + dstlen) = '\0';

--- 50 unchanged lines hidden (view full) ---

1469 */
1470 sp->leapcnt = 0; /* so, we're off a little */
1471 sp->timecnt = 0;
1472 sp->typecnt = 0;
1473 sp->charcnt = 0;
1474 sp->goback = sp->goahead = false;
1475 init_ttinfo(&sp->ttis[0], 0, false, 0);
1476 strcpy(sp->chars, utc);
1354 sp->charcnt = charcnt;
1355 cp = sp->chars;
1356 memcpy(cp, stdname, stdlen);
1357 cp += stdlen;
1358 *cp++ = '\0';
1359 if (dstlen != 0) {
1360 memcpy(cp, dstname, dstlen);
1361 *(cp + dstlen) = '\0';

--- 50 unchanged lines hidden (view full) ---

1412 */
1413 sp->leapcnt = 0; /* so, we're off a little */
1414 sp->timecnt = 0;
1415 sp->typecnt = 0;
1416 sp->charcnt = 0;
1417 sp->goback = sp->goahead = false;
1418 init_ttinfo(&sp->ttis[0], 0, false, 0);
1419 strcpy(sp->chars, utc);
1477 sp->defaulttype = 0;
1478 return 0;
1479 } else {
1480 int err = tzload(name, sp, true);
1481 if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL))
1482 err = 0;
1483 if (err == 0)
1484 err = scrub_abbrs(sp);
1485 return err;

--- 88 unchanged lines hidden (view full) ---

1574
1575void
1576tzfree(timezone_t sp)
1577{
1578 free(sp);
1579}
1580
1581/*
1420 return 0;
1421 } else {
1422 int err = tzload(name, sp, true);
1423 if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL))
1424 err = 0;
1425 if (err == 0)
1426 err = scrub_abbrs(sp);
1427 return err;

--- 88 unchanged lines hidden (view full) ---

1516
1517void
1518tzfree(timezone_t sp)
1519{
1520 free(sp);
1521}
1522
1523/*
1582** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
1583** ctime_r are obsolescent and have potential security problems that
1524** NetBSD 6.1.4 has ctime_rz, but omit it because C23 deprecates ctime and
1525** POSIX.1-2024 removes ctime_r. Both have potential security problems that
1584** ctime_rz would share. Callers can instead use localtime_rz + strftime.
1585**
1586** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1587** in zones with three or more time zone abbreviations.
1588** Callers can instead use localtime_rz + strftime.
1589*/
1590
1591#endif
1592
1593/*
1594** The easy way to behave "as if no library function calls" localtime
1595** is to not call it, so we drop its guts into "localsub", which can be
1596** freely called. (And no, the PANS doesn't require the above behavior,
1597** but it *is* desirable.)
1598**
1599** If successful and SETNAME is nonzero,
1600** set the applicable parts of tzname, timezone and altzone;
1526** ctime_rz would share. Callers can instead use localtime_rz + strftime.
1527**
1528** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1529** in zones with three or more time zone abbreviations.
1530** Callers can instead use localtime_rz + strftime.
1531*/
1532
1533#endif
1534
1535/*
1536** The easy way to behave "as if no library function calls" localtime
1537** is to not call it, so we drop its guts into "localsub", which can be
1538** freely called. (And no, the PANS doesn't require the above behavior,
1539** but it *is* desirable.)
1540**
1541** If successful and SETNAME is nonzero,
1542** set the applicable parts of tzname, timezone and altzone;
1601** however, it's OK to omit this step
1602** if the timezone is compatible with POSIX.1-2017
1543** however, it's OK to omit this step for proleptic TZ strings
1603** since in that case tzset should have already done this step correctly.
1604** SETNAME's type is int_fast32_t for compatibility with gmtsub,
1605** but it is actually a boolean and its value should be 0 or 1.
1606*/
1607
1608/*ARGSUSED*/
1609static struct tm *
1610localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,

--- 51 unchanged lines hidden (view full) ---

1662 if (! (INT_MIN <= newy && newy <= INT_MAX))
1663 return NULL;
1664 result->tm_year = newy;
1665#endif
1666 }
1667 return result;
1668 }
1669 if (sp->timecnt == 0 || t < sp->ats[0]) {
1544** since in that case tzset should have already done this step correctly.
1545** SETNAME's type is int_fast32_t for compatibility with gmtsub,
1546** but it is actually a boolean and its value should be 0 or 1.
1547*/
1548
1549/*ARGSUSED*/
1550static struct tm *
1551localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,

--- 51 unchanged lines hidden (view full) ---

1603 if (! (INT_MIN <= newy && newy <= INT_MAX))
1604 return NULL;
1605 result->tm_year = newy;
1606#endif
1607 }
1608 return result;
1609 }
1610 if (sp->timecnt == 0 || t < sp->ats[0]) {
1670 i = sp->defaulttype;
1611 i = 0;
1671 } else {
1672 register int lo = 1;
1673 register int hi = sp->timecnt;
1674
1675 while (lo < hi) {
1676 register int mid = (lo + hi) >> 1;
1677
1678 if (t < sp->ats[mid])

--- 798 unchanged lines hidden (view full) ---

2477 }
2478 tzset_unlocked();
2479 t = mktime_tzname(lclptr, tmp, true);
2480 unlock();
2481 return t;
2482}
2483
2484#if STD_INSPIRED
1612 } else {
1613 register int lo = 1;
1614 register int hi = sp->timecnt;
1615
1616 while (lo < hi) {
1617 register int mid = (lo + hi) >> 1;
1618
1619 if (t < sp->ats[mid])

--- 798 unchanged lines hidden (view full) ---

2418 }
2419 tzset_unlocked();
2420 t = mktime_tzname(lclptr, tmp, true);
2421 unlock();
2422 return t;
2423}
2424
2425#if STD_INSPIRED
2485/* This function is obsolescent and may disapper in future releases.
2426/* This function is obsolescent and may disappear in future releases.
2486 Callers can instead use mktime. */
2487time_t
2488timelocal(struct tm *tmp)
2489{
2490 if (tmp != NULL)
2491 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2492 return mktime(tmp);
2493}
2494#endif
2495
2496#ifndef EXTERN_TIMEOFF
2497# ifndef timeoff
2498# define timeoff my_timeoff /* Don't collide with OpenBSD 7.4 <time.h>. */
2499# endif
2500# define EXTERN_TIMEOFF static
2501#endif
2502
2427 Callers can instead use mktime. */
2428time_t
2429timelocal(struct tm *tmp)
2430{
2431 if (tmp != NULL)
2432 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2433 return mktime(tmp);
2434}
2435#endif
2436
2437#ifndef EXTERN_TIMEOFF
2438# ifndef timeoff
2439# define timeoff my_timeoff /* Don't collide with OpenBSD 7.4 <time.h>. */
2440# endif
2441# define EXTERN_TIMEOFF static
2442#endif
2443
2503/* This function is obsolescent and may disapper in future releases.
2444/* This function is obsolescent and may disappear in future releases.
2504 Callers can instead use mktime_z with a fixed-offset zone. */
2505EXTERN_TIMEOFF time_t
2506timeoff(struct tm *tmp, long offset)
2507{
2508 if (tmp)
2509 tmp->tm_isdst = 0;
2510 _once(&gmt_once, gmtcheck);
2511 return time1(tmp, gmtsub, gmtptr, offset);

--- 164 unchanged lines hidden ---
2445 Callers can instead use mktime_z with a fixed-offset zone. */
2446EXTERN_TIMEOFF time_t
2447timeoff(struct tm *tmp, long offset)
2448{
2449 if (tmp)
2450 tmp->tm_isdst = 0;
2451 _once(&gmt_once, gmtcheck);
2452 return time1(tmp, gmtsub, gmtptr, offset);

--- 164 unchanged lines hidden ---