]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
time-util: introduce SAVE_TIMEZONE macro
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 9 Sep 2025 00:36:07 +0000 (09:36 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 27 Sep 2025 02:51:06 +0000 (11:51 +0900)
src/basic/time-util.c
src/basic/time-util.h
src/test/test-time-util.c

index 43ef5e42700e5c8d0dd7ea88e5d75b17dcafa486..bb5ba210b336dcbdec3b41f42fb4b35f4fd112ab 100644 (file)
@@ -7,6 +7,7 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "env-util.h"
 #include "errno-util.h"
 #include "extract-word.h"
 #include "fd-util.h"
@@ -1592,6 +1593,26 @@ int verify_timezone(const char *name, int log_level) {
         return 0;
 }
 
+void reset_timezonep(char **p) {
+        assert(p);
+
+        (void) set_unset_env("TZ", *p, /* overwrite = */ true);
+        tzset();
+        *p = mfree(*p);
+}
+
+char* save_timezone(void) {
+        const char *e = getenv("TZ");
+        if (!e)
+                return NULL;
+
+        char *s = strdup(e);
+        if (!s)
+                log_debug("Failed to save $TZ=%s, unsetting the environment variable.", e);
+
+        return s;
+}
+
 bool clock_supported(clockid_t clock) {
         struct timespec ts;
 
index d31e62d18ae6088f6d40f061c6d1610e60923f2a..da31e29f1263f99136855bb6b78e8f9ef07e5892 100644 (file)
@@ -163,6 +163,12 @@ static inline bool timezone_is_valid(const char *name, int log_level) {
         return verify_timezone(name, log_level) >= 0;
 }
 
+void reset_timezonep(char **p);
+char* save_timezone(void);
+#define SAVE_TIMEZONE                                                   \
+        _unused_ _cleanup_(reset_timezonep)                             \
+             char *_saved_timezone_ = save_timezone()
+
 bool clock_supported(clockid_t clock);
 
 usec_t usec_shift_clock(usec_t, clockid_t from, clockid_t to);
index 5e01bb2fe3278faff5ada6b6e9d9aac76726e61a..b036f6aba5e7666dfd81d8291b642e1beea258a1 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <stdlib.h>
+
 #include "env-util.h"
 #include "random-util.h"
 #include "serialize.h"
 
 #define TRIAL 100u
 
+static void set_timezone(const char *tz) {
+        if (!tz)
+                ASSERT_OK_ERRNO(unsetenv("TZ"));
+        if (isempty(tz))
+                ASSERT_OK_ERRNO(setenv("TZ", tz, /* overwrite = */ true));
+        else
+                ASSERT_OK_ERRNO(setenv("TZ", strjoina(":", tz), /* overwrite = */ true));
+
+        tzset();
+        log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(tzname[0]), strempty(tzname[1]));
+}
+
 TEST(parse_sec) {
         usec_t u;
 
@@ -445,24 +458,13 @@ TEST(FORMAT_TIMESTAMP) {
 }
 
 static void test_format_timestamp_with_tz_one(const char *tz) {
-        const char *saved_tz, *colon_tz;
-
         if (!timezone_is_valid(tz, LOG_DEBUG))
                 return;
 
-        log_info("/* %s(%s) */", __func__, tz);
-
-        saved_tz = getenv("TZ");
-
-        assert_se(colon_tz = strjoina(":", tz));
-        assert_se(setenv("TZ", colon_tz, 1) >= 0);
-        tzset();
-        log_debug("%s: tzname[0]=%s, tzname[1]=%s", tz, strempty(tzname[0]), strempty(tzname[1]));
+        SAVE_TIMEZONE;
+        set_timezone(tz);
 
         test_format_timestamp_loop();
-
-        assert_se(set_unset_env("TZ", saved_tz, true) == 0);
-        tzset();
 }
 
 TEST(FORMAT_TIMESTAMP_with_tz) {
@@ -984,24 +986,13 @@ TEST(parse_timestamp) {
 }
 
 static void test_parse_timestamp_with_tz_one(const char *tz) {
-        const char *saved_tz, *colon_tz;
-
         if (!timezone_is_valid(tz, LOG_DEBUG))
                 return;
 
-        log_info("/* %s(%s) */", __func__, tz);
-
-        saved_tz = getenv("TZ");
-
-        assert_se(colon_tz = strjoina(":", tz));
-        assert_se(setenv("TZ", colon_tz, 1) >= 0);
-        tzset();
-        log_debug("%s: tzname[0]=%s, tzname[1]=%s", tz, strempty(tzname[0]), strempty(tzname[1]));
+        SAVE_TIMEZONE;
+        set_timezone(tz);
 
         test_parse_timestamp_impl(tz);
-
-        assert_se(set_unset_env("TZ", saved_tz, true) == 0);
-        tzset();
 }
 
 TEST(parse_timestamp_with_tz) {
@@ -1093,7 +1084,7 @@ TEST(usec_shift_clock) {
 }
 
 TEST(in_utc_timezone) {
-        const char *tz = getenv("TZ");
+        SAVE_TIMEZONE;
 
         assert_se(setenv("TZ", ":UTC", 1) >= 0);
         assert_se(in_utc_timezone());
@@ -1106,9 +1097,6 @@ TEST(in_utc_timezone) {
         assert_se(!in_utc_timezone());
         ASSERT_STREQ(tzname[0], "CET");
         ASSERT_STREQ(tzname[1], "CEST");
-
-        assert_se(set_unset_env("TZ", tz, true) == 0);
-        tzset();
 }
 
 TEST(map_clock_usec) {
@@ -1162,14 +1150,12 @@ static void test_timezone_offset_change_one(const char *utc, const char *pretty)
 }
 
 TEST(timezone_offset_change) {
-        const char *tz = getenv("TZ");
+        SAVE_TIMEZONE;
 
         /* See issue #26370. */
 
         if (timezone_is_valid("Africa/Casablanca", LOG_DEBUG)) {
-                assert_se(setenv("TZ", ":Africa/Casablanca", 1) >= 0);
-                tzset();
-                log_debug("Africa/Casablanca: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
+                set_timezone("Africa/Casablanca");
 
                 test_timezone_offset_change_one("Sun 2015-10-25 01:59:59 UTC", "Sun 2015-10-25 02:59:59 +01");
                 test_timezone_offset_change_one("Sun 2015-10-25 02:00:00 UTC", "Sun 2015-10-25 02:00:00 +00");
@@ -1180,9 +1166,7 @@ TEST(timezone_offset_change) {
         }
 
         if (timezone_is_valid("Asia/Atyrau", LOG_DEBUG)) {
-                assert_se(setenv("TZ", ":Asia/Atyrau", 1) >= 0);
-                tzset();
-                log_debug("Asia/Atyrau: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
+                set_timezone("Asia/Atyrau");
 
                 test_timezone_offset_change_one("Sat 2004-03-27 21:59:59 UTC", "Sun 2004-03-28 01:59:59 +04");
                 test_timezone_offset_change_one("Sat 2004-03-27 22:00:00 UTC", "Sun 2004-03-28 03:00:00 +05");
@@ -1191,18 +1175,13 @@ TEST(timezone_offset_change) {
         }
 
         if (timezone_is_valid("Chile/EasterIsland", LOG_DEBUG)) {
-                assert_se(setenv("TZ", ":Chile/EasterIsland", 1) >= 0);
-                tzset();
-                log_debug("Chile/EasterIsland: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
+                set_timezone("Chile/EasterIsland");
 
                 test_timezone_offset_change_one("Sun 1981-10-11 03:59:59 UTC", "Sat 1981-10-10 20:59:59 -07");
                 test_timezone_offset_change_one("Sun 1981-10-11 04:00:00 UTC", "Sat 1981-10-10 22:00:00 -06");
                 test_timezone_offset_change_one("Sun 1982-03-14 02:59:59 UTC", "Sat 1982-03-13 20:59:59 -06");
                 test_timezone_offset_change_one("Sun 1982-03-14 03:00:00 UTC", "Sat 1982-03-13 21:00:00 -06");
         }
-
-        assert_se(set_unset_env("TZ", tz, true) == 0);
-        tzset();
 }
 
 static usec_t absdiff(usec_t a, usec_t b) {