]> git.ipfire.org Git - thirdparty/util-linux.git/blob - hwclock/hwclock.c
Imported from util-linux-2.10s tarball.
[thirdparty/util-linux.git] / hwclock / hwclock.c
1 /*
2 * hwclock.c
3 *
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>.
8 *
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.
15 *
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.
20 *
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 *
24 * Distributed under GPL
25 */
26
27 /*
28 * clock [-u] -r - read hardware clock
29 * clock [-u] -w - write hardware clock from system time
30 * clock [-u] -s - set system time from hardware clock
31 * clock [-u] -a - set system time from hardware clock, adjust the time
32 * to correct for systematic error, and write it back to
33 * the hardware clock
34 * -u indicates cmos clock is kept in universal time
35 * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980)
36 * -J indicates we're dealing with a Jensen (early DEC Alpha PC)
37 */
38
39 /*
40 * Explanation of `adjusting' (Rob Hooft):
41 *
42 * The problem with my machine is that its CMOS clock is 10 seconds
43 * per day slow. With this version of clock.c, and my '/etc/rc.local'
44 * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error
45 * is automatically corrected at every boot.
46 *
47 * To do this job, the program reads and writes the file '/etc/adjtime'
48 * to determine the correction, and to save its data. In this file are
49 * three numbers:
50 *
51 * 1) the correction in seconds per day. (So if your clock runs 5
52 * seconds per day fast, the first number should read -5.0)
53 * 2) the number of seconds since 1/1/1970 the last time the program
54 * was used
55 * 3) the remaining part of a second which was leftover after the last
56 * adjustment
57 *
58 * Installation and use of this program:
59 *
60 * a) create a file '/etc/adjtime' containing as the first and only line:
61 * '0.0 0 0.0'
62 * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in
63 * universal or local time. This updates the second number.
64 * c) set your system time using the 'date' command.
65 * d) update your cmos time using 'clock -wu' or 'clock -w'
66 * e) replace the first number in /etc/adjtime by your correction.
67 * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local'
68 */
69
70 #include <string.h>
71 #include <stdio.h>
72 #include <fcntl.h>
73 #include <sys/ioctl.h>
74 #include <errno.h>
75 #include <stdlib.h>
76 #include <unistd.h>
77 #include <time.h>
78 #include <sys/time.h>
79 #include <sys/stat.h>
80 #include <stdarg.h>
81
82 #include "shhopt.h"
83 #include "clock.h"
84 #include "nls.h"
85
86 #define MYNAME "hwclock"
87 #define VERSION "2.4c"
88
89 char *progname = MYNAME;
90
91 /* The struct that holds our hardware access routines */
92 struct clock_ops *ur;
93
94 #define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1));
95
96 /* Here the information for time adjustments is kept. */
97 #define ADJPATH "/etc/adjtime"
98
99 /* Store the date here when "badyear" flag is set. */
100 #define LASTDATE "/var/lib/lastdate"
101
102 struct adjtime {
103 /* This is information we keep in the adjtime file that tells us how
104 to do drift corrections. Elements are all straight from the
105 adjtime file, so see documentation of that file for details.
106 Exception is <dirty>, which is an indication that what's in this
107 structure is not what's in the disk file (because it has been
108 updated since read from the disk file).
109 */
110 bool dirty;
111 /* line 1 */
112 float drift_factor;
113 time_t last_adj_time;
114 float not_adjusted;
115 /* line 2 */
116 time_t last_calib_time;
117 /* The most recent time that we set the clock from an external
118 authority (as opposed to just doing a drift adjustment) */
119 /* line 3 */
120 enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc;
121 /* To which time zone, local or UTC, we most recently set the
122 hardware clock. */
123 };
124
125 bool debug;
126 /* We are running in debug mode, wherein we put a lot of information about
127 what we're doing to standard output. */
128
129 bool badyear;
130 /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */
131
132 int epoch_option = -1;
133 /* User-specified epoch, used when rtc fails to return epoch. */
134
135 /*
136 * Almost all Award BIOS's made between 04/26/94 and 05/31/95
137 * have a nasty bug limiting the RTC year byte to the range 94-99.
138 * Any year between 2000 and 2093 gets changed to 2094, every time
139 * you start the system.
140 * With the --badyear option, we write the date to file and hope
141 * that the file is updated at least once a year.
142 * I recommend putting this command "hwclock --badyear" in the monthly
143 * crontab, just to be safe. -- Dave Coffin 11/12/98
144 */
145 static void
146 write_date_to_file (struct tm *tm) {
147 FILE *fp;
148
149 if ((fp = fopen(LASTDATE,"w"))) {
150 fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1,
151 tm->tm_year+1900);
152 fclose(fp);
153 } else
154 perror(LASTDATE);
155 }
156
157 static void
158 read_date_from_file (struct tm *tm) {
159 int last_mday, last_mon, last_year;
160 FILE *fp;
161
162 if ((fp = fopen(LASTDATE,"r"))) {
163 if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) {
164 tm->tm_year = last_year-1900;
165 if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday)
166 tm->tm_year ++;
167 }
168 fclose(fp);
169 }
170 write_date_to_file (tm);
171 }
172
173 static float
174 time_diff(struct timeval subtrahend, struct timeval subtractor) {
175 /*---------------------------------------------------------------------------
176 The difference in seconds between two times in "timeval" format.
177 ----------------------------------------------------------------------------*/
178 return( (subtrahend.tv_sec - subtractor.tv_sec)
179 + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6 );
180 }
181
182
183 static struct timeval
184 time_inc(struct timeval addend, float increment) {
185 /*----------------------------------------------------------------------------
186 The time, in "timeval" format, which is <increment> seconds after
187 the time <addend>. Of course, <increment> may be negative.
188 -----------------------------------------------------------------------------*/
189 struct timeval newtime;
190
191 newtime.tv_sec = addend.tv_sec + (int) increment;
192 newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6;
193
194 /* Now adjust it so that the microsecond value is between 0 and 1 million */
195 if (newtime.tv_usec < 0) {
196 newtime.tv_usec += 1E6;
197 newtime.tv_sec -= 1;
198 } else if (newtime.tv_usec >= 1E6) {
199 newtime.tv_usec -= 1E6;
200 newtime.tv_sec += 1;
201 }
202 return(newtime);
203 }
204
205
206 static bool
207 hw_clock_is_utc(const bool utc, const bool local_opt,
208 const struct adjtime adjtime) {
209 bool ret;
210
211 if (utc)
212 ret = TRUE; /* --utc explicitly given on command line */
213 else if (local_opt)
214 ret = FALSE; /* --localtime explicitly given */
215 else
216 /* get info from adjtime file - default is local */
217 ret = (adjtime.local_utc == UTC);
218 if (debug)
219 printf(_("Assuming hardware clock is kept in %s time.\n"),
220 ret ? _("UTC") : _("local"));
221 return ret;
222 }
223
224
225
226 static void
227 read_adjtime(struct adjtime *adjtime_p, int *rc_p) {
228 /*----------------------------------------------------------------------------
229 Read the adjustment parameters out of the /etc/adjtime file.
230
231 Return them as the adjtime structure <*adjtime_p>.
232
233 If there is no /etc/adjtime file, return defaults.
234 If values are missing from the file, return defaults for them.
235
236 return *rc_p = 0 if all OK, !=0 otherwise.
237
238 -----------------------------------------------------------------------------*/
239 FILE *adjfile;
240 int rc; /* local return code */
241 struct stat statbuf; /* We don't even use the contents of this. */
242
243 rc = stat(ADJPATH, &statbuf);
244 if (rc < 0 && errno == ENOENT) {
245 /* He doesn't have a adjtime file, so we'll use defaults. */
246 adjtime_p->drift_factor = 0;
247 adjtime_p->last_adj_time = 0;
248 adjtime_p->not_adjusted = 0;
249 adjtime_p->last_calib_time = 0;
250 adjtime_p->local_utc = UNKNOWN;
251
252 *rc_p = 0;
253 } else {
254 adjfile = fopen(ADJPATH, "r"); /* open file for reading */
255 if (adjfile == NULL) {
256 outsyserr("cannot open file " ADJPATH);
257 *rc_p = 2;
258 } else {
259 char line1[81]; /* String: first line of adjtime file */
260 char line2[81]; /* String: second line of adjtime file */
261 char line3[81]; /* String: third line of adjtime file */
262
263 line1[0] = '\0'; /* In case fgets fails */
264 fgets(line1, sizeof(line1), adjfile);
265 line2[0] = '\0'; /* In case fgets fails */
266 fgets(line2, sizeof(line2), adjfile);
267 line3[0] = '\0'; /* In case fgets fails */
268 fgets(line3, sizeof(line3), adjfile);
269
270 fclose(adjfile);
271
272 /* Set defaults in case values are missing from file */
273 adjtime_p->drift_factor = 0;
274 adjtime_p->last_adj_time = 0;
275 adjtime_p->not_adjusted = 0;
276 adjtime_p->last_calib_time = 0;
277
278 sscanf(line1, "%f %d %f",
279 &adjtime_p->drift_factor,
280 (int *) &adjtime_p->last_adj_time,
281 &adjtime_p->not_adjusted);
282
283 sscanf(line2, "%d", (int *) &adjtime_p->last_calib_time);
284
285 if (!strcmp(line3, "UTC\n"))
286 adjtime_p->local_utc = UTC;
287 else if (!strcmp(line3, "LOCAL\n"))
288 adjtime_p->local_utc = LOCAL;
289 else {
290 adjtime_p->local_utc = UNKNOWN;
291 if (line3[0]) {
292 fprintf(stderr, _("%s: Warning: unrecognized third line in adjtime file\n"),
293 MYNAME);
294 fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n"));
295 }
296 }
297
298 *rc_p = 0;
299 }
300 adjtime_p->dirty = FALSE;
301
302 if (debug) {
303 printf(_("Last drift adjustment done at %d seconds after 1969\n"),
304 (int) adjtime_p->last_adj_time);
305 printf(_("Last calibration done at %d seconds after 1969\n"),
306 (int) adjtime_p->last_calib_time);
307 printf(_("Hardware clock is on %s time\n"),
308 (adjtime_p->local_utc == LOCAL) ? _("local") :
309 (adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown"));
310 }
311 }
312 }
313
314
315 static void
316 synchronize_to_clock_tick(int *retcode_p) {
317 /*-----------------------------------------------------------------------------
318 Wait until the falling edge of the Hardware Clock's update flag so
319 that any time that is read from the clock immediately after we
320 return will be exact.
321
322 The clock only has 1 second precision, so it gives the exact time only
323 once per second, right on the falling edge of the update flag.
324
325 We wait (up to one second) either blocked waiting for an rtc device
326 or in a CPU spin loop. The former is probably not very accurate.
327
328 Return *retcode_p == 0 if it worked, nonzero if it didn't.
329
330 -----------------------------------------------------------------------------*/
331 if (debug) printf(_("Waiting for clock tick...\n"));
332
333 *retcode_p = ur->synchronize_to_clock_tick();
334
335 if (debug) printf(_("...got clock tick\n"));
336 }
337
338
339
340 static void
341 mktime_tz(struct tm tm, const bool universal,
342 bool *valid_p, time_t *systime_p) {
343 /*-----------------------------------------------------------------------------
344 Convert a time in broken down format (hours, minutes, etc.) into standard
345 unix time (seconds into epoch). Return it as *systime_p.
346
347 The broken down time is argument <tm>. This broken down time is either in
348 local time zone or UTC, depending on value of logical argument "universal".
349 True means it is in UTC.
350
351 If the argument contains values that do not constitute a valid time,
352 and mktime() recognizes this, return *valid_p == false and
353 *systime_p undefined. However, mktime() sometimes goes ahead and
354 computes a fictional time "as if" the input values were valid,
355 e.g. if they indicate the 31st day of April, mktime() may compute
356 the time of May 1. In such a case, we return the same fictional
357 value mktime() does as *systime_p and return *valid_p == true.
358
359 -----------------------------------------------------------------------------*/
360 time_t mktime_result; /* The value returned by our mktime() call */
361 char *zone; /* Local time zone name */
362
363 /* We use the C library function mktime(), but since it only works on
364 local time zone input, we may have to fake it out by temporarily
365 changing the local time zone to UTC.
366 */
367 zone = (char *) getenv("TZ"); /* remember original time zone */
368 if (universal) {
369 /* Set timezone to UTC */
370 setenv("TZ", "", TRUE);
371 /* Note: tzset() gets called implicitly by the time code, but only the
372 first time. When changing the environment variable, better call
373 tzset() explicitly.
374 */
375 tzset();
376 }
377 mktime_result = mktime(&tm);
378 if (mktime_result == -1) {
379 /* This apparently (not specified in mktime() documentation) means
380 the 'tm' structure does not contain valid values (however, not
381 containing valid values does _not_ imply mktime() returns -1).
382 */
383 *valid_p = FALSE;
384 *systime_p = 0;
385 if (debug)
386 printf(_("Invalid values in hardware clock: "
387 "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"),
388 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
389 tm.tm_hour, tm.tm_min, tm.tm_sec);
390 } else {
391 *valid_p = TRUE;
392 *systime_p = mktime_result;
393 if (debug)
394 printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
395 "%ld seconds since 1969\n"),
396 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
397 tm.tm_hour, tm.tm_min, tm.tm_sec, (long) *systime_p);
398 }
399 /* now put back the original zone. */
400 if (zone) setenv("TZ", zone, TRUE);
401 else unsetenv("TZ");
402 tzset();
403 }
404
405
406 static void
407 read_hardware_clock(const bool universal, bool *valid_p, time_t *systime_p){
408 /*----------------------------------------------------------------------------
409 Read the hardware clock and return the current time via <tm> argument.
410
411 Use the method indicated by <method> argument to access the hardware clock.
412 -----------------------------------------------------------------------------*/
413 struct tm tm;
414 int err;
415
416 err = ur->read_hardware_clock(&tm);
417
418 if (badyear)
419 read_date_from_file(&tm);
420
421 if (debug)
422 printf (_("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"),
423 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
424 tm.tm_hour, tm.tm_min, tm.tm_sec);
425 mktime_tz(tm, universal, valid_p, systime_p);
426 }
427
428
429 static void
430 set_hardware_clock(const time_t newtime,
431 const bool universal,
432 const bool testing) {
433 /*----------------------------------------------------------------------------
434 Set the Hardware Clock to the time <newtime>, in local time zone or UTC,
435 according to <universal>.
436 ----------------------------------------------------------------------------*/
437 int err;
438 struct tm new_broken_time;
439 /* Time to which we will set Hardware Clock, in broken down format, in
440 the time zone of caller's choice
441 */
442
443 if (universal)
444 new_broken_time = *gmtime(&newtime);
445 else
446 new_broken_time = *localtime(&newtime);
447
448 if (debug)
449 printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d "
450 "= %d seconds since 1969\n"),
451 new_broken_time.tm_hour, new_broken_time.tm_min,
452 new_broken_time.tm_sec, (int) newtime);
453
454 if (testing)
455 printf(_("Clock not changed - testing only.\n"));
456 else {
457 if (badyear) {
458 /*
459 * Write the real year to a file, then write a fake year
460 * between 1995 and 1998 to the RTC. This way, Award BIOS boots
461 * on 29 Feb 2000 thinking that it's 29 Feb 1996.
462 */
463 write_date_to_file (&new_broken_time);
464 new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3);
465 }
466 err = ur->set_hardware_clock(&new_broken_time);
467 }
468 }
469
470
471
472 static void
473 set_hardware_clock_exact(const time_t settime,
474 const struct timeval ref_time,
475 const bool universal,
476 const bool testing) {
477 /*----------------------------------------------------------------------------
478 Set the Hardware Clock to the time "settime", in local time zone or UTC,
479 according to "universal".
480
481 But correct "settime" and wait for a fraction of a second so that
482 "settime" is the value of the Hardware Clock as of system time
483 "ref_time", which is in the past. For example, if "settime" is
484 14:03:05 and "ref_time" is 12:10:04.5 and the current system
485 time is 12:10:06.0: Wait .5 seconds (to make exactly 2 seconds since
486 "ref_time") and then set the Hardware Clock to 14:03:07, thus
487 getting a precise and retroactive setting of the clock.
488
489 (Don't be confused by the fact that the system clock and the Hardware
490 Clock differ by two hours in the above example. That's just to remind
491 you that there are two independent time scales here).
492
493 This function ought to be able to accept set times as fractional times.
494 Idea for future enhancement.
495
496 -----------------------------------------------------------------------------*/
497 time_t newtime; /* Time to which we will set Hardware Clock */
498 struct timeval now_time; /* locally used time */
499
500 gettimeofday(&now_time, NULL);
501 newtime = settime + (int) time_diff(now_time, ref_time) + 1;
502 if (debug)
503 printf(_("Time elapsed since reference time has been %.6f seconds.\n"
504 "Delaying further to reach the next full second.\n"),
505 time_diff(now_time, ref_time));
506
507 /* Now delay some more until Hardware Clock time newtime arrives */
508 do gettimeofday(&now_time, NULL);
509 while (time_diff(now_time, ref_time) < newtime - settime);
510
511 set_hardware_clock(newtime, universal, testing);
512 }
513
514
515
516 static void
517 display_time(const bool hclock_valid, const time_t systime,
518 const float sync_duration) {
519 /*----------------------------------------------------------------------------
520 Put the time "systime" on standard output in display format.
521 Except if hclock_valid == false, just tell standard output that we don't
522 know what time it is.
523
524 Include in the output the adjustment "sync_duration".
525 -----------------------------------------------------------------------------*/
526 if (!hclock_valid)
527 fprintf(stderr, _("The Hardware Clock registers contain values that are "
528 "either invalid (e.g. 50th day of month) or beyond the range "
529 "we can handle (e.g. Year 2095).\n"));
530 else {
531 struct tm *lt;
532 char *format = "%c";
533 char ctime_now[200];
534
535 lt = localtime(&systime);
536 strftime(ctime_now, sizeof(ctime_now), format, lt);
537 printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration));
538 }
539 }
540
541
542
543 static int
544 interpret_date_string(const char *date_opt, time_t * const time_p) {
545 /*----------------------------------------------------------------------------
546 Interpret the value of the --date option, which is something like
547 "13:05:01". In fact, it can be any of the myriad ASCII strings that specify
548 a time which the "date" program can understand. The date option value in
549 question is our "dateopt" argument.
550
551 The specified time is in the local time zone.
552
553 Our output, "*time_p", is a seconds-into-epoch time.
554
555 We use the "date" program to interpret the date string. "date" must be
556 runnable by issuing the command "date" to the /bin/sh shell. That means
557 in must be in the current PATH.
558
559 If anything goes wrong (and many things can), we return return code
560 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p
561 is valid.
562 ----------------------------------------------------------------------------*/
563 FILE *date_child_fp;
564 char date_resp[100];
565 const char magic[]="seconds-into-epoch=";
566 char date_command[100];
567 int retcode; /* our eventual return code */
568 int rc; /* local return code */
569
570 if (date_opt == NULL) {
571 fprintf(stderr, _("No --date option specified.\n"));
572 retcode = 14;
573 } else if (strchr(date_opt, '"') != NULL) {
574 /* Quotation marks in date_opt would ruin the date command we construct.
575 */
576 fprintf(stderr, _("The value of the --date option is not a valid date.\n"
577 "In particular, it contains quotation marks.\n"));
578 retcode = 12;
579 } else {
580 sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s",
581 date_opt);
582 if (debug) printf(_("Issuing date command: %s\n"), date_command);
583
584 date_child_fp = popen(date_command, "r");
585 if (date_child_fp == NULL) {
586 outsyserr(_("Unable to run 'date' program in /bin/sh shell. "
587 "popen() failed"));
588 retcode = 10;
589 } else {
590 date_resp[0] = '\0'; /* in case fgets fails */
591 fgets(date_resp, sizeof(date_resp), date_child_fp);
592 if (debug) printf(_("response from date command = %s\n"), date_resp);
593 if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) {
594 fprintf(stderr, _("The date command issued by %s returned "
595 "unexpected results.\n"
596 "The command was:\n %s\nThe response was:\n %s\n"),
597 MYNAME, date_command, date_resp);
598 retcode = 8;
599 } else {
600 int seconds_since_epoch;
601 rc = sscanf(date_resp + sizeof(magic)-1, "%d", &seconds_since_epoch);
602 if (rc < 1) {
603 fprintf(stderr, _("The date command issued by %s returned "
604 "something other than an integer where the converted "
605 "time value was expected.\n"
606 "The command was:\n %s\nThe response was:\n %s\n"),
607 MYNAME, date_command, date_resp);
608 retcode = 6;
609 } else {
610 retcode = 0;
611 *time_p = seconds_since_epoch;
612 if (debug)
613 printf(_("date string %s equates to %d seconds since 1969.\n"),
614 date_opt, (int) *time_p);
615 }
616 }
617 fclose(date_child_fp);
618 }
619 }
620 return(retcode);
621 }
622
623
624
625 static int
626 set_system_clock(const bool hclock_valid, const time_t newtime,
627 const bool testing) {
628 /*----------------------------------------------------------------------------
629 Set the System Clock to time 'newtime'.
630
631 Also set the kernel time zone value to the value indicated by the
632 TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as
633 tzset() would interpret them.
634
635 EXCEPT: if hclock_valid is false, just issue an error message
636 saying there is no valid time in the Hardware Clock to which to set
637 the system time.
638
639 If 'testing' is true, don't actually update anything -- just say we
640 would have.
641 -----------------------------------------------------------------------------*/
642 int retcode;
643
644 if (!hclock_valid) {
645 fprintf(stderr,_("The Hardware Clock does not contain a valid time, so "
646 "we cannot set the System Time from it.\n"));
647 retcode = 1;
648 } else {
649 struct timeval tv;
650 struct tm *broken;
651 int minuteswest;
652 int rc;
653
654 tv.tv_sec = newtime;
655 tv.tv_usec = 0;
656
657 broken = localtime(&newtime);
658 #ifdef HAVE_tm_gmtoff
659 minuteswest = -broken->tm_gmtoff/60; /* GNU extension */
660 #else
661 minuteswest = timezone/60;
662 if (broken->tm_isdst)
663 minuteswest -= 60;
664 #endif
665
666 if (debug) {
667 printf( _("Calling settimeofday:\n") );
668 printf( _("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
669 (long) tv.tv_sec, (long) tv.tv_usec );
670 printf( _("\ttz.tz_minuteswest = %d\n"), minuteswest);
671 }
672 if (testing) {
673 printf(_("Not setting system clock because running in test mode.\n"));
674 retcode = 0;
675 } else {
676 const struct timezone tz = { minuteswest, 0 };
677
678 rc = settimeofday(&tv, &tz);
679 if (rc != 0) {
680 if (errno == EPERM)
681 fprintf(stderr, _("Must be superuser to set system clock.\n"));
682 else
683 outsyserr(_("settimeofday() failed"));
684 retcode = 1;
685 } else retcode = 0;
686 }
687 }
688 return(retcode);
689 }
690
691
692 static void
693 adjust_drift_factor(struct adjtime *adjtime_p,
694 const time_t nowtime,
695 const bool hclock_valid, const time_t hclocktime ) {
696 /*---------------------------------------------------------------------------
697 Update the drift factor in <*adjtime_p> to reflect the fact that the
698 Hardware Clock was calibrated to <nowtime> and before that was set
699 to <hclocktime>.
700
701 We assume that the user has been doing regular drift adjustments
702 using the drift factor in the adjtime file, so if <nowtime> and
703 <clocktime> are different, that means the adjustment factor isn't
704 quite right.
705
706 We record in the adjtime file the time at which we last calibrated
707 the clock so we can compute the drift rate each time we calibrate.
708
709 EXCEPT: if <hclock_valid> is false, assume Hardware Clock was not set
710 before to anything meaningful and regular adjustments have not been
711 done, so don't adjust the drift factor.
712
713 ----------------------------------------------------------------------------*/
714 if (!hclock_valid) {
715 if (debug)
716 printf(_("Not adjusting drift factor because the Hardware Clock "
717 "previously contained garbage.\n"));
718 } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) {
719 if (debug)
720 printf(_("Not adjusting drift factor because it has been less than a "
721 "day since the last calibration.\n"));
722 } else {
723 const float factor_adjust =
724 ((float) (nowtime - hclocktime)
725 / (hclocktime - adjtime_p->last_calib_time))
726 * 24 * 60 * 60;
727
728 if (debug)
729 printf(_("Clock drifted %d seconds in the past %d seconds "
730 "in spite of a drift factor of %f seconds/day.\n"
731 "Adjusting drift factor by %f seconds/day\n"),
732 (int) (nowtime - hclocktime),
733 (int) (hclocktime - adjtime_p->last_calib_time),
734 adjtime_p->drift_factor,
735 factor_adjust );
736
737 adjtime_p->drift_factor += factor_adjust;
738 }
739 adjtime_p->last_calib_time = nowtime;
740
741 adjtime_p->last_adj_time = nowtime;
742
743 adjtime_p->not_adjusted = 0;
744
745 adjtime_p->dirty = TRUE;
746 }
747
748
749
750 static void
751 calculate_adjustment(
752 const float factor,
753 const time_t last_time,
754 const float not_adjusted,
755 const time_t systime,
756 int *adjustment_p,
757 float *retro_p,
758 const int debug ) {
759 /*----------------------------------------------------------------------------
760 Do the drift adjustment calculation.
761
762 The way we have to set the clock, we need the adjustment in two parts:
763
764 1) an integer number of seconds (return as *adjustment_p)
765
766 2) a positive fraction of a second (less than 1) (return as *retro_p)
767
768 The sum of these two values is the adjustment needed. Positive means to
769 advance the clock or insert seconds. Negative means to retard the clock
770 or remove seconds.
771 ----------------------------------------------------------------------------*/
772 float exact_adjustment;
773
774 exact_adjustment = ((float) (systime - last_time)) * factor / (24 * 60 * 60)
775 + not_adjusted;
776 *adjustment_p = FLOOR(exact_adjustment);
777
778 *retro_p = exact_adjustment - (float) *adjustment_p;
779 if (debug) {
780 printf (_("Time since last adjustment is %d seconds\n"),
781 (int) (systime - last_time));
782 printf (_("Need to insert %d seconds and refer time back "
783 "%.6f seconds ago\n"),
784 *adjustment_p, *retro_p);
785 }
786 }
787
788
789
790 static void
791 save_adjtime(const struct adjtime adjtime, const bool testing) {
792 /*-----------------------------------------------------------------------------
793 Write the contents of the <adjtime> structure to its disk file.
794
795 But if the contents are clean (unchanged since read from disk), don't
796 bother.
797 -----------------------------------------------------------------------------*/
798 char newfile[412]; /* Stuff to write to disk file */
799
800 if (adjtime.dirty) {
801 /* snprintf is not always available, but this is safe
802 as long as libc does not use more than 100 positions for %ld or %f */
803 sprintf(newfile, "%f %ld %f\n%ld\n%s\n",
804 adjtime.drift_factor,
805 (long) adjtime.last_adj_time,
806 adjtime.not_adjusted,
807 (long) adjtime.last_calib_time,
808 (adjtime.local_utc == UTC) ? "UTC" : "LOCAL");
809
810 if (testing) {
811 printf(_("Not updating adjtime file because of testing mode.\n"));
812 printf(_("Would have written the following to %s:\n%s"),
813 ADJPATH, newfile);
814 } else {
815 FILE *adjfile;
816 int err = 0;
817
818 adjfile = fopen(ADJPATH, "w");
819 if (adjfile == NULL) {
820 outsyserr("Could not open file with the clock adjustment parameters "
821 "in it (" ADJPATH ") for writing");
822 err = 1;
823 } else {
824 if (fputs(newfile, adjfile) < 0) {
825 outsyserr("Could not update file with the clock adjustment "
826 "parameters (" ADJPATH ") in it");
827 err = 1;
828 }
829 if (fclose(adjfile) < 0) {
830 outsyserr("Could not update file with the clock adjustment "
831 "parameters (" ADJPATH ") in it");
832 err = 1;
833 }
834 }
835 if (err)
836 fprintf(stderr, _("Drift adjustment parameters not updated.\n"));
837 }
838 }
839 }
840
841
842
843 static void
844 do_adjustment(struct adjtime *adjtime_p,
845 const bool hclock_valid, const time_t hclocktime,
846 const struct timeval read_time,
847 const bool universal, const bool testing) {
848 /*---------------------------------------------------------------------------
849 Do the adjustment requested, by 1) setting the Hardware Clock (if
850 necessary), and 2) updating the last-adjusted time in the adjtime
851 structure.
852
853 Do not update anything if the Hardware Clock does not currently present
854 a valid time.
855
856 arguments <factor> and <last_time> are current values from the adjtime
857 file.
858
859 <hclock_valid> means the Hardware Clock contains a valid time, and that
860 time is <hclocktime>.
861
862 <read_time> is the current system time (to be precise, it is the system
863 time at the time <hclocktime> was read, which due to computational delay
864 could be a short time ago).
865
866 <universal>: the Hardware Clock is kept in UTC.
867
868 <testing>: We are running in test mode (no updating of clock).
869
870 We do not bother to update the clock if the adjustment would be less than
871 one second. This is to avoid cumulative error and needless CPU hogging
872 (remember we use an infinite loop for some timing) if the user runs us
873 frequently.
874
875 ----------------------------------------------------------------------------*/
876 if (!hclock_valid) {
877 fprintf(stderr, _("The Hardware Clock does not contain a valid time, "
878 "so we cannot adjust it.\n"));
879 } else {
880 int adjustment;
881 /* Number of seconds we must insert in the Hardware Clock */
882 float retro;
883 /* Fraction of second we have to remove from clock after inserting
884 <adjustment> whole seconds.
885 */
886 calculate_adjustment(adjtime_p->drift_factor,
887 adjtime_p->last_adj_time,
888 adjtime_p->not_adjusted,
889 hclocktime,
890 &adjustment, &retro,
891 debug );
892 if (adjustment > 0 || adjustment < -1) {
893 set_hardware_clock_exact(hclocktime + adjustment,
894 time_inc(read_time, -retro),
895 universal, testing);
896 adjtime_p->last_adj_time = hclocktime + adjustment;
897 adjtime_p->not_adjusted = 0;
898 adjtime_p->dirty = TRUE;
899 } else
900 if (debug)
901 printf(_("Needed adjustment is less than one second, "
902 "so not setting clock.\n"));
903 }
904 }
905
906
907
908 static void
909 determine_clock_access_method(const bool user_requests_ISA) {
910
911 ur = NULL;
912
913 if (user_requests_ISA)
914 ur = probe_for_cmos_clock();
915
916 if (!ur)
917 ur = probe_for_rtc_clock();
918
919 if (!ur)
920 ur = probe_for_kd_clock();
921
922 if (!ur && !user_requests_ISA)
923 ur = probe_for_cmos_clock();
924
925 if (debug) {
926 if (ur)
927 printf(_("Using %s.\n"), ur->interface_name);
928 else
929 printf(_("No usable clock interface found.\n"));
930 }
931 }
932
933 static void
934 manipulate_clock(const bool show, const bool adjust,
935 const bool set, const time_t set_time,
936 const bool hctosys, const bool systohc,
937 const struct timeval startup_time,
938 const bool utc, const bool local_opt,
939 const bool testing, int *retcode_p) {
940 /*---------------------------------------------------------------------------
941 Do all the normal work of hwclock - read, set clock, etc.
942
943 Issue output to stdout and error message to stderr where appropriate.
944
945 Return rc == 0 if everything went OK, rc != 0 if not.
946 ----------------------------------------------------------------------------*/
947 struct adjtime adjtime;
948 /* Contents of the adjtime file, or what they should be. */
949 int rc; /* local return code */
950 bool no_auth; /* User lacks necessary authorization to access the clock */
951
952 no_auth = ur->get_permissions();
953
954 if (no_auth) *retcode_p = 1;
955 else {
956 if (adjust || set || systohc || (!utc && !local_opt))
957 read_adjtime(&adjtime, &rc);
958 else {
959 /* A little trick to avoid reading the file if we don't have to */
960 adjtime.dirty = FALSE;
961 rc = 0;
962 }
963 if (rc != 0) *retcode_p = 2;
964 else {
965 const bool universal = hw_clock_is_utc(utc, local_opt, adjtime);
966
967 if ((set || systohc || adjust) &&
968 (adjtime.local_utc == UTC) != universal) {
969 adjtime.local_utc = universal ? UTC : LOCAL;
970 adjtime.dirty = TRUE;
971 }
972
973 synchronize_to_clock_tick(retcode_p);
974 /* this takes up to 1 second */
975 if (*retcode_p == 0) {
976 struct timeval read_time;
977 /* The time at which we read the Hardware Clock */
978
979 bool hclock_valid;
980 /* The Hardware Clock gives us a valid time, or at least something
981 close enough to fool mktime().
982 */
983
984 time_t hclocktime;
985 /* The time the hardware clock had just after we
986 synchronized to its next clock tick when we started up.
987 Defined only if hclock_valid is true.
988 */
989
990 gettimeofday(&read_time, NULL);
991 read_hardware_clock(universal, &hclock_valid, &hclocktime);
992
993 if (show) {
994 display_time(hclock_valid, hclocktime,
995 time_diff(read_time, startup_time));
996 *retcode_p = 0;
997 } else if (set) {
998 set_hardware_clock_exact(set_time, startup_time,
999 universal, testing);
1000 adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime);
1001 *retcode_p = 0;
1002 } else if (adjust) {
1003 do_adjustment(&adjtime, hclock_valid, hclocktime,
1004 read_time, universal, testing);
1005 *retcode_p = 0;
1006 } else if (systohc) {
1007 struct timeval nowtime, reftime;
1008 /* We can only set_hardware_clock_exact to a whole seconds
1009 time, so we set it with reference to the most recent
1010 whole seconds time.
1011 */
1012 gettimeofday(&nowtime, NULL);
1013 reftime.tv_sec = nowtime.tv_sec;
1014 reftime.tv_usec = 0;
1015
1016 set_hardware_clock_exact((time_t) reftime.tv_sec, reftime,
1017 universal, testing);
1018 *retcode_p = 0;
1019 adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid,
1020 hclocktime);
1021 } else if (hctosys) {
1022 rc = set_system_clock(hclock_valid, hclocktime, testing);
1023 if (rc != 0) {
1024 printf(_("Unable to set system clock.\n"));
1025 *retcode_p = 1;
1026 } else *retcode_p = 0;
1027 }
1028 save_adjtime(adjtime, testing);
1029 }
1030 }
1031 }
1032 }
1033
1034
1035 static void
1036 manipulate_epoch(const bool getepoch, const bool setepoch,
1037 const int epoch_opt, const bool testing) {
1038 /*----------------------------------------------------------------------------
1039 Get or set the Hardware Clock epoch value in the kernel, as appropriate.
1040 <getepoch>, <setepoch>, and <epoch> are hwclock invocation options.
1041
1042 <epoch> == -1 if the user did not specify an "epoch" option.
1043
1044 -----------------------------------------------------------------------------*/
1045 /*
1046 Maintenance note: This should work on non-Alpha machines, but the
1047 evidence today (98.03.04) indicates that the kernel only keeps the
1048 epoch value on Alphas. If that is ever fixed, this function should be
1049 changed.
1050 */
1051
1052 #ifndef __alpha__
1053 fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock "
1054 "only on an Alpha machine.\nThis copy of hwclock was built for "
1055 "a machine other than Alpha\n(and thus is presumably not running "
1056 "on an Alpha now). No action taken.\n"));
1057 #else
1058 if (getepoch) {
1059 unsigned long epoch;
1060
1061 if (get_epoch_rtc(&epoch, 0))
1062 fprintf(stderr, _("Unable to get the epoch value from the kernel.\n"));
1063 else
1064 printf(_("Kernel is assuming an epoch value of %lu\n"), epoch);
1065 } else if (setepoch) {
1066 if (epoch_opt == -1)
1067 fprintf(stderr, _("To set the epoch value, you must use the 'epoch' "
1068 "option to tell to what value to set it.\n"));
1069 else if (testing)
1070 printf(_("Not setting the epoch to %d - testing only.\n"),
1071 epoch_opt);
1072 else if (set_epoch_rtc(epoch_opt))
1073 printf(_("Unable to set the epoch value in the kernel.\n"));
1074 }
1075 #endif
1076 }
1077
1078 #if __ia64__
1079 #define RTC_DEV "/dev/efirtc"
1080 #else
1081 #define RTC_DEV "/dev/rtc"
1082 #endif
1083
1084 /*
1085 usage - Output (error and) usage information
1086
1087 This function is called both directly from main to show usage
1088 information and as fatal function from shhopt if some argument is
1089 not understood. In case of normal usage info FMT should be NULL.
1090 In that case the info is printed to stdout. If FMT is given
1091 usage will act like fprintf( stderr, fmt, ... ), show a usage
1092 information and terminate the program afterwards.
1093 */
1094 static void
1095 usage( const char *fmt, ... ) {
1096 FILE *usageto;
1097 va_list ap;
1098
1099 usageto = fmt ? stderr : stdout;
1100
1101 fprintf( usageto, _(
1102 "hwclock - query and set the hardware clock (RTC)\n\n"
1103 "Usage: hwclock [function] [options...]\n\n"
1104 "Functions:\n"
1105 " --help show this help\n"
1106 " --show read hardware clock and print result\n"
1107 " --set set the rtc to the time given with --date\n"
1108 " --hctosys set the system time from the hardware clock\n"
1109 " --systohc set the hardware clock to the current system time\n"
1110 " --adjust adjust the rtc to account for systematic drift since \n"
1111 " the clock was last set or adjusted\n"
1112 " --getepoch print out the kernel's hardware clock epoch value\n"
1113 " --setepoch set the kernel's hardware clock epoch value to the \n"
1114 " value given with --epoch\n"
1115 " --version print out the version of hwclock to stdout\n"
1116 "\nOptions: \n"
1117 " --utc the hardware clock is kept in coordinated universal time\n"
1118 " --localtime the hardware clock is kept in local time\n"
1119 " --directisa access the ISA bus directly instead of %s\n"
1120 " --badyear ignore rtc's year because the bios is broken\n"
1121 " --date specifies the time to which to set the hardware clock\n"
1122 " --epoch=year specifies the year which is the beginning of the \n"
1123 " hardware clock's epoch value\n"
1124 ),RTC_DEV);
1125 #ifdef __alpha__
1126 fprintf( usageto, _(
1127 " --jensen, --arc, --srm, --funky-toy\n"
1128 " tell hwclock the type of alpha you have (see hwclock(8))\n"
1129 ) );
1130 #endif
1131
1132
1133 fflush(stdout);
1134 if( fmt ) {
1135 usageto = stderr;
1136 va_start(ap, fmt);
1137 vfprintf(stderr, fmt, ap);
1138 va_end(ap);
1139 }
1140
1141 exit( fmt ? 99 : 0 );
1142 }
1143
1144 int
1145 main(int argc, char **argv) {
1146
1147 struct timeval startup_time;
1148 /* The time we started up, in seconds into the epoch, including fractions.
1149 */
1150 time_t set_time; /* Time to which user said to set Hardware Clock */
1151
1152 bool permitted; /* User is permitted to do the function */
1153 int retcode; /* Our eventual return code */
1154
1155 int rc; /* local return code */
1156
1157 /* option_def is the control table for the option parser. These other
1158 variables are the results of parsing the options and their meanings
1159 are given by the option_def. The only exception is <show>, which
1160 may be modified after parsing is complete to effect an implied option.
1161 */
1162 bool help, show, set, systohc, hctosys, adjust, getepoch, setepoch, version;
1163 bool ARCconsole, utc, testing, directisa, Jensen, SRM, funky_toy;
1164 bool local_opt;
1165 char *date_opt;
1166
1167 const optStruct option_def[] = {
1168 { 'h', (char *) "help", OPT_FLAG, &help, 0 },
1169 { 'r', (char *) "show", OPT_FLAG, &show, 0 },
1170 { 0, (char *) "set", OPT_FLAG, &set, 0 },
1171 { 'w', (char *) "systohc", OPT_FLAG, &systohc, 0 },
1172 { 's', (char *) "hctosys", OPT_FLAG, &hctosys, 0 },
1173 { 0, (char *) "getepoch", OPT_FLAG, &getepoch, 0 },
1174 { 0, (char *) "setepoch", OPT_FLAG, &setepoch, 0 },
1175 { 'a', (char *) "adjust", OPT_FLAG, &adjust, 0 },
1176 { 'v', (char *) "version", OPT_FLAG, &version, 0 },
1177 { 'V', (char *) "version", OPT_FLAG, &version, 0 },
1178 { 0, (char *) "date", OPT_STRING, &date_opt, 0 },
1179 { 0, (char *) "epoch", OPT_UINT, &epoch_option,0 },
1180 { 'u', (char *) "utc", OPT_FLAG, &utc, 0 },
1181 { 0, (char *) "localtime", OPT_FLAG, &local_opt, 0 },
1182 { 0, (char *) "badyear", OPT_FLAG, &badyear, 0 },
1183 { 0, (char *) "directisa", OPT_FLAG, &directisa, 0 },
1184 { 0, (char *) "test", OPT_FLAG, &testing, 0 },
1185 { 'D', (char *) "debug", OPT_FLAG, &debug, 0 },
1186 #ifdef __alpha__
1187 { 'A', (char *) "ARC", OPT_FLAG, &ARCconsole,0 },
1188 { 'J', (char *) "Jensen", OPT_FLAG, &Jensen, 0 },
1189 { 'S', (char *) "SRM", OPT_FLAG, &SRM, 0 },
1190 { 'F', (char *) "funky-toy", OPT_FLAG, &funky_toy, 0 },
1191 #endif
1192 { 0, (char *) NULL, OPT_END, NULL, 0 }
1193 };
1194 int argc_parse; /* argc, except we modify it as we parse */
1195 char **argv_parse; /* argv, except we modify it as we parse */
1196
1197 gettimeofday(&startup_time, NULL); /* Remember what time we were invoked */
1198
1199 setlocale(LC_ALL, "");
1200 #ifdef LC_NUMERIC
1201 /* We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid
1202 LC_NUMERIC since it gives problems when we write to /etc/adjtime.
1203 - gqueri@mail.dotcom.fr */
1204 setlocale(LC_NUMERIC, "C");
1205 #endif
1206 bindtextdomain(PACKAGE, LOCALEDIR);
1207 textdomain(PACKAGE);
1208
1209 /* set option defaults */
1210 help = show = set = systohc = hctosys = adjust = getepoch = setepoch =
1211 version = utc = local_opt = ARCconsole = SRM = funky_toy =
1212 directisa = badyear = Jensen = testing = debug = FALSE;
1213 date_opt = NULL;
1214
1215 argc_parse = argc; argv_parse = argv;
1216 optParseOptions(&argc_parse, argv_parse, option_def, 0);
1217 /* Uses and sets argc_parse, argv_parse.
1218 Sets show, systohc, hctosys, adjust, utc, local_opt, version,
1219 testing, debug, set, date_opt, getepoch, setepoch, epoch_option
1220 */
1221 /* This is an ugly routine - for example, if I give an incorrect
1222 option, it only says "unrecognized option" without telling
1223 me what options are recognized. Rewrite with standard
1224 getopt() and usage() and throw shhopt out. */
1225
1226 if (argc_parse - 1 > 0) {
1227 usage( _("%s takes no non-option arguments. "
1228 "You supplied %d.\n"),
1229 MYNAME, argc_parse - 1);
1230 }
1231
1232 if (help)
1233 usage( NULL );
1234
1235 if (show + set + systohc + hctosys + adjust +
1236 getepoch + setepoch + version > 1) {
1237 fprintf(stderr, _("You have specified multiple function options.\n"
1238 "You can only perform one function at a time.\n"));
1239 exit(100);
1240 }
1241
1242 if (utc && local_opt) {
1243 fprintf(stderr, _("%s: The --utc and --localtime options are mutually "
1244 "exclusive. You specified both.\n"), MYNAME);
1245 exit(100);
1246 }
1247
1248 #ifdef __alpha__
1249 set_cmos_epoch(ARCconsole, SRM);
1250 set_cmos_access(Jensen, funky_toy);
1251 #endif
1252
1253 if (set) {
1254 rc = interpret_date_string(date_opt, &set_time); /* (time-consuming) */
1255 if (rc != 0) {
1256 fprintf(stderr, _("No usable set-to time. Cannot set clock.\n"));
1257 exit(100);
1258 }
1259 }
1260
1261 if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch |
1262 version))
1263 show = 1; /* default to show */
1264
1265
1266 if (getuid() == 0) permitted = TRUE;
1267 else {
1268 /* program is designed to run setuid (in some situations) -- be secure! */
1269 if (set || hctosys || systohc || adjust) {
1270 fprintf(stderr,
1271 _("Sorry, only the superuser can change the Hardware Clock.\n"));
1272 permitted = FALSE;
1273 } else if (hctosys) {
1274 fprintf(stderr,
1275 _("Sorry, only the superuser can change the System Clock.\n"));
1276 permitted = FALSE;
1277 } else if (setepoch) {
1278 fprintf(stderr,
1279 _("Sorry, only the superuser can change "
1280 "the Hardware Clock epoch in the kernel.\n"));
1281 permitted = FALSE;
1282 } else
1283 permitted = TRUE;
1284 }
1285
1286 if (!permitted) retcode = 2;
1287 else {
1288 retcode = 0;
1289 if (version) {
1290 printf(MYNAME " " VERSION "/%s\n",util_linux_version);
1291 } else if (getepoch || setepoch) {
1292 manipulate_epoch(getepoch, setepoch, epoch_option, testing);
1293 } else {
1294 if (debug)
1295 printf(MYNAME " " VERSION "/%s\n",util_linux_version);
1296 determine_clock_access_method(directisa);
1297 if (!ur) {
1298 fprintf(stderr,
1299 _("Cannot access the Hardware Clock via any known method.\n"));
1300 if (!debug)
1301 fprintf(stderr,
1302 _("Use the --debug option to see the details of our "
1303 "search for an access method.\n"));
1304 } else
1305 manipulate_clock(show, adjust, set, set_time, hctosys, systohc,
1306 startup_time, utc, local_opt, testing, &rc);
1307 }
1308 }
1309 exit(retcode);
1310 }
1311
1312 /* A single routine for greater uniformity */
1313 void
1314 outsyserr(char *msg, ...) {
1315 va_list args;
1316 int errsv = errno;
1317
1318 fprintf(stderr, "%s: ", progname);
1319 va_start(args, msg);
1320 vfprintf(stderr, msg, args);
1321 va_end(args);
1322 fprintf(stderr, ", errno=%d: %s.\n",
1323 errsv, strerror(errsv));
1324 }
1325
1326 /****************************************************************************
1327
1328 History of this program:
1329
1330 98.08.12 BJH Version 2.4
1331
1332 Don't use century byte from Hardware Clock. Add comments telling why.
1333
1334
1335 98.06.20 BJH Version 2.3.
1336
1337 Make --hctosys set the kernel timezone from TZ environment variable
1338 and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com).
1339
1340 98.03.05 BJH. Version 2.2.
1341
1342 Add --getepoch and --setepoch.
1343
1344 Fix some word length things so it works on Alpha.
1345
1346 Make it work when /dev/rtc doesn't have the interrupt functions.
1347 In this case, busywait for the top of a second instead of blocking and
1348 waiting for the update complete interrupt.
1349
1350 Fix a bunch of bugs too numerous to mention.
1351
1352 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte
1353 50) of the ISA Hardware Clock when using direct ISA I/O. Problem
1354 discovered by job (jei@iclnl.icl.nl).
1355
1356 Use the rtc clock access method in preference to the KDGHWCLK method.
1357 Problem discovered by Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>.
1358
1359 November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt
1360 (janl@math.uio.no) to make it compile on linux 1.2 machines as well
1361 as more recent versions of the kernel. Introduced the NO_CLOCK
1362 access method and wrote feature test code to detect absense of rtc
1363 headers.
1364
1365
1366 **************************************************************************
1367 Maintenance notes
1368
1369 To compile this, you must use GNU compiler optimization (-O option)
1370 in order to make the "extern inline" functions from asm/io.h (inb(),
1371 etc.) compile. If you don't optimize, which means the compiler
1372 will generate no inline functions, the references to these functions
1373 in this program will be compiled as external references. Since you
1374 probably won't be linking with any functions by these names, you will
1375 have unresolved external references when you link.
1376
1377 The program is designed to run setuid superuser, since we need to be
1378 able to do direct I/O. (More to the point: we need permission to
1379 execute the iopl() system call). (However, if you use one of the
1380 methods other than direct ISA I/O to access the clock, no setuid is
1381 required).
1382
1383 Here's some info on how we must deal with the time that elapses while
1384 this program runs: There are two major delays as we run:
1385
1386 1) Waiting up to 1 second for a transition of the Hardware Clock so
1387 we are synchronized to the Hardware Clock.
1388
1389 2) Running the "date" program to interpret the value of our --date
1390 option.
1391
1392 Reading the /etc/adjtime file is the next biggest source of delay and
1393 uncertainty.
1394
1395 The user wants to know what time it was at the moment he invoked us,
1396 not some arbitrary time later. And in setting the clock, he is
1397 giving us the time at the moment we are invoked, so if we set the
1398 clock some time later, we have to add some time to that.
1399
1400 So we check the system time as soon as we start up, then run "date"
1401 and do file I/O if necessary, then wait to synchronize with a
1402 Hardware Clock edge, then check the system time again to see how
1403 much time we spent. We immediately read the clock then and (if
1404 appropriate) report that time, and additionally, the delay we measured.
1405
1406 If we're setting the clock to a time given by the user, we wait some
1407 more so that the total delay is an integral number of seconds, then
1408 set the Hardware Clock to the time the user requested plus that
1409 integral number of seconds. N.B. The Hardware Clock can only be set
1410 in integral seconds.
1411
1412 If we're setting the clock to the system clock value, we wait for
1413 the system clock to reach the top of a second, and then set the
1414 Hardware Clock to the system clock's value.
1415
1416 Here's an interesting point about setting the Hardware Clock: On my
1417 machine, when you set it, it sets to that precise time. But one can
1418 imagine another clock whose update oscillator marches on a steady one
1419 second period, so updating the clock between any two oscillator ticks
1420 is the same as updating it right at the earlier tick. To avoid any
1421 complications that might cause, we set the clock as soon as possible
1422 after an oscillator tick.
1423
1424
1425 About synchronizing to the Hardware Clock when reading the time: The
1426 precision of the Hardware Clock counters themselves is one second.
1427 You can't read the counters and find out that is 12:01:02.5. But if
1428 you consider the location in time of the counter's ticks as part of
1429 its value, then its precision is as infinite as time is continuous!
1430 What I'm saying is this: To find out the _exact_ time in the
1431 hardware clock, we wait until the next clock tick (the next time the
1432 second counter changes) and measure how long we had to wait. We
1433 then read the value of the clock counters and subtract the wait time
1434 and we know precisely what time it was when we set out to query the
1435 time.
1436
1437 hwclock uses this method, and considers the Hardware Clock to have
1438 infinite precision.
1439
1440
1441 Enhancements needed:
1442
1443 - When waiting for whole second boundary in set_hardware_clock_exact,
1444 fail if we miss the goal by more than .1 second, as could happen if
1445 we get pre-empted (by the kernel dispatcher).
1446
1447 ****************************************************************************/
1448