Date: Mon, 13 Sep 2021 14:42:13 GMT From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: ddedf2a11eb2 - main - tzcode: Implement timezone change detection Message-ID: <202109131442.18DEgDIn043709@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by trasz: URL: https://cgit.FreeBSD.org/src/commit/?id=ddedf2a11eb20af1ee52cb3da70a57c21904af8f commit ddedf2a11eb20af1ee52cb3da70a57c21904af8f Author: Edward Tomasz Napierala <trasz@FreeBSD.org> AuthorDate: 2021-09-12 03:07:26 +0000 Commit: Edward Tomasz Napierala <trasz@FreeBSD.org> CommitDate: 2021-09-12 03:07:58 +0000 tzcode: Implement timezone change detection Implement optional timezone change detection for local time libc functions. This is disabled by default; set WITH_DETECT_TZ_CHANGES to build it. Reviewed By: imp Sponsored by: NetApp, Inc. Sponsored by: Klara, Inc. X-NetApp-PR: #47 Differential Revision: https://reviews.freebsd.org/D30183 --- contrib/tzcode/stdtime/localtime.c | 89 +++++++++++++++++++++++++++++- lib/libc/stdtime/Makefile.inc | 4 ++ share/mk/src.opts.mk | 1 + tools/build/options/WITH_DETECT_TZ_CHANGES | 2 + 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/contrib/tzcode/stdtime/localtime.c b/contrib/tzcode/stdtime/localtime.c index e221c1fa3964..926b24470e19 100644 --- a/contrib/tzcode/stdtime/localtime.c +++ b/contrib/tzcode/stdtime/localtime.c @@ -354,6 +354,45 @@ settzname(void) } } +#ifdef DETECT_TZ_CHANGES +/* + * Determine if there's a change in the timezone since the last time we checked. + * Returns: -1 on error + * 0 if the timezone has not changed + * 1 if the timezone has changed + */ +static int +change_in_tz(const char *name) +{ + static char old_name[PATH_MAX]; + static struct stat old_sb; + struct stat sb; + int error; + + error = stat(name, &sb); + if (error != 0) + return -1; + + if (strcmp(name, old_name) != 0) { + strlcpy(old_name, name, sizeof(old_name)); + old_sb = sb; + return 1; + } + + if (sb.st_dev != old_sb.st_dev || + sb.st_ino != old_sb.st_ino || + sb.st_ctime != old_sb.st_ctime || + sb.st_mtime != old_sb.st_mtime) { + old_sb = sb; + return 1; + } + + return 0; +} +#else /* !DETECT_TZ_CHANGES */ +#define change_in_tz(X) 0 +#endif /* !DETECT_TZ_CHANGES */ + static int differ_by_repeat(const time_t t1, const time_t t0) { @@ -379,6 +418,7 @@ register const int doextend; int stored; int nread; int res; + int ret; union { struct tzhead tzhead; char buf[2 * sizeof(struct tzhead) + @@ -427,6 +467,22 @@ register const int doextend; (void) strcat(fullname, name); name = fullname; } + if (doextend == TRUE) { + /* + * Detect if the timezone file has changed. Check + * 'doextend' to ignore TZDEFRULES; the change_in_tz() + * function can only keep state for a single file. + */ + ret = change_in_tz(name); + if (ret <= 0) { + /* + * Returns -1 if there was an error, + * and 0 if the timezone had not changed. + */ + free(fullname); + return ret; + } + } if ((fid = _open(name, OPEN_MODE)) == -1) { free(fullname); return -1; @@ -1209,12 +1265,43 @@ gmtload(struct state *const sp) (void) tzparse(gmt, sp, TRUE); } +#ifdef DETECT_TZ_CHANGES +static int +recheck_tzdata() +{ + static time_t last_checked; + struct timespec now; + time_t current_time; + int error; + + /* + * We want to recheck the timezone file every 61 sec. + */ + error = clock_gettime(CLOCK_MONOTONIC, &now); + if (error <= 0) { + /* XXX: Can we somehow report this? */ + return 0; + } + + current_time = now.tv_sec; + if ((current_time - last_checked > 61) || + (last_checked > current_time)) { + last_checked = current_time; + return 1; + } + + return 0; +} +#else /* !DETECT_TZ_CHANGES */ +#define recheck_tzdata() 0 +#endif /* !DETECT_TZ_CHANGES */ + static void tzsetwall_basic(int rdlocked) { if (!rdlocked) _RWLOCK_RDLOCK(&lcl_rwlock); - if (lcl_is_set < 0) { + if (lcl_is_set < 0 && recheck_tzdata() == 0) { if (!rdlocked) _RWLOCK_UNLOCK(&lcl_rwlock); return; diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc index fb0d2b934148..3d483469bc97 100644 --- a/lib/libc/stdtime/Makefile.inc +++ b/lib/libc/stdtime/Makefile.inc @@ -12,6 +12,10 @@ CFLAGS+= -I${SRCTOP}/contrib/tzcode/stdtime -I${LIBC_SRCTOP}/stdtime CFLAGS.localtime.c= -fwrapv +.if ${MK_DETECT_TZ_CHANGES} != "no" +CFLAGS+= -DDETECT_TZ_CHANGES +.endif + MAN+= ctime.3 strftime.3 strptime.3 time2posix.3 MAN+= tzfile.5 diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 28e18260affd..ff894d3b3517 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -196,6 +196,7 @@ __DEFAULT_NO_OPTIONS = \ BHYVE_SNAPSHOT \ CLANG_EXTRAS \ CLANG_FORMAT \ + DETECT_TZ_CHANGES \ DTRACE_TESTS \ EXPERIMENTAL \ HESIOD \ diff --git a/tools/build/options/WITH_DETECT_TZ_CHANGES b/tools/build/options/WITH_DETECT_TZ_CHANGES new file mode 100644 index 000000000000..6a2d18473892 --- /dev/null +++ b/tools/build/options/WITH_DETECT_TZ_CHANGES @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Make the time handling code detect changes to the timezone files.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202109131442.18DEgDIn043709>