hwclock: implement --systz
No binary (build failed)
—
(log yok)
| @@ -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" \ | |
| @@ -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); | |