Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Karel Zak
628cd548a7 hwclock: add --mode-file and --drift-file, obsolete --adjfile
Use ul_hwclock_get_drift_file() and ul_hwclock_get_mode_file() to
make it optionally possible to split drift information to
/var/lib/hwclock/drift and to keep /etc/adjtime read-only.

Signed-off-by: Karel Zak <kzak@redhat.com>
2021-03-05 16:10:01 +01:00
Karel Zak
1010d2f771 rtcwake: use ul_hwclock_get_mode_file()
Signed-off-by: Karel Zak <kzak@redhat.com>
2021-03-05 16:09:18 +01:00
Karel Zak
b200c2aab0 build-sys: split _PATH_ADJTIME to two files
This patch introduces:

* _PATH_HWCLOCK_MODE_FILE for clock mode (UTC or LOCAL), default is
   _PATH_ADJTIME (/etc/adjtime).

* _PATH_HWCLOCK_DRIFT_FILE - optional file for clock drift information,
  the default is /var/lib/hwclock/drift. If the file does not exist than
  default to _PATH_HWCLOCK_MODE_FILE.

The both files use 'adjtime' file format for better backward compatibility.

The file /etc/adjtime is de-facto standard and it's used by more 3rd party
utils (e.g. systemd). Unfortunately, keep state files in /etc is bad
idea. This change makes /etc/adjtime read-only for UTC / LOCAL info
and rest is maintained in /var/lib/hwclock/drift.

Note that /var/lib/hwclock/drift is not automatically created. It's up
to downstream (or system admin) to create the file, for example by:

 		cp /etc/adjtime /var/lib/hwclock/drift

otherwise binary will fall back to /etc/adjtime. This idea makes
hwclock backwardly compatible and more portable without recompilation.
(This patch does not implement changes for hwclock.)

Signed-off-by: Karel Zak <kzak@redhat.com>
2021-03-05 15:53:22 +01:00
10 changed files with 191 additions and 101 deletions

View file

@ -141,6 +141,8 @@ edit_cmd = sed \
-e 's|@usrsbin_execdir[@]|$(usrsbin_execdir)|g' \
-e 's|@VERSION[@]|$(VERSION)|g' \
-e 's|@ADJTIME_PATH[@]|$(ADJTIME_PATH)|g' \
-e 's|@CLOCKMODE_PATH[@]|$(CLOCKMODE_PATH)|g' \
-e 's|@CLOCKDRIFT_PATH[@]|$(CLOCKDRIFT_PATH)|g' \
-e 's|@LIBUUID_VERSION[@]|$(LIBUUID_VERSION)|g' \
-e 's|@LIBMOUNT_VERSION[@]|$(LIBMOUNT_VERSION)|g' \
-e 's|@LIBMOUNT_MAJOR_VERSION[@]|$(LIBMOUNT_MAJOR_VERSION)|g' \

View file

@ -2572,14 +2572,23 @@ AC_ARG_VAR([SOLIB_LDFLAGS],
[LDFLAGS used for shared libraries])
AC_ARG_VAR([ADJTIME_PATH],
[Path to hwclock adjtime file, default /etc/adjtime])
[Path to adjtime file; fallback if CLOCKMODE_PATH or CLOCKDRIFT_PATH do not exist, default is /etc/adjtime])
AS_IF([test "x$ADJTIME_PATH" = x], [ADJTIME_PATH="/etc/adjtime"])
AC_DEFINE_UNQUOTED([CONFIG_ADJTIME_PATH], "$ADJTIME_PATH", [Path to hwclock adjtime file])
AC_DEFINE_UNQUOTED([CONFIG_ADJTIME_FILE], "$ADJTIME_PATH", [Path to adjtime file])
AC_ARG_VAR([CLOCKMODE_PATH],
[Path to hwclock utc/local setting file, default ADJTIME_PATH])
AS_IF([test "x$CLOCKMODE_PATH" = x], [CLOCKMODE_PATH=$ADJTIME_PATH])
AC_DEFINE_UNQUOTED([CONFIG_HWCLOCK_MODE_FILE], "$CLOCKMODE_PATH", [Path to hwclock utc/local mode file])
AC_ARG_VAR([CLOCKDRIFT_PATH],
[Path to hwclock drift status file, default /var/lib/hwclock/drift])
AS_IF([test "x$CLOCKDRIFT_PATH" = x], [CLOCKDRIFT_PATH="/var/lib/hwclock/drift"])
AC_DEFINE_UNQUOTED([CONFIG_HWCLOCK_DRIFT_FILE], "$CLOCKDRIFT_PATH", [Path to hwclock drift status file])
LIBS=""
AC_CONFIG_HEADERS([config.h])
#

View file

@ -156,11 +156,9 @@
#define _PATH_DEV_BYPARTUUID "/dev/disk/by-partuuid"
/* hwclock paths */
#ifdef CONFIG_ADJTIME_PATH
# define _PATH_ADJTIME CONFIG_ADJTIME_PATH
#else
# define _PATH_ADJTIME "/etc/adjtime"
#endif
#define _PATH_HWCLOCK_DRIFT_FILE CONFIG_HWCLOCK_DRIFT_FILE
#define _PATH_HWCLOCK_MODE_FILE CONFIG_HWCLOCK_MODE_FILE
#define _PATH_ADJTIME CONFIG_ADJTIME_FILE
#ifdef __ia64__
# define _PATH_RTC_DEV "/dev/efirtc"

View file

@ -89,4 +89,8 @@ int strtime_short(const time_t *t, struct timeval *now, int flags, char *buf, si
extern time_t timegm(struct tm *tm);
#endif
const char *ul_hwclock_get_drift_file(void);
const char *ul_hwclock_get_mode_file(void);
int ul_hwclock_mode_is_utc(const char *modefile, int *rc);
#endif /* UTIL_LINUX_TIME_UTIL_H */

View file

@ -29,6 +29,7 @@
#include "nls.h"
#include "strutils.h"
#include "timeutils.h"
#include "pathnames.h"
#define WHITESPACE " \t\n\r"
@ -568,6 +569,59 @@ time_t timegm(struct tm *tm)
}
#endif /* HAVE_TIMEGM */
/* hwclock drift information */
const char *ul_hwclock_get_drift_file(void)
{
if (access(_PATH_HWCLOCK_DRIFT_FILE, F_OK) == 0)
return _PATH_HWCLOCK_DRIFT_FILE;
return ul_hwclock_get_mode_file();
}
const char *ul_hwclock_get_mode_file(void)
{
if (strcmp(_PATH_HWCLOCK_MODE_FILE, _PATH_ADJTIME) != 0
&& access(_PATH_HWCLOCK_MODE_FILE, F_OK) == 0)
return _PATH_HWCLOCK_MODE_FILE;
return _PATH_ADJTIME; /* backward compatible default */
}
int ul_hwclock_mode_is_utc(const char *modefile, int *rc)
{
FILE *fp = NULL;
char linebuf[8];
*rc = EINVAL;
if (!modefile)
modefile = ul_hwclock_get_mode_file();
fp = fopen(modefile, "r");
if (!fp) {
*rc = errno;
goto dflt;
}
if (skip_fline(fp) || skip_fline(fp)) /* skip two lines */
goto dflt;
if (!fgets(linebuf, sizeof linebuf, fp)) /* read 3rd line */
goto dflt;
fclose(fp);
fp = NULL;
if (strncmp(linebuf, "LOCAL", 5) == 0) {
*rc = 0;
return 0;
}
if (strncmp(linebuf, "UTC", 3) == 0)
*rc = 0;
dflt:
if (fp)
fclose(fp);
return 1;
}
#ifdef TEST_PROGRAM_TIMEUTILS
int main(int argc, char *argv[])
@ -576,16 +630,29 @@ int main(int argc, char *argv[])
char buf[ISO_BUFSIZ];
if (argc < 2) {
fprintf(stderr, "usage: %s [<time> [<usec>]] | [--timestamp <str>]\n", argv[0]);
fprintf(stderr, "usage: %1$s <time> [<usec>]\n"
" %1$s --timestamp <str>\n"
" %1$s --clockmode\n",
argv[0]);
exit(EXIT_FAILURE);
}
if (strcmp(argv[1], "--timestamp") == 0) {
if (strcmp(argv[1], "--clockmode") == 0) {
int rc = 0,
utc = ul_hwclockmode_is_utc(NULL, &rc);
printf("%s: mode is %s [rc=%d]\n",
ul_hwclock_get_mode_file(),
utc ? "UTC" : "LOCAL", rc);
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
} else if (strcmp(argv[1], "--timestamp") == 0) {
usec_t usec = 0;
parse_timestamp(argv[2], &usec);
tv.tv_sec = (time_t) (usec / 1000000);
tv.tv_usec = usec % 1000000;
} else {
tv.tv_sec = strtos64_or_err(argv[1], "failed to parse <time>");
if (argc == 3)

View file

@ -74,8 +74,8 @@ the kernel uses the fixed Hardware Clock epoch of 1900.
Predict what the Hardware Clock will read in the future based upon the
time given by the
.B \-\-date
option and the information in
.IR @ADJTIME_PATH@ .
option and the information in clock drift file, see the discussion below,
under FILES section.
This is useful, for example, to account for drift when setting a
Hardware Clock wakeup (aka alarm). See
.BR \%rtcwake (8).
@ -103,8 +103,8 @@ Showing the Hardware Clock time is the default when no function is specified.
The
.B \-\-get
function also applies drift correction to the time read, based upon the
information in
.IR @ADJTIME_PATH@ .
information in clock drift file, see the discussion below,
under FILES section.
Do not use this function if the Hardware Clock is being modified by
anything other than the current operating system's
.B \%hwclock
@ -123,9 +123,8 @@ for the system. If the Hardware Clock is kept in local time then the time read
from it must be shifted to the UTC timescale before using it to set the System
Clock. The
.B \%\-\-hctosys
function does this based upon the information in the
.I @ADJTIME_PATH@
file or the command line arguments
function does this based upon the information in the clock mode file (see below)
or the command line arguments
.BR \%\-\-localtime " and " \-\-utc .
Note: no daylight saving adjustment is made. See the discussion below, under
.BR "LOCAL vs UTC" .
@ -163,13 +162,12 @@ something has changed the Hardware Clock, like NTP's \%'11\ minute\ mode', then
will set the time incorrectly by including drift compensation.
.sp
Drift compensation can be inhibited by setting the drift factor in
.I @ADJTIME_PATH@
to zero. This setting will be persistent as long as the
drift (adjtime) file to zero. This setting will be persistent as long as the
.BR \%\-\-update\-drift " option is not used with " \%\-\-systohc
at shutdown (or anywhere else). Another way to inhibit this is by using the
.BR \%\-\-noadjfile " option when calling the " \%\-\-hctosys
function. A third method is to delete the
.IR @ADJTIME_PATH@ " file."
function. A third method is to delete the drift file, see the discussion below,
under FILES section.
.B Hwclock
will then default to using the UTC timescale for the Hardware Clock. If
the Hardware Clock is ticking local time it will need to be defined in
@ -194,8 +192,8 @@ the Hardware Clock while its Linux instance is not running.
.B \-\-set
Set the Hardware Clock to the time given by the
.B \-\-date
option, and update the timestamps in
.IR @ADJTIME_PATH@ .
option, and update the timestamps in clock drift file, see the discussion below,
under FILES section.
With the
.B \%\-\-update-drift
option also (re)calculate the drift factor. Try it without the option if
@ -234,7 +232,7 @@ changed then a reboot would be required to inform the kernel.
.TP
.BR \-w , \ \-\-systohc
Set the Hardware Clock from the System Clock, and update the timestamps in
.IR @ADJTIME_PATH@ .
clock drift file, see the discussion below, under FILES section.
With the
.B \%\-\-update-drift
option also (re)calculate the drift factor. Try it without the option if
@ -251,8 +249,12 @@ Display help text and exit.
.SH OPTIONS
.
.TP
.BI \-\-adjfile= filename
.RI "Override the default " @ADJTIME_PATH@ " file path."
.BI \-\-drift-file= filename
.RI "Override the default " @CLOCKDRIFT_PATH@ " file path."
.
.TP
.BI \-\-mode-file= filename
.RI "Override the default " @CLOCKMODE_PATH@ " file path."
.
.TP
.BI \%\-\-date= date_string
@ -371,8 +373,8 @@ If you specify neither
then the one last given with a set function
.RB ( \-\-set ", " \%\-\-systohc ", or " \%\-\-adjust ),
as recorded in
.IR @ADJTIME_PATH@ ,
will be used. If the adjtime file doesn't exist, the default is UTC.
.IR @CLOCKMODE_PATH@ ,
will be used. If the clock mode file doesn't exist, the default is UTC.
.sp
Note: daylight saving time changes may be inconsistent when the
Hardware Clock is kept in local time. See the discussion below, under
@ -381,7 +383,7 @@ Hardware Clock is kept in local time. See the discussion below, under
.TP
.B \-\-noadjfile
Disable the facilities provided by
.IR @ADJTIME_PATH@ .
.IR @CLOCKDRIFT_PATH@ .
.B \%hwclock
will not read nor write to that file with this option. Either
.BR \-\-utc " or " \%\-\-localtime
@ -390,14 +392,14 @@ must be specified when using this option.
.TP
.B \-\-test
Do not actually change anything on the system, that is, the Clocks or
.I @ADJTIME_PATH@
.I @CLOCKDRIFT_PATH@
.RB ( \%\-\-verbose
is implicit with this option).
.
.TP
.B \-\-update\-drift
Update the Hardware Clock's drift factor in
.IR @ADJTIME_PATH@ .
.IR @CLOCKDRIFT_PATH@ .
It can only be used with
.BR \-\-set " or " \%\-\-systohc ,
.sp
@ -432,7 +434,7 @@ the RTC is not read).
.RB "Having " \%hwclock
calculate the drift factor is a good starting point, but for optimal
results it will likely need to be adjusted by directly editing the
.I @ADJTIME_PATH@
.I @CLOCKDRIFT_PATH@
file. For most configurations once a machine's optimal drift factor is
crafted it should not need to be changed. Therefore, the old behavior to
automatically (re)calculate drift was changed and now requires this
@ -577,9 +579,9 @@ function lets you apply systematic drift corrections to the
Hardware Clock.
.PP
It works like this:
.BR \%hwclock " keeps a file,"
.IR @ADJTIME_PATH@ ,
that keeps some historical information. This is called the adjtime file.
.BR \%hwclock " keeps a drift file (aka adjtime file),
that keeps some historical information. The file uses adjtime file format,
see the discussion below, under FILES section.
.PP
Suppose you start with no adjtime file. You issue a
.B \%hwclock\ \-\-set
@ -613,7 +615,7 @@ the systematic drift rate is (re)calculated by comparing the fully drift
corrected current Hardware Clock time with the new set time, from that
it derives the 24 hour drift rate based on the last calibrated timestamp
from the adjtime file. This updated drift factor is then saved in
.IR @ADJTIME_PATH@ .
.IR @CLOCKDRIFT_PATH@ .
.PP
A small amount of error creeps in when
the Hardware Clock is set, so
@ -665,6 +667,12 @@ command line.
.PP
You can use an adjtime file that was previously used with the
.BR \%clock "(8) program with " \%hwclock .
.PP
Since v2.37
.B hwclock
can read "UTC" or "LOCAL" (line 3) from a different file than clock
drift infomation. The both files has to use "adjtime" file format.
See the discussion below, under FILES section.
.
.SS Automatic Hardware Clock Synchronization by the Kernel
You should be aware of another way that the Hardware Clock is kept
@ -839,8 +847,8 @@ then the System Clock must be set correctly (step 6a) just before doing so.
.RB "Having " hwclock
calculate the drift factor is a good starting point, but for optimal
results it will likely need to be adjusted by directly editing the
.I @ADJTIME_PATH@
file. Continue to test and refine the drift factor until the Hardware
clock drift file, see the discussion below, under FILES section.
Continue to test and refine the drift factor until the Hardware
Clock is corrected properly at startup. To check this, first make sure
that the System Time is correct before shutdown and then use
.BR \%sntp ", or " \%date\ \-Ins
@ -951,8 +959,15 @@ If this variable is set its value takes precedence over the system
configured timezone database directory path.
.SH FILES
.TP
.I @ADJTIME_PATH@
The configuration and state file for hwclock.
.I @CLOCKMODE_PATH@
The clock mode (e.g. UTC or LOCAL) file in the "adjtime" file format. For the format see
also
.B The Adjtime File
above.
.TP
.I @CLOCKDRIFT_PATH@
The clock drift file in the "adjtime" file format. May be the same file as the clock mode
file. If the file does not exist then defaults to clock mode file (see above).
.TP
.I /etc/localtime
The system timezone file.

View file

@ -204,9 +204,15 @@ hw_clock_is_utc(const struct hwclock_control *ctl,
ret = 1; /* --utc explicitly given on command line */
else if (ctl->local_opt)
ret = 0; /* --localtime explicitly given */
else
/* get info from adjtime file - default is UTC */
else {
int rc = -1;
if (!adjtime || strcmp(ctl->mode_file_name, ctl->drift_file_name) != 0)
/* no adjtime read, or mode requested from a different file */
ret = ul_hwclock_mode_is_utc(ctl->mode_file_name, &rc);
if (rc != 0)
ret = (adjtime->local_utc != LOCAL);
}
if (ctl->verbose)
printf(_("Assuming hardware clock is kept in %s time.\n"),
@ -228,12 +234,15 @@ static int read_adjtime(const struct hwclock_control *ctl,
char line2[81]; /* String: second line of adjtime file */
char line3[81]; /* String: third line of adjtime file */
if (access(ctl->adj_file_name, R_OK) != 0)
if (access(ctl->drift_file_name, R_OK) != 0)
return EXIT_SUCCESS;
adjfile = fopen(ctl->adj_file_name, "r"); /* open file for reading */
if (ctl->verbose)
printf(_("Reading %s\n"), ctl->drift_file_name);
adjfile = fopen(ctl->drift_file_name, "r"); /* open file for reading */
if (adjfile == NULL) {
warn(_("cannot open %s"), ctl->adj_file_name);
warn(_("cannot open %s"), ctl->drift_file_name);
return EXIT_FAILURE;
}
@ -894,18 +903,18 @@ static int save_adjtime(const struct hwclock_control *ctl,
if (ctl->verbose){
printf(_("New %s data:\n%s"),
ctl->adj_file_name, content);
ctl->drift_file_name, content);
}
if (!ctl->testing) {
fp = fopen(ctl->adj_file_name, "w");
fp = fopen(ctl->drift_file_name, "w");
if (fp == NULL) {
warn(_("cannot open %s"), ctl->adj_file_name);
warn(_("cannot open %s"), ctl->drift_file_name);
return EXIT_FAILURE;
}
if (fputs(content, fp) < 0 || close_stream(fp) != 0) {
warn(_("cannot update %s"), ctl->adj_file_name);
warn(_("cannot update %s"), ctl->drift_file_name);
return EXIT_FAILURE;
}
}
@ -1150,6 +1159,8 @@ static void out_version(void)
static void __attribute__((__noreturn__))
usage(void)
{
const char *drift_file = ul_hwclock_get_drift_file();
fputs(USAGE_HEADER, stdout);
printf(_(" %s [function] [option...]\n"), program_invocation_short_name);
@ -1185,9 +1196,12 @@ usage(void)
#endif
puts(_(" --update-drift update the RTC drift factor"));
printf(_(
" --noadjfile do not use %1$s\n"), _PATH_ADJTIME);
" --noadjfile do not use %s\n"), drift_file);
printf(_(
" --adjfile <file> use an alternate file to %1$s\n"), _PATH_ADJTIME);
" --drift-file <file> use an alternate file to %s\n"), drift_file);
printf(_(
" --mode-file <file> use an alternate file to %s\n"), ul_hwclock_get_mode_file());
puts(_(" --test dry run; implies --verbose"));
puts(_(" -v, --verbose display more details"));
fputs(USAGE_SEPARATOR, stdout);
@ -1213,7 +1227,8 @@ int main(int argc, char **argv)
/* Long only options. */
enum {
OPT_ADJFILE = CHAR_MAX + 1,
OPT_DRIFTFILE = CHAR_MAX + 1,
OPT_MODEFILE,
OPT_DATE,
OPT_DELAY,
OPT_DIRECTISA,
@ -1255,7 +1270,9 @@ int main(int argc, char **argv)
#ifdef __linux__
{ "rtc", required_argument, NULL, 'f' },
#endif
{ "adjfile", required_argument, NULL, OPT_ADJFILE },
{ "adjfile", required_argument, NULL, OPT_DRIFTFILE }, /* deprecated */
{ "drift-file", required_argument, NULL, OPT_DRIFTFILE },
{ "mode-file", required_argument, NULL, OPT_MODEFILE },
{ "systz", no_argument, NULL, OPT_SYSTZ },
{ "predict", no_argument, NULL, OPT_PREDICT },
{ "get", no_argument, NULL, OPT_GET },
@ -1268,7 +1285,7 @@ int main(int argc, char **argv)
OPT_GET, OPT_GETEPOCH, OPT_PREDICT,
OPT_SET, OPT_SETEPOCH, OPT_SYSTZ },
{ 'l', 'u' },
{ OPT_ADJFILE, OPT_NOADJFILE },
{ OPT_DRIFTFILE, OPT_NOADJFILE },
{ OPT_NOADJFILE, OPT_UPDATE },
{ 0 }
};
@ -1376,8 +1393,11 @@ int main(int argc, char **argv)
case OPT_DELAY:
ctl.rtc_delay = strtod_or_err(optarg, "invalid --delay argument");
break;
case OPT_ADJFILE:
ctl.adj_file_name = optarg; /* --adjfile */
case OPT_DRIFTFILE:
ctl.drift_file_name = optarg; /* --drift-file */
break;
case OPT_MODEFILE:
ctl.mode_file_name = optarg; /* --mode-file */
break;
case OPT_SYSTZ:
ctl.systz = 1; /* --systz */
@ -1415,8 +1435,10 @@ int main(int argc, char **argv)
errtryhelp(EXIT_FAILURE);
}
if (!ctl.adj_file_name)
ctl.adj_file_name = _PATH_ADJTIME;
if (!ctl.drift_file_name)
ctl.drift_file_name = ul_hwclock_get_drift_file();
if (!ctl.mode_file_name)
ctl.mode_file_name = ul_hwclock_get_mode_file();
if (ctl.update && !ctl.set && !ctl.systohc) {
warnx(_("--update-drift requires --set or --systohc"));

View file

@ -21,7 +21,10 @@ UL_DEBUG_DECLARE_MASK(hwclock);
struct hwclock_control {
char *date_opt;
char *adj_file_name;
const char *drift_file_name; /* adjtime file with drift status */
const char *mode_file_name; /* adjtime file with UTC/LOCAL */
double rtc_delay; /* --delay <seconds> */
#if defined(__linux__) && defined(__alpha__)
char *epoch_option;

View file

@ -56,7 +56,7 @@ entering a system sleep.
.SH OPTIONS
.TP
.BR \-A , " \-\-adjfile " \fIfile
Specify an alternative path to the adjust file.
Specify an alternative path to the file with hwclock UTC or LOCAL mode.
.TP
.BR \-a , " \-\-auto"
Read the clock mode (whether the hardware clock is set to UTC or local time)
@ -167,7 +167,7 @@ Some PC systems can't currently exit sleep states such as \fBmem\fP
using only the kernel code accessed by this driver.
They need help from userspace code to make the framebuffer work again.
.SH FILES
.I @ADJTIME_PATH@
.I @CLOCKMODE_PATH@
.SH HISTORY
The program was posted several times on LKML and other lists
before appearing in kernel commit message for Linux 2.6 in the GIT

View file

@ -50,7 +50,6 @@
# define RTC_AF 0x20 /* Alarm interrupt */
#endif
#define ADJTIME_ZONE_BUFSIZ 8
#define SYS_WAKEUP_PATH_TEMPLATE "/sys/class/rtc/%s/device/power/wakeup"
#define SYS_POWER_STATE_PATH "/sys/power/state"
#define DEFAULT_RTC_DEVICE "/dev/rtc0"
@ -83,7 +82,7 @@ enum clock_modes {
struct rtcwake_control {
char *mode_str; /* name of the requested mode */
char **possible_modes; /* modes listed in /sys/power/state */
char *adjfile; /* adjtime file path */
char *clock_mode_file; /* file in adjtime format with hwclock timezone */
enum clock_modes clock_mode; /* hwclock timezone */
time_t sys_time; /* system time */
time_t rtc_time; /* hardware time */
@ -104,8 +103,8 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(USAGE_OPTIONS, out);
fputs(_(" -a, --auto reads the clock mode from adjust file (default)\n"), out);
fprintf(out,
_(" -A, --adjfile <file> specifies the path to the adjust file\n"
" the default is %s\n"), _PATH_ADJTIME);
_(" -A, --adjfile <file> path to the file with hwclock mode\n"
" the default is %s\n"), ul_hwclock_get_mode_file());
fputs(_(" --date <timestamp> date time of timestamp to wake\n"), out);
fputs(_(" -d, --device <device> select rtc device (rtc0|rtc1|...)\n"), out);
fputs(_(" -n, --dry-run does everything, but suspend\n"), out);
@ -304,36 +303,6 @@ static void suspend_system(struct rtcwake_control *ctl)
errx(EXIT_FAILURE, _("write error"));
}
static int read_clock_mode(struct rtcwake_control *ctl)
{
FILE *fp;
char linebuf[ADJTIME_ZONE_BUFSIZ];
fp = fopen(ctl->adjfile, "r");
if (!fp)
return -1;
/* skip two lines */
if (skip_fline(fp) || skip_fline(fp)) {
fclose(fp);
return -1;
}
/* read third line */
if (!fgets(linebuf, sizeof linebuf, fp)) {
fclose(fp);
return -1;
}
if (strncmp(linebuf, "UTC", 3) == 0)
ctl->clock_mode = CM_UTC;
else if (strncmp(linebuf, "LOCAL", 5) == 0)
ctl->clock_mode = CM_LOCAL;
else if (ctl->verbose)
warnx(_("unexpected third line in: %s: %s"), ctl->adjfile, linebuf);
fclose(fp);
return 0;
}
static int print_alarm(struct rtcwake_control *ctl, int fd)
{
struct rtc_wkalrm wake;
@ -424,7 +393,6 @@ int main(int argc, char **argv)
{
struct rtcwake_control ctl = {
.mode_str = "suspend", /* default mode */
.adjfile = _PATH_ADJTIME,
.clock_mode = CM_AUTO
};
char *devname = DEFAULT_RTC_DEVICE;
@ -473,7 +441,7 @@ int main(int argc, char **argv)
switch (t) {
case 'A':
/* for better compatibility with hwclock */
ctl.adjfile = optarg;
ctl.clock_mode_file = optarg;
break;
case 'a':
ctl.clock_mode = CM_AUTO;
@ -529,9 +497,11 @@ int main(int argc, char **argv)
}
}
if (ctl.clock_mode == CM_AUTO && read_clock_mode(&ctl) < 0) {
printf(_("%s: assuming RTC uses UTC ...\n"), program_invocation_short_name);
ctl.clock_mode = CM_UTC;
if (ctl.clock_mode == CM_AUTO) {
ctl.clock_mode = ul_hwclock_mode_is_utc(ctl.clock_mode_file, &rc);
if (rc)
printf(_("%s: failed to get clock mode; assuming RTC uses UTC\n"),
program_invocation_short_name);
}
if (ctl.verbose)