]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Use numeric timezone in rrdtool dump XML output (#1173)
authorTobias Oetiker <tobi@oetiker.ch>
Tue, 26 May 2026 14:47:17 +0000 (16:47 +0200)
committerTobias Oetiker <tobi@oetiker.ch>
Tue, 26 May 2026 14:47:17 +0000 (16:47 +0200)
Replace %Z (locale timezone name) with %z (numeric UTC offset, e.g. +0900)
in strftime() calls inside rrd_dump_cb_r(). %Z emits the locale-encoded
timezone name which may contain non-UTF-8 bytes (e.g. CJK locales produce
bytes like 0xB1 0xB1 0xB1 0xEA), invalidating the XML file's UTF-8
declaration and causing 'rrdtool restore' to fail with
'Input is not proper UTF-8'. %z always produces ASCII digits and sign.

Reported by @k79e, fix by @oetiker.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CHANGES
src/rrd_dump.c

diff --git a/CHANGES b/CHANGES
index fe64e8880051d0023c4f0f621f7b7a5ef8eeff58..6f2dbcf73b42d6d24cf1b1186875faca7ed43c5d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,15 @@ RRDtool - master ...
 ====================
 Bugfixes
 --------
+* `rrdtool dump` now uses a numeric UTC offset (`%z`, e.g. `+0900`) instead
+  of the locale timezone name (`%Z`) in XML comments. Locale timezone names
+  can be encoded in a non-UTF-8 encoding (e.g. CJK locales), which breaks
+  the XML declaration and causes `rrdtool restore` to fail with
+  "Input is not proper UTF-8". The numeric offset is always ASCII.
+  Note: existing dump files already containing locale timezone names remain
+  valid XML as long as their encoding matches; newly created dumps will
+  always contain pure ASCII in these comments. Issue #1173
+  reported by @k79e, fix by @oetiker.
 * Pad the Perl `$RRDs::VERSION` / `$RRDp::VERSION` numeric encoding so
   two-digit minor releases compare monotonically. The numeric version
   now uses three-digit zero-padded minor and patch fields, e.g.
index cdee9377210c9a73db187d5cb16de48a2bdc5aa2..c257d9004408b7b917f317ea406362f0c62c29f8 100644 (file)
@@ -127,7 +127,7 @@ int rrd_dump_cb_r(
 
 #ifdef HAVE_STRFTIME
     localtime_r(&rrd.live_head->last_up, &tm);
-    strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
+    strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %z", &tm);
 #else
 # error "Need strftime"
 #endif
@@ -426,7 +426,7 @@ int rrd_dump_cb_r(
             timer++;
 #ifdef HAVE_STRFTIME
             localtime_r(&now, &tm);
-            strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
+            strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %z", &tm);
 #else
 # error "Need strftime"
 #endif