From ef71b8f1128b72bf072f1bd0a306b1bb06781a40 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Sun, 24 Jul 2011 17:35:43 +0200 Subject: hwclock: coding style clean up Despide amount of the change this change should be harmless. Everything is about indendation, comment restructuring etc not code changes. Signed-off-by: Sami Kerola --- hwclock/hwclock.c | 2453 +++++++++++++++++++++++++++-------------------------- 1 file changed, 1234 insertions(+), 1219 deletions(-) (limited to 'hwclock/hwclock.c') diff --git a/hwclock/hwclock.c b/hwclock/hwclock.c index 68e76b896..0c6b0f6cd 100644 --- a/hwclock/hwclock.c +++ b/hwclock/hwclock.c @@ -8,35 +8,24 @@ * * Major rewrite by Bryan Henderson , 96.09.19. * The new program is called hwclock. New features: - * - You can set the hardware clock without also modifying the system clock. - * - You can read and set the clock with finer than 1 second precision. - * - When you set the clock, hwclock automatically refigures the drift - * rate, based on how far off the clock was before you set it. + * + * - You can set the hardware clock without also modifying the system + * clock. + * - You can read and set the clock with finer than 1 second precision. + * - When you set the clock, hwclock automatically refigures the drift + * rate, based on how far off the clock was before you set it. * * Reshuffled things, added sparc code, and re-added alpha stuff * by David Mosberger * and Jay Estabrook * and Martin Ostermann , aeb@cwi.nl, 990212. * - * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98 + * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98 * Change of local time handling, Stefan Ring * Change of adjtime handling, James P. Rutledge . * * Distributed under GPL */ - -/* - * clock [-u] -r - read hardware clock - * clock [-u] -w - write hardware clock from system time - * clock [-u] -s - set system time from hardware clock - * clock [-u] -a - set system time from hardware clock, adjust the time - * to correct for systematic error, and write it back to - * the hardware clock - * -u indicates cmos clock is kept in universal time - * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980) - * -J indicates we're dealing with a Jensen (early DEC Alpha PC) - */ - /* * Explanation of `adjusting' (Rob Hooft): * @@ -49,23 +38,23 @@ * to determine the correction, and to save its data. In this file are * three numbers: * - * 1) the correction in seconds per day. (So if your clock runs 5 - * seconds per day fast, the first number should read -5.0) - * 2) the number of seconds since 1/1/1970 the last time the program - * was used - * 3) the remaining part of a second which was leftover after the last - * adjustment + * 1) the correction in seconds per day. (So if your clock runs 5 + * seconds per day fast, the first number should read -5.0) + * 2) the number of seconds since 1/1/1970 the last time the program + * was used + * 3) the remaining part of a second which was leftover after the last + * adjustment * * Installation and use of this program: * - * a) create a file '/etc/adjtime' containing as the first and only line: - * '0.0 0 0.0' - * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in - * universal or local time. This updates the second number. - * c) set your system time using the 'date' command. - * d) update your cmos time using 'clock -wu' or 'clock -w' - * e) replace the first number in /etc/adjtime by your correction. - * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local' + * a) create a file '/etc/adjtime' containing as the first and only + * line: '0.0 0 0.0' + * b) run 'clock -au' or 'clock -a', depending on whether your cmos is + * in universal or local time. This updates the second number. + * c) set your system time using the 'date' command. + * d) update your cmos time using 'clock -wu' or 'clock -w' + * e) replace the first number in /etc/adjtime by your correction. + * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local' */ #include @@ -108,115 +97,125 @@ const char *adj_file_name = NULL; #define LASTDATE "/var/lib/lastdate" struct adjtime { - /* This is information we keep in the adjtime file that tells us how - to do drift corrections. Elements are all straight from the - adjtime file, so see documentation of that file for details. - Exception is , which is an indication that what's in this - structure is not what's in the disk file (because it has been - updated since read from the disk file). - */ - bool dirty; - - /* line 1 */ - double drift_factor; - time_t last_adj_time; - double not_adjusted; - - /* line 2 */ - time_t last_calib_time; - /* The most recent time that we set the clock from an external - authority (as opposed to just doing a drift adjustment) */ - - /* line 3 */ - enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc; - /* To which time zone, local or UTC, we most recently set the - hardware clock. */ + /* + * This is information we keep in the adjtime file that tells us how + * to do drift corrections. Elements are all straight from the + * adjtime file, so see documentation of that file for details. + * Exception is , which is an indication that what's in this + * structure is not what's in the disk file (because it has been + * updated since read from the disk file). + */ + bool dirty; + /* line 1 */ + double drift_factor; + time_t last_adj_time; + double not_adjusted; + /* line 2 */ + time_t last_calib_time; + /* + * The most recent time that we set the clock from an external + * authority (as opposed to just doing a drift adjustment) + */ + /* line 3 */ + enum a_local_utc { LOCAL, UTC, UNKNOWN } local_utc; + /* + * To which time zone, local or UTC, we most recently set the + * hardware clock. + */ }; + +/* + * We are running in debug mode, wherein we put a lot of information about + * what we're doing to standard output. + */ bool debug; - /* We are running in debug mode, wherein we put a lot of information about - what we're doing to standard output. */ +/* Workaround for Award 4.50g BIOS bug: keep the year in a file. */ bool badyear; - /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */ +/* User-specified epoch, used when rtc fails to return epoch. */ int epoch_option = -1; - /* User-specified epoch, used when rtc fails to return epoch. */ /* - * 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. - * With the --badyear option, we write the date to file and hope - * that the file is updated at least once a year. - * I recommend putting this command "hwclock --badyear" in the monthly - * crontab, just to be safe. -- Dave Coffin 11/12/98 + * 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. + * + * With the --badyear option, we write the date to file and hope that the + * file is updated at least once a year. I recommend putting this command + * "hwclock --badyear" in the monthly crontab, just to be safe. + * + * -- Dave Coffin 11/12/98 */ -static void -write_date_to_file (struct tm *tm) { - FILE *fp; - - if ((fp = fopen(LASTDATE,"w"))) { - fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1, - tm->tm_year+1900); - fclose(fp); - } else - perror(LASTDATE); +static void write_date_to_file(struct tm *tm) +{ + FILE *fp; + + if ((fp = fopen(LASTDATE, "w"))) { + fprintf(fp, "%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon + 1, + tm->tm_year + 1900); + fclose(fp); + } else + perror(LASTDATE); } -static void -read_date_from_file (struct tm *tm) { - int last_mday, last_mon, last_year; - FILE *fp; - - if ((fp = fopen(LASTDATE,"r"))) { - if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) { - tm->tm_year = last_year-1900; - if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday) - tm->tm_year ++; - } - fclose(fp); - } - write_date_to_file (tm); +static void read_date_from_file(struct tm *tm) +{ + int last_mday, last_mon, last_year; + FILE *fp; + + if ((fp = fopen(LASTDATE, "r"))) { + if (fscanf(fp, "%d.%d.%d\n", &last_mday, &last_mon, &last_year) + == 3) { + tm->tm_year = last_year - 1900; + if ((tm->tm_mon << 5) + tm->tm_mday < + ((last_mon - 1) << 5) + last_mday) + tm->tm_year++; + } + fclose(fp); + } + write_date_to_file(tm); } -double -time_diff(struct timeval subtrahend, struct timeval subtractor) { -/*--------------------------------------------------------------------------- - The difference in seconds between two times in "timeval" format. -----------------------------------------------------------------------------*/ - return (subtrahend.tv_sec - subtractor.tv_sec) - + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6; +/* + * The difference in seconds between two times in "timeval" format. + */ +double time_diff(struct timeval subtrahend, struct timeval subtractor) +{ + return (subtrahend.tv_sec - subtractor.tv_sec) + + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6; } - -static struct timeval -time_inc(struct timeval addend, double increment) { -/*---------------------------------------------------------------------------- - The time, in "timeval" format, which is seconds after - the time . Of course, may be negative. ------------------------------------------------------------------------------*/ - struct timeval newtime; - - newtime.tv_sec = addend.tv_sec + (int) increment; - newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6; - - /* Now adjust it so that the microsecond value is between 0 and 1 million */ - if (newtime.tv_usec < 0) { - newtime.tv_usec += 1E6; - newtime.tv_sec -= 1; - } else if (newtime.tv_usec >= 1E6) { - newtime.tv_usec -= 1E6; - newtime.tv_sec += 1; - } - return newtime; +/* + * The time, in "timeval" format, which is seconds after the + * time . Of course, may be negative. + */ +static struct timeval time_inc(struct timeval addend, double increment) +{ + struct timeval newtime; + + newtime.tv_sec = addend.tv_sec + (int)increment; + newtime.tv_usec = addend.tv_usec + (increment - (int)increment) * 1E6; + + /* + * Now adjust it so that the microsecond value is between 0 and 1 + * million. + */ + if (newtime.tv_usec < 0) { + newtime.tv_usec += 1E6; + newtime.tv_sec -= 1; + } else if (newtime.tv_usec >= 1E6) { + newtime.tv_usec -= 1E6; + newtime.tv_sec += 1; + } + return newtime; } - static bool hw_clock_is_utc(const bool utc, const bool local_opt, - const struct adjtime adjtime) { + const struct adjtime adjtime) +{ bool ret; if (utc) @@ -224,7 +223,7 @@ hw_clock_is_utc(const bool utc, const bool local_opt, else if (local_opt) ret = FALSE; /* --localtime explicitly given */ else - /* get info from adjtime file - default is UTC */ + /* get info from adjtime file - default is UTC */ ret = (adjtime.local_utc != LOCAL); if (debug) printf(_("Assuming hardware clock is kept in %s time.\n"), @@ -232,122 +231,120 @@ hw_clock_is_utc(const bool utc, const bool local_opt, return ret; } +/* + * Read the adjustment parameters out of the /etc/adjtime file. + * + * Return them as the adjtime structure <*adjtime_p>. If there is no + * /etc/adjtime file, return defaults. If values are missing from the file, + * return defaults for them. + * + * return value 0 if all OK, !=0 otherwise. + */ +static int read_adjtime(struct adjtime *adjtime_p) +{ + FILE *adjfile; + int rc; /* local return code */ + struct stat statbuf; /* We don't even use the contents of this. */ + char line1[81]; /* String: first line of adjtime file */ + char line2[81]; /* String: second line of adjtime file */ + char line3[81]; /* String: third line of adjtime file */ + long timeval; + + rc = stat(adj_file_name, &statbuf); + if (rc < 0 && errno == ENOENT) { + /* He doesn't have a adjtime file, so we'll use defaults. */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + adjtime_p->local_utc = UNKNOWN; + adjtime_p->dirty = FALSE; /* don't create a zero adjfile */ + + return 0; + } - -static int -read_adjtime(struct adjtime *adjtime_p) { -/*---------------------------------------------------------------------------- - Read the adjustment parameters out of the /etc/adjtime file. - - Return them as the adjtime structure <*adjtime_p>. - If there is no /etc/adjtime file, return defaults. - If values are missing from the file, return defaults for them. - - return value 0 if all OK, !=0 otherwise. - ------------------------------------------------------------------------------*/ - FILE *adjfile; - int rc; /* local return code */ - struct stat statbuf; /* We don't even use the contents of this. */ - - rc = stat(adj_file_name, &statbuf); - if (rc < 0 && errno == ENOENT) { - /* He doesn't have a adjtime file, so we'll use defaults. */ - adjtime_p->drift_factor = 0; - adjtime_p->last_adj_time = 0; - adjtime_p->not_adjusted = 0; - adjtime_p->last_calib_time = 0; - adjtime_p->local_utc = UNKNOWN; - adjtime_p->dirty = FALSE; /* don't create a zero adjfile */ - - return 0; - } - - adjfile = fopen(adj_file_name, "r"); /* open file for reading */ - if (adjfile == NULL) { - outsyserr("cannot open file %s", adj_file_name); - return EX_OSFILE; - } - - { - char line1[81]; /* String: first line of adjtime file */ - char line2[81]; /* String: second line of adjtime file */ - char line3[81]; /* String: third line of adjtime file */ - long timeval; - - if (!fgets(line1, sizeof(line1), adjfile)) - line1[0] = '\0'; /* In case fgets fails */ - if (!fgets(line2, sizeof(line2), adjfile)) - line2[0] = '\0'; /* In case fgets fails */ - if (!fgets(line3, sizeof(line3), adjfile)) - line3[0] = '\0'; /* In case fgets fails */ - - fclose(adjfile); - - /* Set defaults in case values are missing from file */ - adjtime_p->drift_factor = 0; - adjtime_p->last_adj_time = 0; - adjtime_p->not_adjusted = 0; - adjtime_p->last_calib_time = 0; - timeval = 0; - - sscanf(line1, "%lf %ld %lf", - &adjtime_p->drift_factor, - &timeval, - &adjtime_p->not_adjusted); - adjtime_p->last_adj_time = timeval; - - sscanf(line2, "%ld", &timeval); - adjtime_p->last_calib_time = timeval; - - if (!strcmp(line3, "UTC\n")) - adjtime_p->local_utc = UTC; - else if (!strcmp(line3, "LOCAL\n")) - adjtime_p->local_utc = LOCAL; - else { - adjtime_p->local_utc = UNKNOWN; - if (line3[0]) { - fprintf(stderr, - _("%s: Warning: unrecognized third line in adjtime file\n"), - MYNAME); - fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n")); + adjfile = fopen(adj_file_name, "r"); /* open file for reading */ + if (adjfile == NULL) { + outsyserr("cannot open file %s", adj_file_name); + return EX_OSFILE; } - } - } - adjtime_p->dirty = FALSE; - - if (debug) { - printf(_("Last drift adjustment done at %ld seconds after 1969\n"), - (long) adjtime_p->last_adj_time); - printf(_("Last calibration done at %ld seconds after 1969\n"), - (long) adjtime_p->last_calib_time); - printf(_("Hardware clock is on %s time\n"), - (adjtime_p->local_utc == LOCAL) ? _("local") : - (adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown")); - } - - return 0; -} -static int -synchronize_to_clock_tick(void) { -/*----------------------------------------------------------------------------- - Wait until the falling edge of the Hardware Clock's update flag so - that any time that is read from the clock immediately after we - return will be exact. + if (!fgets(line1, sizeof(line1), adjfile)) + line1[0] = '\0'; /* In case fgets fails */ + if (!fgets(line2, sizeof(line2), adjfile)) + line2[0] = '\0'; /* In case fgets fails */ + if (!fgets(line3, sizeof(line3), adjfile)) + line3[0] = '\0'; /* In case fgets fails */ + + fclose(adjfile); + + /* Set defaults in case values are missing from file */ + adjtime_p->drift_factor = 0; + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->last_calib_time = 0; + timeval = 0; + + sscanf(line1, "%lf %ld %lf", + &adjtime_p->drift_factor, + &timeval, &adjtime_p->not_adjusted); + adjtime_p->last_adj_time = timeval; + + sscanf(line2, "%ld", &timeval); + adjtime_p->last_calib_time = timeval; + + if (!strcmp(line3, "UTC\n")) { + adjtime_p->local_utc = UTC; + } else if (!strcmp(line3, "LOCAL\n")) { + adjtime_p->local_utc = LOCAL; + } else { + adjtime_p->local_utc = UNKNOWN; + if (line3[0]) { + fprintf(stderr, + _("%s: Warning: unrecognized third line in adjtime file\n"), + MYNAME); + fprintf(stderr, + _("(Expected: `UTC' or `LOCAL' or nothing.)\n")); + } + } - The clock only has 1 second precision, so it gives the exact time only - once per second, right on the falling edge of the update flag. + adjtime_p->dirty = FALSE; - We wait (up to one second) either blocked waiting for an rtc device - or in a CPU spin loop. The former is probably not very accurate. + if (debug) { + printf(_ + ("Last drift adjustment done at %ld seconds after 1969\n"), + (long)adjtime_p->last_adj_time); + printf(_("Last calibration done at %ld seconds after 1969\n"), + (long)adjtime_p->last_calib_time); + printf(_("Hardware clock is on %s time\n"), + (adjtime_p->local_utc == + LOCAL) ? _("local") : (adjtime_p->local_utc == + UTC) ? _("UTC") : _("unknown")); + } + + return 0; +} - Return 0 if it worked, nonzero if it didn't. ------------------------------------------------------------------------------*/ +/* + * Wait until the falling edge of the Hardware Clock's update flag so that + * any time that is read from the clock immediately after we return will be + * exact. + * + * The clock only has 1 second precision, so it gives the exact time only + * once per second, right on the falling edge of the update flag. + * + * We wait (up to one second) either blocked waiting for an rtc device or in + * a CPU spin loop. The former is probably not very accurate. + * + * Return 0 if it worked, nonzero if it didn't. + */ +static int synchronize_to_clock_tick(void) +{ int rc; - if (debug) printf(_("Waiting for clock tick...\n")); + if (debug) + printf(_("Waiting for clock tick...\n")); rc = ur->synchronize_to_clock_tick(); @@ -361,254 +358,259 @@ synchronize_to_clock_tick(void) { return rc; } - - +/* + * Convert a time in broken down format (hours, minutes, etc.) into standard + * unix time (seconds into epoch). Return it as *systime_p. + * + * The broken down time is argument . This broken down time is either + * in local time zone or UTC, depending on value of logical argument + * "universal". True means it is in UTC. + * + * If the argument contains values that do not constitute a valid time, and + * mktime() recognizes this, return *valid_p == false and *systime_p + * undefined. However, mktime() sometimes goes ahead and computes a + * fictional time "as if" the input values were valid, e.g. if they indicate + * the 31st day of April, mktime() may compute the time of May 1. In such a + * case, we return the same fictional value mktime() does as *systime_p and + * return *valid_p == true. + */ static void mktime_tz(struct tm tm, const bool universal, - bool *valid_p, time_t *systime_p) { -/*----------------------------------------------------------------------------- - Convert a time in broken down format (hours, minutes, etc.) into standard - unix time (seconds into epoch). Return it as *systime_p. - - The broken down time is argument . This broken down time is either in - local time zone or UTC, depending on value of logical argument "universal". - True means it is in UTC. - - If the argument contains values that do not constitute a valid time, - and mktime() recognizes this, return *valid_p == false and - *systime_p undefined. However, mktime() sometimes goes ahead and - computes a fictional time "as if" the input values were valid, - e.g. if they indicate the 31st day of April, mktime() may compute - the time of May 1. In such a case, we return the same fictional - value mktime() does as *systime_p and return *valid_p == true. - ------------------------------------------------------------------------------*/ - time_t mktime_result; /* The value returned by our mktime() call */ - char *zone; /* Local time zone name */ - - /* We use the C library function mktime(), but since it only works on - local time zone input, we may have to fake it out by temporarily - changing the local time zone to UTC. - */ - zone = getenv("TZ"); /* remember original time zone */ - if (universal) { - /* Set timezone to UTC */ - setenv("TZ", "", TRUE); - /* Note: tzset() gets called implicitly by the time code, but only the - first time. When changing the environment variable, better call - tzset() explicitly. - */ - tzset(); - } - mktime_result = mktime(&tm); - if (mktime_result == -1) { - /* This apparently (not specified in mktime() documentation) means - the 'tm' structure does not contain valid values (however, not - containing valid values does _not_ imply mktime() returns -1). - */ - *valid_p = FALSE; - *systime_p = 0; - if (debug) - printf(_("Invalid values in hardware clock: " - "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"), - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - } else { - *valid_p = TRUE; - *systime_p = mktime_result; - if (debug) - printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = " - "%ld seconds since 1969\n"), - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, (long) *systime_p); - } - /* now put back the original zone. */ - if (zone) setenv("TZ", zone, TRUE); - else unsetenv("TZ"); - tzset(); + bool * valid_p, time_t * systime_p) +{ + time_t mktime_result; /* The value returned by our mktime() call */ + char *zone; /* Local time zone name */ + + /* + * We use the C library function mktime(), but since it only works + * on local time zone input, we may have to fake it out by + * temporarily changing the local time zone to UTC. + */ + zone = getenv("TZ"); /* remember original time zone */ + if (universal) { + /* Set timezone to UTC */ + setenv("TZ", "", TRUE); + /* + * Note: tzset() gets called implicitly by the time code, + * but only the first time. When changing the environment + * variable, better call tzset() explicitly. + */ + tzset(); + } + mktime_result = mktime(&tm); + if (mktime_result == -1) { + /* + * This apparently (not specified in mktime() documentation) + * means the 'tm' structure does not contain valid values + * (however, not containing valid values does _not_ imply + * mktime() returns -1). + */ + *valid_p = FALSE; + *systime_p = 0; + if (debug) + printf(_("Invalid values in hardware clock: " + "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"), + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + } else { + *valid_p = TRUE; + *systime_p = mktime_result; + if (debug) + printf(_ + ("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = " + "%ld seconds since 1969\n"), tm.tm_year + 1900, + tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec, (long)*systime_p); + } + /* now put back the original zone. */ + if (zone) + setenv("TZ", zone, TRUE); + else + unsetenv("TZ"); + tzset(); } - +/* + * Read the hardware clock and return the current time via argument. + * + * Use the method indicated by argument to access the hardware + * clock. + */ static int -read_hardware_clock(const bool universal, bool *valid_p, time_t *systime_p){ -/*---------------------------------------------------------------------------- - Read the hardware clock and return the current time via argument. - - Use the method indicated by argument to access the hardware clock. ------------------------------------------------------------------------------*/ - struct tm tm; - int err; +read_hardware_clock(const bool universal, bool * valid_p, time_t * systime_p) +{ + struct tm tm; + int err; - err = ur->read_hardware_clock(&tm); - if (err) - return err; + err = ur->read_hardware_clock(&tm); + if (err) + return err; - if (badyear) - read_date_from_file(&tm); + if (badyear) + read_date_from_file(&tm); - if (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); + if (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); - return 0; + return 0; } - +/* + * Set the Hardware Clock to the time , in local time zone or UTC, + * according to . + */ static void set_hardware_clock(const time_t newtime, - const bool universal, - const bool testing) { -/*---------------------------------------------------------------------------- - Set the Hardware Clock to the time , in local time zone or UTC, - according to . -----------------------------------------------------------------------------*/ - struct tm new_broken_time; - /* Time to which we will set Hardware Clock, in broken down format, in - the time zone of caller's choice - */ - - if (universal) - new_broken_time = *gmtime(&newtime); - else - new_broken_time = *localtime(&newtime); - - if (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) - printf(_("Clock not changed - testing only.\n")); - else { - if (badyear) { - /* - * Write the real year to a file, then write a fake year - * between 1995 and 1998 to the RTC. This way, Award BIOS boots - * on 29 Feb 2000 thinking that it's 29 Feb 1996. - */ - write_date_to_file (&new_broken_time); - new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3); - } - ur->set_hardware_clock(&new_broken_time); - } -} + const bool universal, const bool testing) +{ + struct tm new_broken_time; + /* + * Time to which we will set Hardware Clock, in broken down format, + * in the time zone of caller's choice + */ + + if (universal) + new_broken_time = *gmtime(&newtime); + else + new_broken_time = *localtime(&newtime); + if (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) + printf(_("Clock not changed - testing only.\n")); + else { + if (badyear) { + /* + * Write the real year to a file, then write a fake + * year between 1995 and 1998 to the RTC. This way, + * Award BIOS boots on 29 Feb 2000 thinking that + * it's 29 Feb 1996. + */ + write_date_to_file(&new_broken_time); + new_broken_time.tm_year = + 95 + ((new_broken_time.tm_year + 1) & 3); + } + ur->set_hardware_clock(&new_broken_time); + } +} +/* + * Set the Hardware Clock to the time "sethwtime", in local time zone or + * UTC, according to "universal". + * + * Wait for a fraction of a second so that "sethwtime" is the value of the + * Hardware Clock as of system time "refsystime", which is in the past. For + * example, if "sethwtime" is 14:03:05 and "refsystime" is 12:10:04.5 and + * the current system time is 12:10:06.0: Wait .5 seconds (to make exactly 2 + * seconds since "refsystime") and then set the Hardware Clock to 14:03:07, + * thus getting a precise and retroactive setting of the clock. + * + * (Don't be confused by the fact that the system clock and the Hardware + * Clock differ by two hours in the above example. That's just to remind you + * that there are two independent time scales here). + * + * This function ought to be able to accept set times as fractional times. + * 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 the Hardware Clock to the time "sethwtime", in local time zone or UTC, - according to "universal". - - Wait for a fraction of a second so that "sethwtime" is the value of - the Hardware Clock as of system time "refsystime", which is in the past. - For example, if "sethwtime" is 14:03:05 and "refsystime" is 12:10:04.5 - and the current system time is 12:10:06.0: Wait .5 seconds (to make - exactly 2 seconds since "refsystime") and then set the Hardware Clock - to 14:03:07, thus getting a precise and retroactive setting of the clock. - - (Don't be confused by the fact that the system clock and the Hardware - Clock differ by two hours in the above example. That's just to remind - you that there are two independent time scales here). - - This function ought to be able to accept set times as fractional times. - Idea for future enhancement. ------------------------------------------------------------------------------*/ - - time_t newhwtime; - struct timeval beginsystime, nowsystime; - double tdiff; + const struct timeval refsystime, + const bool universal, const bool testing) +{ + time_t newhwtime; + struct timeval beginsystime, nowsystime; + double tdiff; time_resync: - gettimeofday(&beginsystime, NULL); - tdiff = time_diff(beginsystime, refsystime); - newhwtime = sethwtime + (int) (tdiff + 0.5); - if (debug) - printf(_("Time elapsed since reference time has been %.6f seconds.\n" - "Delaying further to reach the new time.\n"), tdiff); - - /* - * Now delay some more until Hardware Clock time newhwtime arrives. The 0.5 s - * is because the Hardware Clock always sets to your set time plus 500 ms - * (because it is designed to update to the next second precisely 500 ms - * after you finish the setting). - */ - do { - gettimeofday(&nowsystime, NULL); - tdiff = time_diff(nowsystime, beginsystime); - if (tdiff < 0) - goto time_resync; /* probably backward time reset */ - if (tdiff > 0.1) - goto time_resync; /* probably forward time reset */ - beginsystime = nowsystime; - tdiff = time_diff(nowsystime, refsystime); - } while (newhwtime == sethwtime + (int) (tdiff + 0.5)); - - set_hardware_clock(newhwtime, universal, testing); + gettimeofday(&beginsystime, NULL); + tdiff = time_diff(beginsystime, refsystime); + newhwtime = sethwtime + (int)(tdiff + 0.5); + if (debug) + printf(_ + ("Time elapsed since reference time has been %.6f seconds.\n" + "Delaying further to reach the new time.\n"), tdiff); + + /* + * Now delay some more until Hardware Clock time newhwtime arrives. + * The 0.5 s is because the Hardware Clock always sets to your set + * time plus 500 ms (because it is designed to update to the next + * second precisely 500 ms after you finish the setting). + */ + do { + gettimeofday(&nowsystime, NULL); + tdiff = time_diff(nowsystime, beginsystime); + if (tdiff < 0) + goto time_resync; /* probably backward time reset */ + if (tdiff > 0.1) + goto time_resync; /* probably forward time reset */ + beginsystime = nowsystime; + tdiff = time_diff(nowsystime, refsystime); + } while (newhwtime == sethwtime + (int)(tdiff + 0.5)); + + set_hardware_clock(newhwtime, universal, testing); } - - +/* + * Put the time "systime" on standard output in display format. Except if + * hclock_valid == false, just tell standard output that we don't know what + * time it is. + * + * Include in the output the adjustment "sync_duration". + */ static void display_time(const bool hclock_valid, const time_t systime, - const double sync_duration) { -/*---------------------------------------------------------------------------- - Put the time "systime" on standard output in display format. - Except if hclock_valid == false, just tell standard output that we don't - know what time it is. - - Include in the output the adjustment "sync_duration". ------------------------------------------------------------------------------*/ - if (!hclock_valid) - fprintf(stderr, _("The Hardware Clock registers contain values that are " - "either invalid (e.g. 50th day of month) or beyond the range " - "we can handle (e.g. Year 2095).\n")); - else { - struct tm *lt; - char *format = "%c"; - char ctime_now[200]; - - lt = localtime(&systime); - strftime(ctime_now, sizeof(ctime_now), format, lt); - printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration)); - } -} - - - -static int -interpret_date_string(const char *date_opt, time_t * const time_p) { -/*---------------------------------------------------------------------------- - Interpret the value of the --date option, which is something like - "13:05:01". In fact, it can be any of the myriad ASCII strings that specify - a time which the "date" program can understand. The date option value in - question is our "dateopt" argument. - - The specified time is in the local time zone. - - Our output, "*time_p", is a seconds-into-epoch time. + const double sync_duration) +{ + if (!hclock_valid) + fprintf(stderr, + _ + ("The Hardware Clock registers contain values that are " + "either invalid (e.g. 50th day of month) or beyond the range " + "we can handle (e.g. Year 2095).\n")); + else { + struct tm *lt; + char *format = "%c"; + char ctime_now[200]; - We use the "date" program to interpret the date string. "date" must be - runnable by issuing the command "date" to the /bin/sh shell. That means - in must be in the current PATH. + lt = localtime(&systime); + strftime(ctime_now, sizeof(ctime_now), format, lt); + printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration)); + } +} - 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. -----------------------------------------------------------------------------*/ +/* + * Interpret the value of the --date option, which is something like + * "13:05:01". In fact, it can be any of the myriad ASCII strings that + * specify a time which the "date" program can understand. The date option + * value in question is our "dateopt" argument. + * + * The specified time is in the local time zone. + * + * Our output, "*time_p", is a seconds-into-epoch time. + * + * We use the "date" program to interpret the date string. "date" must be + * runnable by issuing the command "date" to the /bin/sh shell. That means + * in must be in the current PATH. + * + * 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) +{ FILE *date_child_fp; char date_resp[100]; - const char magic[]="seconds-into-epoch="; + const char magic[] = "seconds-into-epoch="; char date_command[100]; - int retcode; /* our eventual return code */ - int rc; /* local return code */ + int retcode; /* our eventual return code */ + int rc; /* local return code */ if (date_opt == NULL) { fprintf(stderr, _("No --date option specified.\n")); @@ -624,8 +626,9 @@ interpret_date_string(const char *date_opt, time_t * const time_p) { /* Quotes in date_opt would ruin the date command we construct. */ if (strchr(date_opt, '"') != NULL) { fprintf(stderr, - _("The value of the --date option is not a valid date.\n" - "In particular, it contains quotation marks.\n")); + _ + ("The value of the --date option is not a valid date.\n" + "In particular, it contains quotation marks.\n")); return 12; } @@ -642,10 +645,10 @@ 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 */ + date_resp[0] = '\0'; /* in case fgets fails */ if (debug) printf(_("response from date command = %s\n"), date_resp); - if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) { + if (strncmp(date_resp, magic, sizeof(magic) - 1) != 0) { fprintf(stderr, _("The date command issued by %s returned " "unexpected results.\n" "The command was:\n %s\n" @@ -654,7 +657,7 @@ interpret_date_string(const char *date_opt, time_t * const time_p) { retcode = 8; } else { long seconds_since_epoch; - rc = sscanf(date_resp + sizeof(magic)-1, "%ld", + rc = sscanf(date_resp + sizeof(magic) - 1, "%ld", &seconds_since_epoch); if (rc < 1) { fprintf(stderr, @@ -671,7 +674,7 @@ interpret_date_string(const char *date_opt, time_t * const time_p) { if (debug) printf(_("date string %s equates to " "%ld seconds since 1969.\n"), - date_opt, (long) *time_p); + date_opt, (long)*time_p); } } pclose(date_child_fp); @@ -679,173 +682,181 @@ interpret_date_string(const char *date_opt, time_t * const time_p) { return retcode; } - - +/* + * Set the System Clock to time 'newtime'. + * + * Also set the kernel time zone value to the value indicated by the TZ + * environment variable and/or /usr/lib/zoneinfo/, interpreted as tzset() + * would interpret them. + * + * EXCEPT: if hclock_valid is false, just issue an error message saying + * there is no valid time in the Hardware Clock to which to set the system + * time. + * + * If 'testing' is true, don't actually update anything -- just say we would + * have. + */ static int set_system_clock(const bool hclock_valid, const time_t newtime, - const bool testing) { -/*---------------------------------------------------------------------------- - Set the System Clock to time 'newtime'. - - Also set the kernel time zone value to the value indicated by the - TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as - tzset() would interpret them. - - EXCEPT: if hclock_valid is false, just issue an error message - saying there is no valid time in the Hardware Clock to which to set - the system time. - - If 'testing' is true, don't actually update anything -- just say we - would have. ------------------------------------------------------------------------------*/ - int retcode; - - if (!hclock_valid) { - fprintf(stderr, _("The Hardware Clock does not contain a valid time, so " - "we cannot set the System Time from it.\n")); - retcode = 1; - } else { - struct timeval tv; - struct tm *broken; - int minuteswest; - int rc; - - tv.tv_sec = newtime; - tv.tv_usec = 0; - - broken = localtime(&newtime); + const bool testing) +{ + int retcode; + + if (!hclock_valid) { + fprintf(stderr, + _ + ("The Hardware Clock does not contain a valid time, so " + "we cannot set the System Time from it.\n")); + retcode = 1; + } else { + struct timeval tv; + struct tm *broken; + int minuteswest; + int rc; + + tv.tv_sec = newtime; + tv.tv_usec = 0; + + broken = localtime(&newtime); #ifdef HAVE_TM_GMTOFF - minuteswest = -broken->tm_gmtoff/60; /* GNU extension */ + minuteswest = -broken->tm_gmtoff / 60; /* GNU extension */ #else - minuteswest = timezone/60; - if (broken->tm_isdst) - minuteswest -= 60; + minuteswest = timezone / 60; + if (broken->tm_isdst) + minuteswest -= 60; #endif - if (debug) { - printf(_("Calling settimeofday:\n")); - printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"), - (long) tv.tv_sec, (long) tv.tv_usec); - printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest); - } - if (testing) { - printf(_("Not setting system clock because running in test mode.\n")); - retcode = 0; - } else { - const struct timezone tz = { minuteswest, 0 }; - - rc = settimeofday(&tv, &tz); - if (rc) { - if (errno == EPERM) { - fprintf(stderr, - _("Must be superuser to set system clock.\n")); - retcode = EX_NOPERM; - } else { - outsyserr(_("settimeofday() failed")); - retcode = 1; - } - } else retcode = 0; - } - } - return retcode; + if (debug) { + printf(_("Calling settimeofday:\n")); + printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"), + (long)tv.tv_sec, (long)tv.tv_usec); + printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest); + } + if (testing) { + printf(_ + ("Not setting system clock because running in test mode.\n")); + retcode = 0; + } else { + const struct timezone tz = { minuteswest, 0 }; + + rc = settimeofday(&tv, &tz); + if (rc) { + if (errno == EPERM) { + fprintf(stderr, + _ + ("Must be superuser to set system clock.\n")); + retcode = EX_NOPERM; + } else { + outsyserr(_("settimeofday() failed")); + retcode = 1; + } + } else + retcode = 0; + } + } + return retcode; } +/* + * Reset the System Clock from local time to UTC, based on its current value + * and the timezone unless universal is TRUE. + * + * Also set the kernel time zone value to the value indicated by the TZ + * environment variable and/or /usr/lib/zoneinfo/, interpreted as tzset() + * would interpret them. + * + * 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) +{ + int retcode; + struct timeval tv; + struct tm *broken; + int minuteswest; + int rc; + + gettimeofday(&tv, NULL); + if (debug) { + struct tm broken_time; + char ctime_now[200]; + + broken_time = *gmtime(&tv.tv_sec); + strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", + &broken_time); + printf(_("Current system time: %ld = %s\n"), (long)tv.tv_sec, + ctime_now); + } -static int -set_system_clock_timezone(const bool universal, const bool testing) { -/*---------------------------------------------------------------------------- - Reset the System Clock from local time to UTC, based on its current - value and the timezone unless universal is TRUE. - - Also set the kernel time zone value to the value indicated by the - TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as - tzset() would interpret them. - - If 'testing' is true, don't actually update anything -- just say we - would have. ------------------------------------------------------------------------------*/ - int retcode; - struct timeval tv; - struct tm *broken; - int minuteswest; - int rc; - - gettimeofday(&tv, NULL); - if (debug) { - struct tm broken_time; - char ctime_now[200]; - - broken_time = *gmtime(&tv.tv_sec); - strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", &broken_time); - printf(_("Current system time: %ld = %s\n"), (long) tv.tv_sec, ctime_now); - } - - broken = localtime(&tv.tv_sec); + broken = localtime(&tv.tv_sec); #ifdef HAVE_TM_GMTOFF - minuteswest = -broken->tm_gmtoff/60; /* GNU extension */ + minuteswest = -broken->tm_gmtoff / 60; /* GNU extension */ #else - minuteswest = timezone/60; - if (broken->tm_isdst) - minuteswest -= 60; + minuteswest = timezone / 60; + if (broken->tm_isdst) + minuteswest -= 60; #endif - gettimeofday(&tv, NULL); - if (!universal) - tv.tv_sec += minuteswest * 60; - - if (debug) { - struct tm broken_time; - char ctime_now[200]; - - broken_time = *gmtime(&tv.tv_sec); - strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", &broken_time); - - printf(_("Calling settimeofday:\n")); - printf(_("\tUTC: %s\n"), ctime_now); - printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"), - (long) tv.tv_sec, (long) tv.tv_usec); - printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest); - } - if (testing) { - printf(_("Not setting system clock because running in test mode.\n")); - retcode = 0; - } else { - const struct timezone tz = { minuteswest, 0 }; - - rc = settimeofday(&tv, &tz); - if (rc) { - if (errno == EPERM) { - fprintf(stderr, - _("Must be superuser to set system clock.\n")); - retcode = EX_NOPERM; - } else { - outsyserr(_("settimeofday() failed")); - retcode = 1; - } - } else retcode = 0; - } - return retcode; -} + gettimeofday(&tv, NULL); + if (!universal) + tv.tv_sec += minuteswest * 60; + if (debug) { + struct tm broken_time; + char ctime_now[200]; + + broken_time = *gmtime(&tv.tv_sec); + strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", + &broken_time); + + printf(_("Calling settimeofday:\n")); + printf(_("\tUTC: %s\n"), ctime_now); + printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"), + (long)tv.tv_sec, (long)tv.tv_usec); + printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest); + } + if (testing) { + printf(_ + ("Not setting system clock because running in test mode.\n")); + retcode = 0; + } else { + const struct timezone tz = { minuteswest, 0 }; + rc = settimeofday(&tv, &tz); + if (rc) { + if (errno == EPERM) { + fprintf(stderr, + _ + ("Must be superuser to set system clock.\n")); + retcode = EX_NOPERM; + } else { + outsyserr(_("settimeofday() failed")); + retcode = 1; + } + } else + retcode = 0; + } + return retcode; +} + +/* + * Update the drift factor in <*adjtime_p> to reflect the fact that the + * Hardware Clock was calibrated to and before that was set to + * . + * + * We record in the adjtime file the time at which we last calibrated the + * clock so we can compute the drift rate each time we calibrate. + * + * EXCEPT: if is false, assume Hardware Clock was not set + * before to anything meaningful and regular adjustments have not been done, + * so don't adjust the drift factor. + */ static void adjust_drift_factor(struct adjtime *adjtime_p, - const time_t nowtime, - const bool hclock_valid, - const time_t hclocktime, - const double sync_delay) { -/*------------------------------------------------------------------------ - Update the drift factor in <*adjtime_p> to reflect the fact that the - Hardware Clock was calibrated to and before that was set - to . - - We record in the adjtime file the time at which we last calibrated - the clock so we can compute the drift rate each time we calibrate. - - EXCEPT: if is false, assume Hardware Clock was not set - before to anything meaningful and regular adjustments have not been - done, so don't adjust the drift factor. - ------------------------------------------------------------------------*/ + const time_t nowtime, + const bool hclock_valid, + const time_t hclocktime, const double sync_delay) +{ if (!hclock_valid) { if (debug) printf(_("Not adjusting drift factor because the " @@ -867,9 +878,9 @@ adjust_drift_factor(struct adjtime *adjtime_p, * At adjustment time we adjust the hardware clock according * to the contents of /etc/adjtime. * - * At calibration time we set the hardware clock and - * update /etc/adjtime, that is, for each calibration - * (except the first) we also do an adjustment. + * At calibration time we set the hardware clock and update + * /etc/adjtime, that is, for each calibration (except the + * first) we also do an adjustment. * * We are now at calibration time. * @@ -887,21 +898,21 @@ adjust_drift_factor(struct adjtime *adjtime_p, /* Days since last adjustment (in hardware clock time) */ adj_days = (double)(hclocktime - adjtime_p->last_adj_time) - / sec_per_day; + / sec_per_day; /* Expected drift (sec) since last adjustment */ exp_drift = adj_days * adjtime_p->drift_factor - + adjtime_p->not_adjusted; + + adjtime_p->not_adjusted; /* Uncorrected drift (sec) since last calibration */ unc_drift = (double)(nowtime - hclocktime) - + sync_delay - exp_drift; + + sync_delay - exp_drift; /* Days since last calibration (in hardware clock time) */ cal_days = ((double)(adjtime_p->last_adj_time - - adjtime_p->last_calib_time) + - adjtime_p->last_calib_time) + adjtime_p->not_adjusted) - / (sec_per_day * atime_per_htime) + adj_days; + / (sec_per_day * atime_per_htime) + adj_days; /* Amount to add to previous drift factor */ factor_adjust = unc_drift / cal_days; @@ -912,9 +923,8 @@ adjust_drift_factor(struct adjtime *adjtime_p, "%f seconds/day.\n" "Adjusting drift factor by %f seconds/day\n"), unc_drift, - (int) (nowtime - adjtime_p->last_calib_time), - adjtime_p->drift_factor, - factor_adjust); + (int)(nowtime - adjtime_p->last_calib_time), + adjtime_p->drift_factor, factor_adjust); adjtime_p->drift_factor += factor_adjust; } @@ -927,383 +937,403 @@ adjust_drift_factor(struct adjtime *adjtime_p, adjtime_p->dirty = TRUE; } - - +/* + * Do the drift adjustment calculation. + * + * The way we have to set the clock, we need the adjustment in two parts: + * + * 1) an integer number of seconds (return as *adjustment_p) + * 2) a positive fraction of a second (less than 1) (return as *retro_p) + * + * The sum of these two values is the adjustment needed. Positive means to + * advance the clock or insert seconds. Negative means to retard the clock + * or remove seconds. + */ static void calculate_adjustment(const double factor, - const time_t last_time, - const double not_adjusted, - const time_t systime, - int *adjustment_p, - double *retro_p) { -/*---------------------------------------------------------------------------- - Do the drift adjustment calculation. - - The way we have to set the clock, we need the adjustment in two parts: - - 1) an integer number of seconds (return as *adjustment_p) - - 2) a positive fraction of a second (less than 1) (return as *retro_p) - - The sum of these two values is the adjustment needed. Positive means to - advance the clock or insert seconds. Negative means to retard the clock - or remove seconds. -----------------------------------------------------------------------------*/ - double exact_adjustment; - - exact_adjustment = ((double) (systime - last_time)) * factor / (24 * 60 * 60) - + not_adjusted; - *adjustment_p = FLOOR(exact_adjustment); - - *retro_p = exact_adjustment - (double) *adjustment_p; - if (debug) { - printf (_("Time since last adjustment is %d seconds\n"), - (int) (systime - last_time)); - printf (_("Need to insert %d seconds and refer time back " - "%.6f seconds ago\n"), - *adjustment_p, *retro_p); - } -} - + const time_t last_time, + const double not_adjusted, + const time_t systime, int *adjustment_p, double *retro_p) +{ + double exact_adjustment; + exact_adjustment = + ((double)(systime - last_time)) * factor / (24 * 60 * 60) + + not_adjusted; + *adjustment_p = FLOOR(exact_adjustment); -static void -save_adjtime(const struct adjtime adjtime, const bool testing) { -/*----------------------------------------------------------------------------- - Write the contents of the structure to its disk file. - - But if the contents are clean (unchanged since read from disk), don't - bother. ------------------------------------------------------------------------------*/ - char newfile[412]; /* Stuff to write to disk file */ - - if (adjtime.dirty) { - /* snprintf is not always available, but this is safe - as long as libc does not use more than 100 positions for %ld or %f */ - sprintf(newfile, "%f %ld %f\n%ld\n%s\n", - adjtime.drift_factor, - (long) adjtime.last_adj_time, - adjtime.not_adjusted, - (long) adjtime.last_calib_time, - (adjtime.local_utc == UTC) ? "UTC" : "LOCAL"); - - if (testing) { - printf(_("Not updating adjtime file because of testing mode.\n")); - printf(_("Would have written the following to %s:\n%s"), - adj_file_name, newfile); - } else { - FILE *adjfile; - int err = 0; - - adjfile = fopen(adj_file_name, "w"); - if (adjfile == NULL) { - outsyserr(_("Could not open file with the clock adjustment parameters " - "in it (%s) for writing"), adj_file_name); - err = 1; - } else { - if (fputs(newfile, adjfile) < 0) { - outsyserr(_("Could not update file with the clock adjustment " - "parameters (%s) in it"), adj_file_name); - err = 1; - } - if (fclose(adjfile) < 0) { - outsyserr(_("Could not update file with the clock adjustment " - "parameters (%s) in it"), adj_file_name); - err = 1; - } - } - if (err) - fprintf(stderr, _("Drift adjustment parameters not updated.\n")); - } - } + *retro_p = exact_adjustment - (double)*adjustment_p; + if (debug) { + printf(_("Time since last adjustment is %d seconds\n"), + (int)(systime - last_time)); + printf(_("Need to insert %d seconds and refer time back " + "%.6f seconds ago\n"), *adjustment_p, *retro_p); + } } +/* + * Write the contents of the structure to its disk file. + * + * 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) +{ + char newfile[412]; /* Stuff to write to disk file */ + if (adjtime.dirty) { + /* + * snprintf is not always available, but this is safe as + * long as libc does not use more than 100 positions for %ld + * or %f + */ + sprintf(newfile, "%f %ld %f\n%ld\n%s\n", + adjtime.drift_factor, + (long)adjtime.last_adj_time, + adjtime.not_adjusted, + (long)adjtime.last_calib_time, + (adjtime.local_utc == UTC) ? "UTC" : "LOCAL"); + + if (testing) { + printf(_ + ("Not updating adjtime file because of testing mode.\n")); + printf(_("Would have written the following to %s:\n%s"), + adj_file_name, newfile); + } else { + FILE *adjfile; + int err = 0; + + adjfile = fopen(adj_file_name, "w"); + if (adjfile == NULL) { + outsyserr(_ + ("Could not open file with the clock adjustment parameters " + "in it (%s) for writing"), + adj_file_name); + err = 1; + } else { + if (fputs(newfile, adjfile) < 0) { + outsyserr(_ + ("Could not update file with the clock adjustment " + "parameters (%s) in it"), + adj_file_name); + err = 1; + } + if (fclose(adjfile) < 0) { + outsyserr(_ + ("Could not update file with the clock adjustment " + "parameters (%s) in it"), + adj_file_name); + err = 1; + } + } + if (err) + fprintf(stderr, + _ + ("Drift adjustment parameters not updated.\n")); + } + } +} +/* + * Do the adjustment requested, by 1) setting the Hardware Clock (if + * necessary), and 2) updating the last-adjusted time in the adjtime + * structure. + * + * Do not update anything if the Hardware Clock does not currently present a + * valid time. + * + * Arguments and are current values from the adjtime + * file. + * + * means the Hardware Clock contains a valid time, and that + * time is . + * + * is the current system time (to be precise, it is the system + * time at the time was read, which due to computational delay + * could be a short time ago). + * + * : the Hardware Clock is kept in UTC. + * + * : We are running in test mode (no updating of clock). + * + * We do not bother to update the clock if the adjustment would be less than + * one second. This is to avoid cumulative error and needless CPU hogging + * (remember we use an infinite loop for some timing) if the user runs us + * frequently. + */ static void do_adjustment(struct adjtime *adjtime_p, - const bool hclock_valid, const time_t hclocktime, - const struct timeval read_time, - const bool universal, const bool testing) { -/*--------------------------------------------------------------------------- - Do the adjustment requested, by 1) setting the Hardware Clock (if - necessary), and 2) updating the last-adjusted time in the adjtime - structure. - - Do not update anything if the Hardware Clock does not currently present - a valid time. - - arguments and are current values from the adjtime - file. - - means the Hardware Clock contains a valid time, and that - time is . - - is the current system time (to be precise, it is the system - time at the time was read, which due to computational delay - could be a short time ago). - - : the Hardware Clock is kept in UTC. - - : We are running in test mode (no updating of clock). - - We do not bother to update the clock if the adjustment would be less than - one second. This is to avoid cumulative error and needless CPU hogging - (remember we use an infinite loop for some timing) if the user runs us - frequently. - -----------------------------------------------------------------------------*/ - if (!hclock_valid) { - fprintf(stderr, _("The Hardware Clock does not contain a valid time, " - "so we cannot adjust it.\n")); - adjtime_p->last_calib_time = 0; /* calibration startover is required */ - adjtime_p->last_adj_time = 0; - adjtime_p->not_adjusted = 0; - adjtime_p->dirty = TRUE; - } else if (adjtime_p->last_adj_time == 0) { - if (debug) - printf(_("Not setting clock because last adjustment time is zero, " - "so history is bad.")); - } else { - int adjustment; - /* Number of seconds we must insert in the Hardware Clock */ - double retro; - /* Fraction of second we have to remove from clock after inserting - whole seconds. - */ - calculate_adjustment(adjtime_p->drift_factor, - adjtime_p->last_adj_time, - adjtime_p->not_adjusted, - hclocktime, - &adjustment, &retro); - if (adjustment > 0 || adjustment < -1) { - set_hardware_clock_exact(hclocktime + adjustment, - time_inc(read_time, -retro), - universal, testing); - adjtime_p->last_adj_time = hclocktime + adjustment; - adjtime_p->not_adjusted = 0; - adjtime_p->dirty = TRUE; - } else - if (debug) - printf(_("Needed adjustment is less than one second, " - "so not setting clock.\n")); - } + const bool hclock_valid, const time_t hclocktime, + const struct timeval read_time, + const bool universal, const bool testing) +{ + if (!hclock_valid) { + fprintf(stderr, + _("The Hardware Clock does not contain a valid time, " + "so we cannot adjust it.\n")); + adjtime_p->last_calib_time = 0; /* calibration startover is required */ + adjtime_p->last_adj_time = 0; + adjtime_p->not_adjusted = 0; + adjtime_p->dirty = TRUE; + } else if (adjtime_p->last_adj_time == 0) { + if (debug) + printf(_ + ("Not setting clock because last adjustment time is zero, " + "so history is bad.")); + } else { + int adjustment; + /* Number of seconds we must insert in the Hardware Clock */ + double retro; + /* + * Fraction of second we have to remove from clock after + * inserting whole seconds. + */ + calculate_adjustment(adjtime_p->drift_factor, + adjtime_p->last_adj_time, + adjtime_p->not_adjusted, + hclocktime, &adjustment, &retro); + if (adjustment > 0 || adjustment < -1) { + set_hardware_clock_exact(hclocktime + adjustment, + time_inc(read_time, -retro), + universal, testing); + adjtime_p->last_adj_time = hclocktime + adjustment; + adjtime_p->not_adjusted = 0; + adjtime_p->dirty = TRUE; + } else if (debug) + printf(_("Needed adjustment is less than one second, " + "so not setting clock.\n")); + } } +static void determine_clock_access_method(const bool user_requests_ISA) +{ + ur = NULL; - -static void -determine_clock_access_method(const bool user_requests_ISA) { - - ur = NULL; - - if (user_requests_ISA) - ur = probe_for_cmos_clock(); + if (user_requests_ISA) + ur = probe_for_cmos_clock(); #ifdef __linux__ - if (!ur) - ur = probe_for_rtc_clock(); + if (!ur) + ur = probe_for_rtc_clock(); #endif - if (!ur) - ur = probe_for_kd_clock(); + if (!ur) + ur = probe_for_kd_clock(); - if (!ur && !user_requests_ISA) - ur = probe_for_cmos_clock(); + if (!ur && !user_requests_ISA) + ur = probe_for_cmos_clock(); - if (debug) { - if (ur) - printf(_("Using %s.\n"), ur->interface_name); - else - printf(_("No usable clock interface found.\n")); - } + if (debug) { + if (ur) + printf(_("Using %s.\n"), ur->interface_name); + else + printf(_("No usable clock interface found.\n")); + } } +/* + * Do all the normal work of hwclock - read, set clock, etc. + * + * Issue output to stdout and error message to stderr where appropriate. + * + * 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 testing, const bool predict) { -/*--------------------------------------------------------------------------- - Do all the normal work of hwclock - read, set clock, etc. - - Issue output to stdout and error message to stderr where appropriate. - - Return rc == 0 if everything went OK, rc != 0 if not. -----------------------------------------------------------------------------*/ - struct adjtime adjtime; - /* Contents of the adjtime file, or what they should be. */ - int rc; /* local return code */ - bool no_auth; /* User lacks necessary authorization to access the clock */ - - if (!systz && !predict) { - no_auth = ur->get_permissions(); - if (no_auth) - return EX_NOPERM; - } - - if (!noadjfile && (adjust || set || systohc || (!utc && !local_opt) || predict)) { - rc = read_adjtime(&adjtime); - if (rc) - return rc; - } else { - /* A little trick to avoid reading the file if we don't have to */ - adjtime.dirty = FALSE; - rc = 0; - } - - { - const bool 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; - } - - { - struct timeval read_time; - /* The time at which we read the Hardware Clock */ - - bool hclock_valid = FALSE; - /* The Hardware Clock gives us a valid time, or at least something - close enough to fool mktime(). - */ - - time_t hclocktime = 0; - /* The time the hardware clock had just after we - synchronized to its next clock tick when we started up. - Defined only if hclock_valid is true. - */ + 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 testing, const bool predict) +{ + /* Contents of the adjtime file, or what they should be. */ + struct adjtime adjtime; + bool universal; + /* Set if user lacks necessary authorization to access the clock */ + bool no_auth; + /* The time at which we read the Hardware Clock */ + struct timeval read_time; + /* + * The Hardware Clock gives us a valid time, or at + * least something close enough to fool mktime(). + */ + bool hclock_valid = FALSE; + /* + * The time the hardware clock had just after we + * synchronized to its next clock tick when we + * started up. Defined only if hclock_valid is true. + */ + time_t hclocktime = 0; + /* local return code */ + int rc; + + if (!systz && !predict) { + no_auth = ur->get_permissions(); + if (no_auth) + return EX_NOPERM; + } + + if (!noadjfile + && (adjust || set || systohc || (!utc && !local_opt) || predict)) { + rc = read_adjtime(&adjtime); + if (rc) + return rc; + } else { + /* A little trick to avoid reading the file if we don't have to */ + adjtime.dirty = FALSE; + rc = 0; + } + + universal = hw_clock_is_utc(utc, local_opt, adjtime); + + if ((set || systohc || adjust) && + (adjtime.local_utc == UTC) != universal) { + adjtime.local_utc = universal ? UTC : LOCAL; + adjtime.dirty = TRUE; + } if (show || adjust || hctosys || (!noadjfile && !systz && !predict)) { - /* data from HW-clock are required */ - rc = synchronize_to_clock_tick(); - - /* 2 = synchronization timeout. We don't error out if the user is - attempting to set the RTC - the RTC could be functioning but - contain invalid time data so we still want to allow a user to set - the RTC time. - */ - - if (rc && rc != 2 && !set && !systohc) - return EX_IOERR; - gettimeofday(&read_time, NULL); - - /* If we can't synchronize to a clock tick, we likely can't read - from the RTC so don't bother reading it again. */ - if (!rc) { - rc = read_hardware_clock(universal, &hclock_valid, &hclocktime); - if (rc && !set && !systohc) - return EX_IOERR; - } + /* data from HW-clock are required */ + rc = synchronize_to_clock_tick(); + + /* + * 2 = synchronization timeout. We don't + * error out if the user is attempting to + * set the RTC - the RTC could be + * functioning but contain invalid time data + * so we still want to allow a user to set + * the RTC time. + */ + if (rc && rc != 2 && !set && !systohc) + return EX_IOERR; + gettimeofday(&read_time, NULL); + + /* + * If we can't synchronize to a clock tick, + * we likely can't read from the RTC so + * don't bother reading it again. + */ + if (!rc) { + rc = read_hardware_clock(universal, + &hclock_valid, &hclocktime); + if (rc && !set && !systohc) + return EX_IOERR; + } } - if (show) { - display_time(hclock_valid, 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, set_time, hclock_valid, hclocktime, - time_diff(read_time, startup_time)); - } else if (adjust) { - do_adjustment(&adjtime, hclock_valid, hclocktime, - read_time, universal, testing); - } else if (systohc) { - struct timeval nowtime, reftime; - /* We can only set_hardware_clock_exact to a whole seconds - time, so we set it with reference to the most recent - whole seconds time. - */ - 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, (time_t) reftime.tv_sec, hclock_valid, - hclocktime, (double) read_time.tv_usec / 1E6); - } else if (hctosys) { - rc = set_system_clock(hclock_valid, hclocktime, testing); - if (rc) { - printf(_("Unable to set system clock.\n")); - return rc; - } + if (show) { + display_time(hclock_valid, 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, set_time, + hclock_valid, + hclocktime, + time_diff(read_time, startup_time)); + } else if (adjust) { + do_adjustment(&adjtime, hclock_valid, + hclocktime, read_time, universal, testing); + } else if (systohc) { + struct timeval nowtime, reftime; + /* + * We can only set_hardware_clock_exact to a + * whole seconds time, so we set it with + * reference to the most recent whole + * seconds time. + */ + 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, (time_t) + reftime.tv_sec, + hclock_valid, hclocktime, (double) + read_time.tv_usec / 1E6); + } else if (hctosys) { + rc = set_system_clock(hclock_valid, hclocktime, testing); + if (rc) { + printf(_("Unable to set system clock.\n")); + return rc; + } } else if (systz) { - rc = set_system_clock_timezone(universal, testing); - if (rc) { - printf(_("Unable to set system clock.\n")); - return rc; - } - } else if (predict) { - int adjustment; - double retro; - - calculate_adjustment(adjtime.drift_factor, - adjtime.last_adj_time, - adjtime.not_adjusted, - set_time, - &adjustment, &retro); - if (debug) { - printf(_("At %ld seconds after 1969, RTC is predicted to read %ld seconds after 1969.\n"), - set_time, set_time + adjustment); - } - display_time(TRUE, set_time + adjustment, -retro); - } - if (!noadjfile) - save_adjtime(adjtime, testing); - } - } - return 0; + rc = set_system_clock_timezone(universal, testing); + if (rc) { + printf(_("Unable to set system clock.\n")); + return rc; + } + } else if (predict) { + int adjustment; + double retro; + + calculate_adjustment(adjtime.drift_factor, + adjtime.last_adj_time, + adjtime.not_adjusted, + set_time, &adjustment, &retro); + if (debug) { + printf(_ + ("At %ld seconds after 1969, RTC is predicted to read %ld seconds after 1969.\n"), + set_time, set_time + adjustment); + } + display_time(TRUE, set_time + adjustment, -retro); + } + if (!noadjfile) + save_adjtime(adjtime, testing); + return 0; } - +/* + * Get or set the Hardware Clock epoch value in the kernel, as appropriate. + * , , and are hwclock invocation options. + * + * == -1 if the user did not specify an "epoch" option. + */ #ifdef __linux__ static void manipulate_epoch(const bool getepoch, const bool setepoch, - const int epoch_opt, const bool testing) { -/*---------------------------------------------------------------------------- - Get or set the Hardware Clock epoch value in the kernel, as appropriate. - , , and are hwclock invocation options. - - == -1 if the user did not specify an "epoch" option. - ------------------------------------------------------------------------------*/ - /* - Maintenance note: This should work on non-Alpha machines, but the - evidence today (98.03.04) indicates that the kernel only keeps the - epoch value on Alphas. If that is ever fixed, this function should be - changed. - */ - + const int epoch_opt, const bool testing) +{ + /* + * Maintenance note: This should work on non-Alpha machines, but the + * evidence today (98.03.04) indicates that the kernel only keeps + * the epoch value on Alphas. If that is ever fixed, this function + * should be changed. + */ #ifndef __alpha__ - fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock " - "only on an Alpha machine.\nThis copy of hwclock was built for " - "a machine other than Alpha\n(and thus is presumably not running " - "on an Alpha now). No action taken.\n")); + fprintf(stderr, + _("The kernel keeps an epoch value for the Hardware Clock " + "only on an Alpha machine.\nThis copy of hwclock was built for " + "a machine other than Alpha\n(and thus is presumably not running " + "on an Alpha now). No action taken.\n")); #else - if (getepoch) { - unsigned long epoch; - - if (get_epoch_rtc(&epoch, 0)) - fprintf(stderr, _("Unable to get the epoch value from the kernel.\n")); - else - printf(_("Kernel is assuming an epoch value of %lu\n"), epoch); - } else if (setepoch) { - if (epoch_opt == -1) - fprintf(stderr, _("To set the epoch value, you must use the 'epoch' " - "option to tell to what value to set it.\n")); - else if (testing) - printf(_("Not setting the epoch to %d - testing only.\n"), - epoch_opt); - else if (set_epoch_rtc(epoch_opt)) - printf(_("Unable to set the epoch value in the kernel.\n")); - } + if (getepoch) { + unsigned long epoch; + + if (get_epoch_rtc(&epoch, 0)) + fprintf(stderr, + _ + ("Unable to get the epoch value from the kernel.\n")); + else + printf(_("Kernel is assuming an epoch value of %lu\n"), + epoch); + } else if (setepoch) { + if (epoch_opt == -1) + fprintf(stderr, + _ + ("To set the epoch value, you must use the 'epoch' " + "option to tell to what value to set it.\n")); + else if (testing) + printf(_ + ("Not setting the epoch to %d - testing only.\n"), + epoch_opt); + else if (set_epoch_rtc(epoch_opt)) + printf(_ + ("Unable to set the epoch value in the kernel.\n")); + } #endif } #endif @@ -1314,123 +1344,118 @@ manipulate_epoch(const bool getepoch, const bool setepoch, #define RTC_DEV "/dev/rtc" #endif -static void -out_version(void) { +static void out_version(void) +{ printf(_("%s from %s\n"), MYNAME, PACKAGE_STRING); } /* - usage - Output (error and) usage information - - This function is called both directly from main to show usage - information and as fatal function from shhopt if some argument is - not understood. In case of normal usage info FMT should be NULL. - In that case the info is printed to stdout. If FMT is given - usage will act like fprintf( stderr, fmt, ... ), show a usage - information and terminate the program afterwards. -*/ -static void -usage( const char *fmt, ... ) { - FILE *usageto; - va_list ap; - - usageto = fmt ? stderr : stdout; - - fprintf( usageto, _( - "hwclock - query and set the hardware clock (RTC)\n\n" - "Usage: hwclock [function] [options...]\n\n" - "Functions:\n" - " -h | --help show this help\n" - " -r | --show read hardware clock and print result\n" - " --set set the rtc to the time given with --date\n" - " -s | --hctosys set the system time from the hardware clock\n" - " -w | --systohc set the hardware clock to the current system time\n" - " --systz set the system time based on the current timezone\n" - " --adjust adjust the rtc to account for systematic drift since\n" - " the clock was last set or adjusted\n" + * usage - Output (error and) usage information + * + * This function is called both directly from main to show usage information + * and as fatal function from shhopt if some argument is not understood. In + * case of normal usage info FMT should be NULL. In that case the info is + * printed to stdout. If FMT is given usage will act like fprintf( stderr, + * fmt, ... ), show a usage information and terminate the program + * afterwards. + */ +static void usage(const char *fmt, ...) +{ + FILE *usageto; + va_list ap; + + usageto = fmt ? stderr : stdout; + + fprintf(usageto, + _("hwclock - query and set the hardware clock (RTC)\n\n" + "Usage: hwclock [function] [options...]\n\n" "Functions:\n" + " -h | --help show this help\n" + " -r | --show read hardware clock and print result\n" + " --set set the rtc to the time given with --date\n" + " -s | --hctosys set the system time from the hardware clock\n" + " -w | --systohc set the hardware clock to the current system time\n" + " --systz set the system time based on the current timezone\n" + " --adjust adjust the rtc to account for systematic drift since\n" + " the clock was last set or adjusted\n" #ifdef __linux__ - " --getepoch print out the kernel's hardware clock epoch value\n" - " --setepoch set the kernel's hardware clock epoch value to the \n" - " value given with --epoch\n" + " --getepoch print out the kernel's hardware clock epoch value\n" + " --setepoch set the kernel's hardware clock epoch value to the \n" + " value given with --epoch\n" #endif - " --predict predict rtc reading at time given with --date\n" - " -v | --version print out the version of hwclock to stdout\n" - "\nOptions: \n" - " -u | --utc the hardware clock is kept in UTC\n" - " --localtime the hardware clock is kept in local time\n" + " --predict predict rtc reading at time given with --date\n" + " -v | --version print out the version of hwclock to stdout\n" + "\nOptions: \n" + " -u | --utc the hardware clock is kept in UTC\n" + " --localtime the hardware clock is kept in local time\n" #ifdef __linux__ - " -f | --rtc=path special /dev/... file to use instead of default\n" + " -f | --rtc=path special /dev/... file to use instead of default\n" #endif - " --directisa access the ISA bus directly instead of %s\n" - " --badyear ignore rtc's year because the bios is broken\n" - " --date specifies the time to which to set the hardware clock\n" - " --epoch=year specifies the year which is the beginning of the \n" - " hardware clock's epoch value\n" - " --noadjfile do not access /etc/adjtime. Requires the use of\n" - " either --utc or --localtime\n" - " --adjfile=path specifies the path to the adjust file (default is\n" - " /etc/adjtime)\n" - " --test do everything except actually updating the hardware\n" - " clock or anything else\n" - " -D | --debug debug mode\n" - "\n" - ),RTC_DEV); + " --directisa access the ISA bus directly instead of %s\n" + " --badyear ignore rtc's year because the bios is broken\n" + " --date specifies the time to which to set the hardware clock\n" + " --epoch=year specifies the year which is the beginning of the \n" + " hardware clock's epoch value\n" + " --noadjfile do not access /etc/adjtime. Requires the use of\n" + " either --utc or --localtime\n" + " --adjfile=path specifies the path to the adjust file (default is\n" + " /etc/adjtime)\n" + " --test do everything except actually updating the hardware\n" + " clock or anything else\n" + " -D | --debug debug mode\n" "\n"), RTC_DEV); #ifdef __alpha__ - fprintf(usageto, _( - " -J|--jensen, -A|--arc, -S|--srm, -F|--funky-toy\n" - " tell hwclock the type of alpha you have (see hwclock(8))\n" - "\n" - ) ); + fprintf(usageto, _(" -J|--jensen, -A|--arc, -S|--srm, -F|--funky-toy\n" + " tell hwclock the type of alpha you have (see hwclock(8))\n" + "\n")); #endif - fflush(stdout); - if (fmt) { - usageto = stderr; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - } + fflush(stdout); + if (fmt) { + usageto = stderr; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + } - hwclock_exit(fmt ? EX_USAGE : 0); + hwclock_exit(fmt ? EX_USAGE : 0); } static const struct option longopts[] = { - { "adjust", 0, 0, 'a' }, - { "help", 0, 0, 'h' }, - { "show", 0, 0, 'r' }, - { "hctosys", 0, 0, 's' }, - { "utc", 0, 0, 'u' }, - { "version", 0, 0, 'v' }, - { "systohc", 0, 0, 'w' }, - { "debug", 0, 0, 'D' }, + {"adjust", 0, 0, 'a'}, + {"help", 0, 0, 'h'}, + {"show", 0, 0, 'r'}, + {"hctosys", 0, 0, 's'}, + {"utc", 0, 0, 'u'}, + {"version", 0, 0, 'v'}, + {"systohc", 0, 0, 'w'}, + {"debug", 0, 0, 'D'}, #ifdef __alpha__ - { "ARC", 0, 0, 'A' }, - { "arc", 0, 0, 'A' }, - { "Jensen", 0, 0, 'J' }, - { "jensen", 0, 0, 'J' }, - { "SRM", 0, 0, 'S' }, - { "srm", 0, 0, 'S' }, - { "funky-toy", 0, 0, 'F'}, + {"ARC", 0, 0, 'A'}, + {"arc", 0, 0, 'A'}, + {"Jensen", 0, 0, 'J'}, + {"jensen", 0, 0, 'J'}, + {"SRM", 0, 0, 'S'}, + {"srm", 0, 0, 'S'}, + {"funky-toy", 0, 0, 'F'}, #endif - { "set", 0, 0, 128 }, + {"set", 0, 0, 128}, #ifdef __linux__ - { "getepoch", 0, 0, 129 }, - { "setepoch", 0, 0, 130 }, + {"getepoch", 0, 0, 129}, + {"setepoch", 0, 0, 130}, #endif - { "noadjfile", 0, 0, 131 }, - { "localtime", 0, 0, 132 }, - { "badyear", 0, 0, 133 }, - { "directisa", 0, 0, 134 }, - { "test", 0, 0, 135 }, - { "date", 1, 0, 136 }, - { "epoch", 1, 0, 137 }, + {"noadjfile", 0, 0, 131}, + {"localtime", 0, 0, 132}, + {"badyear", 0, 0, 133}, + {"directisa", 0, 0, 134}, + {"test", 0, 0, 135}, + {"date", 1, 0, 136}, + {"epoch", 1, 0, 137}, #ifdef __linux__ - { "rtc", 1, 0, 'f' }, + {"rtc", 1, 0, 'f'}, #endif - { "adjfile", 1, 0, 138 }, - { "systz", 0, 0, 139 }, - { "predict-hc", 0, 0, 140 }, - { NULL, 0, 0, 0 } + {"adjfile", 1, 0, 138}, + {"systz", 0, 0, 139}, + {"predict-hc", 0, 0, 140}, + {NULL, 0, 0, 0} }; /* @@ -1442,20 +1467,22 @@ static const struct option longopts[] = { * 0: OK (or not) * 1: failure */ -int -main(int argc, char **argv) { - +int main(int argc, char **argv) +{ struct timeval startup_time; - /* The time we started up, in seconds into the epoch, including - fractions. */ - time_t set_time = 0; /* Time to which user said to set Hardware Clock */ + /* + * The time we started up, in seconds into the epoch, including + * fractions. + */ + time_t set_time = 0; /* Time to which user said to set Hardware Clock */ - bool permitted; /* User is permitted to do the function */ + bool permitted; /* User is permitted to do the function */ 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; + bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch, + predict; bool utc, testing, local_opt, noadjfile, directisa; char *date_opt; #ifdef __alpha__ @@ -1468,32 +1495,37 @@ main(int argc, char **argv) { hwaudit_fd = audit_open(); if (hwaudit_fd < 0 && !(errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)) { - /* You get these error codes only when the kernel doesn't have - * audit compiled in. */ + /* + * You get these error codes only when the kernel doesn't + * have audit compiled in. + */ fprintf(stderr, _("%s: Unable to connect to audit system\n"), - MYNAME); + MYNAME); return EX_NOPERM; } #endif setlocale(LC_ALL, ""); #ifdef LC_NUMERIC - /* We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid - LC_NUMERIC since it gives problems when we write to /etc/adjtime. - - gqueri@mail.dotcom.fr */ + /* + * We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid + * LC_NUMERIC since it gives problems when we write to /etc/adjtime. + * - gqueri@mail.dotcom.fr + */ setlocale(LC_NUMERIC, "C"); #endif bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); /* Set option defaults */ - show = set = systohc = hctosys = systz = adjust = noadjfile = predict = FALSE; + show = set = systohc = hctosys = systz = adjust = noadjfile = predict = + FALSE; getepoch = setepoch = utc = local_opt = testing = debug = FALSE; #ifdef __alpha__ ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE; #endif date_opt = NULL; - while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL)) + while ((c = getopt_long(argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL)) != -1) { switch (c) { case 'D': @@ -1543,7 +1575,7 @@ main(int argc, char **argv) { noadjfile = TRUE; break; case 132: - local_opt = TRUE; /* --localtime */ + local_opt = TRUE; /* --localtime */ break; case 133: badyear = TRUE; @@ -1552,33 +1584,33 @@ main(int argc, char **argv) { directisa = TRUE; break; case 135: - testing = TRUE; /* --test */ + testing = TRUE; /* --test */ break; case 136: - date_opt = optarg; /* --date */ + date_opt = optarg; /* --date */ break; case 137: epoch_option = atoi(optarg); /* --epoch */ break; case 138: - adj_file_name = optarg; /* --adjfile */ + adj_file_name = optarg; /* --adjfile */ break; case 139: - systz = TRUE; /* --systz */ + systz = TRUE; /* --systz */ break; case 140: - predict = TRUE; /* --predict-hc */ + predict = TRUE; /* --predict-hc */ break; #ifdef __linux__ case 'f': - rtc_dev_name = optarg; /* --rtc */ + rtc_dev_name = optarg; /* --rtc */ break; #endif - case 'v': /* --version */ + case 'v': /* --version */ case 'V': out_version(); return 0; - case 'h': /* --help */ + case 'h': /* --help */ case '?': default: usage(NULL); @@ -1591,19 +1623,18 @@ main(int argc, char **argv) { #ifdef HAVE_LIBAUDIT if (testing != TRUE) { if (adjust == TRUE || hctosys == TRUE || systohc == TRUE || - set == TRUE || setepoch == TRUE) { + set == TRUE || setepoch == TRUE) { hwaudit_on = TRUE; } } #endif if (argc > 0) { usage(_("%s takes no non-option arguments. " - "You supplied %d.\n"), - MYNAME, argc); + "You supplied %d.\n"), MYNAME, argc); } if (show + set + systohc + hctosys + systz + adjust + getepoch - + setepoch + predict > 1){ + + setepoch + predict > 1) { fprintf(stderr, _("You have specified multiple functions.\n" "You can only perform one function " "at a time.\n")); @@ -1638,7 +1669,6 @@ main(int argc, char **argv) { "either --utc or --localtime\n"), MYNAME); hwclock_exit(EX_USAGE); } - #ifdef __alpha__ set_cmos_epoch(ARCconsole, SRM); set_cmos_access(Jensen, funky_toy); @@ -1656,8 +1686,7 @@ main(int argc, char **argv) { if (!(show | set | systohc | hctosys | systz | adjust | getepoch | setepoch | predict)) - show = 1; /* default to show */ - + show = 1; /* default to show */ if (getuid() == 0) permitted = TRUE; @@ -1710,15 +1739,15 @@ main(int argc, char **argv) { } rc = manipulate_clock(show, adjust, noadjfile, set, set_time, - hctosys, systohc, systz, startup_time, utc, - local_opt, testing, predict); + hctosys, systohc, systz, startup_time, utc, + local_opt, testing, predict); hwclock_exit(rc); - return rc; /* Not reached */ + return rc; /* Not reached */ } /* A single routine for greater uniformity */ -void -outsyserr(char *msg, ...) { +void outsyserr(char *msg, ...) +{ va_list args; int errsv = errno; @@ -1726,144 +1755,130 @@ outsyserr(char *msg, ...) { va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); - fprintf(stderr, ", errno=%d: %s.\n", - errsv, strerror(errsv)); + fprintf(stderr, ", errno=%d: %s.\n", errsv, strerror(errsv)); } - #ifdef HAVE_LIBAUDIT -void -hwaudit_exit(int status) +void hwaudit_exit(int status) { if (hwaudit_on) { audit_log_user_message(hwaudit_fd, AUDIT_USYS_CONFIG, - "changing system time", NULL, NULL, NULL, status ? 0 : 1); + "changing system time", NULL, NULL, NULL, + status ? 0 : 1); close(hwaudit_fd); } exit(status); } #endif -/**************************************************************************** - - History of this program: - - 98.08.12 BJH Version 2.4 - - Don't use century byte from Hardware Clock. Add comments telling why. - - - 98.06.20 BJH Version 2.3. - - Make --hctosys set the kernel timezone from TZ environment variable - and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com). - - 98.03.05 BJH. Version 2.2. - - Add --getepoch and --setepoch. - - Fix some word length things so it works on Alpha. - - Make it work when /dev/rtc doesn't have the interrupt functions. - In this case, busywait for the top of a second instead of blocking and - waiting for the update complete interrupt. - - Fix a bunch of bugs too numerous to mention. - - 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte - 50) of the ISA Hardware Clock when using direct ISA I/O. Problem - discovered by job (jei@iclnl.icl.nl). - - Use the rtc clock access method in preference to the KDGHWCLK method. - Problem discovered by Andreas Schwab . - - November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt - (janl@math.uio.no) to make it compile on linux 1.2 machines as well - as more recent versions of the kernel. Introduced the NO_CLOCK - access method and wrote feature test code to detect absense of rtc - headers. - - -************************************************************************** - Maintenance notes - - To compile this, you must use GNU compiler optimization (-O option) - in order to make the "extern inline" functions from asm/io.h (inb(), - etc.) compile. If you don't optimize, which means the compiler - will generate no inline functions, the references to these functions - in this program will be compiled as external references. Since you - probably won't be linking with any functions by these names, you will - have unresolved external references when you link. - - The program is designed to run setuid superuser, since we need to be - able to do direct I/O. (More to the point: we need permission to - execute the iopl() system call). (However, if you use one of the - methods other than direct ISA I/O to access the clock, no setuid is - required). - - Here's some info on how we must deal with the time that elapses while - this program runs: There are two major delays as we run: - - 1) Waiting up to 1 second for a transition of the Hardware Clock so - we are synchronized to the Hardware Clock. - - 2) Running the "date" program to interpret the value of our --date - option. - - Reading the /etc/adjtime file is the next biggest source of delay and - uncertainty. - - The user wants to know what time it was at the moment he invoked us, - not some arbitrary time later. And in setting the clock, he is - giving us the time at the moment we are invoked, so if we set the - clock some time later, we have to add some time to that. - - So we check the system time as soon as we start up, then run "date" - and do file I/O if necessary, then wait to synchronize with a - Hardware Clock edge, then check the system time again to see how - much time we spent. We immediately read the clock then and (if - appropriate) report that time, and additionally, the delay we measured. - - If we're setting the clock to a time given by the user, we wait some - more so that the total delay is an integral number of seconds, then - set the Hardware Clock to the time the user requested plus that - integral number of seconds. N.B. The Hardware Clock can only be set - in integral seconds. - - If we're setting the clock to the system clock value, we wait for - the system clock to reach the top of a second, and then set the - Hardware Clock to the system clock's value. - - Here's an interesting point about setting the Hardware Clock: On my - machine, when you set it, it sets to that precise time. But one can - imagine another clock whose update oscillator marches on a steady one - second period, so updating the clock between any two oscillator ticks - is the same as updating it right at the earlier tick. To avoid any - complications that might cause, we set the clock as soon as possible - after an oscillator tick. - - - About synchronizing to the Hardware Clock when reading the time: The - precision of the Hardware Clock counters themselves is one second. - You can't read the counters and find out that is 12:01:02.5. But if - you consider the location in time of the counter's ticks as part of - its value, then its precision is as infinite as time is continuous! - What I'm saying is this: To find out the _exact_ time in the - hardware clock, we wait until the next clock tick (the next time the - second counter changes) and measure how long we had to wait. We - then read the value of the clock counters and subtract the wait time - and we know precisely what time it was when we set out to query the - time. - - hwclock uses this method, and considers the Hardware Clock to have - infinite precision. - - - Enhancements needed: - - - When waiting for whole second boundary in set_hardware_clock_exact, - fail if we miss the goal by more than .1 second, as could happen if - we get pre-empted (by the kernel dispatcher). - -****************************************************************************/ - +/* + * History of this program: + * + * 98.08.12 BJH Version 2.4 + * + * Don't use century byte from Hardware Clock. Add comments telling why. + * + * 98.06.20 BJH Version 2.3. + * + * Make --hctosys set the kernel timezone from TZ environment variable + * and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com). + * + * 98.03.05 BJH. Version 2.2. + * + * Add --getepoch and --setepoch. + * + * Fix some word length things so it works on Alpha. + * + * Make it work when /dev/rtc doesn't have the interrupt functions. In this + * case, busywait for the top of a second instead of blocking and waiting + * for the update complete interrupt. + * + * Fix a bunch of bugs too numerous to mention. + * + * 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte 50) of + * the ISA Hardware Clock when using direct ISA I/O. Problem discovered by + * job (jei@iclnl.icl.nl). + * + * Use the rtc clock access method in preference to the KDGHWCLK method. + * Problem discovered by Andreas Schwab . + * + * November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt + * (janl@math.uio.no) to make it compile on linux 1.2 machines as well as + * more recent versions of the kernel. Introduced the NO_CLOCK access method + * and wrote feature test code to detect absense of rtc headers. + * + *************************************************************************** + * Maintenance notes + * + * To compile this, you must use GNU compiler optimization (-O option) in + * order to make the "extern inline" functions from asm/io.h (inb(), etc.) + * compile. If you don't optimize, which means the compiler will generate no + * inline functions, the references to these functions in this program will + * be compiled as external references. Since you probably won't be linking + * with any functions by these names, you will have unresolved external + * references when you link. + * + * The program is designed to run setuid superuser, since we need to be able + * to do direct I/O. (More to the point: we need permission to execute the + * iopl() system call). (However, if you use one of the methods other than + * direct ISA I/O to access the clock, no setuid is required). + * + * Here's some info on how we must deal with the time that elapses while + * this program runs: There are two major delays as we run: + * + * 1) Waiting up to 1 second for a transition of the Hardware Clock so + * we are synchronized to the Hardware Clock. + * 2) Running the "date" program to interpret the value of our --date + * option. + * + * Reading the /etc/adjtime file is the next biggest source of delay and + * uncertainty. + * + * The user wants to know what time it was at the moment he invoked us, not + * some arbitrary time later. And in setting the clock, he is giving us the + * time at the moment we are invoked, so if we set the clock some time + * later, we have to add some time to that. + * + * So we check the system time as soon as we start up, then run "date" and + * do file I/O if necessary, then wait to synchronize with a Hardware Clock + * edge, then check the system time again to see how much time we spent. We + * immediately read the clock then and (if appropriate) report that time, + * and additionally, the delay we measured. + * + * If we're setting the clock to a time given by the user, we wait some more + * so that the total delay is an integral number of seconds, then set the + * Hardware Clock to the time the user requested plus that integral number + * of seconds. N.B. The Hardware Clock can only be set in integral seconds. + * + * If we're setting the clock to the system clock value, we wait for the + * system clock to reach the top of a second, and then set the Hardware + * Clock to the system clock's value. + * + * Here's an interesting point about setting the Hardware Clock: On my + * machine, when you set it, it sets to that precise time. But one can + * imagine another clock whose update oscillator marches on a steady one + * second period, so updating the clock between any two oscillator ticks is + * the same as updating it right at the earlier tick. To avoid any + * complications that might cause, we set the clock as soon as possible + * after an oscillator tick. + * + * About synchronizing to the Hardware Clock when reading the time: The + * precision of the Hardware Clock counters themselves is one second. You + * can't read the counters and find out that is 12:01:02.5. But if you + * consider the location in time of the counter's ticks as part of its + * value, then its precision is as infinite as time is continuous! What I'm + * saying is this: To find out the _exact_ time in the hardware clock, we + * wait until the next clock tick (the next time the second counter changes) + * and measure how long we had to wait. We then read the value of the clock + * counters and subtract the wait time and we know precisely what time it + * was when we set out to query the time. + * + * hwclock uses this method, and considers the Hardware Clock to have + * infinite precision. + * + * TODO: Enhancements needed: + * + * - When waiting for whole second boundary in set_hardware_clock_exact, + * fail if we miss the goal by more than .1 second, as could happen if we + * get pre-empted (by the kernel dispatcher). + */ -- cgit v1.2.3-55-g7522