PostgreSQL Source Code  git master
zic.c
Go to the documentation of this file.
1 /* Compile .zi time zone data into TZif binary files. */
2 
3 /*
4  * This file is in the public domain, so clarified as of
5  * 2006-07-17 by Arthur David Olson.
6  *
7  * IDENTIFICATION
8  * src/timezone/zic.c
9  */
10 
11 #include "postgres_fe.h"
12 
13 #include <fcntl.h>
14 #include <sys/stat.h>
15 #include <time.h>
16 
17 #include "pg_getopt.h"
18 
19 #include "private.h"
20 #include "tzfile.h"
21 
22 #define ZIC_VERSION_PRE_2013 '2'
23 #define ZIC_VERSION '3'
24 
25 typedef int64 zic_t;
26 #define ZIC_MIN PG_INT64_MIN
27 #define ZIC_MAX PG_INT64_MAX
28 
29 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
30 #define ZIC_MAX_ABBR_LEN_WO_WARN 6
31 #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
32 
33 #ifndef WIN32
34 #ifdef S_IRUSR
35 #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
36 #else
37 #define MKDIR_UMASK 0755
38 #endif
39 #endif
40 /* Port to native MS-Windows and to ancient UNIX. */
41 #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT
42 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
43 #endif
44 
45 /* The maximum ptrdiff_t value, for pre-C99 platforms. */
46 #ifndef PTRDIFF_MAX
47 static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
48 #endif
49 
50 /*
51  * The type for line numbers. In Postgres, use %d to format them; upstream
52  * uses PRIdMAX but we prefer not to rely on that, not least because it
53  * results in platform-dependent strings to be translated.
54  */
55 typedef int lineno_t;
56 
57 struct rule
58 {
59  const char *r_filename;
60  lineno_t r_linenum;
61  const char *r_name;
62 
63  zic_t r_loyear; /* for example, 1986 */
64  zic_t r_hiyear; /* for example, 1986 */
65  bool r_lowasnum;
66  bool r_hiwasnum;
67 
68  int r_month; /* 0..11 */
69 
70  int r_dycode; /* see below */
72  int r_wday;
73 
74  zic_t r_tod; /* time from midnight */
75  bool r_todisstd; /* is r_tod standard time? */
76  bool r_todisut; /* is r_tod UT? */
77  bool r_isdst; /* is this daylight saving time? */
78  zic_t r_save; /* offset from standard time */
79  const char *r_abbrvar; /* variable part of abbreviation */
80 
81  bool r_todo; /* a rule to do (used in outzone) */
82  zic_t r_temp; /* used in outzone */
83 };
84 
85 /*
86  * r_dycode r_dayofmonth r_wday
87  */
88 
89 #define DC_DOM 0 /* 1..31 */ /* unused */
90 #define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */
91 #define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */
92 
93 struct zone
94 {
95  const char *z_filename;
96  lineno_t z_linenum;
97 
98  const char *z_name;
100  char *z_rule;
101  const char *z_format;
103 
104  bool z_isdst;
106 
107  struct rule *z_rules;
108  ptrdiff_t z_nrules;
109 
110  struct rule z_untilrule;
112 };
113 
114 extern int link(const char *target, const char *linkname);
115 #ifndef AT_SYMLINK_FOLLOW
116 #define linkat(targetdir, target, linknamedir, linkname, flag) \
117  (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
118 #endif
119 
120 static void memory_exhausted(const char *msg) pg_attribute_noreturn();
121 static void verror(const char *string, va_list args) pg_attribute_printf(1, 0);
122 static void error(const char *string,...) pg_attribute_printf(1, 2);
123 static void warning(const char *string,...) pg_attribute_printf(1, 2);
124 static void usage(FILE *stream, int status) pg_attribute_noreturn();
125 static void addtt(zic_t starttime, int type);
126 static int addtype(zic_t, char const *, bool, bool, bool);
127 static void leapadd(zic_t, int, int);
128 static void adjleap(void);
129 static void associate(void);
130 static void dolink(const char *, const char *, bool);
131 static char **getfields(char *buf);
132 static zic_t gethms(const char *string, const char *errstring);
133 static zic_t getsave(char *, bool *);
134 static void inexpires(char **, int);
135 static void infile(const char *filename);
136 static void inleap(char **fields, int nfields);
137 static void inlink(char **fields, int nfields);
138 static void inrule(char **fields, int nfields);
139 static bool inzcont(char **fields, int nfields);
140 static bool inzone(char **fields, int nfields);
141 static bool inzsub(char **, int, bool);
142 static bool itsdir(char const *);
143 static bool itssymlink(char const *);
144 static bool is_alpha(char a);
145 static char lowerit(char);
146 static void mkdirs(char const *, bool);
147 static void newabbr(const char *abbr);
148 static zic_t oadd(zic_t t1, zic_t t2);
149 static void outzone(const struct zone *zp, ptrdiff_t ntzones);
150 static zic_t rpytime(const struct rule *rp, zic_t wantedy);
151 static void rulesub(struct rule *rp,
152  const char *loyearp, const char *hiyearp,
153  const char *typep, const char *monthp,
154  const char *dayp, const char *timep);
155 static zic_t tadd(zic_t t1, zic_t t2);
156 
157 /* Bound on length of what %z can expand to. */
158 enum
159 {
160 PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
161 
162 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
163  TZif files whose POSIX-TZ-style strings contain '<'; see
164  QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
165  workaround will no longer be needed when Qt 5.6.1 and earlier are
166  obsolete, say in the year 2021. */
167 #ifndef WORK_AROUND_QTBUG_53071
168 enum
169 {
171 #endif
172 
173 static int charcnt;
174 static bool errors;
175 static bool warnings;
176 static const char *filename;
177 static int leapcnt;
178 static bool leapseen;
181 static lineno_t linenum;
183 static int max_format_len;
186 static bool noise;
187 static bool print_abbrevs;
189 static const char *rfilename;
190 static lineno_t rlinenum;
191 static const char *progname;
192 static ptrdiff_t timecnt;
193 static ptrdiff_t timecnt_alloc;
194 static int typecnt;
195 
196 /*
197  * Line codes.
198  */
199 
200 #define LC_RULE 0
201 #define LC_ZONE 1
202 #define LC_LINK 2
203 #define LC_LEAP 3
204 #define LC_EXPIRES 4
205 
206 /*
207  * Which fields are which on a Zone line.
208  */
209 
210 #define ZF_NAME 1
211 #define ZF_STDOFF 2
212 #define ZF_RULE 3
213 #define ZF_FORMAT 4
214 #define ZF_TILYEAR 5
215 #define ZF_TILMONTH 6
216 #define ZF_TILDAY 7
217 #define ZF_TILTIME 8
218 #define ZONE_MINFIELDS 5
219 #define ZONE_MAXFIELDS 9
220 
221 /*
222  * Which fields are which on a Zone continuation line.
223  */
224 
225 #define ZFC_STDOFF 0
226 #define ZFC_RULE 1
227 #define ZFC_FORMAT 2
228 #define ZFC_TILYEAR 3
229 #define ZFC_TILMONTH 4
230 #define ZFC_TILDAY 5
231 #define ZFC_TILTIME 6
232 #define ZONEC_MINFIELDS 3
233 #define ZONEC_MAXFIELDS 7
234 
235 /*
236  * Which files are which on a Rule line.
237  */
238 
239 #define RF_NAME 1
240 #define RF_LOYEAR 2
241 #define RF_HIYEAR 3
242 #define RF_COMMAND 4
243 #define RF_MONTH 5
244 #define RF_DAY 6
245 #define RF_TOD 7
246 #define RF_SAVE 8
247 #define RF_ABBRVAR 9
248 #define RULE_FIELDS 10
249 
250 /*
251  * Which fields are which on a Link line.
252  */
253 
254 #define LF_TARGET 1
255 #define LF_LINKNAME 2
256 #define LINK_FIELDS 3
257 
258 /*
259  * Which fields are which on a Leap line.
260  */
261 
262 #define LP_YEAR 1
263 #define LP_MONTH 2
264 #define LP_DAY 3
265 #define LP_TIME 4
266 #define LP_CORR 5
267 #define LP_ROLL 6
268 #define LEAP_FIELDS 7
269 
270 /* Expires lines are like Leap lines, except without CORR and ROLL fields. */
271 #define EXPIRES_FIELDS 5
272 
273 /*
274  * Year synonyms.
275  */
276 
277 #define YR_MINIMUM 0
278 #define YR_MAXIMUM 1
279 #define YR_ONLY 2
280 
281 static struct rule *rules;
282 static ptrdiff_t nrules; /* number of rules */
283 static ptrdiff_t nrules_alloc;
284 
285 static struct zone *zones;
286 static ptrdiff_t nzones; /* number of zones */
287 static ptrdiff_t nzones_alloc;
288 
289 struct link
290 {
291  const char *l_filename;
292  lineno_t l_linenum;
293  const char *l_target;
294  const char *l_linkname;
295 };
296 
297 static struct link *links;
298 static ptrdiff_t nlinks;
299 static ptrdiff_t nlinks_alloc;
300 
301 struct lookup
302 {
303  const char *l_word;
304  const int l_value;
305 };
306 
307 static struct lookup const *byword(const char *string,
308  const struct lookup *lp);
309 
310 static struct lookup const zi_line_codes[] = {
311  {"Rule", LC_RULE},
312  {"Zone", LC_ZONE},
313  {"Link", LC_LINK},
314  {NULL, 0}
315 };
316 static struct lookup const leap_line_codes[] = {
317  {"Leap", LC_LEAP},
318  {"Expires", LC_EXPIRES},
319  {NULL, 0}
320 };
321 
322 static struct lookup const mon_names[] = {
323  {"January", TM_JANUARY},
324  {"February", TM_FEBRUARY},
325  {"March", TM_MARCH},
326  {"April", TM_APRIL},
327  {"May", TM_MAY},
328  {"June", TM_JUNE},
329  {"July", TM_JULY},
330  {"August", TM_AUGUST},
331  {"September", TM_SEPTEMBER},
332  {"October", TM_OCTOBER},
333  {"November", TM_NOVEMBER},
334  {"December", TM_DECEMBER},
335  {NULL, 0}
336 };
337 
338 static struct lookup const wday_names[] = {
339  {"Sunday", TM_SUNDAY},
340  {"Monday", TM_MONDAY},
341  {"Tuesday", TM_TUESDAY},
342  {"Wednesday", TM_WEDNESDAY},
343  {"Thursday", TM_THURSDAY},
344  {"Friday", TM_FRIDAY},
345  {"Saturday", TM_SATURDAY},
346  {NULL, 0}
347 };
348 
349 static struct lookup const lasts[] = {
350  {"last-Sunday", TM_SUNDAY},
351  {"last-Monday", TM_MONDAY},
352  {"last-Tuesday", TM_TUESDAY},
353  {"last-Wednesday", TM_WEDNESDAY},
354  {"last-Thursday", TM_THURSDAY},
355  {"last-Friday", TM_FRIDAY},
356  {"last-Saturday", TM_SATURDAY},
357  {NULL, 0}
358 };
359 
360 static struct lookup const begin_years[] = {
361  {"minimum", YR_MINIMUM},
362  {"maximum", YR_MAXIMUM},
363  {NULL, 0}
364 };
365 
366 static struct lookup const end_years[] = {
367  {"minimum", YR_MINIMUM},
368  {"maximum", YR_MAXIMUM},
369  {"only", YR_ONLY},
370  {NULL, 0}
371 };
372 
373 static struct lookup const leap_types[] = {
374  {"Rolling", true},
375  {"Stationary", false},
376  {NULL, 0}
377 };
378 
379 static const int len_months[2][MONSPERYEAR] = {
380  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
381  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
382 };
383 
384 static const int len_years[2] = {
386 };
387 
388 static struct attype
389 {
391  bool dontmerge;
392  unsigned char type;
393 } *attypes;
395 static char isdsts[TZ_MAX_TYPES];
396 static unsigned char desigidx[TZ_MAX_TYPES];
397 static bool ttisstds[TZ_MAX_TYPES];
398 static bool ttisuts[TZ_MAX_TYPES];
399 static char chars[TZ_MAX_CHARS];
402 static char roll[TZ_MAX_LEAPS];
403 
404 /*
405  * Memory allocation.
406  */
407 
408 static void
409 memory_exhausted(const char *msg)
410 {
411  fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
412  exit(EXIT_FAILURE);
413 }
414 
415 static size_t
416 size_product(size_t nitems, size_t itemsize)
417 {
418  if (SIZE_MAX / itemsize < nitems)
419  memory_exhausted(_("size overflow"));
420  return nitems * itemsize;
421 }
422 
423 static void *
424 memcheck(void *ptr)
425 {
426  if (ptr == NULL)
427  memory_exhausted(strerror(errno));
428  return ptr;
429 }
430 
431 static void *
432 emalloc(size_t size)
433 {
434  return memcheck(malloc(size));
435 }
436 
437 static void *
438 erealloc(void *ptr, size_t size)
439 {
440  return memcheck(realloc(ptr, size));
441 }
442 
443 static char *
444 ecpyalloc(char const *str)
445 {
446  return memcheck(strdup(str));
447 }
448 
449 static void *
450 growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
451 {
452  if (nitems < *nitems_alloc)
453  return ptr;
454  else
455  {
456  ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
457  ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
458 
459  if ((amax - 1) / 3 * 2 < *nitems_alloc)
460  memory_exhausted(_("integer overflow"));
461  *nitems_alloc += (*nitems_alloc >> 1) + 1;
462  return erealloc(ptr, size_product(*nitems_alloc, itemsize));
463  }
464 }
465 
466 /*
467  * Error handling.
468  */
469 
470 static void
471 eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
472 {
473  filename = name;
474  linenum = num;
475  rfilename = rname;
476  rlinenum = rnum;
477 }
478 
479 static void
480 eat(char const *name, lineno_t num)
481 {
482  eats(name, num, NULL, -1);
483 }
484 
485 static void
486 verror(const char *string, va_list args)
487 {
488  /*
489  * Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
490  * "*" -v on BSD systems.
491  */
492  if (filename)
493  fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
494  vfprintf(stderr, string, args);
495  if (rfilename != NULL)
496  fprintf(stderr, _(" (rule from \"%s\", line %d)"),
497  rfilename, rlinenum);
498  fprintf(stderr, "\n");
499 }
500 
501 static void
502 error(const char *string,...)
503 {
504  va_list args;
505 
506  va_start(args, string);
507  verror(string, args);
508  va_end(args);
509  errors = true;
510 }
511 
512 static void
513 warning(const char *string,...)
514 {
515  va_list args;
516 
517  fprintf(stderr, _("warning: "));
518  va_start(args, string);
519  verror(string, args);
520  va_end(args);
521  warnings = true;
522 }
523 
524 static void
525 close_file(FILE *stream, char const *dir, char const *name)
526 {
527  char const *e = (ferror(stream) ? _("I/O error")
528  : fclose(stream) != 0 ? strerror(errno) : NULL);
529 
530  if (e)
531  {
532  fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
533  dir ? dir : "", dir ? "/" : "",
534  name ? name : "", name ? ": " : "",
535  e);
536  exit(EXIT_FAILURE);
537  }
538 }
539 
540 static void
541 usage(FILE *stream, int status)
542 {
543  fprintf(stream,
544  _("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
545  "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
546  " [ -L leapseconds ] \\\n"
547  "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
548  "\t[ filename ... ]\n\n"
549  "Report bugs to %s.\n"),
550  progname, progname, PACKAGE_BUGREPORT);
551  if (status == EXIT_SUCCESS)
552  close_file(stream, NULL, NULL);
553  exit(status);
554 }
555 
556 /* Change the working directory to DIR, possibly creating DIR and its
557  ancestors. After this is done, all files are accessed with names
558  relative to DIR. */
559 static void
560 change_directory(char const *dir)
561 {
562  if (chdir(dir) != 0)
563  {
564  int chdir_errno = errno;
565 
566  if (chdir_errno == ENOENT)
567  {
568  mkdirs(dir, false);
569  chdir_errno = chdir(dir) == 0 ? 0 : errno;
570  }
571  if (chdir_errno != 0)
572  {
573  fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
574  progname, dir, strerror(chdir_errno));
575  exit(EXIT_FAILURE);
576  }
577  }
578 }
579 
580 #define TIME_T_BITS_IN_FILE 64
581 
582 /* The minimum and maximum values representable in a TZif file. */
585 
586 /* The minimum, and one less than the maximum, values specified by
587  the -r option. These default to MIN_TIME and MAX_TIME. */
590 
591 /* The time specified by an Expires line, or negative if no such line. */
592 static zic_t leapexpires = -1;
593 
594 /* The time specified by an #expires comment, or negative if no such line. */
596 
597 /* Set the time range of the output to TIMERANGE.
598  Return true if successful. */
599 static bool
601 {
602  int64 lo = min_time,
603  hi = max_time;
604  char *lo_end = timerange,
605  *hi_end;
606 
607  if (*timerange == '@')
608  {
609  errno = 0;
610  lo = strtoimax(timerange + 1, &lo_end, 10);
611  if (lo_end == timerange + 1 || (lo == PG_INT64_MAX && errno == ERANGE))
612  return false;
613  }
614  hi_end = lo_end;
615  if (lo_end[0] == '/' && lo_end[1] == '@')
616  {
617  errno = 0;
618  hi = strtoimax(lo_end + 2, &hi_end, 10);
619  if (hi_end == lo_end + 2 || hi == PG_INT64_MIN)
620  return false;
621  hi -= !(hi == PG_INT64_MAX && errno == ERANGE);
622  }
623  if (*hi_end || hi < lo || max_time < lo || hi < min_time)
624  return false;
625  lo_time = lo < min_time ? min_time : lo;
626  hi_time = max_time < hi ? max_time : hi;
627  return true;
628 }
629 
630 static const char *psxrules;
631 static const char *lcltime;
632 static const char *directory;
633 static const char *leapsec;
634 static const char *tzdefault;
635 
636 /* -1 if the TZif output file should be slim, 0 if default, 1 if the
637  output should be fat for backward compatibility. ZIC_BLOAT_DEFAULT
638  determines the default. */
639 static int bloat;
640 
641 static bool
643 {
644  return 0 <= bloat;
645 }
646 
647 #ifndef ZIC_BLOAT_DEFAULT
648 #define ZIC_BLOAT_DEFAULT "slim"
649 #endif
650 
651 int
652 main(int argc, char **argv)
653 {
654  int c,
655  k;
656  ptrdiff_t i,
657  j;
658  bool timerange_given = false;
659 
660 #ifndef WIN32
661  umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
662 #endif
663  progname = argv[0];
664  if (TYPE_BIT(zic_t) < 64)
665  {
666  fprintf(stderr, "%s: %s\n", progname,
667  _("wild compilation-time specification of zic_t"));
668  return EXIT_FAILURE;
669  }
670  for (k = 1; k < argc; k++)
671  if (strcmp(argv[k], "--version") == 0)
672  {
673  printf("zic %s\n", PG_VERSION);
674  close_file(stdout, NULL, NULL);
675  return EXIT_SUCCESS;
676  }
677  else if (strcmp(argv[k], "--help") == 0)
678  {
680  }
681  while ((c = getopt(argc, argv, "b:d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
682  switch (c)
683  {
684  default:
685  usage(stderr, EXIT_FAILURE);
686  case 'b':
687  if (strcmp(optarg, "slim") == 0)
688  {
689  if (0 < bloat)
690  error(_("incompatible -b options"));
691  bloat = -1;
692  }
693  else if (strcmp(optarg, "fat") == 0)
694  {
695  if (bloat < 0)
696  error(_("incompatible -b options"));
697  bloat = 1;
698  }
699  else
700  error(_("invalid option: -b '%s'"), optarg);
701  break;
702  case 'd':
703  if (directory == NULL)
704  directory = strdup(optarg);
705  else
706  {
707  fprintf(stderr,
708  _("%s: More than one -d option specified\n"),
709  progname);
710  return EXIT_FAILURE;
711  }
712  break;
713  case 'l':
714  if (lcltime == NULL)
715  lcltime = strdup(optarg);
716  else
717  {
718  fprintf(stderr,
719  _("%s: More than one -l option specified\n"),
720  progname);
721  return EXIT_FAILURE;
722  }
723  break;
724  case 'p':
725  if (psxrules == NULL)
726  psxrules = strdup(optarg);
727  else
728  {
729  fprintf(stderr,
730  _("%s: More than one -p option specified\n"),
731  progname);
732  return EXIT_FAILURE;
733  }
734  break;
735  case 't':
736  if (tzdefault != NULL)
737  {
738  fprintf(stderr,
739  _("%s: More than one -t option"
740  " specified\n"),
741  progname);
742  return EXIT_FAILURE;
743  }
744  tzdefault = optarg;
745  break;
746  case 'y':
747  warning(_("-y ignored"));
748  break;
749  case 'L':
750  if (leapsec == NULL)
751  leapsec = strdup(optarg);
752  else
753  {
754  fprintf(stderr,
755  _("%s: More than one -L option specified\n"),
756  progname);
757  return EXIT_FAILURE;
758  }
759  break;
760  case 'v':
761  noise = true;
762  break;
763  case 'P':
764  print_abbrevs = true;
765  print_cutoff = time(NULL);
766  break;
767  case 'r':
768  if (timerange_given)
769  {
770  fprintf(stderr,
771  _("%s: More than one -r option specified\n"),
772  progname);
773  return EXIT_FAILURE;
774  }
775  if (!timerange_option(optarg))
776  {
777  fprintf(stderr,
778  _("%s: invalid time range: %s\n"),
779  progname, optarg);
780  return EXIT_FAILURE;
781  }
782  timerange_given = true;
783  break;
784  case 's':
785  warning(_("-s ignored"));
786  break;
787  }
788  if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
789  usage(stderr, EXIT_FAILURE); /* usage message by request */
790  if (bloat == 0)
791  {
792  static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
793 
794  if (strcmp(bloat_default, "slim") == 0)
795  bloat = -1;
796  else if (strcmp(bloat_default, "fat") == 0)
797  bloat = 1;
798  else
799  abort(); /* Configuration error. */
800  }
801  if (directory == NULL)
802  directory = "data";
803  if (tzdefault == NULL)
804  tzdefault = TZDEFAULT;
805 
806  if (optind < argc && leapsec != NULL)
807  {
808  infile(leapsec);
809  adjleap();
810  }
811 
812  for (k = optind; k < argc; k++)
813  infile(argv[k]);
814  if (errors)
815  return EXIT_FAILURE;
816  associate();
817  change_directory(directory);
818  for (i = 0; i < nzones; i = j)
819  {
820  /*
821  * Find the next non-continuation zone entry.
822  */
823  for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
824  continue;
825  outzone(&zones[i], j - i);
826  }
827 
828  /*
829  * Make links.
830  */
831  for (i = 0; i < nlinks; ++i)
832  {
833  eat(links[i].l_filename, links[i].l_linenum);
834  dolink(links[i].l_target, links[i].l_linkname, false);
835  if (noise)
836  for (j = 0; j < nlinks; ++j)
837  if (strcmp(links[i].l_linkname,
838  links[j].l_target) == 0)
839  warning(_("link to link"));
840  }
841  if (lcltime != NULL)
842  {
843  eat(_("command line"), 1);
844  dolink(lcltime, tzdefault, true);
845  }
846  if (psxrules != NULL)
847  {
848  eat(_("command line"), 1);
849  dolink(psxrules, TZDEFRULES, true);
850  }
851  if (warnings && (ferror(stderr) || fclose(stderr) != 0))
852  return EXIT_FAILURE;
853  return errors ? EXIT_FAILURE : EXIT_SUCCESS;
854 }
855 
856 static bool
857 componentcheck(char const *name, char const *component,
858  char const *component_end)
859 {
860  enum
861  {
862  component_len_max = 14};
863  ptrdiff_t component_len = component_end - component;
864 
865  if (component_len == 0)
866  {
867  if (!*name)
868  error(_("empty file name"));
869  else
870  error(_(component == name
871  ? "file name '%s' begins with '/'"
872  : *component_end
873  ? "file name '%s' contains '//'"
874  : "file name '%s' ends with '/'"),
875  name);
876  return false;
877  }
878  if (0 < component_len && component_len <= 2
879  && component[0] == '.' && component_end[-1] == '.')
880  {
881  int len = component_len;
882 
883  error(_("file name '%s' contains '%.*s' component"),
884  name, len, component);
885  return false;
886  }
887  if (noise)
888  {
889  if (0 < component_len && component[0] == '-')
890  warning(_("file name '%s' component contains leading '-'"),
891  name);
892  if (component_len_max < component_len)
893  warning(_("file name '%s' contains overlength component"
894  " '%.*s...'"),
895  name, component_len_max, component);
896  }
897  return true;
898 }
899 
900 static bool
901 namecheck(const char *name)
902 {
903  char const *cp;
904 
905  /* Benign characters in a portable file name. */
906  static char const benign[] =
907  "-/_"
908  "abcdefghijklmnopqrstuvwxyz"
909  "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
910 
911  /*
912  * Non-control chars in the POSIX portable character set, excluding the
913  * benign characters.
914  */
915  static char const printable_and_not_benign[] =
916  " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
917 
918  char const *component = name;
919 
920  for (cp = name; *cp; cp++)
921  {
922  unsigned char c = *cp;
923 
924  if (noise && !strchr(benign, c))
925  {
926  warning((strchr(printable_and_not_benign, c)
927  ? _("file name '%s' contains byte '%c'")
928  : _("file name '%s' contains byte '\\%o'")),
929  name, c);
930  }
931  if (c == '/')
932  {
933  if (!componentcheck(name, component, cp))
934  return false;
935  component = cp + 1;
936  }
937  }
938  return componentcheck(name, component, cp);
939 }
940 
941 /*
942  * Create symlink contents suitable for symlinking FROM to TO, as a
943  * freshly allocated string. FROM should be a relative file name, and
944  * is relative to the global variable DIRECTORY. TO can be either
945  * relative or absolute.
946  */
947 #ifdef HAVE_SYMLINK
948 static char *
949 relname(char const *target, char const *linkname)
950 {
951  size_t i,
952  taillen,
953  dotdotetcsize;
954  size_t dir_len = 0,
955  dotdots = 0,
956  linksize = SIZE_MAX;
957  char const *f = target;
958  char *result = NULL;
959 
960  if (*linkname == '/')
961  {
962  /* Make F absolute too. */
963  size_t len = strlen(directory);
964  bool needslash = len && directory[len - 1] != '/';
965 
966  linksize = len + needslash + strlen(target) + 1;
967  f = result = emalloc(linksize);
968  strcpy(result, directory);
969  result[len] = '/';
970  strcpy(result + len + needslash, target);
971  }
972  for (i = 0; f[i] && f[i] == linkname[i]; i++)
973  if (f[i] == '/')
974  dir_len = i + 1;
975  for (; linkname[i]; i++)
976  dotdots += linkname[i] == '/' && linkname[i - 1] != '/';
977  taillen = strlen(f + dir_len);
978  dotdotetcsize = 3 * dotdots + taillen + 1;
979  if (dotdotetcsize <= linksize)
980  {
981  if (!result)
982  result = emalloc(dotdotetcsize);
983  for (i = 0; i < dotdots; i++)
984  memcpy(result + 3 * i, "../", 3);
985  memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
986  }
987  return result;
988 }
989 #endif /* HAVE_SYMLINK */
990 
991 /* Hard link FROM to TO, following any symbolic links.
992  Return 0 if successful, an error number otherwise. */
993 static int
994 hardlinkerr(char const *target, char const *linkname)
995 {
996  int r = linkat(AT_FDCWD, target, AT_FDCWD, linkname, AT_SYMLINK_FOLLOW);
997 
998  return r == 0 ? 0 : errno;
999 }
1000 
1001 static void
1002 dolink(char const *target, char const *linkname, bool staysymlink)
1003 {
1004  bool remove_only = strcmp(target, "-") == 0;
1005  bool linkdirs_made = false;
1006  int link_errno;
1007 
1008  /*
1009  * We get to be careful here since there's a fair chance of root running
1010  * us.
1011  */
1012  if (!remove_only && itsdir(target))
1013  {
1014  fprintf(stderr, _("%s: linking target %s/%s failed: %s\n"),
1015  progname, directory, target, strerror(EPERM));
1016  exit(EXIT_FAILURE);
1017  }
1018  if (staysymlink)
1019  staysymlink = itssymlink(linkname);
1020  if (remove(linkname) == 0)
1021  linkdirs_made = true;
1022  else if (errno != ENOENT)
1023  {
1024  char const *e = strerror(errno);
1025 
1026  fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
1027  progname, directory, linkname, e);
1028  exit(EXIT_FAILURE);
1029  }
1030  if (remove_only)
1031  return;
1032  link_errno = staysymlink ? ENOTSUP : hardlinkerr(target, linkname);
1033  if (link_errno == ENOENT && !linkdirs_made)
1034  {
1035  mkdirs(linkname, true);
1036  linkdirs_made = true;
1037  link_errno = hardlinkerr(target, linkname);
1038  }
1039  if (link_errno != 0)
1040  {
1041 #ifdef HAVE_SYMLINK
1042  bool absolute = *target == '/';
1043  char *linkalloc = absolute ? NULL : relname(target, linkname);
1044  char const *contents = absolute ? target : linkalloc;
1045  int symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
1046 
1047  if (!linkdirs_made
1048  && (symlink_errno == ENOENT || symlink_errno == ENOTSUP))
1049  {
1050  mkdirs(linkname, true);
1051  if (symlink_errno == ENOENT)
1052  symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
1053  }
1054  free(linkalloc);
1055  if (symlink_errno == 0)
1056  {
1057  if (link_errno != ENOTSUP)
1058  warning(_("symbolic link used because hard link failed: %s"),
1059  strerror(link_errno));
1060  }
1061  else
1062 #endif /* HAVE_SYMLINK */
1063  {
1064  FILE *fp,
1065  *tp;
1066  int c;
1067 
1068  fp = fopen(target, "rb");
1069  if (!fp)
1070  {
1071  char const *e = strerror(errno);
1072 
1073  fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
1074  progname, directory, target, e);
1075  exit(EXIT_FAILURE);
1076  }
1077  tp = fopen(linkname, "wb");
1078  if (!tp)
1079  {
1080  char const *e = strerror(errno);
1081 
1082  fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
1083  progname, directory, linkname, e);
1084  exit(EXIT_FAILURE);
1085  }
1086  while ((c = getc(fp)) != EOF)
1087  putc(c, tp);
1088  close_file(fp, directory, target);
1089  close_file(tp, directory, linkname);
1090  if (link_errno != ENOTSUP)
1091  warning(_("copy used because hard link failed: %s"),
1092  strerror(link_errno));
1093 #ifdef HAVE_SYMLINK
1094  else if (symlink_errno != ENOTSUP)
1095  warning(_("copy used because symbolic link failed: %s"),
1096  strerror(symlink_errno));
1097 #endif
1098  }
1099  }
1100 }
1101 
1102 /* Return true if NAME is a directory. */
1103 static bool
1104 itsdir(char const *name)
1105 {
1106  struct stat st;
1107  int res = stat(name, &st);
1108 #ifdef S_ISDIR
1109  if (res == 0)
1110  return S_ISDIR(st.st_mode) != 0;
1111 #endif
1112  if (res == 0 || errno == EOVERFLOW)
1113  {
1114  size_t n = strlen(name);
1115  char *nameslashdot = emalloc(n + 3);
1116  bool dir;
1117 
1118  memcpy(nameslashdot, name, n);
1119  strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
1120  dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
1121  free(nameslashdot);
1122  return dir;
1123  }
1124  return false;
1125 }
1126 
1127 /* Return true if NAME is a symbolic link. */
1128 static bool
1129 itssymlink(char const *name)
1130 {
1131 #ifdef HAVE_SYMLINK
1132  char c;
1133 
1134  return 0 <= readlink(name, &c, 1);
1135 #else
1136  return false;
1137 #endif
1138 }
1139 
1140 /*
1141  * Associate sets of rules with zones.
1142  */
1143 
1144 /*
1145  * Sort by rule name.
1146  */
1147 
1148 static int
1149 rcomp(const void *cp1, const void *cp2)
1150 {
1151  return strcmp(((const struct rule *) cp1)->r_name,
1152  ((const struct rule *) cp2)->r_name);
1153 }
1154 
1155 static void
1157 {
1158  struct zone *zp;
1159  struct rule *rp;
1160  ptrdiff_t i,
1161  j,
1162  base,
1163  out;
1164 
1165  if (nrules != 0)
1166  {
1167  qsort(rules, nrules, sizeof *rules, rcomp);
1168  for (i = 0; i < nrules - 1; ++i)
1169  {
1170  if (strcmp(rules[i].r_name,
1171  rules[i + 1].r_name) != 0)
1172  continue;
1173  if (strcmp(rules[i].r_filename,
1174  rules[i + 1].r_filename) == 0)
1175  continue;
1176  eat(rules[i].r_filename, rules[i].r_linenum);
1177  warning(_("same rule name in multiple files"));
1178  eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
1179  warning(_("same rule name in multiple files"));
1180  for (j = i + 2; j < nrules; ++j)
1181  {
1182  if (strcmp(rules[i].r_name,
1183  rules[j].r_name) != 0)
1184  break;
1185  if (strcmp(rules[i].r_filename,
1186  rules[j].r_filename) == 0)
1187  continue;
1188  if (strcmp(rules[i + 1].r_filename,
1189  rules[j].r_filename) == 0)
1190  continue;
1191  break;
1192  }
1193  i = j - 1;
1194  }
1195  }
1196  for (i = 0; i < nzones; ++i)
1197  {
1198  zp = &zones[i];
1199  zp->z_rules = NULL;
1200  zp->z_nrules = 0;
1201  }
1202  for (base = 0; base < nrules; base = out)
1203  {
1204  rp = &rules[base];
1205  for (out = base + 1; out < nrules; ++out)
1206  if (strcmp(rp->r_name, rules[out].r_name) != 0)
1207  break;
1208  for (i = 0; i < nzones; ++i)
1209  {
1210  zp = &zones[i];
1211  if (strcmp(zp->z_rule, rp->r_name) != 0)
1212  continue;
1213  zp->z_rules = rp;
1214  zp->z_nrules = out - base;
1215  }
1216  }
1217  for (i = 0; i < nzones; ++i)
1218  {
1219  zp = &zones[i];
1220  if (zp->z_nrules == 0)
1221  {
1222  /*
1223  * Maybe we have a local standard time offset.
1224  */
1225  eat(zp->z_filename, zp->z_linenum);
1226  zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
1227 
1228  /*
1229  * Note, though, that if there's no rule, a '%s' in the format is
1230  * a bad thing.
1231  */
1232  if (zp->z_format_specifier == 's')
1233  error("%s", _("%s in ruleless zone"));
1234  }
1235  }
1236  if (errors)
1237  exit(EXIT_FAILURE);
1238 }
1239 
1240 static void
1241 infile(const char *name)
1242 {
1243  FILE *fp;
1244  char **fields;
1245  char *cp;
1246  const struct lookup *lp;
1247  int nfields;
1248  bool wantcont;
1249  lineno_t num;
1250  char buf[BUFSIZ];
1251 
1252  if (strcmp(name, "-") == 0)
1253  {
1254  name = _("standard input");
1255  fp = stdin;
1256  }
1257  else if ((fp = fopen(name, "r")) == NULL)
1258  {
1259  const char *e = strerror(errno);
1260 
1261  fprintf(stderr, _("%s: Cannot open %s: %s\n"),
1262  progname, name, e);
1263  exit(EXIT_FAILURE);
1264  }
1265  wantcont = false;
1266  for (num = 1;; ++num)
1267  {
1268  eat(name, num);
1269  if (fgets(buf, sizeof buf, fp) != buf)
1270  break;
1271  cp = strchr(buf, '\n');
1272  if (cp == NULL)
1273  {
1274  error(_("line too long"));
1275  exit(EXIT_FAILURE);
1276  }
1277  *cp = '\0';
1278  fields = getfields(buf);
1279  nfields = 0;
1280  while (fields[nfields] != NULL)
1281  {
1282  static char nada;
1283 
1284  if (strcmp(fields[nfields], "-") == 0)
1285  fields[nfields] = &nada;
1286  ++nfields;
1287  }
1288  if (nfields == 0)
1289  {
1290  if (name == leapsec && *buf == '#')
1291  {
1292  /*
1293  * PG: INT64_FORMAT isn't portable for sscanf, so be content
1294  * with scanning a "long". Once we are requiring C99 in all
1295  * live branches, it'd be sensible to adopt upstream's
1296  * practice of using the <inttypes.h> macros. But for now, we
1297  * don't actually use this code, and it won't overflow before
1298  * 2038 anyway.
1299  */
1300  long cl_tmp;
1301 
1302  sscanf(buf, "#expires %ld", &cl_tmp);
1303  comment_leapexpires = cl_tmp;
1304  }
1305  }
1306  else if (wantcont)
1307  {
1308  wantcont = inzcont(fields, nfields);
1309  }
1310  else
1311  {
1312  struct lookup const *line_codes
1313  = name == leapsec ? leap_line_codes : zi_line_codes;
1314 
1315  lp = byword(fields[0], line_codes);
1316  if (lp == NULL)
1317  error(_("input line of unknown type"));
1318  else
1319  switch (lp->l_value)
1320  {
1321  case LC_RULE:
1322  inrule(fields, nfields);
1323  wantcont = false;
1324  break;
1325  case LC_ZONE:
1326  wantcont = inzone(fields, nfields);
1327  break;
1328  case LC_LINK:
1329  inlink(fields, nfields);
1330  wantcont = false;
1331  break;
1332  case LC_LEAP:
1333  inleap(fields, nfields);
1334  wantcont = false;
1335  break;
1336  case LC_EXPIRES:
1337  inexpires(fields, nfields);
1338  wantcont = false;
1339  break;
1340  default: /* "cannot happen" */
1341  fprintf(stderr,
1342  _("%s: panic: Invalid l_value %d\n"),
1343  progname, lp->l_value);
1344  exit(EXIT_FAILURE);
1345  }
1346  }
1347  free(fields);
1348  }
1349  close_file(fp, NULL, filename);
1350  if (wantcont)
1351  error(_("expected continuation line not found"));
1352 }
1353 
1354 /*
1355  * Convert a string of one of the forms
1356  * h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
1357  * into a number of seconds.
1358  * A null string maps to zero.
1359  * Call error with errstring and return zero on errors.
1360  */
1361 
1362 static zic_t
1363 gethms(char const *string, char const *errstring)
1364 {
1365  /* PG: make hh be int not zic_t to avoid sscanf portability issues */
1366  int hh;
1367  int sign,
1368  mm = 0,
1369  ss = 0;
1370  char hhx,
1371  mmx,
1372  ssx,
1373  xr = '0',
1374  xs;
1375  int tenths = 0;
1376  bool ok = true;
1377 
1378  if (string == NULL || *string == '\0')
1379  return 0;
1380  if (*string == '-')
1381  {
1382  sign = -1;
1383  ++string;
1384  }
1385  else
1386  sign = 1;
1387  switch (sscanf(string,
1388  "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1389  &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs))
1390  {
1391  default:
1392  ok = false;
1393  break;
1394  case 8:
1395  ok = '0' <= xr && xr <= '9';
1396  /* fallthrough */
1397  case 7:
1398  ok &= ssx == '.';
1399  if (ok && noise)
1400  warning(_("fractional seconds rejected by"
1401  " pre-2018 versions of zic"));
1402  /* fallthrough */
1403  case 5:
1404  ok &= mmx == ':';
1405  /* fallthrough */
1406  case 3:
1407  ok &= hhx == ':';
1408  /* fallthrough */
1409  case 1:
1410  break;
1411  }
1412  if (!ok)
1413  {
1414  error("%s", errstring);
1415  return 0;
1416  }
1417  if (hh < 0 ||
1418  mm < 0 || mm >= MINSPERHOUR ||
1419  ss < 0 || ss > SECSPERMIN)
1420  {
1421  error("%s", errstring);
1422  return 0;
1423  }
1424  /* Some compilers warn that this test is unsatisfiable for 32-bit ints */
1425 #if INT_MAX > PG_INT32_MAX
1426  if (ZIC_MAX / SECSPERHOUR < hh)
1427  {
1428  error(_("time overflow"));
1429  return 0;
1430  }
1431 #endif
1432  ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
1433  if (noise && (hh > HOURSPERDAY ||
1434  (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
1435  warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1436  return oadd(sign * (zic_t) hh * SECSPERHOUR,
1437  sign * (mm * SECSPERMIN + ss));
1438 }
1439 
1440 static zic_t
1441 getsave(char *field, bool *isdst)
1442 {
1443  int dst = -1;
1444  zic_t save;
1445  size_t fieldlen = strlen(field);
1446 
1447  if (fieldlen != 0)
1448  {
1449  char *ep = field + fieldlen - 1;
1450 
1451  switch (*ep)
1452  {
1453  case 'd':
1454  dst = 1;
1455  *ep = '\0';
1456  break;
1457  case 's':
1458  dst = 0;
1459  *ep = '\0';
1460  break;
1461  }
1462  }
1463  save = gethms(field, _("invalid saved time"));
1464  *isdst = dst < 0 ? save != 0 : dst;
1465  return save;
1466 }
1467 
1468 static void
1469 inrule(char **fields, int nfields)
1470 {
1471  static struct rule r;
1472 
1473  if (nfields != RULE_FIELDS)
1474  {
1475  error(_("wrong number of fields on Rule line"));
1476  return;
1477  }
1478  switch (*fields[RF_NAME])
1479  {
1480  case '\0':
1481  case ' ':
1482  case '\f':
1483  case '\n':
1484  case '\r':
1485  case '\t':
1486  case '\v':
1487  case '+':
1488  case '-':
1489  case '0':
1490  case '1':
1491  case '2':
1492  case '3':
1493  case '4':
1494  case '5':
1495  case '6':
1496  case '7':
1497  case '8':
1498  case '9':
1499  error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
1500  return;
1501  }
1502  r.r_filename = filename;
1503  r.r_linenum = linenum;
1504  r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
1505  rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
1506  fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
1507  r.r_name = ecpyalloc(fields[RF_NAME]);
1508  r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
1509  if (max_abbrvar_len < strlen(r.r_abbrvar))
1510  max_abbrvar_len = strlen(r.r_abbrvar);
1511  rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
1512  rules[nrules++] = r;
1513 }
1514 
1515 static bool
1516 inzone(char **fields, int nfields)
1517 {
1518  ptrdiff_t i;
1519 
1520  if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
1521  {
1522  error(_("wrong number of fields on Zone line"));
1523  return false;
1524  }
1525  if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0)
1526  {
1527  error(
1528  _("\"Zone %s\" line and -l option are mutually exclusive"),
1529  tzdefault);
1530  return false;
1531  }
1532  if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL)
1533  {
1534  error(
1535  _("\"Zone %s\" line and -p option are mutually exclusive"),
1536  TZDEFRULES);
1537  return false;
1538  }
1539  for (i = 0; i < nzones; ++i)
1540  if (zones[i].z_name != NULL &&
1541  strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
1542  {
1543  error(_("duplicate zone name %s"
1544  " (file \"%s\", line %d)"),
1545  fields[ZF_NAME],
1546  zones[i].z_filename,
1547  zones[i].z_linenum);
1548  return false;
1549  }
1550  return inzsub(fields, nfields, false);
1551 }
1552 
1553 static bool
1554 inzcont(char **fields, int nfields)
1555 {
1556  if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS)
1557  {
1558  error(_("wrong number of fields on Zone continuation line"));
1559  return false;
1560  }
1561  return inzsub(fields, nfields, true);
1562 }
1563 
1564 static bool
1565 inzsub(char **fields, int nfields, bool iscont)
1566 {
1567  char *cp;
1568  char *cp1;
1569  static struct zone z;
1570  int i_stdoff,
1571  i_rule,
1572  i_format;
1573  int i_untilyear,
1574  i_untilmonth;
1575  int i_untilday,
1576  i_untiltime;
1577  bool hasuntil;
1578 
1579  if (iscont)
1580  {
1581  i_stdoff = ZFC_STDOFF;
1582  i_rule = ZFC_RULE;
1583  i_format = ZFC_FORMAT;
1584  i_untilyear = ZFC_TILYEAR;
1585  i_untilmonth = ZFC_TILMONTH;
1586  i_untilday = ZFC_TILDAY;
1587  i_untiltime = ZFC_TILTIME;
1588  z.z_name = NULL;
1589  }
1590  else if (!namecheck(fields[ZF_NAME]))
1591  return false;
1592  else
1593  {
1594  i_stdoff = ZF_STDOFF;
1595  i_rule = ZF_RULE;
1596  i_format = ZF_FORMAT;
1597  i_untilyear = ZF_TILYEAR;
1598  i_untilmonth = ZF_TILMONTH;
1599  i_untilday = ZF_TILDAY;
1600  i_untiltime = ZF_TILTIME;
1601  z.z_name = ecpyalloc(fields[ZF_NAME]);
1602  }
1603  z.z_filename = filename;
1604  z.z_linenum = linenum;
1605  z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
1606  if ((cp = strchr(fields[i_format], '%')) != NULL)
1607  {
1608  if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
1609  || strchr(fields[i_format], '/'))
1610  {
1611  error(_("invalid abbreviation format"));
1612  return false;
1613  }
1614  }
1615  z.z_rule = ecpyalloc(fields[i_rule]);
1616  z.z_format = cp1 = ecpyalloc(fields[i_format]);
1617  z.z_format_specifier = cp ? *cp : '\0';
1618  if (z.z_format_specifier == 'z')
1619  {
1620  if (noise)
1621  warning(_("format '%s' not handled by pre-2015 versions of zic"),
1622  z.z_format);
1623  cp1[cp - fields[i_format]] = 's';
1624  }
1625  if (max_format_len < strlen(z.z_format))
1626  max_format_len = strlen(z.z_format);
1627  hasuntil = nfields > i_untilyear;
1628  if (hasuntil)
1629  {
1632  rulesub(&z.z_untilrule,
1633  fields[i_untilyear],
1634  "only",
1635  "",
1636  (nfields > i_untilmonth) ?
1637  fields[i_untilmonth] : "Jan",
1638  (nfields > i_untilday) ? fields[i_untilday] : "1",
1639  (nfields > i_untiltime) ? fields[i_untiltime] : "0");
1641  z.z_untilrule.r_loyear);
1642  if (iscont && nzones > 0 &&
1643  z.z_untiltime > min_time &&
1644  z.z_untiltime < max_time &&
1645  zones[nzones - 1].z_untiltime > min_time &&
1646  zones[nzones - 1].z_untiltime < max_time &&
1647  zones[nzones - 1].z_untiltime >= z.z_untiltime)
1648  {
1649  error(_("Zone continuation line end time is not after end time of previous line"));
1650  return false;
1651  }
1652  }
1653  zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
1654  zones[nzones++] = z;
1655 
1656  /*
1657  * If there was an UNTIL field on this line, there's more information
1658  * about the zone on the next line.
1659  */
1660  return hasuntil;
1661 }
1662 
1663 static zic_t
1664 getleapdatetime(char **fields, int nfields, bool expire_line)
1665 {
1666  const char *cp;
1667  const struct lookup *lp;
1668  zic_t i,
1669  j;
1670 
1671  /* PG: make year be int not zic_t to avoid sscanf portability issues */
1672  int year;
1673  int month,
1674  day;
1675  zic_t dayoff,
1676  tod;
1677  zic_t t;
1678  char xs;
1679 
1680  dayoff = 0;
1681  cp = fields[LP_YEAR];
1682  if (sscanf(cp, "%d%c", &year, &xs) != 1)
1683  {
1684  /*
1685  * Leapin' Lizards!
1686  */
1687  error(_("invalid leaping year"));
1688  return -1;
1689  }
1690  if (!expire_line)
1691  {
1692  if (!leapseen || leapmaxyear < year)
1693  leapmaxyear = year;
1694  if (!leapseen || leapminyear > year)
1695  leapminyear = year;
1696  leapseen = true;
1697  }
1698  j = EPOCH_YEAR;
1699  while (j != year)
1700  {
1701  if (year > j)
1702  {
1703  i = len_years[isleap(j)];
1704  ++j;
1705  }
1706  else
1707  {
1708  --j;
1709  i = -len_years[isleap(j)];
1710  }
1711  dayoff = oadd(dayoff, i);
1712  }
1713  if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL)
1714  {
1715  error(_("invalid month name"));
1716  return -1;
1717  }
1718  month = lp->l_value;
1719  j = TM_JANUARY;
1720  while (j != month)
1721  {
1722  i = len_months[isleap(year)][j];
1723  dayoff = oadd(dayoff, i);
1724  ++j;
1725  }
1726  cp = fields[LP_DAY];
1727  if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
1728  day <= 0 || day > len_months[isleap(year)][month])
1729  {
1730  error(_("invalid day of month"));
1731  return -1;
1732  }
1733  dayoff = oadd(dayoff, day - 1);
1734  if (dayoff < min_time / SECSPERDAY)
1735  {
1736  error(_("time too small"));
1737  return -1;
1738  }
1739  if (dayoff > max_time / SECSPERDAY)
1740  {
1741  error(_("time too large"));
1742  return -1;
1743  }
1744  t = dayoff * SECSPERDAY;
1745  tod = gethms(fields[LP_TIME], _("invalid time of day"));
1746  t = tadd(t, tod);
1747  if (t < 0)
1748  error(_("leap second precedes Epoch"));
1749  return t;
1750 }
1751 
1752 static void
1753 inleap(char **fields, int nfields)
1754 {
1755  if (nfields != LEAP_FIELDS)
1756  error(_("wrong number of fields on Leap line"));
1757  else
1758  {
1759  zic_t t = getleapdatetime(fields, nfields, false);
1760 
1761  if (0 <= t)
1762  {
1763  struct lookup const *lp = byword(fields[LP_ROLL], leap_types);
1764 
1765  if (!lp)
1766  error(_("invalid Rolling/Stationary field on Leap line"));
1767  else
1768  {
1769  int correction = 0;
1770 
1771  if (!fields[LP_CORR][0]) /* infile() turns "-" into "". */
1772  correction = -1;
1773  else if (strcmp(fields[LP_CORR], "+") == 0)
1774  correction = 1;
1775  else
1776  error(_("invalid CORRECTION field on Leap line"));
1777  if (correction)
1778  leapadd(t, correction, lp->l_value);
1779  }
1780  }
1781  }
1782 }
1783 
1784 static void
1785 inexpires(char **fields, int nfields)
1786 {
1787  if (nfields != EXPIRES_FIELDS)
1788  error(_("wrong number of fields on Expires line"));
1789  else if (0 <= leapexpires)
1790  error(_("multiple Expires lines"));
1791  else
1792  leapexpires = getleapdatetime(fields, nfields, true);
1793 }
1794 
1795 static void
1796 inlink(char **fields, int nfields)
1797 {
1798  struct link l;
1799 
1800  if (nfields != LINK_FIELDS)
1801  {
1802  error(_("wrong number of fields on Link line"));
1803  return;
1804  }
1805  if (*fields[LF_TARGET] == '\0')
1806  {
1807  error(_("blank TARGET field on Link line"));
1808  return;
1809  }
1810  if (!namecheck(fields[LF_LINKNAME]))
1811  return;
1812  l.l_filename = filename;
1813  l.l_linenum = linenum;
1814  l.l_target = ecpyalloc(fields[LF_TARGET]);
1815  l.l_linkname = ecpyalloc(fields[LF_LINKNAME]);
1816  links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
1817  links[nlinks++] = l;
1818 }
1819 
1820 static void
1821 rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
1822  const char *typep, const char *monthp, const char *dayp,
1823  const char *timep)
1824 {
1825  const struct lookup *lp;
1826  const char *cp;
1827  char *dp;
1828  char *ep;
1829  char xs;
1830 
1831  /* PG: year_tmp is to avoid sscanf portability issues */
1832  int year_tmp;
1833 
1834  if ((lp = byword(monthp, mon_names)) == NULL)
1835  {
1836  error(_("invalid month name"));
1837  return;
1838  }
1839  rp->r_month = lp->l_value;
1840  rp->r_todisstd = false;
1841  rp->r_todisut = false;
1842  dp = ecpyalloc(timep);
1843  if (*dp != '\0')
1844  {
1845  ep = dp + strlen(dp) - 1;
1846  switch (lowerit(*ep))
1847  {
1848  case 's': /* Standard */
1849  rp->r_todisstd = true;
1850  rp->r_todisut = false;
1851  *ep = '\0';
1852  break;
1853  case 'w': /* Wall */
1854  rp->r_todisstd = false;
1855  rp->r_todisut = false;
1856  *ep = '\0';
1857  break;
1858  case 'g': /* Greenwich */
1859  case 'u': /* Universal */
1860  case 'z': /* Zulu */
1861  rp->r_todisstd = true;
1862  rp->r_todisut = true;
1863  *ep = '\0';
1864  break;
1865  }
1866  }
1867  rp->r_tod = gethms(dp, _("invalid time of day"));
1868  free(dp);
1869 
1870  /*
1871  * Year work.
1872  */
1873  cp = loyearp;
1874  lp = byword(cp, begin_years);
1875  rp->r_lowasnum = lp == NULL;
1876  if (!rp->r_lowasnum)
1877  switch (lp->l_value)
1878  {
1879  case YR_MINIMUM:
1880  rp->r_loyear = ZIC_MIN;
1881  break;
1882  case YR_MAXIMUM:
1883  rp->r_loyear = ZIC_MAX;
1884  break;
1885  default: /* "cannot happen" */
1886  fprintf(stderr,
1887  _("%s: panic: Invalid l_value %d\n"),
1888  progname, lp->l_value);
1889  exit(EXIT_FAILURE);
1890  }
1891  else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1892  rp->r_loyear = year_tmp;
1893  else
1894  {
1895  error(_("invalid starting year"));
1896  return;
1897  }
1898  cp = hiyearp;
1899  lp = byword(cp, end_years);
1900  rp->r_hiwasnum = lp == NULL;
1901  if (!rp->r_hiwasnum)
1902  switch (lp->l_value)
1903  {
1904  case YR_MINIMUM:
1905  rp->r_hiyear = ZIC_MIN;
1906  break;
1907  case YR_MAXIMUM:
1908  rp->r_hiyear = ZIC_MAX;
1909  break;
1910  case YR_ONLY:
1911  rp->r_hiyear = rp->r_loyear;
1912  break;
1913  default: /* "cannot happen" */
1914  fprintf(stderr,
1915  _("%s: panic: Invalid l_value %d\n"),
1916  progname, lp->l_value);
1917  exit(EXIT_FAILURE);
1918  }
1919  else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1920  rp->r_hiyear = year_tmp;
1921  else
1922  {
1923  error(_("invalid ending year"));
1924  return;
1925  }
1926  if (rp->r_loyear > rp->r_hiyear)
1927  {
1928  error(_("starting year greater than ending year"));
1929  return;
1930  }
1931  if (*typep != '\0')
1932  {
1933  error(_("year type \"%s\" is unsupported; use \"-\" instead"),
1934  typep);
1935  return;
1936  }
1937 
1938  /*
1939  * Day work. Accept things such as: 1 lastSunday last-Sunday
1940  * (undocumented; warn about this) Sun<=20 Sun>=7
1941  */
1942  dp = ecpyalloc(dayp);
1943  if ((lp = byword(dp, lasts)) != NULL)
1944  {
1945  rp->r_dycode = DC_DOWLEQ;
1946  rp->r_wday = lp->l_value;
1947  rp->r_dayofmonth = len_months[1][rp->r_month];
1948  }
1949  else
1950  {
1951  if ((ep = strchr(dp, '<')) != NULL)
1952  rp->r_dycode = DC_DOWLEQ;
1953  else if ((ep = strchr(dp, '>')) != NULL)
1954  rp->r_dycode = DC_DOWGEQ;
1955  else
1956  {
1957  ep = dp;
1958  rp->r_dycode = DC_DOM;
1959  }
1960  if (rp->r_dycode != DC_DOM)
1961  {
1962  *ep++ = 0;
1963  if (*ep++ != '=')
1964  {
1965  error(_("invalid day of month"));
1966  free(dp);
1967  return;
1968  }
1969  if ((lp = byword(dp, wday_names)) == NULL)
1970  {
1971  error(_("invalid weekday name"));
1972  free(dp);
1973  return;
1974  }
1975  rp->r_wday = lp->l_value;
1976  }
1977  if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
1978  rp->r_dayofmonth <= 0 ||
1979  (rp->r_dayofmonth > len_months[1][rp->r_month]))
1980  {
1981  error(_("invalid day of month"));
1982  free(dp);
1983  return;
1984  }
1985  }
1986  free(dp);
1987 }
1988 
1989 static void
1990 convert(const int32 val, char *const buf)
1991 {
1992  int i;
1993  int shift;
1994  unsigned char *const b = (unsigned char *) buf;
1995 
1996  for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1997  b[i] = val >> shift;
1998 }
1999 
2000 static void
2001 convert64(const zic_t val, char *const buf)
2002 {
2003  int i;
2004  int shift;
2005  unsigned char *const b = (unsigned char *) buf;
2006 
2007  for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
2008  b[i] = val >> shift;
2009 }
2010 
2011 static void
2012 puttzcode(const int32 val, FILE *const fp)
2013 {
2014  char buf[4];
2015 
2016  convert(val, buf);
2017  fwrite(buf, sizeof buf, 1, fp);
2018 }
2019 
2020 static void
2021 puttzcodepass(zic_t val, FILE *fp, int pass)
2022 {
2023  if (pass == 1)
2024  puttzcode(val, fp);
2025  else
2026  {
2027  char buf[8];
2028 
2029  convert64(val, buf);
2030  fwrite(buf, sizeof buf, 1, fp);
2031  }
2032 }
2033 
2034 static int
2035 atcomp(const void *avp, const void *bvp)
2036 {
2037  const zic_t a = ((const struct attype *) avp)->at;
2038  const zic_t b = ((const struct attype *) bvp)->at;
2039 
2040  return (a < b) ? -1 : (a > b);
2041 }
2042 
2044 {
2046  ptrdiff_t base,
2047  count;
2048  int leapbase,
2049  leapcount;
2050 };
2051 
2052 static struct timerange
2053 limitrange(struct timerange r, zic_t lo, zic_t hi,
2054  zic_t const *ats, unsigned char const *types)
2055 {
2056  while (0 < r.count && ats[r.base] < lo)
2057  {
2058  r.defaulttype = types[r.base];
2059  r.count--;
2060  r.base++;
2061  }
2062  while (0 < r.leapcount && trans[r.leapbase] < lo)
2063  {
2064  r.leapcount--;
2065  r.leapbase++;
2066  }
2067 
2068  if (hi < ZIC_MAX)
2069  {
2070  while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
2071  r.count--;
2072  while (0 < r.leapcount && hi + 1 < trans[r.leapbase + r.leapcount - 1])
2073  r.leapcount--;
2074  }
2075 
2076  return r;
2077 }
2078 
2079 static void
2080 writezone(const char *const name, const char *const string, char version,
2081  int defaulttype)
2082 {
2083  FILE *fp;
2084  ptrdiff_t i,
2085  j;
2086  int pass;
2087  static const struct tzhead tzh0;
2088  static struct tzhead tzh;
2089  bool dir_checked = false;
2090  zic_t one = 1;
2091  zic_t y2038_boundary = one << 31;
2092  ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071;
2093 
2094  /*
2095  * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
2096  * faster.
2097  */
2098  zic_t *ats = emalloc(MAXALIGN(size_product(nats, sizeof *ats + 1)));
2099  void *typesptr = ats + nats;
2100  unsigned char *types = typesptr;
2101  struct timerange rangeall,
2102  range32,
2103  range64;
2104 
2105  /*
2106  * Sort.
2107  */
2108  if (timecnt > 1)
2109  qsort(attypes, timecnt, sizeof *attypes, atcomp);
2110 
2111  /*
2112  * Optimize.
2113  */
2114  {
2115  ptrdiff_t fromi,
2116  toi;
2117 
2118  toi = 0;
2119  fromi = 0;
2120  for (; fromi < timecnt; ++fromi)
2121  {
2122  if (toi != 0
2123  && ((attypes[fromi].at
2124  + utoffs[attypes[toi - 1].type])
2125  <= (attypes[toi - 1].at
2126  + utoffs[toi == 1 ? 0
2127  : attypes[toi - 2].type])))
2128  {
2129  attypes[toi - 1].type =
2130  attypes[fromi].type;
2131  continue;
2132  }
2133  if (toi == 0
2134  || attypes[fromi].dontmerge
2135  || (utoffs[attypes[toi - 1].type]
2136  != utoffs[attypes[fromi].type])
2137  || (isdsts[attypes[toi - 1].type]
2138  != isdsts[attypes[fromi].type])
2139  || (desigidx[attypes[toi - 1].type]
2140  != desigidx[attypes[fromi].type]))
2141  attypes[toi++] = attypes[fromi];
2142  }
2143  timecnt = toi;
2144  }
2145 
2146  if (noise && timecnt > 1200)
2147  {
2148  if (timecnt > TZ_MAX_TIMES)
2149  warning(_("reference clients mishandle"
2150  " more than %d transition times"),
2151  TZ_MAX_TIMES);
2152  else
2153  warning(_("pre-2014 clients may mishandle"
2154  " more than 1200 transition times"));
2155  }
2156 
2157  /*
2158  * Transfer.
2159  */
2160  for (i = 0; i < timecnt; ++i)
2161  {
2162  ats[i] = attypes[i].at;
2163  types[i] = attypes[i].type;
2164  }
2165 
2166  /*
2167  * Correct for leap seconds.
2168  */
2169  for (i = 0; i < timecnt; ++i)
2170  {
2171  j = leapcnt;
2172  while (--j >= 0)
2173  if (ats[i] > trans[j] - corr[j])
2174  {
2175  ats[i] = tadd(ats[i], corr[j]);
2176  break;
2177  }
2178  }
2179 
2180  /*
2181  * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2182  * inserting a no-op transition at time y2038_boundary - 1. This works
2183  * only for timestamps before the boundary, which should be good enough in
2184  * practice as QTBUG-53071 should be long-dead by 2038. Do this after
2185  * correcting for leap seconds, as the idea is to insert a transition just
2186  * before 32-bit pg_time_t rolls around, and this occurs at a slightly
2187  * different moment if transitions are leap-second corrected.
2188  */
2189  if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat()
2190  && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
2191  {
2192  ats[timecnt] = y2038_boundary - 1;
2193  types[timecnt] = types[timecnt - 1];
2194  timecnt++;
2195  }
2196 
2197  rangeall.defaulttype = defaulttype;
2198  rangeall.base = rangeall.leapbase = 0;
2199  rangeall.count = timecnt;
2200  rangeall.leapcount = leapcnt;
2201  range64 = limitrange(rangeall, lo_time, hi_time, ats, types);
2202  range32 = limitrange(range64, PG_INT32_MIN, PG_INT32_MAX, ats, types);
2203 
2204  /*
2205  * Remove old file, if any, to snap links.
2206  */
2207  if (remove(name) == 0)
2208  dir_checked = true;
2209  else if (errno != ENOENT)
2210  {
2211  const char *e = strerror(errno);
2212 
2213  fprintf(stderr, _("%s: Cannot remove %s/%s: %s\n"),
2214  progname, directory, name, e);
2215  exit(EXIT_FAILURE);
2216  }
2217  fp = fopen(name, "wb");
2218  if (!fp)
2219  {
2220  int fopen_errno = errno;
2221 
2222  if (fopen_errno == ENOENT && !dir_checked)
2223  {
2224  mkdirs(name, true);
2225  fp = fopen(name, "wb");
2226  fopen_errno = errno;
2227  }
2228  if (!fp)
2229  {
2230  fprintf(stderr, _("%s: Cannot create %s/%s: %s\n"),
2231  progname, directory, name, strerror(fopen_errno));
2232  exit(EXIT_FAILURE);
2233  }
2234  }
2235  for (pass = 1; pass <= 2; ++pass)
2236  {
2237  ptrdiff_t thistimei,
2238  thistimecnt,
2239  thistimelim;
2240  int thisleapi,
2241  thisleapcnt,
2242  thisleaplim;
2243  int currenttype,
2244  thisdefaulttype;
2245  bool locut,
2246  hicut;
2247  zic_t lo;
2248  int old0;
2249  char omittype[TZ_MAX_TYPES];
2250  int typemap[TZ_MAX_TYPES];
2251  int thistypecnt,
2252  stdcnt,
2253  utcnt;
2254  char thischars[TZ_MAX_CHARS];
2255  int thischarcnt;
2256  bool toomanytimes;
2257  int indmap[TZ_MAX_CHARS];
2258 
2259  if (pass == 1)
2260  {
2261  /*
2262  * Arguably the default time type in the 32-bit data should be
2263  * range32.defaulttype, which is suited for timestamps just before
2264  * PG_INT32_MIN. However, zic traditionally used the time type of
2265  * the indefinite past instead. Internet RFC 8532 says readers
2266  * should ignore 32-bit data, so this discrepancy matters only to
2267  * obsolete readers where the traditional type might be more
2268  * appropriate even if it's "wrong". So, use the historical zic
2269  * value, unless -r specifies a low cutoff that excludes some
2270  * 32-bit timestamps.
2271  */
2272  thisdefaulttype = (lo_time <= PG_INT32_MIN
2273  ? range64.defaulttype
2274  : range32.defaulttype);
2275 
2276  thistimei = range32.base;
2277  thistimecnt = range32.count;
2278  toomanytimes = thistimecnt >> 31 >> 1 != 0;
2279  thisleapi = range32.leapbase;
2280  thisleapcnt = range32.leapcount;
2281  locut = PG_INT32_MIN < lo_time;
2282  hicut = hi_time < PG_INT32_MAX;
2283  }
2284  else
2285  {
2286  thisdefaulttype = range64.defaulttype;
2287  thistimei = range64.base;
2288  thistimecnt = range64.count;
2289  toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
2290  thisleapi = range64.leapbase;
2291  thisleapcnt = range64.leapcount;
2292  locut = min_time < lo_time;
2293  hicut = hi_time < max_time;
2294  }
2295  if (toomanytimes)
2296  error(_("too many transition times"));
2297 
2298  /*
2299  * Keep the last too-low transition if no transition is exactly at LO.
2300  * The kept transition will be output as a LO "transition"; see
2301  * "Output a LO_TIME transition" below. This is needed when the
2302  * output is truncated at the start, and is also useful when catering
2303  * to buggy 32-bit clients that do not use time type 0 for timestamps
2304  * before the first transition.
2305  */
2306  if (0 < thistimei && ats[thistimei] != lo_time)
2307  {
2308  thistimei--;
2309  thistimecnt++;
2310  locut = false;
2311  }
2312 
2313  thistimelim = thistimei + thistimecnt;
2314  thisleaplim = thisleapi + thisleapcnt;
2315  if (thistimecnt != 0)
2316  {
2317  if (ats[thistimei] == lo_time)
2318  locut = false;
2319  if (hi_time < ZIC_MAX && ats[thistimelim - 1] == hi_time + 1)
2320  hicut = false;
2321  }
2322  memset(omittype, true, typecnt);
2323  omittype[thisdefaulttype] = false;
2324  for (i = thistimei; i < thistimelim; i++)
2325  omittype[types[i]] = false;
2326 
2327  /*
2328  * Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
2329  * OLD0 and THISDEFAULTTYPE so that THISDEFAULTTYPE appears as type 0
2330  * in the output instead of OLD0. TYPEMAP also omits unused types.
2331  */
2332  old0 = strlen(omittype);
2333 
2334 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2335 
2336  /*
2337  * For some pre-2011 systems: if the last-to-be-written standard (or
2338  * daylight) type has an offset different from the most recently used
2339  * offset, append an (unused) copy of the most recently used type (to
2340  * help get global "altzone" and "timezone" variables set correctly).
2341  */
2342  if (want_bloat())
2343  {
2344  int mrudst,
2345  mrustd,
2346  hidst,
2347  histd,
2348  type;
2349 
2350  hidst = histd = mrudst = mrustd = -1;
2351  for (i = thistimei; i < thistimelim; ++i)
2352  if (isdsts[types[i]])
2353  mrudst = types[i];
2354  else
2355  mrustd = types[i];
2356  for (i = old0; i < typecnt; i++)
2357  {
2358  int h = (i == old0 ? thisdefaulttype
2359  : i == thisdefaulttype ? old0 : i);
2360 
2361  if (!omittype[h])
2362  {
2363  if (isdsts[h])
2364  hidst = i;
2365  else
2366  histd = i;
2367  }
2368  }
2369  if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
2370  utoffs[hidst] != utoffs[mrudst])
2371  {
2372  isdsts[mrudst] = -1;
2373  type = addtype(utoffs[mrudst],
2374  &chars[desigidx[mrudst]],
2375  true,
2376  ttisstds[mrudst],
2377  ttisuts[mrudst]);
2378  isdsts[mrudst] = 1;
2379  omittype[type] = false;
2380  }
2381  if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
2382  utoffs[histd] != utoffs[mrustd])
2383  {
2384  isdsts[mrustd] = -1;
2385  type = addtype(utoffs[mrustd],
2386  &chars[desigidx[mrustd]],
2387  false,
2388  ttisstds[mrustd],
2389  ttisuts[mrustd]);
2390  isdsts[mrustd] = 0;
2391  omittype[type] = false;
2392  }
2393  }
2394 #endif /* !defined
2395  * LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
2396  thistypecnt = 0;
2397  for (i = old0; i < typecnt; i++)
2398  if (!omittype[i])
2399  typemap[i == old0 ? thisdefaulttype
2400  : i == thisdefaulttype ? old0 : i]
2401  = thistypecnt++;
2402 
2403  for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
2404  indmap[i] = -1;
2405  thischarcnt = stdcnt = utcnt = 0;
2406  for (i = old0; i < typecnt; i++)
2407  {
2408  char *thisabbr;
2409 
2410  if (omittype[i])
2411  continue;
2412  if (ttisstds[i])
2413  stdcnt = thistypecnt;
2414  if (ttisuts[i])
2415  utcnt = thistypecnt;
2416  if (indmap[desigidx[i]] >= 0)
2417  continue;
2418  thisabbr = &chars[desigidx[i]];
2419  for (j = 0; j < thischarcnt; ++j)
2420  if (strcmp(&thischars[j], thisabbr) == 0)
2421  break;
2422  if (j == thischarcnt)
2423  {
2424  strcpy(&thischars[thischarcnt], thisabbr);
2425  thischarcnt += strlen(thisabbr) + 1;
2426  }
2427  indmap[desigidx[i]] = j;
2428  }
2429  if (pass == 1 && !want_bloat())
2430  {
2431  utcnt = stdcnt = thisleapcnt = 0;
2432  thistimecnt = -(locut + hicut);
2433  thistypecnt = thischarcnt = 1;
2434  thistimelim = thistimei;
2435  }
2436 #define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
2437  tzh = tzh0;
2438  memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
2439  tzh.tzh_version[0] = version;
2440  convert(utcnt, tzh.tzh_ttisutcnt);
2441  convert(stdcnt, tzh.tzh_ttisstdcnt);
2442  convert(thisleapcnt, tzh.tzh_leapcnt);
2443  convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
2444  convert(thistypecnt, tzh.tzh_typecnt);
2445  convert(thischarcnt, tzh.tzh_charcnt);
2446  DO(tzh_magic);
2447  DO(tzh_version);
2448  DO(tzh_reserved);
2449  DO(tzh_ttisutcnt);
2450  DO(tzh_ttisstdcnt);
2451  DO(tzh_leapcnt);
2452  DO(tzh_timecnt);
2453  DO(tzh_typecnt);
2454  DO(tzh_charcnt);
2455 #undef DO
2456  if (pass == 1 && !want_bloat())
2457  {
2458  /* Output a minimal data block with just one time type. */
2459  puttzcode(0, fp); /* utoff */
2460  putc(0, fp); /* dst */
2461  putc(0, fp); /* index of abbreviation */
2462  putc(0, fp); /* empty-string abbreviation */
2463  continue;
2464  }
2465 
2466  /* PG: print current timezone abbreviations if requested */
2467  if (print_abbrevs && pass == 2)
2468  {
2469  /* Print "type" data for periods ending after print_cutoff */
2470  for (i = thistimei; i < thistimelim; ++i)
2471  {
2472  if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
2473  {
2474  unsigned char tm = types[i];
2475  char *thisabbrev = &thischars[indmap[desigidx[tm]]];
2476 
2477  fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
2478  thisabbrev,
2479  utoffs[tm],
2480  isdsts[tm] ? "\tD" : "");
2481  }
2482  }
2483  /* Print the default type if we have no transitions at all */
2484  if (thistimei >= thistimelim)
2485  {
2486  unsigned char tm = defaulttype;
2487  char *thisabbrev = &thischars[indmap[desigidx[tm]]];
2488 
2489  fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
2490  thisabbrev,
2491  utoffs[tm],
2492  isdsts[tm] ? "\tD" : "");
2493  }
2494  }
2495 
2496  /*
2497  * Output a LO_TIME transition if needed; see limitrange. But do not
2498  * go below the minimum representable value for this pass.
2499  */
2500  lo = pass == 1 && lo_time < PG_INT32_MIN ? PG_INT32_MIN : lo_time;
2501 
2502  if (locut)
2503  puttzcodepass(lo, fp, pass);
2504  for (i = thistimei; i < thistimelim; ++i)
2505  {
2506  zic_t at = ats[i] < lo ? lo : ats[i];
2507 
2508  puttzcodepass(at, fp, pass);
2509  }
2510  if (hicut)
2511  puttzcodepass(hi_time + 1, fp, pass);
2512  currenttype = 0;
2513  if (locut)
2514  putc(currenttype, fp);
2515  for (i = thistimei; i < thistimelim; ++i)
2516  {
2517  currenttype = typemap[types[i]];
2518  putc(currenttype, fp);
2519  }
2520  if (hicut)
2521  putc(currenttype, fp);
2522 
2523  for (i = old0; i < typecnt; i++)
2524  {
2525  int h = (i == old0 ? thisdefaulttype
2526  : i == thisdefaulttype ? old0 : i);
2527 
2528  if (!omittype[h])
2529  {
2530  puttzcode(utoffs[h], fp);
2531  putc(isdsts[h], fp);
2532  putc(indmap[desigidx[h]], fp);
2533  }
2534  }
2535  if (thischarcnt != 0)
2536  fwrite(thischars, sizeof thischars[0],
2537  thischarcnt, fp);
2538  for (i = thisleapi; i < thisleaplim; ++i)
2539  {
2540  zic_t todo;
2541 
2542  if (roll[i])
2543  {
2544  if (timecnt == 0 || trans[i] < ats[0])
2545  {
2546  j = 0;
2547  while (isdsts[j])
2548  if (++j >= typecnt)
2549  {
2550  j = 0;
2551  break;
2552  }
2553  }
2554  else
2555  {
2556  j = 1;
2557  while (j < timecnt &&
2558  trans[i] >= ats[j])
2559  ++j;
2560  j = types[j - 1];
2561  }
2562  todo = tadd(trans[i], -utoffs[j]);
2563  }
2564  else
2565  todo = trans[i];
2566  puttzcodepass(todo, fp, pass);
2567  puttzcode(corr[i], fp);
2568  }
2569  if (stdcnt != 0)
2570  for (i = old0; i < typecnt; i++)
2571  if (!omittype[i])
2572  putc(ttisstds[i], fp);
2573  if (utcnt != 0)
2574  for (i = old0; i < typecnt; i++)
2575  if (!omittype[i])
2576  putc(ttisuts[i], fp);
2577  }
2578  fprintf(fp, "\n%s\n", string);
2579  close_file(fp, directory, name);
2580  free(ats);
2581 }
2582 
2583 static char const *
2584 abbroffset(char *buf, zic_t offset)
2585 {
2586  char sign = '+';
2587  int seconds,
2588  minutes;
2589 
2590  if (offset < 0)
2591  {
2592  offset = -offset;
2593  sign = '-';
2594  }
2595 
2596  seconds = offset % SECSPERMIN;
2597  offset /= SECSPERMIN;
2598  minutes = offset % MINSPERHOUR;
2599  offset /= MINSPERHOUR;
2600  if (100 <= offset)
2601  {
2602  error(_("%%z UT offset magnitude exceeds 99:59:59"));
2603  return "%z";
2604  }
2605  else
2606  {
2607  char *p = buf;
2608 
2609  *p++ = sign;
2610  *p++ = '0' + offset / 10;
2611  *p++ = '0' + offset % 10;
2612  if (minutes | seconds)
2613  {
2614  *p++ = '0' + minutes / 10;
2615  *p++ = '0' + minutes % 10;
2616  if (seconds)
2617  {
2618  *p++ = '0' + seconds / 10;
2619  *p++ = '0' + seconds % 10;
2620  }
2621  }
2622  *p = '\0';
2623  return buf;
2624  }
2625 }
2626 
2627 static size_t
2628 doabbr(char *abbr, struct zone const *zp, char const *letters,
2629  bool isdst, zic_t save, bool doquotes)
2630 {
2631  char *cp;
2632  char *slashp;
2633  size_t len;
2634  char const *format = zp->z_format;
2635 
2636  slashp = strchr(format, '/');
2637  if (slashp == NULL)
2638  {
2639  char letterbuf[PERCENT_Z_LEN_BOUND + 1];
2640 
2641  if (zp->z_format_specifier == 'z')
2642  letters = abbroffset(letterbuf, zp->z_stdoff + save);
2643  else if (!letters)
2644  letters = "%s";
2645  sprintf(abbr, format, letters);
2646  }
2647  else if (isdst)
2648  {
2649  strcpy(abbr, slashp + 1);
2650  }
2651  else
2652  {
2653  memcpy(abbr, format, slashp - format);
2654  abbr[slashp - format] = '\0';
2655  }
2656  len = strlen(abbr);
2657  if (!doquotes)
2658  return len;
2659  for (cp = abbr; is_alpha(*cp); cp++)
2660  continue;
2661  if (len > 0 && *cp == '\0')
2662  return len;
2663  abbr[len + 2] = '\0';
2664  abbr[len + 1] = '>';
2665  memmove(abbr + 1, abbr, len);
2666  abbr[0] = '<';
2667  return len + 2;
2668 }
2669 
2670 static void
2672 {
2673  if (min_year > x)
2674  min_year = x;
2675  if (max_year < x)
2676  max_year = x;
2677 }
2678 
2679 static int
2680 stringoffset(char *result, zic_t offset)
2681 {
2682  int hours;
2683  int minutes;
2684  int seconds;
2685  bool negative = offset < 0;
2686  int len = negative;
2687 
2688  if (negative)
2689  {
2690  offset = -offset;
2691  result[0] = '-';
2692  }
2693  seconds = offset % SECSPERMIN;
2694  offset /= SECSPERMIN;
2695  minutes = offset % MINSPERHOUR;
2696  offset /= MINSPERHOUR;
2697  hours = offset;
2698  if (hours >= HOURSPERDAY * DAYSPERWEEK)
2699  {
2700  result[0] = '\0';
2701  return 0;
2702  }
2703  len += sprintf(result + len, "%d", hours);
2704  if (minutes != 0 || seconds != 0)
2705  {
2706  len += sprintf(result + len, ":%02d", minutes);
2707  if (seconds != 0)
2708  len += sprintf(result + len, ":%02d", seconds);
2709  }
2710  return len;
2711 }
2712 
2713 static int
2714 stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
2715 {
2716  zic_t tod = rp->r_tod;
2717  int compat = 0;
2718 
2719  if (rp->r_dycode == DC_DOM)
2720  {
2721  int month,
2722  total;
2723 
2724  if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
2725  return -1;
2726  total = 0;
2727  for (month = 0; month < rp->r_month; ++month)
2728  total += len_months[0][month];
2729  /* Omit the "J" in Jan and Feb, as that's shorter. */
2730  if (rp->r_month <= 1)
2731  result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
2732  else
2733  result += sprintf(result, "J%d", total + rp->r_dayofmonth);
2734  }
2735  else
2736  {
2737  int week;
2738  int wday = rp->r_wday;
2739  int wdayoff;
2740 
2741  if (rp->r_dycode == DC_DOWGEQ)
2742  {
2743  wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
2744  if (wdayoff)
2745  compat = 2013;
2746  wday -= wdayoff;
2747  tod += wdayoff * SECSPERDAY;
2748  week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
2749  }
2750  else if (rp->r_dycode == DC_DOWLEQ)
2751  {
2752  if (rp->r_dayofmonth == len_months[1][rp->r_month])
2753  week = 5;
2754  else
2755  {
2756  wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
2757  if (wdayoff)
2758  compat = 2013;
2759  wday -= wdayoff;
2760  tod += wdayoff * SECSPERDAY;
2761  week = rp->r_dayofmonth / DAYSPERWEEK;
2762  }
2763  }
2764  else
2765  return -1; /* "cannot happen" */
2766  if (wday < 0)
2767  wday += DAYSPERWEEK;
2768  result += sprintf(result, "M%d.%d.%d",
2769  rp->r_month + 1, week, wday);
2770  }
2771  if (rp->r_todisut)
2772  tod += stdoff;
2773  if (rp->r_todisstd && !rp->r_isdst)
2774  tod += save;
2775  if (tod != 2 * SECSPERMIN * MINSPERHOUR)
2776  {
2777  *result++ = '/';
2778  if (!stringoffset(result, tod))
2779  return -1;
2780  if (tod < 0)
2781  {
2782  if (compat < 2013)
2783  compat = 2013;
2784  }
2785  else if (SECSPERDAY <= tod)
2786  {
2787  if (compat < 1994)
2788  compat = 1994;
2789  }
2790  }
2791  return compat;
2792 }
2793 
2794 static int
2795 rule_cmp(struct rule const *a, struct rule const *b)
2796 {
2797  if (!a)
2798  return -!!b;
2799  if (!b)
2800  return 1;
2801  if (a->r_hiyear != b->r_hiyear)
2802  return a->r_hiyear < b->r_hiyear ? -1 : 1;
2803  if (a->r_month - b->r_month != 0)
2804  return a->r_month - b->r_month;
2805  return a->r_dayofmonth - b->r_dayofmonth;
2806 }
2807 
2808 static int
2809 stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
2810 {
2811  const struct zone *zp;
2812  struct rule *rp;
2813  struct rule *stdrp;
2814  struct rule *dstrp;
2815  ptrdiff_t i;
2816  const char *abbrvar;
2817  int compat = 0;
2818  int c;
2819  size_t len;
2820  int offsetlen;
2821  struct rule stdr,
2822  dstr;
2823 
2824  result[0] = '\0';
2825 
2826  /*
2827  * Internet RFC 8536 section 5.1 says to use an empty TZ string if future
2828  * timestamps are truncated.
2829  */
2830  if (hi_time < max_time)
2831  return -1;
2832 
2833  zp = zpfirst + zonecount - 1;
2834  stdrp = dstrp = NULL;
2835  for (i = 0; i < zp->z_nrules; ++i)
2836  {
2837  rp = &zp->z_rules[i];
2838  if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
2839  continue;
2840  if (!rp->r_isdst)
2841  {
2842  if (stdrp == NULL)
2843  stdrp = rp;
2844  else
2845  return -1;
2846  }
2847  else
2848  {
2849  if (dstrp == NULL)
2850  dstrp = rp;
2851  else
2852  return -1;
2853  }
2854  }
2855  if (stdrp == NULL && dstrp == NULL)
2856  {
2857  /*
2858  * There are no rules running through "max". Find the latest std rule
2859  * in stdabbrrp and latest rule of any type in stdrp.
2860  */
2861  struct rule *stdabbrrp = NULL;
2862 
2863  for (i = 0; i < zp->z_nrules; ++i)
2864  {
2865  rp = &zp->z_rules[i];
2866  if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0)
2867  stdabbrrp = rp;
2868  if (rule_cmp(stdrp, rp) < 0)
2869  stdrp = rp;
2870  }
2871  if (stdrp != NULL && stdrp->r_isdst)
2872  {
2873  /* Perpetual DST. */
2874  dstr.r_month = TM_JANUARY;
2875  dstr.r_dycode = DC_DOM;
2876  dstr.r_dayofmonth = 1;
2877  dstr.r_tod = 0;
2878  dstr.r_todisstd = dstr.r_todisut = false;
2879  dstr.r_isdst = stdrp->r_isdst;
2880  dstr.r_save = stdrp->r_save;
2881  dstr.r_abbrvar = stdrp->r_abbrvar;
2882  stdr.r_month = TM_DECEMBER;
2883  stdr.r_dycode = DC_DOM;
2884  stdr.r_dayofmonth = 31;
2885  stdr.r_tod = SECSPERDAY + stdrp->r_save;
2886  stdr.r_todisstd = stdr.r_todisut = false;
2887  stdr.r_isdst = false;
2888  stdr.r_save = 0;
2889  stdr.r_abbrvar
2890  = (stdabbrrp ? stdabbrrp->r_abbrvar : "");
2891  dstrp = &dstr;
2892  stdrp = &stdr;
2893  }
2894  }
2895  if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst))
2896  return -1;
2897  abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
2898  len = doabbr(result, zp, abbrvar, false, 0, true);
2899  offsetlen = stringoffset(result + len, -zp->z_stdoff);
2900  if (!offsetlen)
2901  {
2902  result[0] = '\0';
2903  return -1;
2904  }
2905  len += offsetlen;
2906  if (dstrp == NULL)
2907  return compat;
2908  len += doabbr(result + len, zp, dstrp->r_abbrvar,
2909  dstrp->r_isdst, dstrp->r_save, true);
2910  if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
2911  {
2912  offsetlen = stringoffset(result + len,
2913  -(zp->z_stdoff + dstrp->r_save));
2914  if (!offsetlen)
2915  {
2916  result[0] = '\0';
2917  return -1;
2918  }
2919  len += offsetlen;
2920  }
2921  result[len++] = ',';
2922  c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
2923  if (c < 0)
2924  {
2925  result[0] = '\0';
2926  return -1;
2927  }
2928  if (compat < c)
2929  compat = c;
2930  len += strlen(result + len);
2931  result[len++] = ',';
2932  c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
2933  if (c < 0)
2934  {
2935  result[0] = '\0';
2936  return -1;
2937  }
2938  if (compat < c)
2939  compat = c;
2940  return compat;
2941 }
2942 
2943 static void
2944 outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
2945 {
2946  const struct zone *zp;
2947  struct rule *rp;
2948  ptrdiff_t i,
2949  j;
2950  bool usestart,
2951  useuntil;
2952  zic_t starttime,
2953  untiltime;
2954  zic_t stdoff;
2955  zic_t save;
2956  zic_t year;
2957  zic_t startoff;
2958  bool startttisstd;
2959  bool startttisut;
2960  int type;
2961  char *startbuf;
2962  char *ab;
2963  char *envvar;
2964  int max_abbr_len;
2965  int max_envvar_len;
2966  bool prodstic; /* all rules are min to max */
2967  int compat;
2968  bool do_extend;
2969  char version;
2970  ptrdiff_t lastatmax = -1;
2971  zic_t one = 1;
2972  zic_t y2038_boundary = one << 31;
2973  zic_t max_year0;
2974  int defaulttype = -1;
2975 
2976  max_abbr_len = 2 + max_format_len + max_abbrvar_len;
2977  max_envvar_len = 2 * max_abbr_len + 5 * 9;
2978  startbuf = emalloc(max_abbr_len + 1);
2979  ab = emalloc(max_abbr_len + 1);
2980  envvar = emalloc(max_envvar_len + 1);
2981  INITIALIZE(untiltime);
2982  INITIALIZE(starttime);
2983 
2984  /*
2985  * Now. . .finally. . .generate some useful data!
2986  */
2987  timecnt = 0;
2988  typecnt = 0;
2989  charcnt = 0;
2990  prodstic = zonecount == 1;
2991 
2992  /*
2993  * Thanks to Earl Chew for noting the need to unconditionally initialize
2994  * startttisstd.
2995  */
2996  startttisstd = false;
2997  startttisut = false;
2998  min_year = max_year = EPOCH_YEAR;
2999  if (leapseen)
3000  {
3001  updateminmax(leapminyear);
3002  updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
3003  }
3004  for (i = 0; i < zonecount; ++i)
3005  {
3006  zp = &zpfirst[i];
3007  if (i < zonecount - 1)
3009  for (j = 0; j < zp->z_nrules; ++j)
3010  {
3011  rp = &zp->z_rules[j];
3012  if (rp->r_lowasnum)
3013  updateminmax(rp->r_loyear);
3014  if (rp->r_hiwasnum)
3015  updateminmax(rp->r_hiyear);
3016  if (rp->r_lowasnum || rp->r_hiwasnum)
3017  prodstic = false;
3018  }
3019  }
3020 
3021  /*
3022  * Generate lots of data if a rule can't cover all future times.
3023  */
3024  compat = stringzone(envvar, zpfirst, zonecount);
3025  version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
3026  do_extend = compat < 0;
3027  if (noise)
3028  {
3029  if (!*envvar)
3030  warning("%s %s",
3031  _("no POSIX environment variable for zone"),
3032  zpfirst->z_name);
3033  else if (compat != 0)
3034  {
3035  /*
3036  * Circa-COMPAT clients, and earlier clients, might not work for
3037  * this zone when given dates before 1970 or after 2038.
3038  */
3039  warning(_("%s: pre-%d clients may mishandle"
3040  " distant timestamps"),
3041  zpfirst->z_name, compat);
3042  }
3043  }
3044  if (do_extend)
3045  {
3046  /*
3047  * Search through a couple of extra years past the obvious 400, to
3048  * avoid edge cases. For example, suppose a non-POSIX rule applies
3049  * from 2012 onwards and has transitions in March and September, plus
3050  * some one-off transitions in November 2013. If zic looked only at
3051  * the last 400 years, it would set max_year=2413, with the intent
3052  * that the 400 years 2014 through 2413 will be repeated. The last
3053  * transition listed in the tzfile would be in 2413-09, less than 400
3054  * years after the last one-off transition in 2013-11. Two years
3055  * might be overkill, but with the kind of edge cases available we're
3056  * not sure that one year would suffice.
3057  */
3058  enum
3059  {
3060  years_of_observations = YEARSPERREPEAT + 2};
3061 
3062  if (min_year >= ZIC_MIN + years_of_observations)
3063  min_year -= years_of_observations;
3064  else
3065  min_year = ZIC_MIN;
3066  if (max_year <= ZIC_MAX - years_of_observations)
3067  max_year += years_of_observations;
3068  else
3069  max_year = ZIC_MAX;
3070 
3071  /*
3072  * Regardless of any of the above, for a "proDSTic" zone which
3073  * specifies that its rules always have and always will be in effect,
3074  * we only need one cycle to define the zone.
3075  */
3076  if (prodstic)
3077  {
3078  min_year = 1900;
3079  max_year = min_year + years_of_observations;
3080  }
3081  }
3082  max_year0 = max_year;
3083  if (want_bloat())
3084  {
3085  /*
3086  * For the benefit of older systems, generate data from 1900 through
3087  * 2038.
3088  */
3089  if (min_year > 1900)
3090  min_year = 1900;
3091  if (max_year < 2038)
3092  max_year = 2038;
3093  }
3094 
3095  for (i = 0; i < zonecount; ++i)
3096  {
3097  struct rule *prevrp = NULL;
3098 
3099  /*
3100  * A guess that may well be corrected later.
3101  */
3102  save = 0;
3103  zp = &zpfirst[i];
3104  usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
3105  useuntil = i < (zonecount - 1);
3106  if (useuntil && zp->z_untiltime <= min_time)
3107  continue;
3108  stdoff = zp->z_stdoff;
3109  eat(zp->z_filename, zp->z_linenum);
3110  *startbuf = '\0';
3111  startoff = zp->z_stdoff;
3112  if (zp->z_nrules == 0)
3113  {
3114  save = zp->z_save;
3115  doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
3116  type = addtype(oadd(zp->z_stdoff, save),
3117  startbuf, zp->z_isdst, startttisstd,
3118  startttisut);
3119  if (usestart)
3120  {
3121  addtt(starttime, type);
3122  usestart = false;
3123  }
3124  else
3125  defaulttype = type;
3126  }
3127  else
3128  for (year = min_year; year <= max_year; ++year)
3129  {
3130  if (useuntil && year > zp->z_untilrule.r_hiyear)
3131  break;
3132 
3133  /*
3134  * Mark which rules to do in the current year. For those to
3135  * do, calculate rpytime(rp, year); The former TYPE field was
3136  * also considered here.
3137  */
3138  for (j = 0; j < zp->z_nrules; ++j)
3139  {
3140  rp = &zp->z_rules[j];
3141  eats(zp->z_filename, zp->z_linenum,
3142  rp->r_filename, rp->r_linenum);
3143  rp->r_todo = year >= rp->r_loyear &&
3144  year <= rp->r_hiyear;
3145  if (rp->r_todo)
3146  {
3147  rp->r_temp = rpytime(rp, year);
3148  rp->r_todo
3149  = (rp->r_temp < y2038_boundary
3150  || year <= max_year0);
3151  }
3152  }
3153  for (;;)
3154  {
3155  ptrdiff_t k;
3156  zic_t jtime,
3157  ktime;
3158  zic_t offset;
3159 
3160  INITIALIZE(ktime);
3161  if (useuntil)
3162  {
3163  /*
3164  * Turn untiltime into UT assuming the current stdoff
3165  * and save values.
3166  */
3167  untiltime = zp->z_untiltime;
3168  if (!zp->z_untilrule.r_todisut)
3169  untiltime = tadd(untiltime,
3170  -stdoff);
3171  if (!zp->z_untilrule.r_todisstd)
3172  untiltime = tadd(untiltime,
3173  -save);
3174  }
3175 
3176  /*
3177  * Find the rule (of those to do, if any) that takes
3178  * effect earliest in the year.
3179  */
3180  k = -1;
3181  for (j = 0; j < zp->z_nrules; ++j)
3182  {
3183  rp = &zp->z_rules[j];
3184  if (!rp->r_todo)
3185  continue;
3186  eats(zp->z_filename, zp->z_linenum,
3187  rp->r_filename, rp->r_linenum);
3188  offset = rp->r_todisut ? 0 : stdoff;
3189  if (!rp->r_todisstd)
3190  offset = oadd(offset, save);
3191  jtime = rp->r_temp;
3192  if (jtime == min_time ||
3193  jtime == max_time)
3194  continue;
3195  jtime = tadd(jtime, -offset);
3196  if (k < 0 || jtime < ktime)
3197  {
3198  k = j;
3199  ktime = jtime;
3200  }
3201  else if (jtime == ktime)
3202  {
3203  char const *dup_rules_msg =
3204  _("two rules for same instant");
3205 
3206  eats(zp->z_filename, zp->z_linenum,
3207  rp->r_filename, rp->r_linenum);
3208  warning("%s", dup_rules_msg);
3209  rp = &zp->z_rules[k];
3210  eats(zp->z_filename, zp->z_linenum,
3211  rp->r_filename, rp->r_linenum);
3212  error("%s", dup_rules_msg);
3213  }
3214  }
3215  if (k < 0)
3216  break; /* go on to next year */
3217  rp = &zp->z_rules[k];
3218  rp->r_todo = false;
3219  if (useuntil && ktime >= untiltime)
3220  break;
3221  save = rp->r_save;
3222  if (usestart && ktime == starttime)
3223  usestart = false;
3224  if (usestart)
3225  {
3226  if (ktime < starttime)
3227  {
3228  startoff = oadd(zp->z_stdoff,
3229  save);
3230  doabbr(startbuf, zp,
3231  rp->r_abbrvar,
3232  rp->r_isdst,
3233  rp->r_save,
3234  false);
3235  continue;
3236  }
3237  if (*startbuf == '\0'
3238  && startoff == oadd(zp->z_stdoff,
3239  save))
3240  {
3241  doabbr(startbuf,
3242  zp,
3243  rp->r_abbrvar,
3244  rp->r_isdst,
3245  rp->r_save,
3246  false);
3247  }
3248  }
3249  eats(zp->z_filename, zp->z_linenum,
3250  rp->r_filename, rp->r_linenum);
3251  doabbr(ab, zp, rp->r_abbrvar,
3252  rp->r_isdst, rp->r_save, false);
3253  offset = oadd(zp->z_stdoff, rp->r_save);
3254  if (!want_bloat() && !useuntil && !do_extend
3255  && prevrp
3256  && rp->r_hiyear == ZIC_MAX
3257  && prevrp->r_hiyear == ZIC_MAX)
3258  break;
3259  type = addtype(offset, ab, rp->r_isdst,
3260  rp->r_todisstd, rp->r_todisut);
3261  if (defaulttype < 0 && !rp->r_isdst)
3262  defaulttype = type;
3263  if (rp->r_hiyear == ZIC_MAX
3264  && !(0 <= lastatmax
3265  && ktime < attypes[lastatmax].at))
3266  lastatmax = timecnt;
3267  addtt(ktime, type);
3268  prevrp = rp;
3269  }
3270  }
3271  if (usestart)
3272  {
3273  if (*startbuf == '\0' &&
3274  zp->z_format != NULL &&
3275  strchr(zp->z_format, '%') == NULL &&
3276  strchr(zp->z_format, '/') == NULL)
3277  strcpy(startbuf, zp->z_format);
3278  eat(zp->z_filename, zp->z_linenum);
3279  if (*startbuf == '\0')
3280  error(_("cannot determine time zone abbreviation to use just after until time"));
3281  else
3282  {
3283  bool isdst = startoff != zp->z_stdoff;
3284 
3285  type = addtype(startoff, startbuf, isdst,
3286  startttisstd, startttisut);
3287  if (defaulttype < 0 && !isdst)
3288  defaulttype = type;
3289  addtt(starttime, type);
3290  }
3291  }
3292 
3293  /*
3294  * Now we may get to set starttime for the next zone line.
3295  */
3296  if (useuntil)
3297  {
3298  startttisstd = zp->z_untilrule.r_todisstd;
3299  startttisut = zp->z_untilrule.r_todisut;
3300  starttime = zp->z_untiltime;
3301  if (!startttisstd)
3302  starttime = tadd(starttime, -save);
3303  if (!startttisut)
3304  starttime = tadd(starttime, -stdoff);
3305  }
3306  }
3307  if (defaulttype < 0)
3308  defaulttype = 0;
3309  if (0 <= lastatmax)
3310  attypes[lastatmax].dontmerge = true;
3311  if (do_extend)
3312  {
3313  /*
3314  * If we're extending the explicitly listed observations for 400 years
3315  * because we can't fill the POSIX-TZ field, check whether we actually
3316  * ended up explicitly listing observations through that period. If
3317  * there aren't any near the end of the 400-year period, add a
3318  * redundant one at the end of the final year, to make it clear that
3319  * we are claiming to have definite knowledge of the lack of
3320  * transitions up to that point.
3321  */
3322  struct rule xr;
3323  struct attype *lastat;
3324 
3325  xr.r_month = TM_JANUARY;
3326  xr.r_dycode = DC_DOM;
3327  xr.r_dayofmonth = 1;
3328  xr.r_tod = 0;
3329  for (lastat = attypes, i = 1; i < timecnt; i++)
3330  if (attypes[i].at > lastat->at)
3331  lastat = &attypes[i];
3332  if (!lastat || lastat->at < rpytime(&xr, max_year - 1))
3333  {
3334  addtt(rpytime(&xr, max_year + 1),
3335  lastat ? lastat->type : defaulttype);
3336  attypes[timecnt - 1].dontmerge = true;
3337  }
3338  }
3339  writezone(zpfirst->z_name, envvar, version, defaulttype);
3340  free(startbuf);
3341  free(ab);
3342  free(envvar);
3343 }
3344 
3345 static void
3346 addtt(zic_t starttime, int type)
3347 {
3348  attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
3349  attypes[timecnt].at = starttime;
3350  attypes[timecnt].dontmerge = false;
3351  attypes[timecnt].type = type;
3352  ++timecnt;
3353 }
3354 
3355 static int
3356 addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
3357 {
3358  int i,
3359  j;
3360 
3361  if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
3362  {
3363  error(_("UT offset out of range"));
3364  exit(EXIT_FAILURE);
3365  }
3366  if (!want_bloat())
3367  ttisstd = ttisut = false;
3368 
3369  for (j = 0; j < charcnt; ++j)
3370  if (strcmp(&chars[j], abbr) == 0)
3371  break;
3372  if (j == charcnt)
3373  newabbr(abbr);
3374  else
3375  {
3376  /* If there's already an entry, return its index. */
3377  for (i = 0; i < typecnt; i++)
3378  if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
3379  && ttisstd == ttisstds[i] && ttisut == ttisuts[i])
3380  return i;
3381  }
3382 
3383  /*
3384  * There isn't one; add a new one, unless there are already too many.
3385  */
3386  if (typecnt >= TZ_MAX_TYPES)
3387  {
3388  error(_("too many local time types"));
3389  exit(EXIT_FAILURE);
3390  }
3391  i = typecnt++;
3392  utoffs[i] = utoff;
3393  isdsts[i] = isdst;
3394  ttisstds[i] = ttisstd;
3395  ttisuts[i] = ttisut;
3396  desigidx[i] = j;
3397  return i;
3398 }
3399 
3400 static void
3401 leapadd(zic_t t, int correction, int rolling)
3402 {
3403  int i;
3404 
3405  if (TZ_MAX_LEAPS <= leapcnt)
3406  {
3407  error(_("too many leap seconds"));
3408  exit(EXIT_FAILURE);
3409  }
3410  for (i = 0; i < leapcnt; ++i)
3411  if (t <= trans[i])
3412  break;
3413  memmove(&trans[i + 1], &trans[i], (leapcnt - i) * sizeof *trans);
3414  memmove(&corr[i + 1], &corr[i], (leapcnt - i) * sizeof *corr);
3415  memmove(&roll[i + 1], &roll[i], (leapcnt - i) * sizeof *roll);
3416  trans[i] = t;
3417  corr[i] = correction;
3418  roll[i] = rolling;
3419  ++leapcnt;
3420 }
3421 
3422 static void
3423 adjleap(void)
3424 {
3425  int i;
3426  zic_t last = 0;
3427  zic_t prevtrans = 0;
3428 
3429  /*
3430  * propagate leap seconds forward
3431  */
3432  for (i = 0; i < leapcnt; ++i)
3433  {
3434  if (trans[i] - prevtrans < 28 * SECSPERDAY)
3435  {
3436  error(_("Leap seconds too close together"));
3437  exit(EXIT_FAILURE);
3438  }
3439  prevtrans = trans[i];
3440  trans[i] = tadd(trans[i], last);
3441  last = corr[i] += last;
3442  }
3443 
3444  if (leapexpires < 0)
3445  {
3446  leapexpires = comment_leapexpires;
3447  if (0 <= leapexpires)
3448  warning(_("\"#expires\" is obsolescent; use \"Expires\""));
3449  }
3450 
3451  if (0 <= leapexpires)
3452  {
3453  leapexpires = oadd(leapexpires, last);
3454  if (!(leapcnt == 0 || (trans[leapcnt - 1] < leapexpires)))
3455  {
3456  error(_("last Leap time does not precede Expires time"));
3457  exit(EXIT_FAILURE);
3458  }
3459  if (leapexpires <= hi_time)
3460  hi_time = leapexpires - 1;
3461  }
3462 }
3463 
3464 /* Is A a space character in the C locale? */
3465 static bool
3466 is_space(char a)
3467 {
3468  switch (a)
3469  {
3470  default:
3471  return false;
3472  case ' ':
3473  case '\f':
3474  case '\n':
3475  case '\r':
3476  case '\t':
3477  case '\v':
3478  return true;
3479  }
3480 }
3481 
3482 /* Is A an alphabetic character in the C locale? */
3483 static bool
3484 is_alpha(char a)
3485 {
3486  switch (a)
3487  {
3488  default:
3489  return false;
3490  case 'A':
3491  case 'B':
3492  case 'C':
3493  case 'D':
3494  case 'E':
3495  case 'F':
3496  case 'G':
3497  case 'H':
3498  case 'I':
3499  case 'J':
3500  case 'K':
3501  case 'L':
3502  case 'M':
3503  case 'N':
3504  case 'O':
3505  case 'P':
3506  case 'Q':
3507  case 'R':
3508  case 'S':
3509  case 'T':
3510  case 'U':
3511  case 'V':
3512  case 'W':
3513  case 'X':
3514  case 'Y':
3515  case 'Z':
3516  case 'a':
3517  case 'b':
3518  case 'c':
3519  case 'd':
3520  case 'e':
3521  case 'f':
3522  case 'g':
3523  case 'h':
3524  case 'i':
3525  case 'j':
3526  case 'k':
3527  case 'l':
3528  case 'm':
3529  case 'n':
3530  case 'o':
3531  case 'p':
3532  case 'q':
3533  case 'r':
3534  case 's':
3535  case 't':
3536  case 'u':
3537  case 'v':
3538  case 'w':
3539  case 'x':
3540  case 'y':
3541  case 'z':
3542  return true;
3543  }
3544 }
3545 
3546 /* If A is an uppercase character in the C locale, return its lowercase
3547  counterpart. Otherwise, return A. */
3548 static char
3549 lowerit(char a)
3550 {
3551  switch (a)
3552  {
3553  default:
3554  return a;
3555  case 'A':
3556  return 'a';
3557  case 'B':
3558  return 'b';
3559  case 'C':
3560  return 'c';
3561  case 'D':
3562  return 'd';
3563  case 'E':
3564  return 'e';
3565  case 'F':
3566  return 'f';
3567  case 'G':
3568  return 'g';
3569  case 'H':
3570  return 'h';
3571  case 'I':
3572  return 'i';
3573  case 'J':
3574  return 'j';
3575  case 'K':
3576  return 'k';
3577  case 'L':
3578  return 'l';
3579  case 'M':
3580  return 'm';
3581  case 'N':
3582  return 'n';
3583  case 'O':
3584  return 'o';
3585  case 'P':
3586  return 'p';
3587  case 'Q':
3588  return 'q';
3589  case 'R':
3590  return 'r';
3591  case 'S':
3592  return 's';
3593  case 'T':
3594  return 't';
3595  case 'U':
3596  return 'u';
3597  case 'V':
3598  return 'v';
3599  case 'W':
3600  return 'w';
3601  case 'X':
3602  return 'x';
3603  case 'Y':
3604  return 'y';
3605  case 'Z':
3606  return 'z';
3607  }
3608 }
3609 
3610 /* case-insensitive equality */
3611 static bool
3612 ciequal(const char *ap, const char *bp)
3613 {
3614  while (lowerit(*ap) == lowerit(*bp++))
3615  if (*ap++ == '\0')
3616  return true;
3617  return false;
3618 }
3619 
3620 static bool
3621 itsabbr(const char *abbr, const char *word)
3622 {
3623  if (lowerit(*abbr) != lowerit(*word))
3624  return false;
3625  ++word;
3626  while (*++abbr != '\0')
3627  do
3628  {
3629  if (*word == '\0')
3630  return false;
3631  } while (lowerit(*word++) != lowerit(*abbr));
3632  return true;
3633 }
3634 
3635 /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
3636 
3637 static bool
3638 ciprefix(char const *abbr, char const *word)
3639 {
3640  do
3641  if (!*abbr)
3642  return true;
3643  while (lowerit(*abbr++) == lowerit(*word++));
3644 
3645  return false;
3646 }
3647 
3648 static const struct lookup *
3649 byword(const char *word, const struct lookup *table)
3650 {
3651  const struct lookup *foundlp;
3652  const struct lookup *lp;
3653 
3654  if (word == NULL || table == NULL)
3655  return NULL;
3656 
3657  /*
3658  * If TABLE is LASTS and the word starts with "last" followed by a
3659  * non-'-', skip the "last" and look in WDAY_NAMES instead. Warn about any
3660  * usage of the undocumented prefix "last-".
3661  */
3662  if (table == lasts && ciprefix("last", word) && word[4])
3663  {
3664  if (word[4] == '-')
3665  warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
3666  word, word + 5);
3667  else
3668  {
3669  word += 4;
3670  table = wday_names;
3671  }
3672  }
3673 
3674  /*
3675  * Look for exact match.
3676  */
3677  for (lp = table; lp->l_word != NULL; ++lp)
3678  if (ciequal(word, lp->l_word))
3679  return lp;
3680 
3681  /*
3682  * Look for inexact match.
3683  */
3684  foundlp = NULL;
3685  for (lp = table; lp->l_word != NULL; ++lp)
3686  if (ciprefix(word, lp->l_word))
3687  {
3688  if (foundlp == NULL)
3689  foundlp = lp;
3690  else
3691  return NULL; /* multiple inexact matches */
3692  }
3693 
3694  if (foundlp && noise)
3695  {
3696  /* Warn about any backward-compatibility issue with pre-2017c zic. */
3697  bool pre_2017c_match = false;
3698 
3699  for (lp = table; lp->l_word; lp++)
3700  if (itsabbr(word, lp->l_word))
3701  {
3702  if (pre_2017c_match)
3703  {
3704  warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
3705  break;
3706  }
3707  pre_2017c_match = true;
3708  }
3709  }
3710 
3711  return foundlp;
3712 }
3713 
3714 static char **
3715 getfields(char *cp)
3716 {
3717  char *dp;
3718  char **array;
3719  int nsubs;
3720 
3721  if (cp == NULL)
3722  return NULL;
3723  array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
3724  nsubs = 0;
3725  for (;;)
3726  {
3727  while (is_space(*cp))
3728  ++cp;
3729  if (*cp == '\0' || *cp == '#')
3730  break;
3731  array[nsubs++] = dp = cp;
3732  do
3733  {
3734  if ((*dp = *cp++) != '"')
3735  ++dp;
3736  else
3737  while ((*dp = *cp++) != '"')
3738  if (*dp != '\0')
3739  ++dp;
3740  else
3741  {
3742  error(_("Odd number of quotation marks"));
3743  exit(EXIT_FAILURE);
3744  }
3745  } while (*cp && *cp != '#' && !is_space(*cp));
3746  if (is_space(*cp))
3747  ++cp;
3748  *dp = '\0';
3749  }
3750  array[nsubs] = NULL;
3751  return array;
3752 }
3753 
3754 static void
3756 {
3757  error(_("time overflow"));
3758  exit(EXIT_FAILURE);
3759 }
3760 
3761 static zic_t
3763 {
3764  if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
3765  time_overflow();
3766  return t1 + t2;
3767 }
3768 
3769 static zic_t
3771 {
3772  if (t1 < 0)
3773  {
3774  if (t2 < min_time - t1)
3775  {
3776  if (t1 != min_time)
3777  time_overflow();
3778  return min_time;
3779  }
3780  }
3781  else
3782  {
3783  if (max_time - t1 < t2)
3784  {
3785  if (t1 != max_time)
3786  time_overflow();
3787  return max_time;
3788  }
3789  }
3790  return t1 + t2;
3791 }
3792 
3793 /*
3794  * Given a rule, and a year, compute the date (in seconds since January 1,
3795  * 1970, 00:00 LOCAL time) in that year that the rule refers to.
3796  */
3797 
3798 static zic_t
3799 rpytime(const struct rule *rp, zic_t wantedy)
3800 {
3801  int m,
3802  i;
3803  zic_t dayoff; /* with a nod to Margaret O. */
3804  zic_t t,
3805  y;
3806 
3807  if (wantedy == ZIC_MIN)
3808  return min_time;
3809  if (wantedy == ZIC_MAX)
3810  return max_time;
3811  dayoff = 0;
3812  m = TM_JANUARY;
3813  y = EPOCH_YEAR;
3814  if (y < wantedy)
3815  {
3816  wantedy -= y;
3817  dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
3818  wantedy %= YEARSPERREPEAT;
3819  wantedy += y;
3820  }
3821  else if (wantedy < 0)
3822  {
3823  dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
3824  wantedy %= YEARSPERREPEAT;
3825  }
3826  while (wantedy != y)
3827  {
3828  if (wantedy > y)
3829  {
3830  i = len_years[isleap(y)];
3831  ++y;
3832  }
3833  else
3834  {
3835  --y;
3836  i = -len_years[isleap(y)];
3837  }
3838  dayoff = oadd(dayoff, i);
3839  }
3840  while (m != rp->r_month)
3841  {
3842  i = len_months[isleap(y)][m];
3843  dayoff = oadd(dayoff, i);
3844  ++m;
3845  }
3846  i = rp->r_dayofmonth;
3847  if (m == TM_FEBRUARY && i == 29 && !isleap(y))
3848  {
3849  if (rp->r_dycode == DC_DOWLEQ)
3850  --i;
3851  else
3852  {
3853  error(_("use of 2/29 in non leap-year"));
3854  exit(EXIT_FAILURE);
3855  }
3856  }
3857  --i;
3858  dayoff = oadd(dayoff, i);
3859  if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ)
3860  {
3861  zic_t wday;
3862 
3863 #define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3864  wday = EPOCH_WDAY;
3865 
3866  /*
3867  * Don't trust mod of negative numbers.
3868  */
3869  if (dayoff >= 0)
3870  wday = (wday + dayoff) % LDAYSPERWEEK;
3871  else
3872  {
3873  wday -= ((-dayoff) % LDAYSPERWEEK);
3874  if (wday < 0)
3875  wday += LDAYSPERWEEK;
3876  }
3877  while (wday != rp->r_wday)
3878  if (rp->r_dycode == DC_DOWGEQ)
3879  {
3880  dayoff = oadd(dayoff, 1);
3881  if (++wday >= LDAYSPERWEEK)
3882  wday = 0;
3883  ++i;
3884  }
3885  else
3886  {
3887  dayoff = oadd(dayoff, -1);
3888  if (--wday < 0)
3889  wday = LDAYSPERWEEK - 1;
3890  --i;
3891  }
3892  if (i < 0 || i >= len_months[isleap(y)][m])
3893  {
3894  if (noise)
3895  warning(_("rule goes past start/end of month; \
3896 will not work with pre-2004 versions of zic"));
3897  }
3898  }
3899  if (dayoff < min_time / SECSPERDAY)
3900  return min_time;
3901  if (dayoff > max_time / SECSPERDAY)
3902  return max_time;
3903  t = (zic_t) dayoff * SECSPERDAY;
3904  return tadd(t, rp->r_tod);
3905 }
3906 
3907 static void
3908 newabbr(const char *string)
3909 {
3910  int i;
3911 
3912  if (strcmp(string, GRANDPARENTED) != 0)
3913  {
3914  const char *cp;
3915  const char *mp;
3916 
3917  cp = string;
3918  mp = NULL;
3919  while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
3920  || *cp == '-' || *cp == '+')
3921  ++cp;
3922  if (noise && cp - string < 3)
3923  mp = _("time zone abbreviation has fewer than 3 characters");
3924  if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
3925  mp = _("time zone abbreviation has too many characters");
3926  if (*cp != '\0')
3927  mp = _("time zone abbreviation differs from POSIX standard");
3928  if (mp != NULL)
3929  warning("%s (%s)", mp, string);
3930  }
3931  i = strlen(string) + 1;
3932  if (charcnt + i > TZ_MAX_CHARS)
3933  {
3934  error(_("too many, or too long, time zone abbreviations"));
3935  exit(EXIT_FAILURE);
3936  }
3937  strcpy(&chars[charcnt], string);
3938  charcnt += i;
3939 }
3940 
3941 /* Ensure that the directories of ARGNAME exist, by making any missing
3942  ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
3943  do it for ARGNAME too. Exit with failure if there is trouble.
3944  Do not consider an existing non-directory to be trouble. */
3945 static void
3946 mkdirs(char const *argname, bool ancestors)
3947 {
3948  char *name;
3949  char *cp;
3950 
3951  cp = name = ecpyalloc(argname);
3952 
3953  /*
3954  * On MS-Windows systems, do not worry about drive letters or backslashes,
3955  * as this should suffice in practice. Time zone names do not use drive
3956  * letters and backslashes. If the -d option of zic does not name an
3957  * already-existing directory, it can use slashes to separate the
3958  * already-existing ancestor prefix from the to-be-created subdirectories.
3959  */
3960 
3961  /* Do not mkdir a root directory, as it must exist. */
3962  while (*cp == '/')
3963  cp++;
3964 
3965  while (cp && ((cp = strchr(cp, '/')) || !ancestors))
3966  {
3967  if (cp)
3968  *cp = '\0';
3969 
3970  /*
3971  * Try to create it. It's OK if creation fails because the directory
3972  * already exists, perhaps because some other process just created it.
3973  * For simplicity do not check first whether it already exists, as
3974  * that is checked anyway if the mkdir fails.
3975  */
3976  if (mkdir(name, MKDIR_UMASK) != 0)
3977  {
3978  /*
3979  * For speed, skip itsdir if errno == EEXIST. Since mkdirs is
3980  * called only after open fails with ENOENT on a subfile, EEXIST
3981  * implies itsdir here.
3982  */
3983  int err = errno;
3984 
3985  if (err != EEXIST && !itsdir(name))
3986  {
3987  error(_("%s: Cannot create directory %s: %s"),
3988  progname, name, strerror(err));
3989  exit(EXIT_FAILURE);
3990  }
3991  }
3992  if (cp)
3993  *cp++ = '/';
3994  }
3995  free(name);
3996 }
3997 
3998 
3999 #ifdef WIN32
4000 /*
4001  * To run on win32
4002  */
4003 int
4004 link(const char *oldpath, const char *newpath)
4005 {
4006  if (!CopyFile(oldpath, newpath, false))
4007  {
4008  _dosmaperr(GetLastError());
4009  return -1;
4010  }
4011  return 0;
4012 }
4013 #endif
#define TZDEFAULT
Definition: tzfile.h:27
static bool ciprefix(char const *abbr, char const *word)
Definition: zic.c:3638
static bool ttisstds[TZ_MAX_TYPES]
Definition: zic.c:397
#define LP_CORR
Definition: zic.c:266
static ptrdiff_t nlinks
Definition: zic.c:298
#define ZF_TILMONTH
Definition: zic.c:215
static zic_t leapmaxyear
Definition: zic.c:180
#define pg_attribute_noreturn()
Definition: c.h:167
lineno_t r_linenum
Definition: zic.c:60
static int rcomp(const void *cp1, const void *cp2)
Definition: zic.c:1149
#define SECSPERMIN
Definition: private.h:101
static bool print_abbrevs
Definition: zic.c:187
#define YR_MINIMUM
Definition: zic.c:277
static zic_t print_cutoff
Definition: zic.c:188
static int typecnt
Definition: zic.c:194
zic_t z_save
Definition: zic.c:105
static void change_directory(char const *dir)
Definition: zic.c:560
#define PG_INT64_MAX
Definition: c.h:515
#define TM_MARCH
Definition: private.h:121
static void inexpires(char **, int)
Definition: zic.c:1785
static struct lookup const zi_line_codes[]
Definition: zic.c:310
zic_t r_tod
Definition: zic.c:74
static int stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
Definition: zic.c:2809
#define TM_THURSDAY
Definition: private.h:115
#define EXIT_SUCCESS
Definition: settings.h:157
static struct lookup const leap_line_codes[]
Definition: zic.c:316
static int bloat
Definition: zic.c:639
#define ZF_TILTIME
Definition: zic.c:217
Definition: zic.c:388
#define ZF_TILYEAR
Definition: zic.c:214
struct typedefs * types
Definition: ecpg.c:29
#define ZF_NAME
Definition: zic.c:210
#define TM_FRIDAY
Definition: private.h:116
unsigned char type
Definition: zic.c:392
#define ZFC_TILMONTH
Definition: zic.c:229
bool r_todisstd
Definition: zic.c:75
static zic_t lo_time
Definition: zic.c:588
static char isdsts[TZ_MAX_TYPES]
Definition: zic.c:395
ptrdiff_t count
Definition: zic.c:2046
static char * ecpyalloc(char const *str)
Definition: zic.c:444
#define ZF_RULE
Definition: zic.c:212
static void static void static void warning(const char *string,...) pg_attribute_printf(1
Definition: zic.c:513
static void inrule(char **fields, int nfields)
Definition: zic.c:1469
static zic_t corr[TZ_MAX_LEAPS]
Definition: zic.c:401
int r_month
Definition: zic.c:68
#define DC_DOWGEQ
Definition: zic.c:90
static struct lookup const begin_years[]
Definition: zic.c:360
#define TM_APRIL
Definition: private.h:122
#define TM_SATURDAY
Definition: private.h:117
#define TM_JULY
Definition: private.h:125
static void addtt(zic_t starttime, int type)
Definition: zic.c:3346
#define RF_COMMAND
Definition: zic.c:242
static bool errors
Definition: zic.c:174
#define ZF_STDOFF
Definition: zic.c:211
#define SECSPERDAY
Definition: private.h:108
#define isleap(y)
Definition: datetime.h:271
#define ENOTSUP
Definition: private.h:38
static void associate(void)
Definition: zic.c:1156
#define INITIALIZE(x)
Definition: private.h:92
#define S_IWOTH
Definition: win32_port.h:307
const char * z_format
Definition: zic.c:101
zic_t r_save
Definition: zic.c:78
#define LC_LEAP
Definition: zic.c:203
void _dosmaperr(unsigned long)
Definition: win32error.c:171
#define TM_DECEMBER
Definition: private.h:130
static int rule_cmp(struct rule const *a, struct rule const *b)
Definition: zic.c:2795
#define SECSPERHOUR
Definition: private.h:107
#define DC_DOM
Definition: zic.c:89
#define MONSPERYEAR
Definition: private.h:109
static zic_t hi_time
Definition: zic.c:589
zic_t z_untiltime
Definition: zic.c:111
#define HOURSPERDAY
Definition: private.h:103
#define TZ_MAX_TIMES
Definition: tzfile.h:100
#define printf(...)
Definition: port.h:221
#define DAYSPERNYEAR
Definition: private.h:105
#define ZIC_BLOAT_DEFAULT
Definition: zic.c:648
static ptrdiff_t nzones
Definition: zic.c:286
struct rule z_untilrule
Definition: zic.c:110
static zic_t min_year
Definition: zic.c:185
static const int len_months[2][MONSPERYEAR]
Definition: zic.c:379
char tzh_timecnt[4]
Definition: tzfile.h:47
NameData relname
Definition: pg_class.h:38
static void updateminmax(const zic_t x)
Definition: zic.c:2671
#define ZONEC_MAXFIELDS
Definition: zic.c:233
#define ZFC_FORMAT
Definition: zic.c:227
static bool warnings
Definition: zic.c:175
int leapbase
Definition: zic.c:2048
static const char * leapsec
Definition: zic.c:633
#define fprintf
Definition: port.h:219
static int max_format_len
Definition: zic.c:183
static int stringoffset(char *result, zic_t offset)
Definition: zic.c:2680
const int l_value
Definition: zic.c:304
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:71
static void mkdirs(char const *, bool)
Definition: zic.c:3946
bool z_isdst
Definition: zic.c:104
char tzh_ttisutcnt[4]
Definition: tzfile.h:44
#define TM_AUGUST
Definition: private.h:126
#define LP_ROLL
Definition: zic.c:267
static lineno_t rlinenum
Definition: zic.c:190
Definition: localtime.c:72
signed int int32
Definition: c.h:417
static const char * filename
Definition: zic.c:176
#define pg_attribute_printf(f, a)
Definition: c.h:152
#define GRANDPARENTED
Definition: private.h:30
bool r_lowasnum
Definition: zic.c:65
static void inleap(char **fields, int nfields)
Definition: zic.c:1753
char z_format_specifier
Definition: zic.c:102
static char ** getfields(char *buf)
Definition: zic.c:3715
#define DAYSPERLYEAR
Definition: private.h:106
char * z_rule
Definition: zic.c:100
static struct pg_tm tm
Definition: localtime.c:102
static const char * psxrules
Definition: zic.c:630
#define TM_SEPTEMBER
Definition: private.h:127
#define malloc(a)
Definition: header.h:50
#define ZIC_MAX
Definition: zic.c:27
static bool itsdir(char const *)
Definition: zic.c:1104
const char * r_name
Definition: zic.c:61
static char const * abbroffset(char *buf, zic_t offset)
Definition: zic.c:2584
#define TM_MAY
Definition: private.h:123
#define ZF_FORMAT
Definition: zic.c:213
static void static void static void static void usage(FILE *stream, int status) pg_attribute_noreturn()
Definition: zic.c:541
#define LDAYSPERWEEK
#define ZFC_STDOFF
Definition: zic.c:225
#define TZ_MAX_LEAPS
Definition: tzfile.h:108
static void verror(const char *string, va_list args) pg_attribute_printf(1
Definition: zic.c:486
#define sprintf
Definition: port.h:217
static void leapadd(zic_t, int, int)
Definition: zic.c:3401
static bool is_alpha(char a)
Definition: zic.c:3484
const char * z_filename
Definition: zic.c:95
#define YR_ONLY
Definition: zic.c:279
static void dolink(const char *, const char *, bool)
Definition: zic.c:1002
static zic_t tadd(zic_t t1, zic_t t2)
Definition: zic.c:3770
static bool is_space(char a)
Definition: zic.c:3466
static void convert(const int32 val, char *const buf)
Definition: zic.c:1990
static zic_t comment_leapexpires
Definition: zic.c:595
int optind
Definition: getopt.c:50
#define TIME_T_BITS_IN_FILE
Definition: zic.c:580
static zic_t gethms(const char *string, const char *errstring)
Definition: zic.c:1363
static lineno_t linenum
Definition: zic.c:181
static bool inzcont(char **fields, int nfields)
Definition: zic.c:1554
static int hardlinkerr(char const *target, char const *linkname)
Definition: zic.c:994
static int addtype(zic_t, char const *, bool, bool, bool)
Definition: zic.c:3356
#define LF_LINKNAME
Definition: zic.c:255
char tzh_magic[4]
Definition: tzfile.h:41
#define LEAP_FIELDS
Definition: zic.c:268
static bool inzsub(char **, int, bool)
Definition: zic.c:1565
bool r_todo
Definition: zic.c:81
#define TM_OCTOBER
Definition: private.h:128
static void writezone(const char *const name, const char *const string, char version, int defaulttype)
Definition: zic.c:2080
int defaulttype
Definition: zic.c:2045
static size_t doabbr(char *abbr, struct zone const *zp, char const *letters, bool isdst, zic_t save, bool doquotes)
Definition: zic.c:2628
#define DAYSPERWEEK
Definition: private.h:104
static const char * rfilename
Definition: zic.c:189
static struct lookup const mon_names[]
Definition: zic.c:322
#define ZONE_MAXFIELDS
Definition: zic.c:219
static bool componentcheck(char const *name, char const *component, char const *component_end)
Definition: zic.c:857
char sign
Definition: informix.c:668
#define TZ_MAGIC
Definition: tzfile.h:37
#define LP_DAY
Definition: zic.c:264
#define ZIC_VERSION_PRE_2013
Definition: zic.c:22
bool r_isdst
Definition: zic.c:77
#define MINVAL(t, b)
Definition: private.h:72
char * c
static bool leapseen
Definition: zic.c:178
static char * buf
Definition: pg_test_fsync.c:68
#define symlink(oldpath, newpath)
Definition: win32_port.h:227
#define PG_INT64_MIN
Definition: c.h:514
#define ZIC_VERSION
Definition: zic.c:23
static void adjleap(void)
Definition: zic.c:3423
static int stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
Definition: zic.c:2714
#define readlink(path, buf, size)
Definition: win32_port.h:228
static const char * lcltime
Definition: zic.c:631
char string[11]
Definition: preproc-type.c:46
static int leapcnt
Definition: zic.c:177
static ptrdiff_t nzones_alloc
Definition: zic.c:287
static int max_abbrvar_len
Definition: zic.c:182
#define ZFC_TILTIME
Definition: zic.c:231
int64 zic_t
Definition: zic.c:25
static struct rule * rules
Definition: zic.c:281
Definition: zic.c:301
zic_t r_hiyear
Definition: zic.c:64
#define S_IWGRP
Definition: win32_port.h:295
static bool ciequal(const char *ap, const char *bp)
Definition: zic.c:3612
static zic_t getleapdatetime(char **fields, int nfields, bool expire_line)
Definition: zic.c:1664
zic_t r_temp
Definition: zic.c:82
#define ZIC_MIN
Definition: zic.c:26
static zic_t leapexpires
Definition: zic.c:592
char tzh_leapcnt[4]
Definition: tzfile.h:46
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
Definition: zic.c:450
bool r_todisut
Definition: zic.c:76
#define PG_INT32_MIN
Definition: c.h:511
static struct lookup const end_years[]
Definition: zic.c:366
const char * r_filename
Definition: zic.c:59
#define RF_SAVE
Definition: zic.c:246
#define ZFC_RULE
Definition: zic.c:226
enum COMPAT_MODE compat
Definition: ecpg.c:25
int r_dycode
Definition: zic.c:70
#define ZIC_MAX_ABBR_LEN_WO_WARN
Definition: zic.c:30
static zic_t utoffs[TZ_MAX_TYPES]
Definition: zic.c:394
const char * l_word
Definition: zic.c:303
#define TZ_MAX_CHARS
Definition: tzfile.h:105
#define TM_SUNDAY
Definition: private.h:111
zic_t at
Definition: zic.c:390
#define EPOCH_YEAR
Definition: private.h:134
#define DC_DOWLEQ
Definition: zic.c:91
#define LP_TIME
Definition: zic.c:265
static zic_t rpytime(const struct rule *rp, zic_t wantedy)
Definition: zic.c:3799
static ptrdiff_t timecnt_alloc
Definition: zic.c:193
#define strtoimax
Definition: private.h:52
static ptrdiff_t nlinks_alloc
Definition: zic.c:299
static bool itssymlink(char const *)
Definition: zic.c:1129
#define LC_LINK
Definition: zic.c:202
static void time_overflow(void)
Definition: zic.c:3755
static void eat(char const *name, lineno_t num)
Definition: zic.c:480
#define ZF_TILDAY
Definition: zic.c:216
const char * r_abbrvar
Definition: zic.c:79
unsigned short st_mode
Definition: win32_port.h:260
#define RF_HIYEAR
Definition: zic.c:241
static struct attype * attypes
#define LC_ZONE
Definition: zic.c:201
static zic_t const max_time
Definition: zic.c:584
int leapcount
Definition: zic.c:2048
static bool noise
Definition: zic.c:186
static struct link * links
Definition: zic.c:297
ptrdiff_t z_nrules
Definition: zic.c:108
Definition: tzfile.h:39
#define TM_JANUARY
Definition: private.h:119
static void puttzcodepass(zic_t val, FILE *fp, int pass)
Definition: zic.c:2021
static void infile(const char *filename)
Definition: zic.c:1241
int main(int argc, char **argv)
Definition: zic.c:652
lineno_t z_linenum
Definition: zic.c:96
char tzh_typecnt[4]
Definition: tzfile.h:48
#define TM_FEBRUARY
Definition: private.h:120
static const char * progname
Definition: zic.c:191
static zic_t max_year
Definition: zic.c:184
#define free(a)
Definition: header.h:65
#define TM_JUNE
Definition: private.h:124
static bool inzone(char **fields, int nfields)
Definition: zic.c:1516
#define LINK_FIELDS
Definition: zic.c:256
char tzh_version[1]
Definition: tzfile.h:42
int r_dayofmonth
Definition: zic.c:71
int r_wday
Definition: zic.c:72
char tzh_charcnt[4]
Definition: tzfile.h:49
ptrdiff_t base
Definition: zic.c:2046
#define TZDEFRULES
Definition: tzfile.h:28
#define MKDIR_UMASK
Definition: zic.c:37
#define LC_EXPIRES
Definition: zic.c:204
static ptrdiff_t timecnt
Definition: zic.c:192
#define RF_NAME
Definition: zic.c:239
static ptrdiff_t nrules_alloc
Definition: zic.c:283
static void rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, const char *typep, const char *monthp, const char *dayp, const char *timep)
Definition: zic.c:1821
static void inlink(char **fields, int nfields)
Definition: zic.c:1796
static zic_t getsave(char *, bool *)
Definition: zic.c:1441
#define EPOCH_WDAY
Definition: private.h:135
#define strerror
Definition: port.h:228
static const char * directory
Definition: zic.c:632
static int charcnt
Definition: zic.c:173
const char * z_name
Definition: zic.c:98
static void close_file(FILE *stream, char const *dir, char const *name)
Definition: zic.c:525
static struct lookup const * byword(const char *string, const struct lookup *lp)
Definition: zic.c:3649
static ptrdiff_t const PTRDIFF_MAX
Definition: zic.c:47
#define MAXALIGN(LEN)
Definition: c.h:753
#define realloc(a, b)
Definition: header.h:60
#define INT64_FORMAT
Definition: c.h:471
const char * name
Definition: encode.c:561
static int atcomp(const void *avp, const void *bvp)
Definition: zic.c:2035
static char lowerit(char)
Definition: zic.c:3549
#define TM_TUESDAY
Definition: private.h:113
#define EXPIRES_FIELDS
Definition: zic.c:271
static zic_t leapminyear
Definition: zic.c:179
static ptrdiff_t nrules
Definition: zic.c:282
#define S_ISDIR(m)
Definition: win32_port.h:316
static void word(struct vars *, int, struct state *, struct state *)
Definition: regcomp.c:1246
#define YEARSPERREPEAT
Definition: private.h:99
static struct zone * zones
Definition: zic.c:285
struct rule * z_rules
Definition: zic.c:107
static struct timerange limitrange(struct timerange r, zic_t lo, zic_t hi, zic_t const *ats, unsigned char const *types)
Definition: zic.c:2053
static void outzone(const struct zone *zp, ptrdiff_t ntzones)
Definition: zic.c:2944
#define LP_YEAR
Definition: zic.c:262
#define MAXVAL(t, b)
Definition: private.h:69
Definition: zic.c:93
#define YR_MAXIMUM
Definition: zic.c:278
e
Definition: preproc-init.c:82
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:400
#define TZ_MAX_TYPES
Definition: tzfile.h:103
static struct lookup const lasts[]
Definition: zic.c:349
bool r_hiwasnum
Definition: zic.c:66
#define RF_TOD
Definition: zic.c:245
static struct lookup const wday_names[]
Definition: zic.c:338
#define PG_INT32_MAX
Definition: c.h:512
char * optarg
Definition: getopt.c:52
static void * memcheck(void *ptr)
Definition: zic.c:424
static void newabbr(const char *abbr)
Definition: zic.c:3908
#define TM_MONDAY
Definition: private.h:112
char tzh_ttisstdcnt[4]
Definition: tzfile.h:45
#define ZFC_TILDAY
Definition: zic.c:230
#define RF_ABBRVAR
Definition: zic.c:247
#define TYPE_BIT(type)
Definition: private.h:60
int i
static struct lookup const leap_types[]
Definition: zic.c:373
#define EXIT_FAILURE
Definition: settings.h:161
int link(const char *target, const char *linkname)
#define LF_TARGET
Definition: zic.c:254
static const char * tzdefault
Definition: zic.c:634
static const int len_years[2]
Definition: zic.c:384
int lineno_t
Definition: zic.c:55
static char format
static bool timerange_option(char *timerange)
Definition: zic.c:600
#define mkdir(a, b)
Definition: win32_port.h:63
#define SECSPERREPEAT
Definition: private.h:159
#define vfprintf
Definition: port.h:218
#define qsort(a, b, c, d)
Definition: port.h:497
#define DO(field)
#define EOVERFLOW
Definition: private.h:41
#define linkat(targetdir, target, linknamedir, linkname, flag)
Definition: zic.c:116
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static void static void error(const char *string,...) pg_attribute_printf(1
Definition: zic.c:502
static bool ttisuts[TZ_MAX_TYPES]
Definition: zic.c:398
zic_t r_loyear
Definition: zic.c:63
static zic_t const min_time
Definition: zic.c:583
#define TM_WEDNESDAY
Definition: private.h:114
#define LP_MONTH
Definition: zic.c:263
static void memory_exhausted(const char *msg) pg_attribute_noreturn()
Definition: zic.c:409
#define ZFC_TILYEAR
Definition: zic.c:228
bool dontmerge
Definition: zic.c:391
static void eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
Definition: zic.c:471
static char chars[TZ_MAX_CHARS]
Definition: zic.c:399
#define TM_NOVEMBER
Definition: private.h:129
#define RF_LOYEAR
Definition: zic.c:240
#define LC_RULE
Definition: zic.c:200
#define _(x)
Definition: elog.c:88
long val
Definition: informix.c:664
static zic_t oadd(zic_t t1, zic_t t2)
Definition: zic.c:3762
static size_t size_product(size_t nitems, size_t itemsize)
Definition: zic.c:416
#define MINSPERHOUR
Definition: private.h:102
static bool want_bloat(void)
Definition: zic.c:642
static void puttzcode(const int32 val, FILE *const fp)
Definition: zic.c:2012
static void * erealloc(void *ptr, size_t size)
Definition: zic.c:438
#define RULE_FIELDS
Definition: zic.c:248
static unsigned char desigidx[TZ_MAX_TYPES]
Definition: zic.c:396
#define RF_MONTH
Definition: zic.c:243
#define stat
Definition: win32_port.h:275
zic_t z_stdoff
Definition: zic.c:99
static void convert64(const zic_t val, char *const buf)
Definition: zic.c:2001
static bool namecheck(const char *name)
Definition: zic.c:901
#define RF_DAY
Definition: zic.c:244
static char roll[TZ_MAX_LEAPS]
Definition: zic.c:402
static bool itsabbr(const char *abbr, const char *word)
Definition: zic.c:3621
static void * emalloc(size_t size)
Definition: zic.c:432