4 * clock.c was written by Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992
5 * Modified for clock adjustments - Rob Hooft <hooft@chem.ruu.nl>, Nov 1992
6 * Improvements by Harald Koenig <koenig@nova.tat.physik.uni-tuebingen.de>
7 * and Alan Modra <alan@spri.levels.unisa.edu.au>.
9 * Major rewrite by Bryan Henderson <bryanh@giraffe-data.com>, 96.09.19.
10 * The new program is called hwclock. New features:
11 * - You can set the hardware clock without also modifying the system clock.
12 * - You can read and set the clock with finer than 1 second precision.
13 * - When you set the clock, hwclock automatically refigures the drift
14 * rate, based on how far off the clock was before you set it.
16 * Reshuffled things, added sparc code, and re-added alpha stuff
17 * by David Mosberger <davidm@azstarnet.com>
18 * and Jay Estabrook <jestabro@amt.tay1.dec.com>
19 * and Martin Ostermann <ost@coments.rwth-aachen.de>, aeb@cwi.nl, 990212.
21 * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98
22 * Change of local time handling, Stefan Ring <e9725446@stud3.tuwien.ac.at>
23 * Change of adjtime handling, James P. Rutledge <ao112@rgfn.epcc.edu>.
25 * Distributed under GPL
29 * clock [-u] -r - read hardware clock
30 * clock [-u] -w - write hardware clock from system time
31 * clock [-u] -s - set system time from hardware clock
32 * clock [-u] -a - set system time from hardware clock, adjust the time
33 * to correct for systematic error, and write it back to
35 * -u indicates cmos clock is kept in universal time
36 * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980)
37 * -J indicates we're dealing with a Jensen (early DEC Alpha PC)
41 * Explanation of `adjusting' (Rob Hooft):
43 * The problem with my machine is that its CMOS clock is 10 seconds
44 * per day slow. With this version of clock.c, and my '/etc/rc.local'
45 * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error
46 * is automatically corrected at every boot.
48 * To do this job, the program reads and writes the file '/etc/adjtime'
49 * to determine the correction, and to save its data. In this file are
52 * 1) the correction in seconds per day. (So if your clock runs 5
53 * seconds per day fast, the first number should read -5.0)
54 * 2) the number of seconds since 1/1/1970 the last time the program
56 * 3) the remaining part of a second which was leftover after the last
59 * Installation and use of this program:
61 * a) create a file '/etc/adjtime' containing as the first and only line:
63 * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in
64 * universal or local time. This updates the second number.
65 * c) set your system time using the 'date' command.
66 * d) update your cmos time using 'clock -wu' or 'clock -w'
67 * e) replace the first number in /etc/adjtime by your correction.
68 * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local'
74 #include <sys/ioctl.h>
90 static int hwaudit_fd = -1;
91 static int hwaudit_on;
94 #define MYNAME "hwclock"
96 char *progname = MYNAME;
98 /* The struct that holds our hardware access routines */
101 #define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1));
103 /* Here the information for time adjustments is kept. */
104 #define ADJPATH "/etc/adjtime"
106 const char *adj_file_name = NULL;
108 /* Store the date here when "badyear" flag is set. */
109 #define LASTDATE "/var/lib/lastdate"
112 /* This is information we keep in the adjtime file that tells us how
113 to do drift corrections. Elements are all straight from the
114 adjtime file, so see documentation of that file for details.
115 Exception is <dirty>, which is an indication that what's in this
116 structure is not what's in the disk file (because it has been
117 updated since read from the disk file).
123 time_t last_adj_time;
127 time_t last_calib_time;
128 /* The most recent time that we set the clock from an external
129 authority (as opposed to just doing a drift adjustment) */
132 enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc;
133 /* To which time zone, local or UTC, we most recently set the
138 /* We are running in debug mode, wherein we put a lot of information about
139 what we're doing to standard output. */
142 /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */
144 int epoch_option = -1;
145 /* User-specified epoch, used when rtc fails to return epoch. */
148 * Almost all Award BIOS's made between 04/26/94 and 05/31/95
149 * have a nasty bug limiting the RTC year byte to the range 94-99.
150 * Any year between 2000 and 2093 gets changed to 2094, every time
151 * you start the system.
152 * With the --badyear option, we write the date to file and hope
153 * that the file is updated at least once a year.
154 * I recommend putting this command "hwclock --badyear" in the monthly
155 * crontab, just to be safe. -- Dave Coffin 11/12/98
158 write_date_to_file (struct tm *tm) {
161 if ((fp = fopen(LASTDATE,"w"))) {
162 fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1,
170 read_date_from_file (struct tm *tm) {
171 int last_mday, last_mon, last_year;
174 if ((fp = fopen(LASTDATE,"r"))) {
175 if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) {
176 tm->tm_year = last_year-1900;
177 if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday)
182 write_date_to_file (tm);
186 time_diff(struct timeval subtrahend, struct timeval subtractor) {
187 /*---------------------------------------------------------------------------
188 The difference in seconds between two times in "timeval" format.
189 ----------------------------------------------------------------------------*/
190 return (subtrahend.tv_sec - subtractor.tv_sec)
191 + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6;
195 static struct timeval
196 time_inc(struct timeval addend, double increment) {
197 /*----------------------------------------------------------------------------
198 The time, in "timeval" format, which is <increment> seconds after
199 the time <addend>. Of course, <increment> may be negative.
200 -----------------------------------------------------------------------------*/
201 struct timeval newtime;
203 newtime.tv_sec = addend.tv_sec + (int) increment;
204 newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6;
206 /* Now adjust it so that the microsecond value is between 0 and 1 million */
207 if (newtime.tv_usec < 0) {
208 newtime.tv_usec += 1E6;
210 } else if (newtime.tv_usec >= 1E6) {
211 newtime.tv_usec -= 1E6;
219 hw_clock_is_utc(const bool utc, const bool local_opt,
220 const struct adjtime adjtime) {
224 ret = TRUE; /* --utc explicitly given on command line */
226 ret = FALSE; /* --localtime explicitly given */
228 /* get info from adjtime file - default is local */
229 ret = (adjtime.local_utc == UTC);
231 printf(_("Assuming hardware clock is kept in %s time.\n"),
232 ret ? _("UTC") : _("local"));
239 read_adjtime(struct adjtime *adjtime_p) {
240 /*----------------------------------------------------------------------------
241 Read the adjustment parameters out of the /etc/adjtime file.
243 Return them as the adjtime structure <*adjtime_p>.
244 If there is no /etc/adjtime file, return defaults.
245 If values are missing from the file, return defaults for them.
247 return value 0 if all OK, !=0 otherwise.
249 -----------------------------------------------------------------------------*/
251 int rc; /* local return code */
252 struct stat statbuf; /* We don't even use the contents of this. */
254 rc = stat(adj_file_name, &statbuf);
255 if (rc < 0 && errno == ENOENT) {
256 /* He doesn't have a adjtime file, so we'll use defaults. */
257 adjtime_p->drift_factor = 0;
258 adjtime_p->last_adj_time = 0;
259 adjtime_p->not_adjusted = 0;
260 adjtime_p->last_calib_time = 0;
261 adjtime_p->local_utc = UNKNOWN;
262 adjtime_p->dirty = FALSE; /* don't create a zero adjfile */
267 adjfile = fopen(adj_file_name, "r"); /* open file for reading */
268 if (adjfile == NULL) {
269 outsyserr("cannot open file %s", adj_file_name);
274 char line1[81]; /* String: first line of adjtime file */
275 char line2[81]; /* String: second line of adjtime file */
276 char line3[81]; /* String: third line of adjtime file */
279 if (!fgets(line1, sizeof(line1), adjfile))
280 line1[0] = '\0'; /* In case fgets fails */
281 if (!fgets(line2, sizeof(line2), adjfile))
282 line2[0] = '\0'; /* In case fgets fails */
283 if (!fgets(line3, sizeof(line3), adjfile))
284 line3[0] = '\0'; /* In case fgets fails */
288 /* Set defaults in case values are missing from file */
289 adjtime_p->drift_factor = 0;
290 adjtime_p->last_adj_time = 0;
291 adjtime_p->not_adjusted = 0;
292 adjtime_p->last_calib_time = 0;
295 sscanf(line1, "%lf %ld %lf",
296 &adjtime_p->drift_factor,
298 &adjtime_p->not_adjusted);
299 adjtime_p->last_adj_time = timeval;
301 sscanf(line2, "%ld", &timeval);
302 adjtime_p->last_calib_time = timeval;
304 if (!strcmp(line3, "UTC\n"))
305 adjtime_p->local_utc = UTC;
306 else if (!strcmp(line3, "LOCAL\n"))
307 adjtime_p->local_utc = LOCAL;
309 adjtime_p->local_utc = UNKNOWN;
312 _("%s: Warning: unrecognized third line in adjtime file\n"),
314 fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n"));
318 adjtime_p->dirty = FALSE;
321 printf(_("Last drift adjustment done at %ld seconds after 1969\n"),
322 (long) adjtime_p->last_adj_time);
323 printf(_("Last calibration done at %ld seconds after 1969\n"),
324 (long) adjtime_p->last_calib_time);
325 printf(_("Hardware clock is on %s time\n"),
326 (adjtime_p->local_utc == LOCAL) ? _("local") :
327 (adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown"));
335 synchronize_to_clock_tick(void) {
336 /*-----------------------------------------------------------------------------
337 Wait until the falling edge of the Hardware Clock's update flag so
338 that any time that is read from the clock immediately after we
339 return will be exact.
341 The clock only has 1 second precision, so it gives the exact time only
342 once per second, right on the falling edge of the update flag.
344 We wait (up to one second) either blocked waiting for an rtc device
345 or in a CPU spin loop. The former is probably not very accurate.
347 Return 0 if it worked, nonzero if it didn't.
348 -----------------------------------------------------------------------------*/
351 if (debug) printf(_("Waiting for clock tick...\n"));
353 rc = ur->synchronize_to_clock_tick();
357 printf(_("...synchronization failed\n"));
359 printf(_("...got clock tick\n"));
368 mktime_tz(struct tm tm, const bool universal,
369 bool *valid_p, time_t *systime_p) {
370 /*-----------------------------------------------------------------------------
371 Convert a time in broken down format (hours, minutes, etc.) into standard
372 unix time (seconds into epoch). Return it as *systime_p.
374 The broken down time is argument <tm>. This broken down time is either in
375 local time zone or UTC, depending on value of logical argument "universal".
376 True means it is in UTC.
378 If the argument contains values that do not constitute a valid time,
379 and mktime() recognizes this, return *valid_p == false and
380 *systime_p undefined. However, mktime() sometimes goes ahead and
381 computes a fictional time "as if" the input values were valid,
382 e.g. if they indicate the 31st day of April, mktime() may compute
383 the time of May 1. In such a case, we return the same fictional
384 value mktime() does as *systime_p and return *valid_p == true.
386 -----------------------------------------------------------------------------*/
387 time_t mktime_result; /* The value returned by our mktime() call */
388 char *zone; /* Local time zone name */
390 /* We use the C library function mktime(), but since it only works on
391 local time zone input, we may have to fake it out by temporarily
392 changing the local time zone to UTC.
394 zone = getenv("TZ"); /* remember original time zone */
396 /* Set timezone to UTC */
397 setenv("TZ", "", TRUE);
398 /* Note: tzset() gets called implicitly by the time code, but only the
399 first time. When changing the environment variable, better call
404 mktime_result = mktime(&tm);
405 if (mktime_result == -1) {
406 /* This apparently (not specified in mktime() documentation) means
407 the 'tm' structure does not contain valid values (however, not
408 containing valid values does _not_ imply mktime() returns -1).
413 printf(_("Invalid values in hardware clock: "
414 "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"),
415 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
416 tm.tm_hour, tm.tm_min, tm.tm_sec);
419 *systime_p = mktime_result;
421 printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
422 "%ld seconds since 1969\n"),
423 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
424 tm.tm_hour, tm.tm_min, tm.tm_sec, (long) *systime_p);
426 /* now put back the original zone. */
427 if (zone) setenv("TZ", zone, TRUE);
434 read_hardware_clock(const bool universal, bool *valid_p, time_t *systime_p){
435 /*----------------------------------------------------------------------------
436 Read the hardware clock and return the current time via <tm> argument.
438 Use the method indicated by <method> argument to access the hardware clock.
439 -----------------------------------------------------------------------------*/
443 err = ur->read_hardware_clock(&tm);
448 read_date_from_file(&tm);
451 printf (_("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"),
452 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
453 tm.tm_hour, tm.tm_min, tm.tm_sec);
454 mktime_tz(tm, universal, valid_p, systime_p);
461 set_hardware_clock(const time_t newtime,
462 const bool universal,
463 const bool testing) {
464 /*----------------------------------------------------------------------------
465 Set the Hardware Clock to the time <newtime>, in local time zone or UTC,
466 according to <universal>.
467 ----------------------------------------------------------------------------*/
469 struct tm new_broken_time;
470 /* Time to which we will set Hardware Clock, in broken down format, in
471 the time zone of caller's choice
475 new_broken_time = *gmtime(&newtime);
477 new_broken_time = *localtime(&newtime);
480 printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d "
481 "= %ld seconds since 1969\n"),
482 new_broken_time.tm_hour, new_broken_time.tm_min,
483 new_broken_time.tm_sec, (long) newtime);
486 printf(_("Clock not changed - testing only.\n"));
490 * Write the real year to a file, then write a fake year
491 * between 1995 and 1998 to the RTC. This way, Award BIOS boots
492 * on 29 Feb 2000 thinking that it's 29 Feb 1996.
494 write_date_to_file (&new_broken_time);
495 new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3);
497 err = ur->set_hardware_clock(&new_broken_time);
504 set_hardware_clock_exact(const time_t sethwtime,
505 const struct timeval refsystime,
506 const bool universal,
507 const bool testing) {
508 /*----------------------------------------------------------------------------
509 Set the Hardware Clock to the time "sethwtime", in local time zone or UTC,
510 according to "universal".
512 Wait for a fraction of a second so that "sethwtime" is the value of
513 the Hardware Clock as of system time "refsystime", which is in the past.
514 For example, if "sethwtime" is 14:03:05 and "refsystime" is 12:10:04.5
515 and the current system time is 12:10:06.0: Wait .5 seconds (to make
516 exactly 2 seconds since "refsystime") and then set the Hardware Clock
517 to 14:03:07, thus getting a precise and retroactive setting of the clock.
519 (Don't be confused by the fact that the system clock and the Hardware
520 Clock differ by two hours in the above example. That's just to remind
521 you that there are two independent time scales here).
523 This function ought to be able to accept set times as fractional times.
524 Idea for future enhancement.
525 -----------------------------------------------------------------------------*/
528 struct timeval beginsystime, nowsystime;
532 gettimeofday(&beginsystime, NULL);
533 tdiff = time_diff(beginsystime, refsystime);
534 newhwtime = sethwtime + (int) (tdiff + 0.5);
536 printf(_("Time elapsed since reference time has been %.6f seconds.\n"
537 "Delaying further to reach the new time.\n"), tdiff);
540 * Now delay some more until Hardware Clock time newhwtime arrives. The 0.5 s
541 * is because the Hardware Clock always sets to your set time plus 500 ms
542 * (because it is designed to update to the next second precisely 500 ms
543 * after you finish the setting).
546 gettimeofday(&nowsystime, NULL);
547 tdiff = time_diff(nowsystime, beginsystime);
549 goto time_resync; /* probably backward time reset */
551 goto time_resync; /* probably forward time reset */
552 beginsystime = nowsystime;
553 tdiff = time_diff(nowsystime, refsystime);
554 } while (newhwtime == sethwtime + (int) (tdiff + 0.5));
556 set_hardware_clock(newhwtime, universal, testing);
562 display_time(const bool hclock_valid, const time_t systime,
563 const double sync_duration) {
564 /*----------------------------------------------------------------------------
565 Put the time "systime" on standard output in display format.
566 Except if hclock_valid == false, just tell standard output that we don't
567 know what time it is.
569 Include in the output the adjustment "sync_duration".
570 -----------------------------------------------------------------------------*/
572 fprintf(stderr, _("The Hardware Clock registers contain values that are "
573 "either invalid (e.g. 50th day of month) or beyond the range "
574 "we can handle (e.g. Year 2095).\n"));
580 lt = localtime(&systime);
581 strftime(ctime_now, sizeof(ctime_now), format, lt);
582 printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration));
589 interpret_date_string(const char *date_opt, time_t * const time_p) {
590 /*----------------------------------------------------------------------------
591 Interpret the value of the --date option, which is something like
592 "13:05:01". In fact, it can be any of the myriad ASCII strings that specify
593 a time which the "date" program can understand. The date option value in
594 question is our "dateopt" argument.
596 The specified time is in the local time zone.
598 Our output, "*time_p", is a seconds-into-epoch time.
600 We use the "date" program to interpret the date string. "date" must be
601 runnable by issuing the command "date" to the /bin/sh shell. That means
602 in must be in the current PATH.
604 If anything goes wrong (and many things can), we return return code
605 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p
607 ----------------------------------------------------------------------------*/
610 const char magic[]="seconds-into-epoch=";
611 char date_command[100];
612 int retcode; /* our eventual return code */
613 int rc; /* local return code */
615 if (date_opt == NULL) {
616 fprintf(stderr, _("No --date option specified.\n"));
620 /* prevent overflow - a security risk */
621 if (strlen(date_opt) > sizeof(date_command) - 50) {
622 fprintf(stderr, _("--date argument too long\n"));
626 /* Quotes in date_opt would ruin the date command we construct. */
627 if (strchr(date_opt, '"') != NULL) {
629 _("The value of the --date option is not a valid date.\n"
630 "In particular, it contains quotation marks.\n"));
634 sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s",
637 printf(_("Issuing date command: %s\n"), date_command);
639 date_child_fp = popen(date_command, "r");
640 if (date_child_fp == NULL) {
641 outsyserr(_("Unable to run 'date' program in /bin/sh shell. "
646 if (!fgets(date_resp, sizeof(date_resp), date_child_fp))
647 date_resp[0] = '\0'; /* in case fgets fails */
649 printf(_("response from date command = %s\n"), date_resp);
650 if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) {
651 fprintf(stderr, _("The date command issued by %s returned "
652 "unexpected results.\n"
653 "The command was:\n %s\n"
654 "The response was:\n %s\n"),
655 MYNAME, date_command, date_resp);
658 long seconds_since_epoch;
659 rc = sscanf(date_resp + sizeof(magic)-1, "%ld",
660 &seconds_since_epoch);
663 _("The date command issued by %s returned "
664 "something other than an integer where the "
665 "converted time value was expected.\n"
666 "The command was:\n %s\n"
667 "The response was:\n %s\n"),
668 MYNAME, date_command, date_resp);
672 *time_p = seconds_since_epoch;
674 printf(_("date string %s equates to "
675 "%ld seconds since 1969.\n"),
676 date_opt, (long) *time_p);
679 pclose(date_child_fp);
687 set_system_clock(const bool hclock_valid, const time_t newtime,
688 const bool testing) {
689 /*----------------------------------------------------------------------------
690 Set the System Clock to time 'newtime'.
692 Also set the kernel time zone value to the value indicated by the
693 TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as
694 tzset() would interpret them.
696 EXCEPT: if hclock_valid is false, just issue an error message
697 saying there is no valid time in the Hardware Clock to which to set
700 If 'testing' is true, don't actually update anything -- just say we
702 -----------------------------------------------------------------------------*/
706 fprintf(stderr, _("The Hardware Clock does not contain a valid time, so "
707 "we cannot set the System Time from it.\n"));
718 broken = localtime(&newtime);
719 #ifdef HAVE_TM_GMTOFF
720 minuteswest = -broken->tm_gmtoff/60; /* GNU extension */
722 minuteswest = timezone/60;
723 if (broken->tm_isdst)
728 printf(_("Calling settimeofday:\n"));
729 printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
730 (long) tv.tv_sec, (long) tv.tv_usec);
731 printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
734 printf(_("Not setting system clock because running in test mode.\n"));
737 const struct timezone tz = { minuteswest, 0 };
739 rc = settimeofday(&tv, &tz);
741 if (errno == EPERM) {
743 _("Must be superuser to set system clock.\n"));
746 outsyserr(_("settimeofday() failed"));
757 set_system_clock_timezone(const bool universal, const bool testing) {
758 /*----------------------------------------------------------------------------
759 Reset the System Clock from local time to UTC, based on its current
760 value and the timezone unless universal is TRUE.
762 Also set the kernel time zone value to the value indicated by the
763 TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as
764 tzset() would interpret them.
766 If 'testing' is true, don't actually update anything -- just say we
768 -----------------------------------------------------------------------------*/
775 gettimeofday(&tv, NULL);
777 struct tm broken_time;
780 broken_time = *gmtime(&tv.tv_sec);
781 strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", &broken_time);
782 printf(_("Current system time: %ld = %s\n"), (long) tv.tv_sec, ctime_now);
785 broken = localtime(&tv.tv_sec);
786 #ifdef HAVE_TM_GMTOFF
787 minuteswest = -broken->tm_gmtoff/60; /* GNU extension */
789 minuteswest = timezone/60;
790 if (broken->tm_isdst)
794 gettimeofday(&tv, NULL);
796 tv.tv_sec += minuteswest * 60;
799 struct tm broken_time;
802 broken_time = *gmtime(&tv.tv_sec);
803 strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", &broken_time);
805 printf(_("Calling settimeofday:\n"));
806 printf(_("\tUTC: %s\n"), ctime_now);
807 printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
808 (long) tv.tv_sec, (long) tv.tv_usec);
809 printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
812 printf(_("Not setting system clock because running in test mode.\n"));
815 const struct timezone tz = { minuteswest, 0 };
817 rc = settimeofday(&tv, &tz);
819 if (errno == EPERM) {
821 _("Must be superuser to set system clock.\n"));
824 outsyserr(_("settimeofday() failed"));
834 adjust_drift_factor(struct adjtime *adjtime_p,
835 const time_t nowtime,
836 const bool hclock_valid,
837 const time_t hclocktime,
838 const double sync_delay) {
839 /*------------------------------------------------------------------------
840 Update the drift factor in <*adjtime_p> to reflect the fact that the
841 Hardware Clock was calibrated to <nowtime> and before that was set
844 We record in the adjtime file the time at which we last calibrated
845 the clock so we can compute the drift rate each time we calibrate.
847 EXCEPT: if <hclock_valid> is false, assume Hardware Clock was not set
848 before to anything meaningful and regular adjustments have not been
849 done, so don't adjust the drift factor.
850 ------------------------------------------------------------------------*/
853 printf(_("Not adjusting drift factor because the "
854 "Hardware Clock previously contained "
856 } else if (adjtime_p->last_calib_time == 0) {
858 printf(_("Not adjusting drift factor because last "
859 "calibration time is zero,\n"
860 "so history is bad and calibration startover "
862 } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) {
864 printf(_("Not adjusting drift factor because it has "
865 "been less than a day since the last "
867 } else if (adjtime_p->last_calib_time != 0) {
869 * At adjustment time we adjust the hardware clock according
870 * to the contents of /etc/adjtime.
872 * At calibration time we set the hardware clock and
873 * update /etc/adjtime, that is, for each calibration
874 * (except the first) we also do an adjustment.
876 * We are now at calibration time.
878 * Let us do computation in doubles. (Floats almost suffice,
879 * but 195 days + 1 second equals 195 days in floats.)
881 const double sec_per_day = 24.0 * 60.0 * 60.0;
882 double atime_per_htime;
883 double adj_days, cal_days;
884 double exp_drift, unc_drift;
885 double factor_adjust;
887 /* Adjusted time units per hardware time unit */
888 atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day;
890 /* Days since last adjustment (in hardware clock time) */
891 adj_days = (double)(hclocktime - adjtime_p->last_adj_time)
894 /* Expected drift (sec) since last adjustment */
895 exp_drift = adj_days * adjtime_p->drift_factor
896 + adjtime_p->not_adjusted;
898 /* Uncorrected drift (sec) since last calibration */
899 unc_drift = (double)(nowtime - hclocktime)
900 + sync_delay - exp_drift;
902 /* Days since last calibration (in hardware clock time) */
903 cal_days = ((double)(adjtime_p->last_adj_time
904 - adjtime_p->last_calib_time)
905 + adjtime_p->not_adjusted)
906 / (sec_per_day * atime_per_htime) + adj_days;
908 /* Amount to add to previous drift factor */
909 factor_adjust = unc_drift / cal_days;
912 printf(_("Clock drifted %.1f seconds in the past "
913 "%d seconds in spite of a drift factor of "
915 "Adjusting drift factor by %f seconds/day\n"),
917 (int) (nowtime - adjtime_p->last_calib_time),
918 adjtime_p->drift_factor,
921 adjtime_p->drift_factor += factor_adjust;
923 adjtime_p->last_calib_time = nowtime;
925 adjtime_p->last_adj_time = nowtime;
927 adjtime_p->not_adjusted = 0;
929 adjtime_p->dirty = TRUE;
935 calculate_adjustment(const double factor,
936 const time_t last_time,
937 const double not_adjusted,
938 const time_t systime,
941 /*----------------------------------------------------------------------------
942 Do the drift adjustment calculation.
944 The way we have to set the clock, we need the adjustment in two parts:
946 1) an integer number of seconds (return as *adjustment_p)
948 2) a positive fraction of a second (less than 1) (return as *retro_p)
950 The sum of these two values is the adjustment needed. Positive means to
951 advance the clock or insert seconds. Negative means to retard the clock
953 ----------------------------------------------------------------------------*/
954 double exact_adjustment;
956 exact_adjustment = ((double) (systime - last_time)) * factor / (24 * 60 * 60)
958 *adjustment_p = FLOOR(exact_adjustment);
960 *retro_p = exact_adjustment - (double) *adjustment_p;
962 printf (_("Time since last adjustment is %d seconds\n"),
963 (int) (systime - last_time));
964 printf (_("Need to insert %d seconds and refer time back "
965 "%.6f seconds ago\n"),
966 *adjustment_p, *retro_p);
973 save_adjtime(const struct adjtime adjtime, const bool testing) {
974 /*-----------------------------------------------------------------------------
975 Write the contents of the <adjtime> structure to its disk file.
977 But if the contents are clean (unchanged since read from disk), don't
979 -----------------------------------------------------------------------------*/
980 char newfile[412]; /* Stuff to write to disk file */
983 /* snprintf is not always available, but this is safe
984 as long as libc does not use more than 100 positions for %ld or %f */
985 sprintf(newfile, "%f %ld %f\n%ld\n%s\n",
986 adjtime.drift_factor,
987 (long) adjtime.last_adj_time,
988 adjtime.not_adjusted,
989 (long) adjtime.last_calib_time,
990 (adjtime.local_utc == UTC) ? "UTC" : "LOCAL");
993 printf(_("Not updating adjtime file because of testing mode.\n"));
994 printf(_("Would have written the following to %s:\n%s"),
995 adj_file_name, newfile);
1000 adjfile = fopen(adj_file_name, "w");
1001 if (adjfile == NULL) {
1002 outsyserr(_("Could not open file with the clock adjustment parameters "
1003 "in it (%s) for writing"), adj_file_name);
1006 if (fputs(newfile, adjfile) < 0) {
1007 outsyserr(_("Could not update file with the clock adjustment "
1008 "parameters (%s) in it"), adj_file_name);
1011 if (fclose(adjfile) < 0) {
1012 outsyserr(_("Could not update file with the clock adjustment "
1013 "parameters (%s) in it"), adj_file_name);
1018 fprintf(stderr, _("Drift adjustment parameters not updated.\n"));
1026 do_adjustment(struct adjtime *adjtime_p,
1027 const bool hclock_valid, const time_t hclocktime,
1028 const struct timeval read_time,
1029 const bool universal, const bool testing) {
1030 /*---------------------------------------------------------------------------
1031 Do the adjustment requested, by 1) setting the Hardware Clock (if
1032 necessary), and 2) updating the last-adjusted time in the adjtime
1035 Do not update anything if the Hardware Clock does not currently present
1038 arguments <factor> and <last_time> are current values from the adjtime
1041 <hclock_valid> means the Hardware Clock contains a valid time, and that
1042 time is <hclocktime>.
1044 <read_time> is the current system time (to be precise, it is the system
1045 time at the time <hclocktime> was read, which due to computational delay
1046 could be a short time ago).
1048 <universal>: the Hardware Clock is kept in UTC.
1050 <testing>: We are running in test mode (no updating of clock).
1052 We do not bother to update the clock if the adjustment would be less than
1053 one second. This is to avoid cumulative error and needless CPU hogging
1054 (remember we use an infinite loop for some timing) if the user runs us
1057 ----------------------------------------------------------------------------*/
1058 if (!hclock_valid) {
1059 fprintf(stderr, _("The Hardware Clock does not contain a valid time, "
1060 "so we cannot adjust it.\n"));
1061 adjtime_p->last_calib_time = 0; /* calibration startover is required */
1062 adjtime_p->last_adj_time = 0;
1063 adjtime_p->not_adjusted = 0;
1064 adjtime_p->dirty = TRUE;
1065 } else if (adjtime_p->last_adj_time == 0) {
1067 printf(_("Not setting clock because last adjustment time is zero, "
1068 "so history is bad."));
1071 /* Number of seconds we must insert in the Hardware Clock */
1073 /* Fraction of second we have to remove from clock after inserting
1074 <adjustment> whole seconds.
1076 calculate_adjustment(adjtime_p->drift_factor,
1077 adjtime_p->last_adj_time,
1078 adjtime_p->not_adjusted,
1080 &adjustment, &retro);
1081 if (adjustment > 0 || adjustment < -1) {
1082 set_hardware_clock_exact(hclocktime + adjustment,
1083 time_inc(read_time, -retro),
1084 universal, testing);
1085 adjtime_p->last_adj_time = hclocktime + adjustment;
1086 adjtime_p->not_adjusted = 0;
1087 adjtime_p->dirty = TRUE;
1090 printf(_("Needed adjustment is less than one second, "
1091 "so not setting clock.\n"));
1098 determine_clock_access_method(const bool user_requests_ISA) {
1102 if (user_requests_ISA)
1103 ur = probe_for_cmos_clock();
1106 ur = probe_for_rtc_clock();
1109 ur = probe_for_kd_clock();
1111 if (!ur && !user_requests_ISA)
1112 ur = probe_for_cmos_clock();
1116 printf(_("Using %s.\n"), ur->interface_name);
1118 printf(_("No usable clock interface found.\n"));
1123 manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
1124 const bool set, const time_t set_time,
1125 const bool hctosys, const bool systohc, const bool systz,
1126 const struct timeval startup_time,
1127 const bool utc, const bool local_opt,
1128 const bool testing) {
1129 /*---------------------------------------------------------------------------
1130 Do all the normal work of hwclock - read, set clock, etc.
1132 Issue output to stdout and error message to stderr where appropriate.
1134 Return rc == 0 if everything went OK, rc != 0 if not.
1135 ----------------------------------------------------------------------------*/
1136 struct adjtime adjtime;
1137 /* Contents of the adjtime file, or what they should be. */
1138 int rc; /* local return code */
1139 bool no_auth; /* User lacks necessary authorization to access the clock */
1142 no_auth = ur->get_permissions();
1147 if (!noadjfile && (adjust || set || systohc || (!utc && !local_opt))) {
1148 rc = read_adjtime(&adjtime);
1152 /* A little trick to avoid reading the file if we don't have to */
1153 adjtime.dirty = FALSE;
1158 const bool universal = hw_clock_is_utc(utc, local_opt, adjtime);
1160 if ((set || systohc || adjust) &&
1161 (adjtime.local_utc == UTC) != universal) {
1162 adjtime.local_utc = universal ? UTC : LOCAL;
1163 adjtime.dirty = TRUE;
1167 struct timeval read_time;
1168 /* The time at which we read the Hardware Clock */
1170 bool hclock_valid = FALSE;
1171 /* The Hardware Clock gives us a valid time, or at least something
1172 close enough to fool mktime().
1175 time_t hclocktime = 0;
1176 /* The time the hardware clock had just after we
1177 synchronized to its next clock tick when we started up.
1178 Defined only if hclock_valid is true.
1181 if (show || adjust || hctosys || (!noadjfile && !systz)) {
1182 /* data from HW-clock are required */
1183 rc = synchronize_to_clock_tick();
1184 if (rc && rc != 2) /* 2= synchronization timeout */
1186 gettimeofday(&read_time, NULL);
1187 rc = read_hardware_clock(universal, &hclock_valid, &hclocktime);
1193 display_time(hclock_valid, hclocktime,
1194 time_diff(read_time, startup_time));
1196 set_hardware_clock_exact(set_time, startup_time,
1197 universal, testing);
1199 adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime,
1200 time_diff(read_time, startup_time));
1201 } else if (adjust) {
1202 do_adjustment(&adjtime, hclock_valid, hclocktime,
1203 read_time, universal, testing);
1204 } else if (systohc) {
1205 struct timeval nowtime, reftime;
1206 /* We can only set_hardware_clock_exact to a whole seconds
1207 time, so we set it with reference to the most recent
1210 gettimeofday(&nowtime, NULL);
1211 reftime.tv_sec = nowtime.tv_sec;
1212 reftime.tv_usec = 0;
1214 set_hardware_clock_exact((time_t) reftime.tv_sec, reftime,
1215 universal, testing);
1217 adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid,
1218 hclocktime, (double) read_time.tv_usec / 1E6);
1219 } else if (hctosys) {
1220 rc = set_system_clock(hclock_valid, hclocktime, testing);
1222 printf(_("Unable to set system clock.\n"));
1226 rc = set_system_clock_timezone(universal, testing);
1228 printf(_("Unable to set system clock.\n"));
1233 save_adjtime(adjtime, testing);
1241 manipulate_epoch(const bool getepoch, const bool setepoch,
1242 const int epoch_opt, const bool testing) {
1243 /*----------------------------------------------------------------------------
1244 Get or set the Hardware Clock epoch value in the kernel, as appropriate.
1245 <getepoch>, <setepoch>, and <epoch> are hwclock invocation options.
1247 <epoch> == -1 if the user did not specify an "epoch" option.
1249 -----------------------------------------------------------------------------*/
1251 Maintenance note: This should work on non-Alpha machines, but the
1252 evidence today (98.03.04) indicates that the kernel only keeps the
1253 epoch value on Alphas. If that is ever fixed, this function should be
1258 fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock "
1259 "only on an Alpha machine.\nThis copy of hwclock was built for "
1260 "a machine other than Alpha\n(and thus is presumably not running "
1261 "on an Alpha now). No action taken.\n"));
1264 unsigned long epoch;
1266 if (get_epoch_rtc(&epoch, 0))
1267 fprintf(stderr, _("Unable to get the epoch value from the kernel.\n"));
1269 printf(_("Kernel is assuming an epoch value of %lu\n"), epoch);
1270 } else if (setepoch) {
1271 if (epoch_opt == -1)
1272 fprintf(stderr, _("To set the epoch value, you must use the 'epoch' "
1273 "option to tell to what value to set it.\n"));
1275 printf(_("Not setting the epoch to %d - testing only.\n"),
1277 else if (set_epoch_rtc(epoch_opt))
1278 printf(_("Unable to set the epoch value in the kernel.\n"));
1284 #define RTC_DEV "/dev/efirtc"
1286 #define RTC_DEV "/dev/rtc"
1291 printf(_("%s from %s\n"), MYNAME, PACKAGE_STRING);
1295 usage - Output (error and) usage information
1297 This function is called both directly from main to show usage
1298 information and as fatal function from shhopt if some argument is
1299 not understood. In case of normal usage info FMT should be NULL.
1300 In that case the info is printed to stdout. If FMT is given
1301 usage will act like fprintf( stderr, fmt, ... ), show a usage
1302 information and terminate the program afterwards.
1305 usage( const char *fmt, ... ) {
1309 usageto = fmt ? stderr : stdout;
1311 fprintf( usageto, _(
1312 "hwclock - query and set the hardware clock (RTC)\n\n"
1313 "Usage: hwclock [function] [options...]\n\n"
1315 " -h | --help show this help\n"
1316 " -r | --show read hardware clock and print result\n"
1317 " --set set the rtc to the time given with --date\n"
1318 " -s | --hctosys set the system time from the hardware clock\n"
1319 " -w | --systohc set the hardware clock to the current system time\n"
1320 " --systz set the system time based on the current timezone\n"
1321 " --adjust adjust the rtc to account for systematic drift since\n"
1322 " the clock was last set or adjusted\n"
1323 " --getepoch print out the kernel's hardware clock epoch value\n"
1324 " --setepoch set the kernel's hardware clock epoch value to the \n"
1325 " value given with --epoch\n"
1326 " -v | --version print out the version of hwclock to stdout\n"
1328 " -u | --utc the hardware clock is kept in UTC\n"
1329 " --localtime the hardware clock is kept in local time\n"
1330 " -f | --rtc=path special /dev/... file to use instead of default\n"
1331 " --directisa access the ISA bus directly instead of %s\n"
1332 " --badyear ignore rtc's year because the bios is broken\n"
1333 " --date specifies the time to which to set the hardware clock\n"
1334 " --epoch=year specifies the year which is the beginning of the \n"
1335 " hardware clock's epoch value\n"
1336 " --noadjfile do not access /etc/adjtime. Requires the use of\n"
1337 " either --utc or --localtime\n"
1338 " --adjfile=path specifies the path to the adjust file (default is\n"
1340 " --test do everything except actually updating the hardware\n"
1341 " clock or anything else\n"
1342 " -D | --debug debug mode\n"
1347 " -J|--jensen, -A|--arc, -S|--srm, -F|--funky-toy\n"
1348 " tell hwclock the type of alpha you have (see hwclock(8))\n"
1357 vfprintf(stderr, fmt, ap);
1361 hwclock_exit(fmt ? EX_USAGE : 0);
1364 static const struct option longopts[] = {
1365 { "adjust", 0, 0, 'a' },
1366 { "help", 0, 0, 'h' },
1367 { "show", 0, 0, 'r' },
1368 { "hctosys", 0, 0, 's' },
1369 { "utc", 0, 0, 'u' },
1370 { "version", 0, 0, 'v' },
1371 { "systohc", 0, 0, 'w' },
1372 { "debug", 0, 0, 'D' },
1374 { "ARC", 0, 0, 'A' },
1375 { "arc", 0, 0, 'A' },
1376 { "Jensen", 0, 0, 'J' },
1377 { "jensen", 0, 0, 'J' },
1378 { "SRM", 0, 0, 'S' },
1379 { "srm", 0, 0, 'S' },
1380 { "funky-toy", 0, 0, 'F'},
1382 { "set", 0, 0, 128 },
1383 { "getepoch", 0, 0, 129 },
1384 { "setepoch", 0, 0, 130 },
1385 { "noadjfile", 0, 0, 131 },
1386 { "localtime", 0, 0, 132 },
1387 { "badyear", 0, 0, 133 },
1388 { "directisa", 0, 0, 134 },
1389 { "test", 0, 0, 135 },
1390 { "date", 1, 0, 136 },
1391 { "epoch", 1, 0, 137 },
1392 { "rtc", 1, 0, 'f' },
1393 { "adjfile", 1, 0, 138 },
1394 { "systz", 0, 0, 139 },
1400 * EX_USAGE: bad invocation
1401 * EX_NOPERM: no permission
1402 * EX_OSFILE: cannot open /dev/rtc or /etc/adjtime
1403 * EX_IOERR: ioctl error getting or setting the time
1408 main(int argc, char **argv) {
1410 struct timeval startup_time;
1411 /* The time we started up, in seconds into the epoch, including
1413 time_t set_time = 0; /* Time to which user said to set Hardware Clock */
1415 bool permitted; /* User is permitted to do the function */
1418 /* Variables set by various options; show may also be set later */
1419 /* The options debug, badyear and epoch_option are global */
1420 bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch;
1421 bool utc, testing, local_opt, noadjfile, directisa;
1422 bool ARCconsole, Jensen, SRM, funky_toy;
1425 /* Remember what time we were invoked */
1426 gettimeofday(&startup_time, NULL);
1428 #ifdef HAVE_LIBAUDIT
1429 hwaudit_fd = audit_open();
1430 if (hwaudit_fd < 0 && !(errno == EINVAL || errno == EPROTONOSUPPORT ||
1431 errno == EAFNOSUPPORT)) {
1432 /* You get these error codes only when the kernel doesn't have
1433 * audit compiled in. */
1434 fprintf(stderr, _("%s: Unable to connect to audit system\n"),
1439 setlocale(LC_ALL, "");
1441 /* We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid
1442 LC_NUMERIC since it gives problems when we write to /etc/adjtime.
1443 - gqueri@mail.dotcom.fr */
1444 setlocale(LC_NUMERIC, "C");
1446 bindtextdomain(PACKAGE, LOCALEDIR);
1447 textdomain(PACKAGE);
1449 /* Set option defaults */
1450 show = set = systohc = hctosys = systz = adjust = noadjfile = FALSE;
1451 getepoch = setepoch = utc = local_opt = testing = debug = FALSE;
1452 ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE;
1455 while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL))
1503 local_opt = TRUE; /* --localtime */
1512 testing = TRUE; /* --test */
1515 date_opt = optarg; /* --date */
1518 epoch_option = atoi(optarg); /* --epoch */
1521 adj_file_name = optarg; /* --adjfile */
1524 systz = TRUE; /* --systz */
1527 rtc_dev_name = optarg; /* --rtc */
1529 case 'v': /* --version */
1533 case 'h': /* --help */
1543 #ifdef HAVE_LIBAUDIT
1544 if (testing != TRUE) {
1545 if (adjust == TRUE || hctosys == TRUE || systohc == TRUE ||
1546 set == TRUE || setepoch == TRUE) {
1552 usage(_("%s takes no non-option arguments. "
1553 "You supplied %d.\n"),
1557 if (show + set + systohc + hctosys + systz + adjust + getepoch
1559 fprintf(stderr, _("You have specified multiple functions.\n"
1560 "You can only perform one function "
1562 hwclock_exit(EX_USAGE);
1565 if (utc && local_opt) {
1566 fprintf(stderr, _("%s: The --utc and --localtime options "
1567 "are mutually exclusive. You specified "
1568 "both.\n"), MYNAME);
1569 hwclock_exit(EX_USAGE);
1572 if (adjust && noadjfile) {
1573 fprintf(stderr, _("%s: The --adjust and --noadjfile options "
1574 "are mutually exclusive. You specified "
1575 "both.\n"), MYNAME);
1576 hwclock_exit(EX_USAGE);
1579 if (adj_file_name && noadjfile) {
1580 fprintf(stderr, _("%s: The --adjfile and --noadjfile options "
1581 "are mutually exclusive. You specified "
1582 "both.\n"), MYNAME);
1583 hwclock_exit(EX_USAGE);
1586 adj_file_name = ADJPATH;
1588 if (noadjfile && !(utc || local_opt)) {
1589 fprintf(stderr, _("%s: With --noadjfile, you must specify "
1590 "either --utc or --localtime\n"), MYNAME);
1591 hwclock_exit(EX_USAGE);
1595 set_cmos_epoch(ARCconsole, SRM);
1596 set_cmos_access(Jensen, funky_toy);
1600 rc = interpret_date_string(date_opt, &set_time);
1601 /* (time-consuming) */
1603 fprintf(stderr, _("No usable set-to time. "
1604 "Cannot set clock.\n"));
1605 hwclock_exit(EX_USAGE);
1609 if (!(show | set | systohc | hctosys | systz | adjust | getepoch
1611 show = 1; /* default to show */
1617 /* program is designed to run setuid (in some situations) */
1618 if (set || systohc || adjust) {
1620 _("Sorry, only the superuser can change "
1621 "the Hardware Clock.\n"));
1623 } else if (systz || hctosys) {
1625 _("Sorry, only the superuser can change "
1626 "the System Clock.\n"));
1628 } else if (setepoch) {
1630 _("Sorry, only the superuser can change the "
1631 "Hardware Clock epoch in the kernel.\n"));
1638 hwclock_exit(EX_NOPERM);
1640 if (getepoch || setepoch) {
1641 manipulate_epoch(getepoch, setepoch, epoch_option, testing);
1648 determine_clock_access_method(directisa);
1651 _("Cannot access the Hardware Clock via "
1652 "any known method.\n"));
1655 _("Use the --debug option to see the "
1656 "details of our search for an access "
1662 rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
1663 hctosys, systohc, systz, startup_time, utc,
1664 local_opt, testing);
1666 return rc; /* Not reached */
1669 /* A single routine for greater uniformity */
1671 outsyserr(char *msg, ...) {
1675 fprintf(stderr, "%s: ", progname);
1676 va_start(args, msg);
1677 vfprintf(stderr, msg, args);
1679 fprintf(stderr, ", errno=%d: %s.\n",
1680 errsv, strerror(errsv));
1684 #ifdef HAVE_LIBAUDIT
1686 hwaudit_exit(int status)
1689 audit_log_user_message(hwaudit_fd, AUDIT_USYS_CONFIG,
1690 "changing system time", NULL, NULL, NULL, status ? 0 : 1);
1697 /****************************************************************************
1699 History of this program:
1701 98.08.12 BJH Version 2.4
1703 Don't use century byte from Hardware Clock. Add comments telling why.
1706 98.06.20 BJH Version 2.3.
1708 Make --hctosys set the kernel timezone from TZ environment variable
1709 and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com).
1711 98.03.05 BJH. Version 2.2.
1713 Add --getepoch and --setepoch.
1715 Fix some word length things so it works on Alpha.
1717 Make it work when /dev/rtc doesn't have the interrupt functions.
1718 In this case, busywait for the top of a second instead of blocking and
1719 waiting for the update complete interrupt.
1721 Fix a bunch of bugs too numerous to mention.
1723 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte
1724 50) of the ISA Hardware Clock when using direct ISA I/O. Problem
1725 discovered by job (jei@iclnl.icl.nl).
1727 Use the rtc clock access method in preference to the KDGHWCLK method.
1728 Problem discovered by Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>.
1730 November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt
1731 (janl@math.uio.no) to make it compile on linux 1.2 machines as well
1732 as more recent versions of the kernel. Introduced the NO_CLOCK
1733 access method and wrote feature test code to detect absense of rtc
1737 **************************************************************************
1740 To compile this, you must use GNU compiler optimization (-O option)
1741 in order to make the "extern inline" functions from asm/io.h (inb(),
1742 etc.) compile. If you don't optimize, which means the compiler
1743 will generate no inline functions, the references to these functions
1744 in this program will be compiled as external references. Since you
1745 probably won't be linking with any functions by these names, you will
1746 have unresolved external references when you link.
1748 The program is designed to run setuid superuser, since we need to be
1749 able to do direct I/O. (More to the point: we need permission to
1750 execute the iopl() system call). (However, if you use one of the
1751 methods other than direct ISA I/O to access the clock, no setuid is
1754 Here's some info on how we must deal with the time that elapses while
1755 this program runs: There are two major delays as we run:
1757 1) Waiting up to 1 second for a transition of the Hardware Clock so
1758 we are synchronized to the Hardware Clock.
1760 2) Running the "date" program to interpret the value of our --date
1763 Reading the /etc/adjtime file is the next biggest source of delay and
1766 The user wants to know what time it was at the moment he invoked us,
1767 not some arbitrary time later. And in setting the clock, he is
1768 giving us the time at the moment we are invoked, so if we set the
1769 clock some time later, we have to add some time to that.
1771 So we check the system time as soon as we start up, then run "date"
1772 and do file I/O if necessary, then wait to synchronize with a
1773 Hardware Clock edge, then check the system time again to see how
1774 much time we spent. We immediately read the clock then and (if
1775 appropriate) report that time, and additionally, the delay we measured.
1777 If we're setting the clock to a time given by the user, we wait some
1778 more so that the total delay is an integral number of seconds, then
1779 set the Hardware Clock to the time the user requested plus that
1780 integral number of seconds. N.B. The Hardware Clock can only be set
1781 in integral seconds.
1783 If we're setting the clock to the system clock value, we wait for
1784 the system clock to reach the top of a second, and then set the
1785 Hardware Clock to the system clock's value.
1787 Here's an interesting point about setting the Hardware Clock: On my
1788 machine, when you set it, it sets to that precise time. But one can
1789 imagine another clock whose update oscillator marches on a steady one
1790 second period, so updating the clock between any two oscillator ticks
1791 is the same as updating it right at the earlier tick. To avoid any
1792 complications that might cause, we set the clock as soon as possible
1793 after an oscillator tick.
1796 About synchronizing to the Hardware Clock when reading the time: The
1797 precision of the Hardware Clock counters themselves is one second.
1798 You can't read the counters and find out that is 12:01:02.5. But if
1799 you consider the location in time of the counter's ticks as part of
1800 its value, then its precision is as infinite as time is continuous!
1801 What I'm saying is this: To find out the _exact_ time in the
1802 hardware clock, we wait until the next clock tick (the next time the
1803 second counter changes) and measure how long we had to wait. We
1804 then read the value of the clock counters and subtract the wait time
1805 and we know precisely what time it was when we set out to query the
1808 hwclock uses this method, and considers the Hardware Clock to have
1812 Enhancements needed:
1814 - When waiting for whole second boundary in set_hardware_clock_exact,
1815 fail if we miss the goal by more than .1 second, as could happen if
1816 we get pre-empted (by the kernel dispatcher).
1818 ****************************************************************************/