diff options
author | Sami Kerola | 2016-07-16 17:45:07 +0200 |
---|---|---|
committer | Sami Kerola | 2017-02-05 00:39:37 +0100 |
commit | 336f7c5f684be96b4908cd3f02226964ed302e63 (patch) | |
tree | d1de0ec622de82419f6092f6badfdbc9bf8d35e0 /sys-utils/hwclock.c | |
parent | hwclock: remove unnecessary type casts (diff) | |
download | kernel-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/hwclock.c')
-rw-r--r-- | sys-utils/hwclock.c | 522 |
1 files changed, 234 insertions, 288 deletions
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); |