22#define ZIC_VERSION_PRE_2013 '2'
23#define ZIC_VERSION '3'
26#define ZIC_MIN INT_FAST64_MIN
27#define ZIC_MAX INT_FAST64_MAX
28#define PRIdZIC PRIdFAST64
29#define SCNdZIC SCNdFAST64
31#ifndef ZIC_MAX_ABBR_LEN_WO_WARN
32#define ZIC_MAX_ABBR_LEN_WO_WARN 6
37#define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
39#define MKDIR_UMASK 0755
43#if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT
44#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
53#if __STDC_VERSION__ < 201112
54#define _Alignof(type) offsetof(struct { char a; type b; }, b)
119extern int link(
const char *target,
const char *linkname);
120#ifndef AT_SYMLINK_FOLLOW
121#define linkat(targetdir, target, linknamedir, linkname, flag) \
122 (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
130 bool isdst,
bool ttisstd,
bool ttisut);
131static
void leapadd(
zic_t t,
int correction,
int rolling);
134static
void dolink(const
char *target, const
char *linkname,
137static
zic_t gethms(const
char *
string, const
char *errstring);
139static
void inexpires(
char **fields,
int nfields);
141static
void inleap(
char **fields,
int nfields);
142static
void inlink(
char **fields,
int nfields);
143static
void inrule(
char **fields,
int nfields);
144static
bool inzcont(
char **fields,
int nfields);
145static
bool inzone(
char **fields,
int nfields);
146static
bool inzsub(
char **fields,
int nfields,
bool iscont);
151static
void mkdirs(
char const *argname,
bool ancestors);
152static
void newabbr(const
char *
string);
154static
void outzone(const struct
zone *zpfirst, ptrdiff_t zonecount);
157 const
char *loyearp, const
char *hiyearp,
158 const
char *typep, const
char *monthp,
159 const
char *dayp, const
char *timep);
172#ifndef WORK_AROUND_QTBUG_53071
223#define ZONE_MINFIELDS 5
224#define ZONE_MAXFIELDS 9
234#define ZFC_TILMONTH 4
237#define ZONEC_MINFIELDS 3
238#define ZONEC_MAXFIELDS 7
253#define RULE_FIELDS 10
276#define EXPIRES_FIELDS 5
380 {
"Stationary",
false},
385 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
386 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
423 if (SIZE_MAX / itemsize <
nitems)
431 size_t aligned_size = size + alignment - 1;
433 aligned_size -= aligned_size % alignment;
434 if (aligned_size < size)
468 if (
nitems < *nitems_alloc)
473 ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
475 if ((amax - 1) / 3 * 2 < *nitems_alloc)
477 *nitems_alloc += (*nitems_alloc >> 1) + 1;
512 fprintf(stderr,
_(
" (rule from \"%s\", line %" PRIdMAX
")"),
522 va_start(
args,
string);
534 va_start(
args,
string);
543 char const *
e = (ferror(stream) ?
_(
"I/O error")
544 : fclose(stream) != 0 ?
strerror(errno) : NULL);
549 dir ? dir :
"", dir ?
"/" :
"",
560 _(
"%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
561 "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
562 " [ -L leapseconds ] \\\n"
563 "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
564 "\t[ filename ... ]\n\n"
565 "Report bugs to %s.\n"),
580 int chdir_errno = errno;
582 if (chdir_errno == ENOENT)
585 chdir_errno = chdir(dir) == 0 ? 0 : errno;
587 if (chdir_errno != 0)
589 fprintf(stderr,
_(
"%s: Can't chdir to %s: %s\n"),
596#define TIME_T_BITS_IN_FILE 64
626 lo = strtoimax(
timerange + 1, &lo_end, 10);
627 if (lo_end ==
timerange + 1 || (lo == INTMAX_MAX && errno == ERANGE))
631 if (lo_end[0] ==
'/' && lo_end[1] ==
'@')
634 hi = strtoimax(lo_end + 2, &hi_end, 10);
635 if (hi_end == lo_end + 2 || hi == INTMAX_MIN)
637 hi -= !(hi == INTMAX_MAX && errno == ERANGE);
663#ifndef ZIC_BLOAT_DEFAULT
664#define ZIC_BLOAT_DEFAULT "slim"
674 bool timerange_given =
false;
683 _(
"wild compilation-time specification of zic_t"));
686 for (k = 1; k < argc; k++)
687 if (strcmp(argv[k],
"--version") == 0)
689 printf(
"zic %s\n", PG_VERSION);
693 else if (strcmp(argv[k],
"--help") == 0)
697 while ((
c =
getopt(argc, argv,
"b:d:l:L:p:Pr:st:vy:")) != EOF &&
c != -1)
703 if (strcmp(
optarg,
"slim") == 0)
706 error(
_(
"incompatible -b options"));
709 else if (strcmp(
optarg,
"fat") == 0)
712 error(
_(
"incompatible -b options"));
724 _(
"%s: More than one -d option specified\n"),
735 _(
"%s: More than one -l option specified\n"),
746 _(
"%s: More than one -p option specified\n"),
755 _(
"%s: More than one -t option"
771 _(
"%s: More than one -L option specified\n"),
787 _(
"%s: More than one -r option specified\n"),
794 _(
"%s: invalid time range: %s\n"),
798 timerange_given =
true;
804 if (
optind == argc - 1 && strcmp(argv[
optind],
"=") == 0)
810 if (strcmp(bloat_default,
"slim") == 0)
812 else if (strcmp(bloat_default,
"fat") == 0)
828 for (k =
optind; k < argc; k++)
853 if (strcmp(
links[
i].l_linkname,
859 eat(
_(
"command line"), 1);
864 eat(
_(
"command line"), 1);
867 if (
warnings && (ferror(stderr) || fclose(stderr) != 0))
874 char const *component_end)
878 component_len_max = 14};
879 ptrdiff_t component_len = component_end - component;
881 if (component_len == 0)
884 error(
_(
"empty file name"));
887 ?
"file name '%s' begins with '/'"
889 ?
"file name '%s' contains '//'"
890 :
"file name '%s' ends with '/'"),
894 if (0 < component_len && component_len <= 2
895 && component[0] ==
'.' && component_end[-1] ==
'.')
897 int len = component_len;
899 error(
_(
"file name '%s' contains '%.*s' component"),
905 if (0 < component_len && component[0] ==
'-')
906 warning(
_(
"file name '%s' component contains leading '-'"),
908 if (component_len_max < component_len)
909 warning(
_(
"file name '%s' contains overlength component"
911 name, component_len_max, component);
922 static char const benign[] =
924 "abcdefghijklmnopqrstuvwxyz"
925 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
931 static char const printable_and_not_benign[] =
932 " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
934 char const *component =
name;
936 for (cp =
name; *cp; cp++)
938 unsigned char c = *cp;
940 if (
noise && !strchr(benign,
c))
942 warning((strchr(printable_and_not_benign,
c)
943 ?
_(
"file name '%s' contains byte '%c'")
944 :
_(
"file name '%s' contains byte '\\%o'")),
965relname(
char const *target,
char const *linkname)
973 char const *f = target;
976 if (*linkname ==
'/')
982 linksize =
len + needslash + strlen(target) + 1;
983 f = result =
emalloc(linksize);
986 strcpy(result +
len + needslash, target);
988 for (
i = 0; f[
i] && f[
i] == linkname[
i];
i++)
991 for (; linkname[
i];
i++)
992 dotdots += linkname[
i] ==
'/' && linkname[
i - 1] !=
'/';
993 taillen = strlen(f + dir_len);
994 dotdotetcsize = 3 * dotdots + taillen + 1;
995 if (dotdotetcsize <= linksize)
998 result =
emalloc(dotdotetcsize);
999 for (
i = 0;
i < dotdots;
i++)
1000 memcpy(result + 3 *
i,
"../", 3);
1001 memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
1012 int r =
linkat(AT_FDCWD, target, AT_FDCWD, linkname, AT_SYMLINK_FOLLOW);
1014 return r == 0 ? 0 : errno;
1018dolink(
char const *target,
char const *linkname,
bool staysymlink)
1020 bool remove_only = strcmp(target,
"-") == 0;
1021 bool linkdirs_made =
false;
1028 if (!remove_only &&
itsdir(target))
1030 fprintf(stderr,
_(
"%s: linking target %s/%s failed: %s\n"),
1036 if (remove(linkname) == 0)
1037 linkdirs_made =
true;
1038 else if (errno != ENOENT)
1042 fprintf(stderr,
_(
"%s: Can't remove %s/%s: %s\n"),
1049 if (link_errno == ENOENT && !linkdirs_made)
1052 linkdirs_made =
true;
1055 if (link_errno != 0)
1058 bool absolute = *target ==
'/';
1059 char *linkalloc = absolute ? NULL :
relname(target, linkname);
1060 char const *contents = absolute ? target : linkalloc;
1061 int symlink_errno =
symlink(contents, linkname) == 0 ? 0 : errno;
1064 && (symlink_errno == ENOENT || symlink_errno ==
ENOTSUP))
1067 if (symlink_errno == ENOENT)
1068 symlink_errno =
symlink(contents, linkname) == 0 ? 0 : errno;
1071 if (symlink_errno == 0)
1074 warning(
_(
"symbolic link used because hard link failed: %s"),
1084 fp = fopen(target,
"rb");
1089 fprintf(stderr,
_(
"%s: Can't read %s/%s: %s\n"),
1093 tp = fopen(linkname,
"wb");
1098 fprintf(stderr,
_(
"%s: Can't create %s/%s: %s\n"),
1102 while ((
c = getc(fp)) != EOF)
1107 warning(
_(
"copy used because hard link failed: %s"),
1110 else if (symlink_errno !=
ENOTSUP)
1111 warning(
_(
"copy used because symbolic link failed: %s"),
1130 size_t n = strlen(
name);
1131 char *nameslashdot =
emalloc(n + 3);
1134 memcpy(nameslashdot,
name, n);
1135 strcpy(&nameslashdot[n], &
"/."[!(n &&
name[n - 1] !=
'/')]);
1167 return strcmp(((
const struct rule *) cp1)->r_name,
1168 ((
const struct rule *) cp2)->r_name);
1193 warning(
_(
"same rule name in multiple files"));
1195 warning(
_(
"same rule name in multiple files"));
1218 for (base = 0; base <
nrules; base = out)
1221 for (out = base + 1; out <
nrules; ++out)
1249 error(
"%s",
_(
"%s in ruleless zone"));
1268 if (strcmp(
name,
"-") == 0)
1270 name =
_(
"standard input");
1273 else if ((fp = fopen(
name,
"r")) == NULL)
1277 fprintf(stderr,
_(
"%s: Cannot open %s: %s\n"),
1282 for (num = 1;; ++num)
1287 cp = strchr(
buf,
'\n');
1290 error(
_(
"line too long"));
1296 while (fields[nfields] != NULL)
1300 if (strcmp(fields[nfields],
"-") == 0)
1301 fields[nfields] = &nada;
1311 wantcont =
inzcont(fields, nfields);
1315 struct lookup const *line_codes
1318 lp =
byword(fields[0], line_codes);
1320 error(
_(
"input line of unknown type"));
1329 wantcont =
inzone(fields, nfields);
1345 _(
"%s: panic: Invalid l_value %d\n"),
1354 error(
_(
"expected continuation line not found"));
1366gethms(
char const *
string,
char const *errstring)
1380 if (
string == NULL || *
string ==
'\0')
1389 switch (sscanf(
string,
1390 "%" SCNdZIC "%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);
1423 error(
"%s", errstring);
1428 error(
_(
"time overflow"));
1431 ss += 5 + ((ss ^ 1) & (xr ==
'0')) <= tenths;
1434 warning(
_(
"values over 24 hours not handled by pre-2007 versions of zic"));
1444 size_t fieldlen = strlen(field);
1448 char *ep = field + fieldlen - 1;
1462 save =
gethms(field,
_(
"invalid saved time"));
1463 *isdst = dst < 0 ? save != 0 : dst;
1470 static struct rule r;
1474 error(
_(
"wrong number of fields on Rule line"));
1521 error(
_(
"wrong number of fields on Zone line"));
1527 _(
"\"Zone %s\" line and -l option are mutually exclusive"),
1534 _(
"\"Zone %s\" line and -p option are mutually exclusive"),
1539 if (
zones[
i].z_name != NULL &&
1542 error(
_(
"duplicate zone name %s"
1543 " (file \"%s\", line %" PRIdMAX
")"),
1549 return inzsub(fields, nfields,
false);
1557 error(
_(
"wrong number of fields on Zone continuation line"));
1560 return inzsub(fields, nfields,
true);
1564inzsub(
char **fields,
int nfields,
bool iscont)
1568 static struct zone z;
1605 if ((cp = strchr(fields[i_format],
'%')) != NULL)
1607 if ((*++cp !=
's' && *cp !=
'z') || strchr(cp,
'%')
1608 || strchr(fields[i_format],
'/'))
1610 error(
_(
"invalid abbreviation format"));
1620 warning(
_(
"format '%s' not handled by pre-2015 versions of zic"),
1622 cp1[cp - fields[i_format]] =
's';
1626 hasuntil = nfields > i_untilyear;
1632 fields[i_untilyear],
1635 (nfields > i_untilmonth) ?
1636 fields[i_untilmonth] :
"Jan",
1637 (nfields > i_untilday) ? fields[i_untilday] :
"1",
1638 (nfields > i_untiltime) ? fields[i_untiltime] :
"0");
1641 if (iscont &&
nzones > 0 &&
1648 error(
_(
"Zone continuation line end time is not after end time of previous line"));
1679 if (sscanf(cp,
"%" SCNdZIC "%c", &year, &xs) != 1)
1684 error(
_(
"invalid leaping year"));
1708 dayoff =
oadd(dayoff,
i);
1712 error(
_(
"invalid month name"));
1720 dayoff =
oadd(dayoff,
i);
1724 if (sscanf(cp,
"%d%c", &day, &xs) != 1 ||
1727 error(
_(
"invalid day of month"));
1730 dayoff =
oadd(dayoff, day - 1);
1733 error(
_(
"time too small"));
1738 error(
_(
"time too large"));
1745 error(
_(
"leap second precedes Epoch"));
1753 error(
_(
"wrong number of fields on Leap line"));
1763 error(
_(
"invalid Rolling/Stationary field on Leap line"));
1770 else if (strcmp(fields[
LP_CORR],
"+") == 0)
1773 error(
_(
"invalid CORRECTION field on Leap line"));
1785 error(
_(
"wrong number of fields on Expires line"));
1787 error(
_(
"multiple Expires lines"));
1799 error(
_(
"wrong number of fields on Link line"));
1804 error(
_(
"blank TARGET field on Link line"));
1819 const char *typep,
const char *monthp,
const char *dayp,
1830 error(
_(
"invalid month name"));
1839 ep = dp + strlen(dp) - 1;
1881 _(
"%s: panic: Invalid l_value %d\n"),
1887 error(
_(
"invalid starting year"));
1907 _(
"%s: panic: Invalid l_value %d\n"),
1913 error(
_(
"invalid ending year"));
1918 error(
_(
"starting year greater than ending year"));
1923 error(
_(
"year type \"%s\" is unsupported; use \"-\" instead"),
1941 if ((ep = strchr(dp,
'<')) != NULL)
1943 else if ((ep = strchr(dp,
'>')) != NULL)
1955 error(
_(
"invalid day of month"));
1961 error(
_(
"invalid weekday name"));
1971 error(
_(
"invalid day of month"));
1984 unsigned char *
const b = (
unsigned char *)
buf;
1986 for (
i = 0, shift = 24;
i < 4; ++
i, shift -= 8)
1987 b[
i] =
val >> shift;
1995 unsigned char *
const b = (
unsigned char *)
buf;
1997 for (
i = 0, shift = 56;
i < 8; ++
i, shift -= 8)
1998 b[
i] =
val >> shift;
2007 fwrite(
buf,
sizeof buf, 1, fp);
2020 fwrite(
buf,
sizeof buf, 1, fp);
2030 return (
a <
b) ? -1 : (
a >
b);
2044 zic_t const *ats,
unsigned char const *
types)
2046 while (0 < r.count && ats[r.base] < lo)
2052 while (0 < r.leapcount &&
trans[r.leapbase] < lo)
2060 while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
2062 while (0 < r.leapcount && hi + 1 <
trans[r.leapbase + r.leapcount - 1])
2077 static const struct tzhead tzh0;
2078 static struct tzhead tzh;
2079 bool dir_checked =
false;
2081 zic_t y2038_boundary = one << 31;
2090 void *typesptr = ats + nats;
2091 unsigned char *
types = typesptr;
2111 for (; fromi <
timecnt; ++fromi)
2140 warning(
_(
"reference clients mishandle"
2141 " more than %d transition times"),
2144 warning(
_(
"pre-2014 clients may mishandle"
2145 " more than 1200 transition times"));
2181 && ats[
timecnt - 1] < y2038_boundary - 1 && strchr(
string,
'<'))
2183 ats[
timecnt] = y2038_boundary - 1;
2198 if (remove(
name) == 0)
2200 else if (errno != ENOENT)
2204 fprintf(stderr,
_(
"%s: Cannot remove %s/%s: %s\n"),
2208 fp = fopen(
name,
"wb");
2211 int fopen_errno = errno;
2213 if (fopen_errno == ENOENT && !dir_checked)
2216 fp = fopen(
name,
"wb");
2217 fopen_errno = errno;
2221 fprintf(stderr,
_(
"%s: Cannot create %s/%s: %s\n"),
2226 for (pass = 1; pass <= 2; ++pass)
2228 ptrdiff_t thistimei,
2263 thisdefaulttype = (
lo_time <= INT32_MIN
2267 thistimei = range32.
base;
2268 thistimecnt = range32.
count;
2269 toomanytimes = thistimecnt >> 31 >> 1 != 0;
2278 thistimei = range64.
base;
2279 thistimecnt = range64.
count;
2280 toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
2287 error(
_(
"too many transition times"));
2297 if (0 < thistimei && ats[thistimei] !=
lo_time)
2304 thistimelim = thistimei + thistimecnt;
2305 thisleaplim = thisleapi + thisleapcnt;
2306 if (thistimecnt != 0)
2308 if (ats[thistimei] ==
lo_time)
2313 memset(omittype,
true,
typecnt);
2314 omittype[thisdefaulttype] =
false;
2315 for (
i = thistimei;
i < thistimelim;
i++)
2316 omittype[
types[
i]] =
false;
2323 old0 = strlen(omittype);
2325#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2341 hidst = histd = mrudst = mrustd = -1;
2342 for (
i = thistimei;
i < thistimelim; ++
i)
2349 int h = (
i == old0 ? thisdefaulttype
2350 :
i == thisdefaulttype ? old0 :
i);
2360 if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
2370 omittype[
type] =
false;
2372 if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
2382 omittype[
type] =
false;
2390 typemap[
i == old0 ? thisdefaulttype
2391 :
i == thisdefaulttype ? old0 :
i]
2394 for (
i = 0;
i <
sizeof indmap /
sizeof indmap[0]; ++
i)
2396 thischarcnt = stdcnt = utcnt = 0;
2404 stdcnt = thistypecnt;
2406 utcnt = thistypecnt;
2410 for (
j = 0;
j < thischarcnt; ++
j)
2411 if (strcmp(&thischars[
j], thisabbr) == 0)
2413 if (
j == thischarcnt)
2415 strcpy(&thischars[thischarcnt], thisabbr);
2416 thischarcnt += strlen(thisabbr) + 1;
2422 utcnt = stdcnt = thisleapcnt = 0;
2423 thistimecnt = -(locut + hicut);
2424 thistypecnt = thischarcnt = 1;
2425 thistimelim = thistimei;
2427#define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
2461 for (
i = thistimei;
i < thistimelim; ++
i)
2466 char *thisabbrev = &thischars[indmap[
desigidx[
tm]]];
2475 if (thistimei >= thistimelim)
2478 char *thisabbrev = &thischars[indmap[
desigidx[
tm]]];
2495 for (
i = thistimei;
i < thistimelim; ++
i)
2497 zic_t at = ats[
i] < lo ? lo : ats[
i];
2505 putc(currenttype, fp);
2506 for (
i = thistimei;
i < thistimelim; ++
i)
2508 currenttype = typemap[
types[
i]];
2509 putc(currenttype, fp);
2512 putc(currenttype, fp);
2516 int h = (
i == old0 ? thisdefaulttype
2517 :
i == thisdefaulttype ? old0 :
i);
2526 if (thischarcnt != 0)
2527 fwrite(thischars,
sizeof thischars[0],
2529 for (
i = thisleapi;
i < thisleaplim; ++
i)
2569 fprintf(fp,
"\n%s\n",
string);
2593 error(
_(
"%%z UT offset magnitude exceeds 99:59:59"));
2601 *p++ =
'0' + offset / 10;
2602 *p++ =
'0' + offset % 10;
2603 if (minutes | seconds)
2605 *p++ =
'0' + minutes / 10;
2606 *p++ =
'0' + minutes % 10;
2609 *p++ =
'0' + seconds / 10;
2610 *p++ =
'0' + seconds % 10;
2620 bool isdst,
zic_t save,
bool doquotes)
2627 slashp = strchr(
format,
'/');
2640 strcpy(abbr, slashp + 1);
2645 abbr[slashp -
format] =
'\0';
2650 for (cp = abbr;
is_alpha(*cp); cp++)
2652 if (
len > 0 && *cp ==
'\0')
2654 abbr[
len + 2] =
'\0';
2655 abbr[
len + 1] =
'>';
2656 memmove(abbr + 1, abbr,
len);
2676 bool negative = offset < 0;
2695 if (minutes != 0 || seconds != 0)
2718 for (month = 0; month < rp->
r_month; ++month)
2759 result +=
sprintf(result,
"M%d.%d.%d",
2792 if (
a->r_hiyear !=
b->r_hiyear)
2793 return a->r_hiyear <
b->r_hiyear ? -1 : 1;
2794 if (
a->r_month -
b->r_month != 0)
2795 return a->r_month -
b->r_month;
2796 return a->r_dayofmonth -
b->r_dayofmonth;
2802 const struct zone *zp;
2807 const char *abbrvar;
2824 zp = zpfirst + zonecount - 1;
2825 stdrp = dstrp = NULL;
2846 if (stdrp == NULL && dstrp == NULL)
2852 struct rule *stdabbrrp = NULL;
2862 if (stdrp != NULL && stdrp->
r_isdst)
2881 = (stdabbrrp ? stdabbrrp->
r_abbrvar :
"");
2888 abbrvar = (stdrp == NULL) ?
"" : stdrp->
r_abbrvar;
2889 len =
doabbr(result, zp, abbrvar,
false, 0,
true);
2912 result[
len++] =
',';
2921 len += strlen(result +
len);
2922 result[
len++] =
',';
2937 const struct zone *zp;
2961 ptrdiff_t lastatmax = -1;
2963 zic_t y2038_boundary = one << 31;
2965 int defaulttype = -1;
2968 max_envvar_len = 2 * max_abbr_len + 5 * 9;
2969 startbuf =
emalloc(max_abbr_len + 1);
2970 ab =
emalloc(max_abbr_len + 1);
2971 envvar =
emalloc(max_envvar_len + 1);
2981 prodstic = zonecount == 1;
2987 startttisstd =
false;
2988 startttisut =
false;
2995 for (
i = 0;
i < zonecount; ++
i)
2998 if (
i < zonecount - 1)
3022 _(
"no POSIX environment variable for zone"),
3030 warning(
_(
"%s: pre-%d clients may mishandle"
3031 " distant timestamps"),
3086 for (
i = 0;
i < zonecount; ++
i)
3088 struct rule *prevrp = NULL;
3095 usestart =
i > 0 && (zp - 1)->z_untiltime >
min_time;
3096 useuntil =
i < (zonecount - 1);
3108 startbuf, zp->
z_isdst, startttisstd,
3140 = (rp->
r_temp < y2038_boundary
3141 || year <= max_year0);
3160 untiltime =
tadd(untiltime,
3163 untiltime =
tadd(untiltime,
3181 offset =
oadd(offset, save);
3186 jtime =
tadd(jtime, -offset);
3187 if (k < 0 || jtime < ktime)
3192 else if (jtime == ktime)
3194 char const *dup_rules_msg =
3195 _(
"two rules for same instant");
3203 error(
"%s", dup_rules_msg);
3210 if (useuntil && ktime >= untiltime)
3213 if (usestart && ktime == starttime)
3217 if (ktime < starttime)
3228 if (*startbuf ==
'\0'
3252 if (defaulttype < 0 && !rp->
r_isdst)
3264 if (*startbuf ==
'\0' &&
3266 strchr(zp->
z_format,
'%') == NULL &&
3270 if (*startbuf ==
'\0')
3271 error(
_(
"cannot determine time zone abbreviation to use just after until time"));
3274 bool isdst = startoff != zp->
z_stdoff;
3277 startttisstd, startttisut);
3278 if (defaulttype < 0 && !isdst)
3293 starttime =
tadd(starttime, -save);
3295 starttime =
tadd(starttime, -stdoff);
3298 if (defaulttype < 0)
3326 lastat ? lastat->
type : defaulttype);
3347addtype(
zic_t utoff,
char const *abbr,
bool isdst,
bool ttisstd,
bool ttisut)
3352 if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
3354 error(
_(
"UT offset out of range"));
3358 ttisstd = ttisut =
false;
3361 if (strcmp(&
chars[
j], abbr) == 0)
3379 error(
_(
"too many local time types"));
3398 error(
_(
"too many leap seconds"));
3408 corr[
i] = correction;
3418 zic_t prevtrans = 0;
3427 error(
_(
"Leap seconds too close together"));
3432 last =
corr[
i] += last;
3439 warning(
_(
"\"#expires\" is obsolescent; use \"Expires\""));
3447 error(
_(
"last Leap time does not precede Expires time"));
3617 while (*++abbr !=
'\0')
3639static const struct lookup *
3642 const struct lookup *foundlp;
3656 warning(
_(
"\"%s\" is undocumented; use \"last%s\" instead"),
3679 if (foundlp == NULL)
3685 if (foundlp &&
noise)
3688 bool pre_2017c_match =
false;
3693 if (pre_2017c_match)
3695 warning(
_(
"\"%s\" is ambiguous in pre-2017c zic"),
word);
3698 pre_2017c_match =
true;
3720 if (*cp ==
'\0' || *cp ==
'#')
3722 array[nsubs++] = dp = cp;
3725 if ((*dp = *cp++) !=
'"')
3728 while ((*dp = *cp++) !=
'"')
3733 error(
_(
"Odd number of quotation marks"));
3736 }
while (*cp && *cp !=
'#' && !
is_space(*cp));
3741 array[nsubs] = NULL;
3745static _Noreturn
void
3748 error(
_(
"time overflow"));
3812 else if (wantedy < 0)
3817 while (wantedy !=
y)
3829 dayoff =
oadd(dayoff,
i);
3834 dayoff =
oadd(dayoff,
i);
3844 error(
_(
"use of 2/29 in non leap-year"));
3849 dayoff =
oadd(dayoff,
i);
3854#define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3868 while (wday != rp->
r_wday)
3871 dayoff =
oadd(dayoff, 1);
3878 dayoff =
oadd(dayoff, -1);
3886 warning(
_(
"rule goes past start/end of month; \
3887will not work with pre-2004 versions of zic"));
3910 while (
is_alpha(*cp) || (
'0' <= *cp && *cp <=
'9')
3911 || *cp ==
'-' || *cp ==
'+')
3913 if (
noise && cp -
string < 3)
3914 mp =
_(
"time zone abbreviation has fewer than 3 characters");
3916 mp =
_(
"time zone abbreviation has too many characters");
3918 mp =
_(
"time zone abbreviation differs from POSIX standard");
3920 warning(
"%s (%s)", mp,
string);
3922 i = strlen(
string) + 1;
3925 error(
_(
"too many, or too long, time zone abbreviations"));
3956 while (cp && ((cp = strchr(cp,
'/')) || !ancestors))
3978 error(
_(
"%s: Cannot create directory %s: %s"),
3995link(
const char *oldpath,
const char *newpath)
3997 if (!CopyFile(oldpath, newpath,
false))
#define pg_attribute_printf(f, a)
#define fprintf(file, fmt, msg)
void err(int eval, const char *fmt,...)
int getopt(int nargc, char *const *nargv, const char *ostr)
PGDLLIMPORT char * optarg
static const struct lconv_member_info table[]
#define qsort(a, b, c, d)
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
void _dosmaperr(unsigned long)
#define symlink(oldpath, newpath)
#define readlink(path, buf, size)
static char chars[TZ_MAX_CHARS]
static void verror(const char *const string, va_list args) pg_attribute_printf(1
static const char * leapsec
static zic_t gethms(const char *string, const char *errstring)
static ptrdiff_t const PTRDIFF_MAX
#define ZIC_BLOAT_DEFAULT
static void change_directory(char const *dir)
static struct zone * zones
static void * growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
static unsigned char desigidx[TZ_MAX_TYPES]
static bool print_abbrevs
static zic_t getleapdatetime(char **fields, int nfields, bool expire_line)
static char * relname(char const *target, char const *linkname)
static zic_t tadd(zic_t t1, zic_t t2)
static void * memcheck(void *ptr)
static _Noreturn void memory_exhausted(const char *msg)
static char const * abbroffset(char *buf, zic_t offset)
static bool ttisuts[TZ_MAX_TYPES]
static int atcomp(const void *avp, const void *bvp)
static zic_t comment_leapexpires
static char isdsts[TZ_MAX_TYPES]
static struct lookup const lasts[]
static struct lookup const leap_types[]
static void convert64(const zic_t val, char *const buf)
static bool itsdir(char const *name)
static void static void static void warning(const char *const string,...) pg_attribute_printf(1
int main(int argc, char **argv)
static struct lookup const mon_names[]
static zic_t print_cutoff
static int hardlinkerr(char const *target, char const *linkname)
static void eat(char const *name, lineno_t num)
static void inleap(char **fields, int nfields)
static void mkdirs(char const *argname, bool ancestors)
static _Noreturn void time_overflow(void)
static void puttzcodepass(zic_t val, FILE *fp, int pass)
static bool inzone(char **fields, int nfields)
static struct lookup const begin_years[]
#define ZIC_VERSION_PRE_2013
@ WORK_AROUND_QTBUG_53071
static _Noreturn void usage(FILE *stream, int status)
static void close_file(FILE *stream, char const *dir, char const *name)
static void outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
static bool componentcheck(char const *name, char const *component, char const *component_end)
static int max_format_len
static size_t align_to(size_t size, size_t alignment)
static void puttzcode(const int_fast32_t val, FILE *const fp)
static ptrdiff_t nzones_alloc
static int max_abbrvar_len
static zic_t rpytime(const struct rule *rp, zic_t wantedy)
static bool inzcont(char **fields, int nfields)
static ptrdiff_t nlinks_alloc
#define linkat(targetdir, target, linknamedir, linkname, flag)
static const char * lcltime
static const char * rfilename
static bool ttisstds[TZ_MAX_TYPES]
static bool ciprefix(char const *abbr, char const *word)
static int stringoffset(char *result, zic_t offset)
static struct lookup const zi_line_codes[]
static void inexpires(char **fields, int nfields)
static bool want_bloat(void)
static const char * filename
static int stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
static void newabbr(const char *string)
static int addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
static bool is_alpha(char a)
static const int len_months[2][MONSPERYEAR]
static int stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
static bool itssymlink(char const *name)
static bool is_space(char a)
static bool ciequal(const char *ap, const char *bp)
static void inrule(char **fields, int nfields)
static void eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
static void dolink(const char *target, const char *linkname, bool staysymlink)
static zic_t oadd(zic_t t1, zic_t t2)
static void static void error(const char *const string,...) pg_attribute_printf(1
static bool timerange_option(char *timerange)
static char * ecpyalloc(char const *str)
static const char * directory
static const char * psxrules
static struct lookup const * byword(const char *word, const struct lookup *table)
static zic_t utoffs[TZ_MAX_TYPES]
static char roll[TZ_MAX_LEAPS]
static ptrdiff_t nrules_alloc
static void writezone(const char *const name, const char *const string, char version, int defaulttype)
static zic_t const max_time
static char lowerit(char a)
static void * erealloc(void *ptr, size_t size)
static bool namecheck(const char *name)
static bool inzsub(char **fields, int nfields, bool iscont)
static size_t size_product(size_t nitems, size_t itemsize)
static struct rule * rules
static zic_t getsave(char *field, bool *isdst)
static ptrdiff_t timecnt_alloc
static void rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, const char *typep, const char *monthp, const char *dayp, const char *timep)
static void infile(const char *name)
int link(const char *target, const char *linkname)
static bool itsabbr(const char *abbr, const char *word)
static zic_t trans[TZ_MAX_LEAPS]
static zic_t const min_time
#define ZIC_MAX_ABBR_LEN_WO_WARN
static void static void static void static void addtt(zic_t starttime, int type)
static const char * progname
static int rcomp(const void *cp1, const void *cp2)
static void updateminmax(const zic_t x)
static struct attype * attypes
static size_t doabbr(char *abbr, struct zone const *zp, char const *letters, bool isdst, zic_t save, bool doquotes)
static struct lookup const wday_names[]
static char ** getfields(char *cp)
static void adjleap(void)
static struct lookup const end_years[]
static void associate(void)
static struct timerange limitrange(struct timerange r, zic_t lo, zic_t hi, zic_t const *ats, unsigned char const *types)
static struct link * links
static void * emalloc(size_t size)
static const int len_years[2]
static void leapadd(zic_t t, int correction, int rolling)
static struct lookup const leap_line_codes[]
static void convert(const int_fast32_t val, char *const buf)
#define TIME_T_BITS_IN_FILE
static const char * tzdefault
static int rule_cmp(struct rule const *a, struct rule const *b)
static void inlink(char **fields, int nfields)
static zic_t corr[TZ_MAX_LEAPS]