From c37fe30ee3a13c98c77a4ec2cafe0671d4173e42 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 truncate with specified start time
The -k option will take a start time in seconds since January 1, 1970 (Unix Epoch) as input. It will strip away historical transition data before the specified start time. The TZif files will be truncated. --- zic.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/zic.c b/zic.c index 2ebc66a..40185b2 100644 --- a/zic.c +++ b/zic.c @@ -610,6 +610,10 @@ static const char * leapsec; static const char * tzdefault; static const char * yitcommand; +/* This is used to truncate tzfiles. Only transitions starting with truncstart + and onward will be kept. */ +static zic_t truncstart; + int main(int argc, char **argv) { @@ -640,7 +644,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) + truncstart = 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 +659,19 @@ _("%s: More than one -d option specified\n"), return EXIT_FAILURE; } break; + case 'k': + if (truncstart == ZIC_MIN) { + truncstart = atoi(optarg); + if (truncstart > ZIC_MAX) + truncstart = ZIC_MAX; + } + 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 +1767,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 +1883,37 @@ writezone(const char *const name, const char *const string, char version, --leapcnt32; ++leapi32; } + + timei = 0; + if (truncstart != ZIC_MIN) { + /* Discard transitions that happened before the truncstart. */ + int nbr_removes; + + nbr_removes = 0; + for (i = timei32; i < timecnt; ++i) + if (ats[i] < truncstart) + ++nbr_removes; + timecnt32 -= nbr_removes; + timei32 += nbr_removes; + + nbr_removes = 0; + for (i = 0; i < timecnt; ++i) + if (ats[i] < truncstart) + ++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] = truncstart; + defaulttype = types[nbr_removes]; + } + + timecnt -= nbr_removes; + timei += nbr_removes; + } + /* ** Remove old file, if any, to snap links. */ @@ -1910,7 +1959,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; -- 2.11.0