summaryrefslogtreecommitdiffstats
path: root/sys-utils/hwclock.c
diff options
context:
space:
mode:
authorSami Kerola2016-07-16 17:45:07 +0200
committerSami Kerola2017-02-05 00:39:37 +0100
commit336f7c5f684be96b4908cd3f02226964ed302e63 (patch)
treed1de0ec622de82419f6092f6badfdbc9bf8d35e0 /sys-utils/hwclock.c
parenthwclock: remove unnecessary type casts (diff)
downloadkernel-qcow2-util-linux-336f7c5f684be96b4908cd3f02226964ed302e63.tar.gz
kernel-qcow2-util-linux-336f7c5f684be96b4908cd3f02226964ed302e63.tar.xz
kernel-qcow2-util-linux-336f7c5f684be96b4908cd3f02226964ed302e63.zip
hwclock: move command-line options to control structure
The control structure is read-only everywhere else but in main(). Almost all changes are about how variables are referred, with one exception. Calls to read_adjtime() from manipulate_clock() and compare_clock() are moved to main(). This way it is possible to keep variable that tells if hwclock is using UTC-0 be part of control structure. Changes within #ifdef __alpha__ segments were tested by flipping the preprocessor directivive otherway around and getting good compilaton all the way to the point where linking on none-alpha system failed. Reviewed-by: J William Piggott <elseifthen@gmx.com> Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Diffstat (limited to 'sys-utils/hwclock.c')
-rw-r--r--sys-utils/hwclock.c522
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);