summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/basic/time-util.c33
-rw-r--r--src/basic/time-util.h2
-rw-r--r--src/timedate/timedated.c33
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;