From: Yu Watanabe Date: Tue, 9 Sep 2025 00:36:07 +0000 (+0900) Subject: time-util: introduce SAVE_TIMEZONE macro X-Git-Tag: v259-rc1~406^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3f561a6247579360099a25d03155f75ca428b9b;p=thirdparty%2Fsystemd.git time-util: introduce SAVE_TIMEZONE macro --- diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 43ef5e42700..bb5ba210b33 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -7,6 +7,7 @@ #include #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; diff --git a/src/basic/time-util.h b/src/basic/time-util.h index d31e62d18ae..da31e29f126 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -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); diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c index 5e01bb2fe32..b036f6aba5e 100644 --- a/src/test/test-time-util.c +++ b/src/test/test-time-util.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include + #include "env-util.h" #include "random-util.h" #include "serialize.h" @@ -11,6 +12,18 @@ #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) {