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