summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hwclock/clock.h16
-rw-r--r--hwclock/cmos.c979
-rw-r--r--hwclock/hwclock.c2453
-rw-r--r--hwclock/kd.c234
-rw-r--r--hwclock/rtc.c544
5 files changed, 2159 insertions, 2067 deletions
diff --git a/hwclock/clock.h b/hwclock/clock.h
index e4eb7eba8..8d1befe8f 100644
--- a/hwclock/clock.h
+++ b/hwclock/clock.h
@@ -1,20 +1,20 @@
#ifndef HWCLOCK_CLOCK_H
#define HWCLOCK_CLOCK_H
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h> /* for errno, EPERM, EINVAL, ENOENT */
#include <time.h>
#include "c.h"
struct clock_ops {
char *interface_name;
- int (*get_permissions)(void);
- int (*read_hardware_clock)(struct tm *tm);
- int (*set_hardware_clock)(const struct tm *tm);
- int (*synchronize_to_clock_tick)(void);
+ int (*get_permissions) (void);
+ int (*read_hardware_clock) (struct tm * tm);
+ int (*set_hardware_clock) (const struct tm * tm);
+ int (*synchronize_to_clock_tick) (void);
};
extern struct clock_ops *probe_for_cmos_clock(void);
@@ -29,9 +29,9 @@ extern int debug;
extern int epoch_option;
extern void outsyserr(char *msg, ...)
#ifdef __GNUC__
- __attribute__ ((format (printf, 1, 2)));
+ __attribute__ ((format(printf, 1, 2)));
#else
- ;
+ ;
#endif
extern double time_diff(struct timeval subtrahend, struct timeval subtractor);
/* cmos.c */
@@ -50,4 +50,4 @@ extern void hwaudit_exit(int status);
# define hwclock_exit(_status) exit(_status)
#endif
-#endif /* HWCLOCK_CLOCK_H */
+#endif /* HWCLOCK_CLOCK_H */
diff --git a/hwclock/cmos.c b/hwclock/cmos.c
index 0178ef7d3..d6216717f 100644
--- a/hwclock/cmos.c
+++ b/hwclock/cmos.c
@@ -1,47 +1,48 @@
/*
- * i386 CMOS starts out with 14 bytes clock data
- * alpha has something similar, but with details
- * depending on the machine type.
+ * i386 CMOS starts out with 14 bytes clock data alpha has something
+ * similar, but with details depending on the machine type.
*
- * byte 0: seconds (0-59)
- * byte 2: minutes (0-59)
- * byte 4: hours (0-23 in 24hr mode,
- * 1-12 in 12hr mode, with high bit unset/set if am/pm)
- * byte 6: weekday (1-7, Sunday=1)
- * byte 7: day of the month (1-31)
- * byte 8: month (1-12)
- * byte 9: year (0-99)
- * Numbers are stored in BCD/binary if bit 2 of byte 11 is unset/set
- * The clock is in 12hr/24hr mode if bit 1 of byte 11 is unset/set
- * The clock is undefined (being updated) if bit 7 of byte 10 is set.
- * The clock is frozen (to be updated) by setting bit 7 of byte 11
- * Bit 7 of byte 14 indicates whether the CMOS clock is reliable:
- * it is 1 if RTC power has been good since this bit was last read;
- * it is 0 when the battery is dead and system power has been off.
+ * byte 0: seconds 0-59
+ * byte 2: minutes 0-59
+ * byte 4: hours 0-23 in 24hr mode,
+ * 1-12 in 12hr mode, with high bit unset/set
+ * if am/pm.
+ * byte 6: weekday 1-7, Sunday=1
+ * byte 7: day of the month 1-31
+ * byte 8: month 1-12
+ * byte 9: year 0-99
*
- * Avoid setting the RTC clock within 2 seconds of the day rollover
- * that starts a new month or enters daylight saving time.
+ * Numbers are stored in BCD/binary if bit 2 of byte 11 is unset/set The
+ * clock is in 12hr/24hr mode if bit 1 of byte 11 is unset/set The clock is
+ * undefined (being updated) if bit 7 of byte 10 is set. The clock is frozen
+ * (to be updated) by setting bit 7 of byte 11 Bit 7 of byte 14 indicates
+ * whether the CMOS clock is reliable: it is 1 if RTC power has been good
+ * since this bit was last read; it is 0 when the battery is dead and system
+ * power has been off.
+ *
+ * Avoid setting the RTC clock within 2 seconds of the day rollover that
+ * starts a new month or enters daylight saving time.
*
* The century situation is messy:
- * Usually byte 50 (0x32) gives the century (in BCD, so 19 or 20 hex),
- * but IBM PS/2 has (part of) a checksum there and uses byte 55 (0x37).
- * Sometimes byte 127 (0x7f) or Bank 1, byte 0x48 gives the century.
- * The original RTC will not access any century byte; some modern
- * versions will. If a modern RTC or BIOS increments the century byte
- * it may go from 0x19 to 0x20, but in some buggy cases 0x1a is produced.
+ *
+ * Usually byte 50 (0x32) gives the century (in BCD, so 19 or 20 hex), but
+ * IBM PS/2 has (part of) a checksum there and uses byte 55 (0x37).
+ * Sometimes byte 127 (0x7f) or Bank 1, byte 0x48 gives the century. The
+ * original RTC will not access any century byte; some modern versions will.
+ * If a modern RTC or BIOS increments the century byte it may go from 0x19
+ * to 0x20, but in some buggy cases 0x1a is produced.
*/
-
/*
* A struct tm has int fields
- * tm_sec (0-59, 60 or 61 only for leap seconds)
- * tm_min (0-59)
- * tm_hour (0-23)
- * tm_mday (1-31)
- * tm_mon (0-11)
- * tm_year (number of years since 1900)
- * tm_wday (0-6, 0=Sunday)
- * tm_yday (0-365)
- * tm_isdst (>0: yes, 0: no, <0: unknown)
+ * tm_sec 0-59, 60 or 61 only for leap seconds
+ * tm_min 0-59
+ * tm_hour 0-23
+ * tm_mday 1-31
+ * tm_mon 0-11
+ * tm_year number of years since 1900
+ * tm_wday 0-6, 0=Sunday
+ * tm_yday 0-365
+ * tm_isdst >0: yes, 0: no, <0: unknown
*/
#include <unistd.h> /* for geteuid() */
@@ -50,27 +51,40 @@
#include "nls.h"
#if defined(__i386__)
-
# ifdef HAVE_SYS_IO_H
-# include <sys/io.h>
+# include <sys/io.h>
# elif defined(HAVE_ASM_IO_H)
-# include <asm/io.h> /* for inb, outb */
+# include <asm/io.h> /* for inb, outb */
# else
-/* Disable cmos access; we can no longer use asm/io.h, since
- * the kernel does not export that header. */
-# undef __i386__
-void outb(int a, int b){}
-int inb(int c){ return 0; }
-# endif
+/*
+ * Disable cmos access; we can no longer use asm/io.h, since the kernel does
+ * not export that header.
+ */
+#undef __i386__
+void outb(int a, int b)
+{
+}
+
+int inb(int c)
+{
+ return 0;
+}
+#endif /* __i386__ */
#elif defined(__alpha__)
/* <asm/io.h> fails to compile, probably because of u8 etc */
-extern unsigned int inb(unsigned long port);
-extern void outb(unsigned char b,unsigned long port);
+extern unsigned int inb(unsigned long port);
+extern void outb(unsigned char b, unsigned long port);
#else
-void outb(int a, int b){}
-int inb(int c){ return 0; }
-#endif
+void outb(int a, int b)
+{
+}
+
+int inb(int c)
+{
+ return 0;
+}
+#endif /* __alpha__ */
#include "clock.h"
@@ -80,39 +94,40 @@ int inb(int c){ return 0; }
/*
* The epoch.
*
- * Unix uses 1900 as epoch for a struct tm, and 1970 for a time_t.
- * But what was written to CMOS?
- * Digital DECstations use 1928 - this is on a mips or alpha
- * Digital Unix uses 1952, e.g. on AXPpxi33
- * Windows NT uses 1980.
- * The ARC console expects to boot Windows NT and uses 1980.
- * (But a Ruffian uses 1900, just like SRM.)
- * It is reported that ALPHA_PRE_V1_2_SRM_CONSOLE uses 1958.
+ * Unix uses 1900 as epoch for a struct tm, and 1970 for a time_t. But what
+ * was written to CMOS?
+ *
+ * Digital DECstations use 1928 - this is on a mips or alpha Digital Unix
+ * uses 1952, e.g. on AXPpxi33. Windows NT uses 1980. The ARC console
+ * expects to boot Windows NT and uses 1980. (But a Ruffian uses 1900, just
+ * like SRM.) It is reported that ALPHA_PRE_V1_2_SRM_CONSOLE uses 1958.
*/
#define TM_EPOCH 1900
int cmos_epoch = 1900;
-/* Martin Ostermann writes:
-The problem with the Jensen is twofold: First, it has the clock at a
-different address. Secondly, it has a distinction beween "local" and
-normal bus addresses. The local ones pertain to the hardware integrated
-into the chipset, like serial/parallel ports and of course, the RTC.
-Those need to be addressed differently. This is handled fine in the kernel,
-and it's not a problem, since this usually gets totally optimized by the
-compile. But the i/o routines of (g)libc lack this support so far.
-The result of this is, that the old clock program worked only on the
-Jensen when USE_DEV_PORT was defined, but not with the normal inb/outb
-functions.
+/*
+ * Martin Ostermann writes:
+ *
+ * The problem with the Jensen is twofold: First, it has the clock at a
+ * different address. Secondly, it has a distinction beween "local" and
+ * normal bus addresses. The local ones pertain to the hardware integrated
+ * into the chipset, like serial/parallel ports and of course, the RTC.
+ * Those need to be addressed differently. This is handled fine in the
+ * kernel, and it's not a problem, since this usually gets totally optimized
+ * by the compile. But the i/o routines of (g)libc lack this support so far.
+ * The result of this is, that the old clock program worked only on the
+ * Jensen when USE_DEV_PORT was defined, but not with the normal inb/outb
+ * functions.
*/
int use_dev_port = 0; /* 1 for Jensen */
int dev_port_fd;
unsigned short clock_ctl_addr = 0x70; /* 0x170 for Jensen */
-unsigned short clock_data_addr = 0x71; /* 0x171 for Jensen */
-
+unsigned short clock_data_addr = 0x71; /* 0x171 for Jensen */
int century_byte = 0; /* 0: don't access a century byte
- 50 (0x32): usual PC value
- 55 (0x37): PS/2 */
+ * 50 (0x32): usual PC value
+ * 55 (0x37): PS/2
+ */
#ifdef __alpha__
int funkyTOY = 0; /* 1 for PC164/LX164/SX164 type alpha */
@@ -120,217 +135,242 @@ int funkyTOY = 0; /* 1 for PC164/LX164/SX164 type alpha */
#ifdef __alpha
-static int
-is_in_cpuinfo(char *fmt, char *str)
+static int is_in_cpuinfo(char *fmt, char *str)
{
- FILE *cpuinfo;
- char field[256];
- char format[256];
- int found = 0;
-
- sprintf(format, "%s : %s", fmt, "%255s");
-
- if ((cpuinfo = fopen ("/proc/cpuinfo", "r")) != NULL) {
- while (!feof(cpuinfo)) {
- if (fscanf (cpuinfo, format, field) == 1) {
- if (strncmp(field, str, strlen(str)) == 0)
- found = 1;
- break;
- }
- fgets (field, 256, cpuinfo);
+ FILE *cpuinfo;
+ char field[256];
+ char format[256];
+ int found = 0;
+
+ sprintf(format, "%s : %s", fmt, "%255s");
+
+ if ((cpuinfo = fopen("/proc/cpuinfo", "r")) != NULL) {
+ while (!feof(cpuinfo)) {
+ if (fscanf(cpuinfo, format, field) == 1) {
+ if (strncmp(field, str, strlen(str)) == 0)
+ found = 1;
+ break;
+ }
+ fgets(field, 256, cpuinfo);
+ }
+ fclose(cpuinfo);
}
- fclose(cpuinfo);
- }
- return found;
+ return found;
}
-/* Set cmos_epoch, either from user options, or by asking the kernel,
- or by looking at /proc/cpu_info */
-void
-set_cmos_epoch(int ARCconsole, int SRM) {
- unsigned long epoch;
-
- /* Believe the user */
- if (epoch_option != -1) {
- cmos_epoch = epoch_option;
- return;
- }
+/*
+ * Set cmos_epoch, either from user options, or by asking the kernel, or by
+ * looking at /proc/cpu_info
+ */
+void set_cmos_epoch(int ARCconsole, int SRM)
+{
+ unsigned long epoch;
- if (ARCconsole)
- cmos_epoch = 1980;
+ /* Believe the user */
+ if (epoch_option != -1) {
+ cmos_epoch = epoch_option;
+ return;
+ }
- if (ARCconsole || SRM)
- return;
+ if (ARCconsole)
+ cmos_epoch = 1980;
+ if (ARCconsole || SRM)
+ return;
#ifdef __linux__
- /* If we can ask the kernel, we don't need guessing from /proc/cpuinfo */
- if (get_epoch_rtc(&epoch, 1) == 0) {
- cmos_epoch = epoch;
- return;
- }
+ /*
+ * If we can ask the kernel, we don't need guessing from
+ * /proc/cpuinfo
+ */
+ if (get_epoch_rtc(&epoch, 1) == 0) {
+ cmos_epoch = epoch;
+ return;
+ }
#endif
- /* The kernel source today says: read the year.
- If it is in 0-19 then the epoch is 2000.
- If it is in 20-47 then the epoch is 1980.
- If it is in 48-69 then the epoch is 1952.
- If it is in 70-99 then the epoch is 1928.
- Otherwise the epoch is 1900.
- Clearly, this must be changed before 2019. */
-
- /* See whether we are dealing with SRM or MILO, as they have
- different "epoch" ideas. */
- if (is_in_cpuinfo("system serial number", "MILO")) {
- ARCconsole = 1;
- if (debug) printf (_("booted from MILO\n"));
- }
-
- /* See whether we are dealing with a RUFFIAN aka Alpha PC-164 UX (or BX),
- as they have REALLY different TOY (TimeOfYear) format: BCD, and not
- an ARC-style epoch.
- BCD is detected dynamically, but we must NOT adjust like ARC. */
- if (ARCconsole && is_in_cpuinfo("system type", "Ruffian")) {
- ARCconsole = 0;
- if (debug) printf (_("Ruffian BCD clock\n"));
- }
-
- if (ARCconsole)
- cmos_epoch = 1980;
-}
+ /*
+ * The kernel source today says: read the year.
+ *
+ * If it is in 0-19 then the epoch is 2000.
+ * If it is in 20-47 then the epoch is 1980.
+ * If it is in 48-69 then the epoch is 1952.
+ * If it is in 70-99 then the epoch is 1928.
+ *
+ * Otherwise the epoch is 1900.
+ * TODO: Clearly, this must be changed before 2019.
+ */
+ /*
+ * See whether we are dealing with SRM or MILO, as they have
+ * different "epoch" ideas.
+ */
+ if (is_in_cpuinfo("system serial number", "MILO")) {
+ ARCconsole = 1;
+ if (debug)
+ printf(_("booted from MILO\n"));
+ }
-void
-set_cmos_access(int Jensen, int funky_toy) {
-
- /* See whether we're dealing with a Jensen---it has a weird I/O
- system. DEC was just learning how to build Alpha PCs. */
- if (Jensen || is_in_cpuinfo("system type", "Jensen")) {
- use_dev_port = 1;
- clock_ctl_addr = 0x170;
- clock_data_addr = 0x171;
- if (debug) printf (_("clockport adjusted to 0x%x\n"), clock_ctl_addr);
- }
-
- /* see whether we are dealing with PC164/LX164/SX164, as they have a TOY
- that must be accessed differently to work correctly. */
- /* Nautilus stuff reported by Neoklis Kyriazis */
- if (funky_toy ||
- is_in_cpuinfo("system variation", "PC164") ||
- is_in_cpuinfo("system variation", "LX164") ||
- is_in_cpuinfo("system variation", "SX164") ||
- is_in_cpuinfo("system type", "Nautilus")) {
- funkyTOY = 1;
- if (debug) printf (_("funky TOY!\n"));
- }
+ /*
+ * See whether we are dealing with a RUFFIAN aka Alpha PC-164 UX (or
+ * BX), as they have REALLY different TOY (TimeOfYear) format: BCD,
+ * and not an ARC-style epoch. BCD is detected dynamically, but we
+ * must NOT adjust like ARC.
+ */
+ if (ARCconsole && is_in_cpuinfo("system type", "Ruffian")) {
+ ARCconsole = 0;
+ if (debug)
+ printf(_("Ruffian BCD clock\n"));
+ }
+
+ if (ARCconsole)
+ cmos_epoch = 1980;
}
-#endif
+void set_cmos_access(int Jensen, int funky_toy)
+{
+
+ /*
+ * See whether we're dealing with a Jensen---it has a weird I/O
+ * system. DEC was just learning how to build Alpha PCs.
+ */
+ if (Jensen || is_in_cpuinfo("system type", "Jensen")) {
+ use_dev_port = 1;
+ clock_ctl_addr = 0x170;
+ clock_data_addr = 0x171;
+ if (debug)
+ printf(_("clockport adjusted to 0x%x\n"),
+ clock_ctl_addr);
+ }
+
+ /*
+ * See whether we are dealing with PC164/LX164/SX164, as they have a
+ * TOY that must be accessed differently to work correctly.
+ */
+ /* Nautilus stuff reported by Neoklis Kyriazis */
+ if (funky_toy ||
+ is_in_cpuinfo("system variation", "PC164") ||
+ is_in_cpuinfo("system variation", "LX164") ||
+ is_in_cpuinfo("system variation", "SX164") ||
+ is_in_cpuinfo("system type", "Nautilus")) {
+ funkyTOY = 1;
+ if (debug)
+ printf(_("funky TOY!\n"));
+ }
+}
+#endif /* __alpha */
#if __alpha__
/*
- * The Alpha doesn't allow user-level code to disable interrupts (for
- * good reasons). Instead, we ensure atomic operation by performing
- * the operation and checking whether the high 32 bits of the cycle
- * counter changed. If they did, a context switch must have occurred
- * and we redo the operation. As long as the operation is reasonably
- * short, it will complete atomically, eventually.
+ * The Alpha doesn't allow user-level code to disable interrupts (for good
+ * reasons). Instead, we ensure atomic operation by performing the operation
+ * and checking whether the high 32 bits of the cycle counter changed. If
+ * they did, a context switch must have occurred and we redo the operation.
+ * As long as the operation is reasonably short, it will complete
+ * atomically, eventually.
*/
-
static unsigned long
-atomic(const char *name, unsigned long (*op)(unsigned long),
- unsigned long arg)
+atomic(const char *name, unsigned long (*op) (unsigned long), unsigned long arg)
{
- unsigned long ts1, ts2, n, v;
-
- for (n = 0; n < 1000; ++n) {
- asm volatile ("rpcc %0" : "r="(ts1));
- v = (*op)(arg);
- asm volatile ("rpcc %0" : "r="(ts2));
-
- if ((ts1 ^ ts2) >> 32 == 0) {
- return v;
- }
- }
- fprintf(stderr, _("%s: atomic %s failed for 1000 iterations!"), progname, name);
- exit(1);
+ unsigned long ts1, ts2, n, v;
+
+ for (n = 0; n < 1000; ++n) {
+ asm volatile ("rpcc %0":"r=" (ts1));
+ v = (*op) (arg);
+ asm volatile ("rpcc %0":"r=" (ts2));
+
+ if ((ts1 ^ ts2) >> 32 == 0) {
+ return v;
+ }
+ }
+ fprintf(stderr, _("%s: atomic %s failed for 1000 iterations!"),
+ progname, name);
+ exit(1);
}
#else
/*
- * Hmmh, this isn't very atomic. Maybe we should force an error
- * instead?
+ * Hmmh, this isn't very atomic. Maybe we should force an error instead?
*
- * TODO: optimize the access to CMOS by mlockall(MCL_CURRENT)
- * and SCHED_FIFO
+ * TODO: optimize the access to CMOS by mlockall(MCL_CURRENT) and SCHED_FIFO
*/
static unsigned long
-atomic(const char *name, unsigned long (*op)(unsigned long),
- unsigned long arg)
+atomic(const char *name, unsigned long (*op) (unsigned long), unsigned long arg)
{
- return (*op)(arg);
+ return (*op) (arg);
}
#endif
-
-static inline
-unsigned long cmos_read(unsigned long reg)
+static inline unsigned long cmos_read(unsigned long reg)
{
- if (use_dev_port) {
- unsigned char v = reg | 0x80;
- lseek(dev_port_fd, clock_ctl_addr, 0);
- if (write(dev_port_fd, &v, 1) == -1 && debug)
- printf(_("cmos_read(): write to control address %X failed: %s\n"), clock_ctl_addr, strerror(errno));
- lseek(dev_port_fd, clock_data_addr, 0);
- if (read(dev_port_fd, &v, 1) == -1 && debug)
- printf(_("cmos_read(): read data address %X failed: %s\n"), clock_data_addr, strerror(errno));
- return v;
- } else {
- /* We only want to read CMOS data, but unfortunately
- writing to bit 7 disables (1) or enables (0) NMI;
- since this bit is read-only we have to guess the old status.
- Various docs suggest that one should disable NMI while
- reading/writing CMOS data, and enable it again afterwards.
- This would yield the sequence
- outb (reg | 0x80, 0x70);
- val = inb(0x71);
- outb (0x0d, 0x70); // 0x0d: random read-only location
- Other docs state that "any write to 0x70 should be followed
- by an action to 0x71 or the RTC wil be left in an unknown state".
- Most docs say that it doesnt matter at all what one does.
- */
- /* bit 0x80: disable NMI while reading - should we?
- Let us follow the kernel and not disable.
- Called only with 0 <= reg < 128 */
- outb (reg, clock_ctl_addr);
- return inb (clock_data_addr);
- }
+ if (use_dev_port) {
+ unsigned char v = reg | 0x80;
+ lseek(dev_port_fd, clock_ctl_addr, 0);
+ if (write(dev_port_fd, &v, 1) == -1 && debug)
+ printf(_
+ ("cmos_read(): write to control address %X failed: %s\n"),
+ clock_ctl_addr, strerror(errno));
+ lseek(dev_port_fd, clock_data_addr, 0);
+ if (read(dev_port_fd, &v, 1) == -1 && debug)
+ printf(_
+ ("cmos_read(): read data address %X failed: %s\n"),
+ clock_data_addr, strerror(errno));
+ return v;
+ } else {
+ /*
+ * We only want to read CMOS data, but unfortunately writing
+ * to bit 7 disables (1) or enables (0) NMI; since this bit
+ * is read-only we have to guess the old status. Various
+ * docs suggest that one should disable NMI while
+ * reading/writing CMOS data, and enable it again
+ * afterwards. This would yield the sequence
+ *
+ * outb (reg | 0x80, 0x70);
+ * val = inb(0x71);
+ * outb (0x0d, 0x70); // 0x0d: random read-only location
+ *
+ * Other docs state that "any write to 0x70 should be
+ * followed by an action to 0x71 or the RTC wil be left in
+ * an unknown state". Most docs say that it doesnt matter at
+ * all what one does.
+ */
+ /*
+ * bit 0x80: disable NMI while reading - should we? Let us
+ * follow the kernel and not disable. Called only with 0 <=
+ * reg < 128
+ */
+ outb(reg, clock_ctl_addr);
+ return inb(clock_data_addr);
+ }
}
-static inline
-unsigned long cmos_write(unsigned long reg, unsigned long val)
+static inline unsigned long cmos_write(unsigned long reg, unsigned long val)
{
- if (use_dev_port) {
- unsigned char v = reg | 0x80;
- lseek(dev_port_fd, clock_ctl_addr, 0);
- if (write(dev_port_fd, &v, 1) == -1 && debug)
- printf(_("cmos_write(): write to control address %X failed: %s\n"), clock_ctl_addr, strerror(errno));
- v = (val & 0xff);
- lseek(dev_port_fd, clock_data_addr, 0);
- if (write(dev_port_fd, &v, 1) == -1 && debug)
- printf(_("cmos_write(): write to data address %X failed: %s\n"), clock_data_addr, strerror(errno));
- } else {
- outb (reg, clock_ctl_addr);
- outb (val, clock_data_addr);
- }
- return 0;
+ if (use_dev_port) {
+ unsigned char v = reg | 0x80;
+ lseek(dev_port_fd, clock_ctl_addr, 0);
+ if (write(dev_port_fd, &v, 1) == -1 && debug)
+ printf(_
+ ("cmos_write(): write to control address %X failed: %s\n"),
+ clock_ctl_addr, strerror(errno));
+ v = (val & 0xff);
+ lseek(dev_port_fd, clock_data_addr, 0);
+ if (write(dev_port_fd, &v, 1) == -1 && debug)
+ printf(_
+ ("cmos_write(): write to data address %X failed: %s\n"),
+ clock_data_addr, strerror(errno));
+ } else {
+ outb(reg, clock_ctl_addr);
+ outb(val, clock_data_addr);
+ }
+ return 0;
}
static unsigned long cmos_set_time(unsigned long arg)
{
- unsigned char save_control, save_freq_select, pmbit = 0;
- struct tm tm = *(struct tm *) arg;
- unsigned int century;
+ unsigned char save_control, save_freq_select, pmbit = 0;
+ struct tm tm = *(struct tm *)arg;
+ unsigned int century;
/*
* CMOS byte 10 (clock status register A) has 3 bitfields:
@@ -349,260 +389,261 @@ static unsigned long cmos_set_time(unsigned long arg)
* 1111 500 milliseconds (maximum, 2 Hz)
* 0110 976.562 microseconds (default 1024 Hz)
*/
+ save_control = cmos_read(11); /* tell the clock it's being set */
+ cmos_write(11, (save_control | 0x80));
+ save_freq_select = cmos_read(10); /* stop and reset prescaler */
+ cmos_write(10, (save_freq_select | 0x70));
+
+ tm.tm_year += TM_EPOCH;
+ century = tm.tm_year / 100;
+ tm.tm_year -= cmos_epoch;
+ tm.tm_year %= 100;
+ tm.tm_mon += 1;
+ tm.tm_wday += 1;
+
+ if (!(save_control & 0x02)) { /* 12hr mode; the default is 24hr mode */
+ if (tm.tm_hour == 0)
+ tm.tm_hour = 24;
+ if (tm.tm_hour > 12) {
+ tm.tm_hour -= 12;
+ pmbit = 0x80;
+ }
+ }
+
+ if (!(save_control & 0x04)) { /* BCD mode - the default */
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_wday);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_year);
+ BIN_TO_BCD(century);
+ }
- save_control = cmos_read (11); /* tell the clock it's being set */
- cmos_write (11, (save_control | 0x80));
- save_freq_select = cmos_read (10); /* stop and reset prescaler */
- cmos_write (10, (save_freq_select | 0x70));
-
- tm.tm_year += TM_EPOCH;
- century = tm.tm_year/100;
- tm.tm_year -= cmos_epoch;
- tm.tm_year %= 100;
- tm.tm_mon += 1;
- tm.tm_wday += 1;
-
- if (!(save_control & 0x02)) { /* 12hr mode; the default is 24hr mode */
- if (tm.tm_hour == 0)
- tm.tm_hour = 24;
- if (tm.tm_hour > 12) {
- tm.tm_hour -= 12;
- pmbit = 0x80;
- }
- }
-
- if (!(save_control & 0x04)) { /* BCD mode - the default */
- BIN_TO_BCD(tm.tm_sec);
- BIN_TO_BCD(tm.tm_min);
- BIN_TO_BCD(tm.tm_hour);
- BIN_TO_BCD(tm.tm_wday);
- BIN_TO_BCD(tm.tm_mday);
- BIN_TO_BCD(tm.tm_mon);
- BIN_TO_BCD(tm.tm_year);
- BIN_TO_BCD(century);
- }
-
- cmos_write (0, tm.tm_sec);
- cmos_write (2, tm.tm_min);
- cmos_write (4, tm.tm_hour | pmbit);
- cmos_write (6, tm.tm_wday);
- cmos_write (7, tm.tm_mday);
- cmos_write (8, tm.tm_mon);
- cmos_write (9, tm.tm_year);
- if (century_byte)
- cmos_write (century_byte, century);
-
-
- /* The kernel sources, linux/arch/i386/kernel/time.c, have the
- following comment:
-
- The following flags have to be released exactly in this order,
- otherwise the DS12887 (popular MC146818A clone with integrated
- battery and quartz) will not reset the oscillator and will not
- update precisely 500 ms later. You won't find this mentioned
- in the Dallas Semiconductor data sheets, but who believes data
- sheets anyway ... -- Markus Kuhn
- */
-
- cmos_write (11, save_control);
- cmos_write (10, save_freq_select);
- return 0;
+ cmos_write(0, tm.tm_sec);
+ cmos_write(2, tm.tm_min);
+ cmos_write(4, tm.tm_hour | pmbit);
+ cmos_write(6, tm.tm_wday);
+ cmos_write(7, tm.tm_mday);
+ cmos_write(8, tm.tm_mon);
+ cmos_write(9, tm.tm_year);
+ if (century_byte)
+ cmos_write(century_byte, century);
+
+ /*
+ * The kernel sources, linux/arch/i386/kernel/time.c, have the
+ * following comment:
+ *
+ * The following flags have to be released exactly in this order,
+ * otherwise the DS12887 (popular MC146818A clone with integrated
+ * battery and quartz) will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned in
+ * the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */
+ cmos_write(11, save_control);
+ cmos_write(10, save_freq_select);
+ return 0;
}
-static int
-hclock_read(unsigned long reg) {
+static int hclock_read(unsigned long reg)
+{
return atomic("clock read", cmos_read, (reg));
}
-static void
-hclock_set_time(const struct tm *tm) {
+static void hclock_set_time(const struct tm *tm)
+{
atomic("set time", cmos_set_time, (unsigned long)(tm));
}
-static inline int
-cmos_clock_busy(void) {
+static inline int cmos_clock_busy(void)
+{
return
#ifdef __alpha__
- /* poll bit 4 (UF) of Control Register C */
+ /* poll bit 4 (UF) of Control Register C */
funkyTOY ? (hclock_read(12) & 0x10) :
#endif
- /* poll bit 7 (UIP) of Control Register A */
+ /* poll bit 7 (UIP) of Control Register A */
(hclock_read(10) & 0x80);
}
-
-static int
-synchronize_to_clock_tick_cmos(void) {
- int i;
-
- /* Wait for rise. Should be within a second, but in case something
- weird happens, we have a limit on this loop to reduce the impact
- of this failure.
- */
- for (i = 0; !cmos_clock_busy(); i++)
- if (i >= 10000000)
- return 1;
-
- /* Wait for fall. Should be within 2.228 ms. */
- for (i = 0; cmos_clock_busy(); i++)
- if (i >= 1000000)
- return 1;
- return 0;
+static int synchronize_to_clock_tick_cmos(void)
+{
+ int i;
+
+ /*
+ * Wait for rise. Should be within a second, but in case something
+ * weird happens, we have a limit on this loop to reduce the impact
+ * of this failure.
+ */
+ for (i = 0; !cmos_clock_busy(); i++)
+ if (i >= 10000000)
+ return 1;
+
+ /* Wait for fall. Should be within 2.228 ms. */
+ for (i = 0; cmos_clock_busy(); i++)
+ if (i >= 1000000)
+ return 1;
+ return 0;
}
-
-
-static int
-read_hardware_clock_cmos(struct tm *tm) {
-/*----------------------------------------------------------------------------
- Read the hardware clock and return the current time via <tm> argument.
- Assume we have an ISA machine and read the clock directly with CPU I/O
- instructions.
-
- This function is not totally reliable. It takes a finite and
- unpredictable amount of time to execute the code below. During that
- time, the clock may change and we may even read an invalid value in
- the middle of an update. We do a few checks to minimize this
- possibility, but only the kernel can actually read the clock
- properly, since it can execute code in a short and predictable
- amount of time (by turning of interrupts).
-
- In practice, the chance of this function returning the wrong time is
- extremely remote.
-
------------------------------------------------------------------------------*/
- bool got_time = FALSE;
- unsigned char status, pmbit;
-
- status = pmbit = 0; /* just for gcc */
-
- while (!got_time) {
- /* Bit 7 of Byte 10 of the Hardware Clock value is the Update In Progress
- (UIP) bit, which is on while and 244 uS before the Hardware Clock
- updates itself. It updates the counters individually, so reading
- them during an update would produce garbage. The update takes 2mS,
- so we could be spinning here that long waiting for this bit to turn
- off.
-
- Furthermore, it is pathologically possible for us to be in this
- code so long that even if the UIP bit is not on at first, the
- clock has changed while we were running. We check for that too,
- and if it happens, we start over.
- */
-
- if (!cmos_clock_busy()) {
- /* No clock update in progress, go ahead and read */
- tm->tm_sec = hclock_read(0);
- tm->tm_min = hclock_read(2);
- tm->tm_hour = hclock_read(4);
- tm->tm_wday = hclock_read(6);
- tm->tm_mday = hclock_read(7);
- tm->tm_mon = hclock_read(8);
- tm->tm_year = hclock_read(9);
- status = hclock_read(11);
+/*
+ * Read the hardware clock and return the current time via <tm> argument.
+ * Assume we have an ISA machine and read the clock directly with CPU I/O
+ * instructions.
+ *
+ * This function is not totally reliable. It takes a finite and
+ * unpredictable amount of time to execute the code below. During that time,
+ * the clock may change and we may even read an invalid value in the middle
+ * of an update. We do a few checks to minimize this possibility, but only
+ * the kernel can actually read the clock properly, since it can execute
+ * code in a short and predictable amount of time (by turning of
+ * interrupts).
+ *
+ * In practice, the chance of this function returning the wrong time is
+ * extremely remote.
+ */
+static int read_hardware_clock_cmos(struct tm *tm)
+{
+ bool got_time = FALSE;
+ unsigned char status, pmbit;
+
+ status = pmbit = 0; /* just for gcc */
+
+ while (!got_time) {
+ /*
+ * Bit 7 of Byte 10 of the Hardware Clock value is the
+ * Update In Progress (UIP) bit, which is on while and 244
+ * uS before the Hardware Clock updates itself. It updates
+ * the counters individually, so reading them during an
+ * update would produce garbage. The update takes 2mS, so we
+ * could be spinning here that long waiting for this bit to
+ * turn off.
+ *
+ * Furthermore, it is pathologically possible for us to be
+ * in this code so long that even if the UIP bit is not on
+ * at first, the clock has changed while we were running. We
+ * check for that too, and if it happens, we start over.
+ */
+ if (!cmos_clock_busy()) {
+ /* No clock update in progress, go ahead and read */
+ tm->tm_sec = hclock_read(0);
+ tm->tm_min = hclock_read(2);
+ tm->tm_hour = hclock_read(4);
+ tm->tm_wday = hclock_read(6);
+ tm->tm_mday = hclock_read(7);
+ tm->tm_mon = hclock_read(8);
+ tm->tm_year = hclock_read(9);
+ status = hclock_read(11);
#if 0
- if (century_byte)
- century = hclock_read(century_byte);
+ if (century_byte)
+ century = hclock_read(century_byte);
#endif
+ /*
+ * Unless the clock changed while we were reading,
+ * consider this a good clock read .
+ */
+ if (tm->tm_sec == hclock_read(0))
+ got_time = TRUE;
+ }
+ /*
+ * Yes, in theory we could have been running for 60 seconds
+ * and the above test wouldn't work!
+ */
+ }
- /* Unless the clock changed while we were reading, consider this
- a good clock read .
- */
- if (tm->tm_sec == hclock_read (0))
- got_time = TRUE;
- }
- /* Yes, in theory we could have been running for 60 seconds and
- the above test wouldn't work!
- */
- }
-
- if (!(status & 0x04)) { /* BCD mode - the default */
- BCD_TO_BIN(tm->tm_sec);
- BCD_TO_BIN(tm->tm_min);
- pmbit = (tm->tm_hour & 0x80);
- tm->tm_hour &= 0x7f;
- BCD_TO_BIN(tm->tm_hour);
- BCD_TO_BIN(tm->tm_wday);
- BCD_TO_BIN(tm->tm_mday);
- BCD_TO_BIN(tm->tm_mon);
- BCD_TO_BIN(tm->tm_year);
+ if (!(status & 0x04)) { /* BCD mode - the default */
+ BCD_TO_BIN(tm->tm_sec);
+ BCD_TO_BIN(tm->tm_min);
+ pmbit = (tm->tm_hour & 0x80);
+ tm->tm_hour &= 0x7f;
+ BCD_TO_BIN(tm->tm_hour);
+ BCD_TO_BIN(tm->tm_wday);
+ BCD_TO_BIN(tm->tm_mday);
+ BCD_TO_BIN(tm->tm_mon);
+ BCD_TO_BIN(tm->tm_year);
#if 0
- BCD_TO_BIN(century);
+ BCD_TO_BIN(century);
#endif
- }
-
- /* We don't use the century byte of the Hardware Clock
- since we don't know its address (usually 50 or 55).
- Here, we follow the advice of the X/Open Base Working Group:
- "if century is not specified, then values in the range [69-99]
- refer to years in the twentieth century (1969 to 1999 inclusive),
- and values in the range [00-68] refer to years in the twenty-first
- century (2000 to 2068 inclusive)."
- */
-
- tm->tm_wday -= 1;
- tm->tm_mon -= 1;
- tm->tm_year += (cmos_epoch - TM_EPOCH);
- if (tm->tm_year < 69)
- tm->tm_year += 100;
- if (pmbit) {
- tm->tm_hour += 12;
- if (tm->tm_hour == 24)
- tm->tm_hour = 0;
- }
-
- tm->tm_isdst = -1; /* don't know whether it's daylight */
- return 0;
-}
+ }
+ /*
+ * We don't use the century byte of the Hardware Clock since we
+ * don't know its address (usually 50 or 55). Here, we follow the
+ * advice of the X/Open Base Working Group: "if century is not
+ * specified, then values in the range [69-99] refer to years in the
+ * twentieth century (1969 to 1999 inclusive), and values in the
+ * range [00-68] refer to years in the twenty-first century (2000 to
+ * 2068 inclusive)."
+ */
+ tm->tm_wday -= 1;
+ tm->tm_mon -= 1;
+ tm->tm_year += (cmos_epoch - TM_EPOCH);
+ if (tm->tm_year < 69)
+ tm->tm_year += 100;
+ if (pmbit) {
+ tm->tm_hour += 12;
+ if (tm->tm_hour == 24)
+ tm->tm_hour = 0;
+ }
+ tm->tm_isdst = -1; /* don't know whether it's daylight */
+ return 0;
+}
-static int
-set_hardware_clock_cmos(const struct tm *new_broken_time) {
+static int set_hardware_clock_cmos(const struct tm *new_broken_time)
+{
- hclock_set_time(new_broken_time);
- return 0;
+ hclock_set_time(new_broken_time);
+ return 0;
}
-static int
-i386_iopl(const int level) {
+static int i386_iopl(const int level)
+{
#if defined(__i386__) || defined(__alpha__)
#if defined(HAVE_IOPL)
- extern int iopl(const int lvl);
- return iopl(level);
+ extern int iopl(const int lvl);
+ return iopl(level);
#else
- extern int ioperm(unsigned long from, unsigned long num, int turn_on);
- return ioperm(clock_ctl_addr, 2, 1);
+ extern int ioperm(unsigned long from, unsigned long num, int turn_on);
+ return ioperm(clock_ctl_addr, 2, 1);
#endif
#else
- return -2;
+ return -2;
#endif
}
-static int
-get_permissions_cmos(void) {
- int rc;
-
- if (use_dev_port) {
- if ((dev_port_fd = open("/dev/port", O_RDWR)) < 0) {
- int errsv = errno;
- fprintf(stderr, _("Cannot open /dev/port: %s"), strerror(errsv));
- rc = 1;
- } else
- rc = 0;
- } else {
- rc = i386_iopl(3);
- if (rc == -2) {
- fprintf(stderr, _("I failed to get permission because I didn't try.\n"));
- } else if (rc != 0) {
- rc = errno;
- fprintf(stderr, _("%s is unable to get I/O port access: "
- "the iopl(3) call failed.\n"), progname);
- if(rc == EPERM && geteuid())
- fprintf(stderr, _("Probably you need root privileges.\n"));
- }
- }
- return rc ? 1 : 0;
+static int get_permissions_cmos(void)
+{
+ int rc;
+
+ if (use_dev_port) {
+ if ((dev_port_fd = open("/dev/port", O_RDWR)) < 0) {
+ int errsv = errno;
+ fprintf(stderr, _("Cannot open /dev/port: %s"),
+ strerror(errsv));
+ rc = 1;
+ } else
+ rc = 0;
+ } else {
+ rc = i386_iopl(3);
+ if (rc == -2) {
+ fprintf(stderr,
+ _
+ ("I failed to get permission because I didn't try.\n"));
+ } else if (rc != 0) {
+ rc = errno;
+ fprintf(stderr,
+ _("%s is unable to get I/O port access: "
+ "the iopl(3) call failed.\n"), progname);
+ if (rc == EPERM && geteuid())
+ fprintf(stderr,
+ _
+ ("Probably you need root privileges.\n"));
+ }
+ }
+ return rc ? 1 : 0;
}
static struct clock_ops cmos = {
@@ -613,17 +654,17 @@ static struct clock_ops cmos = {
synchronize_to_clock_tick_cmos,
};
-
-/* return &cmos if cmos clock present, NULL otherwise */
-/* choose this construction to avoid gcc messages about unused variables */
-
-struct clock_ops *
-probe_for_cmos_clock(void){
- int have_cmos =
+/*
+ * return &cmos if cmos clock present, NULL otherwise choose this
+ * construction to avoid gcc messages about unused variables
+ */
+struct clock_ops *probe_for_cmos_clock(void)
+{
+ int have_cmos =
#if defined(__i386__) || defined(__alpha__)
TRUE;
#else
FALSE;
#endif
- return have_cmos ? &cmos : NULL;
+ return have_cmos ? &cmos : NULL;
}
diff --git a/hwclock/hwclock.c b/hwclock/hwclock.c
index 68e76b896..0c6b0f6cd 100644
--- a/hwclock/hwclock.c
+++ b/hwclock/hwclock.c
@@ -8,35 +8,24 @@
*
* Major rewrite by Bryan Henderson <bryanh@giraffe-data.com>, 96.09.19.
* The new program is called hwclock. New features:
- * - You can set the hardware clock without also modifying the system clock.
- * - You can read and set the clock with finer than 1 second precision.
- * - When you set the clock, hwclock automatically refigures the drift
- * rate, based on how far off the clock was before you set it.
+ *
+ * - You can set the hardware clock without also modifying the system
+ * clock.
+ * - You can read and set the clock with finer than 1 second precision.
+ * - When you set the clock, hwclock automatically refigures the drift
+ * rate, based on how far off the clock was before you set it.
*
* Reshuffled things, added sparc code, and re-added alpha stuff
* by David Mosberger <davidm@azstarnet.com>
* and Jay Estabrook <jestabro@amt.tay1.dec.com>
* and Martin Ostermann <ost@coments.rwth-aachen.de>, aeb@cwi.nl, 990212.
*
- * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98
+ * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98
* Change of local time handling, Stefan Ring <e9725446@stud3.tuwien.ac.at>
* Change of adjtime handling, James P. Rutledge <ao112@rgfn.epcc.edu>.
*
* Distributed under GPL
*/
-
-/*
- * clock [-u] -r - read hardware clock
- * clock [-u] -w - write hardware clock from system time
- * clock [-u] -s - set system time from hardware clock
- * clock [-u] -a - set system time from hardware clock, adjust the time
- * to correct for systematic error, and write it back to
- * the hardware clock
- * -u indicates cmos clock is kept in universal time
- * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980)
- * -J indicates we're dealing with a Jensen (early DEC Alpha PC)
- */
-
/*
* Explanation of `adjusting' (Rob Hooft):
*
@@ -49,23 +38,23 @@
* to determine the correction, and to save its data. In this file are
* three numbers:
*
- * 1) the correction in seconds per day. (So if your clock runs 5
- * seconds per day fast, the first number should read -5.0)
- * 2) the number of seconds since 1/1/1970 the last time the program
- * was used
- * 3) the remaining part of a second which was leftover after the last
- * adjustment
+ * 1) the correction in seconds per day. (So if your clock runs 5
+ * seconds per day fast, the first number should read -5.0)
+ * 2) the number of seconds since 1/1/1970 the last time the program
+ * was used
+ * 3) the remaining part of a second which was leftover after the last
+ * adjustment
*
* Installation and use of this program:
*
- * a) create a file '/etc/adjtime' containing as the first and only line:
- * '0.0 0 0.0'
- * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in
- * universal or local time. This updates the second number.
- * c) set your system time using the 'date' command.
- * d) update your cmos time using 'clock -wu' or 'clock -w'
- * e) replace the first number in /etc/adjtime by your correction.
- * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local'
+ * a) create a file '/etc/adjtime' containing as the first and only
+ * line: '0.0 0 0.0'
+ * b) run 'clock -au' or 'clock -a', depending on whether your cmos is
+ * in universal or local time. This updates the second number.
+ * c) set your system time using the 'date' command.
+ * d) update your cmos time using 'clock -wu' or 'clock -w'
+ * e) replace the first number in /etc/adjtime by your correction.
+ * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local'
*/
#include <string.h>
@@ -108,115 +97,125 @@ const char *adj_file_name = NULL;
#define LASTDATE "/var/lib/lastdate"
struct adjtime {
- /* This is information we keep in the adjtime file that tells us how
- to do drift corrections. Elements are all straight from the
- adjtime file, so see documentation of that file for details.
- Exception is <dirty>, which is an indication that what's in this
- structure is not what's in the disk file (because it has been
- updated since read from the disk file).
- */
- bool dirty;
-
- /* line 1 */
- double drift_factor;
- time_t last_adj_time;
- double not_adjusted;
-
- /* line 2 */
- time_t last_calib_time;
- /* The most recent time that we set the clock from an external
- authority (as opposed to just doing a drift adjustment) */
-
- /* line 3 */
- enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc;
- /* To which time zone, local or UTC, we most recently set the
- hardware clock. */
+ /*
+ * This is information we keep in the adjtime file that tells us how
+ * to do drift corrections. Elements are all straight from the
+ * adjtime file, so see documentation of that file for details.
+ * Exception is <dirty>, which is an indication that what's in this
+ * structure is not what's in the disk file (because it has been
+ * updated since read from the disk file).
+ */
+ bool dirty;
+ /* line 1 */
+ double drift_factor;
+ time_t last_adj_time;
+ double not_adjusted;
+ /* line 2 */
+ time_t last_calib_time;
+ /*
+ * The most recent time that we set the clock from an external
+ * authority (as opposed to just doing a drift adjustment)
+ */
+ /* line 3 */
+ enum a_local_utc { LOCAL, UTC, UNKNOWN } local_utc;
+ /*
+ * To which time zone, local or UTC, we most recently set the
+ * hardware clock.
+ */
};
+
+/*
+ * We are running in debug mode, wherein we put a lot of information about
+ * what we're doing to standard output.
+ */
bool debug;
- /* We are running in debug mode, wherein we put a lot of information about
- what we're doing to standard output. */
+/* Workaround for Award 4.50g BIOS bug: keep the year in a file. */
bool badyear;
- /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */
+/* User-specified epoch, used when rtc fails to return epoch. */
int epoch_option = -1;
- /* User-specified epoch, used when rtc fails to return epoch. */
/*
- * Almost all Award BIOS's made between 04/26/94 and 05/31/95
- * have a nasty bug limiting the RTC year byte to the range 94-99.
- * Any year between 2000 and 2093 gets changed to 2094, every time
- * you start the system.
- * With the --badyear option, we write the date to file and hope
- * that the file is updated at least once a year.
- * I recommend putting this command "hwclock --badyear" in the monthly
- * crontab, just to be safe. -- Dave Coffin 11/12/98
+ * Almost all Award BIOS's made between 04/26/94 and 05/31/95 have a nasty
+ * bug limiting the RTC year byte to the range 94-99. Any year between 2000
+ * and 2093 gets changed to 2094, every time you start the system.
+ *
+ * With the --badyear option, we write the date to file and hope that the
+ * file is updated at least once a year. I recommend putting this command
+ * "hwclock --badyear" in the monthly crontab, just to be safe.
+ *
+ * -- Dave Coffin 11/12/98
*/
-static void
-write_date_to_file (struct tm *tm) {
- FILE *fp;
-
- if ((fp = fopen(LASTDATE,"w"))) {
- fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1,
- tm->tm_year+1900);
- fclose(fp);
- } else
- perror(LASTDATE);
+static void write_date_to_file(struct tm *tm)
+{
+ FILE *fp;
+
+ if ((fp = fopen(LASTDATE, "w"))) {
+ fprintf(fp, "%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon + 1,
+ tm->tm_year + 1900);
+ fclose(fp);
+ } else
+ perror(LASTDATE);
}
-static void
-read_date_from_file (struct tm *tm) {
- int last_mday, last_mon, last_year;
- FILE *fp;
-
- if ((fp = fopen(LASTDATE,"r"))) {
- if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) {
- tm->tm_year = last_year-1900;
- if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday)
- tm->tm_year ++;
- }
- fclose(fp);
- }
- write_date_to_file (tm);
+static void read_date_from_file(struct tm *tm)
+{
+ int last_mday, last_mon, last_year;
+ FILE *fp;
+
+ if ((fp = fopen(LASTDATE, "r"))) {
+ if (fscanf(fp, "%d.%d.%d\n", &last_mday, &last_mon, &last_year)
+ == 3) {
+ tm->tm_year = last_year - 1900;
+ if ((tm->tm_mon << 5) + tm->tm_mday <
+ ((last_mon - 1) << 5) + last_mday)
+ tm->tm_year++;
+ }
+ fclose(fp);
+ }
+ write_date_to_file(tm);
}
-double
-time_diff(struct timeval subtrahend, struct timeval subtractor) {
-/*---------------------------------------------------------------------------
- The difference in seconds between two times in "timeval" format.
-----------------------------------------------------------------------------*/
- return (subtrahend.tv_sec - subtractor.tv_sec)
- + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6;
+/*
+ * The difference in seconds between two times in "timeval" format.
+ */
+double time_diff(struct timeval subtrahend, struct timeval subtractor)
+{
+ return (subtrahend.tv_sec - subtractor.tv_sec)
+ + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6;
}
-
-static struct timeval
-time_inc(struct timeval addend, double increment) {
-/*----------------------------------------------------------------------------
- The time, in "timeval" format, which is <increment> seconds after
- the time <addend>. Of course, <increment> may be negative.
------------------------------------------------------------------------------*/
- struct timeval newtime;
-
- newtime.tv_sec = addend.tv_sec + (int) increment;
- newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6;
-
- /* Now adjust it so that the microsecond value is between 0 and 1 million */
- if (newtime.tv_usec < 0) {
- newtime.tv_usec += 1E6;
- newtime.tv_sec -= 1;
- } else if (newtime.tv_usec >= 1E6) {
- newtime.tv_usec -= 1E6;
- newtime.tv_sec += 1;
- }
- return newtime;
+/*
+ * The time, in "timeval" format, which is <increment> seconds after the
+ * time <addend>. Of course, <increment> may be negative.
+ */
+static struct timeval time_inc(struct timeval addend, double increment)
+{
+ struct timeval newtime;
+
+ newtime.tv_sec = addend.tv_sec + (int)increment;
+ newtime.tv_usec = addend.tv_usec + (increment - (int)increment) * 1E6;
+
+ /*
+ * Now adjust it so that the microsecond value is between 0 and 1
+ * million.
+ */
+ if (newtime.tv_usec < 0) {
+ newtime.tv_usec += 1E6;
+ newtime.tv_sec -= 1;
+ } else if (newtime.tv_usec >= 1E6) {
+ newtime.tv_usec -= 1E6;
+ newtime.tv_sec += 1;
+ }
+ return newtime;
}
-
static bool
hw_clock_is_utc(const bool utc, const bool local_opt,
- const struct adjtime adjtime) {
+ const struct adjtime adjtime)
+{
bool ret;
if (utc)
@@ -224,7 +223,7 @@ hw_clock_is_utc(const bool utc, const bool local_opt,
else if (local_opt)
ret = FALSE; /* --localtime explicitly given */
else
- /* get info from adjtime file - default is UTC */
+ /* get info from adjtime file - default is UTC */
ret = (adjtime.local_utc != LOCAL);
if (debug)
printf(_("Assuming hardware clock is kept in %s time.\n"),
@@ -232,122 +231,120 @@ hw_clock_is_utc(const bool utc, const bool local_opt,
return ret;
}
+/*
+ * Read the adjustment parameters out of the /etc/adjtime file.
+ *
+ * Return them as the adjtime structure <*adjtime_p>. If there is no
+ * /etc/adjtime file, return defaults. If values are missing from the file,
+ * return defaults for them.
+ *
+ * return value 0 if all OK, !=0 otherwise.
+ */
+static int read_adjtime(struct adjtime *adjtime_p)
+{
+ FILE *adjfile;
+ int rc; /* local return code */
+ struct stat statbuf; /* We don't even use the contents of this. */
+ char line1[81]; /* String: first line of adjtime file */
+ char line2[81]; /* String: second line of adjtime file */
+ char line3[81]; /* String: third line of adjtime file */
+ long timeval;
+
+ rc = stat(adj_file_name, &statbuf);
+ if (rc < 0 && errno == ENOENT) {
+ /* He doesn't have a adjtime file, so we'll use defaults. */
+ adjtime_p->drift_factor = 0;
+ adjtime_p->last_adj_time = 0;
+ adjtime_p->not_adjusted = 0;
+ adjtime_p->last_calib_time = 0;
+ adjtime_p->local_utc = UNKNOWN;
+ adjtime_p->dirty = FALSE; /* don't create a zero adjfile */
+
+ return 0;
+ }
-
-static int
-read_adjtime(struct adjtime *adjtime_p) {
-/*----------------------------------------------------------------------------
- Read the adjustment parameters out of the /etc/adjtime file.
-
- Return them as the adjtime structure <*adjtime_p>.
- If there is no /etc/adjtime file, return defaults.
- If values are missing from the file, return defaults for them.
-
- return value 0 if all OK, !=0 otherwise.
-
------------------------------------------------------------------------------*/
- FILE *adjfile;
- int rc; /* local return code */
- struct stat statbuf; /* We don't even use the contents of this. */
-
- rc = stat(adj_file_name, &statbuf);
- if (rc < 0 && errno == ENOENT) {
- /* He doesn't have a adjtime file, so we'll use defaults. */
- adjtime_p->drift_factor = 0;
- adjtime_p->last_adj_time = 0;
- adjtime_p->not_adjusted = 0;
- adjtime_p->last_calib_time = 0;
- adjtime_p->local_utc = UNKNOWN;
- adjtime_p->dirty = FALSE; /* don't create a zero adjfile */
-
- return 0;
- }
-
- adjfile = fopen(adj_file_name, "r"); /* open file for reading */
- if (adjfile == NULL) {
- outsyserr("cannot open file %s", adj_file_name);
- return EX_OSFILE;
- }
-
- {
- char line1[81]; /* String: first line of adjtime file */
- char line2[81]; /* String: second line of adjtime file */
- char line3[81]; /* String: third line of adjtime file */
- long timeval;
-
- if (!fgets(line1, sizeof(line1), adjfile))
- line1[0] = '\0'; /* In case fgets fails */
- if (!fgets(line2, sizeof(line2), adjfile))
- line2[0] = '\0'; /* In case fgets fails */
- if (!fgets(line3, sizeof(line3), adjfile))
- line3[0] = '\0'; /* In case fgets fails */
-
- fclose(adjfile);
-
- /* Set defaults in case values are missing from file */
- adjtime_p->drift_factor = 0;
- adjtime_p->last_adj_time = 0;
- adjtime_p->not_adjusted = 0;
- adjtime_p->last_calib_time = 0;
- timeval = 0;
-
- sscanf(line1, "%lf %ld %lf",
- &adjtime_p->drift_factor,
- &timeval,
- &adjtime_p->not_adjusted);
- adjtime_p->last_adj_time = timeval;
-
- sscanf(line2, "%ld", &timeval);
- adjtime_p->last_calib_time = timeval;
-
- if (!strcmp(line3, "UTC\n"))
- adjtime_p->local_utc = UTC;
- else if (!strcmp(line3, "LOCAL\n"))
- adjtime_p->local_utc = LOCAL;
- else {
- adjtime_p->local_utc = UNKNOWN;
- if (line3[0]) {
- fprintf(stderr,
- _("%s: Warning: unrecognized third line in adjtime file\n"),
- MYNAME);
- fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n"));
+ adjfile = fopen(adj_file_name, "r"); /* open file for reading */
+ if (adjfile == NULL) {
+ outsyserr("cannot open file %s", adj_file_name);
+ return EX_OSFILE;
}
- }
- }
- adjtime_p->dirty = FALSE;
-
- if (debug) {
- printf(_("Last drift adjustment done at %ld seconds after 1969\n"),
- (long) adjtime_p->last_adj_time);
- printf(_("Last calibration done at %ld seconds after 1969\n"),
- (long) adjtime_p->last_calib_time);
- printf(_("Hardware clock is on %s time\n"),
- (adjtime_p->local_utc == LOCAL) ? _("local") :
- (adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown"));
- }
-
- return 0;
-}
-static int
-synchronize_to_clock_tick(void) {
-/*-----------------------------------------------------------------------------
- Wait until the falling edge of the Hardware Clock's update flag so
- that any time that is read from the clock immediately after we
- return will be exact.
+ if (!fgets(line1, sizeof(line1), adjfile))
+ line1[0] = '\0'; /* In case fgets fails */
+ if (!fgets(line2, sizeof(line2), adjfile))
+ line2[0] = '\0'; /* In case fgets fails */
+ if (!fgets(line3, sizeof(line3), adjfile))
+ line3[0] = '\0'; /* In case fgets fails */
+
+ fclose(adjfile);
+
+ /* Set defaults in case values are missing from file */
+ adjtime_p->drift_factor = 0;
+ adjtime_p->last_adj_time = 0;
+ adjtime_p->not_adjusted = 0;
+ adjtime_p->last_calib_time = 0;
+ timeval = 0;
+
+ sscanf(line1, "%lf %ld %lf",
+ &adjtime_p->drift_factor,
+ &timeval, &adjtime_p->not_adjusted);
+ adjtime_p->last_adj_time = timeval;
+
+ sscanf(line2, "%ld", &timeval);
+ adjtime_p->last_calib_time = timeval;
+
+ if (!strcmp(line3, "UTC\n")) {
+ adjtime_p->local_utc = UTC;
+ } else if (!strcmp(line3, "LOCAL\n")) {
+ adjtime_p->local_utc = LOCAL;
+ } else {
+ adjtime_p->local_utc = UNKNOWN;
+ if (line3[0]) {
+ fprintf(stderr,
+ _("%s: Warning: unrecognized third line in adjtime file\n"),
+ MYNAME);
+ fprintf(stderr,
+ _("(Expected: `UTC' or `LOCAL' or nothing.)\n"));
+ }
+ }
- The clock only has 1 second precision, so it gives the exact time only
- once per second, right on the falling edge of the update flag.
+ adjtime_p->dirty = FALSE;
- We wait (up to one second) either blocked waiting for an rtc device
- or in a CPU spin loop. The former is probably not very accurate.
+ if (debug) {
+ printf(_
+ ("Last drift adjustment done at %ld seconds after 1969\n"),
+ (long)adjtime_p->last_adj_time);
+ printf(_("Last calibration done at %ld seconds after 1969\n"),
+ (long)adjtime_p->last_calib_time);
+ printf(_("Hardware clock is on %s time\n"),
+ (adjtime_p->local_utc ==
+ LOCAL) ? _("local") : (adjtime_p->local_utc ==
+ UTC) ? _("UTC") : _("unknown"));
+ }
+
+ return 0;
+}
- Return 0 if it worked, nonzero if it didn't.
------------------------------------------------------------------------------*/
+/*
+ * Wait until the falling edge of the Hardware Clock's update flag so that
+ * any time that is read from the clock immediately after we return will be
+ * exact.
+ *
+ * The clock only has 1 second precision, so it gives the exact time only
+ * once per second, right on the falling edge of the update flag.
+ *
+ * We wait (up to one second) either blocked waiting for an rtc device or in
+ * a CPU spin loop. The former is probably not very accurate.
+ *
+ * Return 0 if it worked, nonzero if it didn't.
+ */
+static int synchronize_to_clock_tick(void)
+{
int rc;
- if (debug) printf(_("Waiting for clock tick...\n"));
+ if (debug)
+ printf(_("Waiting for clock tick...\n"));
rc = ur->synchronize_to_clock_tick();
@@ -361,254 +358,259 @@ synchronize_to_clock_tick(void) {
return rc;
}
-
-
+/*
+ * Convert a time in broken down format (hours, minutes, etc.) into standard
+ * unix time (seconds into epoch). Return it as *systime_p.
+ *
+ * The broken down time is argument <tm>. This broken down time is either
+ * in local time zone or UTC, depending on value of logical argument
+ * "universal". True means it is in UTC.
+ *
+ * If the argument contains values that do not constitute a valid time, and
+ * mktime() recognizes this, return *valid_p == false and *systime_p
+ * undefined. However, mktime() sometimes goes ahead and computes a
+ * fictional time "as if" the input values were valid, e.g. if they indicate
+ * the 31st day of April, mktime() may compute the time of May 1. In such a
+ * case, we return the same fictional value mktime() does as *systime_p and
+ * return *valid_p == true.
+ */
static void
mktime_tz(struct tm tm, const bool universal,
- bool *valid_p, time_t *systime_p) {
-/*-----------------------------------------------------------------------------
- Convert a time in broken down format (hours, minutes, etc.) into standard
- unix time (seconds into epoch). Return it as *systime_p.
-
- The broken down time is argument <tm>. This broken down time is either in
- local time zone or UTC, depending on value of logical argument "universal".
- True means it is in UTC.
-
- If the argument contains values that do not constitute a valid time,
- and mktime() recognizes this, return *valid_p == false and
- *systime_p undefined. However, mktime() sometimes goes ahead and
- computes a fictional time "as if" the input values were valid,
- e.g. if they indicate the 31st day of April, mktime() may compute
- the time of May 1. In such a case, we return the same fictional
- value mktime() does as *systime_p and return *valid_p == true.
-
------------------------------------------------------------------------------*/
- time_t mktime_result; /* The value returned by our mktime() call */
- char *zone; /* Local time zone name */
-
- /* We use the C library function mktime(), but since it only works on
- local time zone input, we may have to fake it out by temporarily
- changing the local time zone to UTC.
- */
- zone = getenv("TZ"); /* remember original time zone */
- if (universal) {
- /* Set timezone to UTC */
- setenv("TZ", "", TRUE);
- /* Note: tzset() gets called implicitly by the time code, but only the
- first time. When changing the environment variable, better call
- tzset() explicitly.
- */
- tzset();
- }
- mktime_result = mktime(&tm);
- if (mktime_result == -1) {
- /* This apparently (not specified in mktime() documentation) means
- the 'tm' structure does not contain valid values (however, not
- containing valid values does _not_ imply mktime() returns -1).
- */
- *valid_p = FALSE;
- *systime_p = 0;
- if (debug)
- printf(_("Invalid values in hardware clock: "
- "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"),
- tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- } else {
- *valid_p = TRUE;
- *systime_p = mktime_result;
- if (debug)
- printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
- "%ld seconds since 1969\n"),
- tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec, (long) *systime_p);
- }
- /* now put back the original zone. */
- if (zone) setenv("TZ", zone, TRUE);
- else unsetenv("TZ");
- tzset();
+ bool * valid_p, time_t * systime_p)
+{
+ time_t mktime_result; /* The value returned by our mktime() call */
+ char *zone; /* Local time zone name */
+
+ /*
+ * We use the C library function mktime(), but since it only works
+ * on local time zone input, we may have to fake it out by
+ * temporarily changing the local time zone to UTC.
+ */
+ zone = getenv("TZ"); /* remember original time zone */
+ if (universal) {
+ /* Set timezone to UTC */
+ setenv("TZ", "", TRUE);
+ /*
+ * Note: tzset() gets called implicitly by the time code,
+ * but only the first time. When changing the environment
+ * variable, better call tzset() explicitly.
+ */
+ tzset();
+ }
+ mktime_result = mktime(&tm);
+ if (mktime_result == -1) {
+ /*
+ * This apparently (not specified in mktime() documentation)
+ * means the 'tm' structure does not contain valid values
+ * (however, not containing valid values does _not_ imply
+ * mktime() returns -1).
+ */
+ *valid_p = FALSE;
+ *systime_p = 0;
+ if (debug)
+ printf(_("Invalid values in hardware clock: "
+ "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"),
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ } else {
+ *valid_p = TRUE;
+ *systime_p = mktime_result;
+ if (debug)
+ printf(_
+ ("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
+ "%ld seconds since 1969\n"), tm.tm_year + 1900,
+ tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min,
+ tm.tm_sec, (long)*systime_p);
+ }
+ /* now put back the original zone. */
+ if (zone)
+ setenv("TZ", zone, TRUE);
+ else
+ unsetenv("TZ");
+ tzset();
}
-
+/*
+ * Read the hardware clock and return the current time via <tm> argument.
+ *
+ * Use the method indicated by <method> argument to access the hardware
+ * clock.
+ */
static int
-read_hardware_clock(const bool universal, bool *valid_p, time_t *systime_p){
-/*----------------------------------------------------------------------------
- Read the hardware clock and return the current time via <tm> argument.
-
- Use the method indicated by <method> argument to access the hardware clock.
------------------------------------------------------------------------------*/
- struct tm tm;
- int err;
+read_hardware_clock(const bool universal, bool * valid_p, time_t * systime_p)
+{
+ struct tm tm;
+ int err;
- err = ur->read_hardware_clock(&tm);
- if (err)
- return err;
+ err = ur->read_hardware_clock(&tm);
+ if (err)
+ return err;
- if (badyear)
- read_date_from_file(&tm);
+ if (badyear)
+ read_date_from_file(&tm);
- if (debug)
- printf (_("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"),
- tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- mktime_tz(tm, universal, valid_p, systime_p);
+ if (debug)
+ printf(_
+ ("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"),
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec);
+ mktime_tz(tm, universal, valid_p, systime_p);
- return 0;
+ return 0;
}
-
+/*
+ * Set the Hardware Clock to the time <newtime>, in local time zone or UTC,
+ * according to <universal>.
+ */
static void
set_hardware_clock(const time_t newtime,
- const bool universal,
- const bool testing) {
-/*----------------------------------------------------------------------------
- Set the Hardware Clock to the time <newtime>, in local time zone or UTC,
- according to <universal>.
-----------------------------------------------------------------------------*/
- struct tm new_broken_time;
- /* Time to which we will set Hardware Clock, in broken down format, in
- the time zone of caller's choice
- */
-
- if (universal)
- new_broken_time = *gmtime(&newtime);
- else
- new_broken_time = *localtime(&newtime);
-
- if (debug)
- printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d "
- "= %ld seconds since 1969\n"),
- new_broken_time.tm_hour, new_broken_time.tm_min,
- new_broken_time.tm_sec, (long) newtime);
-
- if (testing)
- printf(_("Clock not changed - testing only.\n"));
- else {
- if (badyear) {
- /*
- * Write the real year to a file, then write a fake year
- * between 1995 and 1998 to the RTC. This way, Award BIOS boots
- * on 29 Feb 2000 thinking that it's 29 Feb 1996.
- */
- write_date_to_file (&new_broken_time);
- new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3);
- }
- ur->set_hardware_clock(&new_broken_time);
- }
-}
+ const bool universal, const bool testing)
+{
+ struct tm new_broken_time;
+ /*
+ * Time to which we will set Hardware Clock, in broken down format,
+ * in the time zone of caller's choice
+ */
+
+ if (universal)
+ new_broken_time = *gmtime(&newtime);
+ else
+ new_broken_time = *localtime(&newtime);
+ if (debug)
+ printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d "
+ "= %ld seconds since 1969\n"),
+ new_broken_time.tm_hour, new_broken_time.tm_min,
+ new_broken_time.tm_sec, (long)newtime);
+ if (testing)
+ printf(_("Clock not changed - testing only.\n"));
+ else {
+ if (badyear) {
+ /*
+ * Write the real year to a file, then write a fake
+ * year between 1995 and 1998 to the RTC. This way,
+ * Award BIOS boots on 29 Feb 2000 thinking that
+ * it's 29 Feb 1996.
+ */
+ write_date_to_file(&new_broken_time);
+ new_broken_time.tm_year =
+ 95 + ((new_broken_time.tm_year + 1) & 3);
+ }
+ ur->set_hardware_clock(&new_broken_time);
+ }
+}
+/*
+ * Set the Hardware Clock to the time "sethwtime", in local time zone or
+ * UTC, according to "universal".
+ *
+ * Wait for a fraction of a second so that "sethwtime" is the value of the
+ * Hardware Clock as of system time "refsystime", which is in the past. For
+ * example, if "sethwtime" is 14:03:05 and "refsystime" is 12:10:04.5 and
+ * the current system time is 12:10:06.0: Wait .5 seconds (to make exactly 2
+ * seconds since "refsystime") and then set the Hardware Clock to 14:03:07,
+ * thus getting a precise and retroactive setting of the clock.
+ *
+ * (Don't be confused by the fact that the system clock and the Hardware
+ * Clock differ by two hours in the above example. That's just to remind you
+ * that there are two independent time scales here).
+ *
+ * This function ought to be able to accept set times as fractional times.
+ * Idea for future enhancement.
+ */
static void
set_hardware_clock_exact(const time_t sethwtime,
- const struct timeval refsystime,
- const bool universal,
- const bool testing) {
-/*----------------------------------------------------------------------------
- Set the Hardware Clock to the time "sethwtime", in local time zone or UTC,
- according to "universal".
-
- Wait for a fraction of a second so that "sethwtime" is the value of
- the Hardware Clock as of system time "refsystime", which is in the past.
- For example, if "sethwtime" is 14:03:05 and "refsystime" is 12:10:04.5
- and the current system time is 12:10:06.0: Wait .5 seconds (to make
- exactly 2 seconds since "refsystime") and then set the Hardware Clock
- to 14:03:07, thus getting a precise and retroactive setting of the clock.
-
- (Don't be confused by the fact that the system clock and the Hardware
- Clock differ by two hours in the above example. That's just to remind
- you that there are two independent time scales here).
-
- This function ought to be able to accept set times as fractional times.
- Idea for future enhancement.
------------------------------------------------------------------------------*/
-
- time_t newhwtime;
- struct timeval beginsystime, nowsystime;
- double tdiff;
+ const struct timeval refsystime,
+ const bool universal, const bool testing)
+{
+ time_t newhwtime;
+ struct timeval beginsystime, nowsystime;
+ double tdiff;
time_resync:
- gettimeofday(&beginsystime, NULL);
- tdiff = time_diff(beginsystime, refsystime);
- newhwtime = sethwtime + (int) (tdiff + 0.5);
- if (debug)
- printf(_("Time elapsed since reference time has been %.6f seconds.\n"
- "Delaying further to reach the new time.\n"), tdiff);
-
- /*
- * Now delay some more until Hardware Clock time newhwtime arrives. The 0.5 s
- * is because the Hardware Clock always sets to your set time plus 500 ms
- * (because it is designed to update to the next second precisely 500 ms
- * after you finish the setting).
- */
- do {
- gettimeofday(&nowsystime, NULL);
- tdiff = time_diff(nowsystime, beginsystime);
- if (tdiff < 0)
- goto time_resync; /* probably backward time reset */
- if (tdiff > 0.1)
- goto time_resync; /* probably forward time reset */
- beginsystime = nowsystime;
- tdiff = time_diff(nowsystime, refsystime);
- } while (newhwtime == sethwtime + (int) (tdiff + 0.5));
-
- set_hardware_clock(newhwtime, universal, testing);
+ gettimeofday(&beginsystime, NULL);
+ tdiff = time_diff(beginsystime, refsystime);
+ newhwtime = sethwtime + (int)(tdiff + 0.5);
+ if (debug)
+ printf(_
+ ("Time elapsed since reference time has been %.6f seconds.\n"
+ "Delaying further to reach the new time.\n"), tdiff);
+
+ /*
+ * Now delay some more until Hardware Clock time newhwtime arrives.
+ * The 0.5 s is because the Hardware Clock always sets to your set
+ * time plus 500 ms (because it is designed to update to the next
+ * second precisely 500 ms after you finish the setting).
+ */
+ do {
+ gettimeofday(&nowsystime, NULL);
+ tdiff = time_diff(nowsystime, beginsystime);
+ if (tdiff < 0)
+ goto time_resync; /* probably backward time reset */
+ if (tdiff > 0.1)
+ goto time_resync; /* probably forward time reset */
+ beginsystime = nowsystime;
+ tdiff = time_diff(nowsystime, refsystime);
+ } while (newhwtime == sethwtime + (int)(tdiff + 0.5));
+
+ set_hardware_clock(newhwtime, universal, testing);
}
-
-
+/*
+ * Put the time "systime" on standard output in display format. Except if
+ * hclock_valid == false, just tell standard output that we don't know what
+ * time it is.
+ *
+ * Include in the output the adjustment "sync_duration".
+ */
static void
display_time(const bool hclock_valid, const time_t systime,
- const double sync_duration) {
-/*----------------------------------------------------------------------------
- Put the time "systime" on standard output in display format.
- Except if hclock_valid == false, just tell standard output that we don't
- know what time it is.
-
- Include in the output the adjustment "sync_duration".
------------------------------------------------------------------------------*/
- if (!hclock_valid)
- fprintf(stderr, _("The Hardware Clock registers contain values that are "
- "either invalid (e.g. 50th day of month) or beyond the range "
- "we can handle (e.g. Year 2095).\n"));
- else {
- struct tm *lt;
- char *format = "%c";
- char ctime_now[200];
-
- lt = localtime(&systime);
- strftime(ctime_now, sizeof(ctime_now), format, lt);
- printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration));
- }
-}
-
-
-
-static int
-interpret_date_string(const char *date_opt, time_t * const time_p) {
-/*----------------------------------------------------------------------------
- Interpret the value of the --date option, which is something like
- "13:05:01". In fact, it can be any of the myriad ASCII strings that specify
- a time which the "date" program can understand. The date option value in
- question is our "dateopt" argument.
-
- The specified time is in the local time zone.
-
- Our output, "*time_p", is a seconds-into-epoch time.
+ const double sync_duration)
+{
+ if (!hclock_valid)
+ fprintf(stderr,
+ _
+ ("The Hardware Clock registers contain values that are "
+ "either invalid (e.g. 50th day of month) or beyond the range "
+ "we can handle (e.g. Year 2095).\n"));
+ else {
+ struct tm *lt;
+ char *format = "%c";
+ char ctime_now[200];
- We use the "date" program to interpret the date string. "date" must be
- runnable by issuing the command "date" to the /bin/sh shell. That means
- in must be in the current PATH.
+ lt = localtime(&systime);
+ strftime(ctime_now, sizeof(ctime_now), format, lt);
+ printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration));
+ }
+}
- If anything goes wrong (and many things can), we return return code
- 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p
- is valid.
-----------------------------------------------------------------------------*/
+/*
+ * Interpret the value of the --date option, which is something like
+ * "13:05:01". In fact, it can be any of the myriad ASCII strings that
+ * specify a time which the "date" program can understand. The date option
+ * value in question is our "dateopt" argument.
+ *
+ * The specified time is in the local time zone.
+ *
+ * Our output, "*time_p", is a seconds-into-epoch time.
+ *
+ * We use the "date" program to interpret the date string. "date" must be
+ * runnable by issuing the command "date" to the /bin/sh shell. That means
+ * in must be in the current PATH.
+ *
+ * If anything goes wrong (and many things can), we return return code 10
+ * and arbitrary *time_p. Otherwise, return code is 0 and *time_p is valid.
+ */
+static int interpret_date_string(const char *date_opt, time_t * const time_p)
+{
FILE *date_child_fp;
char date_resp[100];
- const char magic[]="seconds-into-epoch=";
+ const char magic[] = "seconds-into-epoch=";
char date_command[100];
- int retcode; /* our eventual return code */
- int rc; /* local return code */
+ int retcode; /* our eventual return code */
+ int rc; /* local return code */
if (date_opt == NULL) {
fprintf(stderr, _("No --date option specified.\n"));
@@ -624,8 +626,9 @@ interpret_date_string(const char *date_opt, time_t * const time_p) {
/* Quotes in date_opt would ruin the date command we construct. */
if (strchr(date_opt, '"') != NULL) {
fprintf(stderr,
- _("The value of the --date option is not a valid date.\n"
- "In particular, it contains quotation marks.\n"));
+ _
+ ("The value of the --date option is not a valid date.\n"
+ "In particular, it contains quotation marks.\n"));
return 12;
}
@@ -642,10 +645,10 @@ interpret_date_string(const char *date_opt, time_t * const time_p) {
}
if (!fgets(date_resp, sizeof(date_resp), date_child_fp))
- date_resp[0] = '\0'; /* in case fgets fails */
+ date_resp[0] = '\0'; /* in case fgets fails */
if (debug)
printf(_("response from date command = %s\n"), date_resp);
- if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) {
+ if (strncmp(date_resp, magic, sizeof(magic) - 1) != 0) {
fprintf(stderr, _("The date command issued by %s returned "
"unexpected results.\n"
"The command was:\n %s\n"
@@ -654,7 +657,7 @@ interpret_date_string(const char *date_opt, time_t * const time_p) {
retcode = 8;
} else {
long seconds_since_epoch;
- rc = sscanf(date_resp + sizeof(magic)-1, "%ld",
+ rc = sscanf(date_resp + sizeof(magic) - 1, "%ld",
&seconds_since_epoch);
if (rc < 1) {
fprintf(stderr,
@@ -671,7 +674,7 @@ interpret_date_string(const char *date_opt, time_t * const time_p) {
if (debug)
printf(_("date string %s equates to "
"%ld seconds since 1969.\n"),
- date_opt, (long) *time_p);
+ date_opt, (long)*time_p);
}
}
pclose(date_child_fp);
@@ -679,173 +682,181 @@ interpret_date_string(const char *date_opt, time_t * const time_p) {
return retcode;
}
-
-
+/*
+ * Set the System Clock to time 'newtime'.
+ *
+ * Also set the kernel time zone value to the value indicated by the TZ
+ * environment variable and/or /usr/lib/zoneinfo/, interpreted as tzset()
+ * would interpret them.
+ *
+ * EXCEPT: if hclock_valid is false, just issue an error message saying
+ * there is no valid time in the Hardware Clock to which to set the system
+ * time.
+ *
+ * If 'testing' is true, don't actually update anything -- just say we would
+ * have.
+ */
static int
set_system_clock(const bool hclock_valid, const time_t newtime,
- const bool testing) {
-/*----------------------------------------------------------------------------
- Set the System Clock to time 'newtime'.
-
- Also set the kernel time zone value to the value indicated by the
- TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as
- tzset() would interpret them.
-
- EXCEPT: if hclock_valid is false, just issue an error message
- saying there is no valid time in the Hardware Clock to which to set
- the system time.
-
- If 'testing' is true, don't actually update anything -- just say we
- would have.
------------------------------------------------------------------------------*/
- int retcode;
-
- if (!hclock_valid) {
- fprintf(stderr, _("The Hardware Clock does not contain a valid time, so "
- "we cannot set the System Time from it.\n"));
- retcode = 1;
- } else {
- struct timeval tv;
- struct tm *broken;
- int minuteswest;
- int rc;
-
- tv.tv_sec = newtime;
- tv.tv_usec = 0;
-
- broken = localtime(&newtime);
+ const bool testing)
+{
+ int retcode;
+
+ if (!hclock_valid) {
+ fprintf(stderr,
+ _
+ ("The Hardware Clock does not contain a valid time, so "
+ "we cannot set the System Time from it.\n"));
+ retcode = 1;
+ } else {
+ struct timeval tv;
+ struct tm *broken;
+ int minuteswest;
+ int rc;
+
+ tv.tv_sec = newtime;
+ tv.tv_usec = 0;
+
+ broken = localtime(&newtime);
#ifdef HAVE_TM_GMTOFF
- minuteswest = -broken->tm_gmtoff/60; /* GNU extension */
+ minuteswest = -broken->tm_gmtoff / 60; /* GNU extension */
#else
- minuteswest = timezone/60;
- if (broken->tm_isdst)
- minuteswest -= 60;
+ minuteswest = timezone / 60;
+ if (broken->tm_isdst)
+ minuteswest -= 60;
#endif
- if (debug) {
- printf(_("Calling settimeofday:\n"));
- printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
- (long) tv.tv_sec, (long) tv.tv_usec);
- printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
- }
- if (testing) {
- printf(_("Not setting system clock because running in test mode.\n"));
- retcode = 0;
- } else {
- const struct timezone tz = { minuteswest, 0 };
-
- rc = settimeofday(&tv, &tz);
- if (rc) {
- if (errno == EPERM) {
- fprintf(stderr,
- _("Must be superuser to set system clock.\n"));
- retcode = EX_NOPERM;
- } else {
- outsyserr(_("settimeofday() failed"));
- retcode = 1;
- }
- } else retcode = 0;
- }
- }
- return retcode;
+ if (debug) {
+ printf(_("Calling settimeofday:\n"));
+ printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
+ (long)tv.tv_sec, (long)tv.tv_usec);
+ printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
+ }
+ if (testing) {
+ printf(_
+ ("Not setting system clock because running in test mode.\n"));
+ retcode = 0;
+ } else {
+ const struct timezone tz = { minuteswest, 0 };
+
+ rc = settimeofday(&tv, &tz);
+ if (rc) {
+ if (errno == EPERM) {
+ fprintf(stderr,
+ _
+ ("Must be superuser to set system clock.\n"));
+ retcode = EX_NOPERM;
+ } else {
+ outsyserr(_("settimeofday() failed"));
+ retcode = 1;
+ }
+ } else
+ retcode = 0;
+ }
+ }
+ return retcode;
}
+/*
+ * Reset the System Clock from local time to UTC, based on its current value
+ * and the timezone unless universal is TRUE.
+ *
+ * Also set the kernel time zone value to the value indicated by the TZ
+ * environment variable and/or /usr/lib/zoneinfo/, interpreted as tzset()
+ * would interpret them.
+ *
+ * If 'testing' is true, don't actually update anything -- just say we would
+ * have.
+ */
+static int set_system_clock_timezone(const bool universal, const bool testing)
+{
+ int retcode;
+ struct timeval tv;
+ struct tm *broken;
+ int minuteswest;
+ int rc;
+
+ gettimeofday(&tv, NULL);
+ if (debug) {
+ struct tm broken_time;
+ char ctime_now[200];
+
+ broken_time = *gmtime(&tv.tv_sec);
+ strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S",
+ &broken_time);
+ printf(_("Current system time: %ld = %s\n"), (long)tv.tv_sec,
+ ctime_now);
+ }
-static int
-set_system_clock_timezone(const bool universal, const bool testing) {
-/*----------------------------------------------------------------------------
- Reset the System Clock from local time to UTC, based on its current
- value and the timezone unless universal is TRUE.
-
- Also set the kernel time zone value to the value indicated by the
- TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as
- tzset() would interpret them.
-
- If 'testing' is true, don't actually update anything -- just say we
- would have.
------------------------------------------------------------------------------*/
- int retcode;
- struct timeval tv;
- struct tm *broken;
- int minuteswest;
- int rc;
-
- gettimeofday(&tv, NULL);
- if (debug) {
- struct tm broken_time;
- char ctime_now[200];
-
- broken_time = *gmtime(&tv.tv_sec);
- strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", &broken_time);
- printf(_("Current system time: %ld = %s\n"), (long) tv.tv_sec, ctime_now);
- }
-
- broken = localtime(&tv.tv_sec);
+ broken = localtime(&tv.tv_sec);
#ifdef HAVE_TM_GMTOFF
- minuteswest = -broken->tm_gmtoff/60; /* GNU extension */
+ minuteswest = -broken->tm_gmtoff / 60; /* GNU extension */
#else
- minuteswest = timezone/60;
- if (broken->tm_isdst)
- minuteswest -= 60;
+ minuteswest = timezone / 60;
+ if (broken->tm_isdst)
+ minuteswest -= 60;
#endif
- gettimeofday(&tv, NULL);
- if (!universal)
- tv.tv_sec += minuteswest * 60;
-
- if (debug) {
- struct tm broken_time;
- char ctime_now[200];
-
- broken_time = *gmtime(&tv.tv_sec);
- strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S", &broken_time);
-
- printf(_("Calling settimeofday:\n"));
- printf(_("\tUTC: %s\n"), ctime_now);
- printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
- (long) tv.tv_sec, (long) tv.tv_usec);
- printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
- }
- if (testing) {
- printf(_("Not setting system clock because running in test mode.\n"));
- retcode = 0;
- } else {
- const struct timezone tz = { minuteswest, 0 };
-
- rc = settimeofday(&tv, &tz);
- if (rc) {
- if (errno == EPERM) {
- fprintf(stderr,
- _("Must be superuser to set system clock.\n"));
- retcode = EX_NOPERM;
- } else {
- outsyserr(_("settimeofday() failed"));
- retcode = 1;
- }
- } else retcode = 0;
- }
- return retcode;
-}
+ gettimeofday(&tv, NULL);
+ if (!universal)
+ tv.tv_sec += minuteswest * 60;
+ if (debug) {
+ struct tm broken_time;
+ char ctime_now[200];
+
+ broken_time = *gmtime(&tv.tv_sec);
+ strftime(ctime_now, sizeof(ctime_now), "%Y/%m/%d %H:%M:%S",
+ &broken_time);
+
+ printf(_("Calling settimeofday:\n"));
+ printf(_("\tUTC: %s\n"), ctime_now);
+ printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
+ (long)tv.tv_sec, (long)tv.tv_usec);
+ printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
+ }
+ if (testing) {
+ printf(_
+ ("Not setting system clock because running in test mode.\n"));
+ retcode = 0;
+ } else {
+ const struct timezone tz = { minuteswest, 0 };
+ rc = settimeofday(&tv, &tz);
+ if (rc) {
+ if (errno == EPERM) {
+ fprintf(stderr,
+ _
+ ("Must be superuser to set system clock.\n"));
+ retcode = EX_NOPERM;
+ } else {
+ outsyserr(_("settimeofday() failed"));
+ retcode = 1;
+ }
+ } else
+ retcode = 0;
+ }
+ return retcode;
+}
+
+/*
+ * Update the drift factor in <*adjtime_p> to reflect the fact that the
+ * Hardware Clock was calibrated to <nowtime> and before that was set to
+ * <hclocktime>.
+ *
+ * We record in the adjtime file the time at which we last calibrated the
+ * clock so we can compute the drift rate each time we calibrate.
+ *
+ * EXCEPT: if <hclock_valid> is false, assume Hardware Clock was not set
+ * before to anything meaningful and regular adjustments have not been done,
+ * so don't adjust the drift factor.
+ */
static void
adjust_drift_factor(struct adjtime *adjtime_p,
- const time_t nowtime,
- const bool hclock_valid,
- const time_t hclocktime,
- const double sync_delay) {
-/*------------------------------------------------------------------------
- Update the drift factor in <*adjtime_p> to reflect the fact that the
- Hardware Clock was calibrated to <nowtime> and before that was set
- to <hclocktime>.
-
- We record in the adjtime file the time at which we last calibrated
- the clock so we can compute the drift rate each time we calibrate.
-
- EXCEPT: if <hclock_valid> is false, assume Hardware Clock was not set
- before to anything meaningful and regular adjustments have not been
- done, so don't adjust the drift factor.
- ------------------------------------------------------------------------*/
+ const time_t nowtime,
+ const bool hclock_valid,
+ const time_t hclocktime, const double sync_delay)
+{
if (!hclock_valid) {
if (debug)
printf(_("Not adjusting drift factor because the "
@@ -867,9 +878,9 @@ adjust_drift_factor(struct adjtime *adjtime_p,
* At adjustment time we adjust the hardware clock according
* to the contents of /etc/adjtime.
*
- * At calibration time we set the hardware clock and
- * update /etc/adjtime, that is, for each calibration
- * (except the first) we also do an adjustment.
+ * At calibration time we set the hardware clock and update
+ * /etc/adjtime, that is, for each calibration (except the
+ * first) we also do an adjustment.
*
* We are now at calibration time.
*
@@ -887,21 +898,21 @@ adjust_drift_factor(struct adjtime *adjtime_p,
/* Days since last adjustment (in hardware clock time) */
adj_days = (double)(hclocktime - adjtime_p->last_adj_time)
- / sec_per_day;
+ / sec_per_day;
/* Expected drift (sec) since last adjustment */
exp_drift = adj_days * adjtime_p->drift_factor
- + adjtime_p->not_adjusted;
+ + adjtime_p->not_adjusted;
/* Uncorrected drift (sec) since last calibration */
unc_drift = (double)(nowtime - hclocktime)
- + sync_delay - exp_drift;
+ + sync_delay - exp_drift;
/* Days since last calibration (in hardware clock time) */
cal_days = ((double)(adjtime_p->last_adj_time
- - adjtime_p->last_calib_time)
+ - adjtime_p->last_calib_time)
+ adjtime_p->not_adjusted)
- / (sec_per_day * atime_per_htime) + adj_days;
+ / (sec_per_day * atime_per_htime) + adj_days;
/* Amount to add to previous drift factor */
factor_adjust = unc_drift / cal_days;
@@ -912,9 +923,8 @@ adjust_drift_factor(struct adjtime *adjtime_p,
"%f seconds/day.\n"
"Adjusting drift factor by %f seconds/day\n"),
unc_drift,
- (int) (nowtime - adjtime_p->last_calib_time),
- adjtime_p->drift_factor,
- factor_adjust);
+ (int)(nowtime - adjtime_p->last_calib_time),
+ adjtime_p->drift_factor, factor_adjust);
adjtime_p->drift_factor += factor_adjust;
}
@@ -927,383 +937,403 @@ adjust_drift_factor(struct adjtime *adjtime_p,
adjtime_p->dirty = TRUE;
}
-
-
+/*
+ * Do the drift adjustment calculation.
+ *
+ * The way we have to set the clock, we need the adjustment in two parts:
+ *
+ * 1) an integer number of seconds (return as *adjustment_p)
+ * 2) a positive fraction of a second (less than 1) (return as *retro_p)
+ *
+ * The sum of these two values is the adjustment needed. Positive means to
+ * advance the clock or insert seconds. Negative means to retard the clock
+ * or remove seconds.
+ */
static void
calculate_adjustment(const double factor,
- const time_t last_time,
- const double not_adjusted,
- const time_t systime,
- int *adjustment_p,
- double *retro_p) {
-/*----------------------------------------------------------------------------
- Do the drift adjustment calculation.
-
- The way we have to set the clock, we need the adjustment in two parts:
-
- 1) an integer number of seconds (return as *adjustment_p)
-
- 2) a positive fraction of a second (less than 1) (return as *retro_p)
-
- The sum of these two values is the adjustment needed. Positive means to
- advance the clock or insert seconds. Negative means to retard the clock
- or remove seconds.
-----------------------------------------------------------------------------*/
- double exact_adjustment;
-
- exact_adjustment = ((double) (systime - last_time)) * factor / (24 * 60 * 60)
- + not_adjusted;
- *adjustment_p = FLOOR(exact_adjustment);
-
- *retro_p = exact_adjustment - (double) *adjustment_p;
- if (debug) {
- printf (_("Time since last adjustment is %d seconds\n"),
- (int) (systime - last_time));
- printf (_("Need to insert %d seconds and refer time back "
- "%.6f seconds ago\n"),
- *adjustment_p, *retro_p);
- }
-}
-
+ const time_t last_time,
+ const double not_adjusted,
+ const time_t systime, int *adjustment_p, double *retro_p)
+{
+ double exact_adjustment;
+ exact_adjustment =
+ ((double)(systime - last_time)) * factor / (24 * 60 * 60)
+ + not_adjusted;
+ *adjustment_p = FLOOR(exact_adjustment);
-static void
-save_adjtime(const struct adjtime adjtime, const bool testing) {
-/*-----------------------------------------------------------------------------
- Write the contents of the <adjtime> structure to its disk file.
-
- But if the contents are clean (unchanged since read from disk), don't
- bother.
------------------------------------------------------------------------------*/
- char newfile[412]; /* Stuff to write to disk file */
-
- if (adjtime.dirty) {
- /* snprintf is not always available, but this is safe
- as long as libc does not use more than 100 positions for %ld or %f */
- sprintf(newfile, "%f %ld %f\n%ld\n%s\n",
- adjtime.drift_factor,
- (long) adjtime.last_adj_time,
- adjtime.not_adjusted,
- (long) adjtime.last_calib_time,
- (adjtime.local_utc == UTC) ? "UTC" : "LOCAL");
-
- if (testing) {
- printf(_("Not updating adjtime file because of testing mode.\n"));
- printf(_("Would have written the following to %s:\n%s"),
- adj_file_name, newfile);
- } else {
- FILE *adjfile;
- int err = 0;
-
- adjfile = fopen(adj_file_name, "w");
- if (adjfile == NULL) {
- outsyserr(_("Could not open file with the clock adjustment parameters "
- "in it (%s) for writing"), adj_file_name);
- err = 1;
- } else {
- if (fputs(newfile, adjfile) < 0) {
- outsyserr(_("Could not update file with the clock adjustment "
- "parameters (%s) in it"), adj_file_name);
- err = 1;
- }
- if (fclose(adjfile) < 0) {
- outsyserr(_("Could not update file with the clock adjustment "
- "parameters (%s) in it"), adj_file_name);
- err = 1;
- }
- }
- if (err)
- fprintf(stderr, _("Drift adjustment parameters not updated.\n"));
- }
- }
+ *retro_p = exact_adjustment - (double)*adjustment_p;
+ if (debug) {
+ printf(_("Time since last adjustment is %d seconds\n"),
+ (int)(systime - last_time));
+ printf(_("Need to insert %d seconds and refer time back "
+ "%.6f seconds ago\n"), *adjustment_p, *retro_p);
+ }
}
+/*
+ * Write the contents of the <adjtime> structure to its disk file.
+ *
+ * But if the contents are clean (unchanged since read from disk), don't
+ * bother.
+ */
+static void save_adjtime(const struct adjtime adjtime, const bool testing)
+{
+ char newfile[412]; /* Stuff to write to disk file */
+ if (adjtime.dirty) {
+ /*
+ * snprintf is not always available, but this is safe as
+ * long as libc does not use more than 100 positions for %ld
+ * or %f
+ */
+ sprintf(newfile, "%f %ld %f\n%ld\n%s\n",
+ adjtime.drift_factor,
+ (long)adjtime.last_adj_time,
+ adjtime.not_adjusted,
+ (long)adjtime.last_calib_time,
+ (adjtime.local_utc == UTC) ? "UTC" : "LOCAL");
+
+ if (testing) {
+ printf(_
+ ("Not updating adjtime file because of testing mode.\n"));
+ printf(_("Would have written the following to %s:\n%s"),
+ adj_file_name, newfile);
+ } else {
+ FILE *adjfile;
+ int err = 0;
+
+ adjfile = fopen(adj_file_name, "w");
+ if (adjfile == NULL) {
+ outsyserr(_
+ ("Could not open file with the clock adjustment parameters "
+ "in it (%s) for writing"),
+ adj_file_name);
+ err = 1;
+ } else {
+ if (fputs(newfile, adjfile) < 0) {
+ outsyserr(_
+ ("Could not update file with the clock adjustment "
+ "parameters (%s) in it"),
+ adj_file_name);
+ err = 1;
+ }
+ if (fclose(adjfile) < 0) {
+ outsyserr(_
+ ("Could not update file with the clock adjustment "
+ "parameters (%s) in it"),
+ adj_file_name);
+ err = 1;
+ }
+ }
+ if (err)
+ fprintf(stderr,
+ _
+ ("Drift adjustment parameters not updated.\n"));
+ }
+ }
+}
+/*
+ * Do the adjustment requested, by 1) setting the Hardware Clock (if
+ * necessary), and 2) updating the last-adjusted time in the adjtime
+ * structure.
+ *
+ * Do not update anything if the Hardware Clock does not currently present a
+ * valid time.
+ *
+ * Arguments <factor> and <last_time> are current values from the adjtime
+ * file.
+ *
+ * <hclock_valid> means the Hardware Clock contains a valid time, and that
+ * time is <hclocktime>.
+ *
+ * <read_time> is the current system time (to be precise, it is the system
+ * time at the time <hclocktime> was read, which due to computational delay
+ * could be a short time ago).
+ *
+ * <universal>: the Hardware Clock is kept in UTC.
+ *
+ * <testing>: We are running in test mode (no updating of clock).
+ *
+ * We do not bother to update the clock if the adjustment would be less than
+ * one second. This is to avoid cumulative error and needless CPU hogging
+ * (remember we use an infinite loop for some timing) if the user runs us
+ * frequently.
+ */
static void
do_adjustment(struct adjtime *adjtime_p,
- const bool hclock_valid, const time_t hclocktime,
- const struct timeval read_time,
- const bool universal, const bool testing) {
-/*---------------------------------------------------------------------------
- Do the adjustment requested, by 1) setting the Hardware Clock (if
- necessary), and 2) updating the last-adjusted time in the adjtime
- structure.
-
- Do not update anything if the Hardware Clock does not currently present
- a valid time.
-
- arguments <factor> and <last_time> are current values from the adjtime
- file.
-
- <hclock_valid> means the Hardware Clock contains a valid time, and that
- time is <hclocktime>.
-
- <read_time> is the current system time (to be precise, it is the system
- time at the time <hclocktime> was read, which due to computational delay
- could be a short time ago).
-
- <universal>: the Hardware Clock is kept in UTC.
-
- <testing>: We are running in test mode (no updating of clock).
-
- We do not bother to update the clock if the adjustment would be less than
- one second. This is to avoid cumulative error and needless CPU hogging
- (remember we use an infinite loop for some timing) if the user runs us
- frequently.
-
-----------------------------------------------------------------------------*/
- if (!hclock_valid) {
- fprintf(stderr, _("The Hardware Clock does not contain a valid time, "
- "so we cannot adjust it.\n"));
- adjtime_p->last_calib_time = 0; /* calibration startover is required */
- adjtime_p->last_adj_time = 0;
- adjtime_p->not_adjusted = 0;
- adjtime_p->dirty = TRUE;
- } else if (adjtime_p->last_adj_time == 0) {
- if (debug)
- printf(_("Not setting clock because last adjustment time is zero, "
- "so history is bad."));
- } else {
- int adjustment;
- /* Number of seconds we must insert in the Hardware Clock */
- double retro;
- /* Fraction of second we have to remove from clock after inserting
- <adjustment> whole seconds.
- */
- calculate_adjustment(adjtime_p->drift_factor,
- adjtime_p->last_adj_time,
- adjtime_p->not_adjusted,
- hclocktime,
- &adjustment, &retro);
- if (adjustment > 0 || adjustment < -1) {
- set_hardware_clock_exact(hclocktime + adjustment,
- time_inc(read_time, -retro),
- universal, testing);
- adjtime_p->last_adj_time = hclocktime + adjustment;
- adjtime_p->not_adjusted = 0;
- adjtime_p->dirty = TRUE;
- } else
- if (debug)
- printf(_("Needed adjustment is less than one second, "
- "so not setting clock.\n"));
- }
+ const bool hclock_valid, const time_t hclocktime,
+ const struct timeval read_time,
+ const bool universal, const bool testing)
+{
+ if (!hclock_valid) {
+ fprintf(stderr,
+ _("The Hardware Clock does not contain a valid time, "
+ "so we cannot adjust it.\n"));
+ adjtime_p->last_calib_time = 0; /* calibration startover is required */
+ adjtime_p->last_adj_time = 0;
+ adjtime_p->not_adjusted = 0;
+ adjtime_p->dirty = TRUE;
+ } else if (adjtime_p->last_adj_time == 0) {
+ if (debug)
+ printf(_
+ ("Not setting clock because last adjustment time is zero, "
+ "so history is bad."));
+ } else {
+ int adjustment;
+ /* Number of seconds we must insert in the Hardware Clock */
+ double retro;
+ /*
+ * Fraction of second we have to remove from clock after
+ * inserting <adjustment> whole seconds.
+ */
+ calculate_adjustment(adjtime_p->drift_factor,
+ adjtime_p->last_adj_time,
+ adjtime_p->not_adjusted,
+ hclocktime, &adjustment, &retro);
+ if (adjustment > 0 || adjustment < -1) {
+ set_hardware_clock_exact(hclocktime + adjustment,
+ time_inc(read_time, -retro),
+ universal, testing);
+ adjtime_p->last_adj_time = hclocktime + adjustment;
+ adjtime_p->not_adjusted = 0;
+ adjtime_p->dirty = TRUE;
+ } else if (debug)
+ printf(_("Needed adjustment is less than one second, "
+ "so not setting clock.\n"));
+ }
}
+static void determine_clock_access_method(const bool user_requests_ISA)
+{
+ ur = NULL;
-
-static void
-determine_clock_access_method(const bool user_requests_ISA) {
-
- ur = NULL;
-
- if (user_requests_ISA)
- ur = probe_for_cmos_clock();
+ if (user_requests_ISA)
+ ur = probe_for_cmos_clock();
#ifdef __linux__
- if (!ur)
- ur = probe_for_rtc_clock();
+ if (!ur)
+ ur = probe_for_rtc_clock();
#endif
- if (!ur)
- ur = probe_for_kd_clock();
+ if (!ur)
+ ur = probe_for_kd_clock();
- if (!ur && !user_requests_ISA)
- ur = probe_for_cmos_clock();
+ if (!ur && !user_requests_ISA)
+ ur = probe_for_cmos_clock();
- if (debug) {
- if (ur)
- printf(_("Using %s.\n"), ur->interface_name);
- else
- printf(_("No usable clock interface found.\n"));
- }
+ if (debug) {
+ if (ur)
+ printf(_("Using %s.\n"), ur->interface_name);
+ else
+ printf(_("No usable clock interface found.\n"));
+ }
}
+/*
+ * Do all the normal work of hwclock - read, set clock, etc.
+ *
+ * Issue output to stdout and error message to stderr where appropriate.
+ *
+ * Return rc == 0 if everything went OK, rc != 0 if not.
+ */
static int
manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
- const bool set, const time_t set_time,
- const bool hctosys, const bool systohc, const bool systz,
- const struct timeval startup_time,
- const bool utc, const bool local_opt,
- const bool testing, const bool predict) {
-/*---------------------------------------------------------------------------
- Do all the normal work of hwclock - read, set clock, etc.
-
- Issue output to stdout and error message to stderr where appropriate.
-
- Return rc == 0 if everything went OK, rc != 0 if not.
-----------------------------------------------------------------------------*/
- struct adjtime adjtime;
- /* Contents of the adjtime file, or what they should be. */
- int rc; /* local return code */
- bool no_auth; /* User lacks necessary authorization to access the clock */
-
- if (!systz && !predict) {
- no_auth = ur->get_permissions();
- if (no_auth)
- return EX_NOPERM;
- }
-
- if (!noadjfile && (adjust || set || systohc || (!utc && !local_opt) || predict)) {
- rc = read_adjtime(&adjtime);
- if (rc)
- return rc;
- } else {
- /* A little trick to avoid reading the file if we don't have to */
- adjtime.dirty = FALSE;
- rc = 0;
- }
-
- {
- const bool universal = hw_clock_is_utc(utc, local_opt, adjtime);
-
- if ((set || systohc || adjust) &&
- (adjtime.local_utc == UTC) != universal) {
- adjtime.local_utc = universal ? UTC : LOCAL;
- adjtime.dirty = TRUE;
- }
-
- {
- struct timeval read_time;
- /* The time at which we read the Hardware Clock */
-
- bool hclock_valid = FALSE;
- /* The Hardware Clock gives us a valid time, or at least something
- close enough to fool mktime().
- */
-
- time_t hclocktime = 0;
- /* The time the hardware clock had just after we
- synchronized to its next clock tick when we started up.
- Defined only if hclock_valid is true.
- */
+ const bool set, const time_t set_time,
+ const bool hctosys, const bool systohc, const bool systz,
+ const struct timeval startup_time,
+ const bool utc, const bool local_opt,
+ const bool testing, const bool predict)
+{
+ /* Contents of the adjtime file, or what they should be. */
+ struct adjtime adjtime;
+ bool universal;
+ /* Set if user lacks necessary authorization to access the clock */
+ bool no_auth;
+ /* The time at which we read the Hardware Clock */
+ struct timeval read_time;
+ /*
+ * The Hardware Clock gives us a valid time, or at
+ * least something close enough to fool mktime().
+ */
+ bool hclock_valid = FALSE;
+ /*
+ * The time the hardware clock had just after we
+ * synchronized to its next clock tick when we
+ * started up. Defined only if hclock_valid is true.
+ */
+ time_t hclocktime = 0;
+ /* local return code */
+ int rc;
+
+ if (!systz && !predict) {
+ no_auth = ur->get_permissions();
+ if (no_auth)
+ return EX_NOPERM;
+ }
+
+ if (!noadjfile
+ && (adjust || set || systohc || (!utc && !local_opt) || predict)) {
+ rc = read_adjtime(&adjtime);
+ if (rc)
+ return rc;
+ } else {
+ /* A little trick to avoid reading the file if we don't have to */
+ adjtime.dirty = FALSE;
+ rc = 0;
+ }
+
+ universal = hw_clock_is_utc(utc, local_opt, adjtime);
+
+ if ((set || systohc || adjust) &&
+ (adjtime.local_utc == UTC) != universal) {
+ adjtime.local_utc = universal ? UTC : LOCAL;
+ adjtime.dirty = TRUE;
+ }
if (show || adjust || hctosys || (!noadjfile && !systz && !predict)) {
- /* data from HW-clock are required */
- rc = synchronize_to_clock_tick();
-
- /* 2 = synchronization timeout. We don't error out if the user is
- attempting to set the RTC - the RTC could be functioning but
- contain invalid time data so we still want to allow a user to set
- the RTC time.
- */
-
- if (rc && rc != 2 && !set && !systohc)
- return EX_IOERR;
- gettimeofday(&read_time, NULL);
-
- /* If we can't synchronize to a clock tick, we likely can't read
- from the RTC so don't bother reading it again. */
- if (!rc) {
- rc = read_hardware_clock(universal, &hclock_valid, &hclocktime);
- if (rc && !set && !systohc)
- return EX_IOERR;
- }
+ /* data from HW-clock are required */
+ rc = synchronize_to_clock_tick();
+
+ /*
+ * 2 = synchronization timeout. We don't
+ * error out if the user is attempting to
+ * set the RTC - the RTC could be
+ * functioning but contain invalid time data
+ * so we still want to allow a user to set
+ * the RTC time.
+ */
+ if (rc && rc != 2 && !set && !systohc)
+ return EX_IOERR;
+ gettimeofday(&read_time, NULL);
+
+ /*
+ * If we can't synchronize to a clock tick,
+ * we likely can't read from the RTC so
+ * don't bother reading it again.
+ */
+ if (!rc) {
+ rc = read_hardware_clock(universal,
+ &hclock_valid, &hclocktime);
+ if (rc && !set && !systohc)
+ return EX_IOERR;
+ }
}
- if (show) {
- display_time(hclock_valid, hclocktime,
- time_diff(read_time, startup_time));
- } else if (set) {
- set_hardware_clock_exact(set_time, startup_time,
- universal, testing);
- if (!noadjfile)
- adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime,
- time_diff(read_time, startup_time));
- } else if (adjust) {
- do_adjustment(&adjtime, hclock_valid, hclocktime,
- read_time, universal, testing);
- } else if (systohc) {
- struct timeval nowtime, reftime;
- /* We can only set_hardware_clock_exact to a whole seconds
- time, so we set it with reference to the most recent
- whole seconds time.
- */
- gettimeofday(&nowtime, NULL);
- reftime.tv_sec = nowtime.tv_sec;
- reftime.tv_usec = 0;
-
- set_hardware_clock_exact((time_t) reftime.tv_sec, reftime,
- universal, testing);
- if (!noadjfile)
- adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid,
- hclocktime, (double) read_time.tv_usec / 1E6);
- } else if (hctosys) {
- rc = set_system_clock(hclock_valid, hclocktime, testing);
- if (rc) {
- printf(_("Unable to set system clock.\n"));
- return rc;
- }
+ if (show) {
+ display_time(hclock_valid, hclocktime,
+ time_diff(read_time, startup_time));
+ } else if (set) {
+ set_hardware_clock_exact(set_time, startup_time,
+ universal, testing);
+ if (!noadjfile)
+ adjust_drift_factor(&adjtime, set_time,
+ hclock_valid,
+ hclocktime,
+ time_diff(read_time, startup_time));
+ } else if (adjust) {
+ do_adjustment(&adjtime, hclock_valid,
+ hclocktime, read_time, universal, testing);
+ } else if (systohc) {
+ struct timeval nowtime, reftime;
+ /*
+ * We can only set_hardware_clock_exact to a
+ * whole seconds time, so we set it with
+ * reference to the most recent whole
+ * seconds time.
+ */
+ gettimeofday(&nowtime, NULL);
+ reftime.tv_sec = nowtime.tv_sec;
+ reftime.tv_usec = 0;
+ set_hardware_clock_exact((time_t)
+ reftime.tv_sec,
+ reftime, universal, testing);
+ if (!noadjfile)
+ adjust_drift_factor(&adjtime, (time_t)
+ reftime.tv_sec,
+ hclock_valid, hclocktime, (double)
+ read_time.tv_usec / 1E6);
+ } else if (hctosys) {
+ rc = set_system_clock(hclock_valid, hclocktime, testing);
+ if (rc) {
+ printf(_("Unable to set system clock.\n"));
+ return rc;
+ }
} else if (systz) {
- rc = set_system_clock_timezone(universal, testing);
- if (rc) {
- printf(_("Unable to set system clock.\n"));
- return rc;
- }
- } else if (predict) {
- int adjustment;
- double retro;
-
- calculate_adjustment(adjtime.drift_factor,
- adjtime.last_adj_time,
- adjtime.not_adjusted,
- set_time,
- &adjustment, &retro);
- if (debug) {
- printf(_("At %ld seconds after 1969, RTC is predicted to read %ld seconds after 1969.\n"),
- set_time, set_time + adjustment);
- }
- display_time(TRUE, set_time + adjustment, -retro);
- }
- if (!noadjfile)
- save_adjtime(adjtime, testing);
- }
- }
- return 0;
+ rc = set_system_clock_timezone(universal, testing);
+ if (rc) {
+ printf(_("Unable to set system clock.\n"));
+ return rc;
+ }
+ } else if (predict) {
+ int adjustment;
+ double retro;
+
+ calculate_adjustment(adjtime.drift_factor,
+ adjtime.last_adj_time,
+ adjtime.not_adjusted,
+ set_time, &adjustment, &retro);
+ if (debug) {
+ printf(_
+ ("At %ld seconds after 1969, RTC is predicted to read %ld seconds after 1969.\n"),
+ set_time, set_time + adjustment);
+ }
+ display_time(TRUE, set_time + adjustment, -retro);
+ }
+ if (!noadjfile)
+ save_adjtime(adjtime, testing);
+ return 0;
}
-
+/*
+ * Get or set the Hardware Clock epoch value in the kernel, as appropriate.
+ * <getepoch>, <setepoch>, and <epoch> are hwclock invocation options.
+ *
+ * <epoch> == -1 if the user did not specify an "epoch" option.
+ */
#ifdef __linux__
static void
manipulate_epoch(const bool getepoch, const bool setepoch,
- const int epoch_opt, const bool testing) {
-/*----------------------------------------------------------------------------
- Get or set the Hardware Clock epoch value in the kernel, as appropriate.
- <getepoch>, <setepoch>, and <epoch> are hwclock invocation options.
-
- <epoch> == -1 if the user did not specify an "epoch" option.
-
------------------------------------------------------------------------------*/
- /*
- Maintenance note: This should work on non-Alpha machines, but the
- evidence today (98.03.04) indicates that the kernel only keeps the
- epoch value on Alphas. If that is ever fixed, this function should be
- changed.
- */
-
+ const int epoch_opt, const bool testing)
+{
+ /*
+ * Maintenance note: This should work on non-Alpha machines, but the
+ * evidence today (98.03.04) indicates that the kernel only keeps
+ * the epoch value on Alphas. If that is ever fixed, this function
+ * should be changed.
+ */
#ifndef __alpha__
- fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock "
- "only on an Alpha machine.\nThis copy of hwclock was built for "
- "a machine other than Alpha\n(and thus is presumably not running "
- "on an Alpha now). No action taken.\n"));
+ fprintf(stderr,
+ _("The kernel keeps an epoch value for the Hardware Clock "
+ "only on an Alpha machine.\nThis copy of hwclock was built for "
+ "a machine other than Alpha\n(and thus is presumably not running "
+ "on an Alpha now). No action taken.\n"));
#else
- if (getepoch) {
- unsigned long epoch;
-
- if (get_epoch_rtc(&epoch, 0))
- fprintf(stderr, _("Unable to get the epoch value from the kernel.\n"));
- else
- printf(_("Kernel is assuming an epoch value of %lu\n"), epoch);
- } else if (setepoch) {
- if (epoch_opt == -1)
- fprintf(stderr, _("To set the epoch value, you must use the 'epoch' "
- "option to tell to what value to set it.\n"));
- else if (testing)
- printf(_("Not setting the epoch to %d - testing only.\n"),
- epoch_opt);
- else if (set_epoch_rtc(epoch_opt))
- printf(_("Unable to set the epoch value in the kernel.\n"));
- }
+ if (getepoch) {
+ unsigned long epoch;
+
+ if (get_epoch_rtc(&epoch, 0))
+ fprintf(stderr,
+ _
+ ("Unable to get the epoch value from the kernel.\n"));
+ else
+ printf(_("Kernel is assuming an epoch value of %lu\n"),
+ epoch);
+ } else if (setepoch) {
+ if (epoch_opt == -1)
+ fprintf(stderr,
+ _
+ ("To set the epoch value, you must use the 'epoch' "
+ "option to tell to what value to set it.\n"));
+ else if (testing)
+ printf(_
+ ("Not setting the epoch to %d - testing only.\n"),
+ epoch_opt);
+ else if (set_epoch_rtc(epoch_opt))
+ printf(_
+ ("Unable to set the epoch value in the kernel.\n"));
+ }
#endif
}
#endif
@@ -1314,123 +1344,118 @@ manipulate_epoch(const bool getepoch, const bool setepoch,
#define RTC_DEV "/dev/rtc"
#endif
-static void
-out_version(void) {
+static void out_version(void)
+{
printf(_("%s from %s\n"), MYNAME, PACKAGE_STRING);
}
/*
- usage - Output (error and) usage information
-
- This function is called both directly from main to show usage
- information and as fatal function from shhopt if some argument is
- not understood. In case of normal usage info FMT should be NULL.
- In that case the info is printed to stdout. If FMT is given
- usage will act like fprintf( stderr, fmt, ... ), show a usage
- information and terminate the program afterwards.
-*/
-static void
-usage( const char *fmt, ... ) {
- FILE *usageto;
- va_list ap;
-
- usageto = fmt ? stderr : stdout;
-
- fprintf( usageto, _(
- "hwclock - query and set the hardware clock (RTC)\n\n"
- "Usage: hwclock [function] [options...]\n\n"
- "Functions:\n"
- " -h | --help show this help\n"
- " -r | --show read hardware clock and print result\n"
- " --set set the rtc to the time given with --date\n"
- " -s | --hctosys set the system time from the hardware clock\n"
- " -w | --systohc set the hardware clock to the current system time\n"
- " --systz set the system time based on the current timezone\n"
- " --adjust adjust the rtc to account for systematic drift since\n"
- " the clock was last set or adjusted\n"
+ * usage - Output (error and) usage information
+ *
+ * This function is called both directly from main to show usage information
+ * and as fatal function from shhopt if some argument is not understood. In
+ * case of normal usage info FMT should be NULL. In that case the info is
+ * printed to stdout. If FMT is given usage will act like fprintf( stderr,
+ * fmt, ... ), show a usage information and terminate the program
+ * afterwards.
+ */
+static void usage(const char *fmt, ...)
+{
+ FILE *usageto;
+ va_list ap;
+
+ usageto = fmt ? stderr : stdout;
+
+ fprintf(usageto,
+ _("hwclock - query and set the hardware clock (RTC)\n\n"
+ "Usage: hwclock [function] [options...]\n\n" "Functions:\n"
+ " -h | --help show this help\n"
+ " -r | --show read hardware clock and print result\n"
+ " --set set the rtc to the time given with --date\n"
+ " -s | --hctosys set the system time from the hardware clock\n"
+ " -w | --systohc set the hardware clock to the current system time\n"
+ " --systz set the system time based on the current timezone\n"
+ " --adjust adjust the rtc to account for systematic drift since\n"
+ " the clock was last set or adjusted\n"
#ifdef __linux__
- " --getepoch print out the kernel's hardware clock epoch value\n"
- " --setepoch set the kernel's hardware clock epoch value to the \n"
- " value given with --epoch\n"
+ " --getepoch print out the kernel's hardware clock epoch value\n"
+ " --setepoch set the kernel's hardware clock epoch value to the \n"
+ " value given with --epoch\n"
#endif
- " --predict predict rtc reading at time given with --date\n"
- " -v | --version print out the version of hwclock to stdout\n"
- "\nOptions: \n"
- " -u | --utc the hardware clock is kept in UTC\n"
- " --localtime the hardware clock is kept in local time\n"
+ " --predict predict rtc reading at time given with --date\n"
+ " -v | --version print out the version of hwclock to stdout\n"
+ "\nOptions: \n"
+ " -u | --utc the hardware clock is kept in UTC\n"
+ " --localtime the hardware clock is kept in local time\n"
#ifdef __linux__
- " -f | --rtc=path special /dev/... file to use instead of default\n"
+ " -f | --rtc=path special /dev/... file to use instead of default\n"
#endif
- " --directisa access the ISA bus directly instead of %s\n"
- " --badyear ignore rtc's year because the bios is broken\n"
- " --date specifies the time to which to set the hardware clock\n"
- " --epoch=year specifies the year which is the beginning of the \n"
- " hardware clock's epoch value\n"
- " --noadjfile do not access /etc/adjtime. Requires the use of\n"
- " either --utc or --localtime\n"
- " --adjfile=path specifies the path to the adjust file (default is\n"
- " /etc/adjtime)\n"
- " --test do everything except actually updating the hardware\n"
- " clock or anything else\n"
- " -D | --debug debug mode\n"
- "\n"
- ),RTC_DEV);
+ " --directisa access the ISA bus directly instead of %s\n"
+ " --badyear ignore rtc's year because the bios is broken\n"
+ " --date specifies the time to which to set the hardware clock\n"
+ " --epoch=year specifies the year which is the beginning of the \n"
+ " hardware clock's epoch value\n"
+ " --noadjfile do not access /etc/adjtime. Requires the use of\n"
+ " either --utc or --localtime\n"
+ " --adjfile=path specifies the path to the adjust file (default is\n"
+ " /etc/adjtime)\n"
+ " --test do everything except actually updating the hardware\n"
+ " clock or anything else\n"
+ " -D | --debug debug mode\n" "\n"), RTC_DEV);
#ifdef __alpha__
- fprintf(usageto, _(
- " -J|--jensen, -A|--arc, -S|--srm, -F|--funky-toy\n"
- " tell hwclock the type of alpha you have (see hwclock(8))\n"
- "\n"
- ) );
+ fprintf(usageto, _(" -J|--jensen, -A|--arc, -S|--srm, -F|--funky-toy\n"
+ " tell hwclock the type of alpha you have (see hwclock(8))\n"
+ "\n"));
#endif
- fflush(stdout);
- if (fmt) {
- usageto = stderr;
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- }
+ fflush(stdout);
+ if (fmt) {
+ usageto = stderr;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
- hwclock_exit(fmt ? EX_USAGE : 0);
+ hwclock_exit(fmt ? EX_USAGE : 0);
}
static const struct option longopts[] = {
- { "adjust", 0, 0, 'a' },
- { "help", 0, 0, 'h' },
- { "show", 0, 0, 'r' },
- { "hctosys", 0, 0, 's' },
- { "utc", 0, 0, 'u' },
- { "version", 0, 0, 'v' },
- { "systohc", 0, 0, 'w' },
- { "debug", 0, 0, 'D' },
+ {"adjust", 0, 0, 'a'},
+ {"help", 0, 0, 'h'},
+ {"show", 0, 0, 'r'},
+ {"hctosys", 0, 0, 's'},
+ {"utc", 0, 0, 'u'},
+ {"version", 0, 0, 'v'},
+ {"systohc", 0, 0, 'w'},
+ {"debug", 0, 0, 'D'},
#ifdef __alpha__
- { "ARC", 0, 0, 'A' },
- { "arc", 0, 0, 'A' },
- { "Jensen", 0, 0, 'J' },
- { "jensen", 0, 0, 'J' },
- { "SRM", 0, 0, 'S' },
- { "srm", 0, 0, 'S' },
- { "funky-toy", 0, 0, 'F'},
+ {"ARC", 0, 0, 'A'},
+ {"arc", 0, 0, 'A'},
+ {"Jensen", 0, 0, 'J'},
+ {"jensen", 0, 0, 'J'},
+ {"SRM", 0, 0, 'S'},
+ {"srm", 0, 0, 'S'},
+ {"funky-toy", 0, 0, 'F'},
#endif
- { "set", 0, 0, 128 },
+ {"set", 0, 0, 128},
#ifdef __linux__
- { "getepoch", 0, 0, 129 },
- { "setepoch", 0, 0, 130 },
+ {"getepoch", 0, 0, 129},
+ {"setepoch", 0, 0, 130},
#endif
- { "noadjfile", 0, 0, 131 },
- { "localtime", 0, 0, 132 },
- { "badyear", 0, 0, 133 },
- { "directisa", 0, 0, 134 },
- { "test", 0, 0, 135 },
- { "date", 1, 0, 136 },
- { "epoch", 1, 0, 137 },
+ {"noadjfile", 0, 0, 131},
+ {"localtime", 0, 0, 132},
+ {"badyear", 0, 0, 133},
+ {"directisa", 0, 0, 134},
+ {"test", 0, 0, 135},
+ {"date", 1, 0, 136},
+ {"epoch", 1, 0, 137},
#ifdef __linux__
- { "rtc", 1, 0, 'f' },
+ {"rtc", 1, 0, 'f'},
#endif
- { "adjfile", 1, 0, 138 },
- { "systz", 0, 0, 139 },
- { "predict-hc", 0, 0, 140 },
- { NULL, 0, 0, 0 }
+ {"adjfile", 1, 0, 138},
+ {"systz", 0, 0, 139},
+ {"predict-hc", 0, 0, 140},
+ {NULL, 0, 0, 0}
};
/*
@@ -1442,20 +1467,22 @@ static const struct option longopts[] = {
* 0: OK (or not)
* 1: failure
*/
-int
-main(int argc, char **argv) {
-
+int main(int argc, char **argv)
+{
struct timeval startup_time;
- /* The time we started up, in seconds into the epoch, including
- fractions. */
- time_t set_time = 0; /* Time to which user said to set Hardware Clock */
+ /*
+ * The time we started up, in seconds into the epoch, including
+ * fractions.
+ */
+ time_t set_time = 0; /* Time to which user said to set Hardware Clock */
- bool permitted; /* User is permitted to do the function */
+ bool permitted; /* User is permitted to do the function */
int rc, c;
/* Variables set by various options; show may also be set later */
/* The options debug, badyear and epoch_option are global */
- bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch, predict;
+ bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch,
+ predict;
bool utc, testing, local_opt, noadjfile, directisa;
char *date_opt;
#ifdef __alpha__
@@ -1468,32 +1495,37 @@ main(int argc, char **argv) {
hwaudit_fd = audit_open();
if (hwaudit_fd < 0 && !(errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)) {
- /* You get these error codes only when the kernel doesn't have
- * audit compiled in. */
+ /*
+ * You get these error codes only when the kernel doesn't
+ * have audit compiled in.
+ */
fprintf(stderr, _("%s: Unable to connect to audit system\n"),
- MYNAME);
+ MYNAME);
return EX_NOPERM;
}
#endif
setlocale(LC_ALL, "");
#ifdef LC_NUMERIC
- /* We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid
- LC_NUMERIC since it gives problems when we write to /etc/adjtime.
- - gqueri@mail.dotcom.fr */
+ /*
+ * We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid
+ * LC_NUMERIC since it gives problems when we write to /etc/adjtime.
+ * - gqueri@mail.dotcom.fr
+ */
setlocale(LC_NUMERIC, "C");
#endif
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
/* Set option defaults */
- show = set = systohc = hctosys = systz = adjust = noadjfile = predict = FALSE;
+ show = set = systohc = hctosys = systz = adjust = noadjfile = predict =
+ FALSE;
getepoch = setepoch = utc = local_opt = testing = debug = FALSE;
#ifdef __alpha__
ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE;
#endif
date_opt = NULL;
- while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL))
+ while ((c = getopt_long(argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL))
!= -1) {
switch (c) {
case 'D':
@@ -1543,7 +1575,7 @@ main(int argc, char **argv) {
noadjfile = TRUE;
break;
case 132:
- local_opt = TRUE; /* --localtime */
+ local_opt = TRUE; /* --localtime */
break;
case 133:
badyear = TRUE;
@@ -1552,33 +1584,33 @@ main(int argc, char **argv) {
directisa = TRUE;
break;
case 135:
- testing = TRUE; /* --test */
+ testing = TRUE; /* --test */
break;
case 136:
- date_opt = optarg; /* --date */
+ date_opt = optarg; /* --date */
break;
case 137:
epoch_option = atoi(optarg); /* --epoch */
break;
case 138:
- adj_file_name = optarg; /* --adjfile */
+ adj_file_name = optarg; /* --adjfile */
break;
case 139:
- systz = TRUE; /* --systz */
+ systz = TRUE; /* --systz */
break;
case 140:
- predict = TRUE; /* --predict-hc */
+ predict = TRUE; /* --predict-hc */
break;
#ifdef __linux__
case 'f':
- rtc_dev_name = optarg; /* --rtc */
+ rtc_dev_name = optarg; /* --rtc */
break;
#endif
- case 'v': /* --version */
+ case 'v': /* --version */
case 'V':
out_version();
return 0;
- case 'h': /* --help */
+ case 'h': /* --help */
case '?':
default:
usage(NULL);
@@ -1591,19 +1623,18 @@ main(int argc, char **argv) {
#ifdef HAVE_LIBAUDIT
if (testing != TRUE) {
if (adjust == TRUE || hctosys == TRUE || systohc == TRUE ||
- set == TRUE || setepoch == TRUE) {
+ set == TRUE || setepoch == TRUE) {
hwaudit_on = TRUE;
}
}
#endif
if (argc > 0) {
usage(_("%s takes no non-option arguments. "
- "You supplied %d.\n"),
- MYNAME, argc);
+ "You supplied %d.\n"), MYNAME, argc);
}
if (show + set + systohc + hctosys + systz + adjust + getepoch
- + setepoch + predict > 1){
+ + setepoch + predict > 1) {
fprintf(stderr, _("You have specified multiple functions.\n"
"You can only perform one function "
"at a time.\n"));
@@ -1638,7 +1669,6 @@ main(int argc, char **argv) {
"either --utc or --localtime\n"), MYNAME);
hwclock_exit(EX_USAGE);
}
-
#ifdef __alpha__
set_cmos_epoch(ARCconsole, SRM);
set_cmos_access(Jensen, funky_toy);
@@ -1656,8 +1686,7 @@ main(int argc, char **argv) {
if (!(show | set | systohc | hctosys | systz | adjust | getepoch
| setepoch | predict))
- show = 1; /* default to show */
-
+ show = 1; /* default to show */
if (getuid() == 0)
permitted = TRUE;
@@ -1710,15 +1739,15 @@ main(int argc, char **argv) {
}
rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
- hctosys, systohc, systz, startup_time, utc,
- local_opt, testing, predict);
+ hctosys, systohc, systz, startup_time, utc,
+ local_opt, testing, predict);
hwclock_exit(rc);
- return rc; /* Not reached */
+ return rc; /* Not reached */
}
/* A single routine for greater uniformity */
-void
-outsyserr(char *msg, ...) {
+void outsyserr(char *msg, ...)
+{
va_list args;
int errsv = errno;
@@ -1726,144 +1755,130 @@ outsyserr(char *msg, ...) {
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
- fprintf(stderr, ", errno=%d: %s.\n",
- errsv, strerror(errsv));
+ fprintf(stderr, ", errno=%d: %s.\n", errsv, strerror(errsv));
}
-
#ifdef HAVE_LIBAUDIT
-void
-hwaudit_exit(int status)
+void hwaudit_exit(int status)
{
if (hwaudit_on) {
audit_log_user_message(hwaudit_fd, AUDIT_USYS_CONFIG,
- "changing system time", NULL, NULL, NULL, status ? 0 : 1);
+ "changing system time", NULL, NULL, NULL,
+ status ? 0 : 1);
close(hwaudit_fd);
}
exit(status);
}
#endif
-/****************************************************************************
-
- History of this program:
-
- 98.08.12 BJH Version 2.4
-
- Don't use century byte from Hardware Clock. Add comments telling why.
-
-
- 98.06.20 BJH Version 2.3.
-
- Make --hctosys set the kernel timezone from TZ environment variable
- and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com).
-
- 98.03.05 BJH. Version 2.2.
-
- Add --getepoch and --setepoch.
-
- Fix some word length things so it works on Alpha.
-
- Make it work when /dev/rtc doesn't have the interrupt functions.
- In this case, busywait for the top of a second instead of blocking and
- waiting for the update complete interrupt.
-
- Fix a bunch of bugs too numerous to mention.
-
- 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte
- 50) of the ISA Hardware Clock when using direct ISA I/O. Problem
- discovered by job (jei@iclnl.icl.nl).
-
- Use the rtc clock access method in preference to the KDGHWCLK method.
- Problem discovered by Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>.
-
- November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt
- (janl@math.uio.no) to make it compile on linux 1.2 machines as well
- as more recent versions of the kernel. Introduced the NO_CLOCK
- access method and wrote feature test code to detect absense of rtc
- headers.
-
-
-**************************************************************************
- Maintenance notes
-
- To compile this, you must use GNU compiler optimization (-O option)
- in order to make the "extern inline" functions from asm/io.h (inb(),
- etc.) compile. If you don't optimize, which means the compiler
- will generate no inline functions, the references to these functions
- in this program will be compiled as external references. Since you
- probably won't be linking with any functions by these names, you will
- have unresolved external references when you link.
-
- The program is designed to run setuid superuser, since we need to be
- able to do direct I/O. (More to the point: we need permission to
- execute the iopl() system call). (However, if you use one of the
- methods other than direct ISA I/O to access the clock, no setuid is
- required).
-
- Here's some info on how we must deal with the time that elapses while
- this program runs: There are two major delays as we run:
-
- 1) Waiting up to 1 second for a transition of the Hardware Clock so
- we are synchronized to the Hardware Clock.
-
- 2) Running the "date" program to interpret the value of our --date
- option.
-
- Reading the /etc/adjtime file is the next biggest source of delay and
- uncertainty.
-
- The user wants to know what time it was at the moment he invoked us,
- not some arbitrary time later. And in setting the clock, he is
- giving us the time at the moment we are invoked, so if we set the
- clock some time later, we have to add some time to that.
-
- So we check the system time as soon as we start up, then run "date"
- and do file I/O if necessary, then wait to synchronize with a
- Hardware Clock edge, then check the system time again to see how
- much time we spent. We immediately read the clock then and (if
- appropriate) report that time, and additionally, the delay we measured.
-
- If we're setting the clock to a time given by the user, we wait some
- more so that the total delay is an integral number of seconds, then
- set the Hardware Clock to the time the user requested plus that
- integral number of seconds. N.B. The Hardware Clock can only be set
- in integral seconds.
-
- If we're setting the clock to the system clock value, we wait for
- the system clock to reach the top of a second, and then set the
- Hardware Clock to the system clock's value.
-
- Here's an interesting point about setting the Hardware Clock: On my
- machine, when you set it, it sets to that precise time. But one can
- imagine another clock whose update oscillator marches on a steady one
- second period, so updating the clock between any two oscillator ticks
- is the same as updating it right at the earlier tick. To avoid any
- complications that might cause, we set the clock as soon as possible
- after an oscillator tick.
-
-
- About synchronizing to the Hardware Clock when reading the time: The
- precision of the Hardware Clock counters themselves is one second.
- You can't read the counters and find out that is 12:01:02.5. But if
- you consider the location in time of the counter's ticks as part of
- its value, then its precision is as infinite as time is continuous!
- What I'm saying is this: To find out the _exact_ time in the
- hardware clock, we wait until the next clock tick (the next time the
- second counter changes) and measure how long we had to wait. We
- then read the value of the clock counters and subtract the wait time
- and we know precisely what time it was when we set out to query the
- time.
-
- hwclock uses this method, and considers the Hardware Clock to have
- infinite precision.
-
-
- Enhancements needed:
-
- - When waiting for whole second boundary in set_hardware_clock_exact,
- fail if we miss the goal by more than .1 second, as could happen if
- we get pre-empted (by the kernel dispatcher).
-
-****************************************************************************/
-
+/*
+ * History of this program:
+ *
+ * 98.08.12 BJH Version 2.4
+ *
+ * Don't use century byte from Hardware Clock. Add comments telling why.
+ *
+ * 98.06.20 BJH Version 2.3.
+ *
+ * Make --hctosys set the kernel timezone from TZ environment variable
+ * and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com).
+ *
+ * 98.03.05 BJH. Version 2.2.
+ *
+ * Add --getepoch and --setepoch.
+ *
+ * Fix some word length things so it works on Alpha.
+ *
+ * Make it work when /dev/rtc doesn't have the interrupt functions. In this
+ * case, busywait for the top of a second instead of blocking and waiting
+ * for the update complete interrupt.
+ *
+ * Fix a bunch of bugs too numerous to mention.
+ *
+ * 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte 50) of
+ * the ISA Hardware Clock when using direct ISA I/O. Problem discovered by
+ * job (jei@iclnl.icl.nl).
+ *
+ * Use the rtc clock access method in preference to the KDGHWCLK method.
+ * Problem discovered by Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>.
+ *
+ * November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt
+ * (janl@math.uio.no) to make it compile on linux 1.2 machines as well as
+ * more recent versions of the kernel. Introduced the NO_CLOCK access method
+ * and wrote feature test code to detect absense of rtc headers.
+ *
+ ***************************************************************************
+ * Maintenance notes
+ *
+ * To compile this, you must use GNU compiler optimization (-O option) in
+ * order to make the "extern inline" functions from asm/io.h (inb(), etc.)
+ * compile. If you don't optimize, which means the compiler will generate no
+ * inline functions, the references to these functions in this program will
+ * be compiled as external references. Since you probably won't be linking
+ * with any functions by these names, you will have unresolved external
+ * references when you link.
+ *
+ * The program is designed to run setuid superuser, since we need to be able
+ * to do direct I/O. (More to the point: we need permission to execute the
+ * iopl() system call). (However, if you use one of the methods other than
+ * direct ISA I/O to access the clock, no setuid is required).
+ *
+ * Here's some info on how we must deal with the time that elapses while
+ * this program runs: There are two major delays as we run:
+ *
+ * 1) Waiting up to 1 second for a transition of the Hardware Clock so
+ * we are synchronized to the Hardware Clock.
+ * 2) Running the "date" program to interpret the value of our --date
+ * option.
+ *
+ * Reading the /etc/adjtime file is the next biggest source of delay and
+ * uncertainty.
+ *
+ * The user wants to know what time it was at the moment he invoked us, not
+ * some arbitrary time later. And in setting the clock, he is giving us the
+ * time at the moment we are invoked, so if we set the clock some time
+ * later, we have to add some time to that.
+ *
+ * So we check the system time as soon as we start up, then run "date" and
+ * do file I/O if necessary, then wait to synchronize with a Hardware Clock
+ * edge, then check the system time again to see how much time we spent. We
+ * immediately read the clock then and (if appropriate) report that time,
+ * and additionally, the delay we measured.
+ *
+ * If we're setting the clock to a time given by the user, we wait some more
+ * so that the total delay is an integral number of seconds, then set the
+ * Hardware Clock to the time the user requested plus that integral number
+ * of seconds. N.B. The Hardware Clock can only be set in integral seconds.
+ *
+ * If we're setting the clock to the system clock value, we wait for the
+ * system clock to reach the top of a second, and then set the Hardware
+ * Clock to the system clock's value.
+ *
+ * Here's an interesting point about setting the Hardware Clock: On my
+ * machine, when you set it, it sets to that precise time. But one can
+ * imagine another clock whose update oscillator marches on a steady one
+ * second period, so updating the clock between any two oscillator ticks is
+ * the same as updating it right at the earlier tick. To avoid any
+ * complications that might cause, we set the clock as soon as possible
+ * after an oscillator tick.
+ *
+ * About synchronizing to the Hardware Clock when reading the time: The
+ * precision of the Hardware Clock counters themselves is one second. You
+ * can't read the counters and find out that is 12:01:02.5. But if you
+ * consider the location in time of the counter's ticks as part of its
+ * value, then its precision is as infinite as time is continuous! What I'm
+ * saying is this: To find out the _exact_ time in the hardware clock, we
+ * wait until the next clock tick (the next time the second counter changes)
+ * and measure how long we had to wait. We then read the value of the clock
+ * counters and subtract the wait time and we know precisely what time it
+ * was when we set out to query the time.
+ *
+ * hwclock uses this method, and considers the Hardware Clock to have
+ * infinite precision.
+ *
+ * TODO: Enhancements needed:
+ *
+ * - When waiting for whole second boundary in set_hardware_clock_exact,
+ * fail if we miss the goal by more than .1 second, as could happen if we
+ * get pre-empted (by the kernel dispatcher).
+ */
diff --git a/hwclock/kd.c b/hwclock/kd.c
index 66ff579bb..f4957ac64 100644
--- a/hwclock/kd.c
+++ b/hwclock/kd.c
@@ -1,19 +1,21 @@
-/* kd.c - KDGHWCLK stuff, possibly m68k only - deprecated */
+/*
+ * kd.c - KDGHWCLK stuff, possibly m68k only, likely to be deprecated
+ */
#include "clock.h"
#ifdef __m68k__
-#include <unistd.h> /* for close() */
-#include <fcntl.h> /* for O_RDONLY */
-#include <sysexits.h>
-#include <sys/ioctl.h>
+# include <unistd.h> /* for close() */
+# include <fcntl.h> /* for O_RDONLY */
+# include <sysexits.h>
+# include <sys/ioctl.h>
-#include "nls.h"
-#include "usleep.h"
+# include "nls.h"
+# include "usleep.h"
/* Get defines for KDGHWCLK and KDSHWCLK (m68k) */
-#include <linux/kd.h>
+# include <linux/kd.h>
/* Even on m68k, if KDGHWCLK (antique) is not defined, don't build this */
@@ -21,124 +23,126 @@
#if !defined(__m68k__) || !defined(KDGHWCLK)
-struct clock_ops *
-probe_for_kd_clock() {
+struct clock_ops *probe_for_kd_clock()
+{
return NULL;
}
-#else /* __m68k__ && KDGHWCLK */
+#else /* __m68k__ && KDGHWCLK */
-static int con_fd = -1; /* opened by probe_for_kd_clock() */
- /* never closed */
+/* Opened by probe_for_kd_clock(), and never closed. */
+static int con_fd = -1;
static char *con_fd_filename; /* usually "/dev/tty1" */
-static int
-synchronize_to_clock_tick_kd(void) {
-/*----------------------------------------------------------------------------
- Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until
- we see it.
------------------------------------------------------------------------------*/
-
- /* The time when we were called (and started waiting) */
- struct hwclk_time start_time, nowtime;
- struct timeval begin, now;
-
- if (debug)
- printf(_("Waiting in loop for time from KDGHWCLK to change\n"));
-
- if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) {
- outsyserr(_("KDGHWCLK ioctl to read time failed"));
- return 3;
- }
-
- /* Wait for change. Should be within a second, but in case something
- * weird happens, we have a time limit (1.5s) on this loop to reduce the
- * impact of this failure.
- */
- gettimeofday(&begin, NULL);
- do {
- /* Added by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- * "The culprit is the fast loop with KDGHWCLK ioctls. It seems
- * the kernel gets confused by those on Amigas with A2000 RTCs
- * and simply hangs after some time. Inserting a sleep helps."
- */
- usleep(1);
-
- if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) {
- outsyserr(_("KDGHWCLK ioctl to read time failed in loop"));
- return 3;
- }
- if (start_time.tm_sec != nowtime.tm_sec)
- break;
- gettimeofday(&now, NULL);
- if (time_diff(now, begin) > 1.5) {
- fprintf(stderr, _("Timed out waiting for time change.\n"));
- return 2;
- }
- } while(1);
-
- return 0;
+/*
+ * Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until
+ * we see it.
+ */
+static int synchronize_to_clock_tick_kd(void)
+{
+ /* The time when we were called (and started waiting) */
+ struct hwclk_time start_time, nowtime;
+ struct timeval begin, now;
+
+ if (debug)
+ printf(_("Waiting in loop for time from KDGHWCLK to change\n"));
+
+ if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) {
+ outsyserr(_("KDGHWCLK ioctl to read time failed"));
+ return 3;
+ }
+
+ /*
+ * Wait for change. Should be within a second, but in case something
+ * weird happens, we have a time limit (1.5s) on this loop to reduce
+ * the impact of this failure.
+ */
+ gettimeofday(&begin, NULL);
+ do {
+ /*
+ * Added by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ *
+ * "The culprit is the fast loop with KDGHWCLK ioctls. It
+ * seems the kernel gets confused by those on Amigas with
+ * A2000 RTCs and simply hangs after some time. Inserting a
+ * sleep helps."
+ */
+ usleep(1);
+
+ if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) {
+ outsyserr(_
+ ("KDGHWCLK ioctl to read time failed in loop"));
+ return 3;
+ }
+ if (start_time.tm_sec != nowtime.tm_sec)
+ break;
+ gettimeofday(&now, NULL);
+ if (time_diff(now, begin) > 1.5) {
+ fprintf(stderr,
+ _("Timed out waiting for time change.\n"));
+ return 2;
+ }
+ } while (1);
+
+ return 0;
}
+/*
+ * Read the hardware clock and return the current time via <tm> argument.
+ * Use ioctls to /dev/tty1 on what we assume is an m68k machine.
+ *
+ * Note that we don't use /dev/console here. That might be a serial console.
+ */
+static int read_hardware_clock_kd(struct tm *tm)
+{
+ struct hwclk_time t;
+
+ if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
+ outsyserr(_("ioctl() failed to read time from %s"),
+ con_fd_filename);
+ hwclock_exit(EX_IOERR);
+ }
+
+ tm->tm_sec = t.sec;
+ tm->tm_min = t.min;
+ tm->tm_hour = t.hour;
+ tm->tm_mday = t.day;
+ tm->tm_mon = t.mon;
+ tm->tm_year = t.year;
+ tm->tm_wday = t.wday;
+ tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */
-static int
-read_hardware_clock_kd(struct tm *tm) {
-/*----------------------------------------------------------------------------
- Read the hardware clock and return the current time via <tm>
- argument. Use ioctls to /dev/tty1 on what we assume is an m68k
- machine.
-
- Note that we don't use /dev/console here. That might be a serial
- console.
------------------------------------------------------------------------------*/
- struct hwclk_time t;
-
- if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
- outsyserr(_("ioctl() failed to read time from %s"), con_fd_filename);
- hwclock_exit(EX_IOERR);
- }
-
- tm->tm_sec = t.sec;
- tm->tm_min = t.min;
- tm->tm_hour = t.hour;
- tm->tm_mday = t.day;
- tm->tm_mon = t.mon;
- tm->tm_year = t.year;
- tm->tm_wday = t.wday;
- tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */
-
- return 0;
+ return 0;
}
+/*
+ * Set the Hardware Clock to the time <new_broken_time>. Use ioctls to
+ * /dev/tty1 on what we assume is an m68k machine.
+ *
+ * Note that we don't use /dev/console here. That might be a serial console.
+ */
+static int set_hardware_clock_kd(const struct tm *new_broken_time)
+{
+ struct hwclk_time t;
-static int
-set_hardware_clock_kd(const struct tm *new_broken_time) {
-/*----------------------------------------------------------------------------
- Set the Hardware Clock to the time <new_broken_time>. Use ioctls to
- /dev/tty1 on what we assume is an m68k machine.
-
- Note that we don't use /dev/console here. That might be a serial console.
-----------------------------------------------------------------------------*/
- struct hwclk_time t;
-
- t.sec = new_broken_time->tm_sec;
- t.min = new_broken_time->tm_min;
- t.hour = new_broken_time->tm_hour;
- t.day = new_broken_time->tm_mday;
- t.mon = new_broken_time->tm_mon;
- t.year = new_broken_time->tm_year;
- t.wday = new_broken_time->tm_wday;
-
- if (ioctl(con_fd, KDSHWCLK, &t ) == -1) {
- outsyserr(_("ioctl KDSHWCLK failed"));
- hwclock_exit(1);
- }
- return 0;
+ t.sec = new_broken_time->tm_sec;
+ t.min = new_broken_time->tm_min;
+ t.hour = new_broken_time->tm_hour;
+ t.day = new_broken_time->tm_mday;
+ t.mon = new_broken_time->tm_mon;
+ t.year = new_broken_time->tm_year;
+ t.wday = new_broken_time->tm_wday;
+
+ if (ioctl(con_fd, KDSHWCLK, &t) == -1) {
+ outsyserr(_("ioctl KDSHWCLK failed"));
+ hwclock_exit(1);
+ }
+ return 0;
}
-static int
-get_permissions_kd(void) {
- return 0;
+static int get_permissions_kd(void)
+{
+ return 0;
}
static struct clock_ops kd = {
@@ -150,8 +154,8 @@ static struct clock_ops kd = {
};
/* return &kd if KDGHWCLK works, NULL otherwise */
-struct clock_ops *
-probe_for_kd_clock() {
+struct clock_ops *probe_for_kd_clock()
+{
struct clock_ops *ret = NULL;
struct hwclk_time t;
@@ -176,4 +180,4 @@ probe_for_kd_clock() {
}
return ret;
}
-#endif /* __m68k__ && KDGHWCLK */
+#endif /* __m68k__ && KDGHWCLK */
diff --git a/hwclock/rtc.c b/hwclock/rtc.c
index 2e053856a..21c7d746d 100644
--- a/hwclock/rtc.c
+++ b/hwclock/rtc.c
@@ -1,4 +1,6 @@
-/* rtc.c - Use /dev/rtc for clock access */
+/*
+ * rtc.c - Use /dev/rtc for clock access
+ */
#include <unistd.h> /* for close() */
#include <fcntl.h> /* for O_RDONLY */
#include <errno.h>
@@ -12,77 +14,83 @@
/*
* Get defines for rtc stuff.
*
- * Getting the rtc defines is nontrivial.
- * The obvious way is by including <linux/mc146818rtc.h>
- * but that again includes <asm/io.h> which again includes ...
- * and on sparc and alpha this gives compilation errors for
- * many kernel versions. So, we give the defines ourselves here.
- * Moreover, some Sparc person decided to be incompatible, and
- * used a struct rtc_time different from that used in mc146818rtc.h.
+ * Getting the rtc defines is nontrivial. The obvious way is by including
+ * <linux/mc146818rtc.h> but that again includes <asm/io.h> which again
+ * includes ... and on sparc and alpha this gives compilation errors for
+ * many kernel versions. So, we give the defines ourselves here. Moreover,
+ * some Sparc person decided to be incompatible, and used a struct rtc_time
+ * different from that used in mc146818rtc.h.
*/
-/* On Sparcs, there is a <asm/rtc.h> that defines different ioctls
- (that are required on my machine). However, this include file
- does not exist on other architectures. */
+/*
+ * On Sparcs, there is a <asm/rtc.h> that defines different ioctls (that are
+ * required on my machine). However, this include file does not exist on
+ * other architectures.
+ */
/* One might do:
#ifdef __sparc__
-#include <asm/rtc.h>
+# include <asm/rtc.h>
#endif
*/
/* The following is roughly equivalent */
struct sparc_rtc_time
{
- int sec; /* Seconds (0-59) */
- int min; /* Minutes (0-59) */
- int hour; /* Hour (0-23) */
- int dow; /* Day of the week (1-7) */
- int dom; /* Day of the month (1-31) */
- int month; /* Month of year (1-12) */
- int year; /* Year (0-99) */
+ int sec; /* Seconds 0-59 */
+ int min; /* Minutes 0-59 */
+ int hour; /* Hour 0-23 */
+ int dow; /* Day of the week 1-7 */
+ int dom; /* Day of the month 1-31 */
+ int month; /* Month of year 1-12 */
+ int year; /* Year 0-99 */
};
#define RTCGET _IOR('p', 20, struct sparc_rtc_time)
#define RTCSET _IOW('p', 21, struct sparc_rtc_time)
-
/* non-sparc stuff */
#if 0
-#include <linux/version.h>
-/* Check if the /dev/rtc interface is available in this version of
- the system headers. 131072 is linux 2.0.0. */
-#if LINUX_VERSION_CODE >= 131072
-#include <linux/mc146818rtc.h>
-#endif
+# include <linux/version.h>
+/*
+ * Check if the /dev/rtc interface is available in this version of the
+ * system headers. 131072 is linux 2.0.0.
+ */
+# if LINUX_VERSION_CODE >= 131072
+# include <linux/mc146818rtc.h>
+# endif
#endif
-/* struct rtc_time is present since 1.3.99 */
-/* Earlier (since 1.3.89), a struct tm was used. */
+/*
+ * struct rtc_time is present since 1.3.99.
+ * Earlier (since 1.3.89), a struct tm was used.
+ */
struct linux_rtc_time {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year;
- int tm_wday;
- int tm_yday;
- int tm_isdst;
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
};
/* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */
#ifndef RTC_RD_TIME
-#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time)
-#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time)
-#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
-#define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */
+# define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time)
+# define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time)
+# define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
+# define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */
#endif
+
/* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */
#ifndef RTC_EPOCH_READ
-#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
-#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
+# define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
+# define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
#endif
-/* /dev/rtc is conventionally chardev 10/135
+/*
+ * /dev/rtc is conventionally chardev 10/135
* ia64 uses /dev/efirtc, chardev 10/136
* devfs (obsolete) used /dev/misc/... for miscdev
* new RTC framework + udev uses dynamic major and /dev/rtc0.../dev/rtcN
@@ -94,15 +102,15 @@ char *rtc_dev_name;
static int rtc_dev_fd = -1;
-static void
-close_rtc(void) {
+static void close_rtc(void)
+{
if (rtc_dev_fd != -1)
close(rtc_dev_fd);
rtc_dev_fd = -1;
}
-static int
-open_rtc(void) {
+static int open_rtc(void)
+{
char *fls[] = {
#ifdef __ia64__
"/dev/efirtc",
@@ -122,10 +130,11 @@ open_rtc(void) {
if (rtc_dev_name)
rtc_dev_fd = open(rtc_dev_name, O_RDONLY);
else {
- for (p=fls; *p; ++p) {
+ for (p = fls; *p; ++p) {
rtc_dev_fd = open(*p, O_RDONLY);
- if (rtc_dev_fd < 0 && (errno == ENOENT || errno == ENODEV))
+ if (rtc_dev_fd < 0
+ && (errno == ENOENT || errno == ENODEV))
continue;
rtc_dev_name = *p;
break;
@@ -139,8 +148,8 @@ open_rtc(void) {
return rtc_dev_fd;
}
-static int
-open_rtc_or_exit(void) {
+static int open_rtc_or_exit(void)
+{
int rtc_fd = open_rtc();
if (rtc_fd < 0) {
@@ -150,8 +159,8 @@ open_rtc_or_exit(void) {
return rtc_fd;
}
-static int
-do_rtc_read_ioctl(int rtc_fd, struct tm *tm) {
+static int do_rtc_read_ioctl(int rtc_fd, struct tm *tm)
+{
int rc = -1;
char *ioctlname;
@@ -169,7 +178,7 @@ do_rtc_read_ioctl(int rtc_fd, struct tm *tm) {
tm->tm_mon = stm.month - 1;
tm->tm_year = stm.year - 1900;
tm->tm_wday = stm.dow - 1;
- tm->tm_yday = -1; /* day in the year */
+ tm->tm_yday = -1; /* day in the year */
}
#endif
if (rc == -1) { /* no sparc, or RTCGET failed */
@@ -183,134 +192,153 @@ do_rtc_read_ioctl(int rtc_fd, struct tm *tm) {
return -1;
}
- tm->tm_isdst = -1; /* don't know whether it's dst */
+ tm->tm_isdst = -1; /* don't know whether it's dst */
return 0;
}
-static int
-busywait_for_rtc_clock_tick(const int rtc_fd) {
-/*----------------------------------------------------------------------------
- Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
- we see it.
------------------------------------------------------------------------------*/
- struct tm start_time;
- /* The time when we were called (and started waiting) */
- struct tm nowtime;
- int rc;
- struct timeval begin, now;
-
- if (debug)
- printf(_("Waiting in loop for time from %s to change\n"),
- rtc_dev_name);
-
- rc = do_rtc_read_ioctl(rtc_fd, &start_time);
- if (rc)
- return 1;
-
- /* Wait for change. Should be within a second, but in case something
- * weird happens, we have a time limit (1.5s) on this loop to reduce the
- * impact of this failure.
- */
- gettimeofday(&begin, NULL);
- do {
- rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
- if (rc || start_time.tm_sec != nowtime.tm_sec)
- break;
- gettimeofday(&now, NULL);
- if (time_diff(now, begin) > 1.5) {
- fprintf(stderr, _("Timed out waiting for time change.\n"));
- return 2;
- }
- } while(1);
-
- if (rc)
- return 3;
- return 0;
+/*
+ * Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
+ * we see it.
+ */
+static int busywait_for_rtc_clock_tick(const int rtc_fd)
+{
+ struct tm start_time;
+ /* The time when we were called (and started waiting) */
+ struct tm nowtime;
+ int rc;
+ struct timeval begin, now;
+
+ if (debug)
+ printf(_("Waiting in loop for time from %s to change\n"),
+ rtc_dev_name);
+
+ rc = do_rtc_read_ioctl(rtc_fd, &start_time);
+ if (rc)
+ return 1;
+
+ /*
+ * Wait for change. Should be within a second, but in case
+ * something weird happens, we have a time limit (1.5s) on this loop
+ * to reduce the impact of this failure.
+ */
+ gettimeofday(&begin, NULL);
+ do {
+ rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
+ if (rc || start_time.tm_sec != nowtime.tm_sec)
+ break;
+ gettimeofday(&now, NULL);
+ if (time_diff(now, begin) > 1.5) {
+ fprintf(stderr,
+ _("Timed out waiting for time change.\n"));
+ return 2;
+ }
+ } while (1);
+
+ if (rc)
+ return 3;
+ return 0;
}
-static int
-synchronize_to_clock_tick_rtc(void) {
-/*----------------------------------------------------------------------------
- Same as synchronize_to_clock_tick(), but just for /dev/rtc.
------------------------------------------------------------------------------*/
-int rtc_fd; /* File descriptor of /dev/rtc */
-int ret;
-
- rtc_fd = open_rtc();
- if (rtc_fd == -1) {
- outsyserr(_("open() of %s failed"), rtc_dev_name);
- ret = 1;
- } else {
- int rc; /* Return code from ioctl */
- /* Turn on update interrupts (one per second) */
+/*
+ * Same as synchronize_to_clock_tick(), but just for /dev/rtc.
+ */
+static int synchronize_to_clock_tick_rtc(void)
+{
+ int rtc_fd; /* File descriptor of /dev/rtc */
+ int ret;
+
+ rtc_fd = open_rtc();
+ if (rtc_fd == -1) {
+ outsyserr(_("open() of %s failed"), rtc_dev_name);
+ ret = 1;
+ } else {
+ int rc; /* Return code from ioctl */
+ /* Turn on update interrupts (one per second) */
#if defined(__alpha__) || defined(__sparc__)
- /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */
- rc = -1;
- errno = EINVAL;
+ /*
+ * Not all alpha kernels reject RTC_UIE_ON, but probably
+ * they should.
+ */
+ rc = -1;
+ errno = EINVAL;
#else
- rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
+ rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
#endif
- if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
- /* This rtc device doesn't have interrupt functions. This is typical
- on an Alpha, where the Hardware Clock interrupts are used by the
- kernel for the system clock, so aren't at the user's disposal.
- */
- if (debug)
- printf(_("%s does not have interrupt functions. "),
- rtc_dev_name);
- ret = busywait_for_rtc_clock_tick(rtc_fd);
- } else if (rc == 0) {
+ if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
+ /*
+ * This rtc device doesn't have interrupt functions.
+ * This is typical on an Alpha, where the Hardware
+ * Clock interrupts are used by the kernel for the
+ * system clock, so aren't at the user's disposal.
+ */
+ if (debug)
+ printf(_
+ ("%s does not have interrupt functions. "),
+ rtc_dev_name);
+ ret = busywait_for_rtc_clock_tick(rtc_fd);
+ } else if (rc == 0) {
#ifdef Wait_until_update_interrupt
- unsigned long dummy;
-
- /* this blocks until the next update interrupt */
- rc = read(rtc_fd, &dummy, sizeof(dummy));
- ret = 1;
- if (rc == -1)
- outsyserr(_("read() to %s to wait for clock tick failed"),
- rtc_dev_name);
- else
- ret = 0;
+ unsigned long dummy;
+
+ /* this blocks until the next update interrupt */
+ rc = read(rtc_fd, &dummy, sizeof(dummy));
+ ret = 1;
+ if (rc == -1)
+ outsyserr(_
+ ("read() to %s to wait for clock tick failed"),
+ rtc_dev_name);
+ else
+ ret = 0;
#else
- /* Just reading rtc_fd fails on broken hardware: no update
- interrupt comes and a bootscript with a hwclock call hangs */
- fd_set rfds;
- struct timeval tv;
-
- /* Wait up to five seconds for the next update interrupt */
- FD_ZERO(&rfds);
- FD_SET(rtc_fd, &rfds);
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
- ret = 1;
- if (rc == -1)
- outsyserr(_("select() to %s to wait for clock tick failed"),
- rtc_dev_name);
- else if (rc == 0)
- fprintf(stderr, _("select() to %s to wait for clock tick timed out\n"),
- rtc_dev_name);
- else
- ret = 0;
+ /*
+ * Just reading rtc_fd fails on broken hardware: no
+ * update interrupt comes and a bootscript with a
+ * hwclock call hangs
+ */
+ fd_set rfds;
+ struct timeval tv;
+
+ /*
+ * Wait up to five seconds for the next update
+ * interrupt
+ */
+ FD_ZERO(&rfds);
+ FD_SET(rtc_fd, &rfds);
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
+ ret = 1;
+ if (rc == -1)
+ outsyserr(_
+ ("select() to %s to wait for clock tick failed"),
+ rtc_dev_name);
+ else if (rc == 0)
+ fprintf(stderr,
+ _
+ ("select() to %s to wait for clock tick timed out\n"),
+ rtc_dev_name);
+ else
+ ret = 0;
#endif
- /* Turn off update interrupts */
- rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
- if (rc == -1)
- outsyserr(_("ioctl() to %s to turn off update interrupts failed"),
- rtc_dev_name);
- } else {
- outsyserr(_("ioctl() to %s to turn on update interrupts "
- "failed unexpectedly"), rtc_dev_name);
- ret = 1;
- }
- }
- return ret;
+ /* Turn off update interrupts */
+ rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
+ if (rc == -1)
+ outsyserr(_
+ ("ioctl() to %s to turn off update interrupts failed"),
+ rtc_dev_name);
+ } else {
+ outsyserr(_
+ ("ioctl() to %s to turn on update interrupts "
+ "failed unexpectedly"), rtc_dev_name);
+ ret = 1;
+ }
+ }
+ return ret;
}
-
-static int
-read_hardware_clock_rtc(struct tm *tm) {
+static int read_hardware_clock_rtc(struct tm *tm)
+{
int rtc_fd, rc;
rtc_fd = open_rtc_or_exit();
@@ -321,13 +349,12 @@ read_hardware_clock_rtc(struct tm *tm) {
return rc;
}
-
-static int
-set_hardware_clock_rtc(const struct tm *new_broken_time) {
-/*-------------------------------------------------------------------------
- Set the Hardware Clock to the broken down time <new_broken_time>.
- Use ioctls to "rtc" device /dev/rtc.
- -------------------------------------------------------------------------*/
+/*
+ * Set the Hardware Clock to the broken down time <new_broken_time>. Use
+ * ioctls to "rtc" device /dev/rtc.
+ */
+static int set_hardware_clock_rtc(const struct tm *new_broken_time)
+{
int rc = -1;
int rtc_fd;
char *ioctlname;
@@ -368,9 +395,8 @@ set_hardware_clock_rtc(const struct tm *new_broken_time) {
return 0;
}
-
-static int
-get_permissions_rtc(void) {
+static int get_permissions_rtc(void)
+{
return 0;
}
@@ -383,8 +409,8 @@ static struct clock_ops rtc = {
};
/* return &rtc if /dev/rtc can be opened, NULL otherwise */
-struct clock_ops *
-probe_for_rtc_clock(){
+struct clock_ops *probe_for_rtc_clock()
+{
int rtc_fd = open_rtc();
if (rtc_fd >= 0)
return &rtc;
@@ -393,85 +419,91 @@ probe_for_rtc_clock(){
return NULL;
}
+/*
+ * Get the Hardware Clock epoch setting from the kernel.
+ */
+int get_epoch_rtc(unsigned long *epoch_p, int silent)
+{
+ int rtc_fd;
+
+ rtc_fd = open_rtc();
+ if (rtc_fd < 0) {
+ if (!silent) {
+ if (errno == ENOENT)
+ fprintf(stderr,
+ _
+ ("To manipulate the epoch value in the kernel, we must "
+ "access the Linux 'rtc' device driver via the device special "
+ "file %s. This file does not exist on this system.\n"),
+ rtc_dev_name);
+ else
+ outsyserr(_("Unable to open %s"), rtc_dev_name);
+ }
+ return 1;
+ }
+
+ if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
+ if (!silent)
+ outsyserr(_("ioctl(RTC_EPOCH_READ) to %s failed"),
+ rtc_dev_name);
+ return 1;
+ }
+ if (debug)
+ printf(_("we have read epoch %ld from %s "
+ "with RTC_EPOCH_READ ioctl.\n"), *epoch_p,
+ rtc_dev_name);
-int
-get_epoch_rtc(unsigned long *epoch_p, int silent) {
-/*----------------------------------------------------------------------------
- Get the Hardware Clock epoch setting from the kernel.
-----------------------------------------------------------------------------*/
- int rtc_fd;
-
- rtc_fd = open_rtc();
- if (rtc_fd < 0) {
- if (!silent) {
- if (errno == ENOENT)
- fprintf(stderr, _(
- "To manipulate the epoch value in the kernel, we must "
- "access the Linux 'rtc' device driver via the device special "
- "file %s. This file does not exist on this system.\n"),
- rtc_dev_name);
- else
- outsyserr(_("Unable to open %s"), rtc_dev_name);
- }
- return 1;
- }
-
- if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
- if (!silent)
- outsyserr(_("ioctl(RTC_EPOCH_READ) to %s failed"), rtc_dev_name);
- return 1;
- }
-
- if (debug)
- printf(_("we have read epoch %ld from %s "
- "with RTC_EPOCH_READ ioctl.\n"), *epoch_p, rtc_dev_name);
-
- return 0;
+ return 0;
}
+/*
+ * Set the Hardware Clock epoch in the kernel.
+ */
+int set_epoch_rtc(unsigned long epoch)
+{
+ int rtc_fd;
+
+ if (epoch < 1900) {
+ /* kernel would not accept this epoch value
+ *
+ * Bad habit, deciding not to do what the user asks just
+ * because one believes that the kernel might not like it.
+ */
+ fprintf(stderr, _("The epoch value may not be less than 1900. "
+ "You requested %ld\n"), epoch);
+ return 1;
+ }
+
+ rtc_fd = open_rtc();
+ if (rtc_fd < 0) {
+ if (errno == ENOENT)
+ fprintf(stderr,
+ _
+ ("To manipulate the epoch value in the kernel, we must "
+ "access the Linux 'rtc' device driver via the device special "
+ "file %s. This file does not exist on this system.\n"),
+ rtc_dev_name);
+ else
+ outsyserr(_("Unable to open %s"), rtc_dev_name);
+ return 1;
+ }
+ if (debug)
+ printf(_("setting epoch to %ld "
+ "with RTC_EPOCH_SET ioctl to %s.\n"), epoch,
+ rtc_dev_name);
+
+ if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
+ if (errno == EINVAL)
+ fprintf(stderr, _("The kernel device driver for %s "
+ "does not have the RTC_EPOCH_SET ioctl.\n"),
+ rtc_dev_name);
+ else
+ outsyserr(_("ioctl(RTC_EPOCH_SET) to %s failed"),
+ rtc_dev_name);
+ return 1;
+ }
-int
-set_epoch_rtc(unsigned long epoch) {
-/*----------------------------------------------------------------------------
- Set the Hardware Clock epoch in the kernel.
-----------------------------------------------------------------------------*/
- int rtc_fd;
-
- if (epoch < 1900) {
- /* kernel would not accept this epoch value */
- /* Hmm - bad habit, deciding not to do what the user asks
- just because one believes that the kernel might not like it. */
- fprintf(stderr, _("The epoch value may not be less than 1900. "
- "You requested %ld\n"), epoch);
- return 1;
- }
-
- rtc_fd = open_rtc();
- if (rtc_fd < 0) {
- if (errno == ENOENT)
- fprintf(stderr, _("To manipulate the epoch value in the kernel, we must "
- "access the Linux 'rtc' device driver via the device special "
- "file %s. This file does not exist on this system.\n"),
- rtc_dev_name);
- else
- outsyserr(_("Unable to open %s"), rtc_dev_name);
- return 1;
- }
-
- if (debug)
- printf(_("setting epoch to %ld "
- "with RTC_EPOCH_SET ioctl to %s.\n"), epoch, rtc_dev_name);
-
- if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
- if (errno == EINVAL)
- fprintf(stderr, _("The kernel device driver for %s "
- "does not have the RTC_EPOCH_SET ioctl.\n"), rtc_dev_name);
- else
- outsyserr(_("ioctl(RTC_EPOCH_SET) to %s failed"), rtc_dev_name);
- return 1;
- }
-
- return 0;
+ return 0;
}