1 /* Compile .zi time zone data into TZif binary files. */
4 * This file is in the public domain, so clarified as of
5 * 2006-07-17 by Arthur David Olson.
11 #include "postgres_fe.h"
17 #include "pg_getopt.h"
22 #define ZIC_VERSION_PRE_2013 '2'
23 #define ZIC_VERSION '3'
26 #define ZIC_MIN PG_INT64_MIN
27 #define ZIC_MAX PG_INT64_MAX
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 */
35 #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
37 #define MKDIR_UMASK 0755
40 /* Port to native MS-Windows and to ancient UNIX. */
41 #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT
42 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
45 /* The maximum ptrdiff_t value, for pre-C99 platforms. */
47 static ptrdiff_t const PTRDIFF_MAX
= MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
51 * The type for line numbers. In Postgres, use %d to format them; upstream
52 * uses PRIdMAX but we prefer not to rely on that, not least because it
53 * results in platform-dependent strings to be translated.
59 const char *r_filename
;
63 zic_t r_loyear
; /* for example, 1986 */
64 zic_t r_hiyear
; /* for example, 1986 */
68 int r_month
; /* 0..11 */
70 int r_dycode
; /* see below */
74 zic_t r_tod
; /* time from midnight */
75 bool r_todisstd
; /* is r_tod standard time? */
76 bool r_todisut
; /* is r_tod UT? */
77 bool r_isdst
; /* is this daylight saving time? */
78 zic_t r_save
; /* offset from standard time */
79 const char *r_abbrvar
; /* variable part of abbreviation */
81 bool r_todo
; /* a rule to do (used in outzone) */
82 zic_t r_temp
; /* used in outzone */
86 * r_dycode r_dayofmonth r_wday
89 #define DC_DOM 0 /* 1..31 */ /* unused */
90 #define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */
91 #define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */
95 const char *z_filename
;
101 const char *z_format
;
102 char z_format_specifier
;
107 struct rule
*z_rules
;
110 struct rule z_untilrule
;
114 extern int link(const char *target
, const char *linkname
);
115 #ifndef AT_SYMLINK_FOLLOW
116 #define linkat(targetdir, target, linknamedir, linkname, flag) \
117 (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
120 static void memory_exhausted(const char *msg
) pg_attribute_noreturn();
121 static void verror(const char *string
, va_list args
) pg_attribute_printf(1, 0);
122 static void error(const char *string
,...) pg_attribute_printf(1, 2);
123 static void warning(const char *string
,...) pg_attribute_printf(1, 2);
124 static void usage(FILE *stream
, int status
) pg_attribute_noreturn();
125 static void addtt(zic_t starttime
, int type
);
126 static int addtype(zic_t
, char const *, bool, bool, bool);
127 static void leapadd(zic_t
, int, int);
128 static void adjleap(void);
129 static void associate(void);
130 static void dolink(const char *, const char *, bool);
131 static char **getfields(char *buf
);
132 static zic_t
gethms(const char *string
, const char *errstring
);
133 static zic_t
getsave(char *, bool *);
134 static void inexpires(char **, int);
135 static void infile(const char *filename
);
136 static void inleap(char **fields
, int nfields
);
137 static void inlink(char **fields
, int nfields
);
138 static void inrule(char **fields
, int nfields
);
139 static bool inzcont(char **fields
, int nfields
);
140 static bool inzone(char **fields
, int nfields
);
141 static bool inzsub(char **, int, bool);
142 static bool itsdir(char const *);
143 static bool itssymlink(char const *);
144 static bool is_alpha(char a
);
145 static char lowerit(char);
146 static void mkdirs(char const *, bool);
147 static void newabbr(const char *abbr
);
148 static zic_t
oadd(zic_t t1
, zic_t t2
);
149 static void outzone(const struct zone
*zp
, ptrdiff_t ntzones
);
150 static zic_t
rpytime(const struct rule
*rp
, zic_t wantedy
);
151 static void rulesub(struct rule
*rp
,
152 const char *loyearp
, const char *hiyearp
,
153 const char *typep
, const char *monthp
,
154 const char *dayp
, const char *timep
);
155 static zic_t
tadd(zic_t t1
, zic_t t2
);
157 /* Bound on length of what %z can expand to. */
160 PERCENT_Z_LEN_BOUND
= sizeof "+995959" - 1};
162 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
163 TZif files whose POSIX-TZ-style strings contain '<'; see
164 QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
165 workaround will no longer be needed when Qt 5.6.1 and earlier are
166 obsolete, say in the year 2021. */
167 #ifndef WORK_AROUND_QTBUG_53071
170 WORK_AROUND_QTBUG_53071
= true};
175 static bool warnings
;
176 static const char *filename
;
178 static bool leapseen
;
179 static zic_t leapminyear
;
180 static zic_t leapmaxyear
;
181 static lineno_t linenum
;
182 static int max_abbrvar_len
= PERCENT_Z_LEN_BOUND
;
183 static int max_format_len
;
184 static zic_t max_year
;
185 static zic_t min_year
;
187 static bool print_abbrevs
;
188 static zic_t print_cutoff
;
189 static const char *rfilename
;
190 static lineno_t rlinenum
;
191 static const char *progname
;
192 static ptrdiff_t timecnt
;
193 static ptrdiff_t timecnt_alloc
;
207 * Which fields are which on a Zone line.
215 #define ZF_TILMONTH 6
218 #define ZONE_MINFIELDS 5
219 #define ZONE_MAXFIELDS 9
222 * Which fields are which on a Zone continuation line.
228 #define ZFC_TILYEAR 3
229 #define ZFC_TILMONTH 4
231 #define ZFC_TILTIME 6
232 #define ZONEC_MINFIELDS 3
233 #define ZONEC_MAXFIELDS 7
236 * Which files are which on a Rule line.
248 #define RULE_FIELDS 10
251 * Which fields are which on a Link line.
255 #define LF_LINKNAME 2
256 #define LINK_FIELDS 3
259 * Which fields are which on a Leap line.
268 #define LEAP_FIELDS 7
270 /* Expires lines are like Leap lines, except without CORR and ROLL fields. */
271 #define EXPIRES_FIELDS 5
281 static struct rule
*rules
;
282 static ptrdiff_t nrules
; /* number of rules */
283 static ptrdiff_t nrules_alloc
;
285 static struct zone
*zones
;
286 static ptrdiff_t nzones
; /* number of zones */
287 static ptrdiff_t nzones_alloc
;
291 const char *l_filename
;
293 const char *l_target
;
294 const char *l_linkname
;
297 static struct link
*links
;
298 static ptrdiff_t nlinks
;
299 static ptrdiff_t nlinks_alloc
;
307 static struct lookup
const *byword(const char *string
,
308 const struct lookup
*lp
);
310 static struct lookup
const zi_line_codes
[] = {
316 static struct lookup
const leap_line_codes
[] = {
318 {"Expires", LC_EXPIRES
},
322 static struct lookup
const mon_names
[] = {
323 {"January", TM_JANUARY
},
324 {"February", TM_FEBRUARY
},
330 {"August", TM_AUGUST
},
331 {"September", TM_SEPTEMBER
},
332 {"October", TM_OCTOBER
},
333 {"November", TM_NOVEMBER
},
334 {"December", TM_DECEMBER
},
338 static struct lookup
const wday_names
[] = {
339 {"Sunday", TM_SUNDAY
},
340 {"Monday", TM_MONDAY
},
341 {"Tuesday", TM_TUESDAY
},
342 {"Wednesday", TM_WEDNESDAY
},
343 {"Thursday", TM_THURSDAY
},
344 {"Friday", TM_FRIDAY
},
345 {"Saturday", TM_SATURDAY
},
349 static struct lookup
const lasts
[] = {
350 {"last-Sunday", TM_SUNDAY
},
351 {"last-Monday", TM_MONDAY
},
352 {"last-Tuesday", TM_TUESDAY
},
353 {"last-Wednesday", TM_WEDNESDAY
},
354 {"last-Thursday", TM_THURSDAY
},
355 {"last-Friday", TM_FRIDAY
},
356 {"last-Saturday", TM_SATURDAY
},
360 static struct lookup
const begin_years
[] = {
361 {"minimum", YR_MINIMUM
},
362 {"maximum", YR_MAXIMUM
},
366 static struct lookup
const end_years
[] = {
367 {"minimum", YR_MINIMUM
},
368 {"maximum", YR_MAXIMUM
},
373 static struct lookup
const leap_types
[] = {
375 {"Stationary", false},
379 static const int len_months
[2][MONSPERYEAR
] = {
380 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
381 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
384 static const int len_years
[2] = {
385 DAYSPERNYEAR
, DAYSPERLYEAR
394 static zic_t utoffs
[TZ_MAX_TYPES
];
395 static char isdsts
[TZ_MAX_TYPES
];
396 static unsigned char desigidx
[TZ_MAX_TYPES
];
397 static bool ttisstds
[TZ_MAX_TYPES
];
398 static bool ttisuts
[TZ_MAX_TYPES
];
399 static char chars
[TZ_MAX_CHARS
];
400 static zic_t trans
[TZ_MAX_LEAPS
];
401 static zic_t corr
[TZ_MAX_LEAPS
];
402 static char roll
[TZ_MAX_LEAPS
];
409 memory_exhausted(const char *msg
)
411 fprintf(stderr
, _("%s: Memory exhausted: %s\n"), progname
, msg
);
416 size_product(size_t nitems
, size_t itemsize
)
418 if (SIZE_MAX
/ itemsize
< nitems
)
419 memory_exhausted(_("size overflow"));
420 return nitems
* itemsize
;
427 memory_exhausted(strerror(errno
));
434 return memcheck(malloc(size
));
438 erealloc(void *ptr
, size_t size
)
440 return memcheck(realloc(ptr
, size
));
444 ecpyalloc(char const *str
)
446 return memcheck(strdup(str
));
450 growalloc(void *ptr
, size_t itemsize
, ptrdiff_t nitems
, ptrdiff_t *nitems_alloc
)
452 if (nitems
< *nitems_alloc
)
456 ptrdiff_t nitems_max
= PTRDIFF_MAX
- WORK_AROUND_QTBUG_53071
;
457 ptrdiff_t amax
= nitems_max
< SIZE_MAX
? nitems_max
: SIZE_MAX
;
459 if ((amax
- 1) / 3 * 2 < *nitems_alloc
)
460 memory_exhausted(_("integer overflow"));
461 *nitems_alloc
+= (*nitems_alloc
>> 1) + 1;
462 return erealloc(ptr
, size_product(*nitems_alloc
, itemsize
));
471 eats(char const *name
, lineno_t num
, char const *rname
, lineno_t rnum
)
480 eat(char const *name
, lineno_t num
)
482 eats(name
, num
, NULL
, -1);
486 verror(const char *string
, va_list args
)
489 * Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
490 * "*" -v on BSD systems.
493 fprintf(stderr
, _("\"%s\", line %d: "), filename
, linenum
);
494 vfprintf(stderr
, string
, args
);
495 if (rfilename
!= NULL
)
496 fprintf(stderr
, _(" (rule from \"%s\", line %d)"),
497 rfilename
, rlinenum
);
498 fprintf(stderr
, "\n");
502 error(const char *string
,...)
506 va_start(args
, string
);
507 verror(string
, args
);
513 warning(const char *string
,...)
517 fprintf(stderr
, _("warning: "));
518 va_start(args
, string
);
519 verror(string
, args
);
525 close_file(FILE *stream
, char const *dir
, char const *name
)
527 char const *e
= (ferror(stream
) ? _("I/O error")
528 : fclose(stream
) != 0 ? strerror(errno
) : NULL
);
532 fprintf(stderr
, "%s: %s%s%s%s%s\n", progname
,
533 dir
? dir
: "", dir
? "/" : "",
534 name
? name
: "", name
? ": " : "",
541 usage(FILE *stream
, int status
)
544 _("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
545 "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
546 " [ -L leapseconds ] \\\n"
547 "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
548 "\t[ filename ... ]\n\n"
549 "Report bugs to %s.\n"),
550 progname
, progname
, PACKAGE_BUGREPORT
);
551 if (status
== EXIT_SUCCESS
)
552 close_file(stream
, NULL
, NULL
);
556 /* Change the working directory to DIR, possibly creating DIR and its
557 ancestors. After this is done, all files are accessed with names
560 change_directory(char const *dir
)
564 int chdir_errno
= errno
;
566 if (chdir_errno
== ENOENT
)
569 chdir_errno
= chdir(dir
) == 0 ? 0 : errno
;
571 if (chdir_errno
!= 0)
573 fprintf(stderr
, _("%s: Can't chdir to %s: %s\n"),
574 progname
, dir
, strerror(chdir_errno
));
580 #define TIME_T_BITS_IN_FILE 64
582 /* The minimum and maximum values representable in a TZif file. */
583 static zic_t
const min_time
= MINVAL(zic_t
, TIME_T_BITS_IN_FILE
);
584 static zic_t
const max_time
= MAXVAL(zic_t
, TIME_T_BITS_IN_FILE
);
586 /* The minimum, and one less than the maximum, values specified by
587 the -r option. These default to MIN_TIME and MAX_TIME. */
588 static zic_t lo_time
= MINVAL(zic_t
, TIME_T_BITS_IN_FILE
);
589 static zic_t hi_time
= MAXVAL(zic_t
, TIME_T_BITS_IN_FILE
);
591 /* The time specified by an Expires line, or negative if no such line. */
592 static zic_t leapexpires
= -1;
594 /* The time specified by an #expires comment, or negative if no such line. */
595 static zic_t comment_leapexpires
= -1;
597 /* Set the time range of the output to TIMERANGE.
598 Return true if successful. */
600 timerange_option(char *timerange
)
604 char *lo_end
= timerange
,
607 if (*timerange
== '@')
610 lo
= strtoimax(timerange
+ 1, &lo_end
, 10);
611 if (lo_end
== timerange
+ 1 || (lo
== PG_INT64_MAX
&& errno
== ERANGE
))
615 if (lo_end
[0] == '/' && lo_end
[1] == '@')
618 hi
= strtoimax(lo_end
+ 2, &hi_end
, 10);
619 if (hi_end
== lo_end
+ 2 || hi
== PG_INT64_MIN
)
621 hi
-= !(hi
== PG_INT64_MAX
&& errno
== ERANGE
);
623 if (*hi_end
|| hi
< lo
|| max_time
< lo
|| hi
< min_time
)
625 lo_time
= lo
< min_time
? min_time
: lo
;
626 hi_time
= max_time
< hi
? max_time
: hi
;
630 static const char *psxrules
;
631 static const char *lcltime
;
632 static const char *directory
;
633 static const char *leapsec
;
634 static const char *tzdefault
;
636 /* -1 if the TZif output file should be slim, 0 if default, 1 if the
637 output should be fat for backward compatibility. ZIC_BLOAT_DEFAULT
638 determines the default. */
647 #ifndef ZIC_BLOAT_DEFAULT
648 #define ZIC_BLOAT_DEFAULT "slim"
652 main(int argc
, char **argv
)
658 bool timerange_given
= false;
661 umask(umask(S_IWGRP
| S_IWOTH
) | (S_IWGRP
| S_IWOTH
));
664 if (TYPE_BIT(zic_t
) < 64)
666 fprintf(stderr
, "%s: %s\n", progname
,
667 _("wild compilation-time specification of zic_t"));
670 for (k
= 1; k
< argc
; k
++)
671 if (strcmp(argv
[k
], "--version") == 0)
673 printf("zic %s\n", PG_VERSION
);
674 close_file(stdout
, NULL
, NULL
);
677 else if (strcmp(argv
[k
], "--help") == 0)
679 usage(stdout
, EXIT_SUCCESS
);
681 while ((c
= getopt(argc
, argv
, "b:d:l:L:p:Pr:st:vy:")) != EOF
&& c
!= -1)
685 usage(stderr
, EXIT_FAILURE
);
687 if (strcmp(optarg
, "slim") == 0)
690 error(_("incompatible -b options"));
693 else if (strcmp(optarg
, "fat") == 0)
696 error(_("incompatible -b options"));
700 error(_("invalid option: -b '%s'"), optarg
);
703 if (directory
== NULL
)
704 directory
= strdup(optarg
);
708 _("%s: More than one -d option specified\n"),
715 lcltime
= strdup(optarg
);
719 _("%s: More than one -l option specified\n"),
725 if (psxrules
== NULL
)
726 psxrules
= strdup(optarg
);
730 _("%s: More than one -p option specified\n"),
736 if (tzdefault
!= NULL
)
739 _("%s: More than one -t option"
747 warning(_("-y ignored"));
751 leapsec
= strdup(optarg
);
755 _("%s: More than one -L option specified\n"),
764 print_abbrevs
= true;
765 print_cutoff
= time(NULL
);
771 _("%s: More than one -r option specified\n"),
775 if (!timerange_option(optarg
))
778 _("%s: invalid time range: %s\n"),
782 timerange_given
= true;
785 warning(_("-s ignored"));
788 if (optind
== argc
- 1 && strcmp(argv
[optind
], "=") == 0)
789 usage(stderr
, EXIT_FAILURE
); /* usage message by request */
792 static char const bloat_default
[] = ZIC_BLOAT_DEFAULT
;
794 if (strcmp(bloat_default
, "slim") == 0)
796 else if (strcmp(bloat_default
, "fat") == 0)
799 abort(); /* Configuration error. */
801 if (directory
== NULL
)
803 if (tzdefault
== NULL
)
804 tzdefault
= TZDEFAULT
;
806 if (optind
< argc
&& leapsec
!= NULL
)
812 for (k
= optind
; k
< argc
; k
++)
817 change_directory(directory
);
818 for (i
= 0; i
< nzones
; i
= j
)
821 * Find the next non-continuation zone entry.
823 for (j
= i
+ 1; j
< nzones
&& zones
[j
].z_name
== NULL
; ++j
)
825 outzone(&zones
[i
], j
- i
);
831 for (i
= 0; i
< nlinks
; ++i
)
833 eat(links
[i
].l_filename
, links
[i
].l_linenum
);
834 dolink(links
[i
].l_target
, links
[i
].l_linkname
, false);
836 for (j
= 0; j
< nlinks
; ++j
)
837 if (strcmp(links
[i
].l_linkname
,
838 links
[j
].l_target
) == 0)
839 warning(_("link to link"));
843 eat(_("command line"), 1);
844 dolink(lcltime
, tzdefault
, true);
846 if (psxrules
!= NULL
)
848 eat(_("command line"), 1);
849 dolink(psxrules
, TZDEFRULES
, true);
851 if (warnings
&& (ferror(stderr
) || fclose(stderr
) != 0))
853 return errors
? EXIT_FAILURE
: EXIT_SUCCESS
;
857 componentcheck(char const *name
, char const *component
,
858 char const *component_end
)
862 component_len_max
= 14};
863 ptrdiff_t component_len
= component_end
- component
;
865 if (component_len
== 0)
868 error(_("empty file name"));
870 error(_(component
== name
871 ? "file name '%s' begins with '/'"
873 ? "file name '%s' contains '//'"
874 : "file name '%s' ends with '/'"),
878 if (0 < component_len
&& component_len
<= 2
879 && component
[0] == '.' && component_end
[-1] == '.')
881 int len
= component_len
;
883 error(_("file name '%s' contains '%.*s' component"),
884 name
, len
, component
);
889 if (0 < component_len
&& component
[0] == '-')
890 warning(_("file name '%s' component contains leading '-'"),
892 if (component_len_max
< component_len
)
893 warning(_("file name '%s' contains overlength component"
895 name
, component_len_max
, component
);
901 namecheck(const char *name
)
905 /* Benign characters in a portable file name. */
906 static char const benign
[] =
908 "abcdefghijklmnopqrstuvwxyz"
909 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
912 * Non-control chars in the POSIX portable character set, excluding the
915 static char const printable_and_not_benign
[] =
916 " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
918 char const *component
= name
;
920 for (cp
= name
; *cp
; cp
++)
922 unsigned char c
= *cp
;
924 if (noise
&& !strchr(benign
, c
))
926 warning((strchr(printable_and_not_benign
, c
)
927 ? _("file name '%s' contains byte '%c'")
928 : _("file name '%s' contains byte '\\%o'")),
933 if (!componentcheck(name
, component
, cp
))
938 return componentcheck(name
, component
, cp
);
942 * Create symlink contents suitable for symlinking FROM to TO, as a
943 * freshly allocated string. FROM should be a relative file name, and
944 * is relative to the global variable DIRECTORY. TO can be either
945 * relative or absolute.
949 relname(char const *target
, char const *linkname
)
957 char const *f
= target
;
960 if (*linkname
== '/')
962 /* Make F absolute too. */
963 size_t len
= strlen(directory
);
964 bool needslash
= len
&& directory
[len
- 1] != '/';
966 linksize
= len
+ needslash
+ strlen(target
) + 1;
967 f
= result
= emalloc(linksize
);
968 strcpy(result
, directory
);
970 strcpy(result
+ len
+ needslash
, target
);
972 for (i
= 0; f
[i
] && f
[i
] == linkname
[i
]; i
++)
975 for (; linkname
[i
]; i
++)
976 dotdots
+= linkname
[i
] == '/' && linkname
[i
- 1] != '/';
977 taillen
= strlen(f
+ dir_len
);
978 dotdotetcsize
= 3 * dotdots
+ taillen
+ 1;
979 if (dotdotetcsize
<= linksize
)
982 result
= emalloc(dotdotetcsize
);
983 for (i
= 0; i
< dotdots
; i
++)
984 memcpy(result
+ 3 * i
, "../", 3);
985 memmove(result
+ 3 * dotdots
, f
+ dir_len
, taillen
+ 1);
989 #endif /* HAVE_SYMLINK */
991 /* Hard link FROM to TO, following any symbolic links.
992 Return 0 if successful, an error number otherwise. */
994 hardlinkerr(char const *target
, char const *linkname
)
996 int r
= linkat(AT_FDCWD
, target
, AT_FDCWD
, linkname
, AT_SYMLINK_FOLLOW
);
998 return r
== 0 ? 0 : errno
;
1002 dolink(char const *target
, char const *linkname
, bool staysymlink
)
1004 bool remove_only
= strcmp(target
, "-") == 0;
1005 bool linkdirs_made
= false;
1009 * We get to be careful here since there's a fair chance of root running
1012 if (!remove_only
&& itsdir(target
))
1014 fprintf(stderr
, _("%s: linking target %s/%s failed: %s\n"),
1015 progname
, directory
, target
, strerror(EPERM
));
1019 staysymlink
= itssymlink(linkname
);
1020 if (remove(linkname
) == 0)
1021 linkdirs_made
= true;
1022 else if (errno
!= ENOENT
)
1024 char const *e
= strerror(errno
);
1026 fprintf(stderr
, _("%s: Can't remove %s/%s: %s\n"),
1027 progname
, directory
, linkname
, e
);
1032 link_errno
= staysymlink
? ENOTSUP
: hardlinkerr(target
, linkname
);
1033 if (link_errno
== ENOENT
&& !linkdirs_made
)
1035 mkdirs(linkname
, true);
1036 linkdirs_made
= true;
1037 link_errno
= hardlinkerr(target
, linkname
);
1039 if (link_errno
!= 0)
1042 bool absolute
= *target
== '/';
1043 char *linkalloc
= absolute
? NULL
: relname(target
, linkname
);
1044 char const *contents
= absolute
? target
: linkalloc
;
1045 int symlink_errno
= symlink(contents
, linkname
) == 0 ? 0 : errno
;
1048 && (symlink_errno
== ENOENT
|| symlink_errno
== ENOTSUP
))
1050 mkdirs(linkname
, true);
1051 if (symlink_errno
== ENOENT
)
1052 symlink_errno
= symlink(contents
, linkname
) == 0 ? 0 : errno
;
1055 if (symlink_errno
== 0)
1057 if (link_errno
!= ENOTSUP
)
1058 warning(_("symbolic link used because hard link failed: %s"),
1059 strerror(link_errno
));
1062 #endif /* HAVE_SYMLINK */
1068 fp
= fopen(target
, "rb");
1071 char const *e
= strerror(errno
);
1073 fprintf(stderr
, _("%s: Can't read %s/%s: %s\n"),
1074 progname
, directory
, target
, e
);
1077 tp
= fopen(linkname
, "wb");
1080 char const *e
= strerror(errno
);
1082 fprintf(stderr
, _("%s: Can't create %s/%s: %s\n"),
1083 progname
, directory
, linkname
, e
);
1086 while ((c
= getc(fp
)) != EOF
)
1088 close_file(fp
, directory
, target
);
1089 close_file(tp
, directory
, linkname
);
1090 if (link_errno
!= ENOTSUP
)
1091 warning(_("copy used because hard link failed: %s"),
1092 strerror(link_errno
));
1094 else if (symlink_errno
!= ENOTSUP
)
1095 warning(_("copy used because symbolic link failed: %s"),
1096 strerror(symlink_errno
));
1102 /* Return true if NAME is a directory. */
1104 itsdir(char const *name
)
1107 int res
= stat(name
, &st
);
1110 return S_ISDIR(st
.st_mode
) != 0;
1112 if (res
== 0 || errno
== EOVERFLOW
)
1114 size_t n
= strlen(name
);
1115 char *nameslashdot
= emalloc(n
+ 3);
1118 memcpy(nameslashdot
, name
, n
);
1119 strcpy(&nameslashdot
[n
], &"/."[!(n
&& name
[n
- 1] != '/')]);
1120 dir
= stat(nameslashdot
, &st
) == 0 || errno
== EOVERFLOW
;
1127 /* Return true if NAME is a symbolic link. */
1129 itssymlink(char const *name
)
1134 return 0 <= readlink(name
, &c
, 1);
1141 * Associate sets of rules with zones.
1145 * Sort by rule name.
1149 rcomp(const void *cp1
, const void *cp2
)
1151 return strcmp(((const struct rule
*) cp1
)->r_name
,
1152 ((const struct rule
*) cp2
)->r_name
);
1167 qsort(rules
, nrules
, sizeof *rules
, rcomp
);
1168 for (i
= 0; i
< nrules
- 1; ++i
)
1170 if (strcmp(rules
[i
].r_name
,
1171 rules
[i
+ 1].r_name
) != 0)
1173 if (strcmp(rules
[i
].r_filename
,
1174 rules
[i
+ 1].r_filename
) == 0)
1176 eat(rules
[i
].r_filename
, rules
[i
].r_linenum
);
1177 warning(_("same rule name in multiple files"));
1178 eat(rules
[i
+ 1].r_filename
, rules
[i
+ 1].r_linenum
);
1179 warning(_("same rule name in multiple files"));
1180 for (j
= i
+ 2; j
< nrules
; ++j
)
1182 if (strcmp(rules
[i
].r_name
,
1183 rules
[j
].r_name
) != 0)
1185 if (strcmp(rules
[i
].r_filename
,
1186 rules
[j
].r_filename
) == 0)
1188 if (strcmp(rules
[i
+ 1].r_filename
,
1189 rules
[j
].r_filename
) == 0)
1196 for (i
= 0; i
< nzones
; ++i
)
1202 for (base
= 0; base
< nrules
; base
= out
)
1205 for (out
= base
+ 1; out
< nrules
; ++out
)
1206 if (strcmp(rp
->r_name
, rules
[out
].r_name
) != 0)
1208 for (i
= 0; i
< nzones
; ++i
)
1211 if (strcmp(zp
->z_rule
, rp
->r_name
) != 0)
1214 zp
->z_nrules
= out
- base
;
1217 for (i
= 0; i
< nzones
; ++i
)
1220 if (zp
->z_nrules
== 0)
1223 * Maybe we have a local standard time offset.
1225 eat(zp
->z_filename
, zp
->z_linenum
);
1226 zp
->z_save
= getsave(zp
->z_rule
, &zp
->z_isdst
);
1229 * Note, though, that if there's no rule, a '%s' in the format is
1232 if (zp
->z_format_specifier
== 's')
1233 error("%s", _("%s in ruleless zone"));
1241 infile(const char *name
)
1246 const struct lookup
*lp
;
1252 if (strcmp(name
, "-") == 0)
1254 name
= _("standard input");
1257 else if ((fp
= fopen(name
, "r")) == NULL
)
1259 const char *e
= strerror(errno
);
1261 fprintf(stderr
, _("%s: Cannot open %s: %s\n"),
1266 for (num
= 1;; ++num
)
1269 if (fgets(buf
, sizeof buf
, fp
) != buf
)
1271 cp
= strchr(buf
, '\n');
1274 error(_("line too long"));
1278 fields
= getfields(buf
);
1280 while (fields
[nfields
] != NULL
)
1284 if (strcmp(fields
[nfields
], "-") == 0)
1285 fields
[nfields
] = &nada
;
1290 if (name
== leapsec
&& *buf
== '#')
1293 * PG: INT64_FORMAT isn't portable for sscanf, so be content
1294 * with scanning a "long". Once we are requiring C99 in all
1295 * live branches, it'd be sensible to adopt upstream's
1296 * practice of using the <inttypes.h> macros. But for now, we
1297 * don't actually use this code, and it won't overflow before
1302 sscanf(buf
, "#expires %ld", &cl_tmp
);
1303 comment_leapexpires
= cl_tmp
;
1308 wantcont
= inzcont(fields
, nfields
);
1312 struct lookup
const *line_codes
1313 = name
== leapsec
? leap_line_codes
: zi_line_codes
;
1315 lp
= byword(fields
[0], line_codes
);
1317 error(_("input line of unknown type"));
1319 switch (lp
->l_value
)
1322 inrule(fields
, nfields
);
1326 wantcont
= inzone(fields
, nfields
);
1329 inlink(fields
, nfields
);
1333 inleap(fields
, nfields
);
1337 inexpires(fields
, nfields
);
1340 default: /* "cannot happen" */
1342 _("%s: panic: Invalid l_value %d\n"),
1343 progname
, lp
->l_value
);
1349 close_file(fp
, NULL
, filename
);
1351 error(_("expected continuation line not found"));
1355 * Convert a string of one of the forms
1356 * h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
1357 * into a number of seconds.
1358 * A null string maps to zero.
1359 * Call error with errstring and return zero on errors.
1363 gethms(char const *string
, char const *errstring
)
1365 /* PG: make hh be int not zic_t to avoid sscanf portability issues */
1378 if (string
== NULL
|| *string
== '\0')
1387 switch (sscanf(string
,
1388 "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1389 &hh
, &hhx
, &mm
, &mmx
, &ss
, &ssx
, &tenths
, &xr
, &xs
))
1395 ok
= '0' <= xr
&& xr
<= '9';
1400 warning(_("fractional seconds rejected by"
1401 " pre-2018 versions of zic"));
1414 error("%s", errstring
);
1418 mm
< 0 || mm
>= MINSPERHOUR
||
1419 ss
< 0 || ss
> SECSPERMIN
)
1421 error("%s", errstring
);
1424 /* Some compilers warn that this test is unsatisfiable for 32-bit ints */
1425 #if INT_MAX > PG_INT32_MAX
1426 if (ZIC_MAX
/ SECSPERHOUR
< hh
)
1428 error(_("time overflow"));
1432 ss
+= 5 + ((ss
^ 1) & (xr
== '0')) <= tenths
; /* Round to even. */
1433 if (noise
&& (hh
> HOURSPERDAY
||
1434 (hh
== HOURSPERDAY
&& (mm
!= 0 || ss
!= 0))))
1435 warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1436 return oadd(sign
* (zic_t
) hh
* SECSPERHOUR
,
1437 sign
* (mm
* SECSPERMIN
+ ss
));
1441 getsave(char *field
, bool *isdst
)
1445 size_t fieldlen
= strlen(field
);
1449 char *ep
= field
+ fieldlen
- 1;
1463 save
= gethms(field
, _("invalid saved time"));
1464 *isdst
= dst
< 0 ? save
!= 0 : dst
;
1469 inrule(char **fields
, int nfields
)
1471 static struct rule r
;
1473 if (nfields
!= RULE_FIELDS
)
1475 error(_("wrong number of fields on Rule line"));
1478 switch (*fields
[RF_NAME
])
1499 error(_("Invalid rule name \"%s\""), fields
[RF_NAME
]);
1502 r
.r_filename
= filename
;
1503 r
.r_linenum
= linenum
;
1504 r
.r_save
= getsave(fields
[RF_SAVE
], &r
.r_isdst
);
1505 rulesub(&r
, fields
[RF_LOYEAR
], fields
[RF_HIYEAR
], fields
[RF_COMMAND
],
1506 fields
[RF_MONTH
], fields
[RF_DAY
], fields
[RF_TOD
]);
1507 r
.r_name
= ecpyalloc(fields
[RF_NAME
]);
1508 r
.r_abbrvar
= ecpyalloc(fields
[RF_ABBRVAR
]);
1509 if (max_abbrvar_len
< strlen(r
.r_abbrvar
))
1510 max_abbrvar_len
= strlen(r
.r_abbrvar
);
1511 rules
= growalloc(rules
, sizeof *rules
, nrules
, &nrules_alloc
);
1512 rules
[nrules
++] = r
;
1516 inzone(char **fields
, int nfields
)
1520 if (nfields
< ZONE_MINFIELDS
|| nfields
> ZONE_MAXFIELDS
)
1522 error(_("wrong number of fields on Zone line"));
1525 if (lcltime
!= NULL
&& strcmp(fields
[ZF_NAME
], tzdefault
) == 0)
1528 _("\"Zone %s\" line and -l option are mutually exclusive"),
1532 if (strcmp(fields
[ZF_NAME
], TZDEFRULES
) == 0 && psxrules
!= NULL
)
1535 _("\"Zone %s\" line and -p option are mutually exclusive"),
1539 for (i
= 0; i
< nzones
; ++i
)
1540 if (zones
[i
].z_name
!= NULL
&&
1541 strcmp(zones
[i
].z_name
, fields
[ZF_NAME
]) == 0)
1543 error(_("duplicate zone name %s"
1544 " (file \"%s\", line %d)"),
1546 zones
[i
].z_filename
,
1547 zones
[i
].z_linenum
);
1550 return inzsub(fields
, nfields
, false);
1554 inzcont(char **fields
, int nfields
)
1556 if (nfields
< ZONEC_MINFIELDS
|| nfields
> ZONEC_MAXFIELDS
)
1558 error(_("wrong number of fields on Zone continuation line"));
1561 return inzsub(fields
, nfields
, true);
1565 inzsub(char **fields
, int nfields
, bool iscont
)
1569 static struct zone z
;
1581 i_stdoff
= ZFC_STDOFF
;
1583 i_format
= ZFC_FORMAT
;
1584 i_untilyear
= ZFC_TILYEAR
;
1585 i_untilmonth
= ZFC_TILMONTH
;
1586 i_untilday
= ZFC_TILDAY
;
1587 i_untiltime
= ZFC_TILTIME
;
1590 else if (!namecheck(fields
[ZF_NAME
]))
1594 i_stdoff
= ZF_STDOFF
;
1596 i_format
= ZF_FORMAT
;
1597 i_untilyear
= ZF_TILYEAR
;
1598 i_untilmonth
= ZF_TILMONTH
;
1599 i_untilday
= ZF_TILDAY
;
1600 i_untiltime
= ZF_TILTIME
;
1601 z
.z_name
= ecpyalloc(fields
[ZF_NAME
]);
1603 z
.z_filename
= filename
;
1604 z
.z_linenum
= linenum
;
1605 z
.z_stdoff
= gethms(fields
[i_stdoff
], _("invalid UT offset"));
1606 if ((cp
= strchr(fields
[i_format
], '%')) != NULL
)
1608 if ((*++cp
!= 's' && *cp
!= 'z') || strchr(cp
, '%')
1609 || strchr(fields
[i_format
], '/'))
1611 error(_("invalid abbreviation format"));
1615 z
.z_rule
= ecpyalloc(fields
[i_rule
]);
1616 z
.z_format
= cp1
= ecpyalloc(fields
[i_format
]);
1617 z
.z_format_specifier
= cp
? *cp
: '\0';
1618 if (z
.z_format_specifier
== 'z')
1621 warning(_("format '%s' not handled by pre-2015 versions of zic"),
1623 cp1
[cp
- fields
[i_format
]] = 's';
1625 if (max_format_len
< strlen(z
.z_format
))
1626 max_format_len
= strlen(z
.z_format
);
1627 hasuntil
= nfields
> i_untilyear
;
1630 z
.z_untilrule
.r_filename
= filename
;
1631 z
.z_untilrule
.r_linenum
= linenum
;
1632 rulesub(&z
.z_untilrule
,
1633 fields
[i_untilyear
],
1636 (nfields
> i_untilmonth
) ?
1637 fields
[i_untilmonth
] : "Jan",
1638 (nfields
> i_untilday
) ? fields
[i_untilday
] : "1",
1639 (nfields
> i_untiltime
) ? fields
[i_untiltime
] : "0");
1640 z
.z_untiltime
= rpytime(&z
.z_untilrule
,
1641 z
.z_untilrule
.r_loyear
);
1642 if (iscont
&& nzones
> 0 &&
1643 z
.z_untiltime
> min_time
&&
1644 z
.z_untiltime
< max_time
&&
1645 zones
[nzones
- 1].z_untiltime
> min_time
&&
1646 zones
[nzones
- 1].z_untiltime
< max_time
&&
1647 zones
[nzones
- 1].z_untiltime
>= z
.z_untiltime
)
1649 error(_("Zone continuation line end time is not after end time of previous line"));
1653 zones
= growalloc(zones
, sizeof *zones
, nzones
, &nzones_alloc
);
1654 zones
[nzones
++] = z
;
1657 * If there was an UNTIL field on this line, there's more information
1658 * about the zone on the next line.
1664 getleapdatetime(char **fields
, int nfields
, bool expire_line
)
1667 const struct lookup
*lp
;
1671 /* PG: make year be int not zic_t to avoid sscanf portability issues */
1681 cp
= fields
[LP_YEAR
];
1682 if (sscanf(cp
, "%d%c", &year
, &xs
) != 1)
1687 error(_("invalid leaping year"));
1692 if (!leapseen
|| leapmaxyear
< year
)
1694 if (!leapseen
|| leapminyear
> year
)
1703 i
= len_years
[isleap(j
)];
1709 i
= -len_years
[isleap(j
)];
1711 dayoff
= oadd(dayoff
, i
);
1713 if ((lp
= byword(fields
[LP_MONTH
], mon_names
)) == NULL
)
1715 error(_("invalid month name"));
1718 month
= lp
->l_value
;
1722 i
= len_months
[isleap(year
)][j
];
1723 dayoff
= oadd(dayoff
, i
);
1726 cp
= fields
[LP_DAY
];
1727 if (sscanf(cp
, "%d%c", &day
, &xs
) != 1 ||
1728 day
<= 0 || day
> len_months
[isleap(year
)][month
])
1730 error(_("invalid day of month"));
1733 dayoff
= oadd(dayoff
, day
- 1);
1734 if (dayoff
< min_time
/ SECSPERDAY
)
1736 error(_("time too small"));
1739 if (dayoff
> max_time
/ SECSPERDAY
)
1741 error(_("time too large"));
1744 t
= dayoff
* SECSPERDAY
;
1745 tod
= gethms(fields
[LP_TIME
], _("invalid time of day"));
1748 error(_("leap second precedes Epoch"));
1753 inleap(char **fields
, int nfields
)
1755 if (nfields
!= LEAP_FIELDS
)
1756 error(_("wrong number of fields on Leap line"));
1759 zic_t t
= getleapdatetime(fields
, nfields
, false);
1763 struct lookup
const *lp
= byword(fields
[LP_ROLL
], leap_types
);
1766 error(_("invalid Rolling/Stationary field on Leap line"));
1771 if (!fields
[LP_CORR
][0]) /* infile() turns "-" into "". */
1773 else if (strcmp(fields
[LP_CORR
], "+") == 0)
1776 error(_("invalid CORRECTION field on Leap line"));
1778 leapadd(t
, correction
, lp
->l_value
);
1785 inexpires(char **fields
, int nfields
)
1787 if (nfields
!= EXPIRES_FIELDS
)
1788 error(_("wrong number of fields on Expires line"));
1789 else if (0 <= leapexpires
)
1790 error(_("multiple Expires lines"));
1792 leapexpires
= getleapdatetime(fields
, nfields
, true);
1796 inlink(char **fields
, int nfields
)
1800 if (nfields
!= LINK_FIELDS
)
1802 error(_("wrong number of fields on Link line"));
1805 if (*fields
[LF_TARGET
] == '\0')
1807 error(_("blank TARGET field on Link line"));
1810 if (!namecheck(fields
[LF_LINKNAME
]))
1812 l
.l_filename
= filename
;
1813 l
.l_linenum
= linenum
;
1814 l
.l_target
= ecpyalloc(fields
[LF_TARGET
]);
1815 l
.l_linkname
= ecpyalloc(fields
[LF_LINKNAME
]);
1816 links
= growalloc(links
, sizeof *links
, nlinks
, &nlinks_alloc
);
1817 links
[nlinks
++] = l
;
1821 rulesub(struct rule
*rp
, const char *loyearp
, const char *hiyearp
,
1822 const char *typep
, const char *monthp
, const char *dayp
,
1825 const struct lookup
*lp
;
1831 /* PG: year_tmp is to avoid sscanf portability issues */
1834 if ((lp
= byword(monthp
, mon_names
)) == NULL
)
1836 error(_("invalid month name"));
1839 rp
->r_month
= lp
->l_value
;
1840 rp
->r_todisstd
= false;
1841 rp
->r_todisut
= false;
1842 dp
= ecpyalloc(timep
);
1845 ep
= dp
+ strlen(dp
) - 1;
1846 switch (lowerit(*ep
))
1848 case 's': /* Standard */
1849 rp
->r_todisstd
= true;
1850 rp
->r_todisut
= false;
1853 case 'w': /* Wall */
1854 rp
->r_todisstd
= false;
1855 rp
->r_todisut
= false;
1858 case 'g': /* Greenwich */
1859 case 'u': /* Universal */
1860 case 'z': /* Zulu */
1861 rp
->r_todisstd
= true;
1862 rp
->r_todisut
= true;
1867 rp
->r_tod
= gethms(dp
, _("invalid time of day"));
1874 lp
= byword(cp
, begin_years
);
1875 rp
->r_lowasnum
= lp
== NULL
;
1876 if (!rp
->r_lowasnum
)
1877 switch (lp
->l_value
)
1880 rp
->r_loyear
= ZIC_MIN
;
1883 rp
->r_loyear
= ZIC_MAX
;
1885 default: /* "cannot happen" */
1887 _("%s: panic: Invalid l_value %d\n"),
1888 progname
, lp
->l_value
);
1891 else if (sscanf(cp
, "%d%c", &year_tmp
, &xs
) == 1)
1892 rp
->r_loyear
= year_tmp
;
1895 error(_("invalid starting year"));
1899 lp
= byword(cp
, end_years
);
1900 rp
->r_hiwasnum
= lp
== NULL
;
1901 if (!rp
->r_hiwasnum
)
1902 switch (lp
->l_value
)
1905 rp
->r_hiyear
= ZIC_MIN
;
1908 rp
->r_hiyear
= ZIC_MAX
;
1911 rp
->r_hiyear
= rp
->r_loyear
;
1913 default: /* "cannot happen" */
1915 _("%s: panic: Invalid l_value %d\n"),
1916 progname
, lp
->l_value
);
1919 else if (sscanf(cp
, "%d%c", &year_tmp
, &xs
) == 1)
1920 rp
->r_hiyear
= year_tmp
;
1923 error(_("invalid ending year"));
1926 if (rp
->r_loyear
> rp
->r_hiyear
)
1928 error(_("starting year greater than ending year"));
1933 error(_("year type \"%s\" is unsupported; use \"-\" instead"),
1939 * Day work. Accept things such as: 1 lastSunday last-Sunday
1940 * (undocumented; warn about this) Sun<=20 Sun>=7
1942 dp
= ecpyalloc(dayp
);
1943 if ((lp
= byword(dp
, lasts
)) != NULL
)
1945 rp
->r_dycode
= DC_DOWLEQ
;
1946 rp
->r_wday
= lp
->l_value
;
1947 rp
->r_dayofmonth
= len_months
[1][rp
->r_month
];
1951 if ((ep
= strchr(dp
, '<')) != NULL
)
1952 rp
->r_dycode
= DC_DOWLEQ
;
1953 else if ((ep
= strchr(dp
, '>')) != NULL
)
1954 rp
->r_dycode
= DC_DOWGEQ
;
1958 rp
->r_dycode
= DC_DOM
;
1960 if (rp
->r_dycode
!= DC_DOM
)
1965 error(_("invalid day of month"));
1969 if ((lp
= byword(dp
, wday_names
)) == NULL
)
1971 error(_("invalid weekday name"));
1975 rp
->r_wday
= lp
->l_value
;
1977 if (sscanf(ep
, "%d%c", &rp
->r_dayofmonth
, &xs
) != 1 ||
1978 rp
->r_dayofmonth
<= 0 ||
1979 (rp
->r_dayofmonth
> len_months
[1][rp
->r_month
]))
1981 error(_("invalid day of month"));
1990 convert(const int32 val
, char *const buf
)
1994 unsigned char *const b
= (unsigned char *) buf
;
1996 for (i
= 0, shift
= 24; i
< 4; ++i
, shift
-= 8)
1997 b
[i
] = val
>> shift
;
2001 convert64(const zic_t val
, char *const buf
)
2005 unsigned char *const b
= (unsigned char *) buf
;
2007 for (i
= 0, shift
= 56; i
< 8; ++i
, shift
-= 8)
2008 b
[i
] = val
>> shift
;
2012 puttzcode(const int32 val
, FILE *const fp
)
2017 fwrite(buf
, sizeof buf
, 1, fp
);
2021 puttzcodepass(zic_t val
, FILE *fp
, int pass
)
2029 convert64(val
, buf
);
2030 fwrite(buf
, sizeof buf
, 1, fp
);
2035 atcomp(const void *avp
, const void *bvp
)
2037 const zic_t a
= ((const struct attype
*) avp
)->at
;
2038 const zic_t b
= ((const struct attype
*) bvp
)->at
;
2040 return (a
< b
) ? -1 : (a
> b
);
2052 static struct timerange
2053 limitrange(struct timerange r
, zic_t lo
, zic_t hi
,
2054 zic_t
const *ats
, unsigned char const *types
)
2056 while (0 < r
.count
&& ats
[r
.base
] < lo
)
2058 r
.defaulttype
= types
[r
.base
];
2062 while (0 < r
.leapcount
&& trans
[r
.leapbase
] < lo
)
2070 while (0 < r
.count
&& hi
+ 1 < ats
[r
.base
+ r
.count
- 1])
2072 while (0 < r
.leapcount
&& hi
+ 1 < trans
[r
.leapbase
+ r
.leapcount
- 1])
2080 writezone(const char *const name
, const char *const string
, char version
,
2087 static const struct tzhead tzh0
;
2088 static struct tzhead tzh
;
2089 bool dir_checked
= false;
2091 zic_t y2038_boundary
= one
<< 31;
2092 ptrdiff_t nats
= timecnt
+ WORK_AROUND_QTBUG_53071
;
2095 * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
2098 zic_t
*ats
= emalloc(MAXALIGN(size_product(nats
, sizeof *ats
+ 1)));
2099 void *typesptr
= ats
+ nats
;
2100 unsigned char *types
= typesptr
;
2101 struct timerange rangeall
,
2109 qsort(attypes
, timecnt
, sizeof *attypes
, atcomp
);
2120 for (; fromi
< timecnt
; ++fromi
)
2123 && ((attypes
[fromi
].at
2124 + utoffs
[attypes
[toi
- 1].type
])
2125 <= (attypes
[toi
- 1].at
2126 + utoffs
[toi
== 1 ? 0
2127 : attypes
[toi
- 2].type
])))
2129 attypes
[toi
- 1].type
=
2130 attypes
[fromi
].type
;
2134 || attypes
[fromi
].dontmerge
2135 || (utoffs
[attypes
[toi
- 1].type
]
2136 != utoffs
[attypes
[fromi
].type
])
2137 || (isdsts
[attypes
[toi
- 1].type
]
2138 != isdsts
[attypes
[fromi
].type
])
2139 || (desigidx
[attypes
[toi
- 1].type
]
2140 != desigidx
[attypes
[fromi
].type
]))
2141 attypes
[toi
++] = attypes
[fromi
];
2146 if (noise
&& timecnt
> 1200)
2148 if (timecnt
> TZ_MAX_TIMES
)
2149 warning(_("reference clients mishandle"
2150 " more than %d transition times"),
2153 warning(_("pre-2014 clients may mishandle"
2154 " more than 1200 transition times"));
2160 for (i
= 0; i
< timecnt
; ++i
)
2162 ats
[i
] = attypes
[i
].at
;
2163 types
[i
] = attypes
[i
].type
;
2167 * Correct for leap seconds.
2169 for (i
= 0; i
< timecnt
; ++i
)
2173 if (ats
[i
] > trans
[j
] - corr
[j
])
2175 ats
[i
] = tadd(ats
[i
], corr
[j
]);
2181 * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2182 * inserting a no-op transition at time y2038_boundary - 1. This works
2183 * only for timestamps before the boundary, which should be good enough in
2184 * practice as QTBUG-53071 should be long-dead by 2038. Do this after
2185 * correcting for leap seconds, as the idea is to insert a transition just
2186 * before 32-bit pg_time_t rolls around, and this occurs at a slightly
2187 * different moment if transitions are leap-second corrected.
2189 if (WORK_AROUND_QTBUG_53071
&& timecnt
!= 0 && want_bloat()
2190 && ats
[timecnt
- 1] < y2038_boundary
- 1 && strchr(string
, '<'))
2192 ats
[timecnt
] = y2038_boundary
- 1;
2193 types
[timecnt
] = types
[timecnt
- 1];
2197 rangeall
.defaulttype
= defaulttype
;
2198 rangeall
.base
= rangeall
.leapbase
= 0;
2199 rangeall
.count
= timecnt
;
2200 rangeall
.leapcount
= leapcnt
;
2201 range64
= limitrange(rangeall
, lo_time
, hi_time
, ats
, types
);
2202 range32
= limitrange(range64
, PG_INT32_MIN
, PG_INT32_MAX
, ats
, types
);
2205 * Remove old file, if any, to snap links.
2207 if (remove(name
) == 0)
2209 else if (errno
!= ENOENT
)
2211 const char *e
= strerror(errno
);
2213 fprintf(stderr
, _("%s: Cannot remove %s/%s: %s\n"),
2214 progname
, directory
, name
, e
);
2217 fp
= fopen(name
, "wb");
2220 int fopen_errno
= errno
;
2222 if (fopen_errno
== ENOENT
&& !dir_checked
)
2225 fp
= fopen(name
, "wb");
2226 fopen_errno
= errno
;
2230 fprintf(stderr
, _("%s: Cannot create %s/%s: %s\n"),
2231 progname
, directory
, name
, strerror(fopen_errno
));
2235 for (pass
= 1; pass
<= 2; ++pass
)
2237 ptrdiff_t thistimei
,
2249 char omittype
[TZ_MAX_TYPES
];
2250 int typemap
[TZ_MAX_TYPES
];
2254 char thischars
[TZ_MAX_CHARS
];
2257 int indmap
[TZ_MAX_CHARS
];
2262 * Arguably the default time type in the 32-bit data should be
2263 * range32.defaulttype, which is suited for timestamps just before
2264 * PG_INT32_MIN. However, zic traditionally used the time type of
2265 * the indefinite past instead. Internet RFC 8532 says readers
2266 * should ignore 32-bit data, so this discrepancy matters only to
2267 * obsolete readers where the traditional type might be more
2268 * appropriate even if it's "wrong". So, use the historical zic
2269 * value, unless -r specifies a low cutoff that excludes some
2270 * 32-bit timestamps.
2272 thisdefaulttype
= (lo_time
<= PG_INT32_MIN
2273 ? range64
.defaulttype
2274 : range32
.defaulttype
);
2276 thistimei
= range32
.base
;
2277 thistimecnt
= range32
.count
;
2278 toomanytimes
= thistimecnt
>> 31 >> 1 != 0;
2279 thisleapi
= range32
.leapbase
;
2280 thisleapcnt
= range32
.leapcount
;
2281 locut
= PG_INT32_MIN
< lo_time
;
2282 hicut
= hi_time
< PG_INT32_MAX
;
2286 thisdefaulttype
= range64
.defaulttype
;
2287 thistimei
= range64
.base
;
2288 thistimecnt
= range64
.count
;
2289 toomanytimes
= thistimecnt
>> 31 >> 31 >> 2 != 0;
2290 thisleapi
= range64
.leapbase
;
2291 thisleapcnt
= range64
.leapcount
;
2292 locut
= min_time
< lo_time
;
2293 hicut
= hi_time
< max_time
;
2296 error(_("too many transition times"));
2299 * Keep the last too-low transition if no transition is exactly at LO.
2300 * The kept transition will be output as a LO "transition"; see
2301 * "Output a LO_TIME transition" below. This is needed when the
2302 * output is truncated at the start, and is also useful when catering
2303 * to buggy 32-bit clients that do not use time type 0 for timestamps
2304 * before the first transition.
2306 if (0 < thistimei
&& ats
[thistimei
] != lo_time
)
2313 thistimelim
= thistimei
+ thistimecnt
;
2314 thisleaplim
= thisleapi
+ thisleapcnt
;
2315 if (thistimecnt
!= 0)
2317 if (ats
[thistimei
] == lo_time
)
2319 if (hi_time
< ZIC_MAX
&& ats
[thistimelim
- 1] == hi_time
+ 1)
2322 memset(omittype
, true, typecnt
);
2323 omittype
[thisdefaulttype
] = false;
2324 for (i
= thistimei
; i
< thistimelim
; i
++)
2325 omittype
[types
[i
]] = false;
2328 * Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
2329 * OLD0 and THISDEFAULTTYPE so that THISDEFAULTTYPE appears as type 0
2330 * in the output instead of OLD0. TYPEMAP also omits unused types.
2332 old0
= strlen(omittype
);
2334 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2337 * For some pre-2011 systems: if the last-to-be-written standard (or
2338 * daylight) type has an offset different from the most recently used
2339 * offset, append an (unused) copy of the most recently used type (to
2340 * help get global "altzone" and "timezone" variables set correctly).
2350 hidst
= histd
= mrudst
= mrustd
= -1;
2351 for (i
= thistimei
; i
< thistimelim
; ++i
)
2352 if (isdsts
[types
[i
]])
2356 for (i
= old0
; i
< typecnt
; i
++)
2358 int h
= (i
== old0
? thisdefaulttype
2359 : i
== thisdefaulttype
? old0
: i
);
2369 if (hidst
>= 0 && mrudst
>= 0 && hidst
!= mrudst
&&
2370 utoffs
[hidst
] != utoffs
[mrudst
])
2372 isdsts
[mrudst
] = -1;
2373 type
= addtype(utoffs
[mrudst
],
2374 &chars
[desigidx
[mrudst
]],
2379 omittype
[type
] = false;
2381 if (histd
>= 0 && mrustd
>= 0 && histd
!= mrustd
&&
2382 utoffs
[histd
] != utoffs
[mrustd
])
2384 isdsts
[mrustd
] = -1;
2385 type
= addtype(utoffs
[mrustd
],
2386 &chars
[desigidx
[mrustd
]],
2391 omittype
[type
] = false;
2395 * LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
2397 for (i
= old0
; i
< typecnt
; i
++)
2399 typemap
[i
== old0
? thisdefaulttype
2400 : i
== thisdefaulttype
? old0
: i
]
2403 for (i
= 0; i
< sizeof indmap
/ sizeof indmap
[0]; ++i
)
2405 thischarcnt
= stdcnt
= utcnt
= 0;
2406 for (i
= old0
; i
< typecnt
; i
++)
2413 stdcnt
= thistypecnt
;
2415 utcnt
= thistypecnt
;
2416 if (indmap
[desigidx
[i
]] >= 0)
2418 thisabbr
= &chars
[desigidx
[i
]];
2419 for (j
= 0; j
< thischarcnt
; ++j
)
2420 if (strcmp(&thischars
[j
], thisabbr
) == 0)
2422 if (j
== thischarcnt
)
2424 strcpy(&thischars
[thischarcnt
], thisabbr
);
2425 thischarcnt
+= strlen(thisabbr
) + 1;
2427 indmap
[desigidx
[i
]] = j
;
2429 if (pass
== 1 && !want_bloat())
2431 utcnt
= stdcnt
= thisleapcnt
= 0;
2432 thistimecnt
= -(locut
+ hicut
);
2433 thistypecnt
= thischarcnt
= 1;
2434 thistimelim
= thistimei
;
2436 #define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
2438 memcpy(tzh
.tzh_magic
, TZ_MAGIC
, sizeof tzh
.tzh_magic
);
2439 tzh
.tzh_version
[0] = version
;
2440 convert(utcnt
, tzh
.tzh_ttisutcnt
);
2441 convert(stdcnt
, tzh
.tzh_ttisstdcnt
);
2442 convert(thisleapcnt
, tzh
.tzh_leapcnt
);
2443 convert(locut
+ thistimecnt
+ hicut
, tzh
.tzh_timecnt
);
2444 convert(thistypecnt
, tzh
.tzh_typecnt
);
2445 convert(thischarcnt
, tzh
.tzh_charcnt
);
2456 if (pass
== 1 && !want_bloat())
2458 /* Output a minimal data block with just one time type. */
2459 puttzcode(0, fp
); /* utoff */
2460 putc(0, fp
); /* dst */
2461 putc(0, fp
); /* index of abbreviation */
2462 putc(0, fp
); /* empty-string abbreviation */
2466 /* PG: print current timezone abbreviations if requested */
2467 if (print_abbrevs
&& pass
== 2)
2469 /* Print "type" data for periods ending after print_cutoff */
2470 for (i
= thistimei
; i
< thistimelim
; ++i
)
2472 if (i
== thistimelim
- 1 || ats
[i
+ 1] > print_cutoff
)
2474 unsigned char tm
= types
[i
];
2475 char *thisabbrev
= &thischars
[indmap
[desigidx
[tm
]]];
2477 fprintf(stdout
, "%s\t" INT64_FORMAT
"%s\n",
2480 isdsts
[tm
] ? "\tD" : "");
2483 /* Print the default type if we have no transitions at all */
2484 if (thistimei
>= thistimelim
)
2486 unsigned char tm
= defaulttype
;
2487 char *thisabbrev
= &thischars
[indmap
[desigidx
[tm
]]];
2489 fprintf(stdout
, "%s\t" INT64_FORMAT
"%s\n",
2492 isdsts
[tm
] ? "\tD" : "");
2497 * Output a LO_TIME transition if needed; see limitrange. But do not
2498 * go below the minimum representable value for this pass.
2500 lo
= pass
== 1 && lo_time
< PG_INT32_MIN
? PG_INT32_MIN
: lo_time
;
2503 puttzcodepass(lo
, fp
, pass
);
2504 for (i
= thistimei
; i
< thistimelim
; ++i
)
2506 zic_t at
= ats
[i
] < lo
? lo
: ats
[i
];
2508 puttzcodepass(at
, fp
, pass
);
2511 puttzcodepass(hi_time
+ 1, fp
, pass
);
2514 putc(currenttype
, fp
);
2515 for (i
= thistimei
; i
< thistimelim
; ++i
)
2517 currenttype
= typemap
[types
[i
]];
2518 putc(currenttype
, fp
);
2521 putc(currenttype
, fp
);
2523 for (i
= old0
; i
< typecnt
; i
++)
2525 int h
= (i
== old0
? thisdefaulttype
2526 : i
== thisdefaulttype
? old0
: i
);
2530 puttzcode(utoffs
[h
], fp
);
2531 putc(isdsts
[h
], fp
);
2532 putc(indmap
[desigidx
[h
]], fp
);
2535 if (thischarcnt
!= 0)
2536 fwrite(thischars
, sizeof thischars
[0],
2538 for (i
= thisleapi
; i
< thisleaplim
; ++i
)
2544 if (timecnt
== 0 || trans
[i
] < ats
[0])
2557 while (j
< timecnt
&&
2562 todo
= tadd(trans
[i
], -utoffs
[j
]);
2566 puttzcodepass(todo
, fp
, pass
);
2567 puttzcode(corr
[i
], fp
);
2570 for (i
= old0
; i
< typecnt
; i
++)
2572 putc(ttisstds
[i
], fp
);
2574 for (i
= old0
; i
< typecnt
; i
++)
2576 putc(ttisuts
[i
], fp
);
2578 fprintf(fp
, "\n%s\n", string
);
2579 close_file(fp
, directory
, name
);
2584 abbroffset(char *buf
, zic_t offset
)
2596 seconds
= offset
% SECSPERMIN
;
2597 offset
/= SECSPERMIN
;
2598 minutes
= offset
% MINSPERHOUR
;
2599 offset
/= MINSPERHOUR
;
2602 error(_("%%z UT offset magnitude exceeds 99:59:59"));
2610 *p
++ = '0' + offset
/ 10;
2611 *p
++ = '0' + offset
% 10;
2612 if (minutes
| seconds
)
2614 *p
++ = '0' + minutes
/ 10;
2615 *p
++ = '0' + minutes
% 10;
2618 *p
++ = '0' + seconds
/ 10;
2619 *p
++ = '0' + seconds
% 10;
2628 doabbr(char *abbr
, struct zone
const *zp
, char const *letters
,
2629 bool isdst
, zic_t save
, bool doquotes
)
2634 char const *format
= zp
->z_format
;
2636 slashp
= strchr(format
, '/');
2639 char letterbuf
[PERCENT_Z_LEN_BOUND
+ 1];
2641 if (zp
->z_format_specifier
== 'z')
2642 letters
= abbroffset(letterbuf
, zp
->z_stdoff
+ save
);
2645 sprintf(abbr
, format
, letters
);
2649 strcpy(abbr
, slashp
+ 1);
2653 memcpy(abbr
, format
, slashp
- format
);
2654 abbr
[slashp
- format
] = '\0';
2659 for (cp
= abbr
; is_alpha(*cp
); cp
++)
2661 if (len
> 0 && *cp
== '\0')
2663 abbr
[len
+ 2] = '\0';
2664 abbr
[len
+ 1] = '>';
2665 memmove(abbr
+ 1, abbr
, len
);
2671 updateminmax(const zic_t x
)
2680 stringoffset(char *result
, zic_t offset
)
2685 bool negative
= offset
< 0;
2693 seconds
= offset
% SECSPERMIN
;
2694 offset
/= SECSPERMIN
;
2695 minutes
= offset
% MINSPERHOUR
;
2696 offset
/= MINSPERHOUR
;
2698 if (hours
>= HOURSPERDAY
* DAYSPERWEEK
)
2703 len
+= sprintf(result
+ len
, "%d", hours
);
2704 if (minutes
!= 0 || seconds
!= 0)
2706 len
+= sprintf(result
+ len
, ":%02d", minutes
);
2708 len
+= sprintf(result
+ len
, ":%02d", seconds
);
2714 stringrule(char *result
, struct rule
*const rp
, zic_t save
, zic_t stdoff
)
2716 zic_t tod
= rp
->r_tod
;
2719 if (rp
->r_dycode
== DC_DOM
)
2724 if (rp
->r_dayofmonth
== 29 && rp
->r_month
== TM_FEBRUARY
)
2727 for (month
= 0; month
< rp
->r_month
; ++month
)
2728 total
+= len_months
[0][month
];
2729 /* Omit the "J" in Jan and Feb, as that's shorter. */
2730 if (rp
->r_month
<= 1)
2731 result
+= sprintf(result
, "%d", total
+ rp
->r_dayofmonth
- 1);
2733 result
+= sprintf(result
, "J%d", total
+ rp
->r_dayofmonth
);
2738 int wday
= rp
->r_wday
;
2741 if (rp
->r_dycode
== DC_DOWGEQ
)
2743 wdayoff
= (rp
->r_dayofmonth
- 1) % DAYSPERWEEK
;
2747 tod
+= wdayoff
* SECSPERDAY
;
2748 week
= 1 + (rp
->r_dayofmonth
- 1) / DAYSPERWEEK
;
2750 else if (rp
->r_dycode
== DC_DOWLEQ
)
2752 if (rp
->r_dayofmonth
== len_months
[1][rp
->r_month
])
2756 wdayoff
= rp
->r_dayofmonth
% DAYSPERWEEK
;
2760 tod
+= wdayoff
* SECSPERDAY
;
2761 week
= rp
->r_dayofmonth
/ DAYSPERWEEK
;
2765 return -1; /* "cannot happen" */
2767 wday
+= DAYSPERWEEK
;
2768 result
+= sprintf(result
, "M%d.%d.%d",
2769 rp
->r_month
+ 1, week
, wday
);
2773 if (rp
->r_todisstd
&& !rp
->r_isdst
)
2775 if (tod
!= 2 * SECSPERMIN
* MINSPERHOUR
)
2778 if (!stringoffset(result
, tod
))
2785 else if (SECSPERDAY
<= tod
)
2795 rule_cmp(struct rule
const *a
, struct rule
const *b
)
2801 if (a
->r_hiyear
!= b
->r_hiyear
)
2802 return a
->r_hiyear
< b
->r_hiyear
? -1 : 1;
2803 if (a
->r_month
- b
->r_month
!= 0)
2804 return a
->r_month
- b
->r_month
;
2805 return a
->r_dayofmonth
- b
->r_dayofmonth
;
2809 stringzone(char *result
, struct zone
const *zpfirst
, ptrdiff_t zonecount
)
2811 const struct zone
*zp
;
2816 const char *abbrvar
;
2827 * Internet RFC 8536 section 5.1 says to use an empty TZ string if future
2828 * timestamps are truncated.
2830 if (hi_time
< max_time
)
2833 zp
= zpfirst
+ zonecount
- 1;
2834 stdrp
= dstrp
= NULL
;
2835 for (i
= 0; i
< zp
->z_nrules
; ++i
)
2837 rp
= &zp
->z_rules
[i
];
2838 if (rp
->r_hiwasnum
|| rp
->r_hiyear
!= ZIC_MAX
)
2855 if (stdrp
== NULL
&& dstrp
== NULL
)
2858 * There are no rules running through "max". Find the latest std rule
2859 * in stdabbrrp and latest rule of any type in stdrp.
2861 struct rule
*stdabbrrp
= NULL
;
2863 for (i
= 0; i
< zp
->z_nrules
; ++i
)
2865 rp
= &zp
->z_rules
[i
];
2866 if (!rp
->r_isdst
&& rule_cmp(stdabbrrp
, rp
) < 0)
2868 if (rule_cmp(stdrp
, rp
) < 0)
2871 if (stdrp
!= NULL
&& stdrp
->r_isdst
)
2873 /* Perpetual DST. */
2874 dstr
.r_month
= TM_JANUARY
;
2875 dstr
.r_dycode
= DC_DOM
;
2876 dstr
.r_dayofmonth
= 1;
2878 dstr
.r_todisstd
= dstr
.r_todisut
= false;
2879 dstr
.r_isdst
= stdrp
->r_isdst
;
2880 dstr
.r_save
= stdrp
->r_save
;
2881 dstr
.r_abbrvar
= stdrp
->r_abbrvar
;
2882 stdr
.r_month
= TM_DECEMBER
;
2883 stdr
.r_dycode
= DC_DOM
;
2884 stdr
.r_dayofmonth
= 31;
2885 stdr
.r_tod
= SECSPERDAY
+ stdrp
->r_save
;
2886 stdr
.r_todisstd
= stdr
.r_todisut
= false;
2887 stdr
.r_isdst
= false;
2890 = (stdabbrrp
? stdabbrrp
->r_abbrvar
: "");
2895 if (stdrp
== NULL
&& (zp
->z_nrules
!= 0 || zp
->z_isdst
))
2897 abbrvar
= (stdrp
== NULL
) ? "" : stdrp
->r_abbrvar
;
2898 len
= doabbr(result
, zp
, abbrvar
, false, 0, true);
2899 offsetlen
= stringoffset(result
+ len
, -zp
->z_stdoff
);
2908 len
+= doabbr(result
+ len
, zp
, dstrp
->r_abbrvar
,
2909 dstrp
->r_isdst
, dstrp
->r_save
, true);
2910 if (dstrp
->r_save
!= SECSPERMIN
* MINSPERHOUR
)
2912 offsetlen
= stringoffset(result
+ len
,
2913 -(zp
->z_stdoff
+ dstrp
->r_save
));
2921 result
[len
++] = ',';
2922 c
= stringrule(result
+ len
, dstrp
, dstrp
->r_save
, zp
->z_stdoff
);
2930 len
+= strlen(result
+ len
);
2931 result
[len
++] = ',';
2932 c
= stringrule(result
+ len
, stdrp
, dstrp
->r_save
, zp
->z_stdoff
);
2944 outzone(const struct zone
*zpfirst
, ptrdiff_t zonecount
)
2946 const struct zone
*zp
;
2966 bool prodstic
; /* all rules are min to max */
2970 ptrdiff_t lastatmax
= -1;
2972 zic_t y2038_boundary
= one
<< 31;
2974 int defaulttype
= -1;
2976 max_abbr_len
= 2 + max_format_len
+ max_abbrvar_len
;
2977 max_envvar_len
= 2 * max_abbr_len
+ 5 * 9;
2978 startbuf
= emalloc(max_abbr_len
+ 1);
2979 ab
= emalloc(max_abbr_len
+ 1);
2980 envvar
= emalloc(max_envvar_len
+ 1);
2981 INITIALIZE(untiltime
);
2982 INITIALIZE(starttime
);
2985 * Now. . .finally. . .generate some useful data!
2990 prodstic
= zonecount
== 1;
2993 * Thanks to Earl Chew for noting the need to unconditionally initialize
2996 startttisstd
= false;
2997 startttisut
= false;
2998 min_year
= max_year
= EPOCH_YEAR
;
3001 updateminmax(leapminyear
);
3002 updateminmax(leapmaxyear
+ (leapmaxyear
< ZIC_MAX
));
3004 for (i
= 0; i
< zonecount
; ++i
)
3007 if (i
< zonecount
- 1)
3008 updateminmax(zp
->z_untilrule
.r_loyear
);
3009 for (j
= 0; j
< zp
->z_nrules
; ++j
)
3011 rp
= &zp
->z_rules
[j
];
3013 updateminmax(rp
->r_loyear
);
3015 updateminmax(rp
->r_hiyear
);
3016 if (rp
->r_lowasnum
|| rp
->r_hiwasnum
)
3022 * Generate lots of data if a rule can't cover all future times.
3024 compat
= stringzone(envvar
, zpfirst
, zonecount
);
3025 version
= compat
< 2013 ? ZIC_VERSION_PRE_2013
: ZIC_VERSION
;
3026 do_extend
= compat
< 0;
3031 _("no POSIX environment variable for zone"),
3033 else if (compat
!= 0)
3036 * Circa-COMPAT clients, and earlier clients, might not work for
3037 * this zone when given dates before 1970 or after 2038.
3039 warning(_("%s: pre-%d clients may mishandle"
3040 " distant timestamps"),
3041 zpfirst
->z_name
, compat
);
3047 * Search through a couple of extra years past the obvious 400, to
3048 * avoid edge cases. For example, suppose a non-POSIX rule applies
3049 * from 2012 onwards and has transitions in March and September, plus
3050 * some one-off transitions in November 2013. If zic looked only at
3051 * the last 400 years, it would set max_year=2413, with the intent
3052 * that the 400 years 2014 through 2413 will be repeated. The last
3053 * transition listed in the tzfile would be in 2413-09, less than 400
3054 * years after the last one-off transition in 2013-11. Two years
3055 * might be overkill, but with the kind of edge cases available we're
3056 * not sure that one year would suffice.
3060 years_of_observations
= YEARSPERREPEAT
+ 2};
3062 if (min_year
>= ZIC_MIN
+ years_of_observations
)
3063 min_year
-= years_of_observations
;
3066 if (max_year
<= ZIC_MAX
- years_of_observations
)
3067 max_year
+= years_of_observations
;
3072 * Regardless of any of the above, for a "proDSTic" zone which
3073 * specifies that its rules always have and always will be in effect,
3074 * we only need one cycle to define the zone.
3079 max_year
= min_year
+ years_of_observations
;
3082 max_year0
= max_year
;
3086 * For the benefit of older systems, generate data from 1900 through
3089 if (min_year
> 1900)
3091 if (max_year
< 2038)
3095 for (i
= 0; i
< zonecount
; ++i
)
3097 struct rule
*prevrp
= NULL
;
3100 * A guess that may well be corrected later.
3104 usestart
= i
> 0 && (zp
- 1)->z_untiltime
> min_time
;
3105 useuntil
= i
< (zonecount
- 1);
3106 if (useuntil
&& zp
->z_untiltime
<= min_time
)
3108 stdoff
= zp
->z_stdoff
;
3109 eat(zp
->z_filename
, zp
->z_linenum
);
3111 startoff
= zp
->z_stdoff
;
3112 if (zp
->z_nrules
== 0)
3115 doabbr(startbuf
, zp
, NULL
, zp
->z_isdst
, save
, false);
3116 type
= addtype(oadd(zp
->z_stdoff
, save
),
3117 startbuf
, zp
->z_isdst
, startttisstd
,
3121 addtt(starttime
, type
);
3128 for (year
= min_year
; year
<= max_year
; ++year
)
3130 if (useuntil
&& year
> zp
->z_untilrule
.r_hiyear
)
3134 * Mark which rules to do in the current year. For those to
3135 * do, calculate rpytime(rp, year); The former TYPE field was
3136 * also considered here.
3138 for (j
= 0; j
< zp
->z_nrules
; ++j
)
3140 rp
= &zp
->z_rules
[j
];
3141 eats(zp
->z_filename
, zp
->z_linenum
,
3142 rp
->r_filename
, rp
->r_linenum
);
3143 rp
->r_todo
= year
>= rp
->r_loyear
&&
3144 year
<= rp
->r_hiyear
;
3147 rp
->r_temp
= rpytime(rp
, year
);
3149 = (rp
->r_temp
< y2038_boundary
3150 || year
<= max_year0
);
3164 * Turn untiltime into UT assuming the current stdoff
3167 untiltime
= zp
->z_untiltime
;
3168 if (!zp
->z_untilrule
.r_todisut
)
3169 untiltime
= tadd(untiltime
,
3171 if (!zp
->z_untilrule
.r_todisstd
)
3172 untiltime
= tadd(untiltime
,
3177 * Find the rule (of those to do, if any) that takes
3178 * effect earliest in the year.
3181 for (j
= 0; j
< zp
->z_nrules
; ++j
)
3183 rp
= &zp
->z_rules
[j
];
3186 eats(zp
->z_filename
, zp
->z_linenum
,
3187 rp
->r_filename
, rp
->r_linenum
);
3188 offset
= rp
->r_todisut
? 0 : stdoff
;
3189 if (!rp
->r_todisstd
)
3190 offset
= oadd(offset
, save
);
3192 if (jtime
== min_time
||
3195 jtime
= tadd(jtime
, -offset
);
3196 if (k
< 0 || jtime
< ktime
)
3201 else if (jtime
== ktime
)
3203 char const *dup_rules_msg
=
3204 _("two rules for same instant");
3206 eats(zp
->z_filename
, zp
->z_linenum
,
3207 rp
->r_filename
, rp
->r_linenum
);
3208 warning("%s", dup_rules_msg
);
3209 rp
= &zp
->z_rules
[k
];
3210 eats(zp
->z_filename
, zp
->z_linenum
,
3211 rp
->r_filename
, rp
->r_linenum
);
3212 error("%s", dup_rules_msg
);
3216 break; /* go on to next year */
3217 rp
= &zp
->z_rules
[k
];
3219 if (useuntil
&& ktime
>= untiltime
)
3222 if (usestart
&& ktime
== starttime
)
3226 if (ktime
< starttime
)
3228 startoff
= oadd(zp
->z_stdoff
,
3230 doabbr(startbuf
, zp
,
3237 if (*startbuf
== '\0'
3238 && startoff
== oadd(zp
->z_stdoff
,
3249 eats(zp
->z_filename
, zp
->z_linenum
,
3250 rp
->r_filename
, rp
->r_linenum
);
3251 doabbr(ab
, zp
, rp
->r_abbrvar
,
3252 rp
->r_isdst
, rp
->r_save
, false);
3253 offset
= oadd(zp
->z_stdoff
, rp
->r_save
);
3254 if (!want_bloat() && !useuntil
&& !do_extend
3256 && rp
->r_hiyear
== ZIC_MAX
3257 && prevrp
->r_hiyear
== ZIC_MAX
)
3259 type
= addtype(offset
, ab
, rp
->r_isdst
,
3260 rp
->r_todisstd
, rp
->r_todisut
);
3261 if (defaulttype
< 0 && !rp
->r_isdst
)
3263 if (rp
->r_hiyear
== ZIC_MAX
3265 && ktime
< attypes
[lastatmax
].at
))
3266 lastatmax
= timecnt
;
3273 if (*startbuf
== '\0' &&
3274 zp
->z_format
!= NULL
&&
3275 strchr(zp
->z_format
, '%') == NULL
&&
3276 strchr(zp
->z_format
, '/') == NULL
)
3277 strcpy(startbuf
, zp
->z_format
);
3278 eat(zp
->z_filename
, zp
->z_linenum
);
3279 if (*startbuf
== '\0')
3280 error(_("cannot determine time zone abbreviation to use just after until time"));
3283 bool isdst
= startoff
!= zp
->z_stdoff
;
3285 type
= addtype(startoff
, startbuf
, isdst
,
3286 startttisstd
, startttisut
);
3287 if (defaulttype
< 0 && !isdst
)
3289 addtt(starttime
, type
);
3294 * Now we may get to set starttime for the next zone line.
3298 startttisstd
= zp
->z_untilrule
.r_todisstd
;
3299 startttisut
= zp
->z_untilrule
.r_todisut
;
3300 starttime
= zp
->z_untiltime
;
3302 starttime
= tadd(starttime
, -save
);
3304 starttime
= tadd(starttime
, -stdoff
);
3307 if (defaulttype
< 0)
3310 attypes
[lastatmax
].dontmerge
= true;
3314 * If we're extending the explicitly listed observations for 400 years
3315 * because we can't fill the POSIX-TZ field, check whether we actually
3316 * ended up explicitly listing observations through that period. If
3317 * there aren't any near the end of the 400-year period, add a
3318 * redundant one at the end of the final year, to make it clear that
3319 * we are claiming to have definite knowledge of the lack of
3320 * transitions up to that point.
3323 struct attype
*lastat
;
3325 xr
.r_month
= TM_JANUARY
;
3326 xr
.r_dycode
= DC_DOM
;
3327 xr
.r_dayofmonth
= 1;
3329 for (lastat
= attypes
, i
= 1; i
< timecnt
; i
++)
3330 if (attypes
[i
].at
> lastat
->at
)
3331 lastat
= &attypes
[i
];
3332 if (!lastat
|| lastat
->at
< rpytime(&xr
, max_year
- 1))
3334 addtt(rpytime(&xr
, max_year
+ 1),
3335 lastat
? lastat
->type
: defaulttype
);
3336 attypes
[timecnt
- 1].dontmerge
= true;
3339 writezone(zpfirst
->z_name
, envvar
, version
, defaulttype
);
3346 addtt(zic_t starttime
, int type
)
3348 attypes
= growalloc(attypes
, sizeof *attypes
, timecnt
, &timecnt_alloc
);
3349 attypes
[timecnt
].at
= starttime
;
3350 attypes
[timecnt
].dontmerge
= false;
3351 attypes
[timecnt
].type
= type
;
3356 addtype(zic_t utoff
, char const *abbr
, bool isdst
, bool ttisstd
, bool ttisut
)
3361 if (!(-1L - 2147483647L <= utoff
&& utoff
<= 2147483647L))
3363 error(_("UT offset out of range"));
3367 ttisstd
= ttisut
= false;
3369 for (j
= 0; j
< charcnt
; ++j
)
3370 if (strcmp(&chars
[j
], abbr
) == 0)
3376 /* If there's already an entry, return its index. */
3377 for (i
= 0; i
< typecnt
; i
++)
3378 if (utoff
== utoffs
[i
] && isdst
== isdsts
[i
] && j
== desigidx
[i
]
3379 && ttisstd
== ttisstds
[i
] && ttisut
== ttisuts
[i
])
3384 * There isn't one; add a new one, unless there are already too many.
3386 if (typecnt
>= TZ_MAX_TYPES
)
3388 error(_("too many local time types"));
3394 ttisstds
[i
] = ttisstd
;
3395 ttisuts
[i
] = ttisut
;
3401 leapadd(zic_t t
, int correction
, int rolling
)
3405 if (TZ_MAX_LEAPS
<= leapcnt
)
3407 error(_("too many leap seconds"));
3410 for (i
= 0; i
< leapcnt
; ++i
)
3413 memmove(&trans
[i
+ 1], &trans
[i
], (leapcnt
- i
) * sizeof *trans
);
3414 memmove(&corr
[i
+ 1], &corr
[i
], (leapcnt
- i
) * sizeof *corr
);
3415 memmove(&roll
[i
+ 1], &roll
[i
], (leapcnt
- i
) * sizeof *roll
);
3417 corr
[i
] = correction
;
3427 zic_t prevtrans
= 0;
3430 * propagate leap seconds forward
3432 for (i
= 0; i
< leapcnt
; ++i
)
3434 if (trans
[i
] - prevtrans
< 28 * SECSPERDAY
)
3436 error(_("Leap seconds too close together"));
3439 prevtrans
= trans
[i
];
3440 trans
[i
] = tadd(trans
[i
], last
);
3441 last
= corr
[i
] += last
;
3444 if (leapexpires
< 0)
3446 leapexpires
= comment_leapexpires
;
3447 if (0 <= leapexpires
)
3448 warning(_("\"#expires\" is obsolescent; use \"Expires\""));
3451 if (0 <= leapexpires
)
3453 leapexpires
= oadd(leapexpires
, last
);
3454 if (!(leapcnt
== 0 || (trans
[leapcnt
- 1] < leapexpires
)))
3456 error(_("last Leap time does not precede Expires time"));
3459 if (leapexpires
<= hi_time
)
3460 hi_time
= leapexpires
- 1;
3464 /* Is A a space character in the C locale? */
3482 /* Is A an alphabetic character in the C locale? */
3546 /* If A is an uppercase character in the C locale, return its lowercase
3547 counterpart. Otherwise, return A. */
3610 /* case-insensitive equality */
3612 ciequal(const char *ap
, const char *bp
)
3614 while (lowerit(*ap
) == lowerit(*bp
++))
3621 itsabbr(const char *abbr
, const char *word
)
3623 if (lowerit(*abbr
) != lowerit(*word
))
3626 while (*++abbr
!= '\0')
3631 } while (lowerit(*word
++) != lowerit(*abbr
));
3635 /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
3638 ciprefix(char const *abbr
, char const *word
)
3643 while (lowerit(*abbr
++) == lowerit(*word
++));
3648 static const struct lookup
*
3649 byword(const char *word
, const struct lookup
*table
)
3651 const struct lookup
*foundlp
;
3652 const struct lookup
*lp
;
3654 if (word
== NULL
|| table
== NULL
)
3658 * If TABLE is LASTS and the word starts with "last" followed by a
3659 * non-'-', skip the "last" and look in WDAY_NAMES instead. Warn about any
3660 * usage of the undocumented prefix "last-".
3662 if (table
== lasts
&& ciprefix("last", word
) && word
[4])
3665 warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
3675 * Look for exact match.
3677 for (lp
= table
; lp
->l_word
!= NULL
; ++lp
)
3678 if (ciequal(word
, lp
->l_word
))
3682 * Look for inexact match.
3685 for (lp
= table
; lp
->l_word
!= NULL
; ++lp
)
3686 if (ciprefix(word
, lp
->l_word
))
3688 if (foundlp
== NULL
)
3691 return NULL
; /* multiple inexact matches */
3694 if (foundlp
&& noise
)
3696 /* Warn about any backward-compatibility issue with pre-2017c zic. */
3697 bool pre_2017c_match
= false;
3699 for (lp
= table
; lp
->l_word
; lp
++)
3700 if (itsabbr(word
, lp
->l_word
))
3702 if (pre_2017c_match
)
3704 warning(_("\"%s\" is ambiguous in pre-2017c zic"), word
);
3707 pre_2017c_match
= true;
3723 array
= emalloc(size_product(strlen(cp
) + 1, sizeof *array
));
3727 while (is_space(*cp
))
3729 if (*cp
== '\0' || *cp
== '#')
3731 array
[nsubs
++] = dp
= cp
;
3734 if ((*dp
= *cp
++) != '"')
3737 while ((*dp
= *cp
++) != '"')
3742 error(_("Odd number of quotation marks"));
3745 } while (*cp
&& *cp
!= '#' && !is_space(*cp
));
3750 array
[nsubs
] = NULL
;
3757 error(_("time overflow"));
3762 oadd(zic_t t1
, zic_t t2
)
3764 if (t1
< 0 ? t2
< ZIC_MIN
- t1
: ZIC_MAX
- t1
< t2
)
3770 tadd(zic_t t1
, zic_t t2
)
3774 if (t2
< min_time
- t1
)
3783 if (max_time
- t1
< t2
)
3794 * Given a rule, and a year, compute the date (in seconds since January 1,
3795 * 1970, 00:00 LOCAL time) in that year that the rule refers to.
3799 rpytime(const struct rule
*rp
, zic_t wantedy
)
3803 zic_t dayoff
; /* with a nod to Margaret O. */
3807 if (wantedy
== ZIC_MIN
)
3809 if (wantedy
== ZIC_MAX
)
3817 dayoff
= (wantedy
/ YEARSPERREPEAT
) * (SECSPERREPEAT
/ SECSPERDAY
);
3818 wantedy
%= YEARSPERREPEAT
;
3821 else if (wantedy
< 0)
3823 dayoff
= (wantedy
/ YEARSPERREPEAT
) * (SECSPERREPEAT
/ SECSPERDAY
);
3824 wantedy
%= YEARSPERREPEAT
;
3826 while (wantedy
!= y
)
3830 i
= len_years
[isleap(y
)];
3836 i
= -len_years
[isleap(y
)];
3838 dayoff
= oadd(dayoff
, i
);
3840 while (m
!= rp
->r_month
)
3842 i
= len_months
[isleap(y
)][m
];
3843 dayoff
= oadd(dayoff
, i
);
3846 i
= rp
->r_dayofmonth
;
3847 if (m
== TM_FEBRUARY
&& i
== 29 && !isleap(y
))
3849 if (rp
->r_dycode
== DC_DOWLEQ
)
3853 error(_("use of 2/29 in non leap-year"));
3858 dayoff
= oadd(dayoff
, i
);
3859 if (rp
->r_dycode
== DC_DOWGEQ
|| rp
->r_dycode
== DC_DOWLEQ
)
3863 #define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3867 * Don't trust mod of negative numbers.
3870 wday
= (wday
+ dayoff
) % LDAYSPERWEEK
;
3873 wday
-= ((-dayoff
) % LDAYSPERWEEK
);
3875 wday
+= LDAYSPERWEEK
;
3877 while (wday
!= rp
->r_wday
)
3878 if (rp
->r_dycode
== DC_DOWGEQ
)
3880 dayoff
= oadd(dayoff
, 1);
3881 if (++wday
>= LDAYSPERWEEK
)
3887 dayoff
= oadd(dayoff
, -1);
3889 wday
= LDAYSPERWEEK
- 1;
3892 if (i
< 0 || i
>= len_months
[isleap(y
)][m
])
3895 warning(_("rule goes past start/end of month; \
3896 will not work with pre-2004 versions of zic"));
3899 if (dayoff
< min_time
/ SECSPERDAY
)
3901 if (dayoff
> max_time
/ SECSPERDAY
)
3903 t
= (zic_t
) dayoff
* SECSPERDAY
;
3904 return tadd(t
, rp
->r_tod
);
3908 newabbr(const char *string
)
3912 if (strcmp(string
, GRANDPARENTED
) != 0)
3919 while (is_alpha(*cp
) || ('0' <= *cp
&& *cp
<= '9')
3920 || *cp
== '-' || *cp
== '+')
3922 if (noise
&& cp
- string
< 3)
3923 mp
= _("time zone abbreviation has fewer than 3 characters");
3924 if (cp
- string
> ZIC_MAX_ABBR_LEN_WO_WARN
)
3925 mp
= _("time zone abbreviation has too many characters");
3927 mp
= _("time zone abbreviation differs from POSIX standard");
3929 warning("%s (%s)", mp
, string
);
3931 i
= strlen(string
) + 1;
3932 if (charcnt
+ i
> TZ_MAX_CHARS
)
3934 error(_("too many, or too long, time zone abbreviations"));
3937 strcpy(&chars
[charcnt
], string
);
3941 /* Ensure that the directories of ARGNAME exist, by making any missing
3942 ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
3943 do it for ARGNAME too. Exit with failure if there is trouble.
3944 Do not consider an existing non-directory to be trouble. */
3946 mkdirs(char const *argname
, bool ancestors
)
3951 cp
= name
= ecpyalloc(argname
);
3954 * On MS-Windows systems, do not worry about drive letters or backslashes,
3955 * as this should suffice in practice. Time zone names do not use drive
3956 * letters and backslashes. If the -d option of zic does not name an
3957 * already-existing directory, it can use slashes to separate the
3958 * already-existing ancestor prefix from the to-be-created subdirectories.
3961 /* Do not mkdir a root directory, as it must exist. */
3965 while (cp
&& ((cp
= strchr(cp
, '/')) || !ancestors
))
3971 * Try to create it. It's OK if creation fails because the directory
3972 * already exists, perhaps because some other process just created it.
3973 * For simplicity do not check first whether it already exists, as
3974 * that is checked anyway if the mkdir fails.
3976 if (mkdir(name
, MKDIR_UMASK
) != 0)
3979 * For speed, skip itsdir if errno == EEXIST. Since mkdirs is
3980 * called only after open fails with ENOENT on a subfile, EEXIST
3981 * implies itsdir here.
3985 if (err
!= EEXIST
&& !itsdir(name
))
3987 error(_("%s: Cannot create directory %s: %s"),
3988 progname
, name
, strerror(err
));
4004 link(const char *oldpath
, const char *newpath
)
4006 if (!CopyFile(oldpath
, newpath
, false))
4008 _dosmaperr(GetLastError());