Home | History | Annotate | Line # | Download | only in time
localtime.c revision 1.105
      1  1.105  christos /*	$NetBSD: localtime.c,v 1.105 2016/11/04 19:41:53 christos Exp $	*/
      2    1.7       jtc 
      3    1.7       jtc /*
      4    1.7       jtc ** This file is in the public domain, so clarified as of
      5   1.45   mlelstv ** 1996-06-05 by Arthur David Olson.
      6    1.7       jtc */
      7    1.2       jtc 
      8   1.11  christos #include <sys/cdefs.h>
      9   1.24   msaitoh #if defined(LIBC_SCCS) && !defined(lint)
     10   1.11  christos #if 0
     11   1.58  christos static char	elsieid[] = "@(#)localtime.c	8.17";
     12   1.11  christos #else
     13  1.105  christos __RCSID("$NetBSD: localtime.c,v 1.105 2016/11/04 19:41:53 christos Exp $");
     14   1.11  christos #endif
     15   1.24   msaitoh #endif /* LIBC_SCCS and not lint */
     16    1.1       jtc 
     17    1.1       jtc /*
     18   1.45   mlelstv ** Leap second handling from Bradley White.
     19   1.45   mlelstv ** POSIX-style TZ environment variable handling from Guy Harris.
     20    1.1       jtc */
     21    1.1       jtc 
     22    1.1       jtc /*LINTLIBRARY*/
     23    1.1       jtc 
     24   1.12       jtc #include "namespace.h"
     25   1.78  christos #include <assert.h>
     26   1.87  christos #define LOCALTIME_IMPLEMENTATION
     27    1.1       jtc #include "private.h"
     28   1.87  christos 
     29    1.1       jtc #include "tzfile.h"
     30    1.1       jtc #include "fcntl.h"
     31   1.19    kleink #include "reentrant.h"
     32   1.12       jtc 
     33   1.87  christos #if NETBSD_INSPIRED
     34   1.87  christos # define NETBSD_INSPIRED_EXTERN
     35   1.87  christos #else
     36   1.87  christos # define NETBSD_INSPIRED_EXTERN static
     37   1.87  christos #endif
     38   1.87  christos 
     39   1.42  christos #if defined(__weak_alias)
     40   1.25    kleink __weak_alias(daylight,_daylight)
     41   1.23   mycroft __weak_alias(tzname,_tzname)
     42   1.12       jtc #endif
     43    1.1       jtc 
     44   1.45   mlelstv #ifndef TZ_ABBR_MAX_LEN
     45   1.45   mlelstv #define TZ_ABBR_MAX_LEN	16
     46   1.45   mlelstv #endif /* !defined TZ_ABBR_MAX_LEN */
     47   1.45   mlelstv 
     48   1.45   mlelstv #ifndef TZ_ABBR_CHAR_SET
     49   1.45   mlelstv #define TZ_ABBR_CHAR_SET \
     50   1.45   mlelstv 	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
     51   1.45   mlelstv #endif /* !defined TZ_ABBR_CHAR_SET */
     52   1.45   mlelstv 
     53   1.45   mlelstv #ifndef TZ_ABBR_ERR_CHAR
     54   1.45   mlelstv #define TZ_ABBR_ERR_CHAR	'_'
     55   1.45   mlelstv #endif /* !defined TZ_ABBR_ERR_CHAR */
     56   1.45   mlelstv 
     57    1.1       jtc /*
     58    1.1       jtc ** SunOS 4.1.1 headers lack O_BINARY.
     59    1.1       jtc */
     60    1.1       jtc 
     61    1.1       jtc #ifdef O_BINARY
     62   1.86  christos #define OPEN_MODE	(O_RDONLY | O_BINARY | O_CLOEXEC)
     63    1.1       jtc #endif /* defined O_BINARY */
     64    1.1       jtc #ifndef O_BINARY
     65   1.86  christos #define OPEN_MODE	(O_RDONLY | O_CLOEXEC)
     66    1.1       jtc #endif /* !defined O_BINARY */
     67    1.1       jtc 
     68    1.1       jtc #ifndef WILDABBR
     69    1.1       jtc /*
     70    1.1       jtc ** Someone might make incorrect use of a time zone abbreviation:
     71    1.1       jtc **	1.	They might reference tzname[0] before calling tzset (explicitly
     72    1.1       jtc **		or implicitly).
     73    1.1       jtc **	2.	They might reference tzname[1] before calling tzset (explicitly
     74    1.1       jtc **		or implicitly).
     75    1.1       jtc **	3.	They might reference tzname[1] after setting to a time zone
     76    1.1       jtc **		in which Daylight Saving Time is never observed.
     77    1.1       jtc **	4.	They might reference tzname[0] after setting to a time zone
     78    1.1       jtc **		in which Standard Time is never observed.
     79    1.1       jtc **	5.	They might reference tm.TM_ZONE after calling offtime.
     80    1.1       jtc ** What's best to do in the above cases is open to debate;
     81    1.1       jtc ** for now, we just set things up so that in any of the five cases
     82   1.45   mlelstv ** WILDABBR is used. Another possibility: initialize tzname[0] to the
     83    1.1       jtc ** string "tzname[0] used before set", and similarly for the other cases.
     84   1.45   mlelstv ** And another: initialize tzname[0] to "ERA", with an explanation in the
     85    1.1       jtc ** manual page of what this "time zone abbreviation" means (doing this so
     86    1.1       jtc ** that tzname[0] has the "normal" length of three characters).
     87    1.1       jtc */
     88    1.1       jtc #define WILDABBR	"   "
     89    1.1       jtc #endif /* !defined WILDABBR */
     90    1.1       jtc 
     91   1.45   mlelstv static const char	wildabbr[] = WILDABBR;
     92    1.1       jtc 
     93   1.71  christos static const char	gmt[] = "GMT";
     94    1.1       jtc 
     95   1.22    kleink /*
     96   1.22    kleink ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
     97   1.22    kleink ** We default to US rules as of 1999-08-17.
     98   1.22    kleink ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
     99   1.22    kleink ** implementation dependent; for historical reasons, US rules are a
    100   1.22    kleink ** common default.
    101   1.22    kleink */
    102   1.22    kleink #ifndef TZDEFRULESTRING
    103   1.22    kleink #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
    104   1.22    kleink #endif /* !defined TZDEFDST */
    105   1.22    kleink 
    106    1.1       jtc struct ttinfo {				/* time type information */
    107   1.78  christos 	int_fast32_t	tt_gmtoff;	/* UT offset in seconds */
    108   1.87  christos 	bool		tt_isdst;	/* used to set tm_isdst */
    109    1.1       jtc 	int		tt_abbrind;	/* abbreviation list index */
    110   1.87  christos 	bool		tt_ttisstd;	/* transition is std time */
    111   1.87  christos 	bool		tt_ttisgmt;	/* transition is UT */
    112    1.1       jtc };
    113    1.1       jtc 
    114    1.1       jtc struct lsinfo {				/* leap second information */
    115    1.1       jtc 	time_t		ls_trans;	/* transition time */
    116   1.74  christos 	int_fast64_t	ls_corr;	/* correction to apply */
    117    1.1       jtc };
    118    1.1       jtc 
    119   1.87  christos #define SMALLEST(a, b)	(((a) < (b)) ? (a) : (b))
    120    1.1       jtc #define BIGGEST(a, b)	(((a) > (b)) ? (a) : (b))
    121    1.1       jtc 
    122    1.1       jtc #ifdef TZNAME_MAX
    123    1.1       jtc #define MY_TZNAME_MAX	TZNAME_MAX
    124    1.1       jtc #endif /* defined TZNAME_MAX */
    125    1.1       jtc #ifndef TZNAME_MAX
    126    1.1       jtc #define MY_TZNAME_MAX	255
    127    1.1       jtc #endif /* !defined TZNAME_MAX */
    128    1.1       jtc 
    129   1.87  christos #define state __state
    130   1.87  christos struct state {
    131    1.1       jtc 	int		leapcnt;
    132    1.1       jtc 	int		timecnt;
    133    1.1       jtc 	int		typecnt;
    134    1.1       jtc 	int		charcnt;
    135   1.87  christos 	bool		goback;
    136   1.87  christos 	bool		goahead;
    137   1.45   mlelstv 	time_t		ats[TZ_MAX_TIMES];
    138    1.1       jtc 	unsigned char	types[TZ_MAX_TIMES];
    139    1.1       jtc 	struct ttinfo	ttis[TZ_MAX_TYPES];
    140   1.69  christos 	char		chars[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS + 1,
    141   1.69  christos 				sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))];
    142    1.1       jtc 	struct lsinfo	lsis[TZ_MAX_LEAPS];
    143   1.74  christos 	int		defaulttype; /* for early times or if no transitions */
    144    1.1       jtc };
    145    1.1       jtc 
    146   1.96  christos enum r_type {
    147   1.96  christos   JULIAN_DAY,		/* Jn = Julian day */
    148   1.96  christos   DAY_OF_YEAR,		/* n = day of year */
    149   1.96  christos   MONTH_NTH_DAY_OF_WEEK	/* Mm.n.d = month, week, day of week */
    150   1.96  christos };
    151   1.96  christos 
    152    1.1       jtc struct rule {
    153   1.96  christos 	enum r_type	r_type;		/* type of rule */
    154    1.1       jtc 	int		r_day;		/* day number of rule */
    155    1.1       jtc 	int		r_week;		/* week number of rule */
    156    1.1       jtc 	int		r_mon;		/* month number of rule */
    157   1.74  christos 	int_fast32_t	r_time;		/* transition time of rule */
    158    1.1       jtc };
    159    1.1       jtc 
    160   1.87  christos static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
    161   1.87  christos 			 struct tm *);
    162   1.87  christos static bool increment_overflow(int *, int);
    163   1.87  christos static bool increment_overflow_time(time_t *, int_fast32_t);
    164   1.87  christos static bool normalize_overflow32(int_fast32_t *, int *, int);
    165   1.87  christos static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
    166   1.87  christos 			  struct tm *);
    167   1.87  christos static bool typesequiv(struct state const *, int, int);
    168   1.87  christos static bool tzparse(char const *, struct state *, bool);
    169    1.1       jtc 
    170   1.49  christos static timezone_t lclptr;
    171   1.49  christos static timezone_t gmtptr;
    172    1.1       jtc 
    173    1.1       jtc #ifndef TZ_STRLEN_MAX
    174    1.1       jtc #define TZ_STRLEN_MAX 255
    175    1.1       jtc #endif /* !defined TZ_STRLEN_MAX */
    176    1.1       jtc 
    177   1.45   mlelstv static char		lcl_TZname[TZ_STRLEN_MAX + 1];
    178   1.45   mlelstv static int		lcl_is_set;
    179   1.42  christos 
    180   1.42  christos 
    181   1.33  christos #ifdef _REENTRANT
    182   1.45   mlelstv static rwlock_t lcl_lock = RWLOCK_INITIALIZER;
    183   1.19    kleink #endif
    184   1.19    kleink 
    185    1.1       jtc /*
    186    1.1       jtc ** Section 4.12.3 of X3.159-1989 requires that
    187    1.1       jtc **	Except for the strftime function, these functions [asctime,
    188    1.1       jtc **	ctime, gmtime, localtime] return values in one of two static
    189    1.1       jtc **	objects: a broken-down time structure and an array of char.
    190   1.45   mlelstv ** Thanks to Paul Eggert for noting this.
    191    1.1       jtc */
    192    1.1       jtc 
    193    1.1       jtc static struct tm	tm;
    194    1.1       jtc 
    195  1.102  christos #if !HAVE_POSIX_DECLS || defined(__NetBSD__)
    196  1.102  christos # if !defined(__LIBC12_SOURCE__)
    197  1.102  christos 
    198  1.102  christos __aconst char *		tzname[2] = {
    199  1.102  christos 	(__aconst char *)__UNCONST(wildabbr),
    200  1.102  christos 	(__aconst char *)__UNCONST(wildabbr)
    201  1.102  christos };
    202  1.102  christos 
    203  1.102  christos # else
    204  1.102  christos 
    205  1.102  christos extern __aconst char *	tzname[2];
    206  1.102  christos 
    207  1.102  christos # endif /* __LIBC12_SOURCE__ */
    208  1.102  christos 
    209  1.102  christos # ifdef USG_COMPAT
    210  1.102  christos #  if !defined(__LIBC12_SOURCE__)
    211   1.42  christos long 			timezone = 0;
    212    1.1       jtc int			daylight = 0;
    213   1.42  christos #else
    214   1.42  christos extern int		daylight;
    215   1.42  christos extern long		timezone __RENAME(__timezone13);
    216  1.102  christos #  endif /* __LIBC12_SOURCE__ */
    217  1.102  christos # endif /* defined USG_COMPAT */
    218  1.102  christos #endif /* !HAVE_POSIX_DECLS */
    219    1.1       jtc 
    220    1.1       jtc #ifdef ALTZONE
    221   1.81  christos long			altzone = 0;
    222    1.1       jtc #endif /* defined ALTZONE */
    223    1.1       jtc 
    224   1.91  christos /* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND.  */
    225   1.91  christos static void
    226   1.91  christos init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
    227   1.91  christos {
    228   1.91  christos 	s->tt_gmtoff = gmtoff;
    229   1.91  christos 	s->tt_isdst = isdst;
    230   1.91  christos 	s->tt_abbrind = abbrind;
    231   1.91  christos 	s->tt_ttisstd = false;
    232   1.91  christos 	s->tt_ttisgmt = false;
    233   1.91  christos }
    234   1.91  christos 
    235   1.74  christos static int_fast32_t
    236   1.49  christos detzcode(const char *const codep)
    237    1.1       jtc {
    238   1.95  christos 	int_fast32_t result;
    239   1.95  christos 	int	i;
    240   1.95  christos 	int_fast32_t one = 1;
    241   1.95  christos 	int_fast32_t halfmaxval = one << (32 - 2);
    242   1.95  christos 	int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
    243   1.95  christos 	int_fast32_t minval = -1 - maxval;
    244   1.45   mlelstv 
    245   1.95  christos 	result = codep[0] & 0x7f;
    246   1.95  christos 	for (i = 1; i < 4; ++i)
    247   1.45   mlelstv 		result = (result << 8) | (codep[i] & 0xff);
    248   1.95  christos 
    249   1.95  christos 	if (codep[0] & 0x80) {
    250   1.95  christos 	  /* Do two's-complement negation even on non-two's-complement machines.
    251   1.95  christos 	     If the result would be minval - 1, return minval.  */
    252   1.95  christos 	    result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
    253   1.95  christos 	    result += minval;
    254   1.95  christos 	}
    255   1.95  christos  	return result;
    256   1.45   mlelstv }
    257   1.45   mlelstv 
    258   1.81  christos static int_fast64_t
    259   1.49  christos detzcode64(const char *const codep)
    260   1.45   mlelstv {
    261   1.87  christos 	int_fast64_t result;
    262   1.49  christos 	int	i;
    263   1.95  christos 	int_fast64_t one = 1;
    264   1.95  christos 	int_fast64_t halfmaxval = one << (64 - 2);
    265   1.95  christos 	int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
    266   1.95  christos 	int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
    267    1.1       jtc 
    268   1.95  christos 	result = codep[0] & 0x7f;
    269   1.95  christos 	for (i = 1; i < 8; ++i)
    270   1.81  christos 		result = (result << 8) | (codep[i] & 0xff);
    271   1.95  christos 
    272   1.95  christos 	if (codep[0] & 0x80) {
    273   1.95  christos 	  /* Do two's-complement negation even on non-two's-complement machines.
    274   1.95  christos 	     If the result would be minval - 1, return minval.  */
    275   1.95  christos 	  result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
    276   1.95  christos 	  result += minval;
    277   1.95  christos 	}
    278   1.95  christos  	return result;
    279    1.1       jtc }
    280    1.1       jtc 
    281   1.49  christos const char *
    282   1.49  christos tzgetname(const timezone_t sp, int isdst)
    283   1.49  christos {
    284   1.49  christos 	int i;
    285  1.103  ginsbach 	for (i = 0; i < sp->typecnt; ++i) {
    286   1.49  christos 		const struct ttinfo *const ttisp = &sp->ttis[sp->types[i]];
    287   1.49  christos 
    288   1.49  christos 		if (ttisp->tt_isdst == isdst)
    289   1.49  christos 			return &sp->chars[ttisp->tt_abbrind];
    290   1.49  christos 	}
    291   1.88  christos 	errno = ESRCH;
    292   1.49  christos 	return NULL;
    293   1.49  christos }
    294   1.49  christos 
    295   1.99  christos long
    296   1.99  christos tzgetgmtoff(const timezone_t sp, int isdst)
    297   1.99  christos {
    298   1.99  christos 	int i;
    299   1.99  christos 	long l = -1;
    300  1.103  ginsbach 	for (i = 0; i < sp->typecnt; ++i) {
    301   1.99  christos 		const struct ttinfo *const ttisp = &sp->ttis[sp->types[i]];
    302   1.99  christos 
    303   1.99  christos 		if (ttisp->tt_isdst == isdst) {
    304   1.99  christos 			l = ttisp->tt_gmtoff;
    305   1.99  christos 			if (sp->types[i] != 0)
    306   1.99  christos 				return l;
    307   1.99  christos 		}
    308   1.99  christos 	}
    309   1.99  christos 	if (l == -1)
    310   1.99  christos 		errno = ESRCH;
    311   1.99  christos 	return l;
    312   1.99  christos }
    313   1.99  christos 
    314   1.49  christos static void
    315   1.93  christos scrub_abbrs(struct state *sp)
    316   1.49  christos {
    317   1.93  christos 	int i;
    318   1.49  christos 
    319   1.49  christos 	/*
    320   1.49  christos 	** First, replace bogus characters.
    321   1.49  christos 	*/
    322   1.49  christos 	for (i = 0; i < sp->charcnt; ++i)
    323   1.49  christos 		if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
    324   1.49  christos 			sp->chars[i] = TZ_ABBR_ERR_CHAR;
    325   1.49  christos 	/*
    326   1.49  christos 	** Second, truncate long abbreviations.
    327   1.49  christos 	*/
    328   1.49  christos 	for (i = 0; i < sp->typecnt; ++i) {
    329   1.49  christos 		const struct ttinfo * const	ttisp = &sp->ttis[i];
    330   1.49  christos 		char *				cp = &sp->chars[ttisp->tt_abbrind];
    331   1.49  christos 
    332   1.49  christos 		if (strlen(cp) > TZ_ABBR_MAX_LEN &&
    333   1.49  christos 			strcmp(cp, GRANDPARENTED) != 0)
    334   1.49  christos 				*(cp + TZ_ABBR_MAX_LEN) = '\0';
    335   1.49  christos 	}
    336   1.49  christos }
    337   1.49  christos 
    338   1.93  christos static void
    339   1.93  christos update_tzname_etc(const struct state *sp, const struct ttinfo *ttisp)
    340   1.92  christos {
    341   1.93  christos 	tzname[ttisp->tt_isdst] = __UNCONST(&sp->chars[ttisp->tt_abbrind]);
    342   1.92  christos #ifdef USG_COMPAT
    343   1.93  christos 	if (!ttisp->tt_isdst)
    344   1.93  christos 		timezone = - ttisp->tt_gmtoff;
    345   1.93  christos #endif
    346   1.92  christos #ifdef ALTZONE
    347   1.93  christos 	if (ttisp->tt_isdst)
    348   1.93  christos 	    altzone = - ttisp->tt_gmtoff;
    349   1.92  christos #endif /* defined ALTZONE */
    350   1.92  christos }
    351   1.92  christos 
    352   1.45   mlelstv static void
    353   1.45   mlelstv settzname(void)
    354    1.1       jtc {
    355   1.49  christos 	timezone_t const	sp = lclptr;
    356   1.49  christos 	int			i;
    357    1.1       jtc 
    358   1.37  christos 	tzname[0] = (__aconst char *)__UNCONST(wildabbr);
    359   1.37  christos 	tzname[1] = (__aconst char *)__UNCONST(wildabbr);
    360    1.1       jtc #ifdef USG_COMPAT
    361    1.1       jtc 	daylight = 0;
    362    1.1       jtc 	timezone = 0;
    363    1.1       jtc #endif /* defined USG_COMPAT */
    364    1.1       jtc #ifdef ALTZONE
    365    1.1       jtc 	altzone = 0;
    366    1.1       jtc #endif /* defined ALTZONE */
    367    1.1       jtc 	if (sp == NULL) {
    368   1.37  christos 		tzname[0] = tzname[1] = (__aconst char *)__UNCONST(gmt);
    369    1.1       jtc 		return;
    370    1.1       jtc 	}
    371   1.58  christos 	/*
    372   1.58  christos 	** And to get the latest zone names into tzname. . .
    373   1.58  christos 	*/
    374   1.92  christos 	for (i = 0; i < sp->typecnt; ++i)
    375   1.93  christos 		update_tzname_etc(sp, &sp->ttis[i]);
    376    1.1       jtc 
    377   1.93  christos 	for (i = 0; i < sp->timecnt; ++i) {
    378   1.93  christos 		const struct ttinfo * const ttisp = &sp->ttis[sp->types[i]];
    379   1.93  christos 		update_tzname_etc(sp, ttisp);
    380   1.93  christos #ifdef USG_COMPAT
    381   1.93  christos 		if (ttisp->tt_isdst)
    382   1.93  christos 			daylight = 1;
    383   1.93  christos #endif /* defined USG_COMPAT */
    384   1.93  christos 	}
    385    1.1       jtc }
    386    1.1       jtc 
    387   1.87  christos static bool
    388   1.49  christos differ_by_repeat(const time_t t1, const time_t t0)
    389   1.45   mlelstv {
    390   1.78  christos 	if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
    391   1.78  christos 		return 0;
    392   1.45   mlelstv 	return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
    393   1.45   mlelstv }
    394   1.45   mlelstv 
    395   1.91  christos union input_buffer {
    396   1.91  christos 	/* The first part of the buffer, interpreted as a header.  */
    397   1.91  christos 	struct tzhead tzhead;
    398   1.91  christos 
    399   1.91  christos 	/* The entire buffer.  */
    400   1.91  christos 	char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
    401   1.91  christos 	  + 4 * TZ_MAX_TIMES];
    402   1.91  christos };
    403   1.91  christos 
    404   1.91  christos /* Local storage needed for 'tzloadbody'.  */
    405   1.91  christos union local_storage {
    406   1.91  christos 	/* The file name to be opened.  */
    407   1.91  christos 	char fullname[FILENAME_MAX + 1];
    408   1.91  christos 
    409   1.91  christos 	/* The results of analyzing the file's contents after it is opened.  */
    410   1.91  christos 	struct {
    411   1.91  christos 		/* The input buffer.  */
    412   1.91  christos 		union input_buffer u;
    413   1.91  christos 
    414   1.91  christos 		/* A temporary state used for parsing a TZ string in the file.  */
    415   1.91  christos 		struct state st;
    416   1.91  christos 	} u;
    417   1.91  christos };
    418   1.91  christos 
    419   1.91  christos /* Load tz data from the file named NAME into *SP.  Read extended
    420   1.91  christos    format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
    421   1.91  christos    success, an errno value on failure.  */
    422   1.91  christos static int
    423   1.91  christos tzloadbody(char const *name, struct state *sp, bool doextend,
    424   1.91  christos   union local_storage *lsp)
    425   1.49  christos {
    426   1.49  christos 	int			i;
    427   1.49  christos 	int			fid;
    428   1.49  christos 	int			stored;
    429   1.66  christos 	ssize_t			nread;
    430   1.91  christos 	bool			doaccess;
    431   1.91  christos 	char			*fullname = lsp->fullname;
    432   1.91  christos 	union input_buffer	*up = &lsp->u.u;
    433   1.91  christos 	size_t			tzheadsize = sizeof(struct tzhead);
    434   1.83  christos 
    435   1.87  christos 	sp->goback = sp->goahead = false;
    436   1.83  christos 
    437   1.83  christos 	if (! name) {
    438   1.83  christos 		name = TZDEFAULT;
    439   1.83  christos 		if (! name)
    440   1.91  christos 			return EINVAL;
    441   1.83  christos 	}
    442   1.83  christos 
    443   1.83  christos 	if (name[0] == ':')
    444   1.83  christos 		++name;
    445   1.83  christos 	doaccess = name[0] == '/';
    446   1.83  christos 	if (!doaccess) {
    447   1.91  christos 		char const *p = TZDIR;
    448   1.91  christos 		if (! p)
    449   1.91  christos 			return EINVAL;
    450   1.91  christos 		if (sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
    451   1.91  christos 			return ENAMETOOLONG;
    452   1.83  christos 		strcpy(fullname, p);
    453   1.83  christos 		strcat(fullname, "/");
    454   1.83  christos 		strcat(fullname, name);
    455   1.83  christos 		/* Set doaccess if '.' (as in "../") shows up in name.  */
    456   1.83  christos 		if (strchr(name, '.'))
    457   1.87  christos 			doaccess = true;
    458   1.83  christos 		name = fullname;
    459    1.1       jtc 	}
    460   1.83  christos 	if (doaccess && access(name, R_OK) != 0)
    461   1.91  christos 		return errno;
    462   1.83  christos 
    463   1.83  christos 	fid = open(name, OPEN_MODE);
    464   1.83  christos 	if (fid < 0)
    465   1.91  christos 		return errno;
    466   1.58  christos 	nread = read(fid, up->buf, sizeof up->buf);
    467   1.91  christos 	if (nread < (ssize_t)tzheadsize) {
    468   1.91  christos 		int err = nread < 0 ? errno : EINVAL;
    469   1.91  christos 		close(fid);
    470   1.91  christos 		return err;
    471   1.91  christos 	}
    472   1.91  christos 	if (close(fid) < 0)
    473   1.91  christos 		return errno;
    474   1.45   mlelstv 	for (stored = 4; stored <= 8; stored *= 2) {
    475   1.87  christos 		int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
    476   1.87  christos 		int_fast32_t ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
    477   1.87  christos 		int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
    478   1.87  christos 		int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
    479   1.87  christos 		int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
    480   1.87  christos 		int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
    481   1.91  christos 		char const *p = up->buf + tzheadsize;
    482   1.87  christos 		if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
    483   1.87  christos 		       && 0 < typecnt && typecnt < TZ_MAX_TYPES
    484   1.87  christos 		       && 0 <= timecnt && timecnt < TZ_MAX_TIMES
    485   1.87  christos 		       && 0 <= charcnt && charcnt < TZ_MAX_CHARS
    486   1.87  christos 		       && (ttisstdcnt == typecnt || ttisstdcnt == 0)
    487   1.87  christos 		       && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
    488   1.91  christos 		  return EINVAL;
    489   1.91  christos 		if ((size_t)nread
    490   1.91  christos 		    < (tzheadsize		/* struct tzhead */
    491   1.91  christos 		       + timecnt * stored	/* ats */
    492   1.87  christos 		       + timecnt		/* types */
    493   1.87  christos 		       + typecnt * 6		/* ttinfos */
    494   1.87  christos 		       + charcnt		/* chars */
    495   1.87  christos 		       + leapcnt * (stored + 4)	/* lsinfos */
    496   1.87  christos 		       + ttisstdcnt		/* ttisstds */
    497   1.87  christos 		       + ttisgmtcnt))		/* ttisgmts */
    498   1.91  christos 		  return EINVAL;
    499   1.87  christos 		sp->leapcnt = leapcnt;
    500   1.87  christos 		sp->timecnt = timecnt;
    501   1.87  christos 		sp->typecnt = typecnt;
    502   1.87  christos 		sp->charcnt = charcnt;
    503   1.87  christos 
    504   1.87  christos 		/* Read transitions, discarding those out of time_t range.
    505   1.87  christos 		   But pretend the last transition before time_t_min
    506   1.87  christos 		   occurred at time_t_min.  */
    507   1.81  christos 		timecnt = 0;
    508    1.1       jtc 		for (i = 0; i < sp->timecnt; ++i) {
    509   1.81  christos 			int_fast64_t at
    510   1.81  christos 			  = stored == 4 ? detzcode(p) : detzcode64(p);
    511   1.87  christos 			sp->types[i] = at <= time_t_max;
    512   1.81  christos 			if (sp->types[i]) {
    513   1.87  christos 				time_t attime
    514   1.87  christos 				    = ((TYPE_SIGNED(time_t) ?
    515   1.87  christos 				    at < time_t_min : at < 0)
    516   1.87  christos 				    ? time_t_min : (time_t)at);
    517   1.87  christos 				if (timecnt && attime <= sp->ats[timecnt - 1]) {
    518   1.87  christos 					if (attime < sp->ats[timecnt - 1])
    519   1.91  christos 						return EINVAL;
    520   1.87  christos 					sp->types[i - 1] = 0;
    521   1.87  christos 					timecnt--;
    522   1.81  christos 				}
    523   1.87  christos 				sp->ats[timecnt++] = attime;
    524   1.81  christos 			}
    525   1.45   mlelstv 			p += stored;
    526    1.1       jtc 		}
    527   1.87  christos 
    528   1.81  christos 		timecnt = 0;
    529    1.1       jtc 		for (i = 0; i < sp->timecnt; ++i) {
    530   1.81  christos 			unsigned char typ = *p++;
    531   1.81  christos 			if (sp->typecnt <= typ)
    532   1.91  christos 			  return EINVAL;
    533   1.81  christos 			if (sp->types[i])
    534   1.81  christos 				sp->types[timecnt++] = typ;
    535    1.1       jtc 		}
    536   1.87  christos 		sp->timecnt = timecnt;
    537    1.1       jtc 		for (i = 0; i < sp->typecnt; ++i) {
    538   1.49  christos 			struct ttinfo *	ttisp;
    539   1.87  christos 			unsigned char isdst, abbrind;
    540    1.1       jtc 
    541    1.1       jtc 			ttisp = &sp->ttis[i];
    542    1.1       jtc 			ttisp->tt_gmtoff = detzcode(p);
    543    1.1       jtc 			p += 4;
    544   1.87  christos 			isdst = *p++;
    545   1.87  christos 			if (! (isdst < 2))
    546   1.91  christos 				return EINVAL;
    547   1.87  christos 			ttisp->tt_isdst = isdst;
    548   1.87  christos 			abbrind = *p++;
    549   1.87  christos 			if (! (abbrind < sp->charcnt))
    550   1.91  christos 				return EINVAL;
    551   1.87  christos 			ttisp->tt_abbrind = abbrind;
    552    1.1       jtc 		}
    553    1.1       jtc 		for (i = 0; i < sp->charcnt; ++i)
    554    1.1       jtc 			sp->chars[i] = *p++;
    555    1.1       jtc 		sp->chars[i] = '\0';	/* ensure '\0' at end */
    556   1.87  christos 
    557   1.87  christos 		/* Read leap seconds, discarding those out of time_t range.  */
    558   1.87  christos 		leapcnt = 0;
    559    1.1       jtc 		for (i = 0; i < sp->leapcnt; ++i) {
    560   1.87  christos 			int_fast64_t tr = stored == 4 ? detzcode(p) :
    561   1.87  christos 			    detzcode64(p);
    562   1.87  christos 			int_fast32_t corr = detzcode(p + stored);
    563   1.87  christos 			p += stored + 4;
    564   1.87  christos 			if (tr <= time_t_max) {
    565   1.87  christos 				time_t trans = ((TYPE_SIGNED(time_t) ?
    566   1.87  christos 				    tr < time_t_min : tr < 0)
    567   1.87  christos 				    ? time_t_min : (time_t)tr);
    568   1.87  christos 				if (leapcnt && trans <=
    569   1.87  christos 				    sp->lsis[leapcnt - 1].ls_trans) {
    570   1.87  christos 					if (trans <
    571   1.87  christos 					    sp->lsis[leapcnt - 1].ls_trans)
    572   1.91  christos 						return EINVAL;
    573   1.87  christos 					leapcnt--;
    574   1.87  christos 				}
    575   1.87  christos 				sp->lsis[leapcnt].ls_trans = trans;
    576   1.87  christos 				sp->lsis[leapcnt].ls_corr = corr;
    577   1.87  christos 				leapcnt++;
    578   1.87  christos 			}
    579   1.87  christos 		}
    580   1.87  christos 		sp->leapcnt = leapcnt;
    581    1.1       jtc 
    582    1.1       jtc 		for (i = 0; i < sp->typecnt; ++i) {
    583   1.49  christos 			struct ttinfo *	ttisp;
    584    1.1       jtc 
    585    1.1       jtc 			ttisp = &sp->ttis[i];
    586    1.1       jtc 			if (ttisstdcnt == 0)
    587   1.87  christos 				ttisp->tt_ttisstd = false;
    588    1.1       jtc 			else {
    589   1.87  christos 				if (*p != true && *p != false)
    590   1.91  christos 				  return EINVAL;
    591    1.1       jtc 				ttisp->tt_ttisstd = *p++;
    592    1.1       jtc 			}
    593    1.1       jtc 		}
    594    1.1       jtc 		for (i = 0; i < sp->typecnt; ++i) {
    595   1.49  christos 			struct ttinfo *	ttisp;
    596    1.1       jtc 
    597    1.1       jtc 			ttisp = &sp->ttis[i];
    598    1.1       jtc 			if (ttisgmtcnt == 0)
    599   1.87  christos 				ttisp->tt_ttisgmt = false;
    600    1.1       jtc 			else {
    601   1.87  christos 				if (*p != true && *p != false)
    602   1.91  christos 						return EINVAL;
    603    1.1       jtc 				ttisp->tt_ttisgmt = *p++;
    604    1.1       jtc 			}
    605    1.1       jtc 		}
    606   1.45   mlelstv 		/*
    607   1.45   mlelstv 		** If this is an old file, we're done.
    608   1.45   mlelstv 		*/
    609   1.58  christos 		if (up->tzhead.tzh_version[0] == '\0')
    610   1.45   mlelstv 			break;
    611   1.58  christos 		nread -= p - up->buf;
    612   1.91  christos 		memmove(up->buf, p, (size_t)nread);
    613   1.45   mlelstv 	}
    614   1.45   mlelstv 	if (doextend && nread > 2 &&
    615   1.58  christos 		up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
    616   1.45   mlelstv 		sp->typecnt + 2 <= TZ_MAX_TYPES) {
    617   1.87  christos 			struct state *ts = &lsp->u.st;
    618   1.45   mlelstv 
    619   1.58  christos 			up->buf[nread - 1] = '\0';
    620   1.87  christos 			if (tzparse(&up->buf[1], ts, false)
    621   1.98  christos 			    && ts->typecnt == 2) {
    622   1.98  christos 
    623   1.98  christos 			  /* Attempt to reuse existing abbreviations.
    624   1.98  christos 			     Without this, America/Anchorage would stop
    625   1.98  christos 			     working after 2037 when TZ_MAX_CHARS is 50, as
    626   1.98  christos 			     sp->charcnt equals 42 (for LMT CAT CAWT CAPT AHST
    627   1.98  christos 			     AHDT YST AKDT AKST) and ts->charcnt equals 10
    628   1.98  christos 			     (for AKST AKDT).  Reusing means sp->charcnt can
    629   1.98  christos 			     stay 42 in this example.  */
    630   1.98  christos 			  int gotabbr = 0;
    631   1.98  christos 			  int charcnt = sp->charcnt;
    632   1.98  christos 			  for (i = 0; i < 2; i++) {
    633   1.98  christos 			    char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
    634   1.98  christos 			    int j;
    635   1.98  christos 			    for (j = 0; j < charcnt; j++)
    636   1.98  christos 			      if (strcmp(sp->chars + j, tsabbr) == 0) {
    637   1.98  christos 				ts->ttis[i].tt_abbrind = j;
    638   1.98  christos 				gotabbr++;
    639   1.98  christos 				break;
    640   1.98  christos 			      }
    641   1.98  christos 			    if (! (j < charcnt)) {
    642   1.99  christos 			      size_t tsabbrlen = strlen(tsabbr);
    643   1.98  christos 			      if (j + tsabbrlen < TZ_MAX_CHARS) {
    644   1.98  christos 				strcpy(sp->chars + j, tsabbr);
    645  1.100  christos 				charcnt = (int_fast32_t)(j + tsabbrlen + 1);
    646   1.98  christos 				ts->ttis[i].tt_abbrind = j;
    647   1.98  christos 				gotabbr++;
    648   1.98  christos 			      }
    649   1.98  christos 			    }
    650   1.98  christos 			  }
    651   1.98  christos 			  if (gotabbr == 2) {
    652   1.98  christos 			    sp->charcnt = charcnt;
    653   1.98  christos 			    for (i = 0; i < ts->timecnt; i++)
    654   1.98  christos 			      if (sp->ats[sp->timecnt - 1] < ts->ats[i])
    655   1.98  christos 				break;
    656   1.98  christos 			    while (i < ts->timecnt
    657   1.98  christos 				   && sp->timecnt < TZ_MAX_TIMES) {
    658   1.98  christos 			      sp->ats[sp->timecnt] = ts->ats[i];
    659   1.98  christos 			      sp->types[sp->timecnt] = (sp->typecnt
    660   1.98  christos 							+ ts->types[i]);
    661   1.98  christos 			      sp->timecnt++;
    662   1.98  christos 			      i++;
    663   1.98  christos 			    }
    664   1.98  christos 			    sp->ttis[sp->typecnt++] = ts->ttis[0];
    665   1.98  christos 			    sp->ttis[sp->typecnt++] = ts->ttis[1];
    666   1.98  christos 			  }
    667   1.45   mlelstv 			}
    668   1.45   mlelstv 	}
    669   1.45   mlelstv 	if (sp->timecnt > 1) {
    670   1.45   mlelstv 		for (i = 1; i < sp->timecnt; ++i)
    671   1.45   mlelstv 			if (typesequiv(sp, sp->types[i], sp->types[0]) &&
    672   1.45   mlelstv 				differ_by_repeat(sp->ats[i], sp->ats[0])) {
    673   1.87  christos 					sp->goback = true;
    674   1.45   mlelstv 					break;
    675   1.45   mlelstv 				}
    676   1.45   mlelstv 		for (i = sp->timecnt - 2; i >= 0; --i)
    677   1.45   mlelstv 			if (typesequiv(sp, sp->types[sp->timecnt - 1],
    678   1.45   mlelstv 				sp->types[i]) &&
    679   1.45   mlelstv 				differ_by_repeat(sp->ats[sp->timecnt - 1],
    680   1.45   mlelstv 				sp->ats[i])) {
    681   1.87  christos 					sp->goahead = true;
    682   1.45   mlelstv 					break;
    683   1.45   mlelstv 		}
    684    1.1       jtc 	}
    685   1.74  christos 	/*
    686   1.74  christos 	** If type 0 is is unused in transitions,
    687   1.74  christos 	** it's the type to use for early times.
    688   1.74  christos 	*/
    689   1.87  christos 	for (i = 0; i < sp->timecnt; ++i)
    690   1.74  christos 		if (sp->types[i] == 0)
    691   1.74  christos 			break;
    692   1.87  christos 	i = i < sp->timecnt ? -1 : 0;
    693   1.74  christos 	/*
    694   1.74  christos 	** Absent the above,
    695   1.74  christos 	** if there are transition times
    696   1.74  christos 	** and the first transition is to a daylight time
    697   1.74  christos 	** find the standard type less than and closest to
    698   1.74  christos 	** the type of the first transition.
    699   1.74  christos 	*/
    700   1.74  christos 	if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
    701   1.74  christos 		i = sp->types[0];
    702   1.74  christos 		while (--i >= 0)
    703   1.74  christos 			if (!sp->ttis[i].tt_isdst)
    704   1.74  christos 				break;
    705   1.74  christos 	}
    706   1.74  christos 	/*
    707   1.74  christos 	** If no result yet, find the first standard type.
    708   1.74  christos 	** If there is none, punt to type zero.
    709   1.74  christos 	*/
    710   1.74  christos 	if (i < 0) {
    711   1.74  christos 		i = 0;
    712   1.74  christos 		while (sp->ttis[i].tt_isdst)
    713   1.74  christos 			if (++i >= sp->typecnt) {
    714   1.74  christos 				i = 0;
    715   1.74  christos 				break;
    716   1.74  christos 			}
    717   1.74  christos 	}
    718   1.74  christos 	sp->defaulttype = i;
    719   1.91  christos 	return 0;
    720   1.91  christos }
    721   1.91  christos 
    722   1.91  christos /* Load tz data from the file named NAME into *SP.  Read extended
    723   1.91  christos    format if DOEXTEND.  Return 0 on success, an errno value on failure.  */
    724   1.91  christos static int
    725   1.91  christos tzload(char const *name, struct state *sp, bool doextend)
    726   1.91  christos {
    727   1.91  christos 	union local_storage *lsp = malloc(sizeof *lsp);
    728   1.91  christos 	if (!lsp)
    729   1.91  christos 		return errno;
    730   1.91  christos 	else {
    731   1.91  christos 		int err = tzloadbody(name, sp, doextend, lsp);
    732   1.91  christos 		free(lsp);
    733   1.91  christos 		return err;
    734   1.91  christos 	}
    735    1.1       jtc }
    736    1.1       jtc 
    737   1.87  christos static bool
    738   1.96  christos typesequiv(const struct state *sp, int a, int b)
    739   1.45   mlelstv {
    740   1.87  christos 	bool result;
    741   1.45   mlelstv 
    742   1.45   mlelstv 	if (sp == NULL ||
    743   1.45   mlelstv 		a < 0 || a >= sp->typecnt ||
    744   1.45   mlelstv 		b < 0 || b >= sp->typecnt)
    745   1.87  christos 			result = false;
    746   1.45   mlelstv 	else {
    747   1.49  christos 		const struct ttinfo *	ap = &sp->ttis[a];
    748   1.49  christos 		const struct ttinfo *	bp = &sp->ttis[b];
    749   1.45   mlelstv 		result = ap->tt_gmtoff == bp->tt_gmtoff &&
    750   1.45   mlelstv 			ap->tt_isdst == bp->tt_isdst &&
    751   1.45   mlelstv 			ap->tt_ttisstd == bp->tt_ttisstd &&
    752   1.45   mlelstv 			ap->tt_ttisgmt == bp->tt_ttisgmt &&
    753   1.45   mlelstv 			strcmp(&sp->chars[ap->tt_abbrind],
    754   1.45   mlelstv 			&sp->chars[bp->tt_abbrind]) == 0;
    755   1.45   mlelstv 	}
    756   1.45   mlelstv 	return result;
    757   1.45   mlelstv }
    758   1.45   mlelstv 
    759    1.1       jtc static const int	mon_lengths[2][MONSPERYEAR] = {
    760    1.1       jtc 	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
    761    1.1       jtc 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
    762    1.1       jtc };
    763    1.1       jtc 
    764    1.1       jtc static const int	year_lengths[2] = {
    765    1.1       jtc 	DAYSPERNYEAR, DAYSPERLYEAR
    766    1.1       jtc };
    767    1.1       jtc 
    768    1.1       jtc /*
    769    1.1       jtc ** Given a pointer into a time zone string, scan until a character that is not
    770   1.45   mlelstv ** a valid character in a zone name is found. Return a pointer to that
    771    1.1       jtc ** character.
    772    1.1       jtc */
    773    1.1       jtc 
    774   1.87  christos static const char * ATTRIBUTE_PURE
    775   1.67      matt getzname(const char *strp)
    776    1.1       jtc {
    777   1.49  christos 	char	c;
    778    1.1       jtc 
    779    1.5       jtc 	while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
    780    1.1       jtc 		c != '+')
    781    1.1       jtc 			++strp;
    782    1.1       jtc 	return strp;
    783    1.1       jtc }
    784    1.1       jtc 
    785    1.1       jtc /*
    786   1.45   mlelstv ** Given a pointer into an extended time zone string, scan until the ending
    787   1.45   mlelstv ** delimiter of the zone name is located. Return a pointer to the delimiter.
    788   1.45   mlelstv **
    789   1.45   mlelstv ** As with getzname above, the legal character set is actually quite
    790   1.45   mlelstv ** restricted, with other characters producing undefined results.
    791   1.45   mlelstv ** We don't do any checking here; checking is done later in common-case code.
    792   1.45   mlelstv */
    793   1.45   mlelstv 
    794   1.87  christos static const char * ATTRIBUTE_PURE
    795   1.49  christos getqzname(const char *strp, const int delim)
    796   1.45   mlelstv {
    797   1.49  christos 	int	c;
    798   1.45   mlelstv 
    799   1.45   mlelstv 	while ((c = *strp) != '\0' && c != delim)
    800   1.45   mlelstv 		++strp;
    801   1.45   mlelstv 	return strp;
    802   1.45   mlelstv }
    803   1.45   mlelstv 
    804   1.45   mlelstv /*
    805    1.1       jtc ** Given a pointer into a time zone string, extract a number from that string.
    806    1.1       jtc ** Check that the number is within a specified range; if it is not, return
    807    1.1       jtc ** NULL.
    808    1.1       jtc ** Otherwise, return a pointer to the first character not part of the number.
    809    1.1       jtc */
    810    1.1       jtc 
    811    1.1       jtc static const char *
    812   1.68  christos getnum(const char *strp, int *const nump, const int min, const int max)
    813    1.1       jtc {
    814   1.49  christos 	char	c;
    815   1.49  christos 	int	num;
    816    1.1       jtc 
    817   1.46  christos 	if (strp == NULL || !is_digit(c = *strp)) {
    818   1.46  christos 		errno = EINVAL;
    819    1.1       jtc 		return NULL;
    820   1.46  christos 	}
    821    1.1       jtc 	num = 0;
    822    1.5       jtc 	do {
    823    1.1       jtc 		num = num * 10 + (c - '0');
    824   1.46  christos 		if (num > max) {
    825   1.46  christos 			errno = EOVERFLOW;
    826    1.1       jtc 			return NULL;	/* illegal value */
    827   1.46  christos 		}
    828    1.5       jtc 		c = *++strp;
    829    1.5       jtc 	} while (is_digit(c));
    830   1.46  christos 	if (num < min) {
    831   1.46  christos 		errno = EINVAL;
    832    1.1       jtc 		return NULL;		/* illegal value */
    833   1.46  christos 	}
    834    1.1       jtc 	*nump = num;
    835    1.1       jtc 	return strp;
    836    1.1       jtc }
    837    1.1       jtc 
    838    1.1       jtc /*
    839    1.1       jtc ** Given a pointer into a time zone string, extract a number of seconds,
    840    1.1       jtc ** in hh[:mm[:ss]] form, from the string.
    841    1.1       jtc ** If any error occurs, return NULL.
    842    1.1       jtc ** Otherwise, return a pointer to the first character not part of the number
    843    1.1       jtc ** of seconds.
    844    1.1       jtc */
    845    1.1       jtc 
    846    1.1       jtc static const char *
    847   1.74  christos getsecs(const char *strp, int_fast32_t *const secsp)
    848    1.1       jtc {
    849    1.1       jtc 	int	num;
    850    1.1       jtc 
    851    1.1       jtc 	/*
    852   1.83  christos 	** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
    853    1.1       jtc 	** "M10.4.6/26", which does not conform to Posix,
    854    1.1       jtc 	** but which specifies the equivalent of
    855   1.83  christos 	** "02:00 on the first Sunday on or after 23 Oct".
    856    1.1       jtc 	*/
    857    1.1       jtc 	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
    858    1.1       jtc 	if (strp == NULL)
    859    1.1       jtc 		return NULL;
    860   1.74  christos 	*secsp = num * (int_fast32_t) SECSPERHOUR;
    861    1.1       jtc 	if (*strp == ':') {
    862    1.1       jtc 		++strp;
    863    1.1       jtc 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
    864    1.1       jtc 		if (strp == NULL)
    865    1.1       jtc 			return NULL;
    866    1.1       jtc 		*secsp += num * SECSPERMIN;
    867    1.1       jtc 		if (*strp == ':') {
    868    1.1       jtc 			++strp;
    869   1.83  christos 			/* 'SECSPERMIN' allows for leap seconds.  */
    870    1.1       jtc 			strp = getnum(strp, &num, 0, SECSPERMIN);
    871    1.1       jtc 			if (strp == NULL)
    872    1.1       jtc 				return NULL;
    873    1.1       jtc 			*secsp += num;
    874    1.1       jtc 		}
    875    1.1       jtc 	}
    876    1.1       jtc 	return strp;
    877    1.1       jtc }
    878    1.1       jtc 
    879    1.1       jtc /*
    880    1.1       jtc ** Given a pointer into a time zone string, extract an offset, in
    881    1.1       jtc ** [+-]hh[:mm[:ss]] form, from the string.
    882    1.1       jtc ** If any error occurs, return NULL.
    883    1.1       jtc ** Otherwise, return a pointer to the first character not part of the time.
    884    1.1       jtc */
    885    1.1       jtc 
    886    1.1       jtc static const char *
    887   1.74  christos getoffset(const char *strp, int_fast32_t *const offsetp)
    888    1.1       jtc {
    889   1.87  christos 	bool neg = false;
    890    1.1       jtc 
    891    1.1       jtc 	if (*strp == '-') {
    892   1.87  christos 		neg = true;
    893    1.1       jtc 		++strp;
    894    1.5       jtc 	} else if (*strp == '+')
    895    1.5       jtc 		++strp;
    896    1.1       jtc 	strp = getsecs(strp, offsetp);
    897    1.1       jtc 	if (strp == NULL)
    898    1.1       jtc 		return NULL;		/* illegal time */
    899    1.1       jtc 	if (neg)
    900    1.1       jtc 		*offsetp = -*offsetp;
    901    1.1       jtc 	return strp;
    902    1.1       jtc }
    903    1.1       jtc 
    904    1.1       jtc /*
    905    1.1       jtc ** Given a pointer into a time zone string, extract a rule in the form
    906   1.45   mlelstv ** date[/time]. See POSIX section 8 for the format of "date" and "time".
    907    1.1       jtc ** If a valid rule is not found, return NULL.
    908    1.1       jtc ** Otherwise, return a pointer to the first character not part of the rule.
    909    1.1       jtc */
    910    1.1       jtc 
    911    1.1       jtc static const char *
    912   1.49  christos getrule(const char *strp, struct rule *const rulep)
    913    1.1       jtc {
    914    1.1       jtc 	if (*strp == 'J') {
    915    1.1       jtc 		/*
    916    1.1       jtc 		** Julian day.
    917    1.1       jtc 		*/
    918    1.1       jtc 		rulep->r_type = JULIAN_DAY;
    919    1.1       jtc 		++strp;
    920    1.1       jtc 		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
    921    1.1       jtc 	} else if (*strp == 'M') {
    922    1.1       jtc 		/*
    923    1.1       jtc 		** Month, week, day.
    924    1.1       jtc 		*/
    925    1.1       jtc 		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
    926    1.1       jtc 		++strp;
    927    1.1       jtc 		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
    928    1.1       jtc 		if (strp == NULL)
    929    1.1       jtc 			return NULL;
    930    1.1       jtc 		if (*strp++ != '.')
    931    1.1       jtc 			return NULL;
    932    1.1       jtc 		strp = getnum(strp, &rulep->r_week, 1, 5);
    933    1.1       jtc 		if (strp == NULL)
    934    1.1       jtc 			return NULL;
    935    1.1       jtc 		if (*strp++ != '.')
    936    1.1       jtc 			return NULL;
    937    1.1       jtc 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
    938    1.5       jtc 	} else if (is_digit(*strp)) {
    939    1.1       jtc 		/*
    940    1.1       jtc 		** Day of year.
    941    1.1       jtc 		*/
    942    1.1       jtc 		rulep->r_type = DAY_OF_YEAR;
    943    1.1       jtc 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
    944    1.1       jtc 	} else	return NULL;		/* invalid format */
    945    1.1       jtc 	if (strp == NULL)
    946    1.1       jtc 		return NULL;
    947    1.1       jtc 	if (*strp == '/') {
    948    1.1       jtc 		/*
    949    1.1       jtc 		** Time specified.
    950    1.1       jtc 		*/
    951    1.1       jtc 		++strp;
    952   1.78  christos 		strp = getoffset(strp, &rulep->r_time);
    953    1.1       jtc 	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
    954    1.1       jtc 	return strp;
    955    1.1       jtc }
    956    1.1       jtc 
    957    1.1       jtc /*
    958   1.81  christos ** Given a year, a rule, and the offset from UT at the time that rule takes
    959   1.81  christos ** effect, calculate the year-relative time that rule takes effect.
    960    1.1       jtc */
    961    1.1       jtc 
    962   1.87  christos static int_fast32_t ATTRIBUTE_PURE
    963   1.81  christos transtime(const int year, const struct rule *const rulep,
    964   1.81  christos 	  const int_fast32_t offset)
    965   1.49  christos {
    966   1.87  christos 	bool	leapyear;
    967   1.87  christos 	int_fast32_t value;
    968   1.49  christos 	int	i;
    969    1.1       jtc 	int		d, m1, yy0, yy1, yy2, dow;
    970    1.1       jtc 
    971    1.1       jtc 	INITIALIZE(value);
    972    1.1       jtc 	leapyear = isleap(year);
    973    1.1       jtc 	switch (rulep->r_type) {
    974    1.1       jtc 
    975    1.1       jtc 	case JULIAN_DAY:
    976    1.1       jtc 		/*
    977    1.1       jtc 		** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
    978    1.1       jtc 		** years.
    979    1.1       jtc 		** In non-leap years, or if the day number is 59 or less, just
    980    1.1       jtc 		** add SECSPERDAY times the day number-1 to the time of
    981    1.1       jtc 		** January 1, midnight, to get the day.
    982    1.1       jtc 		*/
    983   1.81  christos 		value = (rulep->r_day - 1) * SECSPERDAY;
    984    1.1       jtc 		if (leapyear && rulep->r_day >= 60)
    985    1.1       jtc 			value += SECSPERDAY;
    986    1.1       jtc 		break;
    987    1.1       jtc 
    988    1.1       jtc 	case DAY_OF_YEAR:
    989    1.1       jtc 		/*
    990    1.1       jtc 		** n - day of year.
    991    1.1       jtc 		** Just add SECSPERDAY times the day number to the time of
    992    1.1       jtc 		** January 1, midnight, to get the day.
    993    1.1       jtc 		*/
    994   1.81  christos 		value = rulep->r_day * SECSPERDAY;
    995    1.1       jtc 		break;
    996    1.1       jtc 
    997    1.1       jtc 	case MONTH_NTH_DAY_OF_WEEK:
    998    1.1       jtc 		/*
    999    1.1       jtc 		** Mm.n.d - nth "dth day" of month m.
   1000    1.1       jtc 		*/
   1001    1.1       jtc 
   1002    1.1       jtc 		/*
   1003    1.1       jtc 		** Use Zeller's Congruence to get day-of-week of first day of
   1004    1.1       jtc 		** month.
   1005    1.1       jtc 		*/
   1006    1.1       jtc 		m1 = (rulep->r_mon + 9) % 12 + 1;
   1007    1.1       jtc 		yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
   1008    1.1       jtc 		yy1 = yy0 / 100;
   1009    1.1       jtc 		yy2 = yy0 % 100;
   1010    1.1       jtc 		dow = ((26 * m1 - 2) / 10 +
   1011    1.1       jtc 			1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
   1012    1.1       jtc 		if (dow < 0)
   1013    1.1       jtc 			dow += DAYSPERWEEK;
   1014    1.1       jtc 
   1015    1.1       jtc 		/*
   1016   1.45   mlelstv 		** "dow" is the day-of-week of the first day of the month. Get
   1017    1.1       jtc 		** the day-of-month (zero-origin) of the first "dow" day of the
   1018    1.1       jtc 		** month.
   1019    1.1       jtc 		*/
   1020    1.1       jtc 		d = rulep->r_day - dow;
   1021    1.1       jtc 		if (d < 0)
   1022    1.1       jtc 			d += DAYSPERWEEK;
   1023    1.1       jtc 		for (i = 1; i < rulep->r_week; ++i) {
   1024    1.1       jtc 			if (d + DAYSPERWEEK >=
   1025    1.1       jtc 				mon_lengths[leapyear][rulep->r_mon - 1])
   1026    1.1       jtc 					break;
   1027    1.1       jtc 			d += DAYSPERWEEK;
   1028    1.1       jtc 		}
   1029    1.1       jtc 
   1030    1.1       jtc 		/*
   1031    1.1       jtc 		** "d" is the day-of-month (zero-origin) of the day we want.
   1032    1.1       jtc 		*/
   1033   1.81  christos 		value = d * SECSPERDAY;
   1034   1.81  christos 		for (i = 0; i < rulep->r_mon - 1; ++i)
   1035   1.81  christos 			value += mon_lengths[leapyear][i] * SECSPERDAY;
   1036    1.1       jtc 		break;
   1037    1.1       jtc 	}
   1038    1.1       jtc 
   1039    1.1       jtc 	/*
   1040   1.81  christos 	** "value" is the year-relative time of 00:00:00 UT on the day in
   1041   1.81  christos 	** question. To get the year-relative time of the specified local
   1042    1.1       jtc 	** time on that day, add the transition time and the current offset
   1043   1.78  christos 	** from UT.
   1044    1.1       jtc 	*/
   1045   1.81  christos 	return value + rulep->r_time + offset;
   1046    1.1       jtc }
   1047    1.1       jtc 
   1048    1.1       jtc /*
   1049    1.1       jtc ** Given a POSIX section 8-style TZ string, fill in the rule tables as
   1050    1.1       jtc ** appropriate.
   1051    1.1       jtc */
   1052    1.1       jtc 
   1053   1.87  christos static bool
   1054   1.96  christos tzparse(const char *name, struct state *sp, bool lastditch)
   1055   1.87  christos {
   1056   1.87  christos 	const char *	stdname;
   1057   1.87  christos 	const char *	dstname;
   1058   1.87  christos 	size_t		stdlen;
   1059   1.87  christos 	size_t		dstlen;
   1060   1.96  christos 	size_t		charcnt;
   1061   1.87  christos 	int_fast32_t	stdoffset;
   1062   1.87  christos 	int_fast32_t	dstoffset;
   1063   1.87  christos 	char *		cp;
   1064   1.87  christos 	bool		load_ok;
   1065    1.1       jtc 
   1066   1.84    martin 	dstname = NULL; /* XXX gcc */
   1067    1.1       jtc 	stdname = name;
   1068    1.1       jtc 	if (lastditch) {
   1069   1.96  christos 		stdlen = sizeof gmt - 1;
   1070    1.1       jtc 		name += stdlen;
   1071   1.10       jtc 		stdoffset = 0;
   1072    1.1       jtc 	} else {
   1073   1.45   mlelstv 		if (*name == '<') {
   1074   1.45   mlelstv 			name++;
   1075   1.45   mlelstv 			stdname = name;
   1076   1.45   mlelstv 			name = getqzname(name, '>');
   1077   1.45   mlelstv 			if (*name != '>')
   1078   1.87  christos 			  return false;
   1079   1.45   mlelstv 			stdlen = name - stdname;
   1080   1.45   mlelstv 			name++;
   1081   1.45   mlelstv 		} else {
   1082   1.45   mlelstv 			name = getzname(name);
   1083   1.45   mlelstv 			stdlen = name - stdname;
   1084   1.45   mlelstv 		}
   1085   1.96  christos 		if (!stdlen)
   1086   1.87  christos 			return false;
   1087   1.45   mlelstv 		name = getoffset(name, &stdoffset);
   1088    1.1       jtc 		if (name == NULL)
   1089   1.87  christos 			return false;
   1090    1.1       jtc 	}
   1091   1.96  christos 	charcnt = stdlen + 1;
   1092   1.96  christos 	if (sizeof sp->chars < charcnt)
   1093   1.96  christos 		return false;
   1094   1.91  christos 	load_ok = tzload(TZDEFRULES, sp, false) == 0;
   1095   1.87  christos 	if (!load_ok)
   1096    1.1       jtc 		sp->leapcnt = 0;		/* so, we're off a little */
   1097    1.1       jtc 	if (*name != '\0') {
   1098   1.45   mlelstv 		if (*name == '<') {
   1099   1.45   mlelstv 			dstname = ++name;
   1100   1.45   mlelstv 			name = getqzname(name, '>');
   1101   1.45   mlelstv 			if (*name != '>')
   1102   1.87  christos 				return false;
   1103   1.45   mlelstv 			dstlen = name - dstname;
   1104   1.45   mlelstv 			name++;
   1105   1.45   mlelstv 		} else {
   1106   1.45   mlelstv 			dstname = name;
   1107   1.45   mlelstv 			name = getzname(name);
   1108   1.45   mlelstv 			dstlen = name - dstname; /* length of DST zone name */
   1109   1.45   mlelstv 		}
   1110   1.96  christos 		if (!dstlen)
   1111   1.96  christos 		  return false;
   1112   1.96  christos 		charcnt += dstlen + 1;
   1113   1.96  christos 		if (sizeof sp->chars < charcnt)
   1114   1.96  christos 		  return false;
   1115    1.1       jtc 		if (*name != '\0' && *name != ',' && *name != ';') {
   1116   1.45   mlelstv 			name = getoffset(name, &dstoffset);
   1117    1.1       jtc 			if (name == NULL)
   1118   1.87  christos 			  return false;
   1119    1.1       jtc 		} else	dstoffset = stdoffset - SECSPERHOUR;
   1120   1.87  christos 		if (*name == '\0' && !load_ok)
   1121   1.22    kleink 			name = TZDEFRULESTRING;
   1122    1.1       jtc 		if (*name == ',' || *name == ';') {
   1123    1.1       jtc 			struct rule	start;
   1124    1.1       jtc 			struct rule	end;
   1125   1.78  christos 			int		year;
   1126   1.78  christos 			int		yearlim;
   1127   1.81  christos 			int		timecnt;
   1128   1.78  christos 			time_t		janfirst;
   1129    1.1       jtc 
   1130    1.1       jtc 			++name;
   1131   1.45   mlelstv 			if ((name = getrule(name, &start)) == NULL)
   1132   1.87  christos 				return false;
   1133    1.1       jtc 			if (*name++ != ',')
   1134   1.87  christos 				return false;
   1135   1.45   mlelstv 			if ((name = getrule(name, &end)) == NULL)
   1136   1.87  christos 				return false;
   1137    1.1       jtc 			if (*name != '\0')
   1138   1.87  christos 				return false;
   1139    1.1       jtc 			sp->typecnt = 2;	/* standard time and DST */
   1140    1.1       jtc 			/*
   1141   1.45   mlelstv 			** Two transitions per year, from EPOCH_YEAR forward.
   1142    1.1       jtc 			*/
   1143   1.91  christos 			init_ttinfo(&sp->ttis[0], -dstoffset, true,
   1144   1.91  christos 			    (int)(stdlen + 1));
   1145   1.91  christos 			init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
   1146   1.82  christos 			sp->defaulttype = 0;
   1147   1.81  christos 			timecnt = 0;
   1148    1.1       jtc 			janfirst = 0;
   1149   1.78  christos 			yearlim = EPOCH_YEAR + YEARSPERREPEAT;
   1150   1.78  christos 			for (year = EPOCH_YEAR; year < yearlim; year++) {
   1151   1.81  christos 				int_fast32_t
   1152   1.81  christos 				  starttime = transtime(year, &start, stdoffset),
   1153   1.81  christos 				  endtime = transtime(year, &end, dstoffset);
   1154   1.81  christos 				int_fast32_t
   1155   1.81  christos 				  yearsecs = (year_lengths[isleap(year)]
   1156   1.81  christos 					      * SECSPERDAY);
   1157   1.87  christos 				bool reversed = endtime < starttime;
   1158   1.81  christos 				if (reversed) {
   1159   1.81  christos 					int_fast32_t swap = starttime;
   1160   1.81  christos 					starttime = endtime;
   1161   1.81  christos 					endtime = swap;
   1162   1.81  christos 				}
   1163   1.81  christos 				if (reversed
   1164   1.78  christos 				    || (starttime < endtime
   1165   1.78  christos 					&& (endtime - starttime
   1166   1.78  christos 					    < (yearsecs
   1167   1.78  christos 					       + (stdoffset - dstoffset))))) {
   1168   1.81  christos 					if (TZ_MAX_TIMES - 2 < timecnt)
   1169   1.78  christos 						break;
   1170   1.78  christos 					yearlim = year + YEARSPERREPEAT + 1;
   1171   1.81  christos 					sp->ats[timecnt] = janfirst;
   1172   1.81  christos 					if (increment_overflow_time
   1173   1.81  christos 					    (&sp->ats[timecnt], starttime))
   1174   1.81  christos 						break;
   1175   1.81  christos 					sp->types[timecnt++] = reversed;
   1176   1.81  christos 					sp->ats[timecnt] = janfirst;
   1177   1.81  christos 					if (increment_overflow_time
   1178   1.81  christos 					    (&sp->ats[timecnt], endtime))
   1179   1.81  christos 						break;
   1180   1.81  christos 					sp->types[timecnt++] = !reversed;
   1181    1.1       jtc 				}
   1182   1.81  christos 				if (increment_overflow_time(&janfirst, yearsecs))
   1183   1.45   mlelstv 					break;
   1184    1.1       jtc 			}
   1185   1.81  christos 			sp->timecnt = timecnt;
   1186   1.81  christos 			if (!timecnt)
   1187   1.78  christos 				sp->typecnt = 1;	/* Perpetual DST.  */
   1188    1.1       jtc 		} else {
   1189   1.74  christos 			int_fast32_t	theirstdoffset;
   1190   1.74  christos 			int_fast32_t	theirdstoffset;
   1191   1.74  christos 			int_fast32_t	theiroffset;
   1192   1.87  christos 			bool		isdst;
   1193   1.74  christos 			int		i;
   1194   1.74  christos 			int		j;
   1195    1.1       jtc 
   1196    1.1       jtc 			if (*name != '\0')
   1197   1.87  christos 				return false;
   1198    1.1       jtc 			/*
   1199   1.69  christos 			** Initial values of theirstdoffset and theirdstoffset.
   1200    1.1       jtc 			*/
   1201    1.1       jtc 			theirstdoffset = 0;
   1202    1.1       jtc 			for (i = 0; i < sp->timecnt; ++i) {
   1203    1.1       jtc 				j = sp->types[i];
   1204    1.1       jtc 				if (!sp->ttis[j].tt_isdst) {
   1205    1.5       jtc 					theirstdoffset =
   1206    1.5       jtc 						-sp->ttis[j].tt_gmtoff;
   1207    1.1       jtc 					break;
   1208    1.1       jtc 				}
   1209    1.1       jtc 			}
   1210   1.45   mlelstv 			theirdstoffset = 0;
   1211   1.45   mlelstv 			for (i = 0; i < sp->timecnt; ++i) {
   1212   1.45   mlelstv 				j = sp->types[i];
   1213   1.45   mlelstv 				if (sp->ttis[j].tt_isdst) {
   1214   1.45   mlelstv 					theirdstoffset =
   1215   1.45   mlelstv 						-sp->ttis[j].tt_gmtoff;
   1216   1.45   mlelstv 					break;
   1217   1.45   mlelstv 				}
   1218   1.45   mlelstv 			}
   1219    1.1       jtc 			/*
   1220    1.1       jtc 			** Initially we're assumed to be in standard time.
   1221    1.1       jtc 			*/
   1222   1.87  christos 			isdst = false;
   1223    1.1       jtc 			theiroffset = theirstdoffset;
   1224    1.1       jtc 			/*
   1225    1.1       jtc 			** Now juggle transition times and types
   1226    1.1       jtc 			** tracking offsets as you do.
   1227    1.1       jtc 			*/
   1228    1.1       jtc 			for (i = 0; i < sp->timecnt; ++i) {
   1229    1.1       jtc 				j = sp->types[i];
   1230    1.1       jtc 				sp->types[i] = sp->ttis[j].tt_isdst;
   1231    1.1       jtc 				if (sp->ttis[j].tt_ttisgmt) {
   1232    1.1       jtc 					/* No adjustment to transition time */
   1233    1.1       jtc 				} else {
   1234    1.1       jtc 					/*
   1235    1.1       jtc 					** If summer time is in effect, and the
   1236    1.1       jtc 					** transition time was not specified as
   1237    1.1       jtc 					** standard time, add the summer time
   1238    1.1       jtc 					** offset to the transition time;
   1239    1.1       jtc 					** otherwise, add the standard time
   1240    1.1       jtc 					** offset to the transition time.
   1241    1.1       jtc 					*/
   1242    1.1       jtc 					/*
   1243    1.1       jtc 					** Transitions from DST to DDST
   1244    1.1       jtc 					** will effectively disappear since
   1245    1.1       jtc 					** POSIX provides for only one DST
   1246    1.1       jtc 					** offset.
   1247    1.1       jtc 					*/
   1248   1.45   mlelstv 					if (isdst && !sp->ttis[j].tt_ttisstd) {
   1249   1.66  christos 						sp->ats[i] += (time_t)
   1250   1.66  christos 						    (dstoffset - theirdstoffset);
   1251   1.45   mlelstv 					} else {
   1252   1.66  christos 						sp->ats[i] += (time_t)
   1253   1.66  christos 						    (stdoffset - theirstdoffset);
   1254   1.45   mlelstv 					}
   1255    1.1       jtc 				}
   1256    1.1       jtc 				theiroffset = -sp->ttis[j].tt_gmtoff;
   1257   1.87  christos 				if (sp->ttis[j].tt_isdst)
   1258   1.39  christos 					theirstdoffset = theiroffset;
   1259   1.45   mlelstv 				else	theirdstoffset = theiroffset;
   1260    1.1       jtc 			}
   1261    1.1       jtc 			/*
   1262    1.1       jtc 			** Finally, fill in ttis.
   1263    1.1       jtc 			*/
   1264   1.91  christos 			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
   1265   1.91  christos 			init_ttinfo(&sp->ttis[1], -dstoffset, true,
   1266   1.91  christos 			    (int)(stdlen + 1));
   1267    1.7       jtc 			sp->typecnt = 2;
   1268   1.82  christos 			sp->defaulttype = 0;
   1269    1.1       jtc 		}
   1270    1.1       jtc 	} else {
   1271    1.1       jtc 		dstlen = 0;
   1272    1.1       jtc 		sp->typecnt = 1;		/* only standard time */
   1273    1.1       jtc 		sp->timecnt = 0;
   1274   1.91  christos 		init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
   1275   1.91  christos 		init_ttinfo(&sp->ttis[1], 0, false, 0);
   1276   1.82  christos 		sp->defaulttype = 0;
   1277    1.1       jtc 	}
   1278   1.99  christos 	sp->charcnt = (int)charcnt;
   1279    1.1       jtc 	cp = sp->chars;
   1280   1.87  christos 	(void) memcpy(cp, stdname, stdlen);
   1281    1.1       jtc 	cp += stdlen;
   1282    1.1       jtc 	*cp++ = '\0';
   1283    1.1       jtc 	if (dstlen != 0) {
   1284   1.87  christos 		(void) memcpy(cp, dstname, dstlen);
   1285    1.1       jtc 		*(cp + dstlen) = '\0';
   1286    1.1       jtc 	}
   1287   1.87  christos 	return true;
   1288    1.1       jtc }
   1289    1.1       jtc 
   1290    1.1       jtc static void
   1291   1.87  christos gmtload(struct state *const sp)
   1292   1.49  christos {
   1293   1.91  christos 	if (tzload(gmt, sp, true) != 0)
   1294   1.87  christos 		(void) tzparse(gmt, sp, true);
   1295   1.49  christos }
   1296   1.49  christos 
   1297   1.91  christos static int
   1298   1.87  christos zoneinit(struct state *sp, char const *name)
   1299   1.49  christos {
   1300   1.87  christos 	if (name && ! name[0]) {
   1301   1.91  christos 		/*
   1302   1.91  christos 		** User wants it fast rather than right.
   1303   1.91  christos 		*/
   1304   1.91  christos 		sp->leapcnt = 0;		/* so, we're off a little */
   1305   1.87  christos 		sp->timecnt = 0;
   1306   1.87  christos 		sp->typecnt = 0;
   1307   1.91  christos 		sp->charcnt = 0;
   1308   1.91  christos 		sp->goback = sp->goahead = false;
   1309   1.91  christos 		init_ttinfo(&sp->ttis[0], 0, false, 0);
   1310   1.87  christos 		strcpy(sp->chars, gmt);
   1311   1.91  christos 		sp->defaulttype = 0;
   1312   1.91  christos 		return 0;
   1313   1.91  christos 	} else {
   1314   1.91  christos 		int err = tzload(name, sp, true);
   1315   1.91  christos 		if (err != 0 && name && name[0] != ':' &&
   1316   1.91  christos 		    tzparse(name, sp, false))
   1317   1.93  christos 			err = 0;
   1318   1.93  christos 		if (err == 0)
   1319   1.93  christos 			scrub_abbrs(sp);
   1320   1.91  christos 		return err;
   1321   1.87  christos 	}
   1322   1.49  christos }
   1323   1.87  christos 
   1324   1.19    kleink static void
   1325   1.87  christos tzsetlcl(char const *name)
   1326    1.1       jtc {
   1327   1.91  christos 	struct state *sp = lclptr;
   1328   1.87  christos 	int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
   1329   1.87  christos 	if (lcl < 0 ? lcl_is_set < 0
   1330   1.87  christos 	    : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
   1331    1.1       jtc 		return;
   1332    1.1       jtc 
   1333   1.91  christos 	if (! sp)
   1334   1.91  christos 		lclptr = sp = malloc(sizeof *lclptr);
   1335   1.91  christos 	if (sp) {
   1336   1.91  christos 		if (zoneinit(sp, name) != 0)
   1337   1.91  christos 			zoneinit(sp, "");
   1338   1.91  christos 		if (0 < lcl)
   1339   1.91  christos 			strcpy(lcl_TZname, name);
   1340   1.89  christos 	}
   1341   1.45   mlelstv 	settzname();
   1342   1.87  christos 	lcl_is_set = lcl;
   1343    1.1       jtc }
   1344    1.1       jtc 
   1345   1.87  christos #ifdef STD_INSPIRED
   1346    1.1       jtc void
   1347   1.45   mlelstv tzsetwall(void)
   1348   1.19    kleink {
   1349   1.45   mlelstv 	rwlock_wrlock(&lcl_lock);
   1350   1.87  christos 	tzsetlcl(NULL);
   1351   1.45   mlelstv 	rwlock_unlock(&lcl_lock);
   1352   1.19    kleink }
   1353   1.87  christos #endif
   1354   1.87  christos 
   1355   1.87  christos static void
   1356   1.87  christos tzset_unlocked(void)
   1357   1.87  christos {
   1358   1.87  christos 	tzsetlcl(getenv("TZ"));
   1359   1.87  christos }
   1360   1.19    kleink 
   1361   1.45   mlelstv void
   1362   1.87  christos tzset(void)
   1363    1.1       jtc {
   1364   1.87  christos 	rwlock_wrlock(&lcl_lock);
   1365   1.87  christos 	tzset_unlocked();
   1366   1.87  christos 	rwlock_unlock(&lcl_lock);
   1367   1.87  christos }
   1368    1.1       jtc 
   1369   1.87  christos static void
   1370   1.87  christos gmtcheck(void)
   1371   1.87  christos {
   1372   1.87  christos 	static bool gmt_is_set;
   1373   1.87  christos 	rwlock_wrlock(&lcl_lock);
   1374   1.87  christos 	if (! gmt_is_set) {
   1375   1.87  christos 		gmtptr = malloc(sizeof *gmtptr);
   1376   1.87  christos 		if (gmtptr)
   1377   1.87  christos 			gmtload(gmtptr);
   1378   1.87  christos 		gmt_is_set = true;
   1379    1.1       jtc 	}
   1380   1.87  christos 	rwlock_unlock(&lcl_lock);
   1381   1.87  christos }
   1382    1.1       jtc 
   1383   1.87  christos #if NETBSD_INSPIRED
   1384    1.1       jtc 
   1385   1.87  christos timezone_t
   1386   1.87  christos tzalloc(const char *name)
   1387   1.87  christos {
   1388   1.87  christos 	timezone_t sp = malloc(sizeof *sp);
   1389   1.91  christos 	if (sp) {
   1390   1.91  christos 		int err = zoneinit(sp, name);
   1391   1.91  christos 		if (err != 0) {
   1392   1.91  christos 			free(sp);
   1393   1.91  christos 			errno = err;
   1394   1.91  christos 			return NULL;
   1395   1.91  christos 		}
   1396   1.91  christos 	}
   1397   1.91  christos 	return sp;
   1398    1.1       jtc }
   1399    1.1       jtc 
   1400   1.19    kleink void
   1401   1.87  christos tzfree(timezone_t sp)
   1402   1.19    kleink {
   1403   1.87  christos 	free(sp);
   1404   1.19    kleink }
   1405   1.19    kleink 
   1406    1.1       jtc /*
   1407   1.87  christos ** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
   1408   1.87  christos ** ctime_r are obsolescent and have potential security problems that
   1409   1.87  christos ** ctime_rz would share.  Callers can instead use localtime_rz + strftime.
   1410   1.87  christos **
   1411   1.87  christos ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
   1412   1.87  christos ** in zones with three or more time zone abbreviations.
   1413   1.87  christos ** Callers can instead use localtime_rz + strftime.
   1414   1.87  christos */
   1415   1.87  christos 
   1416   1.87  christos #endif
   1417   1.87  christos 
   1418   1.87  christos /*
   1419    1.1       jtc ** The easy way to behave "as if no library function calls" localtime
   1420   1.83  christos ** is to not call it, so we drop its guts into "localsub", which can be
   1421   1.83  christos ** freely called. (And no, the PANS doesn't require the above behavior,
   1422    1.1       jtc ** but it *is* desirable.)
   1423    1.1       jtc **
   1424   1.93  christos ** If successful and SETNAME is nonzero,
   1425   1.91  christos ** set the applicable parts of tzname, timezone and altzone;
   1426   1.91  christos ** however, it's OK to omit this step if the time zone is POSIX-compatible,
   1427   1.91  christos ** since in that case tzset should have already done this step correctly.
   1428   1.93  christos ** SETNAME's type is intfast32_t for compatibility with gmtsub,
   1429   1.93  christos ** but it is actually a boolean and its value should be 0 or 1.
   1430    1.1       jtc */
   1431    1.1       jtc 
   1432    1.1       jtc /*ARGSUSED*/
   1433   1.45   mlelstv static struct tm *
   1434   1.93  christos localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
   1435   1.87  christos 	 struct tm *const tmp)
   1436   1.49  christos {
   1437   1.49  christos 	const struct ttinfo *	ttisp;
   1438   1.49  christos 	int			i;
   1439   1.49  christos 	struct tm *		result;
   1440    1.1       jtc 	const time_t			t = *timep;
   1441    1.1       jtc 
   1442   1.87  christos 	if (sp == NULL) {
   1443   1.91  christos 		/* Don't bother to set tzname etc.; tzset has already done it.  */
   1444   1.91  christos 		return gmtsub(gmtptr, timep, 0, tmp);
   1445   1.87  christos 	}
   1446   1.45   mlelstv 	if ((sp->goback && t < sp->ats[0]) ||
   1447   1.45   mlelstv 		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
   1448   1.45   mlelstv 			time_t			newt = t;
   1449   1.49  christos 			time_t		seconds;
   1450   1.78  christos 			time_t		years;
   1451   1.45   mlelstv 
   1452   1.45   mlelstv 			if (t < sp->ats[0])
   1453   1.45   mlelstv 				seconds = sp->ats[0] - t;
   1454   1.45   mlelstv 			else	seconds = t - sp->ats[sp->timecnt - 1];
   1455   1.45   mlelstv 			--seconds;
   1456   1.78  christos 			years = (time_t)((seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT);
   1457   1.78  christos 			seconds = (time_t)(years * AVGSECSPERYEAR);
   1458   1.45   mlelstv 			if (t < sp->ats[0])
   1459   1.45   mlelstv 				newt += seconds;
   1460   1.45   mlelstv 			else	newt -= seconds;
   1461   1.45   mlelstv 			if (newt < sp->ats[0] ||
   1462   1.88  christos 				newt > sp->ats[sp->timecnt - 1]) {
   1463   1.88  christos 				errno = EINVAL;
   1464   1.88  christos 				return NULL;	/* "cannot happen" */
   1465   1.88  christos 			}
   1466   1.93  christos 			result = localsub(sp, &newt, setname, tmp);
   1467   1.87  christos 			if (result) {
   1468   1.87  christos 				int_fast64_t newy;
   1469   1.45   mlelstv 
   1470   1.87  christos 				newy = result->tm_year;
   1471   1.45   mlelstv 				if (t < sp->ats[0])
   1472   1.78  christos 					newy -= years;
   1473   1.78  christos 				else	newy += years;
   1474   1.88  christos 				if (! (INT_MIN <= newy && newy <= INT_MAX)) {
   1475   1.88  christos 					errno = EOVERFLOW;
   1476   1.45   mlelstv 					return NULL;
   1477   1.88  christos 				}
   1478   1.87  christos 				result->tm_year = (int)newy;
   1479   1.45   mlelstv 			}
   1480   1.45   mlelstv 			return result;
   1481    1.1       jtc 	}
   1482    1.1       jtc 	if (sp->timecnt == 0 || t < sp->ats[0]) {
   1483   1.74  christos 		i = sp->defaulttype;
   1484    1.1       jtc 	} else {
   1485   1.49  christos 		int	lo = 1;
   1486   1.49  christos 		int	hi = sp->timecnt;
   1487   1.45   mlelstv 
   1488   1.45   mlelstv 		while (lo < hi) {
   1489   1.49  christos 			int	mid = (lo + hi) / 2;
   1490   1.45   mlelstv 
   1491   1.45   mlelstv 			if (t < sp->ats[mid])
   1492   1.45   mlelstv 				hi = mid;
   1493   1.45   mlelstv 			else	lo = mid + 1;
   1494   1.45   mlelstv 		}
   1495   1.45   mlelstv 		i = (int) sp->types[lo - 1];
   1496    1.1       jtc 	}
   1497    1.1       jtc 	ttisp = &sp->ttis[i];
   1498    1.1       jtc 	/*
   1499    1.1       jtc 	** To get (wrong) behavior that's compatible with System V Release 2.0
   1500    1.1       jtc 	** you'd replace the statement below with
   1501    1.1       jtc 	**	t += ttisp->tt_gmtoff;
   1502    1.1       jtc 	**	timesub(&t, 0L, sp, tmp);
   1503    1.1       jtc 	*/
   1504   1.87  christos 	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
   1505   1.87  christos 	if (result) {
   1506   1.92  christos 		result->tm_isdst = ttisp->tt_isdst;
   1507   1.92  christos #ifdef TM_ZONE
   1508   1.93  christos 		result->TM_ZONE = __UNCONST(&sp->chars[ttisp->tt_abbrind]);
   1509   1.92  christos #endif /* defined TM_ZONE */
   1510   1.93  christos 		if (setname)
   1511   1.93  christos 			update_tzname_etc(sp, ttisp);
   1512   1.87  christos 	}
   1513   1.45   mlelstv 	return result;
   1514    1.1       jtc }
   1515    1.1       jtc 
   1516   1.87  christos #if NETBSD_INSPIRED
   1517   1.49  christos 
   1518    1.1       jtc struct tm *
   1519   1.87  christos localtime_rz(timezone_t sp, time_t const *timep, struct tm *tmp)
   1520   1.87  christos {
   1521   1.87  christos 	return localsub(sp, timep, 0, tmp);
   1522   1.87  christos }
   1523   1.87  christos 
   1524   1.87  christos #endif
   1525   1.87  christos 
   1526   1.87  christos static struct tm *
   1527   1.87  christos localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
   1528    1.1       jtc {
   1529   1.87  christos 	rwlock_wrlock(&lcl_lock);
   1530   1.87  christos 	if (setname || !lcl_is_set)
   1531   1.87  christos 		tzset_unlocked();
   1532   1.87  christos 	tmp = localsub(lclptr, timep, setname, tmp);
   1533   1.45   mlelstv 	rwlock_unlock(&lcl_lock);
   1534   1.49  christos 	return tmp;
   1535    1.1       jtc }
   1536    1.1       jtc 
   1537   1.49  christos struct tm *
   1538   1.96  christos localtime(const time_t *timep)
   1539   1.49  christos {
   1540   1.87  christos 	return localtime_tzset(timep, &tm, true);
   1541   1.49  christos }
   1542   1.35    kleink 
   1543   1.18    kleink struct tm *
   1544   1.87  christos localtime_r(const time_t * __restrict timep, struct tm *tmp)
   1545   1.18    kleink {
   1546  1.101  christos 	return localtime_tzset(timep, tmp, true);
   1547   1.18    kleink }
   1548   1.18    kleink 
   1549   1.18    kleink /*
   1550    1.1       jtc ** gmtsub is to gmtime as localsub is to localtime.
   1551    1.1       jtc */
   1552    1.1       jtc 
   1553   1.45   mlelstv static struct tm *
   1554   1.87  christos gmtsub(struct state const *sp, const time_t *timep, int_fast32_t offset,
   1555   1.87  christos        struct tm *tmp)
   1556    1.1       jtc {
   1557   1.49  christos 	struct tm *	result;
   1558   1.19    kleink 
   1559   1.87  christos 	result = timesub(timep, offset, gmtptr, tmp);
   1560    1.1       jtc #ifdef TM_ZONE
   1561    1.1       jtc 	/*
   1562    1.1       jtc 	** Could get fancy here and deliver something such as
   1563  1.104  christos 	** "+xx" or "-xx" if offset is non-zero,
   1564    1.1       jtc 	** but this is no time for a treasure hunt.
   1565    1.1       jtc 	*/
   1566   1.88  christos 	if (result)
   1567   1.88  christos 		result->TM_ZONE = offset ? __UNCONST(wildabbr) : gmtptr ?
   1568   1.88  christos 		    gmtptr->chars : __UNCONST(gmt);
   1569    1.1       jtc #endif /* defined TM_ZONE */
   1570   1.45   mlelstv 	return result;
   1571    1.1       jtc }
   1572    1.1       jtc 
   1573    1.1       jtc 
   1574   1.18    kleink /*
   1575   1.35    kleink ** Re-entrant version of gmtime.
   1576   1.35    kleink */
   1577   1.35    kleink 
   1578   1.18    kleink struct tm *
   1579   1.96  christos gmtime_r(const time_t *timep, struct tm *tmp)
   1580   1.18    kleink {
   1581   1.87  christos 	gmtcheck();
   1582   1.90  christos 	return gmtsub(NULL, timep, 0, tmp);
   1583   1.18    kleink }
   1584   1.18    kleink 
   1585   1.96  christos struct tm *
   1586   1.96  christos gmtime(const time_t *timep)
   1587   1.96  christos {
   1588   1.96  christos 	return gmtime_r(timep, &tm);
   1589   1.96  christos }
   1590    1.1       jtc #ifdef STD_INSPIRED
   1591    1.1       jtc 
   1592    1.1       jtc struct tm *
   1593   1.96  christos offtime(const time_t *timep, long offset)
   1594    1.1       jtc {
   1595   1.87  christos 	gmtcheck();
   1596   1.90  christos 	return gmtsub(gmtptr, timep, (int_fast32_t)offset, &tm);
   1597   1.49  christos }
   1598   1.49  christos 
   1599   1.49  christos struct tm *
   1600   1.49  christos offtime_r(const time_t *timep, long offset, struct tm *tmp)
   1601   1.49  christos {
   1602   1.87  christos 	gmtcheck();
   1603   1.90  christos 	return gmtsub(NULL, timep, (int_fast32_t)offset, tmp);
   1604    1.1       jtc }
   1605    1.1       jtc 
   1606    1.1       jtc #endif /* defined STD_INSPIRED */
   1607    1.1       jtc 
   1608  1.105  christos #if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
   1609  1.105  christos 
   1610  1.105  christos # ifndef USG_COMPAT
   1611  1.105  christos #  define daylight 0
   1612  1.105  christos #  define timezone 0
   1613  1.105  christos # endif
   1614  1.105  christos # ifndef ALTZONE
   1615  1.105  christos #  define altzone 0
   1616  1.105  christos # endif
   1617  1.105  christos 
   1618  1.105  christos /* Convert from the underlying system's time_t to the ersatz time_tz,
   1619  1.105  christos    which is called 'time_t' in this file.  Typically, this merely
   1620  1.105  christos    converts the time's integer width.  On some platforms, the system
   1621  1.105  christos    time is local time not UT, or uses some epoch other than the POSIX
   1622  1.105  christos    epoch.
   1623  1.105  christos 
   1624  1.105  christos    Although this code appears to define a function named 'time' that
   1625  1.105  christos    returns time_t, the macros in private.h cause this code to actually
   1626  1.105  christos    define a function named 'tz_time' that returns tz_time_t.  The call
   1627  1.105  christos    to sys_time invokes the underlying system's 'time' function.  */
   1628  1.105  christos 
   1629  1.105  christos time_t
   1630  1.105  christos time(time_t *p)
   1631  1.105  christos {
   1632  1.105  christos   time_t r = sys_time(0);
   1633  1.105  christos   if (r != (time_t) -1) {
   1634  1.105  christos     int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
   1635  1.105  christos     if (increment_overflow32(&offset, -EPOCH_OFFSET)
   1636  1.105  christos 	|| increment_overflow_time (&r, offset)) {
   1637  1.105  christos       errno = EOVERFLOW;
   1638  1.105  christos       r = -1;
   1639  1.105  christos     }
   1640  1.105  christos   }
   1641  1.105  christos   if (p)
   1642  1.105  christos     *p = r;
   1643  1.105  christos   return r;
   1644  1.105  christos }
   1645  1.105  christos #endif
   1646  1.105  christos 
   1647   1.45   mlelstv /*
   1648   1.45   mlelstv ** Return the number of leap years through the end of the given year
   1649   1.45   mlelstv ** where, to make the math easy, the answer for year zero is defined as zero.
   1650   1.45   mlelstv */
   1651   1.45   mlelstv 
   1652   1.87  christos static int ATTRIBUTE_PURE
   1653   1.49  christos leaps_thru_end_of(const int y)
   1654   1.45   mlelstv {
   1655   1.45   mlelstv 	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
   1656   1.45   mlelstv 		-(leaps_thru_end_of(-(y + 1)) + 1);
   1657   1.45   mlelstv }
   1658   1.45   mlelstv 
   1659   1.45   mlelstv static struct tm *
   1660   1.96  christos timesub(const time_t *timep, int_fast32_t offset,
   1661   1.97       riz     const struct state *sp, struct tm *tmp)
   1662   1.49  christos {
   1663   1.49  christos 	const struct lsinfo *	lp;
   1664   1.49  christos 	time_t			tdays;
   1665   1.49  christos 	int			idays;	/* unsigned would be so 2003 */
   1666   1.74  christos 	int_fast64_t		rem;
   1667   1.49  christos 	int			y;
   1668   1.49  christos 	const int *		ip;
   1669   1.74  christos 	int_fast64_t		corr;
   1670   1.87  christos 	bool			hit;
   1671   1.49  christos 	int			i;
   1672    1.1       jtc 
   1673    1.1       jtc 	corr = 0;
   1674   1.87  christos 	hit = false;
   1675    1.1       jtc 	i = (sp == NULL) ? 0 : sp->leapcnt;
   1676    1.1       jtc 	while (--i >= 0) {
   1677    1.1       jtc 		lp = &sp->lsis[i];
   1678    1.1       jtc 		if (*timep >= lp->ls_trans) {
   1679    1.1       jtc 			if (*timep == lp->ls_trans) {
   1680    1.1       jtc 				hit = ((i == 0 && lp->ls_corr > 0) ||
   1681    1.1       jtc 					lp->ls_corr > sp->lsis[i - 1].ls_corr);
   1682    1.1       jtc 				if (hit)
   1683    1.1       jtc 					while (i > 0 &&
   1684    1.1       jtc 						sp->lsis[i].ls_trans ==
   1685    1.1       jtc 						sp->lsis[i - 1].ls_trans + 1 &&
   1686    1.1       jtc 						sp->lsis[i].ls_corr ==
   1687    1.1       jtc 						sp->lsis[i - 1].ls_corr + 1) {
   1688    1.1       jtc 							++hit;
   1689    1.1       jtc 							--i;
   1690    1.1       jtc 					}
   1691    1.1       jtc 			}
   1692    1.1       jtc 			corr = lp->ls_corr;
   1693    1.1       jtc 			break;
   1694    1.1       jtc 		}
   1695    1.1       jtc 	}
   1696   1.45   mlelstv 	y = EPOCH_YEAR;
   1697   1.66  christos 	tdays = (time_t)(*timep / SECSPERDAY);
   1698   1.96  christos 	rem = *timep % SECSPERDAY;
   1699   1.45   mlelstv 	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
   1700   1.45   mlelstv 		int		newy;
   1701   1.49  christos 		time_t	tdelta;
   1702   1.49  christos 		int	idelta;
   1703   1.49  christos 		int	leapdays;
   1704   1.45   mlelstv 
   1705   1.45   mlelstv 		tdelta = tdays / DAYSPERLYEAR;
   1706   1.78  christos 		if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
   1707   1.78  christos 		       && tdelta <= INT_MAX))
   1708   1.91  christos 			goto out_of_range;
   1709   1.81  christos 		_DIAGASSERT(__type_fit(int, tdelta));
   1710   1.81  christos 		idelta = (int)tdelta;
   1711   1.45   mlelstv 		if (idelta == 0)
   1712   1.45   mlelstv 			idelta = (tdays < 0) ? -1 : 1;
   1713   1.45   mlelstv 		newy = y;
   1714   1.51  christos 		if (increment_overflow(&newy, idelta))
   1715   1.91  christos 			goto out_of_range;
   1716   1.45   mlelstv 		leapdays = leaps_thru_end_of(newy - 1) -
   1717   1.45   mlelstv 			leaps_thru_end_of(y - 1);
   1718   1.45   mlelstv 		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
   1719   1.45   mlelstv 		tdays -= leapdays;
   1720   1.45   mlelstv 		y = newy;
   1721   1.45   mlelstv 	}
   1722   1.45   mlelstv 	/*
   1723   1.45   mlelstv 	** Given the range, we can now fearlessly cast...
   1724   1.45   mlelstv 	*/
   1725   1.45   mlelstv 	idays = (int) tdays;
   1726   1.45   mlelstv 	rem += offset - corr;
   1727    1.1       jtc 	while (rem < 0) {
   1728    1.1       jtc 		rem += SECSPERDAY;
   1729   1.45   mlelstv 		--idays;
   1730    1.1       jtc 	}
   1731    1.1       jtc 	while (rem >= SECSPERDAY) {
   1732    1.1       jtc 		rem -= SECSPERDAY;
   1733   1.45   mlelstv 		++idays;
   1734   1.45   mlelstv 	}
   1735   1.45   mlelstv 	while (idays < 0) {
   1736   1.51  christos 		if (increment_overflow(&y, -1))
   1737   1.91  christos 			goto out_of_range;
   1738   1.45   mlelstv 		idays += year_lengths[isleap(y)];
   1739    1.1       jtc 	}
   1740   1.45   mlelstv 	while (idays >= year_lengths[isleap(y)]) {
   1741   1.45   mlelstv 		idays -= year_lengths[isleap(y)];
   1742   1.51  christos 		if (increment_overflow(&y, 1))
   1743   1.91  christos 			goto out_of_range;
   1744   1.45   mlelstv 	}
   1745   1.45   mlelstv 	tmp->tm_year = y;
   1746   1.51  christos 	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
   1747   1.91  christos 		goto out_of_range;
   1748   1.45   mlelstv 	tmp->tm_yday = idays;
   1749   1.45   mlelstv 	/*
   1750   1.45   mlelstv 	** The "extra" mods below avoid overflow problems.
   1751   1.45   mlelstv 	*/
   1752   1.45   mlelstv 	tmp->tm_wday = EPOCH_WDAY +
   1753   1.45   mlelstv 		((y - EPOCH_YEAR) % DAYSPERWEEK) *
   1754   1.45   mlelstv 		(DAYSPERNYEAR % DAYSPERWEEK) +
   1755   1.45   mlelstv 		leaps_thru_end_of(y - 1) -
   1756   1.45   mlelstv 		leaps_thru_end_of(EPOCH_YEAR - 1) +
   1757   1.45   mlelstv 		idays;
   1758   1.45   mlelstv 	tmp->tm_wday %= DAYSPERWEEK;
   1759   1.45   mlelstv 	if (tmp->tm_wday < 0)
   1760   1.45   mlelstv 		tmp->tm_wday += DAYSPERWEEK;
   1761    1.1       jtc 	tmp->tm_hour = (int) (rem / SECSPERHOUR);
   1762   1.45   mlelstv 	rem %= SECSPERHOUR;
   1763    1.1       jtc 	tmp->tm_min = (int) (rem / SECSPERMIN);
   1764    1.6       jtc 	/*
   1765    1.6       jtc 	** A positive leap second requires a special
   1766   1.45   mlelstv 	** representation. This uses "... ??:59:60" et seq.
   1767    1.6       jtc 	*/
   1768    1.6       jtc 	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
   1769   1.45   mlelstv 	ip = mon_lengths[isleap(y)];
   1770   1.45   mlelstv 	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
   1771   1.45   mlelstv 		idays -= ip[tmp->tm_mon];
   1772   1.45   mlelstv 	tmp->tm_mday = (int) (idays + 1);
   1773    1.1       jtc 	tmp->tm_isdst = 0;
   1774    1.1       jtc #ifdef TM_GMTOFF
   1775    1.1       jtc 	tmp->TM_GMTOFF = offset;
   1776    1.1       jtc #endif /* defined TM_GMTOFF */
   1777   1.45   mlelstv 	return tmp;
   1778   1.91  christos out_of_range:
   1779   1.88  christos 	errno = EOVERFLOW;
   1780   1.88  christos 	return NULL;
   1781    1.1       jtc }
   1782    1.1       jtc 
   1783    1.1       jtc char *
   1784   1.96  christos ctime(const time_t *timep)
   1785    1.1       jtc {
   1786    1.1       jtc /*
   1787    1.1       jtc ** Section 4.12.3.2 of X3.159-1989 requires that
   1788   1.18    kleink **	The ctime function converts the calendar time pointed to by timer
   1789   1.45   mlelstv **	to local time in the form of a string. It is equivalent to
   1790    1.1       jtc **		asctime(localtime(timer))
   1791    1.1       jtc */
   1792   1.91  christos 	struct tm *tmp = localtime(timep);
   1793   1.91  christos 	return tmp ? asctime(tmp) : NULL;
   1794   1.18    kleink }
   1795   1.18    kleink 
   1796   1.18    kleink char *
   1797   1.96  christos ctime_r(const time_t *timep, char *buf)
   1798   1.18    kleink {
   1799   1.91  christos 	struct tm mytm;
   1800   1.91  christos 	struct tm *tmp = localtime_r(timep, &mytm);
   1801   1.91  christos 	return tmp ? asctime_r(tmp, buf) : NULL;
   1802    1.1       jtc }
   1803    1.1       jtc 
   1804   1.49  christos char *
   1805   1.49  christos ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
   1806   1.49  christos {
   1807   1.49  christos 	struct tm	mytm, *rtm;
   1808   1.49  christos 
   1809   1.49  christos 	rtm = localtime_rz(sp, timep, &mytm);
   1810   1.49  christos 	if (rtm == NULL)
   1811   1.49  christos 		return NULL;
   1812   1.49  christos 	return asctime_r(rtm, buf);
   1813   1.49  christos }
   1814   1.49  christos 
   1815    1.1       jtc /*
   1816    1.1       jtc ** Adapted from code provided by Robert Elz, who writes:
   1817    1.1       jtc **	The "best" way to do mktime I think is based on an idea of Bob
   1818    1.7       jtc **	Kridle's (so its said...) from a long time ago.
   1819   1.45   mlelstv **	It does a binary search of the time_t space. Since time_t's are
   1820    1.1       jtc **	just 32 bits, its a max of 32 iterations (even at 64 bits it
   1821    1.1       jtc **	would still be very reasonable).
   1822    1.1       jtc */
   1823    1.1       jtc 
   1824    1.1       jtc #ifndef WRONG
   1825   1.51  christos #define WRONG	((time_t)-1)
   1826    1.1       jtc #endif /* !defined WRONG */
   1827    1.1       jtc 
   1828    1.1       jtc /*
   1829   1.87  christos ** Normalize logic courtesy Paul Eggert.
   1830    1.1       jtc */
   1831    1.1       jtc 
   1832   1.87  christos static bool
   1833   1.96  christos increment_overflow(int *ip, int j)
   1834    1.1       jtc {
   1835   1.87  christos 	int const	i = *ip;
   1836    1.1       jtc 
   1837   1.58  christos 	/*
   1838   1.58  christos 	** If i >= 0 there can only be overflow if i + j > INT_MAX
   1839   1.58  christos 	** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
   1840   1.58  christos 	** If i < 0 there can only be overflow if i + j < INT_MIN
   1841   1.58  christos 	** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
   1842   1.58  christos 	*/
   1843   1.58  christos 	if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
   1844   1.87  christos 		return true;
   1845   1.58  christos 	*ip += j;
   1846   1.87  christos 	return false;
   1847    1.1       jtc }
   1848    1.1       jtc 
   1849   1.87  christos static bool
   1850   1.74  christos increment_overflow32(int_fast32_t *const lp, int const m)
   1851   1.45   mlelstv {
   1852   1.87  christos 	int_fast32_t const l = *lp;
   1853   1.45   mlelstv 
   1854   1.74  christos 	if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
   1855   1.87  christos 		return true;
   1856   1.58  christos 	*lp += m;
   1857   1.87  christos 	return false;
   1858   1.45   mlelstv }
   1859   1.45   mlelstv 
   1860   1.87  christos static bool
   1861   1.81  christos increment_overflow_time(time_t *tp, int_fast32_t j)
   1862   1.81  christos {
   1863   1.81  christos 	/*
   1864   1.81  christos 	** This is like
   1865   1.81  christos 	** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
   1866   1.81  christos 	** except that it does the right thing even if *tp + j would overflow.
   1867   1.81  christos 	*/
   1868   1.81  christos 	if (! (j < 0
   1869   1.81  christos 	       ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
   1870   1.81  christos 	       : *tp <= time_t_max - j))
   1871   1.87  christos 		return true;
   1872   1.81  christos 	*tp += j;
   1873   1.87  christos 	return false;
   1874   1.81  christos }
   1875   1.81  christos 
   1876   1.87  christos static bool
   1877   1.49  christos normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
   1878    1.1       jtc {
   1879   1.49  christos 	int	tensdelta;
   1880    1.1       jtc 
   1881    1.1       jtc 	tensdelta = (*unitsptr >= 0) ?
   1882    1.1       jtc 		(*unitsptr / base) :
   1883    1.1       jtc 		(-1 - (-1 - *unitsptr) / base);
   1884    1.1       jtc 	*unitsptr -= tensdelta * base;
   1885    1.1       jtc 	return increment_overflow(tensptr, tensdelta);
   1886    1.1       jtc }
   1887    1.1       jtc 
   1888   1.87  christos static bool
   1889   1.96  christos normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
   1890   1.45   mlelstv {
   1891   1.49  christos 	int	tensdelta;
   1892   1.45   mlelstv 
   1893   1.45   mlelstv 	tensdelta = (*unitsptr >= 0) ?
   1894   1.45   mlelstv 		(*unitsptr / base) :
   1895   1.45   mlelstv 		(-1 - (-1 - *unitsptr) / base);
   1896   1.45   mlelstv 	*unitsptr -= tensdelta * base;
   1897   1.74  christos 	return increment_overflow32(tensptr, tensdelta);
   1898   1.45   mlelstv }
   1899   1.45   mlelstv 
   1900   1.45   mlelstv static int
   1901   1.87  christos tmcomp(const struct tm *const atmp,
   1902   1.87  christos        const struct tm *const btmp)
   1903    1.1       jtc {
   1904   1.49  christos 	int	result;
   1905    1.1       jtc 
   1906   1.78  christos 	if (atmp->tm_year != btmp->tm_year)
   1907   1.78  christos 		return atmp->tm_year < btmp->tm_year ? -1 : 1;
   1908   1.78  christos 	if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
   1909    1.1       jtc 		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
   1910    1.1       jtc 		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
   1911    1.1       jtc 		(result = (atmp->tm_min - btmp->tm_min)) == 0)
   1912    1.1       jtc 			result = atmp->tm_sec - btmp->tm_sec;
   1913    1.1       jtc 	return result;
   1914    1.1       jtc }
   1915    1.1       jtc 
   1916    1.1       jtc static time_t
   1917   1.87  christos time2sub(struct tm *const tmp,
   1918   1.87  christos 	 struct tm *(*funcp)(struct state const *, time_t const *,
   1919   1.87  christos 			     int_fast32_t, struct tm *),
   1920   1.87  christos 	 struct state const *sp,
   1921   1.87  christos  	 const int_fast32_t offset,
   1922   1.87  christos 	 bool *okayp,
   1923   1.87  christos 	 bool do_norm_secs)
   1924   1.49  christos {
   1925   1.49  christos 	int			dir;
   1926   1.49  christos 	int			i, j;
   1927   1.49  christos 	int			saved_seconds;
   1928   1.74  christos 	int_fast32_t		li;
   1929   1.49  christos 	time_t			lo;
   1930   1.49  christos 	time_t			hi;
   1931   1.61  christos #ifdef NO_ERROR_IN_DST_GAP
   1932   1.61  christos 	time_t			ilo;
   1933   1.61  christos #endif
   1934   1.74  christos 	int_fast32_t		y;
   1935   1.74  christos 	time_t			newt;
   1936   1.74  christos 	time_t			t;
   1937   1.74  christos 	struct tm		yourtm, mytm;
   1938    1.1       jtc 
   1939   1.87  christos 	*okayp = false;
   1940    1.1       jtc 	yourtm = *tmp;
   1941   1.64  christos #ifdef NO_ERROR_IN_DST_GAP
   1942   1.64  christos again:
   1943   1.64  christos #endif
   1944   1.13       jtc 	if (do_norm_secs) {
   1945   1.13       jtc 		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
   1946   1.60  christos 		    SECSPERMIN))
   1947   1.91  christos 			goto out_of_range;
   1948   1.13       jtc 	}
   1949    1.1       jtc 	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
   1950   1.91  christos 		goto out_of_range;
   1951    1.1       jtc 	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
   1952   1.91  christos 		goto out_of_range;
   1953   1.45   mlelstv 	y = yourtm.tm_year;
   1954   1.74  christos 	if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
   1955   1.91  christos 		goto out_of_range;
   1956    1.1       jtc 	/*
   1957   1.45   mlelstv 	** Turn y into an actual year number for now.
   1958    1.1       jtc 	** It is converted back to an offset from TM_YEAR_BASE later.
   1959    1.1       jtc 	*/
   1960   1.74  christos 	if (increment_overflow32(&y, TM_YEAR_BASE))
   1961   1.91  christos 		goto out_of_range;
   1962    1.1       jtc 	while (yourtm.tm_mday <= 0) {
   1963   1.74  christos 		if (increment_overflow32(&y, -1))
   1964   1.91  christos 			goto out_of_range;
   1965   1.45   mlelstv 		li = y + (1 < yourtm.tm_mon);
   1966   1.45   mlelstv 		yourtm.tm_mday += year_lengths[isleap(li)];
   1967    1.1       jtc 	}
   1968    1.1       jtc 	while (yourtm.tm_mday > DAYSPERLYEAR) {
   1969   1.45   mlelstv 		li = y + (1 < yourtm.tm_mon);
   1970   1.45   mlelstv 		yourtm.tm_mday -= year_lengths[isleap(li)];
   1971   1.74  christos 		if (increment_overflow32(&y, 1))
   1972   1.91  christos 			goto out_of_range;
   1973    1.1       jtc 	}
   1974    1.1       jtc 	for ( ; ; ) {
   1975   1.45   mlelstv 		i = mon_lengths[isleap(y)][yourtm.tm_mon];
   1976    1.1       jtc 		if (yourtm.tm_mday <= i)
   1977    1.1       jtc 			break;
   1978    1.1       jtc 		yourtm.tm_mday -= i;
   1979    1.1       jtc 		if (++yourtm.tm_mon >= MONSPERYEAR) {
   1980    1.1       jtc 			yourtm.tm_mon = 0;
   1981   1.74  christos 			if (increment_overflow32(&y, 1))
   1982   1.91  christos 				goto out_of_range;
   1983    1.1       jtc 		}
   1984    1.1       jtc 	}
   1985   1.74  christos 	if (increment_overflow32(&y, -TM_YEAR_BASE))
   1986   1.91  christos 		goto out_of_range;
   1987   1.87  christos 	if (! (INT_MIN <= y && y <= INT_MAX))
   1988   1.91  christos 		goto out_of_range;
   1989   1.66  christos 	yourtm.tm_year = (int)y;
   1990   1.29    kleink 	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
   1991   1.29    kleink 		saved_seconds = 0;
   1992   1.45   mlelstv 	else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
   1993    1.1       jtc 		/*
   1994    1.1       jtc 		** We can't set tm_sec to 0, because that might push the
   1995    1.1       jtc 		** time below the minimum representable time.
   1996    1.1       jtc 		** Set tm_sec to 59 instead.
   1997    1.1       jtc 		** This assumes that the minimum representable time is
   1998    1.1       jtc 		** not in the same minute that a leap second was deleted from,
   1999    1.1       jtc 		** which is a safer assumption than using 58 would be.
   2000    1.1       jtc 		*/
   2001    1.1       jtc 		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
   2002   1.91  christos 			goto out_of_range;
   2003    1.1       jtc 		saved_seconds = yourtm.tm_sec;
   2004    1.1       jtc 		yourtm.tm_sec = SECSPERMIN - 1;
   2005    1.1       jtc 	} else {
   2006    1.1       jtc 		saved_seconds = yourtm.tm_sec;
   2007    1.1       jtc 		yourtm.tm_sec = 0;
   2008    1.1       jtc 	}
   2009    1.1       jtc 	/*
   2010   1.45   mlelstv 	** Do a binary search (this works whatever time_t's type is).
   2011    1.1       jtc 	*/
   2012   1.94  christos 	lo = time_t_min;
   2013   1.94  christos 	hi = time_t_max;
   2014   1.61  christos #ifdef NO_ERROR_IN_DST_GAP
   2015   1.61  christos 	ilo = lo;
   2016   1.61  christos #endif
   2017    1.1       jtc 	for ( ; ; ) {
   2018   1.45   mlelstv 		t = lo / 2 + hi / 2;
   2019   1.45   mlelstv 		if (t < lo)
   2020   1.45   mlelstv 			t = lo;
   2021   1.45   mlelstv 		else if (t > hi)
   2022   1.45   mlelstv 			t = hi;
   2023   1.87  christos 		if (! funcp(sp, &t, offset, &mytm)) {
   2024   1.45   mlelstv 			/*
   2025   1.45   mlelstv 			** Assume that t is too extreme to be represented in
   2026   1.45   mlelstv 			** a struct tm; arrange things so that it is less
   2027   1.45   mlelstv 			** extreme on the next pass.
   2028   1.45   mlelstv 			*/
   2029   1.45   mlelstv 			dir = (t > 0) ? 1 : -1;
   2030   1.45   mlelstv 		} else	dir = tmcomp(&mytm, &yourtm);
   2031    1.1       jtc 		if (dir != 0) {
   2032   1.45   mlelstv 			if (t == lo) {
   2033   1.78  christos 				if (t == time_t_max)
   2034   1.91  christos 					goto out_of_range;
   2035   1.45   mlelstv 				++t;
   2036   1.45   mlelstv 				++lo;
   2037   1.45   mlelstv 			} else if (t == hi) {
   2038   1.78  christos 				if (t == time_t_min)
   2039   1.91  christos 					goto out_of_range;
   2040   1.45   mlelstv 				--t;
   2041   1.45   mlelstv 				--hi;
   2042   1.45   mlelstv 			}
   2043   1.59  christos #ifdef NO_ERROR_IN_DST_GAP
   2044   1.64  christos 			if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0 &&
   2045   1.64  christos 			    do_norm_secs) {
   2046   1.59  christos 				for (i = sp->typecnt - 1; i >= 0; --i) {
   2047   1.59  christos 					for (j = sp->typecnt - 1; j >= 0; --j) {
   2048   1.64  christos 						time_t off;
   2049   1.59  christos 						if (sp->ttis[j].tt_isdst ==
   2050   1.59  christos 						    sp->ttis[i].tt_isdst)
   2051   1.59  christos 							continue;
   2052   1.59  christos 						off = sp->ttis[j].tt_gmtoff -
   2053   1.59  christos 						    sp->ttis[i].tt_gmtoff;
   2054   1.64  christos 						yourtm.tm_sec += off < 0 ?
   2055   1.64  christos 						    -off : off;
   2056   1.64  christos 						goto again;
   2057   1.59  christos 					}
   2058   1.59  christos 				}
   2059   1.59  christos 			}
   2060   1.59  christos #endif
   2061   1.45   mlelstv 			if (lo > hi)
   2062   1.60  christos 				goto invalid;
   2063   1.45   mlelstv 			if (dir > 0)
   2064   1.45   mlelstv 				hi = t;
   2065   1.45   mlelstv 			else	lo = t;
   2066    1.1       jtc 			continue;
   2067    1.1       jtc 		}
   2068   1.87  christos #if defined TM_GMTOFF && ! UNINIT_TRAP
   2069   1.87  christos 		if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
   2070   1.87  christos 		    && (yourtm.TM_GMTOFF < 0
   2071   1.87  christos 			? (-SECSPERDAY <= yourtm.TM_GMTOFF
   2072   1.87  christos 			   && (mytm.TM_GMTOFF <=
   2073   1.87  christos 			       (/*CONSTCOND*/SMALLEST (INT_FAST32_MAX, LONG_MAX)
   2074   1.87  christos 				+ yourtm.TM_GMTOFF)))
   2075   1.87  christos 			: (yourtm.TM_GMTOFF <= SECSPERDAY
   2076   1.87  christos 			   && ((/*CONSTCOND*/BIGGEST (INT_FAST32_MIN, LONG_MIN)
   2077   1.87  christos 				+ yourtm.TM_GMTOFF)
   2078   1.87  christos 			       <= mytm.TM_GMTOFF)))) {
   2079   1.87  christos 		  /* MYTM matches YOURTM except with the wrong UTC offset.
   2080   1.87  christos 		     YOURTM.TM_GMTOFF is plausible, so try it instead.
   2081   1.87  christos 		     It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
   2082   1.87  christos 		     since the guess gets checked.  */
   2083   1.87  christos 		  time_t altt = t;
   2084   1.87  christos 		  int_fast32_t diff = (int_fast32_t)
   2085   1.87  christos 		      (mytm.TM_GMTOFF - yourtm.TM_GMTOFF);
   2086   1.87  christos 		  if (!increment_overflow_time(&altt, diff)) {
   2087   1.87  christos 		    struct tm alttm;
   2088   1.87  christos 		    if (! funcp(sp, &altt, offset, &alttm)
   2089   1.87  christos 			&& alttm.tm_isdst == mytm.tm_isdst
   2090   1.87  christos 			&& alttm.TM_GMTOFF == yourtm.TM_GMTOFF
   2091   1.87  christos 			&& tmcomp(&alttm, &yourtm)) {
   2092   1.87  christos 		      t = altt;
   2093   1.87  christos 		      mytm = alttm;
   2094   1.87  christos 		    }
   2095   1.87  christos 		  }
   2096   1.87  christos 		}
   2097   1.87  christos #endif
   2098    1.1       jtc 		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
   2099    1.1       jtc 			break;
   2100    1.1       jtc 		/*
   2101    1.1       jtc 		** Right time, wrong type.
   2102    1.1       jtc 		** Hunt for right time, right type.
   2103    1.1       jtc 		** It's okay to guess wrong since the guess
   2104    1.1       jtc 		** gets checked.
   2105    1.1       jtc 		*/
   2106    1.1       jtc 		if (sp == NULL)
   2107   1.60  christos 			goto invalid;
   2108    1.5       jtc 		for (i = sp->typecnt - 1; i >= 0; --i) {
   2109    1.1       jtc 			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
   2110    1.1       jtc 				continue;
   2111    1.5       jtc 			for (j = sp->typecnt - 1; j >= 0; --j) {
   2112    1.1       jtc 				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
   2113    1.1       jtc 					continue;
   2114   1.66  christos 				newt = (time_t)(t + sp->ttis[j].tt_gmtoff -
   2115   1.66  christos 				    sp->ttis[i].tt_gmtoff);
   2116   1.87  christos 				if (! funcp(sp, &newt, offset, &mytm))
   2117   1.45   mlelstv 					continue;
   2118    1.1       jtc 				if (tmcomp(&mytm, &yourtm) != 0)
   2119    1.1       jtc 					continue;
   2120    1.1       jtc 				if (mytm.tm_isdst != yourtm.tm_isdst)
   2121    1.1       jtc 					continue;
   2122    1.1       jtc 				/*
   2123    1.1       jtc 				** We have a match.
   2124    1.1       jtc 				*/
   2125    1.1       jtc 				t = newt;
   2126    1.1       jtc 				goto label;
   2127    1.1       jtc 			}
   2128    1.1       jtc 		}
   2129   1.60  christos 		goto invalid;
   2130    1.1       jtc 	}
   2131    1.1       jtc label:
   2132    1.1       jtc 	newt = t + saved_seconds;
   2133    1.1       jtc 	if ((newt < t) != (saved_seconds < 0))
   2134   1.91  christos 		goto out_of_range;
   2135    1.1       jtc 	t = newt;
   2136   1.87  christos 	if (funcp(sp, &t, offset, tmp)) {
   2137   1.87  christos 		*okayp = true;
   2138   1.51  christos 		return t;
   2139   1.60  christos 	}
   2140   1.91  christos out_of_range:
   2141   1.60  christos 	errno = EOVERFLOW;
   2142   1.60  christos 	return WRONG;
   2143   1.60  christos invalid:
   2144   1.60  christos 	errno = EINVAL;
   2145   1.60  christos 	return WRONG;
   2146   1.13       jtc }
   2147   1.13       jtc 
   2148   1.13       jtc static time_t
   2149   1.87  christos time2(struct tm * const	tmp,
   2150   1.87  christos       struct tm *(*funcp)(struct state const *, time_t const *,
   2151   1.87  christos 			  int_fast32_t, struct tm *),
   2152   1.87  christos       struct state const *sp,
   2153   1.87  christos       const int_fast32_t offset,
   2154   1.87  christos       bool *okayp)
   2155   1.13       jtc {
   2156   1.13       jtc 	time_t	t;
   2157   1.13       jtc 
   2158   1.13       jtc 	/*
   2159   1.13       jtc 	** First try without normalization of seconds
   2160   1.13       jtc 	** (in case tm_sec contains a value associated with a leap second).
   2161   1.13       jtc 	** If that fails, try with normalization of seconds.
   2162   1.13       jtc 	*/
   2163   1.87  christos 	t = time2sub(tmp, funcp, sp, offset, okayp, false);
   2164   1.87  christos 	return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
   2165    1.1       jtc }
   2166    1.1       jtc 
   2167    1.1       jtc static time_t
   2168   1.87  christos time1(struct tm *const tmp,
   2169   1.87  christos       struct tm *(*funcp) (struct state const *, time_t const *,
   2170   1.87  christos 			   int_fast32_t, struct tm *),
   2171   1.87  christos       struct state const *sp,
   2172   1.87  christos       const int_fast32_t offset)
   2173   1.49  christos {
   2174   1.49  christos 	time_t			t;
   2175   1.49  christos 	int			samei, otheri;
   2176   1.49  christos 	int			sameind, otherind;
   2177   1.49  christos 	int			i;
   2178   1.49  christos 	int			nseen;
   2179   1.90  christos 	int			save_errno;
   2180   1.83  christos 	char				seen[TZ_MAX_TYPES];
   2181   1.83  christos 	unsigned char			types[TZ_MAX_TYPES];
   2182   1.87  christos 	bool				okay;
   2183    1.1       jtc 
   2184   1.58  christos 	if (tmp == NULL) {
   2185   1.58  christos 		errno = EINVAL;
   2186   1.58  christos 		return WRONG;
   2187   1.58  christos 	}
   2188    1.1       jtc 	if (tmp->tm_isdst > 1)
   2189    1.1       jtc 		tmp->tm_isdst = 1;
   2190   1.90  christos 	save_errno = errno;
   2191   1.87  christos 	t = time2(tmp, funcp, sp, offset, &okay);
   2192   1.90  christos 	if (okay) {
   2193   1.90  christos 		errno = save_errno;
   2194    1.1       jtc 		return t;
   2195   1.90  christos 	}
   2196    1.1       jtc 	if (tmp->tm_isdst < 0)
   2197   1.82  christos #ifdef PCTS
   2198   1.82  christos 		/*
   2199   1.82  christos 		** POSIX Conformance Test Suite code courtesy Grant Sullivan.
   2200   1.82  christos 		*/
   2201    1.1       jtc 		tmp->tm_isdst = 0;	/* reset to std and try again */
   2202   1.82  christos #else
   2203    1.1       jtc 		return t;
   2204    1.1       jtc #endif /* !defined PCTS */
   2205    1.1       jtc 	/*
   2206    1.1       jtc 	** We're supposed to assume that somebody took a time of one type
   2207    1.1       jtc 	** and did some math on it that yielded a "struct tm" that's bad.
   2208    1.1       jtc 	** We try to divine the type they started from and adjust to the
   2209    1.1       jtc 	** type they need.
   2210    1.1       jtc 	*/
   2211   1.60  christos 	if (sp == NULL) {
   2212   1.60  christos 		errno = EINVAL;
   2213    1.1       jtc 		return WRONG;
   2214   1.60  christos 	}
   2215   1.35    kleink 	for (i = 0; i < sp->typecnt; ++i)
   2216   1.87  christos 		seen[i] = false;
   2217   1.35    kleink 	nseen = 0;
   2218   1.35    kleink 	for (i = sp->timecnt - 1; i >= 0; --i)
   2219   1.35    kleink 		if (!seen[sp->types[i]]) {
   2220   1.87  christos 			seen[sp->types[i]] = true;
   2221   1.35    kleink 			types[nseen++] = sp->types[i];
   2222   1.35    kleink 		}
   2223   1.35    kleink 	for (sameind = 0; sameind < nseen; ++sameind) {
   2224   1.35    kleink 		samei = types[sameind];
   2225    1.1       jtc 		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
   2226    1.1       jtc 			continue;
   2227   1.35    kleink 		for (otherind = 0; otherind < nseen; ++otherind) {
   2228   1.35    kleink 			otheri = types[otherind];
   2229    1.1       jtc 			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
   2230    1.1       jtc 				continue;
   2231   1.21  christos 			tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
   2232   1.21  christos 					sp->ttis[samei].tt_gmtoff);
   2233    1.1       jtc 			tmp->tm_isdst = !tmp->tm_isdst;
   2234   1.87  christos 			t = time2(tmp, funcp, sp, offset, &okay);
   2235   1.90  christos 			if (okay) {
   2236   1.90  christos 				errno = save_errno;
   2237    1.1       jtc 				return t;
   2238   1.90  christos 			}
   2239   1.21  christos 			tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
   2240   1.21  christos 					sp->ttis[samei].tt_gmtoff);
   2241    1.1       jtc 			tmp->tm_isdst = !tmp->tm_isdst;
   2242    1.1       jtc 		}
   2243    1.1       jtc 	}
   2244   1.60  christos 	errno = EOVERFLOW;
   2245    1.1       jtc 	return WRONG;
   2246    1.1       jtc }
   2247    1.1       jtc 
   2248   1.87  christos static time_t
   2249   1.87  christos mktime_tzname(timezone_t sp, struct tm *tmp, bool setname)
   2250   1.87  christos {
   2251   1.87  christos 	if (sp)
   2252   1.87  christos 		return time1(tmp, localsub, sp, setname);
   2253   1.87  christos 	else {
   2254   1.87  christos 		gmtcheck();
   2255   1.87  christos 		return time1(tmp, gmtsub, gmtptr, 0);
   2256   1.87  christos 	}
   2257   1.87  christos }
   2258   1.87  christos 
   2259   1.87  christos #if NETBSD_INSPIRED
   2260   1.87  christos 
   2261    1.1       jtc time_t
   2262   1.87  christos mktime_z(timezone_t sp, struct tm *const tmp)
   2263   1.49  christos {
   2264   1.87  christos 	return mktime_tzname(sp, tmp, false);
   2265   1.49  christos }
   2266   1.49  christos 
   2267   1.87  christos #endif
   2268   1.87  christos 
   2269   1.49  christos time_t
   2270   1.96  christos mktime(struct tm *tmp)
   2271    1.1       jtc {
   2272   1.87  christos 	time_t t;
   2273   1.19    kleink 
   2274   1.45   mlelstv 	rwlock_wrlock(&lcl_lock);
   2275   1.45   mlelstv 	tzset_unlocked();
   2276   1.87  christos 	t = mktime_tzname(lclptr, tmp, true);
   2277   1.45   mlelstv 	rwlock_unlock(&lcl_lock);
   2278   1.87  christos 	return t;
   2279    1.1       jtc }
   2280    1.1       jtc 
   2281    1.1       jtc #ifdef STD_INSPIRED
   2282    1.1       jtc 
   2283    1.1       jtc time_t
   2284   1.68  christos timelocal_z(const timezone_t sp, struct tm *const tmp)
   2285   1.49  christos {
   2286   1.49  christos 	if (tmp != NULL)
   2287   1.49  christos 		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
   2288   1.49  christos 	return mktime_z(sp, tmp);
   2289   1.49  christos }
   2290   1.49  christos 
   2291   1.49  christos time_t
   2292   1.96  christos timelocal(struct tm *tmp)
   2293    1.1       jtc {
   2294   1.58  christos 	if (tmp != NULL)
   2295   1.58  christos 		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
   2296    1.1       jtc 	return mktime(tmp);
   2297    1.1       jtc }
   2298    1.1       jtc 
   2299    1.1       jtc time_t
   2300   1.96  christos timegm(struct tm *tmp)
   2301    1.1       jtc {
   2302   1.51  christos 
   2303   1.87  christos 	return timeoff(tmp, 0);
   2304    1.1       jtc }
   2305    1.1       jtc 
   2306    1.1       jtc time_t
   2307   1.96  christos timeoff(struct tm *tmp, long offset)
   2308    1.1       jtc {
   2309   1.87  christos 	if (tmp)
   2310   1.58  christos 		tmp->tm_isdst = 0;
   2311   1.87  christos 	gmtcheck();
   2312   1.87  christos 	return time1(tmp, gmtsub, gmtptr, (int_fast32_t)offset);
   2313    1.1       jtc }
   2314    1.1       jtc 
   2315    1.1       jtc #endif /* defined STD_INSPIRED */
   2316    1.1       jtc 
   2317    1.1       jtc /*
   2318    1.1       jtc ** XXX--is the below the right way to conditionalize??
   2319    1.1       jtc */
   2320    1.1       jtc 
   2321    1.1       jtc #ifdef STD_INSPIRED
   2322    1.1       jtc 
   2323    1.1       jtc /*
   2324    1.1       jtc ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
   2325   1.14       jtc ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
   2326    1.1       jtc ** is not the case if we are accounting for leap seconds.
   2327    1.1       jtc ** So, we provide the following conversion routines for use
   2328    1.1       jtc ** when exchanging timestamps with POSIX conforming systems.
   2329    1.1       jtc */
   2330    1.1       jtc 
   2331   1.74  christos static int_fast64_t
   2332   1.87  christos leapcorr(const timezone_t sp, time_t t)
   2333    1.1       jtc {
   2334   1.87  christos 	struct lsinfo const * lp;
   2335   1.49  christos 	int		i;
   2336    1.1       jtc 
   2337    1.1       jtc 	i = sp->leapcnt;
   2338    1.1       jtc 	while (--i >= 0) {
   2339    1.1       jtc 		lp = &sp->lsis[i];
   2340   1.87  christos 		if (t >= lp->ls_trans)
   2341    1.1       jtc 			return lp->ls_corr;
   2342    1.1       jtc 	}
   2343    1.1       jtc 	return 0;
   2344    1.1       jtc }
   2345    1.1       jtc 
   2346   1.87  christos NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
   2347   1.87  christos time2posix_z(timezone_t sp, time_t t)
   2348   1.49  christos {
   2349   1.87  christos 	return (time_t)(t - leapcorr(sp, t));
   2350   1.49  christos }
   2351   1.49  christos 
   2352   1.49  christos time_t
   2353   1.49  christos time2posix(time_t t)
   2354    1.1       jtc {
   2355   1.45   mlelstv 	rwlock_wrlock(&lcl_lock);
   2356   1.87  christos 	if (!lcl_is_set)
   2357   1.87  christos 		tzset_unlocked();
   2358   1.87  christos 	if (lclptr)
   2359   1.87  christos 		t = (time_t)(t - leapcorr(lclptr, t));
   2360   1.45   mlelstv 	rwlock_unlock(&lcl_lock);
   2361   1.87  christos 	return t;
   2362    1.1       jtc }
   2363    1.1       jtc 
   2364   1.87  christos NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
   2365   1.87  christos posix2time_z(timezone_t sp, time_t t)
   2366    1.1       jtc {
   2367    1.1       jtc 	time_t	x;
   2368    1.1       jtc 	time_t	y;
   2369    1.1       jtc 
   2370    1.1       jtc 	/*
   2371    1.1       jtc 	** For a positive leap second hit, the result
   2372   1.45   mlelstv 	** is not unique. For a negative leap second
   2373    1.1       jtc 	** hit, the corresponding time doesn't exist,
   2374    1.1       jtc 	** so we return an adjacent second.
   2375    1.1       jtc 	*/
   2376   1.87  christos 	x = (time_t)(t + leapcorr(sp, t));
   2377   1.87  christos 	y = (time_t)(x - leapcorr(sp, x));
   2378    1.1       jtc 	if (y < t) {
   2379    1.1       jtc 		do {
   2380    1.1       jtc 			x++;
   2381   1.87  christos 			y = (time_t)(x - leapcorr(sp, x));
   2382    1.1       jtc 		} while (y < t);
   2383   1.87  christos 		x -= y != t;
   2384    1.1       jtc 	} else if (y > t) {
   2385    1.1       jtc 		do {
   2386    1.1       jtc 			--x;
   2387   1.87  christos 			y = (time_t)(x - leapcorr(sp, x));
   2388    1.1       jtc 		} while (y > t);
   2389   1.87  christos 		x += y != t;
   2390    1.1       jtc 	}
   2391   1.49  christos 	return x;
   2392   1.49  christos }
   2393   1.49  christos 
   2394   1.49  christos time_t
   2395   1.49  christos posix2time(time_t t)
   2396   1.49  christos {
   2397   1.49  christos 	rwlock_wrlock(&lcl_lock);
   2398   1.87  christos 	if (!lcl_is_set)
   2399   1.87  christos 		tzset_unlocked();
   2400   1.87  christos 	if (lclptr)
   2401   1.87  christos 		t = posix2time_z(lclptr, t);
   2402   1.45   mlelstv 	rwlock_unlock(&lcl_lock);
   2403   1.87  christos 	return t;
   2404    1.1       jtc }
   2405    1.1       jtc 
   2406    1.1       jtc #endif /* defined STD_INSPIRED */
   2407