From 4093e426a42421fd2d8579b07e8edb3fb116f561 Mon Sep 17 00:00:00 2001 From: Christopher Wong <christwo@axis.com> Date: Tue, 5 Feb 2019 15:02:57 +0100 Subject: [PATCH] zic.c: Add -k option to keep specified year and onward
The -k option will take a year as input. It will strip away historical transition data before the specified year. The TZif files will be truncated. --- zic.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/zic.c b/zic.c index 2ebc66a..9a3b1f5 100644 --- a/zic.c +++ b/zic.c @@ -178,6 +178,7 @@ static void mkdirs(char const *, bool); static void newabbr(const char * abbr); static zic_t oadd(zic_t t1, zic_t t2); static void outzone(const struct zone * zp, ptrdiff_t ntzones); +static zic_t ytime(zic_t year); static zic_t rpytime(const struct rule * rp, zic_t wantedy); static void rulesub(struct rule * rp, const char * loyearp, const char * hiyearp, @@ -610,6 +611,10 @@ static const char * leapsec; static const char * tzdefault; static const char * yitcommand; +/* This is used to truncate tzfiles. Only year specified by keepyear and + onward will be kept. Don't expect year to be outside range 0-9999. */ +static zic_t keepyear; + int main(int argc, char **argv) { @@ -640,7 +645,8 @@ main(int argc, char **argv) } else if (strcmp(argv[k], "--help") == 0) { usage(stdout, EXIT_SUCCESS); } - while ((c = getopt(argc, argv, "d:l:L:p:st:vy:")) != EOF && c != -1) + keepyear = ZIC_MIN; + while ((c = getopt(argc, argv, "d:k:l:L:p:st:vy:")) != EOF && c != -1) switch (c) { default: usage(stderr, EXIT_FAILURE); @@ -654,6 +660,22 @@ _("%s: More than one -d option specified\n"), return EXIT_FAILURE; } break; + case 'k': + if (keepyear == ZIC_MIN) { + keepyear = atoi(optarg); + /* Don't expect year to be outside range 0-9999. */ + if (keepyear < 0) + keepyear = 0; + if (keepyear > 9999) + keepyear = 9999; + } + else { + fprintf(stderr, +_("%s: More than one -k option specified\n"), + progname); + return EXIT_FAILURE; + } + break; case 'l': if (lcltime == NULL) lcltime = optarg; @@ -1749,7 +1771,7 @@ writezone(const char *const name, const char *const string, char version, register FILE * fp; register ptrdiff_t i, j; register int leapcnt32, leapi32; - register ptrdiff_t timecnt32, timei32; + register ptrdiff_t timecnt32, timei32, timei; register int pass; static const struct tzhead tzh0; static struct tzhead tzh; @@ -1865,6 +1887,37 @@ writezone(const char *const name, const char *const string, char version, --leapcnt32; ++leapi32; } + + timei = 0; + if (keepyear != ZIC_MIN) { + /* Discard transitions that happened before the keepyear. */ + int nbr_removes; + + nbr_removes = 0; + for (i = timei32; i < timecnt; ++i) + if (ats[i] < ytime(keepyear)) + ++nbr_removes; + timecnt32 -= nbr_removes; + timei32 += nbr_removes; + + nbr_removes = 0; + for (i = 0; i < timecnt; ++i) + if (ats[i] < ytime(keepyear)) + ++nbr_removes; + + if (nbr_removes > 0) { + /* Override the last removed transition time with the first transition + time that is the start point of the truncation range. Set defaulttype + to this first transition time. */ + --nbr_removes; + ats[nbr_removes] = ytime(keepyear); + defaulttype = types[nbr_removes]; + } + + timecnt -= nbr_removes; + timei += nbr_removes; + } + /* ** Remove old file, if any, to snap links. */ @@ -1910,7 +1963,7 @@ writezone(const char *const name, const char *const string, char version, thisleapi = leapi32; thisleapcnt = leapcnt32; } else { - thistimei = 0; + thistimei = timei; thistimecnt = timecnt; toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0; thisleapi = 0; @@ -3107,6 +3160,19 @@ tadd(zic_t t1, zic_t t2) } /* +** Given a year, compute the date (in seconds since January 1, +** 1970, 00:00). +*/ + +static zic_t +ytime(zic_t year) +{ + struct rule xr = { 0 }; + xr.r_dayofmonth = 1; + return rpytime(&xr, year); +} + +/* ** Given a rule, and a year, compute the date (in seconds since January 1, ** 1970, 00:00 LOCAL time) in that year that the rule refers to. */ -- 2.11.0 ?