summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/usage.src.h19
-rw-r--r--util-linux/hwclock.c64
2 files changed, 59 insertions, 24 deletions
diff --git a/include/usage.src.h b/include/usage.src.h
index 9300b3ce8..ebe80f8e1 100644
--- a/include/usage.src.h
+++ b/include/usage.src.h
@@ -1595,25 +1595,6 @@ INSERT
"\n -e STRING HTML encode STRING" \
"\n -d STRING URL decode STRING" \
-#define hwclock_trivial_usage \
- IF_FEATURE_HWCLOCK_LONG_OPTIONS( \
- "[-r|--show] [-s|--hctosys] [-w|--systohc]" \
- " [-l|--localtime] [-u|--utc]" \
- " [-f FILE]" \
- ) \
- IF_NOT_FEATURE_HWCLOCK_LONG_OPTIONS( \
- "[-r] [-s] [-w] [-l] [-u] [-f FILE]" \
- )
-#define hwclock_full_usage "\n\n" \
- "Query and set hardware clock (RTC)\n" \
- "\nOptions:" \
- "\n -r Show hardware clock time" \
- "\n -s Set system time from hardware clock" \
- "\n -w Set hardware clock to system time" \
- "\n -u Hardware clock is in UTC" \
- "\n -l Hardware clock is in local time" \
- "\n -f FILE Use specified device (e.g. /dev/rtc2)" \
-
#define id_trivial_usage \
"[OPTIONS] [USER]"
#define id_full_usage "\n\n" \
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index 922dd0578..54e97e5bb 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -223,12 +223,63 @@ static void from_sys_clock(const char **pp_rtcname, int utc)
close(rtc);
}
+/*
+ * At system boot, kernel may set system time from RTC,
+ * but it knows nothing about timezones. If RTC is in local time,
+ * then system time is wrong - it is offset by timezone.
+ * This option corrects system time if RTC is in local time,
+ * and (always) sets in-kernel timezone.
+ *
+ * This is an alternate option to --hctosys that does not read the
+ * hardware clock.
+ */
+static void set_system_clock_timezone(int utc)
+{
+ struct timeval tv;
+ struct tm *broken;
+ struct timezone tz;
+
+ gettimeofday(&tv, NULL);
+ broken = localtime(&tv.tv_sec);
+ tz.tz_minuteswest = timezone / 60;
+ if (broken->tm_isdst)
+ tz.tz_minuteswest -= 60;
+ tz.tz_dsttime = 0;
+ gettimeofday(&tv, NULL);
+ if (!utc)
+ tv.tv_sec += tz.tz_minuteswest * 60;
+ if (settimeofday(&tv, &tz))
+ bb_perror_msg_and_die("settimeofday");
+}
+
+//usage:#define hwclock_trivial_usage
+//usage: IF_FEATURE_HWCLOCK_LONG_OPTIONS(
+//usage: "[-r|--show] [-s|--hctosys] [-w|--systohc] [-t|--systz]"
+//usage: " [-l|--localtime] [-u|--utc]"
+//usage: " [-f|--rtc FILE]"
+//usage: )
+//usage: IF_NOT_FEATURE_HWCLOCK_LONG_OPTIONS(
+//usage: "[-r] [-s] [-w] [-t] [-l] [-u] [-f FILE]"
+//usage: )
+//usage:#define hwclock_full_usage "\n\n"
+//usage: "Query and set hardware clock (RTC)\n"
+//usage: "\nOptions:"
+//usage: "\n -r Show hardware clock time"
+//usage: "\n -s Set system time from hardware clock"
+//usage: "\n -w Set hardware clock from system time"
+//usage: "\n -t Set in-kernel timezone, correct system time"
+//usage: "\n if hardware clock is in local time"
+//usage: "\n -u Hardware clock is in UTC"
+//usage: "\n -l Hardware clock is in local time"
+//usage: "\n -f FILE Use specified device (e.g. /dev/rtc2)"
+
#define HWCLOCK_OPT_LOCALTIME 0x01
#define HWCLOCK_OPT_UTC 0x02
#define HWCLOCK_OPT_SHOW 0x04
#define HWCLOCK_OPT_HCTOSYS 0x08
#define HWCLOCK_OPT_SYSTOHC 0x10
-#define HWCLOCK_OPT_RTCFILE 0x20
+#define HWCLOCK_OPT_SYSTZ 0x20
+#define HWCLOCK_OPT_RTCFILE 0x40
int hwclock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int hwclock_main(int argc UNUSED_PARAM, char **argv)
@@ -239,17 +290,18 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
static const char hwclock_longopts[] ALIGN1 =
- "localtime\0" No_argument "l"
+ "localtime\0" No_argument "l" /* short opt is non-standard */
"utc\0" No_argument "u"
"show\0" No_argument "r"
"hctosys\0" No_argument "s"
"systohc\0" No_argument "w"
- "file\0" Required_argument "f"
+ "systz\0" No_argument "t" /* short opt is non-standard */
+ "rtc\0" Required_argument "f"
;
applet_long_options = hwclock_longopts;
#endif
- opt_complementary = "r--ws:w--rs:s--wr:l--u:u--l";
- opt = getopt32(argv, "lurswf:", &rtcname);
+ opt_complementary = "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l";
+ opt = getopt32(argv, "lurswtf:", &rtcname);
/* If -u or -l wasn't given check if we are using utc */
if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME))
@@ -261,6 +313,8 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv)
to_sys_clock(&rtcname, utc);
else if (opt & HWCLOCK_OPT_SYSTOHC)
from_sys_clock(&rtcname, utc);
+ else if (opt & HWCLOCK_OPT_SYSTZ)
+ set_system_clock_timezone(utc);
else
/* default HWCLOCK_OPT_SHOW */
show_clock(&rtcname, utc);