summaryrefslogtreecommitdiff
path: root/util-linux/hwclock.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/hwclock.c')
-rw-r--r--util-linux/hwclock.c64
1 files changed, 59 insertions, 5 deletions
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index 922dd05..54e97e5 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);