Bug Summary

File:src/usr.sbin/zic/zic.c
Warning:line 1408, column 15
The left operand of '>' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name zic.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/zic/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/zic/../../lib/libc/time -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/zic/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/zic/zic.c
1/* $OpenBSD: zic.c,v 1.26 2020/10/13 00:18:46 deraadt Exp $ */
2/*
3** This file is in the public domain, so clarified as of
4** 2006-07-17 by Arthur David Olson.
5*/
6
7#include <sys/types.h>
8#include <sys/wait.h>
9#include <sys/stat.h>
10#include <ctype.h>
11#include <err.h>
12#include <errno(*__errno()).h>
13#include <limits.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <stdint.h>
18#include <unistd.h>
19#include <time.h>
20
21#include "tzfile.h"
22
23#define TRUE1 1
24#define FALSE0 0
25
26#define TYPE_SIGNED(type)(((type) -1) < 0) (((type) -1) < 0)
27
28#define YEARSPERREPEAT400 400 /* years before a Gregorian repeat */
29
30#define GRANDPARENTED"Local time zone must be set--see zic manual page" "Local time zone must be set--see zic manual page"
31
32#define ZIC_VERSION'2' '2'
33
34typedef int_fast64_t zic_t;
35
36#ifndef ZIC_MAX_ABBR_LEN_WO_WARN6
37#define ZIC_MAX_ABBR_LEN_WO_WARN6 6
38#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
39
40#define MKDIR_UMASK(0000400|0000200|0000100|0000040|0000010|0000004|0000001) (S_IRUSR0000400|S_IWUSR0000200|S_IXUSR0000100|S_IRGRP0000040|S_IXGRP0000010|S_IROTH0000004|S_IXOTH0000001)
41
42#define OFFSET_STRLEN_MAXIMUM(7 + INT_STRLEN_MAXIMUM(long)) (7 + INT_STRLEN_MAXIMUM(long))
43#define RULE_STRLEN_MAXIMUM8 8 /* "Mdd.dd.d" */
44
45#define end(cp, n)(memchr((cp), '\0', (n))) (memchr((cp), '\0', (n)))
46
47struct rule {
48 const char *r_filename;
49 int r_linenum;
50 const char *r_name;
51
52 int r_loyear; /* for example, 1986 */
53 int r_hiyear; /* for example, 1986 */
54 int r_lowasnum;
55 int r_hiwasnum;
56
57 int r_month; /* 0..11 */
58
59 int r_dycode; /* see below */
60 int r_dayofmonth;
61 int r_wday;
62
63 long r_tod; /* time from midnight */
64 int r_todisstd; /* above is standard time if TRUE */
65 /* or wall clock time if FALSE */
66 int r_todisgmt; /* above is GMT if TRUE */
67 /* or local time if FALSE */
68 long r_stdoff; /* offset from standard time */
69 const char *r_abbrvar; /* variable part of abbreviation */
70
71 int r_todo; /* a rule to do (used in outzone) */
72 zic_t r_temp; /* used in outzone */
73};
74
75/*
76** r_dycode r_dayofmonth r_wday
77*/
78
79#define DC_DOM0 0 /* 1..31 */ /* unused */
80#define DC_DOWGEQ1 1 /* 1..31 */ /* 0..6 (Sun..Sat) */
81#define DC_DOWLEQ2 2 /* 1..31 */ /* 0..6 (Sun..Sat) */
82
83struct zone {
84 const char *z_filename;
85 int z_linenum;
86
87 const char *z_name;
88 long z_gmtoff;
89 const char *z_rule;
90 const char *z_format;
91
92 long z_stdoff;
93
94 struct rule *z_rules;
95 int z_nrules;
96
97 struct rule z_untilrule;
98 zic_t z_untiltime;
99};
100
101static void addtt(zic_t starttime, int type);
102static int addtype(long gmtoff, const char *abbr, int isdst,
103 int ttisstd, int ttisgmt);
104static void leapadd(zic_t t, int positive, int rolling, int count);
105static void adjleap(void);
106static void associate(void);
107static void convert(long val, char *buf);
108static void convert64(zic_t val, char *buf);
109static void dolink(const char *fromfield, const char *tofield);
110static void doabbr(char *abbr, size_t size, const char *format,
111 const char *letters, int isdst, int doquotes);
112static void eat(const char *name, int num);
113static void eats(const char *name, int num, const char *rname, int rnum);
114static long eitol(int i);
115static void error(const char *message);
116static char **getfields(char *buf);
117static long gethms(const char *string, const char *errstrng, int signable);
118static void infile(const char *filename);
119static void inleap(char **fields, int nfields);
120static void inlink(char **fields, int nfields);
121static void inrule(char **fields, int nfields);
122static int inzcont(char **fields, int nfields);
123static int inzone(char **fields, int nfields);
124static int inzsub(char **fields, int nfields, int iscont);
125static int is32(zic_t x);
126static int itsabbr(const char *abbr, const char *word);
127static int itsdir(const char *name);
128static int mkdirs(char *filename);
129static void newabbr(const char *abbr);
130static long oadd(long t1, long t2);
131static void outzone(const struct zone *zp, int ntzones);
132static void puttzcode(long code, FILE *fp);
133static void puttzcode64(zic_t code, FILE *fp);
134static int rcomp(const void *leftp, const void *rightp);
135static zic_t rpytime(const struct rule *rp, int wantedy);
136static void rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
137 const char *typep, const char *monthp,
138 const char *dayp, const char *timep);
139static int stringoffset(char *result, size_t size, long offset);
140static int stringrule(char *result, size_t size, const struct rule *rp,
141 long dstoff, long gmtoff);
142static void stringzone(char *result, size_t size,
143 const struct zone *zp, int ntzones);
144static void setboundaries(void);
145static zic_t tadd(zic_t t1, long t2);
146static void usage(void);
147static void writezone(const char *name, const char *string);
148
149extern char *__progname;
150
151static int charcnt;
152static int errors;
153static const char *filename;
154static int leapcnt;
155static int leapseen;
156static int leapminyear;
157static int leapmaxyear;
158static int linenum;
159static int max_abbrvar_len;
160static int max_format_len;
161static zic_t max_time;
162static int max_year;
163static zic_t min_time;
164static int min_year;
165static int noise;
166static const char *rfilename;
167static int rlinenum;
168static int timecnt;
169static int typecnt;
170
171/*
172** Line codes.
173*/
174
175#define LC_RULE0 0
176#define LC_ZONE1 1
177#define LC_LINK2 2
178#define LC_LEAP3 3
179
180/*
181** Which fields are which on a Zone line.
182*/
183
184#define ZF_NAME1 1
185#define ZF_GMTOFF2 2
186#define ZF_RULE3 3
187#define ZF_FORMAT4 4
188#define ZF_TILYEAR5 5
189#define ZF_TILMONTH6 6
190#define ZF_TILDAY7 7
191#define ZF_TILTIME8 8
192#define ZONE_MINFIELDS5 5
193#define ZONE_MAXFIELDS9 9
194
195/*
196** Which fields are which on a Zone continuation line.
197*/
198
199#define ZFC_GMTOFF0 0
200#define ZFC_RULE1 1
201#define ZFC_FORMAT2 2
202#define ZFC_TILYEAR3 3
203#define ZFC_TILMONTH4 4
204#define ZFC_TILDAY5 5
205#define ZFC_TILTIME6 6
206#define ZONEC_MINFIELDS3 3
207#define ZONEC_MAXFIELDS7 7
208
209/*
210** Which files are which on a Rule line.
211*/
212
213#define RF_NAME1 1
214#define RF_LOYEAR2 2
215#define RF_HIYEAR3 3
216#define RF_COMMAND4 4
217#define RF_MONTH5 5
218#define RF_DAY6 6
219#define RF_TOD7 7
220#define RF_STDOFF8 8
221#define RF_ABBRVAR9 9
222#define RULE_FIELDS10 10
223
224/*
225** Which fields are which on a Link line.
226*/
227
228#define LF_FROM1 1
229#define LF_TO2 2
230#define LINK_FIELDS3 3
231
232/*
233** Which fields are which on a Leap line.
234*/
235
236#define LP_YEAR1 1
237#define LP_MONTH2 2
238#define LP_DAY3 3
239#define LP_TIME4 4
240#define LP_CORR5 5
241#define LP_ROLL6 6
242#define LEAP_FIELDS7 7
243
244/*
245** Year synonyms.
246*/
247
248#define YR_MINIMUM0 0
249#define YR_MAXIMUM1 1
250#define YR_ONLY2 2
251
252static struct rule *rules;
253static int nrules; /* number of rules */
254
255static struct zone *zones;
256static int nzones; /* number of zones */
257
258struct link {
259 const char *l_filename;
260 int l_linenum;
261 const char *l_from;
262 const char *l_to;
263};
264
265static struct link *links;
266static int nlinks;
267
268struct lookup {
269 const char *l_word;
270 const int l_value;
271};
272
273static struct lookup const *byword(const char *string, const struct lookup *lp);
274
275static struct lookup const line_codes[] = {
276 { "Rule", LC_RULE0 },
277 { "Zone", LC_ZONE1 },
278 { "Link", LC_LINK2 },
279 { "Leap", LC_LEAP3 },
280 { NULL((void *)0), 0}
281};
282
283static struct lookup const mon_names[] = {
284 { "January", TM_JANUARY0 },
285 { "February", TM_FEBRUARY1 },
286 { "March", TM_MARCH2 },
287 { "April", TM_APRIL3 },
288 { "May", TM_MAY4 },
289 { "June", TM_JUNE5 },
290 { "July", TM_JULY6 },
291 { "August", TM_AUGUST7 },
292 { "September", TM_SEPTEMBER8 },
293 { "October", TM_OCTOBER9 },
294 { "November", TM_NOVEMBER10 },
295 { "December", TM_DECEMBER11 },
296 { NULL((void *)0), 0 }
297};
298
299static struct lookup const wday_names[] = {
300 { "Sunday", TM_SUNDAY0 },
301 { "Monday", TM_MONDAY1 },
302 { "Tuesday", TM_TUESDAY2 },
303 { "Wednesday", TM_WEDNESDAY3 },
304 { "Thursday", TM_THURSDAY4 },
305 { "Friday", TM_FRIDAY5 },
306 { "Saturday", TM_SATURDAY6 },
307 { NULL((void *)0), 0 }
308};
309
310static struct lookup const lasts[] = {
311 { "last-Sunday", TM_SUNDAY0 },
312 { "last-Monday", TM_MONDAY1 },
313 { "last-Tuesday", TM_TUESDAY2 },
314 { "last-Wednesday", TM_WEDNESDAY3 },
315 { "last-Thursday", TM_THURSDAY4 },
316 { "last-Friday", TM_FRIDAY5 },
317 { "last-Saturday", TM_SATURDAY6 },
318 { NULL((void *)0), 0 }
319};
320
321static struct lookup const begin_years[] = {
322 { "minimum", YR_MINIMUM0 },
323 { "maximum", YR_MAXIMUM1 },
324 { NULL((void *)0), 0 }
325};
326
327static struct lookup const end_years[] = {
328 { "minimum", YR_MINIMUM0 },
329 { "maximum", YR_MAXIMUM1 },
330 { "only", YR_ONLY2 },
331 { NULL((void *)0), 0 }
332};
333
334static struct lookup const leap_types[] = {
335 { "Rolling", TRUE1 },
336 { "Stationary", FALSE0 },
337 { NULL((void *)0), 0 }
338};
339
340static const int len_months[2][MONSPERYEAR12] = {
341 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
342 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
343};
344
345static const int len_years[2] = {
346 DAYSPERNYEAR365, DAYSPERLYEAR366
347};
348
349static struct attype {
350 zic_t at;
351 unsigned char type;
352} attypes[TZ_MAX_TIMES1200];
353
354static long gmtoffs[TZ_MAX_TYPES256];
355static char isdsts[TZ_MAX_TYPES256];
356static unsigned char abbrinds[TZ_MAX_TYPES256];
357static char ttisstds[TZ_MAX_TYPES256];
358static char ttisgmts[TZ_MAX_TYPES256];
359static char chars[TZ_MAX_CHARS50];
360static zic_t trans[TZ_MAX_LEAPS50];
361static long corr[TZ_MAX_LEAPS50];
362static char roll[TZ_MAX_LEAPS50];
363
364/*
365** Memory allocation.
366*/
367
368static void *
369memcheck(void *ptr)
370{
371 if (ptr == NULL((void *)0))
372 err(1, "Memory exhausted");
373 return ptr;
374}
375
376static char *
377ecatalloc(char *start, const char *tail)
378{
379 size_t len;
380 char *str;
381
382 len = strlen(start) + strlen(tail) + 1;
383 str = memcheck(realloc(start, len));
384 strlcat(str, tail, len);
385 return str;
386}
387
388#define emalloc(size)memcheck(malloc(size)) memcheck(malloc(size))
389#define ereallocarray(ptr, nmemb, size)memcheck(reallocarray(ptr, nmemb, size)) memcheck(reallocarray(ptr, nmemb, size))
390#define erealloc(ptr, size)memcheck(realloc((ptr), (size))) memcheck(realloc((ptr), (size)))
391#define ecpyalloc(ptr)memcheck(strdup(ptr)) memcheck(strdup(ptr))
392
393/*
394** Error handling.
395*/
396
397static void
398eats(const char *name, int num, const char *rname, int rnum)
399{
400 filename = name;
401 linenum = num;
402 rfilename = rname;
403 rlinenum = rnum;
404}
405
406static void
407eat(const char *name, int num)
408{
409 eats(name, num, NULL((void *)0), -1);
410}
411
412static void
413error(const char *string)
414{
415 /*
416 ** Match the format of "cc" to allow sh users to
417 ** zic ... 2>&1 | error -t "*" -v
418 ** on BSD systems.
419 */
420 fprintf(stderr(&__sF[2]), "\"%s\", line %d: %s",
421 filename, linenum, string);
422 if (rfilename != NULL((void *)0))
423 fprintf(stderr(&__sF[2]), " (rule from \"%s\", line %d)",
424 rfilename, rlinenum);
425 fprintf(stderr(&__sF[2]), "\n");
426 ++errors;
427}
428
429static void
430warning(const char *string)
431{
432 char *cp;
433
434 cp = ecpyalloc("warning: ")memcheck(strdup("warning: "));
435 cp = ecatalloc(cp, string);
436 error(cp);
437 free(cp);
438 --errors;
439}
440
441
442static const char *
443scheck(const char *string, const char *format)
444{
445 const char *fp, *result;
446 char *fbuf, *tp, dummy;
447 int c;
448
449 result = "";
450 if (string == NULL((void *)0) || format == NULL((void *)0))
451 return result;
452 fbuf = reallocarray(NULL((void *)0), strlen(format) + 2, 2);
453 if (fbuf == NULL((void *)0))
454 return result;
455 fp = format;
456 tp = fbuf;
457 while ((*tp++ = c = *fp++) != '\0') {
458 if (c != '%')
459 continue;
460 if (*fp == '%') {
461 *tp++ = *fp++;
462 continue;
463 }
464 *tp++ = '*';
465 if (*fp == '*')
466 ++fp;
467 while (isdigit((unsigned char)*fp))
468 *tp++ = *fp++;
469 if (*fp == 'l' || *fp == 'h')
470 *tp++ = *fp++;
471 else if (*fp == '[')
472 do {
473 *tp++ = *fp++;
474 } while (*fp != '\0' && *fp != ']');
475 if ((*tp++ = *fp++) == '\0')
476 break;
477 }
478 *(tp - 1) = '%';
479 *tp++ = 'c';
480 *tp = '\0';
481 if (sscanf(string, fbuf, &dummy) != 1)
482 result = format;
483 free(fbuf);
484 return result;
485}
486
487static void
488usage(void)
489{
490 fprintf(stderr(&__sF[2]),
491 "usage: %s [-v] [-d directory] [-L leapsecondfilename] [-l timezone]\n"
492 "\t\t[-p timezone] [filename ...]\n",
493 __progname);
494 exit(EXIT_FAILURE1);
495}
496
497static const char *psxrules;
498static const char *lcltime;
499static const char *directory;
500static const char *leapsec;
501
502int
503main(int argc, char **argv)
504{
505 int i, j, c;
506
507 if (pledge("stdio rpath wpath cpath proc exec", NULL((void *)0)) == -1)
508 err(1, "pledge");
509
510 umask(umask(S_IWGRP0000020 | S_IWOTH0000002) | (S_IWGRP0000020 | S_IWOTH0000002));
511 while ((c = getopt(argc, argv, "d:l:p:L:vy:")) != -1)
512 switch (c) {
513 default:
514 usage();
515 case 'd':
516 if (directory == NULL((void *)0))
517 directory = optarg;
518 else
519 errx(1, "More than one -d option specified");
520 break;
521 case 'l':
522 if (lcltime == NULL((void *)0))
523 lcltime = optarg;
524 else
525 errx(1, "More than one -l option specified");
526 break;
527 case 'p':
528 if (psxrules == NULL((void *)0))
529 psxrules = optarg;
530 else
531 errx(1, "More than one -p option specified");
532 break;
533 case 'y':
534 warning("ignoring obsolescent option -y");
535 break;
536 case 'L':
537 if (leapsec == NULL((void *)0))
538 leapsec = optarg;
539 else
540 errx(1, "More than one -L option specified");
541 break;
542 case 'v':
543 noise = TRUE1;
544 break;
545 }
546 if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
547 usage(); /* usage message by request */
548 if (directory == NULL((void *)0))
549 directory = TZDIR"/usr/share/zoneinfo";
550
551 setboundaries();
552
553 if (optind < argc && leapsec != NULL((void *)0)) {
554 infile(leapsec);
555 adjleap();
556 }
557
558 for (i = optind; i < argc; ++i)
559 infile(argv[i]);
560 if (errors)
561 exit(EXIT_FAILURE1);
562 associate();
563 for (i = 0; i < nzones; i = j) {
564 /*
565 ** Find the next non-continuation zone entry.
566 */
567 for (j = i + 1; j < nzones && zones[j].z_name == NULL((void *)0); ++j)
568 continue;
569 outzone(&zones[i], j - i);
570 }
571 /*
572 ** Make links.
573 */
574 for (i = 0; i < nlinks; ++i) {
575 eat(links[i].l_filename, links[i].l_linenum);
576 dolink(links[i].l_from, links[i].l_to);
577 if (noise)
578 for (j = 0; j < nlinks; ++j)
579 if (strcmp(links[i].l_to,
580 links[j].l_from) == 0)
581 warning("link to link");
582 }
583 if (lcltime != NULL((void *)0)) {
584 eat("command line", 1);
585 dolink(lcltime, TZDEFAULT"/etc/localtime");
586 }
587 if (psxrules != NULL((void *)0)) {
588 eat("command line", 1);
589 dolink(psxrules, TZDEFRULES"posixrules");
590 }
591 return (errors == 0) ? EXIT_SUCCESS0 : EXIT_FAILURE1;
592}
593
594static void
595dolink(const char *fromfield, const char *tofield)
596{
597 char *fromname, *toname;
598
599 if (fromfield[0] == '/')
600 fromname = ecpyalloc(fromfield)memcheck(strdup(fromfield));
601 else {
602 fromname = ecpyalloc(directory)memcheck(strdup(directory));
603 fromname = ecatalloc(fromname, "/");
604 fromname = ecatalloc(fromname, fromfield);
605 }
606 if (tofield[0] == '/')
607 toname = ecpyalloc(tofield)memcheck(strdup(tofield));
608 else {
609 toname = ecpyalloc(directory)memcheck(strdup(directory));
610 toname = ecatalloc(toname, "/");
611 toname = ecatalloc(toname, tofield);
612 }
613 /*
614 ** We get to be careful here since
615 ** there's a fair chance of root running us.
616 */
617 if (!itsdir(toname))
618 remove(toname);
619 if (link(fromname, toname) != 0) {
620 int result;
621
622 if (mkdirs(toname) != 0)
623 exit(EXIT_FAILURE1);
624
625 result = link(fromname, toname);
626 if (result != 0 && errno(*__errno()) == EXDEV18)
627 result = symlink(fromname, toname);
628 if (result != 0)
629 err(1, "Can't link from %s to %s", fromname, toname);
630 }
631 free(fromname);
632 free(toname);
633}
634
635#define TIME_T_BITS_IN_FILE64 64
636
637static void
638setboundaries(void)
639{
640 int i;
641
642 min_time = -1;
643 for (i = 0; i < TIME_T_BITS_IN_FILE64 - 1; ++i)
644 min_time *= 2;
645 max_time = -(min_time + 1);
646}
647
648static int
649itsdir(const char *name)
650{
651 char *myname;
652 int accres;
653
654 myname = ecpyalloc(name)memcheck(strdup(name));
655 myname = ecatalloc(myname, "/.");
656 accres = access(myname, F_OK0);
657 free(myname);
658 return accres == 0;
659}
660
661/*
662** Associate sets of rules with zones.
663*/
664
665/*
666** Sort by rule name.
667*/
668
669static int
670rcomp(const void *cp1, const void *cp2)
671{
672 return strcmp(((const struct rule *) cp1)->r_name,
673 ((const struct rule *) cp2)->r_name);
674}
675
676static void
677associate(void)
678{
679 struct zone *zp;
680 struct rule *rp;
681 int base, out, i, j;
682
683 if (nrules != 0) {
684 qsort(rules, nrules, sizeof *rules, rcomp);
685 for (i = 0; i < nrules - 1; ++i) {
686 if (strcmp(rules[i].r_name,
687 rules[i + 1].r_name) != 0)
688 continue;
689 if (strcmp(rules[i].r_filename,
690 rules[i + 1].r_filename) == 0)
691 continue;
692 eat(rules[i].r_filename, rules[i].r_linenum);
693 warning("same rule name in multiple files");
694 eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
695 warning("same rule name in multiple files");
696 for (j = i + 2; j < nrules; ++j) {
697 if (strcmp(rules[i].r_name,
698 rules[j].r_name) != 0)
699 break;
700 if (strcmp(rules[i].r_filename,
701 rules[j].r_filename) == 0)
702 continue;
703 if (strcmp(rules[i + 1].r_filename,
704 rules[j].r_filename) == 0)
705 continue;
706 break;
707 }
708 i = j - 1;
709 }
710 }
711 for (i = 0; i < nzones; ++i) {
712 zp = &zones[i];
713 zp->z_rules = NULL((void *)0);
714 zp->z_nrules = 0;
715 }
716 for (base = 0; base < nrules; base = out) {
717 rp = &rules[base];
718 for (out = base + 1; out < nrules; ++out)
719 if (strcmp(rp->r_name, rules[out].r_name) != 0)
720 break;
721 for (i = 0; i < nzones; ++i) {
722 zp = &zones[i];
723 if (strcmp(zp->z_rule, rp->r_name) != 0)
724 continue;
725 zp->z_rules = rp;
726 zp->z_nrules = out - base;
727 }
728 }
729 for (i = 0; i < nzones; ++i) {
730 zp = &zones[i];
731 if (zp->z_nrules == 0) {
732 /*
733 ** Maybe we have a local standard time offset.
734 */
735 eat(zp->z_filename, zp->z_linenum);
736 zp->z_stdoff = gethms(zp->z_rule, "unruly zone",
737 TRUE1);
738 /*
739 ** Note, though, that if there's no rule,
740 ** a '%s' in the format is a bad thing.
741 */
742 if (strchr(zp->z_format, '%') != 0)
743 error("%s in ruleless zone");
744 }
745 }
746 if (errors)
747 exit(EXIT_FAILURE1);
748}
749
750static void
751infile(const char *name)
752{
753 FILE *fp;
754 char **fields, *cp;
755 const struct lookup *lp;
756 int nfields, wantcont, num;
757 char buf[BUFSIZ1024];
758
759 if (strcmp(name, "-") == 0) {
760 name = "standard input";
761 fp = stdin(&__sF[0]);
762 } else if ((fp = fopen(name, "r")) == NULL((void *)0))
763 err(1, "Can't open %s", name);
764 wantcont = FALSE0;
765 for (num = 1; ; ++num) {
766 eat(name, num);
767 if (fgets(buf, sizeof buf, fp) != buf)
768 break;
769 cp = strchr(buf, '\n');
770 if (cp == NULL((void *)0)) {
771 error("line too long");
772 exit(EXIT_FAILURE1);
773 }
774 *cp = '\0';
775 fields = getfields(buf);
776 nfields = 0;
777 while (fields[nfields] != NULL((void *)0)) {
778 static char nada;
779
780 if (strcmp(fields[nfields], "-") == 0)
781 fields[nfields] = &nada;
782 ++nfields;
783 }
784 if (nfields == 0) {
785 /* nothing to do */
786 } else if (wantcont) {
787 wantcont = inzcont(fields, nfields);
788 } else {
789 lp = byword(fields[0], line_codes);
790 if (lp == NULL((void *)0))
791 error("input line of unknown type");
792 else switch ((int) (lp->l_value)) {
793 case LC_RULE0:
794 inrule(fields, nfields);
795 wantcont = FALSE0;
796 break;
797 case LC_ZONE1:
798 wantcont = inzone(fields, nfields);
799 break;
800 case LC_LINK2:
801 inlink(fields, nfields);
802 wantcont = FALSE0;
803 break;
804 case LC_LEAP3:
805 if (name != leapsec)
806 fprintf(stderr(&__sF[2]),
807 "%s: Leap line in non leap seconds file %s\n",
808 __progname, name);
809 /* no exit? */
810 else
811 inleap(fields, nfields);
812 wantcont = FALSE0;
813 break;
814 default: /* "cannot happen" */
815 errx(1, "panic: Invalid l_value %d", lp->l_value);
816 }
817 }
818 free(fields);
819 }
820 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
821 errx(1, "Error reading %s", filename);
822 if (fp != stdin(&__sF[0]) && fclose(fp))
823 err(1, "Error closing %s", filename);
824 if (wantcont)
825 error("expected continuation line not found");
826}
827
828/*
829** Convert a string of one of the forms
830** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
831** into a number of seconds.
832** A null string maps to zero.
833** Call error with errstring and return zero on errors.
834*/
835
836static long
837gethms(const char *string, const char *errstring, int signable)
838{
839 long hh;
840 int mm, ss, sign;
841
842 if (string == NULL((void *)0) || *string == '\0')
843 return 0;
844 if (!signable)
845 sign = 1;
846 else if (*string == '-') {
847 sign = -1;
848 ++string;
849 } else
850 sign = 1;
851 if (sscanf(string, scheck(string, "%ld"), &hh) == 1)
852 mm = ss = 0;
853 else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2)
854 ss = 0;
855 else if (sscanf(string, scheck(string, "%ld:%d:%d"),
856 &hh, &mm, &ss) != 3) {
857 error(errstring);
858 return 0;
859 }
860 if (hh < 0 ||
861 mm < 0 || mm >= MINSPERHOUR60 ||
862 ss < 0 || ss > SECSPERMIN60) {
863 error(errstring);
864 return 0;
865 }
866 if (LONG_MAX9223372036854775807L / SECSPERHOUR(60 * 60) < hh) {
867 error("time overflow");
868 return 0;
869 }
870 return oadd(eitol(sign) * hh * eitol(SECSPERHOUR(60 * 60)),
871 eitol(sign) * (eitol(mm) * eitol(SECSPERMIN60) + eitol(ss)));
872}
873
874static void
875inrule(char **fields, int nfields)
876{
877 static struct rule r;
878
879 if (nfields != RULE_FIELDS10) {
880 error("wrong number of fields on Rule line");
881 return;
882 }
883 if (*fields[RF_NAME1] == '\0') {
884 error("nameless rule");
885 return;
886 }
887 r.r_filename = filename;
888 r.r_linenum = linenum;
889 r.r_stdoff = gethms(fields[RF_STDOFF8], "invalid saved time", TRUE1);
890 rulesub(&r, fields[RF_LOYEAR2], fields[RF_HIYEAR3], fields[RF_COMMAND4],
891 fields[RF_MONTH5], fields[RF_DAY6], fields[RF_TOD7]);
892 r.r_name = ecpyalloc(fields[RF_NAME])memcheck(strdup(fields[1]));
893 r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR])memcheck(strdup(fields[9]));
894 if (max_abbrvar_len < strlen(r.r_abbrvar))
895 max_abbrvar_len = strlen(r.r_abbrvar);
896 rules = ereallocarray(rules, nrules + 1, sizeof *rules)memcheck(reallocarray(rules, nrules + 1, sizeof *rules));
897 rules[nrules++] = r;
898}
899
900static int
901inzone(char **fields, int nfields)
902{
903 int i;
904 static char *buf;
905 size_t len;
906
907 if (nfields < ZONE_MINFIELDS5 || nfields > ZONE_MAXFIELDS9) {
908 error("wrong number of fields on Zone line");
909 return FALSE0;
910 }
911 if (strcmp(fields[ZF_NAME1], TZDEFAULT"/etc/localtime") == 0 && lcltime != NULL((void *)0)) {
912 len = 132 + strlen(TZDEFAULT"/etc/localtime");
913 buf = erealloc(buf, len)memcheck(realloc((buf), (len)));
914 snprintf(buf, len,
915 "\"Zone %s\" line and -l option are mutually exclusive",
916 TZDEFAULT"/etc/localtime");
917 error(buf);
918 return FALSE0;
919 }
920 if (strcmp(fields[ZF_NAME1], TZDEFRULES"posixrules") == 0 && psxrules != NULL((void *)0)) {
921 len = 132 + strlen(TZDEFRULES"posixrules");
922 buf = erealloc(buf, len)memcheck(realloc((buf), (len)));
923 snprintf(buf, len,
924 "\"Zone %s\" line and -p option are mutually exclusive",
925 TZDEFRULES"posixrules");
926 error(buf);
927 return FALSE0;
928 }
929 for (i = 0; i < nzones; ++i)
930 if (zones[i].z_name != NULL((void *)0) &&
931 strcmp(zones[i].z_name, fields[ZF_NAME1]) == 0) {
932 len = 132 + strlen(fields[ZF_NAME1]) +
933 strlen(zones[i].z_filename);
934 buf = erealloc(buf, len)memcheck(realloc((buf), (len)));
935 snprintf(buf, len,
936 "duplicate zone name %s (file \"%s\", line %d)",
937 fields[ZF_NAME1],
938 zones[i].z_filename,
939 zones[i].z_linenum);
940 error(buf);
941 return FALSE0;
942 }
943 return inzsub(fields, nfields, FALSE0);
944}
945
946static int
947inzcont(char **fields, int nfields)
948{
949 if (nfields < ZONEC_MINFIELDS3 || nfields > ZONEC_MAXFIELDS7) {
950 error("wrong number of fields on Zone continuation line");
951 return FALSE0;
952 }
953 return inzsub(fields, nfields, TRUE1);
954}
955
956static int
957inzsub(char **fields, int nfields, int iscont)
958{
959 char *cp;
960 static struct zone z;
961 int i_gmtoff, i_rule, i_format;
962 int i_untilyear, i_untilmonth;
963 int i_untilday, i_untiltime;
964 int hasuntil;
965
966 if (iscont) {
967 i_gmtoff = ZFC_GMTOFF0;
968 i_rule = ZFC_RULE1;
969 i_format = ZFC_FORMAT2;
970 i_untilyear = ZFC_TILYEAR3;
971 i_untilmonth = ZFC_TILMONTH4;
972 i_untilday = ZFC_TILDAY5;
973 i_untiltime = ZFC_TILTIME6;
974 z.z_name = NULL((void *)0);
975 } else {
976 i_gmtoff = ZF_GMTOFF2;
977 i_rule = ZF_RULE3;
978 i_format = ZF_FORMAT4;
979 i_untilyear = ZF_TILYEAR5;
980 i_untilmonth = ZF_TILMONTH6;
981 i_untilday = ZF_TILDAY7;
982 i_untiltime = ZF_TILTIME8;
983 z.z_name = ecpyalloc(fields[ZF_NAME])memcheck(strdup(fields[1]));
984 }
985 z.z_filename = filename;
986 z.z_linenum = linenum;
987 z.z_gmtoff = gethms(fields[i_gmtoff], "invalid UTC offset", TRUE1);
988 if ((cp = strchr(fields[i_format], '%')) != 0) {
989 if (*++cp != 's' || strchr(cp, '%') != 0) {
990 error("invalid abbreviation format");
991 return FALSE0;
992 }
993 }
994 z.z_rule = ecpyalloc(fields[i_rule])memcheck(strdup(fields[i_rule]));
995 z.z_format = ecpyalloc(fields[i_format])memcheck(strdup(fields[i_format]));
996 if (max_format_len < strlen(z.z_format))
997 max_format_len = strlen(z.z_format);
998 hasuntil = nfields > i_untilyear;
999 if (hasuntil) {
1000 z.z_untilrule.r_filename = filename;
1001 z.z_untilrule.r_linenum = linenum;
1002 rulesub(&z.z_untilrule,
1003 fields[i_untilyear],
1004 "only",
1005 "",
1006 (nfields > i_untilmonth) ?
1007 fields[i_untilmonth] : "Jan",
1008 (nfields > i_untilday) ? fields[i_untilday] : "1",
1009 (nfields > i_untiltime) ? fields[i_untiltime] : "0");
1010 z.z_untiltime = rpytime(&z.z_untilrule,
1011 z.z_untilrule.r_loyear);
1012 if (iscont && nzones > 0 &&
1013 z.z_untiltime > min_time &&
1014 z.z_untiltime < max_time &&
1015 zones[nzones - 1].z_untiltime > min_time &&
1016 zones[nzones - 1].z_untiltime < max_time &&
1017 zones[nzones - 1].z_untiltime >= z.z_untiltime) {
1018 error("Zone continuation line end time is not after end time of previous line");
1019 return FALSE0;
1020 }
1021 }
1022 zones = ereallocarray(zones, nzones + 1, sizeof *zones)memcheck(reallocarray(zones, nzones + 1, sizeof *zones));
1023 zones[nzones++] = z;
1024 /*
1025 ** If there was an UNTIL field on this line,
1026 ** there's more information about the zone on the next line.
1027 */
1028 return hasuntil;
1029}
1030
1031static void
1032inleap(char **fields, int nfields)
1033{
1034 const char *cp;
1035 const struct lookup *lp;
1036 int i, j;
1037 int year, month, day;
1038 long dayoff, tod;
1039 zic_t t;
1040
1041 if (nfields != LEAP_FIELDS7) {
1042 error("wrong number of fields on Leap line");
1043 return;
1044 }
1045 dayoff = 0;
1046 cp = fields[LP_YEAR1];
1047 if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
1048 /*
1049 ** Leapin' Lizards!
1050 */
1051 error("invalid leaping year");
1052 return;
1053 }
1054 if (!leapseen || leapmaxyear < year)
1055 leapmaxyear = year;
1056 if (!leapseen || leapminyear > year)
1057 leapminyear = year;
1058 leapseen = TRUE1;
1059 j = EPOCH_YEAR1970;
1060 while (j != year) {
1061 if (year > j) {
1062 i = len_years[isleap(j)(((j) % 4) == 0 && (((j) % 100) != 0 || ((j) % 400) ==
0))
];
1063 ++j;
1064 } else {
1065 --j;
1066 i = -len_years[isleap(j)(((j) % 4) == 0 && (((j) % 100) != 0 || ((j) % 400) ==
0))
];
1067 }
1068 dayoff = oadd(dayoff, eitol(i));
1069 }
1070 if ((lp = byword(fields[LP_MONTH2], mon_names)) == NULL((void *)0)) {
1071 error("invalid month name");
1072 return;
1073 }
1074 month = lp->l_value;
1075 j = TM_JANUARY0;
1076 while (j != month) {
1077 i = len_months[isleap(year)(((year) % 4) == 0 && (((year) % 100) != 0 || ((year)
% 400) == 0))
][j];
1078 dayoff = oadd(dayoff, eitol(i));
1079 ++j;
1080 }
1081 cp = fields[LP_DAY3];
1082 if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
1083 day <= 0 || day > len_months[isleap(year)(((year) % 4) == 0 && (((year) % 100) != 0 || ((year)
% 400) == 0))
][month]) {
1084 error("invalid day of month");
1085 return;
1086 }
1087 dayoff = oadd(dayoff, eitol(day - 1));
1088 if (dayoff < 0 && !TYPE_SIGNED(zic_t)(((zic_t) -1) < 0)) {
1089 error("time before zero");
1090 return;
1091 }
1092 if (dayoff < min_time / SECSPERDAY((long) (60 * 60) * 24)) {
1093 error("time too small");
1094 return;
1095 }
1096 if (dayoff > max_time / SECSPERDAY((long) (60 * 60) * 24)) {
1097 error("time too large");
1098 return;
1099 }
1100 t = (zic_t) dayoff * SECSPERDAY((long) (60 * 60) * 24);
1101 tod = gethms(fields[LP_TIME4], "invalid time of day", FALSE0);
1102 cp = fields[LP_CORR5];
1103 {
1104 int positive;
1105 int count;
1106
1107 if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
1108 positive = FALSE0;
1109 count = 1;
1110 } else if (strcmp(cp, "--") == 0) {
1111 positive = FALSE0;
1112 count = 2;
1113 } else if (strcmp(cp, "+") == 0) {
1114 positive = TRUE1;
1115 count = 1;
1116 } else if (strcmp(cp, "++") == 0) {
1117 positive = TRUE1;
1118 count = 2;
1119 } else {
1120 error("illegal CORRECTION field on Leap line");
1121 return;
1122 }
1123 if ((lp = byword(fields[LP_ROLL6], leap_types)) == NULL((void *)0)) {
1124 error("illegal Rolling/Stationary field on Leap line");
1125 return;
1126 }
1127 leapadd(tadd(t, tod), positive, lp->l_value, count);
1128 }
1129}
1130
1131static void
1132inlink(char **fields, int nfields)
1133{
1134 struct link l;
1135
1136 if (nfields != LINK_FIELDS3) {
1137 error("wrong number of fields on Link line");
1138 return;
1139 }
1140 if (*fields[LF_FROM1] == '\0') {
1141 error("blank FROM field on Link line");
1142 return;
1143 }
1144 if (*fields[LF_TO2] == '\0') {
1145 error("blank TO field on Link line");
1146 return;
1147 }
1148 l.l_filename = filename;
1149 l.l_linenum = linenum;
1150 l.l_from = ecpyalloc(fields[LF_FROM])memcheck(strdup(fields[1]));
1151 l.l_to = ecpyalloc(fields[LF_TO])memcheck(strdup(fields[2]));
1152 links = ereallocarray(links, nlinks + 1, sizeof *links)memcheck(reallocarray(links, nlinks + 1, sizeof *links));
1153 links[nlinks++] = l;
1154}
1155
1156static void
1157rulesub(struct rule * const rp, const char * const loyearp,
1158 const char * const hiyearp, const char * const typep,
1159 const char * const monthp, const char * const dayp,
1160 const char * const timep)
1161{
1162 const struct lookup *lp;
1163 const char *cp;
1164 char *dp, *ep;
1165
1166 if ((lp = byword(monthp, mon_names)) == NULL((void *)0)) {
1167 error("invalid month name");
1168 return;
1169 }
1170 rp->r_month = lp->l_value;
1171 rp->r_todisstd = FALSE0;
1172 rp->r_todisgmt = FALSE0;
1173 dp = ecpyalloc(timep)memcheck(strdup(timep));
1174 if (*dp != '\0') {
1175 ep = dp + strlen(dp) - 1;
1176 switch (tolower((unsigned char)*ep)) {
1177 case 's': /* Standard */
1178 rp->r_todisstd = TRUE1;
1179 rp->r_todisgmt = FALSE0;
1180 *ep = '\0';
1181 break;
1182 case 'w': /* Wall */
1183 rp->r_todisstd = FALSE0;
1184 rp->r_todisgmt = FALSE0;
1185 *ep = '\0';
1186 break;
1187 case 'g': /* Greenwich */
1188 case 'u': /* Universal */
1189 case 'z': /* Zulu */
1190 rp->r_todisstd = TRUE1;
1191 rp->r_todisgmt = TRUE1;
1192 *ep = '\0';
1193 break;
1194 }
1195 }
1196 rp->r_tod = gethms(dp, "invalid time of day", FALSE0);
1197 free(dp);
1198 /*
1199 ** Year work.
1200 */
1201 cp = loyearp;
1202 lp = byword(cp, begin_years);
1203 rp->r_lowasnum = lp == NULL((void *)0);
1204 if (!rp->r_lowasnum) switch ((int) lp->l_value) {
1205 case YR_MINIMUM0:
1206 rp->r_loyear = INT_MIN(-2147483647 -1);
1207 break;
1208 case YR_MAXIMUM1:
1209 rp->r_loyear = INT_MAX2147483647;
1210 break;
1211 default: /* "cannot happen" */
1212 errx(1, "panic: Invalid l_value %d", lp->l_value);
1213 } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
1214 error("invalid starting year");
1215 return;
1216 }
1217 cp = hiyearp;
1218 lp = byword(cp, end_years);
1219 rp->r_hiwasnum = lp == NULL((void *)0);
1220 if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
1221 case YR_MINIMUM0:
1222 rp->r_hiyear = INT_MIN(-2147483647 -1);
1223 break;
1224 case YR_MAXIMUM1:
1225 rp->r_hiyear = INT_MAX2147483647;
1226 break;
1227 case YR_ONLY2:
1228 rp->r_hiyear = rp->r_loyear;
1229 break;
1230 default: /* "cannot happen" */
1231 errx(1, "panic: Invalid l_value %d", lp->l_value);
1232 } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
1233 error("invalid ending year");
1234 return;
1235 }
1236 if (rp->r_loyear > rp->r_hiyear) {
1237 error("starting year greater than ending year");
1238 return;
1239 }
1240 if (*typep != '\0') {
1241 if (rp->r_loyear == rp->r_hiyear) {
1242 error("typed single year");
1243 return;
1244 }
1245 warning("year type is obsolete; use \"-\" instead");
1246 }
1247 /*
1248 ** Day work.
1249 ** Accept things such as:
1250 ** 1
1251 ** last-Sunday
1252 ** Sun<=20
1253 ** Sun>=7
1254 */
1255 dp = ecpyalloc(dayp)memcheck(strdup(dayp));
1256 if ((lp = byword(dp, lasts)) != NULL((void *)0)) {
1257 rp->r_dycode = DC_DOWLEQ2;
1258 rp->r_wday = lp->l_value;
1259 rp->r_dayofmonth = len_months[1][rp->r_month];
1260 } else {
1261 if ((ep = strchr(dp, '<')) != 0)
1262 rp->r_dycode = DC_DOWLEQ2;
1263 else if ((ep = strchr(dp, '>')) != 0)
1264 rp->r_dycode = DC_DOWGEQ1;
1265 else {
1266 ep = dp;
1267 rp->r_dycode = DC_DOM0;
1268 }
1269 if (rp->r_dycode != DC_DOM0) {
1270 *ep++ = 0;
1271 if (*ep++ != '=') {
1272 error("invalid day of month");
1273 free(dp);
1274 return;
1275 }
1276 if ((lp = byword(dp, wday_names)) == NULL((void *)0)) {
1277 error("invalid weekday name");
1278 free(dp);
1279 return;
1280 }
1281 rp->r_wday = lp->l_value;
1282 }
1283 if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
1284 rp->r_dayofmonth <= 0 ||
1285 (rp->r_dayofmonth > len_months[1][rp->r_month])) {
1286 error("invalid day of month");
1287 free(dp);
1288 return;
1289 }
1290 }
1291 free(dp);
1292}
1293
1294static void
1295convert(long val, char *buf)
1296{
1297 int i;
1298 int shift;
1299
1300 for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1301 buf[i] = val >> shift;
1302}
1303
1304static void
1305convert64(zic_t val, char *buf)
1306{
1307 int i;
1308 int shift;
1309
1310 for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
1311 buf[i] = val >> shift;
1312}
1313
1314static void
1315puttzcode(long val, FILE *fp)
1316{
1317 char buf[4];
1318
1319 convert(val, buf);
1320 fwrite(buf, sizeof buf, 1, fp);
1321}
1322
1323static void
1324puttzcode64(zic_t val, FILE *fp)
1325{
1326 char buf[8];
1327
1328 convert64(val, buf);
1329 fwrite(buf, sizeof buf, 1, fp);
1330}
1331
1332static int
1333atcomp(const void *avp, const void *bvp)
1334{
1335 const zic_t a = ((const struct attype *) avp)->at;
1336 const zic_t b = ((const struct attype *) bvp)->at;
1337
1338 return (a < b) ? -1 : (a > b);
1339}
1340
1341static int
1342is32(zic_t x)
1343{
1344 return INT32_MIN(-0x7fffffff - 1) <= x && x <= INT32_MAX0x7fffffff;
1345}
1346
1347static void
1348writezone(const char *name, const char *string)
1349{
1350 FILE *fp;
1351 int i, j;
1352 int leapcnt32, leapi32;
1353 int timecnt32, timei32;
1354 int pass;
1355 static char *fullname;
1356 static const struct tzhead tzh0;
1357 static struct tzhead tzh;
1358 zic_t ats[TZ_MAX_TIMES1200];
1359 unsigned char types[TZ_MAX_TIMES1200];
1360 size_t len;
1361
1362 /*
1363 ** Sort.
1364 */
1365 if (timecnt > 1)
1
Assuming 'timecnt' is <= 1
2
Taking false branch
1366 qsort(attypes, timecnt, sizeof *attypes, atcomp);
1367 /*
1368 ** Optimize.
1369 */
1370 {
1371 int fromi;
1372 int toi;
1373
1374 toi = 0;
1375 fromi = 0;
1376 while (fromi < timecnt && attypes[fromi].at < min_time)
3
Assuming 'fromi' is < 'timecnt'
4
Assuming 'min_time' is <= field 'at'
5
Loop condition is false. Execution continues on line 1378
1377 ++fromi;
1378 if (isdsts[0] == 0)
6
Assuming the condition is false
7
Taking false branch
1379 while (fromi < timecnt && attypes[fromi].type == 0)
1380 ++fromi; /* handled by default rule */
1381 for ( ; fromi < timecnt; ++fromi) {
8
Loop condition is true. Entering loop body
9
Loop condition is false. Execution continues on line 1393
1382 if (toi
8.1
'toi' is equal to 0
!= 0 && ((attypes[fromi].at +
1383 gmtoffs[attypes[toi - 1].type]) <=
1384 (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0 :
1385 attypes[toi - 2].type]))) {
1386 attypes[toi - 1].type = attypes[fromi].type;
1387 continue;
1388 }
1389 if (toi
8.2
'toi' is equal to 0
== 0 ||
1390 attypes[toi - 1].type != attypes[fromi].type)
1391 attypes[toi++] = attypes[fromi];
1392 }
1393 timecnt = toi;
1394 }
1395 /*
1396 ** Transfer.
1397 */
1398 for (i = 0; i < timecnt; ++i) {
10
Loop condition is true. Entering loop body
11
Loop condition is false. Execution continues on line 1405
1399 ats[i] = attypes[i].at;
1400 types[i] = attypes[i].type;
1401 }
1402 /*
1403 ** Correct for leap seconds.
1404 */
1405 for (i = 0; i < timecnt; ++i) {
12
Loop condition is true. Entering loop body
18
The value 1 is assigned to 'i'
19
Assuming 'i' is < 'timecnt'
20
Loop condition is true. Entering loop body
1406 j = leapcnt;
1407 while (--j >= 0)
13
Assuming the condition is true
14
Loop condition is true. Entering loop body
21
Assuming the condition is true
22
Loop condition is true. Entering loop body
1408 if (ats[i] > trans[j] - corr[j]) {
15
Assuming the condition is true
16
Taking true branch
23
The left operand of '>' is a garbage value
1409 ats[i] = tadd(ats[i], corr[j]);
1410 break;
17
Execution continues on line 1405
1411 }
1412 }
1413 /*
1414 ** Figure out 32-bit-limited starts and counts.
1415 */
1416 timecnt32 = timecnt;
1417 timei32 = 0;
1418 leapcnt32 = leapcnt;
1419 leapi32 = 0;
1420 while (timecnt32 > 0 && !is32(ats[timecnt32 - 1]))
1421 --timecnt32;
1422 while (timecnt32 > 0 && !is32(ats[timei32])) {
1423 --timecnt32;
1424 ++timei32;
1425 }
1426 while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1]))
1427 --leapcnt32;
1428 while (leapcnt32 > 0 && !is32(trans[leapi32])) {
1429 --leapcnt32;
1430 ++leapi32;
1431 }
1432 len = strlen(directory) + 1 + strlen(name) + 1;
1433 fullname = erealloc(fullname, len)memcheck(realloc((fullname), (len)));
1434 snprintf(fullname, len, "%s/%s", directory, name);
1435 /*
1436 ** Remove old file, if any, to snap links.
1437 */
1438 if (!itsdir(fullname) && remove(fullname) != 0 && errno(*__errno()) != ENOENT2)
1439 err(1, "Can't remove %s", fullname);
1440 if ((fp = fopen(fullname, "wb")) == NULL((void *)0)) {
1441 if (mkdirs(fullname) != 0)
1442 exit(EXIT_FAILURE1);
1443 if ((fp = fopen(fullname, "wb")) == NULL((void *)0))
1444 err(1, "Can't create %s", fullname);
1445 }
1446 for (pass = 1; pass <= 2; ++pass) {
1447 int thistimei, thistimecnt;
1448 int thisleapi, thisleapcnt;
1449 int thistimelim, thisleaplim;
1450 int writetype[TZ_MAX_TIMES1200];
1451 int typemap[TZ_MAX_TYPES256];
1452 int thistypecnt;
1453 char thischars[TZ_MAX_CHARS50];
1454 char thischarcnt;
1455 int indmap[TZ_MAX_CHARS50];
1456
1457 if (pass == 1) {
1458 thistimei = timei32;
1459 thistimecnt = timecnt32;
1460 thisleapi = leapi32;
1461 thisleapcnt = leapcnt32;
1462 } else {
1463 thistimei = 0;
1464 thistimecnt = timecnt;
1465 thisleapi = 0;
1466 thisleapcnt = leapcnt;
1467 }
1468 thistimelim = thistimei + thistimecnt;
1469 thisleaplim = thisleapi + thisleapcnt;
1470 for (i = 0; i < typecnt; ++i)
1471 writetype[i] = thistimecnt == timecnt;
1472 if (thistimecnt == 0) {
1473 /*
1474 ** No transition times fall in the current
1475 ** (32- or 64-bit) window.
1476 */
1477 if (typecnt != 0)
1478 writetype[typecnt - 1] = TRUE1;
1479 } else {
1480 for (i = thistimei - 1; i < thistimelim; ++i)
1481 if (i >= 0)
1482 writetype[types[i]] = TRUE1;
1483 /*
1484 ** For America/Godthab and Antarctica/Palmer
1485 */
1486 if (thistimei == 0)
1487 writetype[0] = TRUE1;
1488 }
1489#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
1490 /*
1491 ** For some pre-2011 systems: if the last-to-be-written
1492 ** standard (or daylight) type has an offset different from the
1493 ** most recently used offset,
1494 ** append an (unused) copy of the most recently used type
1495 ** (to help get global "altzone" and "timezone" variables
1496 ** set correctly).
1497 */
1498 {
1499 int mrudst, mrustd, hidst, histd, type;
1500
1501 hidst = histd = mrudst = mrustd = -1;
1502 for (i = thistimei; i < thistimelim; ++i)
1503 if (isdsts[types[i]])
1504 mrudst = types[i];
1505 else
1506 mrustd = types[i];
1507 for (i = 0; i < typecnt; ++i)
1508 if (writetype[i]) {
1509 if (isdsts[i])
1510 hidst = i;
1511 else
1512 histd = i;
1513 }
1514 if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
1515 gmtoffs[hidst] != gmtoffs[mrudst]) {
1516 isdsts[mrudst] = -1;
1517 type = addtype(gmtoffs[mrudst],
1518 &chars[abbrinds[mrudst]],
1519 TRUE1, ttisstds[mrudst],
1520 ttisgmts[mrudst]);
1521 isdsts[mrudst] = TRUE1;
1522 writetype[type] = TRUE1;
1523 }
1524 if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
1525 gmtoffs[histd] != gmtoffs[mrustd]) {
1526 isdsts[mrustd] = -1;
1527 type = addtype(gmtoffs[mrustd],
1528 &chars[abbrinds[mrustd]],
1529 FALSE0, ttisstds[mrustd],
1530 ttisgmts[mrustd]);
1531 isdsts[mrustd] = FALSE0;
1532 writetype[type] = TRUE1;
1533 }
1534 }
1535#endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
1536 thistypecnt = 0;
1537 for (i = 0; i < typecnt; ++i)
1538 typemap[i] = writetype[i] ? thistypecnt++ : -1;
1539 for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
1540 indmap[i] = -1;
1541 thischarcnt = 0;
1542 for (i = 0; i < typecnt; ++i) {
1543 char *thisabbr;
1544
1545 if (!writetype[i])
1546 continue;
1547 if (indmap[abbrinds[i]] >= 0)
1548 continue;
1549 thisabbr = &chars[abbrinds[i]];
1550 for (j = 0; j < thischarcnt; ++j)
1551 if (strcmp(&thischars[j], thisabbr) == 0)
1552 break;
1553 if (j == thischarcnt) {
1554 strlcpy(&thischars[(int) thischarcnt],
1555 thisabbr, sizeof(thischars) - thischarcnt);
1556 thischarcnt += strlen(thisabbr) + 1;
1557 }
1558 indmap[abbrinds[i]] = j;
1559 }
1560#define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
1561 tzh = tzh0;
1562 strncpy(tzh.tzh_magic, TZ_MAGIC"TZif", sizeof tzh.tzh_magic);
1563 tzh.tzh_version[0] = ZIC_VERSION'2';
1564 convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt);
1565 convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt);
1566 convert(eitol(thisleapcnt), tzh.tzh_leapcnt);
1567 convert(eitol(thistimecnt), tzh.tzh_timecnt);
1568 convert(eitol(thistypecnt), tzh.tzh_typecnt);
1569 convert(eitol(thischarcnt), tzh.tzh_charcnt);
1570 DO(tzh_magic);
1571 DO(tzh_version);
1572 DO(tzh_reserved);
1573 DO(tzh_ttisgmtcnt);
1574 DO(tzh_ttisstdcnt);
1575 DO(tzh_leapcnt);
1576 DO(tzh_timecnt);
1577 DO(tzh_typecnt);
1578 DO(tzh_charcnt);
1579#undef DO
1580 for (i = thistimei; i < thistimelim; ++i)
1581 if (pass == 1)
1582 puttzcode((long) ats[i], fp);
1583 else
1584 puttzcode64(ats[i], fp);
1585 for (i = thistimei; i < thistimelim; ++i) {
1586 unsigned char uc;
1587
1588 uc = typemap[types[i]];
1589 fwrite(&uc, sizeof uc, 1, fp);
1590 }
1591 for (i = 0; i < typecnt; ++i)
1592 if (writetype[i]) {
1593 puttzcode(gmtoffs[i], fp);
1594 putc(isdsts[i], fp)(!__isthreaded ? __sputc(isdsts[i], fp) : (putc)(isdsts[i], fp
))
;
1595 putc((unsigned char)indmap[abbrinds[i]], fp)(!__isthreaded ? __sputc((unsigned char)indmap[abbrinds[i]], fp
) : (putc)((unsigned char)indmap[abbrinds[i]], fp))
;
1596 }
1597 if (thischarcnt != 0)
1598 fwrite(thischars, sizeof thischars[0], thischarcnt, fp);
1599 for (i = thisleapi; i < thisleaplim; ++i) {
1600 zic_t todo;
1601
1602 if (roll[i]) {
1603 if (timecnt == 0 || trans[i] < ats[0]) {
1604 j = 0;
1605 while (isdsts[j])
1606 if (++j >= typecnt) {
1607 j = 0;
1608 break;
1609 }
1610 } else {
1611 j = 1;
1612 while (j < timecnt &&
1613 trans[i] >= ats[j])
1614 ++j;
1615 j = types[j - 1];
1616 }
1617 todo = tadd(trans[i], -gmtoffs[j]);
1618 } else
1619 todo = trans[i];
1620 if (pass == 1)
1621 puttzcode((long) todo, fp);
1622 else
1623 puttzcode64(todo, fp);
1624 puttzcode(corr[i], fp);
1625 }
1626 for (i = 0; i < typecnt; ++i)
1627 if (writetype[i])
1628 putc(ttisstds[i], fp)(!__isthreaded ? __sputc(ttisstds[i], fp) : (putc)(ttisstds[i
], fp))
;
1629 for (i = 0; i < typecnt; ++i)
1630 if (writetype[i])
1631 putc(ttisgmts[i], fp)(!__isthreaded ? __sputc(ttisgmts[i], fp) : (putc)(ttisgmts[i
], fp))
;
1632 }
1633 fprintf(fp, "\n%s\n", string);
1634 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
|| fclose(fp))
1635 errx(1, "Error writing %s", fullname);
1636}
1637
1638static void
1639doabbr(char *abbr, size_t size, const char *format, const char *letters,
1640 int isdst, int doquotes)
1641{
1642 char *cp, *slashp;
1643 int len;
1644
1645 slashp = strchr(format, '/');
1646 if (slashp == NULL((void *)0)) {
1647 if (letters == NULL((void *)0))
1648 strlcpy(abbr, format, size);
1649 else
1650 snprintf(abbr, size, format, letters);
1651 } else if (isdst) {
1652 strlcpy(abbr, slashp + 1, size);
1653 } else {
1654 if (slashp - format + 1 < size)
1655 size = slashp - format + 1;
1656 strlcpy(abbr, format, size);
1657 }
1658 if (!doquotes)
1659 return;
1660 for (cp = abbr; *cp != '\0'; ++cp)
1661 if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL((void *)0) &&
1662 strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL((void *)0))
1663 break;
1664 len = strlen(abbr);
1665 if (len > 0 && *cp == '\0')
1666 return;
1667 abbr[len + 2] = '\0';
1668 abbr[len + 1] = '>';
1669 for ( ; len > 0; --len)
1670 abbr[len] = abbr[len - 1];
1671 abbr[0] = '<';
1672}
1673
1674static void
1675updateminmax(int x)
1676{
1677 if (min_year > x)
1678 min_year = x;
1679 if (max_year < x)
1680 max_year = x;
1681}
1682
1683static int
1684stringoffset(char *result, size_t size, long offset)
1685{
1686 int hours, minutes, seconds;
1687 char *ep;
1688
1689 result[0] = '\0';
1690 if (offset < 0) {
1691 strlcpy(result, "-", size);
1692 offset = -offset;
1693 }
1694 seconds = offset % SECSPERMIN60;
1695 offset /= SECSPERMIN60;
1696 minutes = offset % MINSPERHOUR60;
1697 offset /= MINSPERHOUR60;
1698 hours = offset;
1699 if (hours >= HOURSPERDAY24) {
1700 result[0] = '\0';
1701 return -1;
1702 }
1703 ep = end(result, size)(memchr((result), '\0', (size)));
1704 snprintf(ep, size - (ep - result), "%d", hours);
1705 if (minutes != 0 || seconds != 0) {
1706 ep = end(result, size)(memchr((result), '\0', (size)));
1707 snprintf(ep, size - (ep - result), ":%02d", minutes);
1708 if (seconds != 0) {
1709 ep = end(result, size)(memchr((result), '\0', (size)));
1710 snprintf(ep, size - (ep - result), ":%02d", seconds);
1711 }
1712 }
1713 return 0;
1714}
1715
1716static int
1717stringrule(char *result, size_t size, const struct rule *rp, long dstoff, long gmtoff)
1718{
1719 long tod;
1720 char *ep;
1721
1722 ep = end(result, size)(memchr((result), '\0', (size)));
1723 size -= ep - result;
1724 result = ep;
1725 if (rp->r_dycode == DC_DOM0) {
1726 int month, total;
1727
1728 if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY1)
1729 return -1;
1730 total = 0;
1731 for (month = 0; month < rp->r_month; ++month)
1732 total += len_months[0][month];
1733 snprintf(result, size, "J%d", total + rp->r_dayofmonth);
1734 } else {
1735 int week;
1736
1737 if (rp->r_dycode == DC_DOWGEQ1) {
1738 if ((rp->r_dayofmonth % DAYSPERWEEK7) != 1)
1739 return -1;
1740 week = 1 + rp->r_dayofmonth / DAYSPERWEEK7;
1741 } else if (rp->r_dycode == DC_DOWLEQ2) {
1742 if (rp->r_dayofmonth == len_months[1][rp->r_month])
1743 week = 5;
1744 else {
1745 if ((rp->r_dayofmonth % DAYSPERWEEK7) != 0)
1746 return -1;
1747 week = rp->r_dayofmonth / DAYSPERWEEK7;
1748 }
1749 } else
1750 return -1; /* "cannot happen" */
1751 snprintf(result, size, "M%d.%d.%d",
1752 rp->r_month + 1, week, rp->r_wday);
1753 }
1754 tod = rp->r_tod;
1755 if (rp->r_todisgmt)
1756 tod += gmtoff;
1757 if (rp->r_todisstd && rp->r_stdoff == 0)
1758 tod += dstoff;
1759 if (tod < 0) {
1760 result[0] = '\0';
1761 return -1;
1762 }
1763 if (tod != 2 * SECSPERMIN60 * MINSPERHOUR60) {
1764 strlcat(result, "/", size);
1765 ep = end(result, size)(memchr((result), '\0', (size)));
1766 if (stringoffset(ep, size - (ep - result), tod) != 0)
1767 return -1;
1768 }
1769 return 0;
1770}
1771
1772static void
1773stringzone(char *result, size_t size, const struct zone *zpfirst, int zonecount)
1774{
1775 const struct zone *zp;
1776 struct rule *rp, *stdrp, *dstrp;
1777 int i;
1778 const char *abbrvar;
1779 char *ep;
1780
1781 result[0] = '\0';
1782 zp = zpfirst + zonecount - 1;
1783 stdrp = dstrp = NULL((void *)0);
1784 for (i = 0; i < zp->z_nrules; ++i) {
1785 rp = &zp->z_rules[i];
1786 if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX2147483647)
1787 continue;
1788 if (rp->r_stdoff == 0) {
1789 if (stdrp == NULL((void *)0))
1790 stdrp = rp;
1791 else
1792 return;
1793 } else {
1794 if (dstrp == NULL((void *)0))
1795 dstrp = rp;
1796 else
1797 return;
1798 }
1799 }
1800 if (stdrp == NULL((void *)0) && dstrp == NULL((void *)0)) {
1801 /*
1802 ** There are no rules running through "max".
1803 ** Let's find the latest rule.
1804 */
1805 for (i = 0; i < zp->z_nrules; ++i) {
1806 rp = &zp->z_rules[i];
1807 if (stdrp == NULL((void *)0) || rp->r_hiyear > stdrp->r_hiyear ||
1808 (rp->r_hiyear == stdrp->r_hiyear &&
1809 rp->r_month > stdrp->r_month))
1810 stdrp = rp;
1811 }
1812 if (stdrp != NULL((void *)0) && stdrp->r_stdoff != 0)
1813 return; /* We end up in DST (a POSIX no-no). */
1814 /*
1815 ** Horrid special case: if year is 2037,
1816 ** presume this is a zone handled on a year-by-year basis;
1817 ** do not try to apply a rule to the zone.
1818 */
1819 if (stdrp != NULL((void *)0) && stdrp->r_hiyear == 2037)
1820 return;
1821 }
1822 if (stdrp == NULL((void *)0) && (zp->z_nrules != 0 || zp->z_stdoff != 0))
1823 return;
1824 abbrvar = (stdrp == NULL((void *)0)) ? "" : stdrp->r_abbrvar;
1825 doabbr(result, size, zp->z_format, abbrvar, FALSE0, TRUE1);
1826 ep = end(result, size)(memchr((result), '\0', (size)));
1827 if (stringoffset(ep, size - (ep - result), -zp->z_gmtoff) != 0) {
1828 result[0] = '\0';
1829 return;
1830 }
1831 if (dstrp == NULL((void *)0))
1832 return;
1833 ep = end(result, size)(memchr((result), '\0', (size)));
1834 doabbr(ep, size - (ep - result), zp->z_format, dstrp->r_abbrvar, TRUE1, TRUE1);
1835 if (dstrp->r_stdoff != SECSPERMIN60 * MINSPERHOUR60) {
1836 ep = end(result, size)(memchr((result), '\0', (size)));
1837 if (stringoffset(ep, size - (ep - result),
1838 -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) {
1839 result[0] = '\0';
1840 return;
1841 }
1842 }
1843 strlcat(result, ",", size);
1844 if (stringrule(result, size, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
1845 result[0] = '\0';
1846 return;
1847 }
1848 strlcat(result, ",", size);
1849 if (stringrule(result, size, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
1850 result[0] = '\0';
1851 return;
1852 }
1853}
1854
1855static void
1856outzone(const struct zone *zpfirst, int zonecount)
1857{
1858 const struct zone *zp;
1859 struct rule *rp;
1860 int i, j, usestart, useuntil, type;
1861 zic_t starttime = 0, untiltime = 0;
1862 long gmtoff, stdoff, startoff;
1863 int year, startttisstd = FALSE0, startttisgmt = FALSE0;
1864 char *startbuf, *ab, *envvar;
1865 int max_abbr_len, max_envvar_len;
1866 int prodstic; /* all rules are min to max */
1867
1868 max_abbr_len = 2 + max_format_len + max_abbrvar_len;
1869 max_envvar_len = 2 * max_abbr_len + 5 * 9;
1870 startbuf = emalloc(max_abbr_len + 1)memcheck(malloc(max_abbr_len + 1));
1871 ab = emalloc(max_abbr_len + 1)memcheck(malloc(max_abbr_len + 1));
1872 envvar = emalloc(max_envvar_len + 1)memcheck(malloc(max_envvar_len + 1));
1873 /*
1874 ** Now. . .finally. . .generate some useful data!
1875 */
1876 timecnt = 0;
1877 typecnt = 0;
1878 charcnt = 0;
1879 prodstic = zonecount == 1;
1880 /*
1881 ** Thanks to Earl Chew
1882 ** for noting the need to unconditionally initialize startttisstd.
1883 */
1884 min_year = max_year = EPOCH_YEAR1970;
1885 if (leapseen) {
1886 updateminmax(leapminyear);
1887 updateminmax(leapmaxyear + (leapmaxyear < INT_MAX2147483647));
1888 }
1889 for (i = 0; i < zonecount; ++i) {
1890 zp = &zpfirst[i];
1891 if (i < zonecount - 1)
1892 updateminmax(zp->z_untilrule.r_loyear);
1893 for (j = 0; j < zp->z_nrules; ++j) {
1894 rp = &zp->z_rules[j];
1895 if (rp->r_lowasnum)
1896 updateminmax(rp->r_loyear);
1897 if (rp->r_hiwasnum)
1898 updateminmax(rp->r_hiyear);
1899 if (rp->r_lowasnum || rp->r_hiwasnum)
1900 prodstic = FALSE0;
1901 }
1902 }
1903 /*
1904 ** Generate lots of data if a rule can't cover all future times.
1905 */
1906 stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount);
1907 if (noise && envvar[0] == '\0') {
1908 char * wp;
1909
1910 wp = ecpyalloc("no POSIX environment variable for zone")memcheck(strdup("no POSIX environment variable for zone"));
1911 wp = ecatalloc(wp, " ");
1912 wp = ecatalloc(wp, zpfirst->z_name);
1913 warning(wp);
1914 free(wp);
1915 }
1916 if (envvar[0] == '\0') {
1917 if (min_year >= INT_MIN(-2147483647 -1) + YEARSPERREPEAT400)
1918 min_year -= YEARSPERREPEAT400;
1919 else
1920 min_year = INT_MIN(-2147483647 -1);
1921 if (max_year <= INT_MAX2147483647 - YEARSPERREPEAT400)
1922 max_year += YEARSPERREPEAT400;
1923 else
1924 max_year = INT_MAX2147483647;
1925 /*
1926 ** Regardless of any of the above,
1927 ** for a "proDSTic" zone which specifies that its rules
1928 ** always have and always will be in effect,
1929 ** we only need one cycle to define the zone.
1930 */
1931 if (prodstic) {
1932 min_year = 1900;
1933 max_year = min_year + YEARSPERREPEAT400;
1934 }
1935 }
1936 /*
1937 ** For the benefit of older systems,
1938 ** generate data from 1900 through 2037.
1939 */
1940 if (min_year > 1900)
1941 min_year = 1900;
1942 if (max_year < 2037)
1943 max_year = 2037;
1944 for (i = 0; i < zonecount; ++i) {
1945 /*
1946 ** A guess that may well be corrected later.
1947 */
1948 stdoff = 0;
1949 zp = &zpfirst[i];
1950 usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
1951 useuntil = i < (zonecount - 1);
1952 if (useuntil && zp->z_untiltime <= min_time)
1953 continue;
1954 gmtoff = zp->z_gmtoff;
1955 eat(zp->z_filename, zp->z_linenum);
1956 *startbuf = '\0';
1957 startoff = zp->z_gmtoff;
1958 if (zp->z_nrules == 0) {
1959 stdoff = zp->z_stdoff;
1960 doabbr(startbuf, max_abbr_len + 1, zp->z_format,
1961 NULL((void *)0), stdoff != 0, FALSE0);
1962 type = addtype(oadd(zp->z_gmtoff, stdoff),
1963 startbuf, stdoff != 0, startttisstd,
1964 startttisgmt);
1965 if (usestart) {
1966 addtt(starttime, type);
1967 usestart = FALSE0;
1968 } else if (stdoff != 0)
1969 addtt(min_time, type);
1970 } else for (year = min_year; year <= max_year; ++year) {
1971 if (useuntil && year > zp->z_untilrule.r_hiyear)
1972 break;
1973 /*
1974 ** Mark which rules to do in the current year.
1975 ** For those to do, calculate rpytime(rp, year);
1976 */
1977 for (j = 0; j < zp->z_nrules; ++j) {
1978 rp = &zp->z_rules[j];
1979 eats(zp->z_filename, zp->z_linenum,
1980 rp->r_filename, rp->r_linenum);
1981 rp->r_todo = year >= rp->r_loyear &&
1982 year <= rp->r_hiyear;
1983 if (rp->r_todo)
1984 rp->r_temp = rpytime(rp, year);
1985 }
1986 for ( ; ; ) {
1987 int k;
1988 zic_t jtime, ktime = 0;
1989 long offset;
1990
1991 if (useuntil) {
1992 /*
1993 ** Turn untiltime into UTC
1994 ** assuming the current gmtoff and
1995 ** stdoff values.
1996 */
1997 untiltime = zp->z_untiltime;
1998 if (!zp->z_untilrule.r_todisgmt)
1999 untiltime = tadd(untiltime,
2000 -gmtoff);
2001 if (!zp->z_untilrule.r_todisstd)
2002 untiltime = tadd(untiltime,
2003 -stdoff);
2004 }
2005 /*
2006 ** Find the rule (of those to do, if any)
2007 ** that takes effect earliest in the year.
2008 */
2009 k = -1;
2010 for (j = 0; j < zp->z_nrules; ++j) {
2011 rp = &zp->z_rules[j];
2012 if (!rp->r_todo)
2013 continue;
2014 eats(zp->z_filename, zp->z_linenum,
2015 rp->r_filename, rp->r_linenum);
2016 offset = rp->r_todisgmt ? 0 : gmtoff;
2017 if (!rp->r_todisstd)
2018 offset = oadd(offset, stdoff);
2019 jtime = rp->r_temp;
2020 if (jtime == min_time ||
2021 jtime == max_time)
2022 continue;
2023 jtime = tadd(jtime, -offset);
2024 if (k < 0 || jtime < ktime) {
2025 k = j;
2026 ktime = jtime;
2027 }
2028 }
2029 if (k < 0)
2030 break; /* go on to next year */
2031 rp = &zp->z_rules[k];
2032 rp->r_todo = FALSE0;
2033 if (useuntil && ktime >= untiltime)
2034 break;
2035 stdoff = rp->r_stdoff;
2036 if (usestart && ktime == starttime)
2037 usestart = FALSE0;
2038 if (usestart) {
2039 if (ktime < starttime) {
2040 startoff = oadd(zp->z_gmtoff,
2041 stdoff);
2042 doabbr(startbuf,
2043 max_abbr_len + 1,
2044 zp->z_format,
2045 rp->r_abbrvar,
2046 rp->r_stdoff != 0,
2047 FALSE0);
2048 continue;
2049 }
2050 if (*startbuf == '\0' &&
2051 startoff == oadd(zp->z_gmtoff,
2052 stdoff)) {
2053 doabbr(startbuf,
2054 max_abbr_len + 1,
2055 zp->z_format,
2056 rp->r_abbrvar,
2057 rp->r_stdoff != 0,
2058 FALSE0);
2059 }
2060 }
2061 eats(zp->z_filename, zp->z_linenum,
2062 rp->r_filename, rp->r_linenum);
2063 doabbr(ab, max_abbr_len + 1, zp->z_format,
2064 rp->r_abbrvar, rp->r_stdoff != 0, FALSE0);
2065 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
2066 type = addtype(offset, ab, rp->r_stdoff != 0,
2067 rp->r_todisstd, rp->r_todisgmt);
2068 addtt(ktime, type);
2069 }
2070 }
2071 if (usestart) {
2072 if (*startbuf == '\0' &&
2073 zp->z_format != NULL((void *)0) &&
2074 strchr(zp->z_format, '%') == NULL((void *)0) &&
2075 strchr(zp->z_format, '/') == NULL((void *)0))
2076 strlcpy(startbuf, zp->z_format, max_abbr_len + 1);
2077 eat(zp->z_filename, zp->z_linenum);
2078 if (*startbuf == '\0')
2079 error("can't determine time zone abbreviation to use just after until time");
2080 else
2081 addtt(starttime,
2082 addtype(startoff, startbuf,
2083 startoff != zp->z_gmtoff,
2084 startttisstd, startttisgmt));
2085 }
2086 /*
2087 ** Now we may get to set starttime for the next zone line.
2088 */
2089 if (useuntil) {
2090 startttisstd = zp->z_untilrule.r_todisstd;
2091 startttisgmt = zp->z_untilrule.r_todisgmt;
2092 starttime = zp->z_untiltime;
2093 if (!startttisstd)
2094 starttime = tadd(starttime, -stdoff);
2095 if (!startttisgmt)
2096 starttime = tadd(starttime, -gmtoff);
2097 }
2098 }
2099 writezone(zpfirst->z_name, envvar);
2100 free(startbuf);
2101 free(ab);
2102 free(envvar);
2103}
2104
2105static void
2106addtt(const zic_t starttime, int type)
2107{
2108 size_t len;
2109
2110 if (starttime <= min_time ||
2111 (timecnt == 1 && attypes[0].at < min_time)) {
2112 gmtoffs[0] = gmtoffs[type];
2113 isdsts[0] = isdsts[type];
2114 ttisstds[0] = ttisstds[type];
2115 ttisgmts[0] = ttisgmts[type];
2116 if (abbrinds[type] != 0) {
2117 len = strlen(&chars[abbrinds[type]]) + 1;
2118 memmove(chars, &chars[abbrinds[type]], len);
2119 }
2120 abbrinds[0] = 0;
2121 charcnt = strlen(chars) + 1;
2122 typecnt = 1;
2123 timecnt = 0;
2124 type = 0;
2125 }
2126 if (timecnt >= TZ_MAX_TIMES1200) {
2127 error("too many transitions?!");
2128 exit(EXIT_FAILURE1);
2129 }
2130 attypes[timecnt].at = starttime;
2131 attypes[timecnt].type = type;
2132 ++timecnt;
2133}
2134
2135static int
2136addtype(long gmtoff, const char *abbr, int isdst, int ttisstd, int ttisgmt)
2137{
2138 int i, j;
2139
2140 if (isdst != TRUE1 && isdst != FALSE0) {
2141 error("internal error - addtype called with bad isdst");
2142 exit(EXIT_FAILURE1);
2143 }
2144 if (ttisstd != TRUE1 && ttisstd != FALSE0) {
2145 error("internal error - addtype called with bad ttisstd");
2146 exit(EXIT_FAILURE1);
2147 }
2148 if (ttisgmt != TRUE1 && ttisgmt != FALSE0) {
2149 error("internal error - addtype called with bad ttisgmt");
2150 exit(EXIT_FAILURE1);
2151 }
2152 /*
2153 ** See if there's already an entry for this zone type.
2154 ** If so, just return its index.
2155 */
2156 for (i = 0; i < typecnt; ++i) {
2157 if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
2158 strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
2159 ttisstd == ttisstds[i] &&
2160 ttisgmt == ttisgmts[i])
2161 return i;
2162 }
2163 /*
2164 ** There isn't one; add a new one, unless there are already too
2165 ** many.
2166 */
2167 if (typecnt >= TZ_MAX_TYPES256) {
2168 error("too many local time types");
2169 exit(EXIT_FAILURE1);
2170 }
2171 if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) {
2172 error("UTC offset out of range");
2173 exit(EXIT_FAILURE1);
2174 }
2175 gmtoffs[i] = gmtoff;
2176 isdsts[i] = isdst;
2177 ttisstds[i] = ttisstd;
2178 ttisgmts[i] = ttisgmt;
2179
2180 for (j = 0; j < charcnt; ++j)
2181 if (strcmp(&chars[j], abbr) == 0)
2182 break;
2183 if (j == charcnt)
2184 newabbr(abbr);
2185 abbrinds[i] = j;
2186 ++typecnt;
2187 return i;
2188}
2189
2190static void
2191leapadd(zic_t t, int positive, int rolling, int count)
2192{
2193 int i, j;
2194
2195 if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS50) {
2196 error("too many leap seconds");
2197 exit(EXIT_FAILURE1);
2198 }
2199 for (i = 0; i < leapcnt; ++i)
2200 if (t <= trans[i]) {
2201 if (t == trans[i]) {
2202 error("repeated leap second moment");
2203 exit(EXIT_FAILURE1);
2204 }
2205 break;
2206 }
2207 do {
2208 for (j = leapcnt; j > i; --j) {
2209 trans[j] = trans[j - 1];
2210 corr[j] = corr[j - 1];
2211 roll[j] = roll[j - 1];
2212 }
2213 trans[i] = t;
2214 corr[i] = positive ? 1L : eitol(-count);
2215 roll[i] = rolling;
2216 ++leapcnt;
2217 } while (positive && --count != 0);
2218}
2219
2220static void
2221adjleap(void)
2222{
2223 int i;
2224 long last = 0;
2225
2226 /*
2227 ** propagate leap seconds forward
2228 */
2229 for (i = 0; i < leapcnt; ++i) {
2230 trans[i] = tadd(trans[i], last);
2231 last = corr[i] += last;
2232 }
2233}
2234
2235/* this function is not strncasecmp */
2236static int
2237itsabbr(const char *sabbr, const char *sword)
2238{
2239 const unsigned char *abbr = sabbr;
2240 const unsigned char *word = sword;
2241
2242 if (tolower(*abbr) != tolower(*word))
2243 return FALSE0;
2244 while (*++abbr != '\0')
2245 do {
2246 ++word;
2247 if (*word == '\0')
2248 return FALSE0;
2249 } while (tolower(*word) != tolower(*abbr));
2250 return TRUE1;
2251}
2252
2253static const struct lookup *
2254byword(const char *word, const struct lookup *table)
2255{
2256 const struct lookup *foundlp;
2257 const struct lookup *lp;
2258
2259 if (word == NULL((void *)0) || table == NULL((void *)0))
2260 return NULL((void *)0);
2261 /*
2262 ** Look for exact match.
2263 */
2264 for (lp = table; lp->l_word != NULL((void *)0); ++lp)
2265 if (strcasecmp(word, lp->l_word) == 0)
2266 return lp;
2267 /*
2268 ** Look for inexact match.
2269 */
2270 foundlp = NULL((void *)0);
2271 for (lp = table; lp->l_word != NULL((void *)0); ++lp)
2272 if (itsabbr(word, lp->l_word)) {
2273 if (foundlp == NULL((void *)0))
2274 foundlp = lp;
2275 else
2276 return NULL((void *)0); /* multiple inexact matches */
2277 }
2278 return foundlp;
2279}
2280
2281static char **
2282getfields(char *cp)
2283{
2284 char *dp;
2285 char **array;
2286 int nsubs;
2287
2288 if (cp == NULL((void *)0))
2289 return NULL((void *)0);
2290 array = ereallocarray(NULL, strlen(cp) + 1, sizeof *array)memcheck(reallocarray(((void *)0), strlen(cp) + 1, sizeof *array
))
;
2291 nsubs = 0;
2292 for ( ; ; ) {
2293 while (isascii((unsigned char)*cp) &&
2294 isspace((unsigned char)*cp))
2295 ++cp;
2296 if (*cp == '\0' || *cp == '#')
2297 break;
2298 array[nsubs++] = dp = cp;
2299 do {
2300 if ((*dp = *cp++) != '"') {
2301 ++dp;
2302 } else {
2303 while ((*dp = *cp++) != '"') {
2304 if (*dp != '\0')
2305 ++dp;
2306 else {
2307 error("Odd number of quotation marks");
2308 exit(EXIT_FAILURE1);
2309 }
2310 }
2311 }
2312 } while (*cp != '\0' && *cp != '#' &&
2313 (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)));
2314 if (isascii((unsigned char)*cp) && isspace((unsigned char)*cp))
2315 ++cp;
2316 *dp = '\0';
2317 }
2318 array[nsubs] = NULL((void *)0);
2319 return array;
2320}
2321
2322static long
2323oadd(long t1, long t2)
2324{
2325 long t = t1 + t2;
2326
2327 if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
2328 error("time overflow");
2329 exit(EXIT_FAILURE1);
2330 }
2331 return t;
2332}
2333
2334static zic_t
2335tadd(zic_t t1, long t2)
2336{
2337 zic_t t;
2338
2339 if (t1 == max_time && t2 > 0)
2340 return max_time;
2341 if (t1 == min_time && t2 < 0)
2342 return min_time;
2343 t = t1 + t2;
2344 if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
2345 error("time overflow");
2346 exit(EXIT_FAILURE1);
2347 }
2348 return t;
2349}
2350
2351/*
2352** Given a rule, and a year, compute the date - in seconds since January 1,
2353** 1970, 00:00 LOCAL time - in that year that the rule refers to.
2354*/
2355static zic_t
2356rpytime(const struct rule *rp, int wantedy)
2357{
2358 int y, m, i;
2359 long dayoff; /* with a nod to Margaret O. */
2360 zic_t t;
2361
2362 if (wantedy == INT_MIN(-2147483647 -1))
2363 return min_time;
2364 if (wantedy == INT_MAX2147483647)
2365 return max_time;
2366 dayoff = 0;
2367 m = TM_JANUARY0;
2368 y = EPOCH_YEAR1970;
2369 while (wantedy != y) {
2370 if (wantedy > y) {
2371 i = len_years[isleap(y)(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) ==
0))
];
2372 ++y;
2373 } else {
2374 --y;
2375 i = -len_years[isleap(y)(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) ==
0))
];
2376 }
2377 dayoff = oadd(dayoff, eitol(i));
2378 }
2379 while (m != rp->r_month) {
2380 i = len_months[isleap(y)(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) ==
0))
][m];
2381 dayoff = oadd(dayoff, eitol(i));
2382 ++m;
2383 }
2384 i = rp->r_dayofmonth;
2385 if (m == TM_FEBRUARY1 && i == 29 && !isleap(y)(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) ==
0))
) {
2386 if (rp->r_dycode == DC_DOWLEQ2)
2387 --i;
2388 else {
2389 error("use of 2/29 in non leap-year");
2390 exit(EXIT_FAILURE1);
2391 }
2392 }
2393 --i;
2394 dayoff = oadd(dayoff, eitol(i));
2395 if (rp->r_dycode == DC_DOWGEQ1 || rp->r_dycode == DC_DOWLEQ2) {
2396 long wday;
2397
2398#define LDAYSPERWEEK((long) 7) ((long) DAYSPERWEEK7)
2399 wday = eitol(EPOCH_WDAY4);
2400 /*
2401 ** Don't trust mod of negative numbers.
2402 */
2403 if (dayoff >= 0)
2404 wday = (wday + dayoff) % LDAYSPERWEEK((long) 7);
2405 else {
2406 wday -= ((-dayoff) % LDAYSPERWEEK((long) 7));
2407 if (wday < 0)
2408 wday += LDAYSPERWEEK((long) 7);
2409 }
2410 while (wday != eitol(rp->r_wday))
2411 if (rp->r_dycode == DC_DOWGEQ1) {
2412 dayoff = oadd(dayoff, 1);
2413 if (++wday >= LDAYSPERWEEK((long) 7))
2414 wday = 0;
2415 ++i;
2416 } else {
2417 dayoff = oadd(dayoff, -1);
2418 if (--wday < 0)
2419 wday = LDAYSPERWEEK((long) 7) - 1;
2420 --i;
2421 }
2422 }
2423 if (dayoff < min_time / SECSPERDAY((long) (60 * 60) * 24))
2424 return min_time;
2425 if (dayoff > max_time / SECSPERDAY((long) (60 * 60) * 24))
2426 return max_time;
2427 t = (zic_t) dayoff * SECSPERDAY((long) (60 * 60) * 24);
2428 return tadd(t, rp->r_tod);
2429}
2430
2431static void
2432newabbr(const char *string)
2433{
2434 int i;
2435
2436 if (strcmp(string, GRANDPARENTED"Local time zone must be set--see zic manual page") != 0) {
2437 const char * cp;
2438 char * wp;
2439
2440 cp = string;
2441 wp = NULL((void *)0);
2442 while (isascii((unsigned char)*cp) &&
2443 (isalnum((unsigned char)*cp) || *cp == '-' || *cp == '+'))
2444 ++cp;
2445 if (noise && cp - string > 3)
2446 wp = "time zone abbreviation has more than 3 characters";
2447 if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN6)
2448 wp = "time zone abbreviation has too many characters";
2449 if (*cp != '\0')
2450 wp = "time zone abbreviation differs from POSIX standard";
2451 if (wp != NULL((void *)0)) {
2452 wp = ecpyalloc(wp)memcheck(strdup(wp));
2453 wp = ecatalloc(wp, " (");
2454 wp = ecatalloc(wp, string);
2455 wp = ecatalloc(wp, ")");
2456 warning(wp);
2457 free(wp);
2458 }
2459 }
2460 i = strlen(string) + 1;
2461 if (charcnt + i > TZ_MAX_CHARS50) {
2462 error("too many, or too long, time zone abbreviations");
2463 exit(EXIT_FAILURE1);
2464 }
2465 strlcpy(&chars[charcnt], string, sizeof(chars) - charcnt);
2466 charcnt += eitol(i);
2467}
2468
2469static int
2470mkdirs(char *argname)
2471{
2472 char * name;
2473 char * cp;
2474
2475 if (argname == NULL((void *)0) || *argname == '\0')
2476 return 0;
2477 cp = name = ecpyalloc(argname)memcheck(strdup(argname));
2478 while ((cp = strchr(cp + 1, '/')) != 0) {
2479 *cp = '\0';
2480 if (!itsdir(name)) {
2481 /*
2482 ** It doesn't seem to exist, so we try to create it.
2483 ** Creation may fail because of the directory being
2484 ** created by some other multiprocessor, so we get
2485 ** to do extra checking.
2486 */
2487 if (mkdir(name, MKDIR_UMASK(0000400|0000200|0000100|0000040|0000010|0000004|0000001)) != 0) {
2488 const char *e = strerror(errno(*__errno()));
2489
2490 if (errno(*__errno()) != EEXIST17 || !itsdir(name)) {
2491 fprintf(stderr(&__sF[2]),
2492 "%s: Can't create directory %s: %s\n",
2493 __progname, name, e);
2494 free(name);
2495 return -1;
2496 }
2497 }
2498 }
2499 *cp = '/';
2500 }
2501 free(name);
2502 return 0;
2503}
2504
2505static long
2506eitol(int i)
2507{
2508 long l = i;
2509
2510 if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0))
2511 errx(1, "%d did not sign extend correctly", i);
2512 return l;
2513}