From b200c2aab04bee6715f3641de0b2ece2ba1ee957 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 5 Mar 2021 15:53:22 +0100 Subject: [PATCH 1/3] build-sys: split _PATH_ADJTIME to two files This patch introduces: * _PATH_HWCLOCK_MODE_FILE for clock mode (UTC or LOCAL), default is _PATH_ADJTIME (/etc/adjtime). * _PATH_HWCLOCK_DRIFT_FILE - optional file for clock drift information, the default is /var/lib/hwclock/drift. If the file does not exist than default to _PATH_HWCLOCK_MODE_FILE. The both files use 'adjtime' file format for better backward compatibility. The file /etc/adjtime is de-facto standard and it's used by more 3rd party utils (e.g. systemd). Unfortunately, keep state files in /etc is bad idea. This change makes /etc/adjtime read-only for UTC / LOCAL info and rest is maintained in /var/lib/hwclock/drift. Note that /var/lib/hwclock/drift is not automatically created. It's up to downstream (or system admin) to create the file, for example by: cp /etc/adjtime /var/lib/hwclock/drift otherwise binary will fall back to /etc/adjtime. This idea makes hwclock backwardly compatible and more portable without recompilation. (This patch does not implement changes for hwclock.) Signed-off-by: Karel Zak --- Makefile.am | 2 ++ configure.ac | 15 ++++++++-- include/pathnames.h | 8 ++--- include/timeutils.h | 4 +++ lib/timeutils.c | 71 +++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 90 insertions(+), 10 deletions(-) diff --git a/Makefile.am b/Makefile.am index 12cb86cba..dca29c604 100644 --- a/Makefile.am +++ b/Makefile.am @@ -141,6 +141,8 @@ edit_cmd = sed \ -e 's|@usrsbin_execdir[@]|$(usrsbin_execdir)|g' \ -e 's|@VERSION[@]|$(VERSION)|g' \ -e 's|@ADJTIME_PATH[@]|$(ADJTIME_PATH)|g' \ + -e 's|@CLOCKMODE_PATH[@]|$(CLOCKMODE_PATH)|g' \ + -e 's|@CLOCKDRIFT_PATH[@]|$(CLOCKDRIFT_PATH)|g' \ -e 's|@LIBUUID_VERSION[@]|$(LIBUUID_VERSION)|g' \ -e 's|@LIBMOUNT_VERSION[@]|$(LIBMOUNT_VERSION)|g' \ -e 's|@LIBMOUNT_MAJOR_VERSION[@]|$(LIBMOUNT_MAJOR_VERSION)|g' \ diff --git a/configure.ac b/configure.ac index 7f59604bd..51ad755aa 100644 --- a/configure.ac +++ b/configure.ac @@ -2572,14 +2572,23 @@ AC_ARG_VAR([SOLIB_LDFLAGS], [LDFLAGS used for shared libraries]) AC_ARG_VAR([ADJTIME_PATH], - [Path to hwclock adjtime file, default /etc/adjtime]) + [Path to adjtime file; fallback if CLOCKMODE_PATH or CLOCKDRIFT_PATH do not exist, default is /etc/adjtime]) AS_IF([test "x$ADJTIME_PATH" = x], [ADJTIME_PATH="/etc/adjtime"]) -AC_DEFINE_UNQUOTED([CONFIG_ADJTIME_PATH], "$ADJTIME_PATH", [Path to hwclock adjtime file]) +AC_DEFINE_UNQUOTED([CONFIG_ADJTIME_FILE], "$ADJTIME_PATH", [Path to adjtime file]) + +AC_ARG_VAR([CLOCKMODE_PATH], + [Path to hwclock utc/local setting file, default ADJTIME_PATH]) +AS_IF([test "x$CLOCKMODE_PATH" = x], [CLOCKMODE_PATH=$ADJTIME_PATH]) +AC_DEFINE_UNQUOTED([CONFIG_HWCLOCK_MODE_FILE], "$CLOCKMODE_PATH", [Path to hwclock utc/local mode file]) + +AC_ARG_VAR([CLOCKDRIFT_PATH], + [Path to hwclock drift status file, default /var/lib/hwclock/drift]) +AS_IF([test "x$CLOCKDRIFT_PATH" = x], [CLOCKDRIFT_PATH="/var/lib/hwclock/drift"]) +AC_DEFINE_UNQUOTED([CONFIG_HWCLOCK_DRIFT_FILE], "$CLOCKDRIFT_PATH", [Path to hwclock drift status file]) LIBS="" - AC_CONFIG_HEADERS([config.h]) # diff --git a/include/pathnames.h b/include/pathnames.h index 9be2baa83..ab718176b 100644 --- a/include/pathnames.h +++ b/include/pathnames.h @@ -156,11 +156,9 @@ #define _PATH_DEV_BYPARTUUID "/dev/disk/by-partuuid" /* hwclock paths */ -#ifdef CONFIG_ADJTIME_PATH -# define _PATH_ADJTIME CONFIG_ADJTIME_PATH -#else -# define _PATH_ADJTIME "/etc/adjtime" -#endif +#define _PATH_HWCLOCK_DRIFT_FILE CONFIG_HWCLOCK_DRIFT_FILE +#define _PATH_HWCLOCK_MODE_FILE CONFIG_HWCLOCK_MODE_FILE +#define _PATH_ADJTIME CONFIG_ADJTIME_FILE #ifdef __ia64__ # define _PATH_RTC_DEV "/dev/efirtc" diff --git a/include/timeutils.h b/include/timeutils.h index e452e556a..379ce9916 100644 --- a/include/timeutils.h +++ b/include/timeutils.h @@ -89,4 +89,8 @@ int strtime_short(const time_t *t, struct timeval *now, int flags, char *buf, si extern time_t timegm(struct tm *tm); #endif +const char *ul_hwclock_get_drift_file(void); +const char *ul_hwclock_get_mode_file(void); +int ul_hwclock_mode_is_utc(const char *modefile, int *rc); + #endif /* UTIL_LINUX_TIME_UTIL_H */ diff --git a/lib/timeutils.c b/lib/timeutils.c index 6f792c0aa..093727f95 100644 --- a/lib/timeutils.c +++ b/lib/timeutils.c @@ -29,6 +29,7 @@ #include "nls.h" #include "strutils.h" #include "timeutils.h" +#include "pathnames.h" #define WHITESPACE " \t\n\r" @@ -568,6 +569,59 @@ time_t timegm(struct tm *tm) } #endif /* HAVE_TIMEGM */ +/* hwclock drift information */ +const char *ul_hwclock_get_drift_file(void) +{ + if (access(_PATH_HWCLOCK_DRIFT_FILE, F_OK) == 0) + return _PATH_HWCLOCK_DRIFT_FILE; + + return ul_hwclock_get_mode_file(); +} + +const char *ul_hwclock_get_mode_file(void) +{ + if (strcmp(_PATH_HWCLOCK_MODE_FILE, _PATH_ADJTIME) != 0 + && access(_PATH_HWCLOCK_MODE_FILE, F_OK) == 0) + return _PATH_HWCLOCK_MODE_FILE; + + return _PATH_ADJTIME; /* backward compatible default */ +} + +int ul_hwclock_mode_is_utc(const char *modefile, int *rc) +{ + FILE *fp = NULL; + char linebuf[8]; + + *rc = EINVAL; + + if (!modefile) + modefile = ul_hwclock_get_mode_file(); + + fp = fopen(modefile, "r"); + if (!fp) { + *rc = errno; + goto dflt; + } + if (skip_fline(fp) || skip_fline(fp)) /* skip two lines */ + goto dflt; + if (!fgets(linebuf, sizeof linebuf, fp)) /* read 3rd line */ + goto dflt; + + fclose(fp); + fp = NULL; + + if (strncmp(linebuf, "LOCAL", 5) == 0) { + *rc = 0; + return 0; + } + if (strncmp(linebuf, "UTC", 3) == 0) + *rc = 0; +dflt: + if (fp) + fclose(fp); + return 1; +} + #ifdef TEST_PROGRAM_TIMEUTILS int main(int argc, char *argv[]) @@ -576,16 +630,29 @@ int main(int argc, char *argv[]) char buf[ISO_BUFSIZ]; if (argc < 2) { - fprintf(stderr, "usage: %s [