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