]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/clock-util.c
util: introduce memcmp_safe()
[thirdparty/systemd.git] / src / basic / clock-util.c
index 00f549c023fc9b640aabba36519f4740b398632e..8555cc795251b3ad5f9c0cadfc8e84261c9e23b2 100644 (file)
@@ -1,23 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2010-2012 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <errno.h>
 #include <fcntl.h>
@@ -33,6 +14,7 @@
 #include "fd-util.h"
 #include "macro.h"
 #include "string-util.h"
+#include "util.h"
 
 int clock_get_hwclock(struct tm *tm) {
         _cleanup_close_ int fd = -1;
@@ -70,9 +52,12 @@ int clock_set_hwclock(const struct tm *tm) {
         return 0;
 }
 
-int clock_is_localtime(void) {
+int clock_is_localtime(const char* adjtime_path) {
         _cleanup_fclose_ FILE *f;
 
+        if (!adjtime_path)
+                adjtime_path = "/etc/adjtime";
+
         /*
          * The third line of adjtime is "UTC" or "LOCAL" or nothing.
          *   # /etc/adjtime
@@ -80,7 +65,7 @@ int clock_is_localtime(void) {
          *   0
          *   UTC
          */
-        f = fopen("/etc/adjtime", "re");
+        f = fopen(adjtime_path, "re");
         if (f) {
                 char line[LINE_MAX];
                 bool b;
@@ -89,7 +74,8 @@ int clock_is_localtime(void) {
                         fgets(line, sizeof(line), f) &&
                         fgets(line, sizeof(line), f);
                 if (!b)
-                        return -EIO;
+                        /* less than three lines -> default to UTC */
+                        return 0;
 
                 truncate_nl(line);
                 return streq(line, "LOCAL");
@@ -97,19 +83,20 @@ int clock_is_localtime(void) {
         } else if (errno != ENOENT)
                 return -errno;
 
+        /* adjtime not present -> default to UTC */
         return 0;
 }
 
 int clock_set_timezone(int *min) {
         const struct timeval *tv_null = NULL;
         struct timespec ts;
-        struct tm *tm;
+        struct tm tm;
         int minutesdelta;
         struct timezone tz;
 
         assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
-        assert_se(tm = localtime(&ts.tv_sec));
-        minutesdelta = tm->tm_gmtoff / 60;
+        assert_se(localtime_r(&ts.tv_sec, &tm));
+        minutesdelta = tm.tm_gmtoff / 60;
 
         tz.tz_minuteswest = -minutesdelta;
         tz.tz_dsttime = 0; /* DST_NONE */
@@ -121,7 +108,8 @@ int clock_set_timezone(int *min) {
          * have read from the RTC.
          */
         if (settimeofday(tv_null, &tz) < 0)
-                return -errno;
+                return negative_errno();
+
         if (min)
                 *min = minutesdelta;
         return 0;
@@ -144,3 +132,17 @@ int clock_reset_timewarp(void) {
 
         return 0;
 }
+
+#define TIME_EPOCH_USEC ((usec_t) TIME_EPOCH * USEC_PER_SEC)
+
+int clock_apply_epoch(void) {
+        struct timespec ts;
+
+        if (now(CLOCK_REALTIME) >= TIME_EPOCH_USEC)
+                return 0;
+
+        if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, TIME_EPOCH_USEC)) < 0)
+                return -errno;
+
+        return 1;
+}