Bug Summary

File:src/usr.sbin/zic/zic.c
Warning:line 1420, column 27
1st function call argument is an uninitialized 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
Assuming 'i' is < 'timecnt'
19
Loop condition is true. Entering loop body
22
Assuming 'i' is >= 'timecnt'
23
Loop condition is false. Execution continues on line 1416
1406 j = leapcnt;
1407 while (--j >= 0)
13
Assuming the condition is true
14
Loop condition is true. Entering loop body
20
Assuming the condition is false
21
Loop condition is false. Execution continues on line 1405
1408 if (ats[i] > trans[j] - corr[j]) {
15
Assuming the condition is true
16
Taking true branch
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
23.1
'timecnt32' is > 0
> 0 && !is32(ats[timecnt32 - 1]))
24
1st function call argument is an uninitialized value
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}