diff options
-rw-r--r-- | src/basic/time-util.c | 33 | ||||
-rw-r--r-- | src/basic/time-util.h | 2 | ||||
-rw-r--r-- | src/timedate/timedated.c | 33 |
3 files changed, 42 insertions, 26 deletions
diff --git a/src/basic/time-util.c b/src/basic/time-util.c index e278196c90..3d8d5d7568 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -26,6 +26,7 @@ #include "util.h" #include "time-util.h" +#include "path-util.h" #include "strv.h" usec_t now(clockid_t clock_id) { @@ -971,7 +972,10 @@ bool timezone_is_valid(const char *name) { const char *p, *t; struct stat st; - if (!name || *name == 0 || *name == '/') + if (isempty(name)) + return false; + + if (name[0] == '/') return false; for (p = name; *p; p++) { @@ -1021,3 +1025,30 @@ clockid_t clock_boottime_or_monotonic(void) { return clock; } + +int get_timezone(char **timezone) { + _cleanup_free_ char *t = NULL; + const char *e; + char *z; + int r; + + r = readlink_malloc("/etc/localtime", &t); + if (r < 0) + return r; /* returns EINVAL if not a symlink */ + + e = path_startswith(t, "/usr/share/zoneinfo/"); + if (!e) + e = path_startswith(t, "../usr/share/zoneinfo/"); + if (!e) + return -EINVAL; + + if (!timezone_is_valid(e)) + return -EINVAL; + + z = strdup(e); + if (!z) + return -ENOMEM; + + *timezone = z; + return 0; +} diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 2aba042217..03a47f310d 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -110,3 +110,5 @@ bool timezone_is_valid(const char *name); clockid_t clock_boottime_or_monotonic(void); #define xstrftime(buf, fmt, tm) assert_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0) + +int get_timezone(char **timezone); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 21d6ee4c0c..42ae70fd1d 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -68,32 +68,15 @@ static int context_read_data(Context *c) { assert(c); - r = readlink_malloc("/etc/localtime", &t); - if (r < 0) { - if (r == -EINVAL) - log_warning("/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); - else - log_warning_errno(r, "Failed to get target of /etc/localtime: %m"); - } else { - const char *e; + r = get_timezone(&t); + if (r == -EINVAL) + log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); + else if (r < 0) + log_warning_errno(r, "Failed to get target of /etc/localtime: %m"); - e = path_startswith(t, "/usr/share/zoneinfo/"); - if (!e) - e = path_startswith(t, "../usr/share/zoneinfo/"); - - if (!e) - log_warning("/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); - else { - c->zone = strdup(e); - if (!c->zone) - return log_oom(); - } - } - - if (isempty(c->zone)) { - free(c->zone); - c->zone = NULL; - } + free(c->zone); + c->zone = t; + t = NULL; c->local_rtc = clock_is_localtime() > 0; |