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 utoff
, char const *abbr
,
127 bool isdst
, bool ttisstd
, bool ttisut
);
128 static void leapadd(zic_t t
, int correction
, int rolling
);
129 static void adjleap(void);
130 static void associate(void);
131 static void dolink(char const *target
, char const *linkname
,
133 static char **getfields(char *cp
);
134 static zic_t
gethms(const char *string
, const char *errstring
);
135 static zic_t
getsave(char *field
, bool *isdst
);
136 static void inexpires(char **fields
, int nfields
);
137 static void infile(const char *name
);
138 static void inleap(char **fields
, int nfields
);
139 static void inlink(char **fields
, int nfields
);
140 static void inrule(char **fields
, int nfields
);
141 static bool inzcont(char **fields
, int nfields
);
142 static bool inzone(char **fields
, int nfields
);
143 static bool inzsub(char **fields
, int nfields
, bool iscont
);
144 static bool itsdir(char const *name
);
145 static bool itssymlink(char const *name
);
146 static bool is_alpha(char a
);
147 static char lowerit(char a
);
148 static void mkdirs(char const *argname
, bool ancestors
);
149 static void newabbr(const char *string
);
150 static zic_t
oadd(zic_t t1
, zic_t t2
);
151 static void outzone(const struct zone
*zpfirst
, ptrdiff_t zonecount
);
152 static zic_t
rpytime(const struct rule
*rp
, zic_t wantedy
);
153 static void rulesub(struct rule
*rp
,
154 const char *loyearp
, const char *hiyearp
,
155 const char *typep
, const char *monthp
,
156 const char *dayp
, const char *timep
);
157 static zic_t
tadd(zic_t t1
, zic_t t2
);
159 /* Bound on length of what %z can expand to. */
162 PERCENT_Z_LEN_BOUND
= sizeof "+995959" - 1};
164 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
165 TZif files whose POSIX-TZ-style strings contain '<'; see
166 QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
167 workaround will no longer be needed when Qt 5.6.1 and earlier are
168 obsolete, say in the year 2021. */
169 #ifndef WORK_AROUND_QTBUG_53071
172 WORK_AROUND_QTBUG_53071
= true};
177 static bool warnings
;
178 static const char *filename
;
180 static bool leapseen
;
181 static zic_t leapminyear
;
182 static zic_t leapmaxyear
;
183 static lineno_t linenum
;
184 static int max_abbrvar_len
= PERCENT_Z_LEN_BOUND
;
185 static int max_format_len
;
186 static zic_t max_year
;
187 static zic_t min_year
;
189 static bool print_abbrevs
;
190 static zic_t print_cutoff
;
191 static const char *rfilename
;
192 static lineno_t rlinenum
;
193 static const char *progname
;
194 static ptrdiff_t timecnt
;
195 static ptrdiff_t timecnt_alloc
;
209 * Which fields are which on a Zone line.
217 #define ZF_TILMONTH 6
220 #define ZONE_MINFIELDS 5
221 #define ZONE_MAXFIELDS 9
224 * Which fields are which on a Zone continuation line.
230 #define ZFC_TILYEAR 3
231 #define ZFC_TILMONTH 4
233 #define ZFC_TILTIME 6
234 #define ZONEC_MINFIELDS 3
235 #define ZONEC_MAXFIELDS 7
238 * Which files are which on a Rule line.
250 #define RULE_FIELDS 10
253 * Which fields are which on a Link line.
257 #define LF_LINKNAME 2
258 #define LINK_FIELDS 3
261 * Which fields are which on a Leap line.
270 #define LEAP_FIELDS 7
272 /* Expires lines are like Leap lines, except without CORR and ROLL fields. */
273 #define EXPIRES_FIELDS 5
283 static struct rule
*rules
;
284 static ptrdiff_t nrules
; /* number of rules */
285 static ptrdiff_t nrules_alloc
;
287 static struct zone
*zones
;
288 static ptrdiff_t nzones
; /* number of zones */
289 static ptrdiff_t nzones_alloc
;
293 const char *l_filename
;
295 const char *l_target
;
296 const char *l_linkname
;
299 static struct link
*links
;
300 static ptrdiff_t nlinks
;
301 static ptrdiff_t nlinks_alloc
;
309 static struct lookup
const *byword(const char *word
,
310 const struct lookup
*table
);
312 static struct lookup
const zi_line_codes
[] = {
318 static struct lookup
const leap_line_codes
[] = {
320 {"Expires", LC_EXPIRES
},
324 static struct lookup
const mon_names
[] = {
325 {"January", TM_JANUARY
},
326 {"February", TM_FEBRUARY
},
332 {"August", TM_AUGUST
},
333 {"September", TM_SEPTEMBER
},
334 {"October", TM_OCTOBER
},
335 {"November", TM_NOVEMBER
},
336 {"December", TM_DECEMBER
},
340 static struct lookup
const wday_names
[] = {
341 {"Sunday", TM_SUNDAY
},
342 {"Monday", TM_MONDAY
},
343 {"Tuesday", TM_TUESDAY
},
344 {"Wednesday", TM_WEDNESDAY
},
345 {"Thursday", TM_THURSDAY
},
346 {"Friday", TM_FRIDAY
},
347 {"Saturday", TM_SATURDAY
},
351 static struct lookup
const lasts
[] = {
352 {"last-Sunday", TM_SUNDAY
},
353 {"last-Monday", TM_MONDAY
},
354 {"last-Tuesday", TM_TUESDAY
},
355 {"last-Wednesday", TM_WEDNESDAY
},
356 {"last-Thursday", TM_THURSDAY
},
357 {"last-Friday", TM_FRIDAY
},
358 {"last-Saturday", TM_SATURDAY
},
362 static struct lookup
const begin_years
[] = {
363 {"minimum", YR_MINIMUM
},
364 {"maximum", YR_MAXIMUM
},
368 static struct lookup
const end_years
[] = {
369 {"minimum", YR_MINIMUM
},
370 {"maximum", YR_MAXIMUM
},
375 static struct lookup
const leap_types
[] = {
377 {"Stationary", false},
381 static const int len_months
[2][MONSPERYEAR
] = {
382 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
383 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
386 static const int len_years
[2] = {
387 DAYSPERNYEAR
, DAYSPERLYEAR
396 static zic_t utoffs
[TZ_MAX_TYPES
];
397 static char isdsts
[TZ_MAX_TYPES
];
398 static unsigned char desigidx
[TZ_MAX_TYPES
];
399 static bool ttisstds
[TZ_MAX_TYPES
];
400 static bool ttisuts
[TZ_MAX_TYPES
];
401 static char chars
[TZ_MAX_CHARS
];
402 static zic_t trans
[TZ_MAX_LEAPS
];
403 static zic_t corr
[TZ_MAX_LEAPS
];
404 static char roll
[TZ_MAX_LEAPS
];
411 memory_exhausted(const char *msg
)
413 fprintf(stderr
, _("%s: Memory exhausted: %s\n"), progname
, msg
);
418 size_product(size_t nitems
, size_t itemsize
)
420 if (SIZE_MAX
/ itemsize
< nitems
)
421 memory_exhausted(_("size overflow"));
422 return nitems
* itemsize
;
429 memory_exhausted(strerror(errno
));
436 return memcheck(malloc(size
));
440 erealloc(void *ptr
, size_t size
)
442 return memcheck(realloc(ptr
, size
));
446 ecpyalloc(char const *str
)
448 return memcheck(strdup(str
));
452 growalloc(void *ptr
, size_t itemsize
, ptrdiff_t nitems
, ptrdiff_t *nitems_alloc
)
454 if (nitems
< *nitems_alloc
)
458 ptrdiff_t nitems_max
= PTRDIFF_MAX
- WORK_AROUND_QTBUG_53071
;
459 ptrdiff_t amax
= nitems_max
< SIZE_MAX
? nitems_max
: SIZE_MAX
;
461 if ((amax
- 1) / 3 * 2 < *nitems_alloc
)
462 memory_exhausted(_("integer overflow"));
463 *nitems_alloc
+= (*nitems_alloc
>> 1) + 1;
464 return erealloc(ptr
, size_product(*nitems_alloc
, itemsize
));
473 eats(char const *name
, lineno_t num
, char const *rname
, lineno_t rnum
)
482 eat(char const *name
, lineno_t num
)
484 eats(name
, num
, NULL
, -1);
488 verror(const char *string
, va_list args
)
491 * Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
492 * "*" -v on BSD systems.
495 fprintf(stderr
, _("\"%s\", line %d: "), filename
, linenum
);
496 vfprintf(stderr
, string
, args
);
497 if (rfilename
!= NULL
)
498 fprintf(stderr
, _(" (rule from \"%s\", line %d)"),
499 rfilename
, rlinenum
);
500 fprintf(stderr
, "\n");
504 error(const char *string
,...)
508 va_start(args
, string
);
509 verror(string
, args
);
515 warning(const char *string
,...)
519 fprintf(stderr
, _("warning: "));
520 va_start(args
, string
);
521 verror(string
, args
);
527 close_file(FILE *stream
, char const *dir
, char const *name
)
529 char const *e
= (ferror(stream
) ? _("I/O error")
530 : fclose(stream
) != 0 ? strerror(errno
) : NULL
);
534 fprintf(stderr
, "%s: %s%s%s%s%s\n", progname
,
535 dir
? dir
: "", dir
? "/" : "",
536 name
? name
: "", name
? ": " : "",
543 usage(FILE *stream
, int status
)
546 _("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
547 "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
548 " [ -L leapseconds ] \\\n"
549 "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
550 "\t[ filename ... ]\n\n"
551 "Report bugs to %s.\n"),
552 progname
, progname
, PACKAGE_BUGREPORT
);
553 if (status
== EXIT_SUCCESS
)
554 close_file(stream
, NULL
, NULL
);
558 /* Change the working directory to DIR, possibly creating DIR and its
559 ancestors. After this is done, all files are accessed with names
562 change_directory(char const *dir
)
566 int chdir_errno
= errno
;
568 if (chdir_errno
== ENOENT
)
571 chdir_errno
= chdir(dir
) == 0 ? 0 : errno
;
573 if (chdir_errno
!= 0)
575 fprintf(stderr
, _("%s: Can't chdir to %s: %s\n"),
576 progname
, dir
, strerror(chdir_errno
));
582 #define TIME_T_BITS_IN_FILE 64
584 /* The minimum and maximum values representable in a TZif file. */
585 static zic_t
const min_time
= MINVAL(zic_t
, TIME_T_BITS_IN_FILE
);
586 static zic_t
const max_time
= MAXVAL(zic_t
, TIME_T_BITS_IN_FILE
);
588 /* The minimum, and one less than the maximum, values specified by
589 the -r option. These default to MIN_TIME and MAX_TIME. */
590 static zic_t lo_time
= MINVAL(zic_t
, TIME_T_BITS_IN_FILE
);
591 static zic_t hi_time
= MAXVAL(zic_t
, TIME_T_BITS_IN_FILE
);
593 /* The time specified by an Expires line, or negative if no such line. */
594 static zic_t leapexpires
= -1;
596 /* The time specified by an #expires comment, or negative if no such line. */
597 static zic_t comment_leapexpires
= -1;
599 /* Set the time range of the output to TIMERANGE.
600 Return true if successful. */
602 timerange_option(char *timerange
)
606 char *lo_end
= timerange
,
609 if (*timerange
== '@')
612 lo
= strtoimax(timerange
+ 1, &lo_end
, 10);
613 if (lo_end
== timerange
+ 1 || (lo
== PG_INT64_MAX
&& errno
== ERANGE
))
617 if (lo_end
[0] == '/' && lo_end
[1] == '@')
620 hi
= strtoimax(lo_end
+ 2, &hi_end
, 10);
621 if (hi_end
== lo_end
+ 2 || hi
== PG_INT64_MIN
)
623 hi
-= !(hi
== PG_INT64_MAX
&& errno
== ERANGE
);
625 if (*hi_end
|| hi
< lo
|| max_time
< lo
|| hi
< min_time
)
627 lo_time
= lo
< min_time
? min_time
: lo
;
628 hi_time
= max_time
< hi
? max_time
: hi
;
632 static const char *psxrules
;
633 static const char *lcltime
;
634 static const char *directory
;
635 static const char *leapsec
;
636 static const char *tzdefault
;
638 /* -1 if the TZif output file should be slim, 0 if default, 1 if the
639 output should be fat for backward compatibility. ZIC_BLOAT_DEFAULT
640 determines the default. */
649 #ifndef ZIC_BLOAT_DEFAULT
650 #define ZIC_BLOAT_DEFAULT "slim"
654 main(int argc
, char **argv
)
660 bool timerange_given
= false;
663 umask(umask(S_IWGRP
| S_IWOTH
) | (S_IWGRP
| S_IWOTH
));
666 if (TYPE_BIT(zic_t
) < 64)
668 fprintf(stderr
, "%s: %s\n", progname
,
669 _("wild compilation-time specification of zic_t"));
672 for (k
= 1; k
< argc
; k
++)
673 if (strcmp(argv
[k
], "--version") == 0)
675 printf("zic %s\n", PG_VERSION
);
676 close_file(stdout
, NULL
, NULL
);
679 else if (strcmp(argv
[k
], "--help") == 0)
681 usage(stdout
, EXIT_SUCCESS
);
683 while ((c
= getopt(argc
, argv
, "b:d:l:L:p:Pr:st:vy:")) != EOF
&& c
!= -1)
687 usage(stderr
, EXIT_FAILURE
);
689 if (strcmp(optarg
, "slim") == 0)
692 error(_("incompatible -b options"));
695 else if (strcmp(optarg
, "fat") == 0)
698 error(_("incompatible -b options"));
702 error(_("invalid option: -b '%s'"), optarg
);
705 if (directory
== NULL
)
706 directory
= strdup(optarg
);
710 _("%s: More than one -d option specified\n"),
717 lcltime
= strdup(optarg
);
721 _("%s: More than one -l option specified\n"),
727 if (psxrules
== NULL
)
728 psxrules
= strdup(optarg
);
732 _("%s: More than one -p option specified\n"),
738 if (tzdefault
!= NULL
)
741 _("%s: More than one -t option"
749 warning(_("-y ignored"));
753 leapsec
= strdup(optarg
);
757 _("%s: More than one -L option specified\n"),
766 print_abbrevs
= true;
767 print_cutoff
= time(NULL
);
773 _("%s: More than one -r option specified\n"),
777 if (!timerange_option(optarg
))
780 _("%s: invalid time range: %s\n"),
784 timerange_given
= true;
787 warning(_("-s ignored"));
790 if (optind
== argc
- 1 && strcmp(argv
[optind
], "=") == 0)
791 usage(stderr
, EXIT_FAILURE
); /* usage message by request */
794 static char const bloat_default
[] = ZIC_BLOAT_DEFAULT
;
796 if (strcmp(bloat_default
, "slim") == 0)
798 else if (strcmp(bloat_default
, "fat") == 0)
801 abort(); /* Configuration error. */
803 if (directory
== NULL
)
805 if (tzdefault
== NULL
)
806 tzdefault
= TZDEFAULT
;
808 if (optind
< argc
&& leapsec
!= NULL
)
814 for (k
= optind
; k
< argc
; k
++)
819 change_directory(directory
);
820 for (i
= 0; i
< nzones
; i
= j
)
823 * Find the next non-continuation zone entry.
825 for (j
= i
+ 1; j
< nzones
&& zones
[j
].z_name
== NULL
; ++j
)
827 outzone(&zones
[i
], j
- i
);
833 for (i
= 0; i
< nlinks
; ++i
)
835 eat(links
[i
].l_filename
, links
[i
].l_linenum
);
836 dolink(links
[i
].l_target
, links
[i
].l_linkname
, false);
838 for (j
= 0; j
< nlinks
; ++j
)
839 if (strcmp(links
[i
].l_linkname
,
840 links
[j
].l_target
) == 0)
841 warning(_("link to link"));
845 eat(_("command line"), 1);
846 dolink(lcltime
, tzdefault
, true);
848 if (psxrules
!= NULL
)
850 eat(_("command line"), 1);
851 dolink(psxrules
, TZDEFRULES
, true);
853 if (warnings
&& (ferror(stderr
) || fclose(stderr
) != 0))
855 return errors
? EXIT_FAILURE
: EXIT_SUCCESS
;
859 componentcheck(char const *name
, char const *component
,
860 char const *component_end
)
864 component_len_max
= 14};
865 ptrdiff_t component_len
= component_end
- component
;
867 if (component_len
== 0)
870 error(_("empty file name"));
872 error(_(component
== name
873 ? "file name '%s' begins with '/'"
875 ? "file name '%s' contains '//'"
876 : "file name '%s' ends with '/'"),
880 if (0 < component_len
&& component_len
<= 2
881 && component
[0] == '.' && component_end
[-1] == '.')
883 int len
= component_len
;
885 error(_("file name '%s' contains '%.*s' component"),
886 name
, len
, component
);
891 if (0 < component_len
&& component
[0] == '-')
892 warning(_("file name '%s' component contains leading '-'"),
894 if (component_len_max
< component_len
)
895 warning(_("file name '%s' contains overlength component"
897 name
, component_len_max
, component
);
903 namecheck(const char *name
)
907 /* Benign characters in a portable file name. */
908 static char const benign
[] =
910 "abcdefghijklmnopqrstuvwxyz"
911 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
914 * Non-control chars in the POSIX portable character set, excluding the
917 static char const printable_and_not_benign
[] =
918 " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
920 char const *component
= name
;
922 for (cp
= name
; *cp
; cp
++)
924 unsigned char c
= *cp
;
926 if (noise
&& !strchr(benign
, c
))
928 warning((strchr(printable_and_not_benign
, c
)
929 ? _("file name '%s' contains byte '%c'")
930 : _("file name '%s' contains byte '\\%o'")),
935 if (!componentcheck(name
, component
, cp
))
940 return componentcheck(name
, component
, cp
);
944 * Create symlink contents suitable for symlinking FROM to TO, as a
945 * freshly allocated string. FROM should be a relative file name, and
946 * is relative to the global variable DIRECTORY. TO can be either
947 * relative or absolute.
951 relname(char const *target
, char const *linkname
)
959 char const *f
= target
;
962 if (*linkname
== '/')
964 /* Make F absolute too. */
965 size_t len
= strlen(directory
);
966 bool needslash
= len
&& directory
[len
- 1] != '/';
968 linksize
= len
+ needslash
+ strlen(target
) + 1;
969 f
= result
= emalloc(linksize
);
970 strcpy(result
, directory
);
972 strcpy(result
+ len
+ needslash
, target
);
974 for (i
= 0; f
[i
] && f
[i
] == linkname
[i
]; i
++)
977 for (; linkname
[i
]; i
++)
978 dotdots
+= linkname
[i
] == '/' && linkname
[i
- 1] != '/';
979 taillen
= strlen(f
+ dir_len
);
980 dotdotetcsize
= 3 * dotdots
+ taillen
+ 1;
981 if (dotdotetcsize
<= linksize
)
984 result
= emalloc(dotdotetcsize
);
985 for (i
= 0; i
< dotdots
; i
++)
986 memcpy(result
+ 3 * i
, "../", 3);
987 memmove(result
+ 3 * dotdots
, f
+ dir_len
, taillen
+ 1);
991 #endif /* HAVE_SYMLINK */
993 /* Hard link FROM to TO, following any symbolic links.
994 Return 0 if successful, an error number otherwise. */
996 hardlinkerr(char const *target
, char const *linkname
)
998 int r
= linkat(AT_FDCWD
, target
, AT_FDCWD
, linkname
, AT_SYMLINK_FOLLOW
);
1000 return r
== 0 ? 0 : errno
;
1004 dolink(char const *target
, char const *linkname
, bool staysymlink
)
1006 bool remove_only
= strcmp(target
, "-") == 0;
1007 bool linkdirs_made
= false;
1011 * We get to be careful here since there's a fair chance of root running
1014 if (!remove_only
&& itsdir(target
))
1016 fprintf(stderr
, _("%s: linking target %s/%s failed: %s\n"),
1017 progname
, directory
, target
, strerror(EPERM
));
1021 staysymlink
= itssymlink(linkname
);
1022 if (remove(linkname
) == 0)
1023 linkdirs_made
= true;
1024 else if (errno
!= ENOENT
)
1026 char const *e
= strerror(errno
);
1028 fprintf(stderr
, _("%s: Can't remove %s/%s: %s\n"),
1029 progname
, directory
, linkname
, e
);
1034 link_errno
= staysymlink
? ENOTSUP
: hardlinkerr(target
, linkname
);
1035 if (link_errno
== ENOENT
&& !linkdirs_made
)
1037 mkdirs(linkname
, true);
1038 linkdirs_made
= true;
1039 link_errno
= hardlinkerr(target
, linkname
);
1041 if (link_errno
!= 0)
1044 bool absolute
= *target
== '/';
1045 char *linkalloc
= absolute
? NULL
: relname(target
, linkname
);
1046 char const *contents
= absolute
? target
: linkalloc
;
1047 int symlink_errno
= symlink(contents
, linkname
) == 0 ? 0 : errno
;
1050 && (symlink_errno
== ENOENT
|| symlink_errno
== ENOTSUP
))
1052 mkdirs(linkname
, true);
1053 if (symlink_errno
== ENOENT
)
1054 symlink_errno
= symlink(contents
, linkname
) == 0 ? 0 : errno
;
1057 if (symlink_errno
== 0)
1059 if (link_errno
!= ENOTSUP
)
1060 warning(_("symbolic link used because hard link failed: %s"),
1061 strerror(link_errno
));
1064 #endif /* HAVE_SYMLINK */
1070 fp
= fopen(target
, "rb");
1073 char const *e
= strerror(errno
);
1075 fprintf(stderr
, _("%s: Can't read %s/%s: %s\n"),
1076 progname
, directory
, target
, e
);
1079 tp
= fopen(linkname
, "wb");
1082 char const *e
= strerror(errno
);
1084 fprintf(stderr
, _("%s: Can't create %s/%s: %s\n"),
1085 progname
, directory
, linkname
, e
);
1088 while ((c
= getc(fp
)) != EOF
)
1090 close_file(fp
, directory
, target
);
1091 close_file(tp
, directory
, linkname
);
1092 if (link_errno
!= ENOTSUP
)
1093 warning(_("copy used because hard link failed: %s"),
1094 strerror(link_errno
));
1096 else if (symlink_errno
!= ENOTSUP
)
1097 warning(_("copy used because symbolic link failed: %s"),
1098 strerror(symlink_errno
));
1104 /* Return true if NAME is a directory. */
1106 itsdir(char const *name
)
1109 int res
= stat(name
, &st
);
1112 return S_ISDIR(st
.st_mode
) != 0;
1114 if (res
== 0 || errno
== EOVERFLOW
)
1116 size_t n
= strlen(name
);
1117 char *nameslashdot
= emalloc(n
+ 3);
1120 memcpy(nameslashdot
, name
, n
);
1121 strcpy(&nameslashdot
[n
], &"/."[!(n
&& name
[n
- 1] != '/')]);
1122 dir
= stat(nameslashdot
, &st
) == 0 || errno
== EOVERFLOW
;
1129 /* Return true if NAME is a symbolic link. */
1131 itssymlink(char const *name
)
1136 return 0 <= readlink(name
, &c
, 1);
1143 * Associate sets of rules with zones.
1147 * Sort by rule name.
1151 rcomp(const void *cp1
, const void *cp2
)
1153 return strcmp(((const struct rule
*) cp1
)->r_name
,
1154 ((const struct rule
*) cp2
)->r_name
);
1169 qsort(rules
, nrules
, sizeof *rules
, rcomp
);
1170 for (i
= 0; i
< nrules
- 1; ++i
)
1172 if (strcmp(rules
[i
].r_name
,
1173 rules
[i
+ 1].r_name
) != 0)
1175 if (strcmp(rules
[i
].r_filename
,
1176 rules
[i
+ 1].r_filename
) == 0)
1178 eat(rules
[i
].r_filename
, rules
[i
].r_linenum
);
1179 warning(_("same rule name in multiple files"));
1180 eat(rules
[i
+ 1].r_filename
, rules
[i
+ 1].r_linenum
);
1181 warning(_("same rule name in multiple files"));
1182 for (j
= i
+ 2; j
< nrules
; ++j
)
1184 if (strcmp(rules
[i
].r_name
,
1185 rules
[j
].r_name
) != 0)
1187 if (strcmp(rules
[i
].r_filename
,
1188 rules
[j
].r_filename
) == 0)
1190 if (strcmp(rules
[i
+ 1].r_filename
,
1191 rules
[j
].r_filename
) == 0)
1198 for (i
= 0; i
< nzones
; ++i
)
1204 for (base
= 0; base
< nrules
; base
= out
)
1207 for (out
= base
+ 1; out
< nrules
; ++out
)
1208 if (strcmp(rp
->r_name
, rules
[out
].r_name
) != 0)
1210 for (i
= 0; i
< nzones
; ++i
)
1213 if (strcmp(zp
->z_rule
, rp
->r_name
) != 0)
1216 zp
->z_nrules
= out
- base
;
1219 for (i
= 0; i
< nzones
; ++i
)
1222 if (zp
->z_nrules
== 0)
1225 * Maybe we have a local standard time offset.
1227 eat(zp
->z_filename
, zp
->z_linenum
);
1228 zp
->z_save
= getsave(zp
->z_rule
, &zp
->z_isdst
);
1231 * Note, though, that if there's no rule, a '%s' in the format is
1234 if (zp
->z_format_specifier
== 's')
1235 error("%s", _("%s in ruleless zone"));
1243 infile(const char *name
)
1248 const struct lookup
*lp
;
1254 if (strcmp(name
, "-") == 0)
1256 name
= _("standard input");
1259 else if ((fp
= fopen(name
, "r")) == NULL
)
1261 const char *e
= strerror(errno
);
1263 fprintf(stderr
, _("%s: Cannot open %s: %s\n"),
1268 for (num
= 1;; ++num
)
1271 if (fgets(buf
, sizeof buf
, fp
) != buf
)
1273 cp
= strchr(buf
, '\n');
1276 error(_("line too long"));
1280 fields
= getfields(buf
);
1282 while (fields
[nfields
] != NULL
)
1286 if (strcmp(fields
[nfields
], "-") == 0)
1287 fields
[nfields
] = &nada
;
1292 if (name
== leapsec
&& *buf
== '#')
1295 * PG: INT64_FORMAT isn't portable for sscanf, so be content
1296 * with scanning a "long". Once we are requiring C99 in all
1297 * live branches, it'd be sensible to adopt upstream's
1298 * practice of using the <inttypes.h> macros. But for now, we
1299 * don't actually use this code, and it won't overflow before
1304 sscanf(buf
, "#expires %ld", &cl_tmp
);
1305 comment_leapexpires
= cl_tmp
;
1310 wantcont
= inzcont(fields
, nfields
);
1314 struct lookup
const *line_codes
1315 = name
== leapsec
? leap_line_codes
: zi_line_codes
;
1317 lp
= byword(fields
[0], line_codes
);
1319 error(_("input line of unknown type"));
1321 switch (lp
->l_value
)
1324 inrule(fields
, nfields
);
1328 wantcont
= inzone(fields
, nfields
);
1331 inlink(fields
, nfields
);
1335 inleap(fields
, nfields
);
1339 inexpires(fields
, nfields
);
1342 default: /* "cannot happen" */
1344 _("%s: panic: Invalid l_value %d\n"),
1345 progname
, lp
->l_value
);
1351 close_file(fp
, NULL
, filename
);
1353 error(_("expected continuation line not found"));
1357 * Convert a string of one of the forms
1358 * h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
1359 * into a number of seconds.
1360 * A null string maps to zero.
1361 * Call error with errstring and return zero on errors.
1365 gethms(char const *string
, char const *errstring
)
1367 /* PG: make hh be int not zic_t to avoid sscanf portability issues */
1380 if (string
== NULL
|| *string
== '\0')
1389 switch (sscanf(string
,
1390 "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1391 &hh
, &hhx
, &mm
, &mmx
, &ss
, &ssx
, &tenths
, &xr
, &xs
))
1397 ok
= '0' <= xr
&& xr
<= '9';
1402 warning(_("fractional seconds rejected by"
1403 " pre-2018 versions of zic"));
1416 error("%s", errstring
);
1420 mm
< 0 || mm
>= MINSPERHOUR
||
1421 ss
< 0 || ss
> SECSPERMIN
)
1423 error("%s", errstring
);
1426 /* Some compilers warn that this test is unsatisfiable for 32-bit ints */
1427 #if INT_MAX > PG_INT32_MAX
1428 if (ZIC_MAX
/ SECSPERHOUR
< hh
)
1430 error(_("time overflow"));
1434 ss
+= 5 + ((ss
^ 1) & (xr
== '0')) <= tenths
; /* Round to even. */
1435 if (noise
&& (hh
> HOURSPERDAY
||
1436 (hh
== HOURSPERDAY
&& (mm
!= 0 || ss
!= 0))))
1437 warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1438 return oadd(sign
* (zic_t
) hh
* SECSPERHOUR
,
1439 sign
* (mm
* SECSPERMIN
+ ss
));
1443 getsave(char *field
, bool *isdst
)
1447 size_t fieldlen
= strlen(field
);
1451 char *ep
= field
+ fieldlen
- 1;
1465 save
= gethms(field
, _("invalid saved time"));
1466 *isdst
= dst
< 0 ? save
!= 0 : dst
;
1471 inrule(char **fields
, int nfields
)
1473 static struct rule r
;
1475 if (nfields
!= RULE_FIELDS
)
1477 error(_("wrong number of fields on Rule line"));
1480 switch (*fields
[RF_NAME
])
1501 error(_("Invalid rule name \"%s\""), fields
[RF_NAME
]);
1504 r
.r_filename
= filename
;
1505 r
.r_linenum
= linenum
;
1506 r
.r_save
= getsave(fields
[RF_SAVE
], &r
.r_isdst
);
1507 rulesub(&r
, fields
[RF_LOYEAR
], fields
[RF_HIYEAR
], fields
[RF_COMMAND
],
1508 fields
[RF_MONTH
], fields
[RF_DAY
], fields
[RF_TOD
]);
1509 r
.r_name
= ecpyalloc(fields
[RF_NAME
]);
1510 r
.r_abbrvar
= ecpyalloc(fields
[RF_ABBRVAR
]);
1511 if (max_abbrvar_len
< strlen(r
.r_abbrvar
))
1512 max_abbrvar_len
= strlen(r
.r_abbrvar
);
1513 rules
= growalloc(rules
, sizeof *rules
, nrules
, &nrules_alloc
);
1514 rules
[nrules
++] = r
;
1518 inzone(char **fields
, int nfields
)
1522 if (nfields
< ZONE_MINFIELDS
|| nfields
> ZONE_MAXFIELDS
)
1524 error(_("wrong number of fields on Zone line"));
1527 if (lcltime
!= NULL
&& strcmp(fields
[ZF_NAME
], tzdefault
) == 0)
1530 _("\"Zone %s\" line and -l option are mutually exclusive"),
1534 if (strcmp(fields
[ZF_NAME
], TZDEFRULES
) == 0 && psxrules
!= NULL
)
1537 _("\"Zone %s\" line and -p option are mutually exclusive"),
1541 for (i
= 0; i
< nzones
; ++i
)
1542 if (zones
[i
].z_name
!= NULL
&&
1543 strcmp(zones
[i
].z_name
, fields
[ZF_NAME
]) == 0)
1545 error(_("duplicate zone name %s"
1546 " (file \"%s\", line %d)"),
1548 zones
[i
].z_filename
,
1549 zones
[i
].z_linenum
);
1552 return inzsub(fields
, nfields
, false);
1556 inzcont(char **fields
, int nfields
)
1558 if (nfields
< ZONEC_MINFIELDS
|| nfields
> ZONEC_MAXFIELDS
)
1560 error(_("wrong number of fields on Zone continuation line"));
1563 return inzsub(fields
, nfields
, true);
1567 inzsub(char **fields
, int nfields
, bool iscont
)
1571 static struct zone z
;
1583 i_stdoff
= ZFC_STDOFF
;
1585 i_format
= ZFC_FORMAT
;
1586 i_untilyear
= ZFC_TILYEAR
;
1587 i_untilmonth
= ZFC_TILMONTH
;
1588 i_untilday
= ZFC_TILDAY
;
1589 i_untiltime
= ZFC_TILTIME
;
1592 else if (!namecheck(fields
[ZF_NAME
]))
1596 i_stdoff
= ZF_STDOFF
;
1598 i_format
= ZF_FORMAT
;
1599 i_untilyear
= ZF_TILYEAR
;
1600 i_untilmonth
= ZF_TILMONTH
;
1601 i_untilday
= ZF_TILDAY
;
1602 i_untiltime
= ZF_TILTIME
;
1603 z
.z_name
= ecpyalloc(fields
[ZF_NAME
]);
1605 z
.z_filename
= filename
;
1606 z
.z_linenum
= linenum
;
1607 z
.z_stdoff
= gethms(fields
[i_stdoff
], _("invalid UT offset"));
1608 if ((cp
= strchr(fields
[i_format
], '%')) != NULL
)
1610 if ((*++cp
!= 's' && *cp
!= 'z') || strchr(cp
, '%')
1611 || strchr(fields
[i_format
], '/'))
1613 error(_("invalid abbreviation format"));
1617 z
.z_rule
= ecpyalloc(fields
[i_rule
]);
1618 z
.z_format
= cp1
= ecpyalloc(fields
[i_format
]);
1619 z
.z_format_specifier
= cp
? *cp
: '\0';
1620 if (z
.z_format_specifier
== 'z')
1623 warning(_("format '%s' not handled by pre-2015 versions of zic"),
1625 cp1
[cp
- fields
[i_format
]] = 's';
1627 if (max_format_len
< strlen(z
.z_format
))
1628 max_format_len
= strlen(z
.z_format
);
1629 hasuntil
= nfields
> i_untilyear
;
1632 z
.z_untilrule
.r_filename
= filename
;
1633 z
.z_untilrule
.r_linenum
= linenum
;
1634 rulesub(&z
.z_untilrule
,
1635 fields
[i_untilyear
],
1638 (nfields
> i_untilmonth
) ?
1639 fields
[i_untilmonth
] : "Jan",
1640 (nfields
> i_untilday
) ? fields
[i_untilday
] : "1",
1641 (nfields
> i_untiltime
) ? fields
[i_untiltime
] : "0");
1642 z
.z_untiltime
= rpytime(&z
.z_untilrule
,
1643 z
.z_untilrule
.r_loyear
);
1644 if (iscont
&& nzones
> 0 &&
1645 z
.z_untiltime
> min_time
&&
1646 z
.z_untiltime
< max_time
&&
1647 zones
[nzones
- 1].z_untiltime
> min_time
&&
1648 zones
[nzones
- 1].z_untiltime
< max_time
&&
1649 zones
[nzones
- 1].z_untiltime
>= z
.z_untiltime
)
1651 error(_("Zone continuation line end time is not after end time of previous line"));
1655 zones
= growalloc(zones
, sizeof *zones
, nzones
, &nzones_alloc
);
1656 zones
[nzones
++] = z
;
1659 * If there was an UNTIL field on this line, there's more information
1660 * about the zone on the next line.
1666 getleapdatetime(char **fields
, int nfields
, bool expire_line
)
1669 const struct lookup
*lp
;
1673 /* PG: make year be int not zic_t to avoid sscanf portability issues */
1683 cp
= fields
[LP_YEAR
];
1684 if (sscanf(cp
, "%d%c", &year
, &xs
) != 1)
1689 error(_("invalid leaping year"));
1694 if (!leapseen
|| leapmaxyear
< year
)
1696 if (!leapseen
|| leapminyear
> year
)
1705 i
= len_years
[isleap(j
)];
1711 i
= -len_years
[isleap(j
)];
1713 dayoff
= oadd(dayoff
, i
);
1715 if ((lp
= byword(fields
[LP_MONTH
], mon_names
)) == NULL
)
1717 error(_("invalid month name"));
1720 month
= lp
->l_value
;
1724 i
= len_months
[isleap(year
)][j
];
1725 dayoff
= oadd(dayoff
, i
);
1728 cp
= fields
[LP_DAY
];
1729 if (sscanf(cp
, "%d%c", &day
, &xs
) != 1 ||
1730 day
<= 0 || day
> len_months
[isleap(year
)][month
])
1732 error(_("invalid day of month"));
1735 dayoff
= oadd(dayoff
, day
- 1);
1736 if (dayoff
< min_time
/ SECSPERDAY
)
1738 error(_("time too small"));
1741 if (dayoff
> max_time
/ SECSPERDAY
)
1743 error(_("time too large"));
1746 t
= dayoff
* SECSPERDAY
;
1747 tod
= gethms(fields
[LP_TIME
], _("invalid time of day"));
1750 error(_("leap second precedes Epoch"));
1755 inleap(char **fields
, int nfields
)
1757 if (nfields
!= LEAP_FIELDS
)
1758 error(_("wrong number of fields on Leap line"));
1761 zic_t t
= getleapdatetime(fields
, nfields
, false);
1765 struct lookup
const *lp
= byword(fields
[LP_ROLL
], leap_types
);
1768 error(_("invalid Rolling/Stationary field on Leap line"));
1773 if (!fields
[LP_CORR
][0]) /* infile() turns "-" into "". */
1775 else if (strcmp(fields
[LP_CORR
], "+") == 0)
1778 error(_("invalid CORRECTION field on Leap line"));
1780 leapadd(t
, correction
, lp
->l_value
);
1787 inexpires(char **fields
, int nfields
)
1789 if (nfields
!= EXPIRES_FIELDS
)
1790 error(_("wrong number of fields on Expires line"));
1791 else if (0 <= leapexpires
)
1792 error(_("multiple Expires lines"));
1794 leapexpires
= getleapdatetime(fields
, nfields
, true);
1798 inlink(char **fields
, int nfields
)
1802 if (nfields
!= LINK_FIELDS
)
1804 error(_("wrong number of fields on Link line"));
1807 if (*fields
[LF_TARGET
] == '\0')
1809 error(_("blank TARGET field on Link line"));
1812 if (!namecheck(fields
[LF_LINKNAME
]))
1814 l
.l_filename
= filename
;
1815 l
.l_linenum
= linenum
;
1816 l
.l_target
= ecpyalloc(fields
[LF_TARGET
]);
1817 l
.l_linkname
= ecpyalloc(fields
[LF_LINKNAME
]);
1818 links
= growalloc(links
, sizeof *links
, nlinks
, &nlinks_alloc
);
1819 links
[nlinks
++] = l
;
1823 rulesub(struct rule
*rp
, const char *loyearp
, const char *hiyearp
,
1824 const char *typep
, const char *monthp
, const char *dayp
,
1827 const struct lookup
*lp
;
1833 /* PG: year_tmp is to avoid sscanf portability issues */
1836 if ((lp
= byword(monthp
, mon_names
)) == NULL
)
1838 error(_("invalid month name"));
1841 rp
->r_month
= lp
->l_value
;
1842 rp
->r_todisstd
= false;
1843 rp
->r_todisut
= false;
1844 dp
= ecpyalloc(timep
);
1847 ep
= dp
+ strlen(dp
) - 1;
1848 switch (lowerit(*ep
))
1850 case 's': /* Standard */
1851 rp
->r_todisstd
= true;
1852 rp
->r_todisut
= false;
1855 case 'w': /* Wall */
1856 rp
->r_todisstd
= false;
1857 rp
->r_todisut
= false;
1860 case 'g': /* Greenwich */
1861 case 'u': /* Universal */
1862 case 'z': /* Zulu */
1863 rp
->r_todisstd
= true;
1864 rp
->r_todisut
= true;
1869 rp
->r_tod
= gethms(dp
, _("invalid time of day"));
1876 lp
= byword(cp
, begin_years
);
1877 rp
->r_lowasnum
= lp
== NULL
;
1878 if (!rp
->r_lowasnum
)
1879 switch (lp
->l_value
)
1882 rp
->r_loyear
= ZIC_MIN
;
1885 rp
->r_loyear
= ZIC_MAX
;
1887 default: /* "cannot happen" */
1889 _("%s: panic: Invalid l_value %d\n"),
1890 progname
, lp
->l_value
);
1893 else if (sscanf(cp
, "%d%c", &year_tmp
, &xs
) == 1)
1894 rp
->r_loyear
= year_tmp
;
1897 error(_("invalid starting year"));
1901 lp
= byword(cp
, end_years
);
1902 rp
->r_hiwasnum
= lp
== NULL
;
1903 if (!rp
->r_hiwasnum
)
1904 switch (lp
->l_value
)
1907 rp
->r_hiyear
= ZIC_MIN
;
1910 rp
->r_hiyear
= ZIC_MAX
;
1913 rp
->r_hiyear
= rp
->r_loyear
;
1915 default: /* "cannot happen" */
1917 _("%s: panic: Invalid l_value %d\n"),
1918 progname
, lp
->l_value
);
1921 else if (sscanf(cp
, "%d%c", &year_tmp
, &xs
) == 1)
1922 rp
->r_hiyear
= year_tmp
;
1925 error(_("invalid ending year"));
1928 if (rp
->r_loyear
> rp
->r_hiyear
)
1930 error(_("starting year greater than ending year"));
1935 error(_("year type \"%s\" is unsupported; use \"-\" instead"),
1941 * Day work. Accept things such as: 1 lastSunday last-Sunday
1942 * (undocumented; warn about this) Sun<=20 Sun>=7
1944 dp
= ecpyalloc(dayp
);
1945 if ((lp
= byword(dp
, lasts
)) != NULL
)
1947 rp
->r_dycode
= DC_DOWLEQ
;
1948 rp
->r_wday
= lp
->l_value
;
1949 rp
->r_dayofmonth
= len_months
[1][rp
->r_month
];
1953 if ((ep
= strchr(dp
, '<')) != NULL
)
1954 rp
->r_dycode
= DC_DOWLEQ
;
1955 else if ((ep
= strchr(dp
, '>')) != NULL
)
1956 rp
->r_dycode
= DC_DOWGEQ
;
1960 rp
->r_dycode
= DC_DOM
;
1962 if (rp
->r_dycode
!= DC_DOM
)
1967 error(_("invalid day of month"));
1971 if ((lp
= byword(dp
, wday_names
)) == NULL
)
1973 error(_("invalid weekday name"));
1977 rp
->r_wday
= lp
->l_value
;
1979 if (sscanf(ep
, "%d%c", &rp
->r_dayofmonth
, &xs
) != 1 ||
1980 rp
->r_dayofmonth
<= 0 ||
1981 (rp
->r_dayofmonth
> len_months
[1][rp
->r_month
]))
1983 error(_("invalid day of month"));
1992 convert(const int32 val
, char *const buf
)
1996 unsigned char *const b
= (unsigned char *) buf
;
1998 for (i
= 0, shift
= 24; i
< 4; ++i
, shift
-= 8)
1999 b
[i
] = val
>> shift
;
2003 convert64(const zic_t val
, char *const buf
)
2007 unsigned char *const b
= (unsigned char *) buf
;
2009 for (i
= 0, shift
= 56; i
< 8; ++i
, shift
-= 8)
2010 b
[i
] = val
>> shift
;
2014 puttzcode(const int32 val
, FILE *const fp
)
2019 fwrite(buf
, sizeof buf
, 1, fp
);
2023 puttzcodepass(zic_t val
, FILE *fp
, int pass
)
2031 convert64(val
, buf
);
2032 fwrite(buf
, sizeof buf
, 1, fp
);
2037 atcomp(const void *avp
, const void *bvp
)
2039 const zic_t a
= ((const struct attype
*) avp
)->at
;
2040 const zic_t b
= ((const struct attype
*) bvp
)->at
;
2042 return (a
< b
) ? -1 : (a
> b
);
2054 static struct timerange
2055 limitrange(struct timerange r
, zic_t lo
, zic_t hi
,
2056 zic_t
const *ats
, unsigned char const *types
)
2058 while (0 < r
.count
&& ats
[r
.base
] < lo
)
2060 r
.defaulttype
= types
[r
.base
];
2064 while (0 < r
.leapcount
&& trans
[r
.leapbase
] < lo
)
2072 while (0 < r
.count
&& hi
+ 1 < ats
[r
.base
+ r
.count
- 1])
2074 while (0 < r
.leapcount
&& hi
+ 1 < trans
[r
.leapbase
+ r
.leapcount
- 1])
2082 writezone(const char *const name
, const char *const string
, char version
,
2089 static const struct tzhead tzh0
;
2090 static struct tzhead tzh
;
2091 bool dir_checked
= false;
2093 zic_t y2038_boundary
= one
<< 31;
2094 ptrdiff_t nats
= timecnt
+ WORK_AROUND_QTBUG_53071
;
2097 * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
2100 zic_t
*ats
= emalloc(MAXALIGN(size_product(nats
, sizeof *ats
+ 1)));
2101 void *typesptr
= ats
+ nats
;
2102 unsigned char *types
= typesptr
;
2103 struct timerange rangeall
,
2111 qsort(attypes
, timecnt
, sizeof *attypes
, atcomp
);
2122 for (; fromi
< timecnt
; ++fromi
)
2125 && ((attypes
[fromi
].at
2126 + utoffs
[attypes
[toi
- 1].type
])
2127 <= (attypes
[toi
- 1].at
2128 + utoffs
[toi
== 1 ? 0
2129 : attypes
[toi
- 2].type
])))
2131 attypes
[toi
- 1].type
=
2132 attypes
[fromi
].type
;
2136 || attypes
[fromi
].dontmerge
2137 || (utoffs
[attypes
[toi
- 1].type
]
2138 != utoffs
[attypes
[fromi
].type
])
2139 || (isdsts
[attypes
[toi
- 1].type
]
2140 != isdsts
[attypes
[fromi
].type
])
2141 || (desigidx
[attypes
[toi
- 1].type
]
2142 != desigidx
[attypes
[fromi
].type
]))
2143 attypes
[toi
++] = attypes
[fromi
];
2148 if (noise
&& timecnt
> 1200)
2150 if (timecnt
> TZ_MAX_TIMES
)
2151 warning(_("reference clients mishandle"
2152 " more than %d transition times"),
2155 warning(_("pre-2014 clients may mishandle"
2156 " more than 1200 transition times"));
2162 for (i
= 0; i
< timecnt
; ++i
)
2164 ats
[i
] = attypes
[i
].at
;
2165 types
[i
] = attypes
[i
].type
;
2169 * Correct for leap seconds.
2171 for (i
= 0; i
< timecnt
; ++i
)
2175 if (ats
[i
] > trans
[j
] - corr
[j
])
2177 ats
[i
] = tadd(ats
[i
], corr
[j
]);
2183 * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2184 * inserting a no-op transition at time y2038_boundary - 1. This works
2185 * only for timestamps before the boundary, which should be good enough in
2186 * practice as QTBUG-53071 should be long-dead by 2038. Do this after
2187 * correcting for leap seconds, as the idea is to insert a transition just
2188 * before 32-bit pg_time_t rolls around, and this occurs at a slightly
2189 * different moment if transitions are leap-second corrected.
2191 if (WORK_AROUND_QTBUG_53071
&& timecnt
!= 0 && want_bloat()
2192 && ats
[timecnt
- 1] < y2038_boundary
- 1 && strchr(string
, '<'))
2194 ats
[timecnt
] = y2038_boundary
- 1;
2195 types
[timecnt
] = types
[timecnt
- 1];
2199 rangeall
.defaulttype
= defaulttype
;
2200 rangeall
.base
= rangeall
.leapbase
= 0;
2201 rangeall
.count
= timecnt
;
2202 rangeall
.leapcount
= leapcnt
;
2203 range64
= limitrange(rangeall
, lo_time
, hi_time
, ats
, types
);
2204 range32
= limitrange(range64
, PG_INT32_MIN
, PG_INT32_MAX
, ats
, types
);
2207 * Remove old file, if any, to snap links.
2209 if (remove(name
) == 0)
2211 else if (errno
!= ENOENT
)
2213 const char *e
= strerror(errno
);
2215 fprintf(stderr
, _("%s: Cannot remove %s/%s: %s\n"),
2216 progname
, directory
, name
, e
);
2219 fp
= fopen(name
, "wb");
2222 int fopen_errno
= errno
;
2224 if (fopen_errno
== ENOENT
&& !dir_checked
)
2227 fp
= fopen(name
, "wb");
2228 fopen_errno
= errno
;
2232 fprintf(stderr
, _("%s: Cannot create %s/%s: %s\n"),
2233 progname
, directory
, name
, strerror(fopen_errno
));
2237 for (pass
= 1; pass
<= 2; ++pass
)
2239 ptrdiff_t thistimei
,
2251 char omittype
[TZ_MAX_TYPES
];
2252 int typemap
[TZ_MAX_TYPES
];
2256 char thischars
[TZ_MAX_CHARS
];
2259 int indmap
[TZ_MAX_CHARS
];
2264 * Arguably the default time type in the 32-bit data should be
2265 * range32.defaulttype, which is suited for timestamps just before
2266 * PG_INT32_MIN. However, zic traditionally used the time type of
2267 * the indefinite past instead. Internet RFC 8532 says readers
2268 * should ignore 32-bit data, so this discrepancy matters only to
2269 * obsolete readers where the traditional type might be more
2270 * appropriate even if it's "wrong". So, use the historical zic
2271 * value, unless -r specifies a low cutoff that excludes some
2272 * 32-bit timestamps.
2274 thisdefaulttype
= (lo_time
<= PG_INT32_MIN
2275 ? range64
.defaulttype
2276 : range32
.defaulttype
);
2278 thistimei
= range32
.base
;
2279 thistimecnt
= range32
.count
;
2280 toomanytimes
= thistimecnt
>> 31 >> 1 != 0;
2281 thisleapi
= range32
.leapbase
;
2282 thisleapcnt
= range32
.leapcount
;
2283 locut
= PG_INT32_MIN
< lo_time
;
2284 hicut
= hi_time
< PG_INT32_MAX
;
2288 thisdefaulttype
= range64
.defaulttype
;
2289 thistimei
= range64
.base
;
2290 thistimecnt
= range64
.count
;
2291 toomanytimes
= thistimecnt
>> 31 >> 31 >> 2 != 0;
2292 thisleapi
= range64
.leapbase
;
2293 thisleapcnt
= range64
.leapcount
;
2294 locut
= min_time
< lo_time
;
2295 hicut
= hi_time
< max_time
;
2298 error(_("too many transition times"));
2301 * Keep the last too-low transition if no transition is exactly at LO.
2302 * The kept transition will be output as a LO "transition"; see
2303 * "Output a LO_TIME transition" below. This is needed when the
2304 * output is truncated at the start, and is also useful when catering
2305 * to buggy 32-bit clients that do not use time type 0 for timestamps
2306 * before the first transition.
2308 if (0 < thistimei
&& ats
[thistimei
] != lo_time
)
2315 thistimelim
= thistimei
+ thistimecnt
;
2316 thisleaplim
= thisleapi
+ thisleapcnt
;
2317 if (thistimecnt
!= 0)
2319 if (ats
[thistimei
] == lo_time
)
2321 if (hi_time
< ZIC_MAX
&& ats
[thistimelim
- 1] == hi_time
+ 1)
2324 memset(omittype
, true, typecnt
);
2325 omittype
[thisdefaulttype
] = false;
2326 for (i
= thistimei
; i
< thistimelim
; i
++)
2327 omittype
[types
[i
]] = false;
2330 * Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
2331 * OLD0 and THISDEFAULTTYPE so that THISDEFAULTTYPE appears as type 0
2332 * in the output instead of OLD0. TYPEMAP also omits unused types.
2334 old0
= strlen(omittype
);
2336 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2339 * For some pre-2011 systems: if the last-to-be-written standard (or
2340 * daylight) type has an offset different from the most recently used
2341 * offset, append an (unused) copy of the most recently used type (to
2342 * help get global "altzone" and "timezone" variables set correctly).
2352 hidst
= histd
= mrudst
= mrustd
= -1;
2353 for (i
= thistimei
; i
< thistimelim
; ++i
)
2354 if (isdsts
[types
[i
]])
2358 for (i
= old0
; i
< typecnt
; i
++)
2360 int h
= (i
== old0
? thisdefaulttype
2361 : i
== thisdefaulttype
? old0
: i
);
2371 if (hidst
>= 0 && mrudst
>= 0 && hidst
!= mrudst
&&
2372 utoffs
[hidst
] != utoffs
[mrudst
])
2374 isdsts
[mrudst
] = -1;
2375 type
= addtype(utoffs
[mrudst
],
2376 &chars
[desigidx
[mrudst
]],
2381 omittype
[type
] = false;
2383 if (histd
>= 0 && mrustd
>= 0 && histd
!= mrustd
&&
2384 utoffs
[histd
] != utoffs
[mrustd
])
2386 isdsts
[mrustd
] = -1;
2387 type
= addtype(utoffs
[mrustd
],
2388 &chars
[desigidx
[mrustd
]],
2393 omittype
[type
] = false;
2397 * LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
2399 for (i
= old0
; i
< typecnt
; i
++)
2401 typemap
[i
== old0
? thisdefaulttype
2402 : i
== thisdefaulttype
? old0
: i
]
2405 for (i
= 0; i
< sizeof indmap
/ sizeof indmap
[0]; ++i
)
2407 thischarcnt
= stdcnt
= utcnt
= 0;
2408 for (i
= old0
; i
< typecnt
; i
++)
2415 stdcnt
= thistypecnt
;
2417 utcnt
= thistypecnt
;
2418 if (indmap
[desigidx
[i
]] >= 0)
2420 thisabbr
= &chars
[desigidx
[i
]];
2421 for (j
= 0; j
< thischarcnt
; ++j
)
2422 if (strcmp(&thischars
[j
], thisabbr
) == 0)
2424 if (j
== thischarcnt
)
2426 strcpy(&thischars
[thischarcnt
], thisabbr
);
2427 thischarcnt
+= strlen(thisabbr
) + 1;
2429 indmap
[desigidx
[i
]] = j
;
2431 if (pass
== 1 && !want_bloat())
2433 utcnt
= stdcnt
= thisleapcnt
= 0;
2434 thistimecnt
= -(locut
+ hicut
);
2435 thistypecnt
= thischarcnt
= 1;
2436 thistimelim
= thistimei
;
2438 #define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
2440 memcpy(tzh
.tzh_magic
, TZ_MAGIC
, sizeof tzh
.tzh_magic
);
2441 tzh
.tzh_version
[0] = version
;
2442 convert(utcnt
, tzh
.tzh_ttisutcnt
);
2443 convert(stdcnt
, tzh
.tzh_ttisstdcnt
);
2444 convert(thisleapcnt
, tzh
.tzh_leapcnt
);
2445 convert(locut
+ thistimecnt
+ hicut
, tzh
.tzh_timecnt
);
2446 convert(thistypecnt
, tzh
.tzh_typecnt
);
2447 convert(thischarcnt
, tzh
.tzh_charcnt
);
2458 if (pass
== 1 && !want_bloat())
2460 /* Output a minimal data block with just one time type. */
2461 puttzcode(0, fp
); /* utoff */
2462 putc(0, fp
); /* dst */
2463 putc(0, fp
); /* index of abbreviation */
2464 putc(0, fp
); /* empty-string abbreviation */
2468 /* PG: print current timezone abbreviations if requested */
2469 if (print_abbrevs
&& pass
== 2)
2471 /* Print "type" data for periods ending after print_cutoff */
2472 for (i
= thistimei
; i
< thistimelim
; ++i
)
2474 if (i
== thistimelim
- 1 || ats
[i
+ 1] > print_cutoff
)
2476 unsigned char tm
= types
[i
];
2477 char *thisabbrev
= &thischars
[indmap
[desigidx
[tm
]]];
2479 fprintf(stdout
, "%s\t" INT64_FORMAT
"%s\n",
2482 isdsts
[tm
] ? "\tD" : "");
2485 /* Print the default type if we have no transitions at all */
2486 if (thistimei
>= thistimelim
)
2488 unsigned char tm
= defaulttype
;
2489 char *thisabbrev
= &thischars
[indmap
[desigidx
[tm
]]];
2491 fprintf(stdout
, "%s\t" INT64_FORMAT
"%s\n",
2494 isdsts
[tm
] ? "\tD" : "");
2499 * Output a LO_TIME transition if needed; see limitrange. But do not
2500 * go below the minimum representable value for this pass.
2502 lo
= pass
== 1 && lo_time
< PG_INT32_MIN
? PG_INT32_MIN
: lo_time
;
2505 puttzcodepass(lo
, fp
, pass
);
2506 for (i
= thistimei
; i
< thistimelim
; ++i
)
2508 zic_t at
= ats
[i
] < lo
? lo
: ats
[i
];
2510 puttzcodepass(at
, fp
, pass
);
2513 puttzcodepass(hi_time
+ 1, fp
, pass
);
2516 putc(currenttype
, fp
);
2517 for (i
= thistimei
; i
< thistimelim
; ++i
)
2519 currenttype
= typemap
[types
[i
]];
2520 putc(currenttype
, fp
);
2523 putc(currenttype
, fp
);
2525 for (i
= old0
; i
< typecnt
; i
++)
2527 int h
= (i
== old0
? thisdefaulttype
2528 : i
== thisdefaulttype
? old0
: i
);
2532 puttzcode(utoffs
[h
], fp
);
2533 putc(isdsts
[h
], fp
);
2534 putc(indmap
[desigidx
[h
]], fp
);
2537 if (thischarcnt
!= 0)
2538 fwrite(thischars
, sizeof thischars
[0],
2540 for (i
= thisleapi
; i
< thisleaplim
; ++i
)
2546 if (timecnt
== 0 || trans
[i
] < ats
[0])
2559 while (j
< timecnt
&&
2564 todo
= tadd(trans
[i
], -utoffs
[j
]);
2568 puttzcodepass(todo
, fp
, pass
);
2569 puttzcode(corr
[i
], fp
);
2572 for (i
= old0
; i
< typecnt
; i
++)
2574 putc(ttisstds
[i
], fp
);
2576 for (i
= old0
; i
< typecnt
; i
++)
2578 putc(ttisuts
[i
], fp
);
2580 fprintf(fp
, "\n%s\n", string
);
2581 close_file(fp
, directory
, name
);
2586 abbroffset(char *buf
, zic_t offset
)
2598 seconds
= offset
% SECSPERMIN
;
2599 offset
/= SECSPERMIN
;
2600 minutes
= offset
% MINSPERHOUR
;
2601 offset
/= MINSPERHOUR
;
2604 error(_("%%z UT offset magnitude exceeds 99:59:59"));
2612 *p
++ = '0' + offset
/ 10;
2613 *p
++ = '0' + offset
% 10;
2614 if (minutes
| seconds
)
2616 *p
++ = '0' + minutes
/ 10;
2617 *p
++ = '0' + minutes
% 10;
2620 *p
++ = '0' + seconds
/ 10;
2621 *p
++ = '0' + seconds
% 10;
2630 doabbr(char *abbr
, struct zone
const *zp
, char const *letters
,
2631 bool isdst
, zic_t save
, bool doquotes
)
2636 char const *format
= zp
->z_format
;
2638 slashp
= strchr(format
, '/');
2641 char letterbuf
[PERCENT_Z_LEN_BOUND
+ 1];
2643 if (zp
->z_format_specifier
== 'z')
2644 letters
= abbroffset(letterbuf
, zp
->z_stdoff
+ save
);
2647 sprintf(abbr
, format
, letters
);
2651 strcpy(abbr
, slashp
+ 1);
2655 memcpy(abbr
, format
, slashp
- format
);
2656 abbr
[slashp
- format
] = '\0';
2661 for (cp
= abbr
; is_alpha(*cp
); cp
++)
2663 if (len
> 0 && *cp
== '\0')
2665 abbr
[len
+ 2] = '\0';
2666 abbr
[len
+ 1] = '>';
2667 memmove(abbr
+ 1, abbr
, len
);
2673 updateminmax(const zic_t x
)
2682 stringoffset(char *result
, zic_t offset
)
2687 bool negative
= offset
< 0;
2695 seconds
= offset
% SECSPERMIN
;
2696 offset
/= SECSPERMIN
;
2697 minutes
= offset
% MINSPERHOUR
;
2698 offset
/= MINSPERHOUR
;
2700 if (hours
>= HOURSPERDAY
* DAYSPERWEEK
)
2705 len
+= sprintf(result
+ len
, "%d", hours
);
2706 if (minutes
!= 0 || seconds
!= 0)
2708 len
+= sprintf(result
+ len
, ":%02d", minutes
);
2710 len
+= sprintf(result
+ len
, ":%02d", seconds
);
2716 stringrule(char *result
, struct rule
*const rp
, zic_t save
, zic_t stdoff
)
2718 zic_t tod
= rp
->r_tod
;
2721 if (rp
->r_dycode
== DC_DOM
)
2726 if (rp
->r_dayofmonth
== 29 && rp
->r_month
== TM_FEBRUARY
)
2729 for (month
= 0; month
< rp
->r_month
; ++month
)
2730 total
+= len_months
[0][month
];
2731 /* Omit the "J" in Jan and Feb, as that's shorter. */
2732 if (rp
->r_month
<= 1)
2733 result
+= sprintf(result
, "%d", total
+ rp
->r_dayofmonth
- 1);
2735 result
+= sprintf(result
, "J%d", total
+ rp
->r_dayofmonth
);
2740 int wday
= rp
->r_wday
;
2743 if (rp
->r_dycode
== DC_DOWGEQ
)
2745 wdayoff
= (rp
->r_dayofmonth
- 1) % DAYSPERWEEK
;
2749 tod
+= wdayoff
* SECSPERDAY
;
2750 week
= 1 + (rp
->r_dayofmonth
- 1) / DAYSPERWEEK
;
2752 else if (rp
->r_dycode
== DC_DOWLEQ
)
2754 if (rp
->r_dayofmonth
== len_months
[1][rp
->r_month
])
2758 wdayoff
= rp
->r_dayofmonth
% DAYSPERWEEK
;
2762 tod
+= wdayoff
* SECSPERDAY
;
2763 week
= rp
->r_dayofmonth
/ DAYSPERWEEK
;
2767 return -1; /* "cannot happen" */
2769 wday
+= DAYSPERWEEK
;
2770 result
+= sprintf(result
, "M%d.%d.%d",
2771 rp
->r_month
+ 1, week
, wday
);
2775 if (rp
->r_todisstd
&& !rp
->r_isdst
)
2777 if (tod
!= 2 * SECSPERMIN
* MINSPERHOUR
)
2780 if (!stringoffset(result
, tod
))
2787 else if (SECSPERDAY
<= tod
)
2797 rule_cmp(struct rule
const *a
, struct rule
const *b
)
2803 if (a
->r_hiyear
!= b
->r_hiyear
)
2804 return a
->r_hiyear
< b
->r_hiyear
? -1 : 1;
2805 if (a
->r_month
- b
->r_month
!= 0)
2806 return a
->r_month
- b
->r_month
;
2807 return a
->r_dayofmonth
- b
->r_dayofmonth
;
2811 stringzone(char *result
, struct zone
const *zpfirst
, ptrdiff_t zonecount
)
2813 const struct zone
*zp
;
2818 const char *abbrvar
;
2829 * Internet RFC 8536 section 5.1 says to use an empty TZ string if future
2830 * timestamps are truncated.
2832 if (hi_time
< max_time
)
2835 zp
= zpfirst
+ zonecount
- 1;
2836 stdrp
= dstrp
= NULL
;
2837 for (i
= 0; i
< zp
->z_nrules
; ++i
)
2839 rp
= &zp
->z_rules
[i
];
2840 if (rp
->r_hiwasnum
|| rp
->r_hiyear
!= ZIC_MAX
)
2857 if (stdrp
== NULL
&& dstrp
== NULL
)
2860 * There are no rules running through "max". Find the latest std rule
2861 * in stdabbrrp and latest rule of any type in stdrp.
2863 struct rule
*stdabbrrp
= NULL
;
2865 for (i
= 0; i
< zp
->z_nrules
; ++i
)
2867 rp
= &zp
->z_rules
[i
];
2868 if (!rp
->r_isdst
&& rule_cmp(stdabbrrp
, rp
) < 0)
2870 if (rule_cmp(stdrp
, rp
) < 0)
2873 if (stdrp
!= NULL
&& stdrp
->r_isdst
)
2875 /* Perpetual DST. */
2876 dstr
.r_month
= TM_JANUARY
;
2877 dstr
.r_dycode
= DC_DOM
;
2878 dstr
.r_dayofmonth
= 1;
2880 dstr
.r_todisstd
= dstr
.r_todisut
= false;
2881 dstr
.r_isdst
= stdrp
->r_isdst
;
2882 dstr
.r_save
= stdrp
->r_save
;
2883 dstr
.r_abbrvar
= stdrp
->r_abbrvar
;
2884 stdr
.r_month
= TM_DECEMBER
;
2885 stdr
.r_dycode
= DC_DOM
;
2886 stdr
.r_dayofmonth
= 31;
2887 stdr
.r_tod
= SECSPERDAY
+ stdrp
->r_save
;
2888 stdr
.r_todisstd
= stdr
.r_todisut
= false;
2889 stdr
.r_isdst
= false;
2892 = (stdabbrrp
? stdabbrrp
->r_abbrvar
: "");
2897 if (stdrp
== NULL
&& (zp
->z_nrules
!= 0 || zp
->z_isdst
))
2899 abbrvar
= (stdrp
== NULL
) ? "" : stdrp
->r_abbrvar
;
2900 len
= doabbr(result
, zp
, abbrvar
, false, 0, true);
2901 offsetlen
= stringoffset(result
+ len
, -zp
->z_stdoff
);
2910 len
+= doabbr(result
+ len
, zp
, dstrp
->r_abbrvar
,
2911 dstrp
->r_isdst
, dstrp
->r_save
, true);
2912 if (dstrp
->r_save
!= SECSPERMIN
* MINSPERHOUR
)
2914 offsetlen
= stringoffset(result
+ len
,
2915 -(zp
->z_stdoff
+ dstrp
->r_save
));
2923 result
[len
++] = ',';
2924 c
= stringrule(result
+ len
, dstrp
, dstrp
->r_save
, zp
->z_stdoff
);
2932 len
+= strlen(result
+ len
);
2933 result
[len
++] = ',';
2934 c
= stringrule(result
+ len
, stdrp
, dstrp
->r_save
, zp
->z_stdoff
);
2946 outzone(const struct zone
*zpfirst
, ptrdiff_t zonecount
)
2948 const struct zone
*zp
;
2968 bool prodstic
; /* all rules are min to max */
2972 ptrdiff_t lastatmax
= -1;
2974 zic_t y2038_boundary
= one
<< 31;
2976 int defaulttype
= -1;
2978 max_abbr_len
= 2 + max_format_len
+ max_abbrvar_len
;
2979 max_envvar_len
= 2 * max_abbr_len
+ 5 * 9;
2980 startbuf
= emalloc(max_abbr_len
+ 1);
2981 ab
= emalloc(max_abbr_len
+ 1);
2982 envvar
= emalloc(max_envvar_len
+ 1);
2983 INITIALIZE(untiltime
);
2984 INITIALIZE(starttime
);
2987 * Now. . .finally. . .generate some useful data!
2992 prodstic
= zonecount
== 1;
2995 * Thanks to Earl Chew for noting the need to unconditionally initialize
2998 startttisstd
= false;
2999 startttisut
= false;
3000 min_year
= max_year
= EPOCH_YEAR
;
3003 updateminmax(leapminyear
);
3004 updateminmax(leapmaxyear
+ (leapmaxyear
< ZIC_MAX
));
3006 for (i
= 0; i
< zonecount
; ++i
)
3009 if (i
< zonecount
- 1)
3010 updateminmax(zp
->z_untilrule
.r_loyear
);
3011 for (j
= 0; j
< zp
->z_nrules
; ++j
)
3013 rp
= &zp
->z_rules
[j
];
3015 updateminmax(rp
->r_loyear
);
3017 updateminmax(rp
->r_hiyear
);
3018 if (rp
->r_lowasnum
|| rp
->r_hiwasnum
)
3024 * Generate lots of data if a rule can't cover all future times.
3026 compat
= stringzone(envvar
, zpfirst
, zonecount
);
3027 version
= compat
< 2013 ? ZIC_VERSION_PRE_2013
: ZIC_VERSION
;
3028 do_extend
= compat
< 0;
3033 _("no POSIX environment variable for zone"),
3035 else if (compat
!= 0)
3038 * Circa-COMPAT clients, and earlier clients, might not work for
3039 * this zone when given dates before 1970 or after 2038.
3041 warning(_("%s: pre-%d clients may mishandle"
3042 " distant timestamps"),
3043 zpfirst
->z_name
, compat
);
3049 * Search through a couple of extra years past the obvious 400, to
3050 * avoid edge cases. For example, suppose a non-POSIX rule applies
3051 * from 2012 onwards and has transitions in March and September, plus
3052 * some one-off transitions in November 2013. If zic looked only at
3053 * the last 400 years, it would set max_year=2413, with the intent
3054 * that the 400 years 2014 through 2413 will be repeated. The last
3055 * transition listed in the tzfile would be in 2413-09, less than 400
3056 * years after the last one-off transition in 2013-11. Two years
3057 * might be overkill, but with the kind of edge cases available we're
3058 * not sure that one year would suffice.
3062 years_of_observations
= YEARSPERREPEAT
+ 2};
3064 if (min_year
>= ZIC_MIN
+ years_of_observations
)
3065 min_year
-= years_of_observations
;
3068 if (max_year
<= ZIC_MAX
- years_of_observations
)
3069 max_year
+= years_of_observations
;
3074 * Regardless of any of the above, for a "proDSTic" zone which
3075 * specifies that its rules always have and always will be in effect,
3076 * we only need one cycle to define the zone.
3081 max_year
= min_year
+ years_of_observations
;
3084 max_year0
= max_year
;
3088 * For the benefit of older systems, generate data from 1900 through
3091 if (min_year
> 1900)
3093 if (max_year
< 2038)
3097 for (i
= 0; i
< zonecount
; ++i
)
3099 struct rule
*prevrp
= NULL
;
3102 * A guess that may well be corrected later.
3106 usestart
= i
> 0 && (zp
- 1)->z_untiltime
> min_time
;
3107 useuntil
= i
< (zonecount
- 1);
3108 if (useuntil
&& zp
->z_untiltime
<= min_time
)
3110 stdoff
= zp
->z_stdoff
;
3111 eat(zp
->z_filename
, zp
->z_linenum
);
3113 startoff
= zp
->z_stdoff
;
3114 if (zp
->z_nrules
== 0)
3117 doabbr(startbuf
, zp
, NULL
, zp
->z_isdst
, save
, false);
3118 type
= addtype(oadd(zp
->z_stdoff
, save
),
3119 startbuf
, zp
->z_isdst
, startttisstd
,
3123 addtt(starttime
, type
);
3130 for (year
= min_year
; year
<= max_year
; ++year
)
3132 if (useuntil
&& year
> zp
->z_untilrule
.r_hiyear
)
3136 * Mark which rules to do in the current year. For those to
3137 * do, calculate rpytime(rp, year); The former TYPE field was
3138 * also considered here.
3140 for (j
= 0; j
< zp
->z_nrules
; ++j
)
3142 rp
= &zp
->z_rules
[j
];
3143 eats(zp
->z_filename
, zp
->z_linenum
,
3144 rp
->r_filename
, rp
->r_linenum
);
3145 rp
->r_todo
= year
>= rp
->r_loyear
&&
3146 year
<= rp
->r_hiyear
;
3149 rp
->r_temp
= rpytime(rp
, year
);
3151 = (rp
->r_temp
< y2038_boundary
3152 || year
<= max_year0
);
3166 * Turn untiltime into UT assuming the current stdoff
3169 untiltime
= zp
->z_untiltime
;
3170 if (!zp
->z_untilrule
.r_todisut
)
3171 untiltime
= tadd(untiltime
,
3173 if (!zp
->z_untilrule
.r_todisstd
)
3174 untiltime
= tadd(untiltime
,
3179 * Find the rule (of those to do, if any) that takes
3180 * effect earliest in the year.
3183 for (j
= 0; j
< zp
->z_nrules
; ++j
)
3185 rp
= &zp
->z_rules
[j
];
3188 eats(zp
->z_filename
, zp
->z_linenum
,
3189 rp
->r_filename
, rp
->r_linenum
);
3190 offset
= rp
->r_todisut
? 0 : stdoff
;
3191 if (!rp
->r_todisstd
)
3192 offset
= oadd(offset
, save
);
3194 if (jtime
== min_time
||
3197 jtime
= tadd(jtime
, -offset
);
3198 if (k
< 0 || jtime
< ktime
)
3203 else if (jtime
== ktime
)
3205 char const *dup_rules_msg
=
3206 _("two rules for same instant");
3208 eats(zp
->z_filename
, zp
->z_linenum
,
3209 rp
->r_filename
, rp
->r_linenum
);
3210 warning("%s", dup_rules_msg
);
3211 rp
= &zp
->z_rules
[k
];
3212 eats(zp
->z_filename
, zp
->z_linenum
,
3213 rp
->r_filename
, rp
->r_linenum
);
3214 error("%s", dup_rules_msg
);
3218 break; /* go on to next year */
3219 rp
= &zp
->z_rules
[k
];
3221 if (useuntil
&& ktime
>= untiltime
)
3224 if (usestart
&& ktime
== starttime
)
3228 if (ktime
< starttime
)
3230 startoff
= oadd(zp
->z_stdoff
,
3232 doabbr(startbuf
, zp
,
3239 if (*startbuf
== '\0'
3240 && startoff
== oadd(zp
->z_stdoff
,
3251 eats(zp
->z_filename
, zp
->z_linenum
,
3252 rp
->r_filename
, rp
->r_linenum
);
3253 doabbr(ab
, zp
, rp
->r_abbrvar
,
3254 rp
->r_isdst
, rp
->r_save
, false);
3255 offset
= oadd(zp
->z_stdoff
, rp
->r_save
);
3256 if (!want_bloat() && !useuntil
&& !do_extend
3258 && rp
->r_hiyear
== ZIC_MAX
3259 && prevrp
->r_hiyear
== ZIC_MAX
)
3261 type
= addtype(offset
, ab
, rp
->r_isdst
,
3262 rp
->r_todisstd
, rp
->r_todisut
);
3263 if (defaulttype
< 0 && !rp
->r_isdst
)
3265 if (rp
->r_hiyear
== ZIC_MAX
3267 && ktime
< attypes
[lastatmax
].at
))
3268 lastatmax
= timecnt
;
3275 if (*startbuf
== '\0' &&
3276 zp
->z_format
!= NULL
&&
3277 strchr(zp
->z_format
, '%') == NULL
&&
3278 strchr(zp
->z_format
, '/') == NULL
)
3279 strcpy(startbuf
, zp
->z_format
);
3280 eat(zp
->z_filename
, zp
->z_linenum
);
3281 if (*startbuf
== '\0')
3282 error(_("cannot determine time zone abbreviation to use just after until time"));
3285 bool isdst
= startoff
!= zp
->z_stdoff
;
3287 type
= addtype(startoff
, startbuf
, isdst
,
3288 startttisstd
, startttisut
);
3289 if (defaulttype
< 0 && !isdst
)
3291 addtt(starttime
, type
);
3296 * Now we may get to set starttime for the next zone line.
3300 startttisstd
= zp
->z_untilrule
.r_todisstd
;
3301 startttisut
= zp
->z_untilrule
.r_todisut
;
3302 starttime
= zp
->z_untiltime
;
3304 starttime
= tadd(starttime
, -save
);
3306 starttime
= tadd(starttime
, -stdoff
);
3309 if (defaulttype
< 0)
3312 attypes
[lastatmax
].dontmerge
= true;
3316 * If we're extending the explicitly listed observations for 400 years
3317 * because we can't fill the POSIX-TZ field, check whether we actually
3318 * ended up explicitly listing observations through that period. If
3319 * there aren't any near the end of the 400-year period, add a
3320 * redundant one at the end of the final year, to make it clear that
3321 * we are claiming to have definite knowledge of the lack of
3322 * transitions up to that point.
3325 struct attype
*lastat
;
3327 xr
.r_month
= TM_JANUARY
;
3328 xr
.r_dycode
= DC_DOM
;
3329 xr
.r_dayofmonth
= 1;
3331 for (lastat
= attypes
, i
= 1; i
< timecnt
; i
++)
3332 if (attypes
[i
].at
> lastat
->at
)
3333 lastat
= &attypes
[i
];
3334 if (!lastat
|| lastat
->at
< rpytime(&xr
, max_year
- 1))
3336 addtt(rpytime(&xr
, max_year
+ 1),
3337 lastat
? lastat
->type
: defaulttype
);
3338 attypes
[timecnt
- 1].dontmerge
= true;
3341 writezone(zpfirst
->z_name
, envvar
, version
, defaulttype
);
3348 addtt(zic_t starttime
, int type
)
3350 attypes
= growalloc(attypes
, sizeof *attypes
, timecnt
, &timecnt_alloc
);
3351 attypes
[timecnt
].at
= starttime
;
3352 attypes
[timecnt
].dontmerge
= false;
3353 attypes
[timecnt
].type
= type
;
3358 addtype(zic_t utoff
, char const *abbr
, bool isdst
, bool ttisstd
, bool ttisut
)
3363 if (!(-1L - 2147483647L <= utoff
&& utoff
<= 2147483647L))
3365 error(_("UT offset out of range"));
3369 ttisstd
= ttisut
= false;
3371 for (j
= 0; j
< charcnt
; ++j
)
3372 if (strcmp(&chars
[j
], abbr
) == 0)
3378 /* If there's already an entry, return its index. */
3379 for (i
= 0; i
< typecnt
; i
++)
3380 if (utoff
== utoffs
[i
] && isdst
== isdsts
[i
] && j
== desigidx
[i
]
3381 && ttisstd
== ttisstds
[i
] && ttisut
== ttisuts
[i
])
3386 * There isn't one; add a new one, unless there are already too many.
3388 if (typecnt
>= TZ_MAX_TYPES
)
3390 error(_("too many local time types"));
3396 ttisstds
[i
] = ttisstd
;
3397 ttisuts
[i
] = ttisut
;
3403 leapadd(zic_t t
, int correction
, int rolling
)
3407 if (TZ_MAX_LEAPS
<= leapcnt
)
3409 error(_("too many leap seconds"));
3412 for (i
= 0; i
< leapcnt
; ++i
)
3415 memmove(&trans
[i
+ 1], &trans
[i
], (leapcnt
- i
) * sizeof *trans
);
3416 memmove(&corr
[i
+ 1], &corr
[i
], (leapcnt
- i
) * sizeof *corr
);
3417 memmove(&roll
[i
+ 1], &roll
[i
], (leapcnt
- i
) * sizeof *roll
);
3419 corr
[i
] = correction
;
3429 zic_t prevtrans
= 0;
3432 * propagate leap seconds forward
3434 for (i
= 0; i
< leapcnt
; ++i
)
3436 if (trans
[i
] - prevtrans
< 28 * SECSPERDAY
)
3438 error(_("Leap seconds too close together"));
3441 prevtrans
= trans
[i
];
3442 trans
[i
] = tadd(trans
[i
], last
);
3443 last
= corr
[i
] += last
;
3446 if (leapexpires
< 0)
3448 leapexpires
= comment_leapexpires
;
3449 if (0 <= leapexpires
)
3450 warning(_("\"#expires\" is obsolescent; use \"Expires\""));
3453 if (0 <= leapexpires
)
3455 leapexpires
= oadd(leapexpires
, last
);
3456 if (!(leapcnt
== 0 || (trans
[leapcnt
- 1] < leapexpires
)))
3458 error(_("last Leap time does not precede Expires time"));
3461 if (leapexpires
<= hi_time
)
3462 hi_time
= leapexpires
- 1;
3466 /* Is A a space character in the C locale? */
3484 /* Is A an alphabetic character in the C locale? */
3548 /* If A is an uppercase character in the C locale, return its lowercase
3549 counterpart. Otherwise, return A. */
3612 /* case-insensitive equality */
3614 ciequal(const char *ap
, const char *bp
)
3616 while (lowerit(*ap
) == lowerit(*bp
++))
3623 itsabbr(const char *abbr
, const char *word
)
3625 if (lowerit(*abbr
) != lowerit(*word
))
3628 while (*++abbr
!= '\0')
3633 } while (lowerit(*word
++) != lowerit(*abbr
));
3637 /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
3640 ciprefix(char const *abbr
, char const *word
)
3645 while (lowerit(*abbr
++) == lowerit(*word
++));
3650 static const struct lookup
*
3651 byword(const char *word
, const struct lookup
*table
)
3653 const struct lookup
*foundlp
;
3654 const struct lookup
*lp
;
3656 if (word
== NULL
|| table
== NULL
)
3660 * If TABLE is LASTS and the word starts with "last" followed by a
3661 * non-'-', skip the "last" and look in WDAY_NAMES instead. Warn about any
3662 * usage of the undocumented prefix "last-".
3664 if (table
== lasts
&& ciprefix("last", word
) && word
[4])
3667 warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
3677 * Look for exact match.
3679 for (lp
= table
; lp
->l_word
!= NULL
; ++lp
)
3680 if (ciequal(word
, lp
->l_word
))
3684 * Look for inexact match.
3687 for (lp
= table
; lp
->l_word
!= NULL
; ++lp
)
3688 if (ciprefix(word
, lp
->l_word
))
3690 if (foundlp
== NULL
)
3693 return NULL
; /* multiple inexact matches */
3696 if (foundlp
&& noise
)
3698 /* Warn about any backward-compatibility issue with pre-2017c zic. */
3699 bool pre_2017c_match
= false;
3701 for (lp
= table
; lp
->l_word
; lp
++)
3702 if (itsabbr(word
, lp
->l_word
))
3704 if (pre_2017c_match
)
3706 warning(_("\"%s\" is ambiguous in pre-2017c zic"), word
);
3709 pre_2017c_match
= true;
3725 array
= emalloc(size_product(strlen(cp
) + 1, sizeof *array
));
3729 while (is_space(*cp
))
3731 if (*cp
== '\0' || *cp
== '#')
3733 array
[nsubs
++] = dp
= cp
;
3736 if ((*dp
= *cp
++) != '"')
3739 while ((*dp
= *cp
++) != '"')
3744 error(_("Odd number of quotation marks"));
3747 } while (*cp
&& *cp
!= '#' && !is_space(*cp
));
3752 array
[nsubs
] = NULL
;
3759 error(_("time overflow"));
3764 oadd(zic_t t1
, zic_t t2
)
3766 if (t1
< 0 ? t2
< ZIC_MIN
- t1
: ZIC_MAX
- t1
< t2
)
3772 tadd(zic_t t1
, zic_t t2
)
3776 if (t2
< min_time
- t1
)
3785 if (max_time
- t1
< t2
)
3796 * Given a rule, and a year, compute the date (in seconds since January 1,
3797 * 1970, 00:00 LOCAL time) in that year that the rule refers to.
3801 rpytime(const struct rule
*rp
, zic_t wantedy
)
3805 zic_t dayoff
; /* with a nod to Margaret O. */
3809 if (wantedy
== ZIC_MIN
)
3811 if (wantedy
== ZIC_MAX
)
3819 dayoff
= (wantedy
/ YEARSPERREPEAT
) * (SECSPERREPEAT
/ SECSPERDAY
);
3820 wantedy
%= YEARSPERREPEAT
;
3823 else if (wantedy
< 0)
3825 dayoff
= (wantedy
/ YEARSPERREPEAT
) * (SECSPERREPEAT
/ SECSPERDAY
);
3826 wantedy
%= YEARSPERREPEAT
;
3828 while (wantedy
!= y
)
3832 i
= len_years
[isleap(y
)];
3838 i
= -len_years
[isleap(y
)];
3840 dayoff
= oadd(dayoff
, i
);
3842 while (m
!= rp
->r_month
)
3844 i
= len_months
[isleap(y
)][m
];
3845 dayoff
= oadd(dayoff
, i
);
3848 i
= rp
->r_dayofmonth
;
3849 if (m
== TM_FEBRUARY
&& i
== 29 && !isleap(y
))
3851 if (rp
->r_dycode
== DC_DOWLEQ
)
3855 error(_("use of 2/29 in non leap-year"));
3860 dayoff
= oadd(dayoff
, i
);
3861 if (rp
->r_dycode
== DC_DOWGEQ
|| rp
->r_dycode
== DC_DOWLEQ
)
3865 #define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3869 * Don't trust mod of negative numbers.
3872 wday
= (wday
+ dayoff
) % LDAYSPERWEEK
;
3875 wday
-= ((-dayoff
) % LDAYSPERWEEK
);
3877 wday
+= LDAYSPERWEEK
;
3879 while (wday
!= rp
->r_wday
)
3880 if (rp
->r_dycode
== DC_DOWGEQ
)
3882 dayoff
= oadd(dayoff
, 1);
3883 if (++wday
>= LDAYSPERWEEK
)
3889 dayoff
= oadd(dayoff
, -1);
3891 wday
= LDAYSPERWEEK
- 1;
3894 if (i
< 0 || i
>= len_months
[isleap(y
)][m
])
3897 warning(_("rule goes past start/end of month; \
3898 will not work with pre-2004 versions of zic"));
3901 if (dayoff
< min_time
/ SECSPERDAY
)
3903 if (dayoff
> max_time
/ SECSPERDAY
)
3905 t
= (zic_t
) dayoff
* SECSPERDAY
;
3906 return tadd(t
, rp
->r_tod
);
3910 newabbr(const char *string
)
3914 if (strcmp(string
, GRANDPARENTED
) != 0)
3921 while (is_alpha(*cp
) || ('0' <= *cp
&& *cp
<= '9')
3922 || *cp
== '-' || *cp
== '+')
3924 if (noise
&& cp
- string
< 3)
3925 mp
= _("time zone abbreviation has fewer than 3 characters");
3926 if (cp
- string
> ZIC_MAX_ABBR_LEN_WO_WARN
)
3927 mp
= _("time zone abbreviation has too many characters");
3929 mp
= _("time zone abbreviation differs from POSIX standard");
3931 warning("%s (%s)", mp
, string
);
3933 i
= strlen(string
) + 1;
3934 if (charcnt
+ i
> TZ_MAX_CHARS
)
3936 error(_("too many, or too long, time zone abbreviations"));
3939 strcpy(&chars
[charcnt
], string
);
3943 /* Ensure that the directories of ARGNAME exist, by making any missing
3944 ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
3945 do it for ARGNAME too. Exit with failure if there is trouble.
3946 Do not consider an existing non-directory to be trouble. */
3948 mkdirs(char const *argname
, bool ancestors
)
3953 cp
= name
= ecpyalloc(argname
);
3956 * On MS-Windows systems, do not worry about drive letters or backslashes,
3957 * as this should suffice in practice. Time zone names do not use drive
3958 * letters and backslashes. If the -d option of zic does not name an
3959 * already-existing directory, it can use slashes to separate the
3960 * already-existing ancestor prefix from the to-be-created subdirectories.
3963 /* Do not mkdir a root directory, as it must exist. */
3967 while (cp
&& ((cp
= strchr(cp
, '/')) || !ancestors
))
3973 * Try to create it. It's OK if creation fails because the directory
3974 * already exists, perhaps because some other process just created it.
3975 * For simplicity do not check first whether it already exists, as
3976 * that is checked anyway if the mkdir fails.
3978 if (mkdir(name
, MKDIR_UMASK
) != 0)
3981 * For speed, skip itsdir if errno == EEXIST. Since mkdirs is
3982 * called only after open fails with ENOENT on a subfile, EEXIST
3983 * implies itsdir here.
3987 if (err
!= EEXIST
&& !itsdir(name
))
3989 error(_("%s: Cannot create directory %s: %s"),
3990 progname
, name
, strerror(err
));
4006 link(const char *oldpath
, const char *newpath
)
4008 if (!CopyFile(oldpath
, newpath
, false))
4010 _dosmaperr(GetLastError());