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