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