diff options
Diffstat (limited to 'util-linux/hwclock.c')
-rw-r--r-- | util-linux/hwclock.c | 64 |
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); |