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))
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}
543 char const *
e = (
ferror(stream) ?
_(
"I/O error")
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"),
596#define TIME_T_BITS_IN_FILE 64
663#ifndef ZIC_BLOAT_DEFAULT
664#define ZIC_BLOAT_DEFAULT "slim"
683 _(
"wild compilation-time specification of zic_t"));
686 for (k = 1; k < argc; k++)
687 if (
strcmp(argv[k],
"--version") == 0)
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)
706 error(
_(
"incompatible -b options"));
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"),
828 for (k =
optind; k < argc; k++)
859 eat(
_(
"command line"), 1);
864 eat(
_(
"command line"), 1);
884 error(
_(
"empty file name"));
887 ?
"file name '%s' begins with '/'"
889 ?
"file name '%s' contains '//'"
890 :
"file name '%s' ends with '/'"),
899 error(
_(
"file name '%s' contains '%.*s' component"),
906 warning(
_(
"file name '%s' component contains leading '-'"),
909 warning(
_(
"file name '%s' contains overlength component"
922 static char const benign[] =
924 "abcdefghijklmnopqrstuvwxyz"
925 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
932 " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
938 unsigned char c = *
cp;
943 ?
_(
"file name '%s' contains byte '%c'")
944 :
_(
"file name '%s' contains byte '\\%o'")),
973 char const *f = target;
1000 memcpy(result + 3 *
i,
"../", 3);
1014 return r == 0 ? 0 :
errno;
1074 warning(
_(
"symbolic link used because hard link failed: %s"),
1084 fp =
fopen(target,
"rb");
1107 warning(
_(
"copy used because hard link failed: %s"),
1111 warning(
_(
"copy used because symbolic link failed: %s"),
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)
1230 zp->z_nrules = out - base;
1236 if (
zp->z_nrules == 0)
1241 eat(
zp->z_filename,
zp->z_linenum);
1248 if (
zp->z_format_specifier ==
's')
1249 error(
"%s",
_(
"%s in ruleless zone"));
1270 name =
_(
"standard input");
1282 for (num = 1;; ++num)
1290 error(
_(
"line too long"));
1296 while (fields[nfields] !=
NULL)
1300 if (
strcmp(fields[nfields],
"-") == 0)
1301 fields[nfields] = &
nada;
1320 error(
_(
"input line of unknown type"));
1322 switch (
lp->l_value)
1345 _(
"%s: panic: Invalid l_value %d\n"),
1354 error(
_(
"expected continuation line not found"));
1380 if (
string ==
NULL || *
string ==
'\0')
1390 "%" SCNdZIC "%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1397 ok =
'0' <=
xr &&
xr <=
'9';
1402 warning(
_(
"fractional seconds rejected by"
1403 " pre-2018 versions of zic"));
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"));
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"),
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);
1568 static struct zone z;
1610 error(
_(
"invalid abbreviation format"));
1620 warning(
_(
"format '%s' not handled by pre-2015 versions of zic"),
1648 error(
_(
"Zone continuation line end time is not after end time of previous line"));
1684 error(
_(
"invalid leaping year"));
1712 error(
_(
"invalid month name"));
1715 month =
lp->l_value;
1727 error(
_(
"invalid day of month"));
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"));
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"));
1830 error(
_(
"invalid month name"));
1833 rp->r_month =
lp->l_value;
1834 rp->r_todisstd =
false;
1835 rp->r_todisut =
false;
1843 rp->r_todisstd =
true;
1844 rp->r_todisut =
false;
1848 rp->r_todisstd =
false;
1849 rp->r_todisut =
false;
1855 rp->r_todisstd =
true;
1856 rp->r_todisut =
true;
1870 if (!
rp->r_lowasnum)
1871 switch (
lp->l_value)
1881 _(
"%s: panic: Invalid l_value %d\n"),
1887 error(
_(
"invalid starting year"));
1893 if (!
rp->r_hiwasnum)
1894 switch (
lp->l_value)
1903 rp->r_hiyear =
rp->r_loyear;
1907 _(
"%s: panic: Invalid l_value %d\n"),
1913 error(
_(
"invalid ending year"));
1916 if (
rp->r_loyear >
rp->r_hiyear)
1918 error(
_(
"starting year greater than ending year"));
1923 error(
_(
"year type \"%s\" is unsupported; use \"-\" instead"),
1936 rp->r_wday =
lp->l_value;
1955 error(
_(
"invalid day of month"));
1961 error(
_(
"invalid weekday name"));
1965 rp->r_wday =
lp->l_value;
1968 rp->r_dayofmonth <= 0 ||
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;
2030 return (
a <
b) ? -1 : (
a >
b);
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])
2078 static struct tzhead tzh;
2140 warning(
_(
"reference clients mishandle"
2141 " more than %d transition times"),
2144 warning(
_(
"pre-2014 clients may mishandle"
2145 " more than 1200 transition times"));
2198 if (remove(
name) == 0)
2287 error(
_(
"too many transition times"));
2325#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2427#define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
2497 zic_t at = ats[
i] < lo ? lo : ats[
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;
2632 if (
zp->z_format_specifier ==
'z')
2652 if (
len > 0 && *
cp ==
'\0')
2676 bool negative = offset < 0;
2718 for (month = 0; month <
rp->r_month; ++month)
2721 if (
rp->r_month <= 1)
2722 result +=
sprintf(result,
"%d", total +
rp->r_dayofmonth - 1);
2724 result +=
sprintf(result,
"J%d", total +
rp->r_dayofmonth);
2729 int wday =
rp->r_wday;
2759 result +=
sprintf(result,
"M%d.%d.%d",
2760 rp->r_month + 1,
week, wday);
2764 if (
rp->r_todisstd && !
rp->r_isdst)
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;
2826 for (
i = 0;
i <
zp->z_nrules; ++
i)
2828 rp = &
zp->z_rules[
i];
2854 for (
i = 0;
i <
zp->z_nrules; ++
i)
2856 rp = &
zp->z_rules[
i];
2867 dstr.r_dayofmonth = 1;
2869 dstr.r_todisstd =
dstr.r_todisut =
false;
2875 stdr.r_dayofmonth = 31;
2877 stdr.r_todisstd =
stdr.r_todisut =
false;
2878 stdr.r_isdst =
false;
2904 -(
zp->z_stdoff +
dstrp->r_save));
2912 result[
len++] =
',';
2922 result[
len++] =
',';
2965 int defaulttype = -1;
3000 for (
j = 0;
j <
zp->z_nrules; ++
j)
3002 rp = &
zp->z_rules[
j];
3007 if (
rp->r_lowasnum ||
rp->r_hiwasnum)
3022 _(
"no POSIX environment variable for zone"),
3030 warning(
_(
"%s: pre-%d clients may mishandle"
3031 " distant timestamps"),
3100 eat(
zp->z_filename,
zp->z_linenum);
3103 if (
zp->z_nrules == 0)
3121 if (
useuntil && year >
zp->z_untilrule.r_hiyear)
3129 for (
j = 0;
j <
zp->z_nrules; ++
j)
3131 rp = &
zp->z_rules[
j];
3132 eats(
zp->z_filename,
zp->z_linenum,
3133 rp->r_filename,
rp->r_linenum);
3134 rp->r_todo = year >=
rp->r_loyear &&
3135 year <=
rp->r_hiyear;
3159 if (!
zp->z_untilrule.r_todisut)
3162 if (!
zp->z_untilrule.r_todisstd)
3172 for (
j = 0;
j <
zp->z_nrules; ++
j)
3174 rp = &
zp->z_rules[
j];
3177 eats(
zp->z_filename,
zp->z_linenum,
3178 rp->r_filename,
rp->r_linenum);
3179 offset =
rp->r_todisut ? 0 :
stdoff;
3180 if (!
rp->r_todisstd)
3195 _(
"two rules for same instant");
3197 eats(
zp->z_filename,
zp->z_linenum,
3198 rp->r_filename,
rp->r_linenum);
3200 rp = &
zp->z_rules[k];
3201 eats(
zp->z_filename,
zp->z_linenum,
3202 rp->r_filename,
rp->r_linenum);
3208 rp = &
zp->z_rules[k];
3217 if (
ktime < starttime)
3240 eats(
zp->z_filename,
zp->z_linenum,
3241 rp->r_filename,
rp->r_linenum);
3243 rp->r_isdst,
rp->r_save,
false);
3244 offset =
oadd(
zp->z_stdoff,
rp->r_save);
3251 rp->r_todisstd,
rp->r_todisut);
3269 eat(
zp->z_filename,
zp->z_linenum);
3271 error(
_(
"cannot determine time zone abbreviation to use just after until time"));
3278 if (defaulttype < 0 && !
isdst)
3291 starttime =
zp->z_untiltime;
3293 starttime =
tadd(starttime, -
save);
3298 if (defaulttype < 0)
3318 xr.r_dayofmonth = 1;
3352 if (!(-1L - 2147483647L <=
utoff &&
utoff <= 2147483647L))
3354 error(
_(
"UT offset out of range"));
3379 error(
_(
"too many local time types"));
3398 error(
_(
"too many leap seconds"));
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 *
3656 warning(
_(
"\"%s\" is undocumented; use \"last%s\" instead"),
3695 warning(
_(
"\"%s\" is ambiguous in pre-2017c zic"),
word);
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"));
3741 array[nsubs] =
NULL;
3748 error(
_(
"time overflow"));
3831 while (m !=
rp->r_month)
3837 i =
rp->r_dayofmonth;
3844 error(
_(
"use of 2/29 in non leap-year"));
3854#define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3868 while (wday !=
rp->r_wday)
3886 warning(
_(
"rule goes past start/end of month; \
3887will not work with pre-2004 versions of zic"));
3895 return tadd(t,
rp->r_tod);
3911 || *
cp ==
'-' || *
cp ==
'+')
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");
3925 error(
_(
"too many, or too long, time zone abbreviations"));
3978 error(
_(
"%s: Cannot create directory %s: %s"),
#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[]
static char buf[DEFAULT_XLOG_SEG_SIZE]
#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 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
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
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 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)
static bool itsabbr(const char *abbr, const char *word)
static zic_t trans[TZ_MAX_LEAPS]
static zic_t const min_time
@ WORK_AROUND_QTBUG_53071
#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]