summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2017-02-09 11:35:50 +0100
committerKarel Zak2017-02-09 11:35:50 +0100
commit1dc2aaadba3c26beda23d2dcf76c166fac9a71d7 (patch)
treec8230d7500c9882c921aedd3f45391dc2565a0a9
parentbuild-sys: improve detection of the "isnan" function in uClibc (diff)
parenthwclock: remove --compare option (diff)
downloadkernel-qcow2-util-linux-1dc2aaadba3c26beda23d2dcf76c166fac9a71d7.tar.gz
kernel-qcow2-util-linux-1dc2aaadba3c26beda23d2dcf76c166fac9a71d7.tar.xz
kernel-qcow2-util-linux-1dc2aaadba3c26beda23d2dcf76c166fac9a71d7.zip
Merge branch 'hwclock-jwp-reviewed' of git://github.com/kerolasa/lelux-utiliteetit
* 'hwclock-jwp-reviewed' of git://github.com/kerolasa/lelux-utiliteetit: (25 commits) hwclock: remove --compare option hwclock: remove trailing dot from messages that include system error message hwclock: make --date=argument less prone to injection hwclock: fix rtc atexit registration hwclock: clarify cmos inb and outb preprocessor directives hwclock: try RTCGET and RTCSET only when normal rtc fails hwclock: stream line synchronize_to_clock_tick_rtc() hwclock: improve coding style hwclock: remove division by zero [asan] hwclock: add debugging to open_rtc() hwclock: remove magic constants from interpret_date_string() hwclock: use symbolic magic values passed in between functions hwclock: initialize struct adjtime members hwclock: alloate date_resp parsing buffer in interpret_date_string() hwclock: simplify save_adjtime() execution flow hwclock: remove dead code and other minor fixes hwclock: move error messages to determine_clock_access_method() hwclock: clarify set_cmos_epoch() code hwclock: move command-line options to control structure hwclock: remove unnecessary type casts ...
-rw-r--r--Documentation/deprecated.txt5
-rw-r--r--bash-completion/hwclock1
-rw-r--r--configure.ac1
-rw-r--r--include/pathnames.h4
-rw-r--r--include/timeutils.h4
-rw-r--r--lib/timeutils.c19
-rw-r--r--login-utils/utmpdump.c1
-rw-r--r--sys-utils/Makemodule.am2
-rw-r--r--sys-utils/hwclock-cmos.c221
-rw-r--r--sys-utils/hwclock-rtc.c221
-rw-r--r--sys-utils/hwclock.8.in6
-rw-r--r--sys-utils/hwclock.c856
-rw-r--r--sys-utils/hwclock.h70
13 files changed, 639 insertions, 772 deletions
diff --git a/Documentation/deprecated.txt b/Documentation/deprecated.txt
index fba47e0b5..df7f18fbf 100644
--- a/Documentation/deprecated.txt
+++ b/Documentation/deprecated.txt
@@ -8,6 +8,11 @@ since: v2.30
--------------------------
+what: hwclock --compare
+why: Output printed by --compare option was nonesense.
+
+--------------------------
+
what: tailf
why: "tail -f" is better nowadays, tailf has unfixed bugs
diff --git a/bash-completion/hwclock b/bash-completion/hwclock
index de1ac20f3..89b17bd07 100644
--- a/bash-completion/hwclock
+++ b/bash-completion/hwclock
@@ -32,7 +32,6 @@ _hwclock_module()
--systohc
--systz
--adjust
- --compare
--getepoch
--setepoch
--predict
diff --git a/configure.ac b/configure.ac
index 3bb3ba810..af7bd2210 100644
--- a/configure.ac
+++ b/configure.ac
@@ -416,6 +416,7 @@ AC_CHECK_FUNCS([ \
strnlen \
sysconf \
sysinfo \
+ timegm \
usleep \
warn \
warnx \
diff --git a/include/pathnames.h b/include/pathnames.h
index a5e8507e0..de6abe63e 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -195,5 +195,9 @@
/* ctrlaltdel paths */
#define _PATH_PROC_CTRL_ALT_DEL "/proc/sys/kernel/ctrl-alt-del"
+/* hwclock-cmos paths */
+#define _PATH_DEV_PORT "/dev/port"
+#define _PATH_PROC_CPUINFO "/proc/cpuinfo"
+
#endif /* PATHNAMES_H */
diff --git a/include/timeutils.h b/include/timeutils.h
index 00d18200d..85fc228db 100644
--- a/include/timeutils.h
+++ b/include/timeutils.h
@@ -78,4 +78,8 @@ int time_is_thisyear(const time_t *t, struct timeval *now);
int strtime_short(const time_t *t, struct timeval *now, int flags, char *buf, size_t bufsz);
+#ifndef HAVE_TIMEGM
+extern time_t timegm(struct tm *tm);
+#endif
+
#endif /* UTIL_LINUX_TIME_UTIL_H */
diff --git a/lib/timeutils.c b/lib/timeutils.c
index ea5c0aad8..d38970c10 100644
--- a/lib/timeutils.c
+++ b/lib/timeutils.c
@@ -20,6 +20,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
@@ -460,6 +461,24 @@ int strtime_short(const time_t *t, struct timeval *now, int flags, char *buf, si
return rc <= 0 ? -1 : 0;
}
+#ifndef HAVE_TIMEGM
+time_t timegm(struct tm *tm)
+{
+ const char *zone = getenv("TZ");
+ time_t ret;
+
+ setenv("TZ", "", 1);
+ tzset();
+ ret = mktime(tm);
+ if (zone)
+ setenv("TZ", zone, 1);
+ else
+ unsetenv("TZ");
+ tzset();
+ return ret;
+}
+#endif /* HAVE_TIMEGM */
+
#ifdef TEST_PROGRAM_TIMEUTILS
int main(int argc, char *argv[])
diff --git a/login-utils/utmpdump.c b/login-utils/utmpdump.c
index 91eb4fb55..8e4839346 100644
--- a/login-utils/utmpdump.c
+++ b/login-utils/utmpdump.c
@@ -45,6 +45,7 @@
#include "timeutils.h"
#include "xalloc.h"
#include "closestream.h"
+#include "timeutils.h"
static time_t strtotime(const char *s_time)
{
diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am
index 88be83e8c..be643c965 100644
--- a/sys-utils/Makemodule.am
+++ b/sys-utils/Makemodule.am
@@ -423,7 +423,7 @@ hwclock_SOURCES = \
if LINUX
hwclock_SOURCES += sys-utils/hwclock-rtc.c
endif
-hwclock_LDADD = $(LDADD) libcommon.la $(MATH_LIBS)
+hwclock_LDADD = $(LDADD) libcommon.la -lm
if HAVE_AUDIT
hwclock_LDADD += -laudit
endif
diff --git a/sys-utils/hwclock-cmos.c b/sys-utils/hwclock-cmos.c
index 9103b7343..013fe094d 100644
--- a/sys-utils/hwclock-cmos.c
+++ b/sys-utils/hwclock-cmos.c
@@ -54,30 +54,28 @@
#include "c.h"
#include "nls.h"
+#include "pathnames.h"
+/* for inb, outb */
#if defined(__i386__) || defined(__x86_64__)
# ifdef HAVE_SYS_IO_H
# include <sys/io.h>
# elif defined(HAVE_ASM_IO_H)
-# include <asm/io.h> /* for inb, outb */
+# include <asm/io.h>
# else
-/*
- * Disable cmos access; we can no longer use asm/io.h, since the kernel does
- * not export that header.
- */
-#undef __i386__
-#undef __x86_64__
-void outb(int a __attribute__ ((__unused__)),
- int b __attribute__ ((__unused__)))
+# undef __i386__
+# undef __x86_64__
+# warning "disable cmos access - no sys/io.h or asm/io.h"
+void outb(int a __attribute__((__unused__)),
+ int b __attribute__((__unused__)))
{
}
-int inb(int c __attribute__ ((__unused__)))
+int inb(int c __attribute__((__unused__)))
{
return 0;
}
-#endif /* __i386__ __x86_64__ */
-
+# endif /* __i386__ __x86_64__ */
#elif defined(__alpha__)
# ifdef HAVE_SYS_IO_H
# include <sys/io.h>
@@ -87,23 +85,26 @@ extern unsigned int inb(unsigned long port);
extern void outb(unsigned char b, unsigned long port);
extern int iopl(int level);
# endif
-#else
-static void outb(int a __attribute__ ((__unused__)),
- int b __attribute__ ((__unused__)))
+#else /* __alpha__ */
+# warning "disable cmos access - not i386, x86_64, or alpha"
+static void outb(int a __attribute__((__unused__)),
+ int b __attribute__((__unused__)))
{
}
-static int inb(int c __attribute__ ((__unused__)))
+static int inb(int c __attribute__((__unused__)))
{
return 0;
}
-#endif /* __alpha__ */
+#endif /* for inb, outb */
#include "hwclock.h"
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#define IOPL_NOT_IMPLEMENTED -2
+
/*
* The epoch.
*
@@ -152,12 +153,12 @@ static int is_in_cpuinfo(char *fmt, char *str)
{
FILE *cpuinfo;
char field[256];
- char format[256];
+ char format[sizeof(field)];
int found = 0;
sprintf(format, "%s : %s", fmt, "%255s");
- cpuinfo = fopen("/proc/cpuinfo", "r");
+ cpuinfo = fopen(_PATH_PROC_CPUINFO, "r");
if (cpuinfo) {
do {
if (fscanf(cpuinfo, format, field) == 1) {
@@ -175,20 +176,20 @@ static int is_in_cpuinfo(char *fmt, char *str)
* Set cmos_epoch, either from user options, or by asking the kernel, or by
* looking at /proc/cpu_info
*/
-void set_cmos_epoch(int ARCconsole, int SRM)
+void set_cmos_epoch(const struct hwclock_control *ctl)
{
unsigned long epoch;
/* Believe the user */
- if (epoch_option != -1) {
- cmos_epoch = epoch_option;
+ if (ctl->epoch_option) {
+ cmos_epoch = ctl->epoch_option;
return;
}
- if (ARCconsole)
+ if (ctl->ARCconsole)
cmos_epoch = 1980;
- if (ARCconsole || SRM)
+ if (ctl->ARCconsole || ctl->SRM)
return;
#ifdef __linux__
@@ -196,7 +197,7 @@ void set_cmos_epoch(int ARCconsole, int SRM)
* If we can ask the kernel, we don't need guessing from
* /proc/cpuinfo
*/
- if (get_epoch_rtc(&epoch, 1) == 0) {
+ if (get_epoch_rtc(ctl, &epoch, 1) == 0) {
cmos_epoch = epoch;
return;
}
@@ -218,39 +219,36 @@ void set_cmos_epoch(int ARCconsole, int SRM)
* different "epoch" ideas.
*/
if (is_in_cpuinfo("system serial number", "MILO")) {
- ARCconsole = 1;
- if (debug)
+ if (ctl->debug)
printf(_("booted from MILO\n"));
+ /*
+ * See whether we are dealing with a RUFFIAN aka Alpha PC-164
+ * UX (or BX), as they have REALLY different TOY (TimeOfYear)
+ * format: BCD, and not an ARC-style epoch. BCD is detected
+ * dynamically, but we must NOT adjust like ARC.
+ */
+ if (is_in_cpuinfo("system type", "Ruffian")) {
+ if (debug)
+ printf(_("Ruffian BCD clock\n"));
+ return;
+ }
}
- /*
- * See whether we are dealing with a RUFFIAN aka Alpha PC-164 UX (or
- * BX), as they have REALLY different TOY (TimeOfYear) format: BCD,
- * and not an ARC-style epoch. BCD is detected dynamically, but we
- * must NOT adjust like ARC.
- */
- if (ARCconsole && is_in_cpuinfo("system type", "Ruffian")) {
- ARCconsole = 0;
- if (debug)
- printf(_("Ruffian BCD clock\n"));
- }
-
- if (ARCconsole)
- cmos_epoch = 1980;
+ cmos_epoch = 1980;
}
-void set_cmos_access(int Jensen, int funky_toy)
+void set_cmos_access(const struct hwclock_control *ctl)
{
/*
* See whether we're dealing with a Jensen---it has a weird I/O
* system. DEC was just learning how to build Alpha PCs.
*/
- if (Jensen || is_in_cpuinfo("system type", "Jensen")) {
+ if (ctl->Jensen || is_in_cpuinfo("system type", "Jensen")) {
use_dev_port = 1;
clock_ctl_addr = 0x170;
clock_data_addr = 0x171;
- if (debug)
+ if (ctl->debug)
printf(_("clockport adjusted to 0x%x\n"),
clock_ctl_addr);
}
@@ -260,19 +258,19 @@ void set_cmos_access(int Jensen, int funky_toy)
* TOY that must be accessed differently to work correctly.
*/
/* Nautilus stuff reported by Neoklis Kyriazis */
- if (funky_toy ||
+ if (ctl->funky_toy ||
is_in_cpuinfo("system variation", "PC164") ||
is_in_cpuinfo("system variation", "LX164") ||
is_in_cpuinfo("system variation", "SX164") ||
is_in_cpuinfo("system type", "Nautilus")) {
funkyTOY = 1;
- if (debug)
+ if (ctl->debug)
printf(_("funky TOY!\n"));
}
}
#endif /* __alpha */
-#if __alpha__
+#ifdef __alpha__
/*
* The Alpha doesn't allow user-level code to disable interrupts (for good
* reasons). Instead, we ensure atomic operation by performing the operation
@@ -282,13 +280,16 @@ void set_cmos_access(int Jensen, int funky_toy)
* atomically, eventually.
*/
static unsigned long
-atomic(const char *name, unsigned long (*op) (unsigned long), unsigned long arg)
+atomic(const char *name,
+ unsigned long (*op) (const struct hwclock_control *ctl, unsigned long),
+ const struct hwclock_control *ctl,
+ unsigned long arg)
{
unsigned long ts1, ts2, n, v;
for (n = 0; n < 1000; ++n) {
asm volatile ("rpcc %0":"r=" (ts1));
- v = (*op) (arg);
+ v = (*op) (ctl, arg);
asm volatile ("rpcc %0":"r=" (ts2));
if ((ts1 ^ ts2) >> 32 == 0) {
@@ -307,24 +308,26 @@ atomic(const char *name, unsigned long (*op) (unsigned long), unsigned long arg)
*/
static unsigned long
atomic(const char *name __attribute__ ((__unused__)),
- unsigned long (*op) (unsigned long),
+ unsigned long (*op) (const struct hwclock_control *ctl, unsigned long),
+ const struct hwclock_control *ctl,
unsigned long arg)
{
- return (*op) (arg);
+ return (*op) (ctl, arg);
}
#endif
-static inline unsigned long cmos_read(unsigned long reg)
+static inline unsigned long cmos_read(const struct hwclock_control *ctl,
+ unsigned long reg)
{
if (use_dev_port) {
unsigned char v = reg | 0x80;
lseek(dev_port_fd, clock_ctl_addr, 0);
- if (write(dev_port_fd, &v, 1) == -1 && debug)
+ if (write(dev_port_fd, &v, 1) == -1 && ctl->debug)
warn(_("cmos_read(): write to control address %X failed"),
clock_ctl_addr);
lseek(dev_port_fd, clock_data_addr, 0);
- if (read(dev_port_fd, &v, 1) == -1 && debug)
+ if (read(dev_port_fd, &v, 1) == -1 && ctl->debug)
warn(_("cmos_read(): read from data address %X failed"),
clock_data_addr);
return v;
@@ -356,17 +359,18 @@ static inline unsigned long cmos_read(unsigned long reg)
}
}
-static inline unsigned long cmos_write(unsigned long reg, unsigned long val)
+static inline unsigned long cmos_write(const struct hwclock_control *ctl,
+ unsigned long reg, unsigned long val)
{
if (use_dev_port) {
unsigned char v = reg | 0x80;
lseek(dev_port_fd, clock_ctl_addr, 0);
- if (write(dev_port_fd, &v, 1) == -1 && debug)
+ if (write(dev_port_fd, &v, 1) == -1 && ctl->debug)
warn(_("cmos_write(): write to control address %X failed"),
clock_ctl_addr);
v = (val & 0xff);
lseek(dev_port_fd, clock_data_addr, 0);
- if (write(dev_port_fd, &v, 1) == -1 && debug)
+ if (write(dev_port_fd, &v, 1) == -1 && ctl->debug)
warn(_("cmos_write(): write to data address %X failed"),
clock_data_addr);
} else {
@@ -376,7 +380,8 @@ static inline unsigned long cmos_write(unsigned long reg, unsigned long val)
return 0;
}
-static unsigned long cmos_set_time(unsigned long arg)
+static unsigned long cmos_set_time(const struct hwclock_control *ctl,
+ unsigned long arg)
{
unsigned char save_control, save_freq_select, pmbit = 0;
struct tm tm = *(struct tm *)arg;
@@ -399,10 +404,10 @@ static unsigned long cmos_set_time(unsigned long arg)
* 1111 500 milliseconds (maximum, 2 Hz)
* 0110 976.562 microseconds (default 1024 Hz)
*/
- save_control = cmos_read(11); /* tell the clock it's being set */
- cmos_write(11, (save_control | 0x80));
- save_freq_select = cmos_read(10); /* stop and reset prescaler */
- cmos_write(10, (save_freq_select | 0x70));
+ save_control = cmos_read(ctl, 11); /* tell the clock it's being set */
+ cmos_write(ctl, 11, (save_control | 0x80));
+ save_freq_select = cmos_read(ctl, 10); /* stop and reset prescaler */
+ cmos_write(ctl, 10, (save_freq_select | 0x70));
tm.tm_year += TM_EPOCH;
century = tm.tm_year / 100;
@@ -431,15 +436,15 @@ static unsigned long cmos_set_time(unsigned long arg)
BIN_TO_BCD(century);
}
- cmos_write(0, tm.tm_sec);
- cmos_write(2, tm.tm_min);
- cmos_write(4, tm.tm_hour | pmbit);
- cmos_write(6, tm.tm_wday);
- cmos_write(7, tm.tm_mday);
- cmos_write(8, tm.tm_mon);
- cmos_write(9, tm.tm_year);
+ cmos_write(ctl, 0, tm.tm_sec);
+ cmos_write(ctl, 2, tm.tm_min);
+ cmos_write(ctl, 4, tm.tm_hour | pmbit);
+ cmos_write(ctl, 6, tm.tm_wday);
+ cmos_write(ctl, 7, tm.tm_mday);
+ cmos_write(ctl, 8, tm.tm_mon);
+ cmos_write(ctl, 9, tm.tm_year);
if (century_byte)
- cmos_write(century_byte, century);
+ cmos_write(ctl, century_byte, century);
/*
* The kernel sources, linux/arch/i386/kernel/time.c, have the
@@ -452,33 +457,34 @@ static unsigned long cmos_set_time(unsigned long arg)
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
*/
- cmos_write(11, save_control);
- cmos_write(10, save_freq_select);
+ cmos_write(ctl, 11, save_control);
+ cmos_write(ctl, 10, save_freq_select);
return 0;
}
-static int hclock_read(unsigned long reg)
+static int hclock_read(const struct hwclock_control *ctl, unsigned long reg)
{
- return atomic("clock read", cmos_read, (reg));
+ return atomic("clock read", cmos_read, ctl, reg);
}
-static void hclock_set_time(const struct tm *tm)
+static void hclock_set_time(const struct hwclock_control *ctl, const struct tm *tm)
{
- atomic("set time", cmos_set_time, (unsigned long)(tm));
+ atomic("set time", cmos_set_time, ctl, (unsigned long)(tm));
}
-static inline int cmos_clock_busy(void)
+static inline int cmos_clock_busy(const struct hwclock_control *ctl)
{
return
#ifdef __alpha__
/* poll bit 4 (UF) of Control Register C */
- funkyTOY ? (hclock_read(12) & 0x10) :
+ funkyTOY ? (hclock_read(ctl, 12) & 0x10) :
#endif
/* poll bit 7 (UIP) of Control Register A */
- (hclock_read(10) & 0x80);
+ (hclock_read(ctl, 10) & 0x80);
}
-static int synchronize_to_clock_tick_cmos(void)
+static int synchronize_to_clock_tick_cmos(const struct hwclock_control *ctl
+ __attribute__((__unused__)))
{
int i;
@@ -487,12 +493,12 @@ static int synchronize_to_clock_tick_cmos(void)
* weird happens, we have a limit on this loop to reduce the impact
* of this failure.
*/
- for (i = 0; !cmos_clock_busy(); i++)
+ for (i = 0; !cmos_clock_busy(ctl); i++)
if (i >= 10000000)
return 1;
/* Wait for fall. Should be within 2.228 ms. */
- for (i = 0; cmos_clock_busy(); i++)
+ for (i = 0; cmos_clock_busy(ctl); i++)
if (i >= 1000000)
return 1;
return 0;
@@ -514,12 +520,11 @@ static int synchronize_to_clock_tick_cmos(void)
* In practice, the chance of this function returning the wrong time is
* extremely remote.
*/
-static int read_hardware_clock_cmos(struct tm *tm)
+static int read_hardware_clock_cmos(const struct hwclock_control *ctl
+ __attribute__((__unused__)), struct tm *tm)
{
bool got_time = FALSE;
- unsigned char status, pmbit;
-
- status = pmbit = 0; /* just for gcc */
+ unsigned char status = 0, pmbit = 0;
while (!got_time) {
/*
@@ -536,25 +541,25 @@ static int read_hardware_clock_cmos(struct tm *tm)
* at first, the clock has changed while we were running. We
* check for that too, and if it happens, we start over.
*/
- if (!cmos_clock_busy()) {
+ if (!cmos_clock_busy(ctl)) {
/* No clock update in progress, go ahead and read */
- tm->tm_sec = hclock_read(0);
- tm->tm_min = hclock_read(2);
- tm->tm_hour = hclock_read(4);
- tm->tm_wday = hclock_read(6);
- tm->tm_mday = hclock_read(7);
- tm->tm_mon = hclock_read(8);
- tm->tm_year = hclock_read(9);
- status = hclock_read(11);
+ tm->tm_sec = hclock_read(ctl, 0);
+ tm->tm_min = hclock_read(ctl, 2);
+ tm->tm_hour = hclock_read(ctl, 4);
+ tm->tm_wday = hclock_read(ctl, 6);
+ tm->tm_mday = hclock_read(ctl, 7);
+ tm->tm_mon = hclock_read(ctl, 8);
+ tm->tm_year = hclock_read(ctl, 9);
+ status = hclock_read(ctl, 11);
#if 0
if (century_byte)
- century = hclock_read(century_byte);
+ century = hclock_read(ctl, century_byte);
#endif
/*
* Unless the clock changed while we were reading,
* consider this a good clock read .
*/
- if (tm->tm_sec == hclock_read(0))
+ if (tm->tm_sec == hclock_read(ctl, 0))
got_time = TRUE;
}
/*
@@ -602,10 +607,12 @@ static int read_hardware_clock_cmos(struct tm *tm)
return 0;
}
-static int set_hardware_clock_cmos(const struct tm *new_broken_time)
+static int set_hardware_clock_cmos(const struct hwclock_control *ctl
+ __attribute__((__unused__)),
+ const struct tm *new_broken_time)
{
- hclock_set_time(new_broken_time);
+ hclock_set_time(ctl, new_broken_time);
return 0;
}
@@ -625,7 +632,7 @@ static int i386_iopl(const int level __attribute__ ((__unused__)))
#else
static int i386_iopl(const int level __attribute__ ((__unused__)))
{
- return -2;
+ return IOPL_NOT_IMPLEMENTED;
}
#endif
@@ -634,19 +641,19 @@ static int get_permissions_cmos(void)
int rc;
if (use_dev_port) {
- if ((dev_port_fd = open("/dev/port", O_RDWR)) < 0) {
- warn(_("cannot open %s"), "/dev/port");
+ if ((dev_port_fd = open(_PATH_DEV_PORT, O_RDWR)) < 0) {
+ warn(_("cannot open %s"), _PATH_DEV_PORT);
rc = 1;
} else
rc = 0;
} else {
rc = i386_iopl(3);
- if (rc == -2) {
+ if (rc == IOPL_NOT_IMPLEMENTED) {
warnx(_("I failed to get permission because I didn't try."));
} else if (rc != 0) {
rc = errno;
warn(_("unable to get I/O port access: "
- "the iopl(3) call failed."));
+ "the iopl(3) call failed"));
if (rc == EPERM && geteuid())
warnx(_("Probably you need root privileges.\n"));
}
@@ -654,7 +661,7 @@ static int get_permissions_cmos(void)
return rc ? 1 : 0;
}
-static struct clock_ops cmos = {
+static struct clock_ops cmos_interface = {
N_("Using direct I/O instructions to ISA clock."),
get_permissions_cmos,
read_hardware_clock_cmos,
@@ -668,11 +675,11 @@ static struct clock_ops cmos = {
*/
struct clock_ops *probe_for_cmos_clock(void)
{
- int have_cmos =
+ static const int have_cmos =
#if defined(__i386__) || defined(__alpha__) || defined(__x86_64__)
TRUE;
#else
FALSE;
#endif
- return have_cmos ? &cmos : NULL;
+ return have_cmos ? &cmos_interface : NULL;
}
diff --git a/sys-utils/hwclock-rtc.c b/sys-utils/hwclock-rtc.c
index 3e32399a3..411ec433a 100644
--- a/sys-utils/hwclock-rtc.c
+++ b/sys-utils/hwclock-rtc.c
@@ -38,6 +38,7 @@
# include <asm/rtc.h>
#endif
*/
+#ifdef __sparc__
/* The following is roughly equivalent */
struct sparc_rtc_time
{
@@ -49,20 +50,8 @@ struct sparc_rtc_time
int month; /* Month of year 1-12 */
int year; /* Year 0-99 */
};
-
#define RTCGET _IOR('p', 20, struct sparc_rtc_time)
#define RTCSET _IOW('p', 21, struct sparc_rtc_time)
-
-/* non-sparc stuff */
-#if 0
-# include <linux/version.h>
-/*
- * Check if the /dev/rtc interface is available in this version of the
- * system headers. 131072 is linux 2.0.0.
- */
-# if LINUX_VERSION_CODE >= 131072
-# include <linux/mc146818rtc.h>
-# endif
#endif
/*
@@ -104,8 +93,7 @@ struct linux_rtc_time {
*/
/* default or user defined dev (by hwclock --rtc=<path>) */
-char *rtc_dev_name;
-
+static const char *rtc_dev_name;
static int rtc_dev_fd = -1;
static void close_rtc(void)
@@ -115,52 +103,53 @@ static void close_rtc(void)
rtc_dev_fd = -1;
}
-static int open_rtc(void)
+static int open_rtc(const struct hwclock_control *ctl)
{
- char *fls[] = {
+ static const char *fls[] = {
#ifdef __ia64__
"/dev/efirtc",
"/dev/misc/efirtc",
#endif
"/dev/rtc",
"/dev/rtc0",
- "/dev/misc/rtc",
- NULL
+ "/dev/misc/rtc"
};
- char **p;
+ size_t i;
if (rtc_dev_fd != -1)
return rtc_dev_fd;
/* --rtc option has been given */
- if (rtc_dev_name)
+ if (ctl->rtc_dev_name) {
+ rtc_dev_name = ctl->rtc_dev_name;
rtc_dev_fd = open(rtc_dev_name, O_RDONLY);
- else {
- for (p = fls; *p; ++p) {
- rtc_dev_fd = open(*p, O_RDONLY);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(fls); i++) {
+ if (ctl->debug)
+ printf(_("Trying to open: %s\n"), fls[i]);
+ rtc_dev_fd = open(fls[i], O_RDONLY);
if (rtc_dev_fd < 0
&& (errno == ENOENT || errno == ENODEV))
continue;
- rtc_dev_name = *p;
+ rtc_dev_name = fls[i];
break;
}
if (rtc_dev_fd < 0)
rtc_dev_name = *fls; /* default for error messages */
}
-
- if (rtc_dev_fd != 1)
+ if (rtc_dev_fd != -1)
atexit(close_rtc);
return rtc_dev_fd;
}
-static int open_rtc_or_exit(void)
+static int open_rtc_or_exit(const struct hwclock_control *ctl)
{
- int rtc_fd = open_rtc();
+ int rtc_fd = open_rtc(ctl);
if (rtc_fd < 0) {
- warn(_("cannot open %s"), rtc_dev_name);
- hwclock_exit(EX_OSFILE);
+ warn(_("cannot open rtc device"));
+ hwclock_exit(ctl, EX_OSFILE);
}
return rtc_fd;
}
@@ -169,28 +158,31 @@ static int do_rtc_read_ioctl(int rtc_fd, struct tm *tm)
{
int rc = -1;
char *ioctlname;
-
#ifdef __sparc__
/* some but not all sparcs use a different ioctl and struct */
struct sparc_rtc_time stm;
+#endif
+
+ ioctlname = "RTC_RD_TIME";
+ rc = ioctl(rtc_fd, RTC_RD_TIME, tm);
- ioctlname = "RTCGET";
- rc = ioctl(rtc_fd, RTCGET, &stm);
- if (rc == 0) {
- tm->tm_sec = stm.sec;
- tm->tm_min = stm.min;
- tm->tm_hour = stm.hour;
- tm->tm_mday = stm.dom;
- tm->tm_mon = stm.month - 1;
- tm->tm_year = stm.year - 1900;
- tm->tm_wday = stm.dow - 1;
- tm->tm_yday = -1; /* day in the year */
+#ifdef __sparc__
+ if (rc == -1) { /* sparc sbus */
+ ioctlname = "RTCGET";
+ rc = ioctl(rtc_fd, RTCGET, &stm);
+ if (rc == 0) {
+ tm->tm_sec = stm.sec;
+ tm->tm_min = stm.min;
+ tm->tm_hour = stm.hour;
+ tm->tm_mday = stm.dom;
+ tm->tm_mon = stm.month - 1;
+ tm->tm_year = stm.year - 1900;
+ tm->tm_wday = stm.dow - 1;
+ tm->tm_yday = -1; /* day in the year */
+ }
}
#endif
- if (rc == -1) { /* no sparc, or RTCGET failed */
- ioctlname = "RTC_RD_TIME";
- rc = ioctl(rtc_fd, RTC_RD_TIME, tm);
- }
+
if (rc == -1) {
warn(_("ioctl(%s) to %s to read the time failed"),
ioctlname, rtc_dev_name);
@@ -205,7 +197,8 @@ static int do_rtc_read_ioctl(int rtc_fd, struct tm *tm)
* Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
* we see it.
*/
-static int busywait_for_rtc_clock_tick(const int rtc_fd)
+static int busywait_for_rtc_clock_tick(const struct hwclock_control *ctl,
+ const int rtc_fd)
{
struct tm start_time;
/* The time when we were called (and started waiting) */
@@ -213,13 +206,13 @@ static int busywait_for_rtc_clock_tick(const int rtc_fd)
int rc;
struct timeval begin, now;
- if (debug)
+ if (ctl->debug)
printf(_("Waiting in loop for time from %s to change\n"),
rtc_dev_name);
rc = do_rtc_read_ioctl(rtc_fd, &start_time);
if (rc)
- return 1;
+ return RTC_BUSYWAIT_FAILED;
/*
* Wait for change. Should be within a second, but in case
@@ -234,27 +227,27 @@ static int busywait_for_rtc_clock_tick(const int rtc_fd)
gettimeofday(&now, NULL);
if (time_diff(now, begin) > 1.5) {
warnx(_("Timed out waiting for time change."));
- return 2;
+ return RTC_BUSYWAIT_TIMEOUT;
}
} while (1);
if (rc)
- return 3;
- return 0;
+ return RTC_BUSYWAIT_FAILED;
+ return RTC_BUSYWAIT_OK;
}
/*
* Same as synchronize_to_clock_tick(), but just for /dev/rtc.
*/
-static int synchronize_to_clock_tick_rtc(void)
+static int synchronize_to_clock_tick_rtc(const struct hwclock_control *ctl)
{
int rtc_fd; /* File descriptor of /dev/rtc */
- int ret;
+ int ret = 1;
- rtc_fd = open_rtc();
+ rtc_fd = open_rtc(ctl);
if (rtc_fd == -1) {
- warn(_("cannot open %s"), rtc_dev_name);
- ret = 1;
+ warn(_("cannot open rtc device"));
+ return ret;
} else {
int rc; /* Return code from ioctl */
/* Turn on update interrupts (one per second) */
@@ -268,18 +261,7 @@ static int synchronize_to_clock_tick_rtc(void)
#else
rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
#endif
- if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
- /*
- * This rtc device doesn't have interrupt functions.
- * This is typical on an Alpha, where the Hardware
- * Clock interrupts are used by the kernel for the
- * system clock, so aren't at the user's disposal.
- */
- if (debug)
- printf(_("%s does not have interrupt functions. "),
- rtc_dev_name);
- ret = busywait_for_rtc_clock_tick(rtc_fd);
- } else if (rc == 0) {
+ if (rc != -1) {
/*
* Just reading rtc_fd fails on broken hardware: no
* update interrupt comes and a bootscript with a
@@ -297,35 +279,44 @@ static int synchronize_to_clock_tick_rtc(void)
tv.tv_sec = 10;
tv.tv_usec = 0;
rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
- ret = 1;
- if (rc == -1)
- warn(_("select() to %s to wait for clock tick failed"),
- rtc_dev_name);
+ if (0 < rc)
+ ret = 0;
else if (rc == 0) {
- if (debug)
+ if (ctl->debug)
printf(_("select() to %s to wait for clock tick timed out"),
rtc_dev_name);
} else
- ret = 0;
+ warn(_("select() to %s to wait for clock tick failed"),
+ rtc_dev_name);
/* Turn off update interrupts */
rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
if (rc == -1)
warn(_("ioctl() to %s to turn off update interrupts failed"),
rtc_dev_name);
- } else {
+ } else if (errno == ENOTTY || errno == EINVAL) {
+ /*
+ * This rtc device doesn't have interrupt functions.
+ * This is typical on an Alpha, where the Hardware
+ * Clock interrupts are used by the kernel for the
+ * system clock, so aren't at the user's disposal.
+ */
+ if (ctl->debug)
+ printf(_("%s does not have interrupt functions. "),
+ rtc_dev_name);
+ ret = busywait_for_rtc_clock_tick(ctl, rtc_fd);
+ } else
warn(_("ioctl() to %s to turn on update interrupts "
"failed unexpectedly"), rtc_dev_name);
- ret = 1;
- }
}
return ret;
}
-static int read_hardware_clock_rtc(struct tm *tm)
+static int read_hardware_clock_rtc(const struct hwclock_control *ctl,
+ struct tm *tm)
{
int rtc_fd, rc;
- rtc_fd = open_rtc_or_exit();
+ rtc_fd = open_rtc_or_exit(ctl);
/* Read the RTC time/date, return answer via tm */
rc = do_rtc_read_ioctl(rtc_fd, tm);
@@ -337,16 +328,20 @@ static int read_hardware_clock_rtc(struct tm *tm)
* Set the Hardware Clock to the broken down time <new_broken_time>. Use
* ioctls to "rtc" device /dev/rtc.
*/
-static int set_hardware_clock_rtc(const struct tm *new_broken_time)
+static int set_hardware_clock_rtc(const struct hwclock_control *ctl,
+ const struct tm *new_broken_time)
{
int rc = -1;
int rtc_fd;
char *ioctlname;
- rtc_fd = open_rtc_or_exit();
+ rtc_fd = open_rtc_or_exit(ctl);
+
+ ioctlname = "RTC_SET_TIME";
+ rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time);
#ifdef __sparc__
- {
+ if (rc == -1) { /* sparc sbus */
struct sparc_rtc_time stm;
stm.sec = new_broken_time->tm_sec;
@@ -361,18 +356,14 @@ static int set_hardware_clock_rtc(const struct tm *new_broken_time)
rc = ioctl(rtc_fd, RTCSET, &stm);
}
#endif
- if (rc == -1) { /* no sparc, or RTCSET failed */
- ioctlname = "RTC_SET_TIME";
- rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time);
- }
if (rc == -1) {
- warn(_("ioctl(%s) to %s to set the time failed."),
+ warn(_("ioctl(%s) to %s to set the time failed"),
ioctlname, rtc_dev_name);
- hwclock_exit(EX_IOERR);
+ hwclock_exit(ctl, EX_IOERR);
}
- if (debug)
+ if (ctl->debug)
printf(_("ioctl(%s) was successful.\n"), ioctlname);
return 0;
@@ -383,8 +374,8 @@ static int get_permissions_rtc(void)
return 0;
}
-static struct clock_ops rtc = {
- N_("Using the /dev interface to the clock."),
+static struct clock_ops rtc_interface = {
+ N_("Using the rtc interface to the clock."),
get_permissions_rtc,
read_hardware_clock_rtc,
set_hardware_clock_rtc,
@@ -392,34 +383,34 @@ static struct clock_ops rtc = {
};
/* return &rtc if /dev/rtc can be opened, NULL otherwise */
-struct clock_ops *probe_for_rtc_clock(void)
+struct clock_ops *probe_for_rtc_clock(const struct hwclock_control *ctl)
{
- int rtc_fd = open_rtc();
- if (rtc_fd >= 0)
- return &rtc;
- if (debug)
- warn(_("cannot open %s"), rtc_dev_name);
- return NULL;
+ const int rtc_fd = open_rtc(ctl);
+
+ if (rtc_fd < 0)
+ return NULL;
+ return &rtc_interface;
}
+#ifdef __alpha__
/*
* Get the Hardware Clock epoch setting from the kernel.
*/
-int get_epoch_rtc(unsigned long *epoch_p, int silent)
+int get_epoch_rtc(const struct hwclock_control *ctl, unsigned long *epoch_p,
+ int silent)
{
int rtc_fd;
- rtc_fd = open_rtc();
+ rtc_fd = open_rtc(ctl);
if (rtc_fd < 0) {
if (!silent) {
if (errno == ENOENT)
warnx(_
("To manipulate the epoch value in the kernel, we must "
"access the Linux 'rtc' device driver via the device special "
- "file %s. This file does not exist on this system."),
- rtc_dev_name);
+ "file. This file does not exist on this system."));
else
- warn(_("cannot open %s"), rtc_dev_name);
+ warn(_("cannot open rtc device"));
}
return 1;
}
@@ -431,7 +422,7 @@ int get_epoch_rtc(unsigned long *epoch_p, int silent)
return 1;
}
- if (debug)
+ if (ctl->debug)
printf(_("we have read epoch %lu from %s "
"with RTC_EPOCH_READ ioctl.\n"), *epoch_p,
rtc_dev_name);
@@ -442,40 +433,39 @@ int get_epoch_rtc(unsigned long *epoch_p, int silent)
/*
* Set the Hardware Clock epoch in the kernel.
*/
-int set_epoch_rtc(unsigned long epoch)
+int set_epoch_rtc(const struct hwclock_control *ctl)
{
int rtc_fd;
- if (epoch < 1900) {
+ if (ctl->epoch_option < 1900) {
/* kernel would not accept this epoch value
*
* Bad habit, deciding not to do what the user asks just
* because one believes that the kernel might not like it.
*/
warnx(_("The epoch value may not be less than 1900. "
- "You requested %ld"), epoch);
+ "You requested %ld"), ctl->epoch_option);
return 1;
}
- rtc_fd = open_rtc();
+ rtc_fd = open_rtc(ctl);
if (rtc_fd < 0) {
if (errno == ENOENT)
warnx(_
("To manipulate the epoch value in the kernel, we must "
"access the Linux 'rtc' device driver via the device special "
- "file %s. This file does not exist on this system."),
- rtc_dev_name);
+ "file. This file does not exist on this system."));
else
- warn(_("cannot open %s"), rtc_dev_name);
+ warn(_("cannot open rtc device"));
return 1;
}
- if (debug)
+ if (ctl->debug)
printf(_("setting epoch to %lu "
- "with RTC_EPOCH_SET ioctl to %s.\n"), epoch,
+ "with RTC_EPOCH_SET ioctl to %s.\n"), ctl->epoch_option,
rtc_dev_name);
- if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
+ if (ioctl(rtc_fd, RTC_EPOCH_SET, ctl->epoch_option) == -1) {
if (errno == EINVAL)
warnx(_("The kernel device driver for %s "
"does not have the RTC_EPOCH_SET ioctl."),
@@ -488,3 +478,4 @@ int set_epoch_rtc(unsigned long epoch)
return 0;
}
+#endif /* __alpha__ */
diff --git a/sys-utils/hwclock.8.in b/sys-utils/hwclock.8.in
index 9534c19bc..2dec7823e 100644
--- a/sys-utils/hwclock.8.in
+++ b/sys-utils/hwclock.8.in
@@ -41,12 +41,6 @@ discussion below, under
.BR "The Adjust Function" .
.
.TP
-.BR \-c , \ \-\-compare
-Periodically compare the Hardware Clock to the System Time and output
-the difference every 10 seconds. This will also print the frequency
-offset and tick.
-.
-.TP
.B \-\-getepoch
.TQ
.B \-\-setepoch
diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c
index 10d9e37e9..02a028950 100644
--- a/sys-utils/hwclock.c
+++ b/sys-utils/hwclock.c
@@ -82,25 +82,21 @@
#include "hwclock.h"
#include "timeutils.h"
#include "env.h"
+#include "xalloc.h"
#ifdef HAVE_LIBAUDIT
#include <libaudit.h>
static int hwaudit_fd = -1;
-static int hwaudit_on;
#endif
/* The struct that holds our hardware access routines */
struct clock_ops *ur;
-#define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1));
-
/* Maximal clock adjustment in seconds per day.
(adjtime() glibc call has 2145 seconds limit on i386, so it is good enough for us as well,
43219 is a maximal safe value preventing exact_adjustment overflow.) */
#define MAX_DRIFT 2145.0
-const char *adj_file_name = NULL;
-
struct adjtime {
/*
* This is information we keep in the adjtime file that tells us how
@@ -122,7 +118,7 @@ struct adjtime {
* authority (as opposed to just doing a drift adjustment)
*/
/* line 3 */
- enum a_local_utc { LOCAL, UTC, UNKNOWN } local_utc;
+ enum a_local_utc { UTC = 0, LOCAL, UNKNOWN } local_utc;
/*
* To which time zone, local or UTC, we most recently set the
* hardware clock.
@@ -130,18 +126,6 @@ struct adjtime {
};
/*
- * We are running in debug mode, wherein we put a lot of information about
- * what we're doing to standard output.
- */
-int debug;
-
-/* Workaround for Award 4.50g BIOS bug: keep the year in a file. */
-bool badyear;
-
-/* User-specified epoch, used when rtc fails to return epoch. */
-unsigned long epoch_option = ULONG_MAX;
-
-/*
* Almost all Award BIOS's made between 04/26/94 and 05/31/95 have a nasty
* bug limiting the RTC year byte to the range 94-99. Any year between 2000
* and 2093 gets changed to 2094, every time you start the system.
@@ -230,19 +214,19 @@ static struct timeval time_inc(struct timeval addend, double increment)
}
static bool
-hw_clock_is_utc(const bool utc, const bool local_opt,
+hw_clock_is_utc(const struct hwclock_control *ctl,
const struct adjtime adjtime)
{
bool ret;
- if (utc)
+ if (ctl->utc)
ret = TRUE; /* --utc explicitly given on command line */
- else if (local_opt)
+ else if (ctl->local_opt)
ret = FALSE; /* --localtime explicitly given */
else
/* get info from adjtime file - default is UTC */
ret = (adjtime.local_utc != LOCAL);
- if (debug)
+ if (ctl->debug)
printf(_("Assuming hardware clock is kept in %s time.\n"),
ret ? _("UTC") : _("local"));
return ret;
@@ -257,33 +241,23 @@ hw_clock_is_utc(const bool utc, const bool local_opt,
*
* return value 0 if all OK, !=0 otherwise.
*/
-static int read_adjtime(struct adjtime *adjtime_p)
+static int read_adjtime(const struct hwclock_control *ctl,
+ struct adjtime *adjtime_p)
{
FILE *adjfile;
char line1[81]; /* String: first line of adjtime file */
char line2[81]; /* String: second line of adjtime file */
char line3[81]; /* String: third line of adjtime file */
- long timeval;
-
- if (access(adj_file_name, R_OK) != 0) {
- /* He doesn't have a adjtime file, so we'll use defaults. */
- adjtime_p->drift_factor = 0;
- adjtime_p->last_adj_time = 0;
- adjtime_p->not_adjusted = 0;
- adjtime_p->last_calib_time = 0;
- adjtime_p->local_utc = UTC;
- adjtime_p->dirty = FALSE; /* don't create a zero adjfile */
+ if (access(ctl->adj_file_name, R_OK) != 0)
return 0;
- }
- adjfile = fopen(adj_file_name, "r"); /* open file for reading */
+ adjfile = fopen(ctl->adj_file_name, "r"); /* open file for reading */
if (adjfile == NULL) {
- warn(_("cannot open %s"), adj_file_name);
+ warn(_("cannot open %s"), ctl->adj_file_name);
return EX_OSFILE;
}
-
if (!fgets(line1, sizeof(line1), adjfile))
line1[0] = '\0'; /* In case fgets fails */
if (!fgets(line2, sizeof(line2), adjfile))
@@ -293,20 +267,12 @@ static int read_adjtime(struct adjtime *adjtime_p)
fclose(adjfile);
- /* Set defaults in case values are missing from file */
- adjtime_p->drift_factor = 0;
- adjtime_p->last_adj_time = 0;
- adjtime_p->not_adjusted = 0;
- adjtime_p->last_calib_time = 0;
- timeval = 0;
-
sscanf(line1, "%lf %ld %lf",
&adjtime_p->drift_factor,
- &timeval, &adjtime_p->not_adjusted);
- adjtime_p->last_adj_time = timeval;
+ &adjtime_p->last_adj_time,
+ &adjtime_p->not_adjusted);
- sscanf(line2, "%ld", &timeval);
- adjtime_p->last_calib_time = timeval;
+ sscanf(line2, "%ld", &adjtime_p->last_calib_time);
if (!strcmp(line3, "UTC\n")) {
adjtime_p->local_utc = UTC;
@@ -320,9 +286,7 @@ static int read_adjtime(struct adjtime *adjtime_p)
}
}
- adjtime_p->dirty = FALSE;
-
- if (debug) {
+ if (ctl->debug) {
printf(_
("Last drift adjustment done at %ld seconds after 1969\n"),
(long)adjtime_p->last_adj_time);
@@ -350,16 +314,16 @@ static int read_adjtime(struct adjtime *adjtime_p)
*
* Return 0 if it worked, nonzero if it didn't.
*/
-static int synchronize_to_clock_tick(void)
+static int synchronize_to_clock_tick(const struct hwclock_control *ctl)
{
int rc;
- if (debug)
+ if (ctl->debug)
printf(_("Waiting for clock tick...\n"));
- rc = ur->synchronize_to_clock_tick();
+ rc = ur->synchronize_to_clock_tick(ctl);
- if (debug) {
+ if (ctl->debug) {
if (rc)
printf(_("...synchronization failed\n"));
else
@@ -386,30 +350,14 @@ static int synchronize_to_clock_tick(void)
* return *valid_p == true.
*/
static void
-mktime_tz(struct tm tm, const bool universal,
- bool * valid_p, time_t * systime_p)
+mktime_tz(const struct hwclock_control *ctl, struct tm tm,
+ bool *valid_p, time_t *systime_p)
{
- time_t mktime_result; /* The value returned by our mktime() call */
- char *zone; /* Local time zone name */
-
- /*
- * We use the C library function mktime(), but since it only works
- * on local time zone input, we may have to fake it out by
- * temporarily changing the local time zone to UTC.
- */
- zone = getenv("TZ"); /* remember original time zone */
- if (universal) {
- /* Set timezone to UTC */
- xsetenv("TZ", "", TRUE);
- /*
- * Note: tzset() gets called implicitly by the time code,
- * but only the first time. When changing the environment
- * variable, better call tzset() explicitly.
- */
- tzset();
- }
- mktime_result = mktime(&tm);
- if (mktime_result == -1) {
+ if (ctl->universal)
+ *systime_p = timegm(&tm);
+ else
+ *systime_p = mktime(&tm);
+ if (*systime_p == -1) {
/*
* This apparently (not specified in mktime() documentation)
* means the 'tm' structure does not contain valid values
@@ -417,28 +365,20 @@ mktime_tz(struct tm tm, const bool universal,
* mktime() returns -1).
*/
*valid_p = FALSE;
- *systime_p = 0;
- if (debug)
+ if (ctl->debug)
printf(_("Invalid values in hardware clock: "
"%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"),
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
} else {
*valid_p = TRUE;
- *systime_p = mktime_result;
- if (debug)
+ if (ctl->debug)
printf(_
("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
"%ld seconds since 1969\n"), tm.tm_year + 1900,
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min,
tm.tm_sec, (long)*systime_p);
}
- /* now put back the original zone. */
- if (zone)
- xsetenv("TZ", zone, TRUE);
- else
- unsetenv("TZ");
- tzset();
}
/*
@@ -448,24 +388,25 @@ mktime_tz(struct tm tm, const bool universal,
* clock.
*/
static int
-read_hardware_clock(const bool universal, bool * valid_p, time_t * systime_p)
+read_hardware_clock(const struct hwclock_control *ctl,
+ bool * valid_p, time_t *systime_p)
{
struct tm tm;
int err;
- err = ur->read_hardware_clock(&tm);
+ err = ur->read_hardware_clock(ctl, &tm);
if (err)
return err;
- if (badyear)
+ if (ctl->badyear)
read_date_from_file(&tm);
- if (debug)
+ if (ctl->debug)
printf(_
("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"),
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec);
- mktime_tz(tm, universal, valid_p, systime_p);
+ mktime_tz(ctl, tm, valid_p, systime_p);
return 0;
}
@@ -475,8 +416,7 @@ read_hardware_clock(const bool universal, bool * valid_p, time_t * systime_p)
* according to <universal>.
*/
static void
-set_hardware_clock(const time_t newtime,
- const bool universal, const bool testing)
+set_hardware_clock(const struct hwclock_control *ctl, const time_t newtime)
{
struct tm new_broken_time;
/*
@@ -484,21 +424,21 @@ set_hardware_clock(const time_t newtime,
* in the time zone of caller's choice
*/
- if (universal)
+ if (ctl->universal)
new_broken_time = *gmtime(&newtime);
else
new_broken_time = *localtime(&newtime);
- if (debug)
+ if (ctl->debug)
printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d "
"= %ld seconds since 1969\n"),
new_broken_time.tm_hour, new_broken_time.tm_min,
new_broken_time.tm_sec, (long)newtime);
- if (testing)
+ if (ctl->testing)
printf(_("Clock not changed - testing only.\n"));
else {
- if (badyear) {
+ if (ctl->badyear) {
/*
* Write the real year to a file, then write a fake
* year between 1995 and 1998 to the RTC. This way,
@@ -509,7 +449,7 @@ set_hardware_clock(const time_t newtime,
new_broken_time.tm_year =
95 + ((new_broken_time.tm_year + 1) & 3);
}
- ur->set_hardware_clock(&new_broken_time);
+ ur->set_hardware_clock(ctl, &new_broken_time);
}
}
@@ -532,9 +472,9 @@ set_hardware_clock(const time_t newtime,
* Idea for future enhancement.
*/
static void
-set_hardware_clock_exact(const time_t sethwtime,
- const struct timeval refsystime,
- const bool universal, const bool testing)
+set_hardware_clock_exact(const struct hwclock_control *ctl,
+ const time_t sethwtime,
+ const struct timeval refsystime)
{
/*
* The Hardware Clock can only be set to any integer time plus one
@@ -598,7 +538,7 @@ set_hardware_clock_exact(const time_t sethwtime,
double ticksize;
/* FOR TESTING ONLY: inject random delays of up to 1000ms */
- if (debug >= 10) {
+ if (ctl->debug >= 10) {
int usec = random() % 1000000;
printf(_("sleeping ~%d usec\n"), usec);
xusleep(usec);
@@ -610,20 +550,20 @@ set_hardware_clock_exact(const time_t sethwtime,
prevsystime = nowsystime;
if (ticksize < 0) {
- if (debug)
+ if (ctl->debug)
printf(_("time jumped backward %.6f seconds "
"to %ld.%06ld - retargeting\n"),
- ticksize, (long)nowsystime.tv_sec,
- (long)nowsystime.tv_usec);
+ ticksize, nowsystime.tv_sec,
+ nowsystime.tv_usec);
/* The retarget is handled at the end of the loop. */
} else if (deltavstarget < 0) {
/* deltavstarget < 0 if current time < target time */
- if (debug >= 2)
+ if (ctl->debug >= 2)
printf(_("%ld.%06ld < %ld.%06ld (%.6f)\n"),
- (long)nowsystime.tv_sec,
- (long)nowsystime.tv_usec,
- (long)targetsystime.tv_sec,
- (long)targetsystime.tv_usec,
+ nowsystime.tv_sec,
+ nowsystime.tv_usec,
+ targetsystime.tv_sec,
+ targetsystime.tv_usec,
deltavstarget);
continue; /* not there yet - keep spinning */
} else if (deltavstarget <= target_time_tolerance_secs) {
@@ -634,13 +574,13 @@ set_hardware_clock_exact(const time_t sethwtime,
* We missed our window. Increase the tolerance and
* aim for the next opportunity.
*/
- if (debug)
+ if (ctl->debug)
printf(_("missed it - %ld.%06ld is too far "
"past %ld.%06ld (%.6f > %.6f)\n"),
- (long)nowsystime.tv_sec,
- (long)nowsystime.tv_usec,
- (long)targetsystime.tv_sec,
- (long)targetsystime.tv_usec,
+ nowsystime.tv_sec,
+ nowsystime.tv_usec,
+ targetsystime.tv_sec,
+ targetsystime.tv_usec,
deltavstarget,
target_time_tolerance_secs);
target_time_tolerance_secs += tolerance_incr_secs;
@@ -662,17 +602,17 @@ set_hardware_clock_exact(const time_t sethwtime,
+ (int)(time_diff(nowsystime, refsystime)
- RTC_SET_DELAY_SECS /* don't count this */
+ 0.5 /* for rounding */);
- if (debug)
+ if (ctl->debug)
printf(_("%ld.%06ld is close enough to %ld.%06ld (%.6f < %.6f)\n"
"Set RTC to %ld (%ld + %d; refsystime = %ld.%06ld)\n"),
- (long)nowsystime.tv_sec, (long)nowsystime.tv_usec,
- (long)targetsystime.tv_sec, (long)targetsystime.tv_usec,
+ nowsystime.tv_sec, nowsystime.tv_usec,
+ targetsystime.tv_sec, targetsystime.tv_usec,
deltavstarget, target_time_tolerance_secs,
- (long)newhwtime, (long)sethwtime,
+ newhwtime, sethwtime,
(int)(newhwtime - sethwtime),
- (long)refsystime.tv_sec, (long)refsystime.tv_usec);
+ refsystime.tv_sec, refsystime.tv_usec);
- set_hardware_clock(newhwtime, universal, testing);
+ set_hardware_clock(ctl, newhwtime);
}
/*
@@ -715,49 +655,49 @@ display_time(const bool hclock_valid, struct timeval hwctime)
* If anything goes wrong (and many things can), we return return code 10
* and arbitrary *time_p. Otherwise, return code is 0 and *time_p is valid.
*/
-static int interpret_date_string(const char *date_opt, time_t * const time_p)
+static int interpret_date_string(const struct hwclock_control *ctl,
+ time_t *const time_p)
{
- FILE *date_child_fp;
- char date_resp[100];
+ FILE *date_child_fp = NULL;
+ char *date_command = NULL;
+ char *date_resp = NULL;
+ size_t len = 0;
const char magic[] = "seconds-into-epoch=";
- char date_command[100];
- int retcode; /* our eventual return code */
- int rc; /* local return code */
+ int retcode = 1;
+ long seconds_since_epoch;
- if (date_opt == NULL) {
+ if (!ctl->date_opt) {
warnx(_("No --date option specified."));
- return 14;
- }
-
- /* prevent overflow - a security risk */
- if (strlen(date_opt) > sizeof(date_command) - 50) {
- warnx(_("--date argument too long"));
- return 13;
+ return retcode;
}
/* Quotes in date_opt would ruin the date command we construct. */
- if (strchr(date_opt, '"') != NULL) {
+ if (strchr(ctl->date_opt, '"') != NULL ||
+ strchr(ctl->date_opt, '`') != NULL ||
+ strchr(ctl->date_opt, '$') != NULL) {
warnx(_
("The value of the --date option is not a valid date.\n"
- "In particular, it contains quotation marks."));
- return 12;
+ "In particular, it contains illegal character(s)."));
+ return retcode;
}
- sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s",
- date_opt);
- if (debug)
+ xasprintf(&date_command, "date --date=\"%s\" +%s%%s",
+ ctl->date_opt, magic);
+ if (ctl->debug)
printf(_("Issuing date command: %s\n"), date_command);
date_child_fp = popen(date_command, "r");
if (date_child_fp == NULL) {
warn(_("Unable to run 'date' program in /bin/sh shell. "
"popen() failed"));
- return 10;
+ goto out;
}
- if (!fgets(date_resp, sizeof(date_resp), date_child_fp))
- date_resp[0] = '\0'; /* in case fgets fails */
- if (debug)
+ if (getline(&date_resp, &len, date_child_fp) < 0) {
+ warn(_("getline() failed"));
+ goto out;
+ }
+ if (ctl->debug)
printf(_("response from date command = %s\n"), date_resp);
if (strncmp(date_resp, magic, sizeof(magic) - 1) != 0) {
warnx(_("The date command issued by %s returned "
@@ -765,30 +705,29 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
"The command was:\n %s\n"
"The response was:\n %s"),
program_invocation_short_name, date_command, date_resp);
- retcode = 8;
+ goto out;
+ }
+
+ if (sscanf(date_resp + sizeof(magic) - 1, "%ld", &seconds_since_epoch) < 1) {
+ warnx(_("The date command issued by %s returned "
+ "something other than an integer where the "
+ "converted time value was expected.\n"
+ "The command was:\n %s\n"
+ "The response was:\n %s\n"),
+ program_invocation_short_name, date_command, date_resp);
} else {
- long seconds_since_epoch;
- rc = sscanf(date_resp + sizeof(magic) - 1, "%ld",
- &seconds_since_epoch);
- if (rc < 1) {
- warnx(_("The date command issued by %s returned "
- "something other than an integer where the "
- "converted time value was expected.\n"
- "The command was:\n %s\n"
- "The response was:\n %s\n"),
- program_invocation_short_name, date_command,
- date_resp);
- retcode = 6;
- } else {
- retcode = 0;
- *time_p = seconds_since_epoch;
- if (debug)
- printf(_("date string %s equates to "
- "%ld seconds since 1969.\n"),
- date_opt, (long)*time_p);
- }
+ retcode = 0;
+ *time_p = seconds_since_epoch;
+ if (ctl->debug)
+ printf(_("date string %s equates to "
+ "%ld seconds since 1969.\n"),
+ ctl->date_opt, *time_p);
}
- pclose(date_child_fp);
+ out:
+ free(date_command);
+ free(date_resp);
+ if (date_child_fp)
+ pclose(date_child_fp);
return retcode;
}
@@ -814,8 +753,8 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
* have.
*/
static int
-set_system_clock(const bool hclock_valid, const struct timeval newtime,
- const bool testing, const bool universal)
+set_system_clock(const struct hwclock_control *ctl, const bool hclock_valid,
+ const struct timeval newtime)
{
int retcode;
@@ -839,13 +778,13 @@ set_system_clock(const bool hclock_valid, const struct timeval newtime,
minuteswest -= 60;
#endif
- if (debug) {
+ if (ctl->debug) {
printf(_("Calling settimeofday:\n"));
printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
- (long)newtime.tv_sec, (long)newtime.tv_usec);
+ newtime.tv_sec, newtime.tv_usec);
printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
}
- if (testing) {
+ if (ctl->testing) {
printf(_
("Not setting system clock because running in test mode.\n"));
retcode = 0;
@@ -856,7 +795,7 @@ set_system_clock(const bool hclock_valid, const struct timeval newtime,
* mode does not clobber the Hardware Clock with UTC. This
* is only available on first call of settimeofday after boot.
*/
- if (!universal)
+ if (!ctl->universal)
rc = settimeofday(tv_null, &tz);
if (!rc)
rc = settimeofday(&newtime, &tz);
@@ -887,7 +826,7 @@ set_system_clock(const bool hclock_valid, const struct timeval newtime,
* If 'testing' is true, don't actually update anything -- just say we would
* have.
*/
-static int set_system_clock_timezone(const bool universal, const bool testing)
+static int set_system_clock_timezone(const struct hwclock_control *ctl)
{
int retcode;
struct timeval tv;
@@ -895,14 +834,14 @@ static int set_system_clock_timezone(const bool universal, const bool testing)
int minuteswest;
gettimeofday(&tv, NULL);
- if (debug) {
+ if (ctl->debug) {
struct tm broken_time;
char ctime_now[200];
broken_time = *gmtime(&tv.tv_sec);
strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S",
&broken_time);
- printf(_("Current system time: %ld = %s\n"), (long)tv.tv_sec,
+ printf(_("Current system time: %ld = %s\n"), tv.tv_sec,
ctime_now);
}
@@ -915,12 +854,12 @@ static int set_system_clock_timezone(const bool universal, const bool testing)
minuteswest -= 60;
#endif
- if (debug) {
+ if (ctl->debug) {
struct tm broken_time;
char ctime_now[200];
gettimeofday(&tv, NULL);
- if (!universal)
+ if (!ctl->universal)
tv.tv_sec += minuteswest * 60;
broken_time = *gmtime(&tv.tv_sec);
@@ -930,10 +869,10 @@ static int set_system_clock_timezone(const bool universal, const bool testing)
printf(_("Calling settimeofday:\n"));
printf(_("\tUTC: %s\n"), ctime_now);
printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
- (long)tv.tv_sec, (long)tv.tv_usec);
+ tv.tv_sec, tv.tv_usec);
printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
}
- if (testing) {
+ if (ctl->testing) {
printf(_
("Not setting system clock because running in test mode.\n"));
retcode = 0;
@@ -948,7 +887,7 @@ static int set_system_clock_timezone(const bool universal, const bool testing)
* compensate. If the systemtime is in fact in UTC, then this is wrong
* so we first do a dummy call to make sure the time is not shifted.
*/
- if (universal)
+ if (ctl->universal)
rc = settimeofday(tv_null, &tz_utc);
/* Now we set the real timezone. Due to the above dummy call, this will
@@ -985,33 +924,33 @@ static int set_system_clock_timezone(const bool universal, const bool testing)
* so don't adjust the drift factor.
*/
static void
-adjust_drift_factor(struct adjtime *adjtime_p,
+adjust_drift_factor(const struct hwclock_control *ctl,
+ struct adjtime *adjtime_p,
const struct timeval nowtime,
const bool hclock_valid,
- const struct timeval hclocktime,
- const bool update)
+ const struct timeval hclocktime)
{
- if (!update) {
- if (debug)
+ if (!ctl->update) {
+ if (ctl->debug)
printf(_("Not adjusting drift factor because the "
"--update-drift option was not used.\n"));
} else if (!hclock_valid) {
- if (debug)
+ if (ctl->debug)
printf(_("Not adjusting drift factor because the "
"Hardware Clock previously contained "
"garbage.\n"));
} else if (adjtime_p->last_calib_time == 0) {
- if (debug)
+ if (ctl->debug)
printf(_("Not adjusting drift factor because last "
"calibration time is zero,\n"
"so history is bad and calibration startover "
"is necessary.\n"));
} else if ((hclocktime.tv_sec - adjtime_p->last_calib_time) < 4 * 60 * 60) {
- if (debug)
+ if (ctl->debug)
printf(_("Not adjusting drift factor because it has "
"been less than four hours since the last "
"calibration.\n"));
- } else if (adjtime_p->last_calib_time != 0) {
+ } else {
/*
* At adjustment time we drift correct the hardware clock
* according to the contents of the adjtime file and refresh
@@ -1045,14 +984,14 @@ adjust_drift_factor(struct adjtime *adjtime_p,
drift_factor = adjtime_p->drift_factor + factor_adjust;
if (fabs(drift_factor) > MAX_DRIFT) {
- if (debug)
+ if (ctl->debug)
printf(_("Clock drift factor was calculated as "
"%f seconds/day.\n"
"It is far too much. Resetting to zero.\n"),
drift_factor);
drift_factor = 0;
} else {
- if (debug)
+ if (ctl->debug)
printf(_("Clock drifted %f seconds in the past "
"%f seconds\nin spite of a drift factor of "
"%f seconds/day.\n"
@@ -1082,7 +1021,8 @@ adjust_drift_factor(struct adjtime *adjtime_p,
*
*/
static void
-calculate_adjustment(const double factor,
+calculate_adjustment(const struct hwclock_control *ctl,
+ const double factor,
const time_t last_time,
const double not_adjusted,
const time_t systime, struct timeval *tdrift_p)
@@ -1092,16 +1032,16 @@ calculate_adjustment(const double factor,
exact_adjustment =
((double)(systime - last_time)) * factor / (24 * 60 * 60)
+ not_adjusted;
- tdrift_p->tv_sec = FLOOR(exact_adjustment);
+ tdrift_p->tv_sec = (time_t) floor(exact_adjustment);
tdrift_p->tv_usec = (exact_adjustment -
(double)tdrift_p->tv_sec) * 1E6;
- if (debug) {
- printf(P_("Time since last adjustment is %d second\n",
- "Time since last adjustment is %d seconds\n",
- (int)(systime - last_time)),
- (int)(systime - last_time));
+ if (ctl->debug) {
+ printf(P_("Time since last adjustment is %ld second\n",
+ "Time since last adjustment is %ld seconds\n",
+ (systime - last_time)),
+ (systime - last_time));
printf(_("Calculated Hardware Clock drift is %ld.%06ld seconds\n"),
- (long)tdrift_p->tv_sec, (long)tdrift_p->tv_usec);
+ tdrift_p->tv_sec, tdrift_p->tv_usec);
}
}
@@ -1111,59 +1051,45 @@ calculate_adjustment(const double factor,
* But if the contents are clean (unchanged since read from disk), don't
* bother.
*/
-static void save_adjtime(const struct adjtime adjtime, const bool testing)
+static void save_adjtime(const struct hwclock_control *ctl,
+ const struct adjtime *adjtime)
{
- char newfile[412]; /* Stuff to write to disk file */
+ char *content; /* Stuff to write to disk file */
+ FILE *fp;
+ int err = 0;
- if (adjtime.dirty) {
- /*
- * snprintf is not always available, but this is safe as
- * long as libc does not use more than 100 positions for %ld
- * or %f
- */
- sprintf(newfile, "%f %ld %f\n%ld\n%s\n",
- adjtime.drift_factor,
- (long)adjtime.last_adj_time,
- adjtime.not_adjusted,
- (long)adjtime.last_calib_time,
- (adjtime.local_utc == LOCAL) ? "LOCAL" : "UTC");
-
- if (testing) {
- printf(_
- ("Not updating adjtime file because of testing mode.\n"));
- printf(_("Would have written the following to %s:\n%s"),
- adj_file_name, newfile);
- } else {
- FILE *adjfile;
- int err = 0;
-
- adjfile = fopen(adj_file_name, "w");
- if (adjfile == NULL) {
- warn(_
- ("Could not open file with the clock adjustment parameters "
- "in it (%s) for writing"), adj_file_name);
- err = 1;
- } else {
- if (fputs(newfile, adjfile) < 0) {
- warn(_
- ("Could not update file with the clock adjustment "
- "parameters (%s) in it"),
- adj_file_name);
- err = 1;
- }
- if (close_stream(adjfile) != 0) {
- warn(_
- ("Could not update file with the clock adjustment "
- "parameters (%s) in it"),
- adj_file_name);
- err = 1;
- }
- }
- if (err)
- warnx(_
- ("Drift adjustment parameters not updated."));
- }
+ if (!adjtime->dirty)
+ return;
+
+ xasprintf(&content, "%f %ld %f\n%ld\n%s\n",
+ adjtime->drift_factor,
+ adjtime->last_adj_time,
+ adjtime->not_adjusted,
+ adjtime->last_calib_time,
+ (adjtime->local_utc == LOCAL) ? "LOCAL" : "UTC");
+
+ if (ctl->testing) {
+ printf(_
+ ("Not updating adjtime file because of testing mode.\n"));
+ printf(_("Would have written the following to %s:\n%s"),
+ ctl->adj_file_name, content);
+ free(content);
+ return;
+ }
+
+ fp = fopen(ctl->adj_file_name, "w");
+ if (fp == NULL) {
+ warn(_("Could not open file with the clock adjustment parameters "
+ "in it (%s) for writing"), ctl->adj_file_name);
+ err = 1;
+ } else if (fputs(content, fp) < 0 || close_stream(fp) != 0) {
+ warn(_("Could not update file with the clock adjustment "
+ "parameters (%s) in it"), ctl->adj_file_name);
+ err = 1;
}
+ free(content);
+ if (err)
+ warnx(_("Drift adjustment parameters not updated."));
}
/*
@@ -1191,10 +1117,9 @@ static void save_adjtime(const struct adjtime adjtime, const bool testing)
*
*/
static void
-do_adjustment(struct adjtime *adjtime_p,
+do_adjustment(const struct hwclock_control *ctl, struct adjtime *adjtime_p,
const bool hclock_valid, const struct timeval hclocktime,
- const struct timeval read_time,
- const bool universal, const bool testing)
+ const struct timeval read_time)
{
if (!hclock_valid) {
warnx(_("The Hardware Clock does not contain a valid time, "
@@ -1204,41 +1129,47 @@ do_adjustment(struct adjtime *adjtime_p,
adjtime_p->not_adjusted = 0;
adjtime_p->dirty = TRUE;
} else if (adjtime_p->last_adj_time == 0) {
- if (debug)
+ if (ctl->debug)
printf(_("Not setting clock because last adjustment time is zero, "
"so history is bad.\n"));
} else if (fabs(adjtime_p->drift_factor) > MAX_DRIFT) {
- if (debug)
+ if (ctl->debug)
printf(_("Not setting clock because drift factor %f is far too high.\n"),
adjtime_p->drift_factor);
} else {
- set_hardware_clock_exact(hclocktime.tv_sec,
+ set_hardware_clock_exact(ctl, hclocktime.tv_sec,
time_inc(read_time,
- -(hclocktime.tv_usec / 1E6)),
- universal, testing);
+ -(hclocktime.tv_usec / 1E6)));
adjtime_p->last_adj_time = hclocktime.tv_sec;
adjtime_p->not_adjusted = 0;
adjtime_p->dirty = TRUE;
}
}
-static void determine_clock_access_method(const bool user_requests_ISA)
+static void determine_clock_access_method(const struct hwclock_control *ctl)
{
ur = NULL;
- if (user_requests_ISA)
+ if (ctl->directisa)
ur = probe_for_cmos_clock();
-
#ifdef __linux__
if (!ur)
- ur = probe_for_rtc_clock();
+ ur = probe_for_rtc_clock(ctl);
#endif
+ if (ur) {
+ if (ctl->debug)
+ puts(ur->interface_name);
- if (debug) {
- if (ur)
- puts(_(ur->interface_name));
- else
+ } else {
+ if (ctl->debug)
printf(_("No usable clock interface found.\n"));
+ warnx(_("Cannot access the Hardware Clock via "
+ "any known method."));
+ if (!ctl->debug)
+ warnx(_("Use the --debug option to see the "
+ "details of our search for an access "
+ "method."));
+ hwclock_exit(ctl, EX_SOFTWARE);
}
}
@@ -1250,18 +1181,9 @@ static void determine_clock_access_method(const bool user_requests_ISA)
* Return rc == 0 if everything went OK, rc != 0 if not.
*/
static int
-manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
- const bool set, const time_t set_time,
- const bool hctosys, const bool systohc, const bool systz,
- const struct timeval startup_time,
- const bool utc, const bool local_opt, const bool update,
- const bool testing, const bool predict, const bool get)
+manipulate_clock(const struct hwclock_control *ctl, const time_t set_time,
+ const struct timeval startup_time, struct adjtime *adjtime)
{
- /* Contents of the adjtime file, or what they should be. */
- struct adjtime adjtime = { 0 };
- bool universal;
- /* Set if user lacks necessary authorization to access the clock */
- bool no_auth;
/* The time at which we read the Hardware Clock */
struct timeval read_time;
/*
@@ -1279,42 +1201,28 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
/* local return code */
int rc = 0;
- if (!systz && !predict) {
- no_auth = ur->get_permissions();
- if (no_auth)
+ if (!ctl->systz && !ctl->predict)
+ if (ur->get_permissions())
return EX_NOPERM;
- }
- if (!noadjfile && !(systz && (utc || local_opt))) {
- rc = read_adjtime(&adjtime);
- if (rc)
- return rc;
- } else {
- /* A little trick to avoid writing the file if we don't have to */
- adjtime.dirty = FALSE;
+ if ((ctl->set || ctl->systohc || ctl->adjust) &&
+ (adjtime->local_utc == UTC) != ctl->universal) {
+ adjtime->local_utc = ctl->universal ? UTC : LOCAL;
+ adjtime->dirty = TRUE;
}
- universal = hw_clock_is_utc(utc, local_opt, adjtime);
-
- if ((set || systohc || adjust) &&
- (adjtime.local_utc == UTC) != universal) {
- adjtime.local_utc = universal ? UTC : LOCAL;
- adjtime.dirty = TRUE;
- }
-
- if (show || get || adjust || hctosys || (!noadjfile && !systz && !predict)) {
+ if (ctl->show || ctl->get || ctl->adjust || ctl->hctosys
+ || (!ctl->noadjfile && !ctl->systz && !ctl->predict)) {
/* data from HW-clock are required */
- rc = synchronize_to_clock_tick();
+ rc = synchronize_to_clock_tick(ctl);
/*
- * 2 = synchronization timeout. We don't
- * error out if the user is attempting to
- * set the RTC - the RTC could be
- * functioning but contain invalid time data
- * so we still want to allow a user to set
- * the RTC time.
+ * We don't error out if the user is attempting to set the
+ * RTC and synchronization timeout happens - the RTC could
+ * be functioning but contain invalid time data so we still
+ * want to allow a user to set the RTC time.
*/
- if (rc && rc != 2 && !set && !systohc)
+ if (rc == RTC_BUSYWAIT_FAILED && !ctl->set && !ctl->systohc)
return EX_IOERR;
gettimeofday(&read_time, NULL);
@@ -1324,9 +1232,9 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
* don't bother reading it again.
*/
if (!rc) {
- rc = read_hardware_clock(universal,
- &hclock_valid, &hclocktime.tv_sec);
- if (rc && !set && !systohc)
+ rc = read_hardware_clock(ctl, &hclock_valid,
+ &hclocktime.tv_sec);
+ if (rc && !ctl->set && !ctl->systohc)
return EX_IOERR;
}
}
@@ -1338,33 +1246,32 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
* --predict. For --predict negate the drift correction, because we
* want to 'predict' a future Hardware Clock time that includes drift.
*/
- hclocktime = predict ? t2tv(set_time) : hclocktime;
- calculate_adjustment(adjtime.drift_factor,
- adjtime.last_adj_time,
- adjtime.not_adjusted,
+ hclocktime = ctl->predict ? t2tv(set_time) : hclocktime;
+ calculate_adjustment(ctl, adjtime->drift_factor,
+ adjtime->last_adj_time,
+ adjtime->not_adjusted,
hclocktime.tv_sec, &tdrift);
- if (!show && !predict)
+ if (!ctl->show && !ctl->predict)
hclocktime = time_inc(tdrift, hclocktime.tv_sec);
- if (show || get) {
+ if (ctl->show || ctl->get) {
display_time(hclock_valid,
time_inc(hclocktime, -time_diff
(read_time, startup_time)));
- } else if (set) {
- set_hardware_clock_exact(set_time, startup_time,
- universal, testing);
- if (!noadjfile)
- adjust_drift_factor(&adjtime,
+ } else if (ctl->set) {
+ set_hardware_clock_exact(ctl, set_time, startup_time);
+ if (!ctl->noadjfile)
+ adjust_drift_factor(ctl, adjtime,
time_inc(t2tv(set_time), time_diff
(read_time, startup_time)),
- hclock_valid, hclocktime, update);
- } else if (adjust) {
+ hclock_valid, hclocktime);
+ } else if (ctl->adjust) {
if (tdrift.tv_sec > 0 || tdrift.tv_sec < -1)
- do_adjustment(&adjtime, hclock_valid,
- hclocktime, read_time, universal, testing);
+ do_adjustment(ctl, adjtime, hclock_valid,
+ hclocktime, read_time);
else
printf(_("Needed adjustment is less than one second, "
"so not setting clock.\n"));
- } else if (systohc) {
+ } else if (ctl->systohc) {
struct timeval nowtime, reftime;
/*
* We can only set_hardware_clock_exact to a
@@ -1375,37 +1282,34 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
gettimeofday(&nowtime, NULL);
reftime.tv_sec = nowtime.tv_sec;
reftime.tv_usec = 0;
- set_hardware_clock_exact((time_t)
- reftime.tv_sec,
- reftime, universal, testing);
- if (!noadjfile)
- adjust_drift_factor(&adjtime, nowtime,
- hclock_valid, hclocktime, update);
- } else if (hctosys) {
- rc = set_system_clock(hclock_valid, hclocktime,
- testing, universal);
+ set_hardware_clock_exact(ctl, (time_t) reftime.tv_sec, reftime);
+ if (!ctl->noadjfile)
+ adjust_drift_factor(ctl, adjtime, nowtime,
+ hclock_valid, hclocktime);
+ } else if (ctl->hctosys) {
+ rc = set_system_clock(ctl, hclock_valid, hclocktime);
if (rc) {
printf(_("Unable to set system clock.\n"));
return rc;
}
- } else if (systz) {
- rc = set_system_clock_timezone(universal, testing);
+ } else if (ctl->systz) {
+ rc = set_system_clock_timezone(ctl);
if (rc) {
printf(_("Unable to set system clock.\n"));
return rc;
}
- } else if (predict) {
+ } else if (ctl->predict) {
hclocktime = time_inc(hclocktime, (double)
-(tdrift.tv_sec + tdrift.tv_usec / 1E6));
- if (debug) {
+ if (ctl->debug) {
printf(_
("At %ld seconds after 1969, RTC is predicted to read %ld seconds after 1969.\n"),
- set_time, (long)hclocktime.tv_sec);
+ set_time, hclocktime.tv_sec);
}
display_time(TRUE, hclocktime);
}
- if (!noadjfile)
- save_adjtime(adjtime, testing);
+ if (!ctl->noadjfile)
+ save_adjtime(ctl, adjtime);
return 0;
}
@@ -1423,10 +1327,7 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
*/
# ifndef __alpha__
static void
-manipulate_epoch(const bool getepoch __attribute__ ((__unused__)),
- const bool setepoch __attribute__ ((__unused__)),
- const unsigned long epoch_opt __attribute__ ((__unused__)),
- const bool testing __attribute__ ((__unused__)))
+manipulate_epoch(const struct hwclock_control *ctl __attribute__((__unused__)))
{
warnx(_("The kernel keeps an epoch value for the Hardware Clock "
"only on an Alpha machine.\nThis copy of hwclock was built for "
@@ -1435,30 +1336,27 @@ manipulate_epoch(const bool getepoch __attribute__ ((__unused__)),
}
# else
static void
-manipulate_epoch(const bool getepoch,
- const bool setepoch,
- const unsigned long epoch_opt,
- const bool testing)
+manipulate_epoch(const struct hwclock_control *ctl)
{
- if (getepoch) {
+ if (ctl->getepoch) {
unsigned long epoch;
- if (get_epoch_rtc(&epoch, 0))
+ if (get_epoch_rtc(ctl, &epoch, 0))
warnx(_
("Unable to get the epoch value from the kernel."));
else
printf(_("Kernel is assuming an epoch value of %lu\n"),
epoch);
- } else if (setepoch) {
- if (epoch_opt == ULONG_MAX)
+ } else if (ctl->setepoch) {
+ if (ctl->epoch_option == 0)
warnx(_
("To set the epoch value, you must use the 'epoch' "
"option to tell to what value to set it."));
- else if (testing)
+ else if (ctl->testing)
printf(_
("Not setting the epoch to %lu - testing only.\n"),
- epoch_opt);
- else if (set_epoch_rtc(epoch_opt))
+ ctl->epoch_option);
+ else if (set_epoch_rtc(ctl))
printf(_
("Unable to set the epoch value in the kernel.\n"));
}
@@ -1466,70 +1364,6 @@ manipulate_epoch(const bool getepoch,
# endif /* __alpha__ */
#endif /* __linux__ */
-/*
- * Compare the system and CMOS time and output the drift
- * in 10 second intervals.
- */
-static int compare_clock (const bool utc, const bool local_opt)
-{
- struct tm tm;
- struct timeval tv;
- struct adjtime adjtime;
- double time1_sys, time2_sys;
- time_t time1_hw, time2_hw;
- bool hclock_valid = FALSE, universal, first_pass = TRUE;
- int rc;
-
- if (ur->get_permissions())
- return EX_NOPERM;
-
- /* dummy call for increased precision */
- gettimeofday(&tv, NULL);
-
- rc = read_adjtime(&adjtime);
- if (rc)
- return rc;
-
- universal = hw_clock_is_utc(utc, local_opt, adjtime);
-
- synchronize_to_clock_tick();
- ur->read_hardware_clock(&tm);
-
- gettimeofday(&tv, NULL);
- time1_sys = tv.tv_sec + tv.tv_usec / 1000000.0;
-
- mktime_tz(tm, universal, &hclock_valid, &time1_hw);
-
- while (1) {
- double res;
-
- synchronize_to_clock_tick();
- ur->read_hardware_clock(&tm);
-
- gettimeofday(&tv, NULL);
- time2_sys = tv.tv_sec + tv.tv_usec / 1000000.0;
-
- mktime_tz(tm, universal, &hclock_valid, &time2_hw);
-
- res = (((double) time1_hw - time1_sys) -
- ((double) time2_hw - time2_sys))
- / (double) (time2_hw - time1_hw);
-
- if (!first_pass)
- printf("%10.0f %10.6f %15.0f %4.0f\n",
- (double) time2_hw, time2_sys, res * 1e6, res *1e4);
- else {
- first_pass = FALSE;
- printf("hw-time system-time freq-offset-ppm tick\n");
- printf("%10.0f %10.6f\n", (double) time1_hw, time1_sys);
- }
- fflush(stdout);
- sleep(10);
- }
-
- return 0;
-}
-
static void out_version(void)
{
printf(UTIL_LINUX_VERSION);
@@ -1545,7 +1379,7 @@ static void out_version(void)
* fmt, ... ), show a usage information and terminate the program
* afterwards.
*/
-static void usage(const char *fmt, ...)
+static void usage(const struct hwclock_control *ctl, const char *fmt, ...)
{
FILE *usageto;
va_list ap;
@@ -1568,7 +1402,6 @@ static void usage(const char *fmt, ...)
" --systz set the system time based on the current timezone\n"
" --adjust adjust the RTC to account for systematic drift since\n"
" the clock was last set or adjusted\n"), usageto);
- fputs(_(" -c, --compare periodically compare the system clock with the CMOS clock\n"), usageto);
#ifdef __linux__
fputs(_(" --getepoch print out the kernel's hardware clock epoch value\n"
" --setepoch set the kernel's hardware clock epoch value to the \n"
@@ -1611,7 +1444,7 @@ static void usage(const char *fmt, ...)
}
fflush(usageto);
- hwclock_exit(fmt ? EX_USAGE : EX_OK);
+ hwclock_exit(ctl, fmt ? EX_USAGE : EX_OK);
}
/*
@@ -1625,7 +1458,9 @@ static void usage(const char *fmt, ...)
*/
int main(int argc, char **argv)
{
+ struct hwclock_control ctl = { 0 };
struct timeval startup_time;
+ struct adjtime adjtime = { 0 };
/*
* The time we started up, in seconds into the epoch, including
* fractions.
@@ -1633,15 +1468,6 @@ int main(int argc, char **argv)
time_t set_time = 0; /* Time to which user said to set Hardware Clock */
int rc, c;
- /* Variables set by various options; show may also be set later */
- /* The options debug, badyear and epoch_option are global */
- bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch,
- predict, compare, get;
- bool utc, testing, local_opt, update, noadjfile, directisa;
- char *date_opt;
-#ifdef __alpha__
- bool ARCconsole, Jensen, SRM, funky_toy;
-#endif
/* Long only options. */
enum {
OPT_ADJFILE = CHAR_MAX + 1,
@@ -1663,7 +1489,6 @@ int main(int argc, char **argv)
static const struct option longopts[] = {
{"adjust", 0, 0, 'a'},
- {"compare", 0, 0, 'c'},
{"help", 0, 0, 'h'},
{"show", 0, 0, 'r'},
{"hctosys", 0, 0, 's'},
@@ -1742,107 +1567,95 @@ int main(int argc, char **argv)
textdomain(PACKAGE);
atexit(close_stdout);
- /* Set option defaults */
- show = set = systohc = hctosys = systz = adjust = noadjfile = predict =
- compare = get = update = FALSE;
- getepoch = setepoch = utc = local_opt = directisa = testing = debug = FALSE;
-#ifdef __alpha__
- ARCconsole = Jensen = SRM = funky_toy = badyear = FALSE;
-#endif
- date_opt = NULL;
-
while ((c = getopt_long(argc, argv,
- "?hvVDacrsuwAJSFf:", longopts, NULL)) != -1) {
+ "?hvVDarsuwAJSFf:", longopts, NULL)) != -1) {
err_exclusive_options(c, longopts, excl, excl_st);
switch (c) {
case 'D':
- ++debug;
+ ctl.debug++;
break;
case 'a':
- adjust = TRUE;
- break;
- case 'c':
- compare = TRUE;
+ ctl.adjust = 1;
break;
case 'r':
- show = TRUE;
+ ctl.show = 1;
break;
case 's':
- hctosys = TRUE;
+ ctl.hctosys = 1;
break;
case 'u':
- utc = TRUE;
+ ctl.utc = 1;
break;
case 'w':
- systohc = TRUE;
+ ctl.systohc = 1;
break;
#ifdef __alpha__
case 'A':
- ARCconsole = TRUE;
+ ctl.ARCconsole = 1;
break;
case 'J':
- Jensen = TRUE;
+ ctl.Jensen = 1;
break;
case 'S':
- SRM = TRUE;
+ ctl.SRM = 1;
break;
case 'F':
- funky_toy = TRUE;
+ ctl.funky_toy = 1;
break;
#endif
case OPT_SET:
- set = TRUE;
+ ctl.set = 1;
break;
#ifdef __linux__
case OPT_GETEPOCH:
- getepoch = TRUE;
+ ctl.getepoch = 1;
break;
case OPT_SETEPOCH:
- setepoch = TRUE;
+ ctl.setepoch = 1;
break;
#endif
case OPT_NOADJFILE:
- noadjfile = TRUE;
+ ctl.noadjfile = 1;
break;
case OPT_LOCALTIME:
- local_opt = TRUE; /* --localtime */
+ ctl.local_opt = 1; /* --localtime */
break;
case OPT_BADYEAR:
- badyear = TRUE;
+ ctl.badyear = 1;
break;
case OPT_DIRECTISA:
- directisa = TRUE;
+ ctl.directisa = 1;
break;
case OPT_TEST:
- testing = TRUE; /* --test */
+ ctl.testing = 1; /* --test */
break;
case OPT_DATE:
- date_opt = optarg; /* --date */
+ ctl.date_opt = optarg; /* --date */
break;
case OPT_EPOCH:
- epoch_option = /* --epoch */
+ ctl.epoch_option = /* --epoch */
strtoul_or_err(optarg, _("invalid epoch argument"));
break;
case OPT_ADJFILE:
- adj_file_name = optarg; /* --adjfile */
+ ctl.adj_file_name = optarg; /* --adjfile */
break;
case OPT_SYSTZ:
- systz = TRUE; /* --systz */
+ ctl.systz = 1; /* --systz */
break;
case OPT_PREDICT_HC:
- predict = TRUE; /* --predict-hc */
+ ctl.predict = 1; /* --predict-hc */
break;
case OPT_GET:
- get = TRUE; /* --get */
+ ctl.get = 1; /* --get */
break;
case OPT_UPDATE:
- update = TRUE; /* --update-drift */
+ ctl.update = 1; /* --update-drift */
break;
#ifdef __linux__
case 'f':
- rtc_dev_name = optarg; /* --rtc */
+ ctl.rtc_dev_name = optarg; /* --rtc */
break;
#endif
case 'v': /* --version */
@@ -1850,9 +1663,9 @@ int main(int argc, char **argv)
out_version();
return 0;
case 'h': /* --help */
- usage(NULL);
+ case '?':
default:
- errtryhelp(EXIT_FAILURE);
+ usage(&ctl, NULL);
}
}
@@ -1860,100 +1673,89 @@ int main(int argc, char **argv)
argv += optind;
#ifdef HAVE_LIBAUDIT
- if (testing != TRUE) {
- if (adjust == TRUE || hctosys == TRUE || systohc == TRUE ||
- set == TRUE || setepoch == TRUE) {
- hwaudit_on = TRUE;
+ if (!ctl.testing) {
+ if (ctl.adjust || ctl.hctosys || ctl.systohc ||
+ ctl.set || ctl.setepoch) {
+ ctl.hwaudit_on = 1;
}
}
#endif
if (argc > 0) {
- usage(_("%s takes no non-option arguments. "
+ usage(&ctl, _("%s takes no non-option arguments. "
"You supplied %d.\n"), program_invocation_short_name,
argc);
}
- if (!adj_file_name)
- adj_file_name = _PATH_ADJTIME;
+ if (!ctl.adj_file_name)
+ ctl.adj_file_name = _PATH_ADJTIME;
- if (noadjfile && !utc && !local_opt) {
+ if (ctl.noadjfile && !ctl.utc && !ctl.local_opt) {
warnx(_("With --noadjfile, you must specify "
"either --utc or --localtime"));
- hwclock_exit(EX_USAGE);
+ hwclock_exit(&ctl, EX_USAGE);
}
#ifdef __alpha__
- set_cmos_epoch(ARCconsole, SRM);
- set_cmos_access(Jensen, funky_toy);
+ set_cmos_epoch(&ctl);
+ set_cmos_access(&ctl);
#endif
- if (set || predict) {
- rc = interpret_date_string(date_opt, &set_time);
+ if (ctl.set || ctl.predict) {
+ rc = interpret_date_string(&ctl, &set_time);
/* (time-consuming) */
if (rc != 0) {
warnx(_("No usable set-to time. "
"Cannot set clock."));
- hwclock_exit(EX_USAGE);
+ hwclock_exit(&ctl, EX_USAGE);
}
}
- if (!(show | set | systohc | hctosys | systz | adjust | getepoch
- | setepoch | predict | compare | get))
- show = 1; /* default to show */
-
+ if (!(ctl.show | ctl.set | ctl.systohc | ctl.hctosys |
+ ctl.systz | ctl.adjust | ctl.getepoch | ctl.setepoch |
+ ctl.predict | ctl.get))
+ ctl.show = 1; /* default to show */
#ifdef __linux__
- if (getepoch || setepoch) {
- manipulate_epoch(getepoch, setepoch, epoch_option, testing);
- hwclock_exit(EX_OK);
+ if (ctl.getepoch || ctl.setepoch) {
+ manipulate_epoch(&ctl);
+ hwclock_exit(&ctl, EX_OK);
}
#endif
- if (debug)
+ if (ctl.debug)
out_version();
- if (!systz && !predict) {
- determine_clock_access_method(directisa);
- if (!ur) {
- warnx(_("Cannot access the Hardware Clock via "
- "any known method."));
- if (!debug)
- warnx(_("Use the --debug option to see the "
- "details of our search for an access "
- "method."));
- hwclock_exit(EX_SOFTWARE);
- }
- }
+ if (!ctl.systz && !ctl.predict)
+ determine_clock_access_method(&ctl);
- if (compare) {
- if (compare_clock(utc, local_opt))
- hwclock_exit(EX_NOPERM);
-
- rc = EX_OK;
+ if (!ctl.noadjfile && !(ctl.systz && (ctl.utc || ctl.local_opt))) {
+ if ((rc = read_adjtime(&ctl, &adjtime)) != 0)
+ hwclock_exit(&ctl, rc);
} else
- rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
- hctosys, systohc, systz, startup_time, utc,
- local_opt, update, testing, predict, get);
-
- hwclock_exit(rc);
+ /* Avoid writing adjtime file if we don't have to. */
+ adjtime.dirty = FALSE;
+ ctl.universal = hw_clock_is_utc(&ctl, adjtime);
+ rc = manipulate_clock(&ctl, set_time, startup_time, &adjtime);
+ hwclock_exit(&ctl, rc);
return rc; /* Not reached */
}
-#ifdef HAVE_LIBAUDIT
-/*
- * hwclock_exit calls either this function or plain exit depending
- * HAVE_LIBAUDIT see also clock.h
- */
-void __attribute__((__noreturn__)) hwaudit_exit(int status)
+void __attribute__((__noreturn__))
+hwclock_exit(const struct hwclock_control *ctl
+#ifndef HAVE_LIBAUDIT
+ __attribute__((__unused__))
+#endif
+ , int status)
{
- if (hwaudit_on) {
+#ifdef HAVE_LIBAUDIT
+ if (ctl->hwaudit_on) {
audit_log_user_message(hwaudit_fd, AUDIT_USYS_CONFIG,
"op=change-system-time", NULL, NULL, NULL,
status ? 0 : 1);
close(hwaudit_fd);
}
+#endif
exit(status);
}
-#endif
/*
* History of this program:
diff --git a/sys-utils/hwclock.h b/sys-utils/hwclock.h
index 974d96a40..b08bd2d7a 100644
--- a/sys-utils/hwclock.h
+++ b/sys-utils/hwclock.h
@@ -9,16 +9,62 @@
#include "c.h"
+enum {
+ RTC_BUSYWAIT_OK = 0,
+ RTC_BUSYWAIT_FAILED,
+ RTC_BUSYWAIT_TIMEOUT
+};
+
+struct hwclock_control {
+ char *date_opt;
+ unsigned long epoch_option;
+ char *adj_file_name;
+#ifdef __linux__
+ char *rtc_dev_name;
+#endif
+ unsigned int debug;
+ unsigned int
+#ifdef HAVE_LIBAUDIT
+ hwaudit_on:1,
+#endif
+ adjust:1,
+ show:1,
+ hctosys:1,
+ utc:1,
+ systohc:1,
+#ifdef __alpha__
+ ARCconsole:1,
+ Jensen:1,
+ SRM:1,
+ funky_toy:1,
+#endif
+#ifdef __linux__
+ getepoch:1,
+ setepoch:1,
+#endif
+ noadjfile:1,
+ local_opt:1,
+ badyear:1,
+ directisa:1,
+ testing:1,
+ systz:1,
+ predict:1,
+ get:1,
+ set:1,
+ update:1,
+ universal:1; /* will store hw_clock_is_utc() return value */
+};
+
struct clock_ops {
char *interface_name;
int (*get_permissions) (void);
- int (*read_hardware_clock) (struct tm * tm);
- int (*set_hardware_clock) (const struct tm * tm);
- int (*synchronize_to_clock_tick) (void);
+ int (*read_hardware_clock) (const struct hwclock_control *ctl, struct tm * tm);
+ int (*set_hardware_clock) (const struct hwclock_control *ctl, const struct tm * tm);
+ int (*synchronize_to_clock_tick) (const struct hwclock_control *ctl);
};
extern struct clock_ops *probe_for_cmos_clock(void);
-extern struct clock_ops *probe_for_rtc_clock(void);
+extern struct clock_ops *probe_for_rtc_clock(const struct hwclock_control *ctl);
typedef int bool;
@@ -27,19 +73,13 @@ extern int debug;
extern unsigned long epoch_option;
extern double time_diff(struct timeval subtrahend, struct timeval subtractor);
/* cmos.c */
-extern void set_cmos_epoch(int ARCconsole, int SRM);
-extern void set_cmos_access(int Jensen, int funky_toy);
+extern void set_cmos_epoch(const struct hwclock_control *ctl);
+extern void set_cmos_access(const struct hwclock_control *ctl);
/* rtc.c */
-extern int get_epoch_rtc(unsigned long *epoch, int silent);
-extern int set_epoch_rtc(unsigned long epoch);
-extern char *rtc_dev_name;
+extern int get_epoch_rtc(const struct hwclock_control *ctl, unsigned long *epoch, int silent);
+extern int set_epoch_rtc(const struct hwclock_control *ctl);
-#ifdef HAVE_LIBAUDIT
-extern void hwaudit_exit(int status);
-# define hwclock_exit(_status) hwaudit_exit(_status)
-#else
-# define hwclock_exit(_status) exit(_status)
-#endif
+extern void hwclock_exit(const struct hwclock_control *ctl, int status);
#endif /* HWCLOCK_CLOCK_H */