]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
time-util: add variant of timezone_is_valid() that returns errno
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 1 Jul 2021 10:10:52 +0000 (10:10 +0000)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 1 Jul 2021 10:10:52 +0000 (10:10 +0000)
This will be useful for tests to skip missing time zones.

src/basic/time-util.c
src/basic/time-util.h
src/test/test-time-util.c

index b2c86a0e41e8dadaa2234f83c0f828acb5ff05a9..796caac6917a1ddf65621b9e4046c6faa5fdbe7e 100644 (file)
@@ -1381,7 +1381,7 @@ int get_timezones(char ***ret) {
         return 0;
 }
 
-bool timezone_is_valid(const char *name, int log_level) {
+int verify_timezone(const char *name, int log_level) {
         bool slash = false;
         const char *p, *t;
         _cleanup_close_ int fd = -1;
@@ -1389,26 +1389,26 @@ bool timezone_is_valid(const char *name, int log_level) {
         int r;
 
         if (isempty(name))
-                return false;
+                return -EINVAL;
 
         /* Always accept "UTC" as valid timezone, since it's the fallback, even if user has no timezones installed. */
         if (streq(name, "UTC"))
-                return true;
+                return 0;
 
         if (name[0] == '/')
-                return false;
+                return -EINVAL;
 
         for (p = name; *p; p++) {
                 if (!(*p >= '0' && *p <= '9') &&
                     !(*p >= 'a' && *p <= 'z') &&
                     !(*p >= 'A' && *p <= 'Z') &&
                     !IN_SET(*p, '-', '_', '+', '/'))
-                        return false;
+                        return -EINVAL;
 
                 if (*p == '/') {
 
                         if (slash)
-                                return false;
+                                return -EINVAL;
 
                         slash = true;
                 } else
@@ -1416,38 +1416,31 @@ bool timezone_is_valid(const char *name, int log_level) {
         }
 
         if (slash)
-                return false;
+                return -EINVAL;
 
         if (p - name >= PATH_MAX)
-                return false;
+                return -ENAMETOOLONG;
 
         t = strjoina("/usr/share/zoneinfo/", name);
 
         fd = open(t, O_RDONLY|O_CLOEXEC);
-        if (fd < 0) {
-                log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t);
-                return false;
-        }
+        if (fd < 0)
+                return log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t);
 
         r = fd_verify_regular(fd);
-        if (r < 0) {
-                log_full_errno(log_level, r, "Timezone file '%s' is not  a regular file: %m", t);
-                return false;
-        }
+        if (r < 0)
+                return log_full_errno(log_level, r, "Timezone file '%s' is not  a regular file: %m", t);
 
         r = loop_read_exact(fd, buf, 4, false);
-        if (r < 0) {
-                log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t);
-                return false;
-        }
+        if (r < 0)
+                return log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t);
 
         /* Magic from tzfile(5) */
-        if (memcmp(buf, "TZif", 4) != 0) {
-                log_full(log_level, "Timezone file '%s' has wrong magic bytes", t);
-                return false;
-        }
+        if (memcmp(buf, "TZif", 4) != 0)
+                return log_full_errno(log_level, SYNTHETIC_ERRNO(EIO),
+                                      "Timezone file '%s' has wrong magic bytes", t);
 
-        return true;
+        return 0;
 }
 
 bool clock_boottime_supported(void) {
index cfde189818b934dd607faf1ee447d3b0d6982d86..2bd947d6a8da117e13b9d6d2840626c16f168c74 100644 (file)
@@ -134,7 +134,10 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit);
 int parse_nsec(const char *t, nsec_t *nsec);
 
 int get_timezones(char ***l);
-bool timezone_is_valid(const char *name, int log_level);
+int verify_timezone(const char *name, int log_level);
+static inline bool timezone_is_valid(const char *name, int log_level) {
+        return verify_timezone(name, log_level) >= 0;
+}
 
 bool clock_boottime_supported(void);
 bool clock_supported(clockid_t clock);
index a40cc523142f51c24171f61df4d8cd26a85677b5..ee4d20449f1475bbf9b9a94c74c179f792162801 100644 (file)
@@ -243,6 +243,17 @@ static void test_format_timespan(usec_t accuracy) {
         test_format_timespan_one(USEC_INFINITY, accuracy);
 }
 
+static void test_verify_timezone(void) {
+        log_info("/* %s */", __func__);
+
+        assert_se(verify_timezone("Europe/Berlin", LOG_DEBUG) == 0);
+        assert_se(verify_timezone("Australia/Sydney", LOG_DEBUG) == 0);
+        assert_se(verify_timezone("Europe/Do not exist", LOG_DEBUG) == -EINVAL);
+        assert_se(verify_timezone("Europe/DoNotExist", LOG_DEBUG) == -ENOENT);
+        assert_se(verify_timezone("/DoNotExist", LOG_DEBUG) == -EINVAL);
+        assert_se(verify_timezone("DoNotExist/", LOG_DEBUG) == -EINVAL);
+}
+
 static void test_timezone_is_valid(void) {
         log_info("/* %s */", __func__);
 
@@ -607,6 +618,7 @@ int main(int argc, char *argv[]) {
         test_format_timespan(1);
         test_format_timespan(USEC_PER_MSEC);
         test_format_timespan(USEC_PER_SEC);
+        test_verify_timezone();
         test_timezone_is_valid();
         test_get_timezones();
         test_usec_add();