summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-07-01 10:10:52 +0000
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-07-01 10:10:52 +0000
commitbdaeafea5dff32ccb479ecf8fe0a3173c995fbf5 (patch)
treeb3c6386c71e7745110576bb858f4da471baac7fc
parent2f15b35352007a7c7a3b58621c199b705571b2cd (diff)
downloadsystemd-bdaeafea5dff32ccb479ecf8fe0a3173c995fbf5.tar.gz
time-util: add variant of timezone_is_valid() that returns errno
This will be useful for tests to skip missing time zones.
-rw-r--r--src/basic/time-util.c43
-rw-r--r--src/basic/time-util.h5
-rw-r--r--src/test/test-time-util.c12
3 files changed, 34 insertions, 26 deletions
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index b2c86a0e41..796caac691 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -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) {
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index cfde189818..2bd947d6a8 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -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);
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
index a40cc52314..ee4d20449f 100644
--- a/src/test/test-time-util.c
+++ b/src/test/test-time-util.c
@@ -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();