diff options
-rw-r--r-- | sys-utils/hwclock-cmos.c | 144 | ||||
-rw-r--r-- | sys-utils/hwclock-rtc.c | 76 | ||||
-rw-r--r-- | sys-utils/hwclock.c | 522 | ||||
-rw-r--r-- | sys-utils/hwclock.h | 60 |
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 */ |