The branch main has been updated by trasz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ddedf2a11eb20af1ee52cb3da70a57c21904af8f

commit ddedf2a11eb20af1ee52cb3da70a57c21904af8f
Author:     Edward Tomasz Napierala <tr...@freebsd.org>
AuthorDate: 2021-09-12 03:07:26 +0000
Commit:     Edward Tomasz Napierala <tr...@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.
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to