diff --git a/src/shared/clock-util.c b/src/shared/clock-util.c index 963a4fd82d9..83662e75c10 100644 --- a/src/shared/clock-util.c +++ b/src/shared/clock-util.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include #include @@ -14,40 +13,6 @@ #include "macro.h" #include "string-util.h" -int clock_get_hwclock(struct tm *tm) { - _cleanup_close_ int fd = -EBADF; - - assert(tm); - - fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); - if (fd < 0) - return -errno; - - /* This leaves the timezone fields of struct tm uninitialized! */ - if (ioctl(fd, RTC_RD_TIME, tm) < 0) - /* Some drivers return -EINVAL in case the time could not be kept, i.e. power loss - * happened. Let's turn that into a clearly recognizable error */ - return errno == EINVAL ? -ENODATA : -errno; - - /* We don't know daylight saving, so we reset this in order not - * to confuse mktime(). */ - tm->tm_isdst = -1; - - return 0; -} - -int clock_set_hwclock(const struct tm *tm) { - _cleanup_close_ int fd = -EBADF; - - assert(tm); - - fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); - if (fd < 0) - return -errno; - - return RET_NERRNO(ioctl(fd, RTC_SET_TIME, tm)); -} - int clock_is_localtime(const char* adjtime_path) { _cleanup_fclose_ FILE *f = NULL; int r; diff --git a/src/shared/clock-util.h b/src/shared/clock-util.h index e224a4741c6..93fbaeb56e7 100644 --- a/src/shared/clock-util.h +++ b/src/shared/clock-util.h @@ -1,12 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include - int clock_is_localtime(const char* adjtime_path); int clock_set_timezone(int *ret_minutesdelta); -int clock_get_hwclock(struct tm *tm); -int clock_set_hwclock(const struct tm *tm); #define EPOCH_CLOCK_FILE "/usr/lib/clock-epoch" #define TIMESYNCD_CLOCK_FILE_DIR "/var/lib/systemd/timesync/" diff --git a/src/timedate/hwclock-util.c b/src/timedate/hwclock-util.c new file mode 100644 index 00000000000..e924f94872b --- /dev/null +++ b/src/timedate/hwclock-util.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include +#include + +#include "errno-util.h" +#include "fd-util.h" +#include "hwclock-util.h" + +int hwclock_get(struct tm *ret) { + _cleanup_close_ int fd = -EBADF; + + assert(ret); + + fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + /* This leaves the timezone fields of struct ret uninitialized! */ + if (ioctl(fd, RTC_RD_TIME, ret) < 0) + /* Some drivers return -EINVAL in case the time could not be kept, i.e. power loss + * happened. Let's turn that into a clearly recognizable error */ + return errno == EINVAL ? -ENODATA : -errno; + + /* We don't know daylight saving, so we reset this in order not + * to confuse mktime(). */ + ret->tm_isdst = -1; + + return 0; +} + +int hwclock_set(const struct tm *tm) { + _cleanup_close_ int fd = -EBADF; + + assert(tm); + + fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + return RET_NERRNO(ioctl(fd, RTC_SET_TIME, tm)); +} diff --git a/src/timedate/hwclock-util.h b/src/timedate/hwclock-util.h new file mode 100644 index 00000000000..8663c026829 --- /dev/null +++ b/src/timedate/hwclock-util.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include + +int hwclock_get(struct tm *ret); +int hwclock_set(const struct tm *tm); diff --git a/src/timedate/meson.build b/src/timedate/meson.build index 48054bb6041..0790695be9c 100644 --- a/src/timedate/meson.build +++ b/src/timedate/meson.build @@ -5,7 +5,11 @@ executables += [ 'name' : 'systemd-timedated', 'dbus' : true, 'conditions' : ['ENABLE_TIMEDATED'], - 'sources' : files('timedated.c'), + 'sources' : files( + 'timedated.c', + 'hwclock-util.c', + ), + }, executable_template + { 'name' : 'timedatectl', diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index e3b4367ec05..7f190388ccc 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -28,6 +28,7 @@ #include "fileio.h" #include "fs-util.h" #include "hashmap.h" +#include "hwclock-util.h" #include "list.h" #include "main-func.h" #include "memory-util.h" @@ -591,7 +592,7 @@ static int property_get_rtc_time( usec_t t = 0; int r; - r = clock_get_hwclock(&tm); + r = hwclock_get(&tm); if (r == -EBUSY) log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp."); else if (r == -ENOENT) @@ -719,7 +720,7 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error * assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); assert_se(localtime_r(&ts.tv_sec, &tm)); - r = clock_set_hwclock(&tm); + r = hwclock_set(&tm); if (r < 0) log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m"); } @@ -792,7 +793,7 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error localtime_or_gmtime_r(&ts.tv_sec, &tm, !c->local_rtc); /* Override the main fields of struct tm, but not the timezone fields */ - r = clock_get_hwclock(&tm); + r = hwclock_get(&tm); if (r < 0) log_debug_errno(r, "Failed to get hardware clock, ignoring: %m"); else { @@ -809,7 +810,7 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error /* Sync RTC from system clock */ localtime_or_gmtime_r(&ts.tv_sec, &tm, !c->local_rtc); - r = clock_set_hwclock(&tm); + r = hwclock_set(&tm); if (r < 0) log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m"); } @@ -902,7 +903,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro /* Sync down to RTC */ localtime_or_gmtime_r(&ts.tv_sec, &tm, !c->local_rtc); - r = clock_set_hwclock(&tm); + r = hwclock_set(&tm); if (r < 0) log_debug_errno(r, "Failed to update hardware clock, ignoring: %m");