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)
121extern int link(
const char *target,
const char *
linkname);
122#ifndef AT_SYMLINK_FOLLOW
123#define linkat(targetdir, target, linknamedir, linkname, flag) \
124 (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
176#ifndef WORK_AROUND_QTBUG_53071
227#define ZONE_MINFIELDS 5
228#define ZONE_MAXFIELDS 9
238#define ZFC_TILMONTH 4
241#define ZONEC_MINFIELDS 3
242#define ZONEC_MAXFIELDS 7
257#define RULE_FIELDS 10
280#define EXPIRES_FIELDS 5
384 {
"Stationary",
false},
389 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
390 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
547 char const *
e = (
ferror(stream) ?
_(
"I/O error")
553 dir ? dir :
"", dir ?
"/" :
"",
564 _(
"%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
565 "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
566 " [ -L leapseconds ] \\\n"
567 "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
568 "\t[ filename ... ]\n\n"
569 "Report bugs to %s.\n"),
602#define TIME_T_BITS_IN_FILE 64
675#ifndef ZIC_BLOAT_DEFAULT
676#define ZIC_BLOAT_DEFAULT "slim"
695 _(
"wild compilation-time specification of zic_t"));
698 for (k = 1; k < argc; k++)
699 if (
strcmp(argv[k],
"--version") == 0)
705 else if (
strcmp(argv[k],
"--help") == 0)
709 while ((
c =
getopt(argc, argv,
"b:d:l:L:p:Pr:st:vy:")) !=
EOF &&
c != -1)
718 error(
_(
"incompatible -b options"));
724 error(
_(
"incompatible -b options"));
736 _(
"%s: More than one -d option specified\n"),
747 _(
"%s: More than one -l option specified\n"),
758 _(
"%s: More than one -p option specified\n"),
767 _(
"%s: More than one -t option"
783 _(
"%s: More than one -L option specified\n"),
799 _(
"%s: More than one -r option specified\n"),
806 _(
"%s: invalid time range: %s\n"),
840 for (k =
optind; k < argc; k++)
871 eat(
_(
"command line"), 1);
876 eat(
_(
"command line"), 1);
896 error(
_(
"empty file name"));
899 ?
"file name '%s' begins with '/'"
901 ?
"file name '%s' contains '//'"
902 :
"file name '%s' ends with '/'"),
911 error(
_(
"file name '%s' contains '%.*s' component"),
918 warning(
_(
"file name '%s' component contains leading '-'"),
921 warning(
_(
"file name '%s' contains overlength component"
934 static char const benign[] =
936 "abcdefghijklmnopqrstuvwxyz"
937 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
944 " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
950 unsigned char c = *
cp;
955 ?
_(
"file name '%s' contains byte '%c'")
956 :
_(
"file name '%s' contains byte '\\%o'")),
985 char const *f = target;
1028 return r == 0 ? 0 :
errno;
1088 warning(
_(
"symbolic link used because hard link failed: %s"),
1098 fp =
fopen(target,
"rb");
1121 warning(
_(
"copy used because hard link failed: %s"),
1125 warning(
_(
"copy used because symbolic link failed: %s"),
1182 ((
const struct rule *)
cp2)->r_name);
1207 warning(
_(
"same rule name in multiple files"));
1209 warning(
_(
"same rule name in multiple files"));
1232 for (base = 0; base <
nrules; base = out)
1235 for (out = base + 1; out <
nrules; ++out)
1244 zp->z_nrules = out - base;
1250 if (
zp->z_nrules == 0)
1255 eat(
zp->z_filename,
zp->z_linenum);
1262 if (
zp->z_format_specifier ==
's')
1263 error(
"%s",
_(
"%s in ruleless zone"));
1284 name =
_(
"standard input");
1296 for (num = 1;; ++num)
1304 error(
_(
"line too long"));
1310 while (fields[nfields] !=
NULL)
1314 if (
strcmp(fields[nfields],
"-") == 0)
1315 fields[nfields] = &
nada;
1334 error(
_(
"input line of unknown type"));
1336 switch (
lp->l_value)
1359 _(
"%s: panic: Invalid l_value %d\n"),
1368 error(
_(
"expected continuation line not found"));
1394 if (
string ==
NULL || *
string ==
'\0')
1404 "%" SCNdZIC "%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1411 ok =
'0' <=
xr &&
xr <=
'9';
1416 warning(
_(
"fractional seconds rejected by"
1417 " pre-2018 versions of zic"));
1442 error(
_(
"time overflow"));
1445 ss += 5 + ((ss ^ 1) & (
xr ==
'0')) <=
tenths;
1448 warning(
_(
"values over 24 hours not handled by pre-2007 versions of zic"));
1484 static struct rule r;
1488 error(
_(
"wrong number of fields on Rule line"));
1535 error(
_(
"wrong number of fields on Zone line"));
1541 _(
"\"Zone %s\" line and -l option are mutually exclusive"),
1548 _(
"\"Zone %s\" line and -p option are mutually exclusive"),
1556 error(
_(
"duplicate zone name %s"
1557 " (file \"%s\", line %" PRIdMAX ")"),
1563 return inzsub(fields, nfields,
false);
1571 error(
_(
"wrong number of fields on Zone continuation line"));
1574 return inzsub(fields, nfields,
true);
1582 static struct zone z;
1624 error(
_(
"invalid abbreviation format"));
1634 warning(
_(
"format '%s' not handled by pre-2015 versions of zic"),
1662 error(
_(
"Zone continuation line end time is not after end time of previous line"));
1698 error(
_(
"invalid leaping year"));
1726 error(
_(
"invalid month name"));
1729 month =
lp->l_value;
1741 error(
_(
"invalid day of month"));
1747 error(
_(
"time too small"));
1752 error(
_(
"time too large"));
1759 error(
_(
"leap second precedes Epoch"));
1767 error(
_(
"wrong number of fields on Leap line"));
1777 error(
_(
"invalid Rolling/Stationary field on Leap line"));
1787 error(
_(
"invalid CORRECTION field on Leap line"));
1799 error(
_(
"wrong number of fields on Expires line"));
1801 error(
_(
"multiple Expires lines"));
1813 error(
_(
"wrong number of fields on Link line"));
1818 error(
_(
"blank TARGET field on Link line"));
1844 error(
_(
"invalid month name"));
1847 rp->r_month =
lp->l_value;
1848 rp->r_todisstd =
false;
1849 rp->r_todisut =
false;
1857 rp->r_todisstd =
true;
1858 rp->r_todisut =
false;
1862 rp->r_todisstd =
false;
1863 rp->r_todisut =
false;
1869 rp->r_todisstd =
true;
1870 rp->r_todisut =
true;
1884 if (!
rp->r_lowasnum)
1885 switch (
lp->l_value)
1895 _(
"%s: panic: Invalid l_value %d\n"),
1901 error(
_(
"invalid starting year"));
1907 if (!
rp->r_hiwasnum)
1908 switch (
lp->l_value)
1917 rp->r_hiyear =
rp->r_loyear;
1921 _(
"%s: panic: Invalid l_value %d\n"),
1927 error(
_(
"invalid ending year"));
1930 if (
rp->r_loyear >
rp->r_hiyear)
1932 error(
_(
"starting year greater than ending year"));
1937 error(
_(
"year type \"%s\" is unsupported; use \"-\" instead"),
1950 rp->r_wday =
lp->l_value;
1969 error(
_(
"invalid day of month"));
1975 error(
_(
"invalid weekday name"));
1979 rp->r_wday =
lp->l_value;
1982 rp->r_dayofmonth <= 0 ||
1985 error(
_(
"invalid day of month"));
1998 unsigned char *
const b = (
unsigned char *)
buf;
2000 for (
i = 0, shift = 24;
i < 4; ++
i, shift -= 8)
2001 b[
i] =
val >> shift;
2009 unsigned char *
const b = (
unsigned char *)
buf;
2011 for (
i = 0, shift = 56;
i < 8; ++
i, shift -= 8)
2012 b[
i] =
val >> shift;
2044 return (
a <
b) ? -1 : (
a >
b);
2060 while (0 < r.count && ats[r.base] < lo)
2066 while (0 < r.leapcount &&
trans[r.leapbase] < lo)
2074 while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
2076 while (0 < r.leapcount && hi + 1 <
trans[r.leapbase + r.leapcount - 1])
2092 static struct tzhead tzh;
2154 warning(
_(
"reference clients mishandle"
2155 " more than %d transition times"),
2158 warning(
_(
"pre-2014 clients may mishandle"
2159 " more than 1200 transition times"));
2212 if (remove(
name) == 0)
2301 error(
_(
"too many transition times"));
2339#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2441#define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
2511 zic_t at = ats[
i] < lo ? lo : ats[
i];
2583 fprintf(fp,
"\n%s\n",
string);
2607 error(
_(
"%%z UT offset magnitude exceeds 99:59:59"));
2615 *p++ =
'0' + offset / 10;
2616 *p++ =
'0' + offset % 10;
2646 if (
zp->z_format_specifier ==
'z')
2666 if (
len > 0 && *
cp ==
'\0')
2690 bool negative = offset < 0;
2732 for (month = 0; month <
rp->r_month; ++month)
2735 if (
rp->r_month <= 1)
2743 int wday =
rp->r_wday;
2774 rp->r_month + 1,
week, wday);
2778 if (
rp->r_todisstd && !
rp->r_isdst)
2806 if (
a->r_hiyear !=
b->r_hiyear)
2807 return a->r_hiyear <
b->r_hiyear ? -1 : 1;
2808 if (
a->r_month -
b->r_month != 0)
2809 return a->r_month -
b->r_month;
2810 return a->r_dayofmonth -
b->r_dayofmonth;
2840 for (
i = 0;
i <
zp->z_nrules; ++
i)
2842 rp = &
zp->z_rules[
i];
2868 for (
i = 0;
i <
zp->z_nrules; ++
i)
2870 rp = &
zp->z_rules[
i];
2881 dstr.r_dayofmonth = 1;
2883 dstr.r_todisstd =
dstr.r_todisut =
false;
2889 stdr.r_dayofmonth = 31;
2891 stdr.r_todisstd =
stdr.r_todisut =
false;
2892 stdr.r_isdst =
false;
2918 -(
zp->z_stdoff +
dstrp->r_save));
2979 int defaulttype = -1;
3014 for (
j = 0;
j <
zp->z_nrules; ++
j)
3016 rp = &
zp->z_rules[
j];
3021 if (
rp->r_lowasnum ||
rp->r_hiwasnum)
3036 _(
"no POSIX environment variable for zone"),
3044 warning(
_(
"%s: pre-%d clients may mishandle"
3045 " distant timestamps"),
3114 eat(
zp->z_filename,
zp->z_linenum);
3117 if (
zp->z_nrules == 0)
3135 if (
useuntil && year >
zp->z_untilrule.r_hiyear)
3143 for (
j = 0;
j <
zp->z_nrules; ++
j)
3145 rp = &
zp->z_rules[
j];
3146 eats(
zp->z_filename,
zp->z_linenum,
3147 rp->r_filename,
rp->r_linenum);
3148 rp->r_todo = year >=
rp->r_loyear &&
3149 year <=
rp->r_hiyear;
3173 if (!
zp->z_untilrule.r_todisut)
3176 if (!
zp->z_untilrule.r_todisstd)
3186 for (
j = 0;
j <
zp->z_nrules; ++
j)
3188 rp = &
zp->z_rules[
j];
3191 eats(
zp->z_filename,
zp->z_linenum,
3192 rp->r_filename,
rp->r_linenum);
3193 offset =
rp->r_todisut ? 0 :
stdoff;
3194 if (!
rp->r_todisstd)
3209 _(
"two rules for same instant");
3211 eats(
zp->z_filename,
zp->z_linenum,
3212 rp->r_filename,
rp->r_linenum);
3214 rp = &
zp->z_rules[k];
3215 eats(
zp->z_filename,
zp->z_linenum,
3216 rp->r_filename,
rp->r_linenum);
3222 rp = &
zp->z_rules[k];
3231 if (
ktime < starttime)
3254 eats(
zp->z_filename,
zp->z_linenum,
3255 rp->r_filename,
rp->r_linenum);
3257 rp->r_isdst,
rp->r_save,
false);
3258 offset =
oadd(
zp->z_stdoff,
rp->r_save);
3265 rp->r_todisstd,
rp->r_todisut);
3283 eat(
zp->z_filename,
zp->z_linenum);
3285 error(
_(
"cannot determine time zone abbreviation to use just after until time"));
3292 if (defaulttype < 0 && !
isdst)
3305 starttime =
zp->z_untiltime;
3307 starttime =
tadd(starttime, -
save);
3312 if (defaulttype < 0)
3332 xr.r_dayofmonth = 1;
3366 if (!(-1L - 2147483647L <=
utoff &&
utoff <= 2147483647L))
3368 error(
_(
"UT offset out of range"));
3393 error(
_(
"too many local time types"));
3412 error(
_(
"too many leap seconds"));
3441 error(
_(
"Leap seconds too close together"));
3446 last =
corr[
i] += last;
3453 warning(
_(
"\"#expires\" is obsolescent; use \"Expires\""));
3461 error(
_(
"last Leap time does not precede Expires time"));
3633 while (*++
abbr !=
'\0')
3655static const struct lookup *
3672 warning(
_(
"\"%s\" is undocumented; use \"last%s\" instead"),
3711 warning(
_(
"\"%s\" is ambiguous in pre-2017c zic"),
word);
3736 if (*
cp ==
'\0' || *
cp ==
'#')
3738 array[nsubs++] =
dp =
cp;
3741 if ((*
dp = *
cp++) !=
'"')
3744 while ((*
dp = *
cp++) !=
'"')
3749 error(
_(
"Odd number of quotation marks"));
3757 array[nsubs] =
NULL;
3764 error(
_(
"time overflow"));
3847 while (m !=
rp->r_month)
3853 i =
rp->r_dayofmonth;
3860 error(
_(
"use of 2/29 in non leap-year"));
3870#define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3884 while (wday !=
rp->r_wday)
3902 warning(
_(
"rule goes past start/end of month; \
3903will not work with pre-2004 versions of zic"));
3911 return tadd(t,
rp->r_tod);
3927 || *
cp ==
'-' || *
cp ==
'+')
3930 mp =
_(
"time zone abbreviation has fewer than 3 characters");
3932 mp =
_(
"time zone abbreviation has too many characters");
3934 mp =
_(
"time zone abbreviation differs from POSIX standard");
3941 error(
_(
"too many, or too long, time zone abbreviations"));
3996 error(
_(
"%s: Cannot create directory %s: %s"),
#define pg_attribute_printf(f, a)
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#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)
@ WORK_AROUND_QTBUG_53071
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
#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]