summaryrefslogtreecommitdiffstats
path: root/sys-utils
diff options
context:
space:
mode:
authorSami Kerola2016-07-16 17:45:07 +0200
committerSami Kerola2017-02-05 00:39:37 +0100
commit336f7c5f684be96b4908cd3f02226964ed302e63 (patch)
treed1de0ec622de82419f6092f6badfdbc9bf8d35e0 /sys-utils
parenthwclock: remove unnecessary type casts (diff)
downloadkernel-qcow2-util-linux-336f7c5f684be96b4908cd3f02226964ed302e63.tar.gz
kernel-qcow2-util-linux-336f7c5f684be96b4908cd3f02226964ed302e63.tar.xz
kernel-qcow2-util-linux-336f7c5f684be96b4908cd3f02226964ed302e63.zip
hwclock: move command-line options to control structure
The control structure is read-only everywhere else but in main(). Almost all changes are about how variables are referred, with one exception. Calls to read_adjtime() from manipulate_clock() and compare_clock() are moved to main(). This way it is possible to keep variable that tells if hwclock is using UTC-0 be part of control structure. Changes within #ifdef __alpha__ segments were tested by flipping the preprocessor directivive otherway around and getting good compilaton all the way to the point where linking on none-alpha system failed. Reviewed-by: J William Piggott <elseifthen@gmx.com> Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Diffstat (limited to 'sys-utils')
-rw-r--r--sys-utils/hwclock-cmos.c144
-rw-r--r--sys-utils/hwclock-rtc.c76
-rw-r--r--sys-utils/hwclock.c522
-rw-r--r--sys-utils/hwclock.h60
4 files changed, 402 insertions, 400 deletions
diff --git a/sys-utils/hwclock-cmos.c b/sys-utils/hwclock-cmos.c
index 9103b7343..625da75c8 100644
--- a/sys-utils/hwclock-cmos.c
+++ b/sys-utils/hwclock-cmos.c
@@ -175,20 +175,21 @@ 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;
+ int set_epoc;
/* 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,8 +219,8 @@ void set_cmos_epoch(int ARCconsole, int SRM)
* different "epoch" ideas.
*/
if (is_in_cpuinfo("system serial number", "MILO")) {
- ARCconsole = 1;
- if (debug)
+ set_epoc = 1;
+ if (ctl->debug)
printf(_("booted from MILO\n"));
}
@@ -229,28 +230,28 @@ void set_cmos_epoch(int ARCconsole, int SRM)
* 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)
+ if (set_epoc && is_in_cpuinfo("system type", "Ruffian")) {
+ set_epoc = 0;
+ if (ctl->debug)
printf(_("Ruffian BCD clock\n"));
}
- if (ARCconsole)
+ if (set_epoc)
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,13 +261,13 @@ 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"));
}
}
@@ -282,13 +283,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 +311,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 +362,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 +383,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 +407,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 +439,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 +460,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 +496,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,7 +523,8 @@ 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;
@@ -536,25 +546,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 +612,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;
}
diff --git a/sys-utils/hwclock-rtc.c b/sys-utils/hwclock-rtc.c
index 3e32399a3..e9ca9ce39 100644
--- a/sys-utils/hwclock-rtc.c
+++ b/sys-utils/hwclock-rtc.c
@@ -104,8 +104,7 @@ struct linux_rtc_time {
*/
/* default or user defined dev (by hwclock --rtc=<path>) */
-char *rtc_dev_name;
-
+static char *rtc_dev_name;
static int rtc_dev_fd = -1;
static void close_rtc(void)
@@ -115,7 +114,7 @@ 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[] = {
#ifdef __ia64__
@@ -133,9 +132,10 @@ static int open_rtc(void)
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 {
+ } else {
for (p = fls; *p; ++p) {
rtc_dev_fd = open(*p, O_RDONLY);
@@ -154,13 +154,13 @@ static int open_rtc(void)
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);
+ hwclock_exit(ctl, EX_OSFILE);
}
return rtc_fd;
}
@@ -205,7 +205,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,7 +214,7 @@ 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);
@@ -246,12 +247,12 @@ static int busywait_for_rtc_clock_tick(const int rtc_fd)
/*
* 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;
- rtc_fd = open_rtc();
+ rtc_fd = open_rtc(ctl);
if (rtc_fd == -1) {
warn(_("cannot open %s"), rtc_dev_name);
ret = 1;
@@ -275,10 +276,10 @@ static int synchronize_to_clock_tick_rtc(void)
* Clock interrupts are used by the kernel for the
* system clock, so aren't at the user's disposal.
*/
- if (debug)
+ if (ctl->debug)
printf(_("%s does not have interrupt functions. "),
rtc_dev_name);
- ret = busywait_for_rtc_clock_tick(rtc_fd);
+ ret = busywait_for_rtc_clock_tick(ctl, rtc_fd);
} else if (rc == 0) {
/*
* Just reading rtc_fd fails on broken hardware: no
@@ -302,7 +303,7 @@ static int synchronize_to_clock_tick_rtc(void)
warn(_("select() to %s to wait for clock tick failed"),
rtc_dev_name);
else if (rc == 0) {
- if (debug)
+ if (ctl->debug)
printf(_("select() to %s to wait for clock tick timed out"),
rtc_dev_name);
} else
@@ -321,11 +322,12 @@ static int synchronize_to_clock_tick_rtc(void)
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,13 +339,14 @@ 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);
#ifdef __sparc__
{
@@ -369,10 +372,10 @@ static int set_hardware_clock_rtc(const struct tm *new_broken_time)
if (rc == -1) {
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;
@@ -392,24 +395,25 @@ 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();
+ int rtc_fd = open_rtc(ctl);
if (rtc_fd >= 0)
return &rtc;
- if (debug)
- warn(_("cannot open %s"), rtc_dev_name);
+ if (ctl->debug)
+ warn(_("cannot open %s"), ctl->rtc_dev_name);
return NULL;
}
/*
* 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)
@@ -431,7 +435,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,22 +446,22 @@ 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(_
@@ -466,16 +470,16 @@ int set_epoch_rtc(unsigned long epoch)
"file %s. This file does not exist on this system."),
rtc_dev_name);
else
- warn(_("cannot open %s"), rtc_dev_name);
+ warn(_("cannot open %s"), ctl->rtc_dev_name);
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."),
diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c
index b57a29e0a..fe0d6736d 100644
--- a/sys-utils/hwclock.c
+++ b/sys-utils/hwclock.c
@@ -86,7 +86,6 @@
#ifdef HAVE_LIBAUDIT
#include <libaudit.h>
static int hwaudit_fd = -1;
-static int hwaudit_on;
#endif
/* The struct that holds our hardware access routines */
@@ -97,8 +96,6 @@ struct clock_ops *ur;
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
@@ -128,18 +125,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.
@@ -228,19 +213,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;
@@ -255,7 +240,8 @@ 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 */
@@ -263,7 +249,7 @@ static int read_adjtime(struct adjtime *adjtime_p)
char line3[81]; /* String: third line of adjtime file */
long timeval;
- if (access(adj_file_name, R_OK) != 0) {
+ if (access(ctl->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;
@@ -275,9 +261,9 @@ static int read_adjtime(struct adjtime *adjtime_p)
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;
}
@@ -320,7 +306,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);
@@ -348,16 +334,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
@@ -384,10 +370,10 @@ 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)
{
- if (universal)
+ if (ctl->universal)
*systime_p = timegm(&tm);
else
*systime_p = mktime(&tm);
@@ -399,14 +385,14 @@ mktime_tz(struct tm tm, const bool universal,
* mktime() returns -1).
*/
*valid_p = FALSE;
- 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;
- if (debug)
+ if (ctl->debug)
printf(_
("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
"%ld seconds since 1969\n"), tm.tm_year + 1900,
@@ -422,24 +408,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;
}
@@ -449,8 +436,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;
/*
@@ -458,21 +444,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,
@@ -483,7 +469,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);
}
}
@@ -506,9 +492,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
@@ -572,7 +558,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);
@@ -584,7 +570,7 @@ 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, nowsystime.tv_sec,
@@ -592,7 +578,7 @@ set_hardware_clock_exact(const time_t sethwtime,
/* 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"),
nowsystime.tv_sec,
nowsystime.tv_usec,
@@ -608,7 +594,7 @@ 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"),
nowsystime.tv_sec,
@@ -636,7 +622,7 @@ 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"),
nowsystime.tv_sec, nowsystime.tv_usec,
@@ -646,7 +632,7 @@ set_hardware_clock_exact(const time_t sethwtime,
(int)(newhwtime - sethwtime),
refsystime.tv_sec, refsystime.tv_usec);
- set_hardware_clock(newhwtime, universal, testing);
+ set_hardware_clock(ctl, newhwtime);
}
/*
@@ -689,7 +675,8 @@ 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];
@@ -698,19 +685,19 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
int retcode; /* our eventual return code */
int rc; /* local return code */
- 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) {
+ if (strlen(ctl->date_opt) > sizeof(date_command) - 50) {
warnx(_("--date argument too long"));
return 13;
}
/* Quotes in date_opt would ruin the date command we construct. */
- if (strchr(date_opt, '"') != NULL) {
+ if (strchr(ctl->date_opt, '"') != NULL) {
warnx(_
("The value of the --date option is not a valid date.\n"
"In particular, it contains quotation marks."));
@@ -718,8 +705,8 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
}
sprintf(date_command, "date --date=\"%s\" +%s%%s",
- date_opt, magic);
- if (debug)
+ ctl->date_opt, magic);
+ if (ctl->debug)
printf(_("Issuing date command: %s\n"), date_command);
date_child_fp = popen(date_command, "r");
@@ -731,7 +718,7 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
if (!fgets(date_resp, sizeof(date_resp), date_child_fp))
date_resp[0] = '\0'; /* in case fgets fails */
- if (debug)
+ 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 "
@@ -756,10 +743,10 @@ static int interpret_date_string(const char *date_opt, time_t * const time_p)
} else {
retcode = 0;
*time_p = seconds_since_epoch;
- if (debug)
+ if (ctl->debug)
printf(_("date string %s equates to "
"%ld seconds since 1969.\n"),
- date_opt, *time_p);
+ ctl->date_opt, *time_p);
}
}
pclose(date_child_fp);
@@ -788,8 +775,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;
@@ -813,13 +800,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"),
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;
@@ -830,7 +817,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);
@@ -861,7 +848,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;
@@ -869,7 +856,7 @@ 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];
@@ -889,12 +876,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);
@@ -907,7 +894,7 @@ static int set_system_clock_timezone(const bool universal, const bool testing)
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;
@@ -922,7 +909,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
@@ -959,29 +946,29 @@ 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"));
@@ -1019,14 +1006,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"
@@ -1056,7 +1043,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)
@@ -1069,7 +1057,7 @@ calculate_adjustment(const double factor,
tdrift_p->tv_sec = (time_t) floor(exact_adjustment);
tdrift_p->tv_usec = (exact_adjustment -
(double)tdrift_p->tv_sec) * 1E6;
- if (debug) {
+ if (ctl->debug) {
printf(P_("Time since last adjustment is %ld second\n",
"Time since last adjustment is %ld seconds\n",
(systime - last_time)),
@@ -1085,51 +1073,52 @@ 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 */
- if (adjtime.dirty) {
+ 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,
- adjtime.last_adj_time,
- adjtime.not_adjusted,
- adjtime.last_calib_time,
- (adjtime.local_utc == LOCAL) ? "LOCAL" : "UTC");
+ adjtime->drift_factor,
+ adjtime->last_adj_time,
+ adjtime->not_adjusted,
+ adjtime->last_calib_time,
+ (adjtime->local_utc == LOCAL) ? "LOCAL" : "UTC");
- if (testing) {
+ if (ctl->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);
+ ctl->adj_file_name, newfile);
} else {
FILE *adjfile;
int err = 0;
- adjfile = fopen(adj_file_name, "w");
+ adjfile = fopen(ctl->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);
+ "in it (%s) for writing"), ctl->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);
+ ctl->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);
+ ctl->adj_file_name);
err = 1;
}
}
@@ -1165,10 +1154,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, "
@@ -1178,37 +1166,36 @@ 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 (debug) {
+ if (ctl->debug) {
if (ur)
puts(_(ur->interface_name));
else
@@ -1224,16 +1211,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 */
@@ -1253,32 +1233,22 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
/* local return code */
int rc = 0;
- if (!systz && !predict) {
+ if (!ctl->systz && !ctl->predict) {
no_auth = ur->get_permissions();
if (no_auth)
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;
- }
-
- 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 ((ctl->set || ctl->systohc || ctl->adjust) &&
+ (adjtime->local_utc == UTC) != ctl->universal) {
+ adjtime->local_utc = ctl->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
@@ -1288,7 +1258,7 @@ manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
* so we still want to allow a user to set
* the RTC time.
*/
- if (rc && rc != 2 && !set && !systohc)
+ if (rc && rc != 2 && !ctl->set && !ctl->systohc)
return EX_IOERR;
gettimeofday(&read_time, NULL);
@@ -1298,9 +1268,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;
}
}
@@ -1312,33 +1282,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
@@ -1349,37 +1318,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, hclocktime.tv_sec);
}
display_time(TRUE, hclocktime);
}
- if (!noadjfile)
- save_adjtime(adjtime, testing);
+ if (!ctl->noadjfile)
+ save_adjtime(ctl, adjtime);
return 0;
}
@@ -1397,10 +1363,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 "
@@ -1409,30 +1372,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"));
}
@@ -1444,15 +1404,13 @@ manipulate_epoch(const bool getepoch,
* 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)
+static int compare_clock(const struct hwclock_control *ctl)
{
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;
+ bool hclock_valid = FALSE, first_pass = TRUE;
if (ur->get_permissions())
return EX_NOPERM;
@@ -1460,30 +1418,24 @@ static int compare_clock (const bool utc, const bool local_opt)
/* 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);
+ synchronize_to_clock_tick(ctl);
+ ur->read_hardware_clock(ctl, &tm);
gettimeofday(&tv, NULL);
time1_sys = tv.tv_sec + tv.tv_usec / 1000000.0;
- mktime_tz(tm, universal, &hclock_valid, &time1_hw);
+ mktime_tz(ctl, tm, &hclock_valid, &time1_hw);
while (1) {
double res;
- synchronize_to_clock_tick();
- ur->read_hardware_clock(&tm);
+ synchronize_to_clock_tick(ctl);
+ ur->read_hardware_clock(ctl, &tm);
gettimeofday(&tv, NULL);
time2_sys = tv.tv_sec + tv.tv_usec / 1000000.0;
- mktime_tz(tm, universal, &hclock_valid, &time2_hw);
+ mktime_tz(ctl, tm, &hclock_valid, &time2_hw);
res = (((double) time1_hw - time1_sys) -
((double) time2_hw - time2_sys))
@@ -1519,7 +1471,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;
@@ -1585,7 +1537,7 @@ static void usage(const char *fmt, ...)
}
fflush(usageto);
- hwclock_exit(fmt ? EX_USAGE : EX_OK);
+ hwclock_exit(ctl, fmt ? EX_USAGE : EX_OK);
}
/*
@@ -1599,7 +1551,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.
@@ -1607,15 +1561,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,
@@ -1716,15 +1661,6 @@ 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) {
@@ -1732,91 +1668,91 @@ int main(int argc, char **argv)
switch (c) {
case 'D':
- ++debug;
+ ctl.debug++;
break;
case 'a':
- adjust = TRUE;
+ ctl.adjust = 1;
break;
case 'c':
- compare = TRUE;
+ ctl.compare = 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 */
@@ -1824,9 +1760,9 @@ int main(int argc, char **argv)
out_version();
return 0;
case 'h': /* --help */
- usage(NULL);
+ case '?':
default:
- errtryhelp(EXIT_FAILURE);
+ usage(&ctl, NULL);
}
}
@@ -1834,88 +1770,98 @@ 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.compare | 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 (!ctl.systz && !ctl.predict) {
+ determine_clock_access_method(&ctl);
if (!ur) {
warnx(_("Cannot access the Hardware Clock via "
"any known method."));
- if (!debug)
+ if (!ctl.debug)
warnx(_("Use the --debug option to see the "
"details of our search for an access "
"method."));
- hwclock_exit(EX_SOFTWARE);
+ hwclock_exit(&ctl, EX_SOFTWARE);
}
}
- if (compare) {
- if (compare_clock(utc, local_opt))
- hwclock_exit(EX_NOPERM);
+ if (!ctl.noadjfile && !(ctl.systz && (ctl.utc || ctl.local_opt))) {
+ if ((rc = read_adjtime(&ctl, &adjtime)) != 0)
+ hwclock_exit(&ctl, rc);
+ } else
+ /* Avoid writing adjtime file if we don't have to. */
+ adjtime.dirty = FALSE;
+ ctl.universal = hw_clock_is_utc(&ctl, adjtime);
+ if (ctl.compare) {
+ if (compare_clock(&ctl))
+ hwclock_exit(&ctl, EX_NOPERM);
rc = EX_OK;
} else
- rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
- hctosys, systohc, systz, startup_time, utc,
- local_opt, update, testing, predict, get);
+ rc = manipulate_clock(&ctl, set_time, startup_time, &adjtime);
- hwclock_exit(rc);
+ hwclock_exit(&ctl, rc);
return rc; /* Not reached */
}
-void __attribute__((__noreturn__)) hwclock_exit(int status)
+void __attribute__((__noreturn__))
+hwclock_exit(const struct hwclock_control *ctl
+#ifndef HAVE_LIBAUDIT
+ __attribute__((__unused__))
+#endif
+ , int status)
{
#ifdef HAVE_LIBAUDIT
- if (hwaudit_on) {
+ if (ctl->hwaudit_on) {
audit_log_user_message(hwaudit_fd, AUDIT_USYS_CONFIG,
"op=change-system-time", NULL, NULL, NULL,
status ? 0 : 1);
diff --git a/sys-utils/hwclock.h b/sys-utils/hwclock.h
index d58ebbc6f..c76068c88 100644
--- a/sys-utils/hwclock.h
+++ b/sys-utils/hwclock.h
@@ -9,16 +9,57 @@
#include "c.h"
+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,
+ compare: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,14 +68,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);
-extern void hwclock_exit(int status);
+extern void hwclock_exit(const struct hwclock_control *ctl, int status);
#endif /* HWCLOCK_CLOCK_H */