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