diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-07-18 04:49:20 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-07-18 04:49:20 +0200 |
commit | 38dd8aa657d80232d8bbce4ed359af2022f605c7 (patch) | |
tree | df326bb4ee6a083cc5b435a7b12d8ecb1331df8c | |
parent | 7aca89a7a32a1e560c447952c28a8b1e7fb775fc (diff) | |
download | busybox-w32-38dd8aa657d80232d8bbce4ed359af2022f605c7.tar.gz busybox-w32-38dd8aa657d80232d8bbce4ed359af2022f605c7.tar.bz2 busybox-w32-38dd8aa657d80232d8bbce4ed359af2022f605c7.zip |
touch: implement -t TIME (needed for testsuite)
This changes date -d TIME format a bit, makes it more compatible
function old new delta
parse_datestr 391 618 +227
touch_main 360 361 +1
packed_usage 26624 26615 -9
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | coreutils/touch.c | 6 | ||||
-rw-r--r-- | include/usage.h | 8 | ||||
-rw-r--r-- | libbb/time.c | 97 |
3 files changed, 91 insertions, 20 deletions
diff --git a/coreutils/touch.c b/coreutils/touch.c index 1b4a5f0ea..e79092fc1 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c | |||
@@ -64,10 +64,14 @@ int touch_main(int argc UNUSED_PARAM, char **argv) | |||
64 | #if ENABLE_DESKTOP && ENABLE_LONG_OPTS | 64 | #if ENABLE_DESKTOP && ENABLE_LONG_OPTS |
65 | applet_long_options = touch_longopts; | 65 | applet_long_options = touch_longopts; |
66 | #endif | 66 | #endif |
67 | opts = getopt32(argv, "c" IF_DESKTOP("r:d:") | 67 | /* -d and -t both set time. In coreutils, |
68 | * accepted data format differs a bit between -d and -t. | ||
69 | * We accept the same formats for both */ | ||
70 | opts = getopt32(argv, "c" IF_DESKTOP("r:d:t:") | ||
68 | /*ignored:*/ "fma" | 71 | /*ignored:*/ "fma" |
69 | IF_DESKTOP(, &reference_file) | 72 | IF_DESKTOP(, &reference_file) |
70 | IF_DESKTOP(, &date_str) | 73 | IF_DESKTOP(, &date_str) |
74 | IF_DESKTOP(, &date_str) | ||
71 | ); | 75 | ); |
72 | 76 | ||
73 | opts &= 1; /* only -c bit is left */ | 77 | opts &= 1; /* only -c bit is left */ |
diff --git a/include/usage.h b/include/usage.h index 9493b6d4b..5aedeab78 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -668,6 +668,7 @@ | |||
668 | #define date_full_usage "\n\n" \ | 668 | #define date_full_usage "\n\n" \ |
669 | "Display time (using +FMT), or set time\n" \ | 669 | "Display time (using +FMT), or set time\n" \ |
670 | "\nOptions:" \ | 670 | "\nOptions:" \ |
671 | "\n [-s] TIME Set time to TIME" \ | ||
671 | "\n -u Work in UTC (don't convert to local time)" \ | 672 | "\n -u Work in UTC (don't convert to local time)" \ |
672 | "\n -R Output RFC-822 compliant date string" \ | 673 | "\n -R Output RFC-822 compliant date string" \ |
673 | IF_FEATURE_DATE_ISOFMT( \ | 674 | IF_FEATURE_DATE_ISOFMT( \ |
@@ -676,18 +677,17 @@ | |||
676 | "\n 'hours', 'minutes', or 'seconds' for date and" \ | 677 | "\n 'hours', 'minutes', or 'seconds' for date and" \ |
677 | "\n time to the indicated precision" \ | 678 | "\n time to the indicated precision" \ |
678 | ) \ | 679 | ) \ |
679 | "\n -d TIME Display TIME, not 'now'" \ | ||
680 | "\n -r FILE Display last modification time of FILE" \ | 680 | "\n -r FILE Display last modification time of FILE" \ |
681 | "\n [-s] TIME Set time to TIME" \ | 681 | "\n -d TIME Display TIME, not 'now'" \ |
682 | IF_FEATURE_DATE_ISOFMT( \ | 682 | IF_FEATURE_DATE_ISOFMT( \ |
683 | "\n -D FMT Use FMT for str->date conversion" \ | 683 | "\n -D FMT Use FMT for -d TIME conversion" \ |
684 | ) \ | 684 | ) \ |
685 | "\n" \ | 685 | "\n" \ |
686 | "\nRecognized formats for TIME:" \ | 686 | "\nRecognized formats for TIME:" \ |
687 | "\n hh:mm[:ss]" \ | 687 | "\n hh:mm[:ss]" \ |
688 | "\n [YYYY.]MM.DD-hh:mm[:ss]" \ | 688 | "\n [YYYY.]MM.DD-hh:mm[:ss]" \ |
689 | "\n YYYY-MM-DD hh:mm[:ss]" \ | 689 | "\n YYYY-MM-DD hh:mm[:ss]" \ |
690 | "\n MMDDhhmm[[YY]YY][.ss]" \ | 690 | "\n [[[[[YY]YY]MM]DD]hh]mm[.ss]" \ |
691 | 691 | ||
692 | #define date_example_usage \ | 692 | #define date_example_usage \ |
693 | "$ date\n" \ | 693 | "$ date\n" \ |
diff --git a/libbb/time.c b/libbb/time.c index 1cf2a050e..0816022b9 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
@@ -16,50 +16,117 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *tm_time) | |||
16 | if (last_colon != NULL) { | 16 | if (last_colon != NULL) { |
17 | /* Parse input and assign appropriately to tm_time */ | 17 | /* Parse input and assign appropriately to tm_time */ |
18 | 18 | ||
19 | /* HH:MM */ | ||
19 | if (sscanf(date_str, "%u:%u%c", | 20 | if (sscanf(date_str, "%u:%u%c", |
20 | &tm_time->tm_hour, | 21 | &tm_time->tm_hour, |
21 | &tm_time->tm_min, | 22 | &tm_time->tm_min, |
22 | &end) >= 2) { | 23 | &end) >= 2) { |
23 | /* no adjustments needed */ | 24 | /* no adjustments needed */ |
24 | } else if (sscanf(date_str, "%u.%u-%u:%u%c", | 25 | } else |
26 | /* mm.dd-HH:MM */ | ||
27 | if (sscanf(date_str, "%u.%u-%u:%u%c", | ||
25 | &tm_time->tm_mon, &tm_time->tm_mday, | 28 | &tm_time->tm_mon, &tm_time->tm_mday, |
26 | &tm_time->tm_hour, &tm_time->tm_min, | 29 | &tm_time->tm_hour, &tm_time->tm_min, |
27 | &end) >= 4) { | 30 | &end) >= 4) { |
28 | /* Adjust dates from 1-12 to 0-11 */ | 31 | /* Adjust month from 1-12 to 0-11 */ |
29 | tm_time->tm_mon -= 1; | 32 | tm_time->tm_mon -= 1; |
30 | } else if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &tm_time->tm_year, | 33 | } else |
34 | /* yyyy.mm.dd-HH:MM */ | ||
35 | if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &tm_time->tm_year, | ||
31 | &tm_time->tm_mon, &tm_time->tm_mday, | 36 | &tm_time->tm_mon, &tm_time->tm_mday, |
32 | &tm_time->tm_hour, &tm_time->tm_min, | 37 | &tm_time->tm_hour, &tm_time->tm_min, |
33 | &end) >= 5) { | 38 | &end) >= 5) { |
34 | tm_time->tm_year -= 1900; /* Adjust years */ | 39 | tm_time->tm_year -= 1900; /* Adjust years */ |
35 | tm_time->tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | 40 | tm_time->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
36 | } else if (sscanf(date_str, "%u-%u-%u %u:%u%c", &tm_time->tm_year, | 41 | } else |
42 | /* yyyy-mm-dd HH:MM */ | ||
43 | if (sscanf(date_str, "%u-%u-%u %u:%u%c", &tm_time->tm_year, | ||
37 | &tm_time->tm_mon, &tm_time->tm_mday, | 44 | &tm_time->tm_mon, &tm_time->tm_mday, |
38 | &tm_time->tm_hour, &tm_time->tm_min, | 45 | &tm_time->tm_hour, &tm_time->tm_min, |
39 | &end) >= 5) { | 46 | &end) >= 5) { |
40 | tm_time->tm_year -= 1900; /* Adjust years */ | 47 | tm_time->tm_year -= 1900; /* Adjust years */ |
41 | tm_time->tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | 48 | tm_time->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
42 | //TODO: coreutils 6.9 also accepts "YYYY-MM-DD HH" (no minutes) | 49 | //TODO: coreutils 6.9 also accepts "yyyy-mm-dd HH" (no minutes) |
43 | } else { | 50 | } else { |
44 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 51 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
45 | } | 52 | } |
46 | if (end == ':') { | 53 | if (end == ':') { |
54 | /* xxx:SS */ | ||
47 | if (sscanf(last_colon + 1, "%u%c", &tm_time->tm_sec, &end) == 1) | 55 | if (sscanf(last_colon + 1, "%u%c", &tm_time->tm_sec, &end) == 1) |
48 | end = '\0'; | 56 | end = '\0'; |
49 | /* else end != NUL and we error out */ | 57 | /* else end != NUL and we error out */ |
50 | } | 58 | } |
51 | } else { | 59 | } else { |
52 | if (sscanf(date_str, "%2u%2u%2u%2u%u%c", &tm_time->tm_mon, | 60 | /* Googled the following on an old date manpage: |
53 | &tm_time->tm_mday, &tm_time->tm_hour, &tm_time->tm_min, | 61 | * |
54 | &tm_time->tm_year, &end) < 4) | 62 | * The canonical representation for setting the date/time is: |
63 | * cc Century (either 19 or 20) | ||
64 | * yy Year in abbreviated form (e.g. 89, 06) | ||
65 | * mm Numeric month, a number from 1 to 12 | ||
66 | * dd Day, a number from 1 to 31 | ||
67 | * HH Hour, a number from 0 to 23 | ||
68 | * MM Minutes, a number from 0 to 59 | ||
69 | * ss Seconds, a number from 0 to 61 (with leap seconds) | ||
70 | * Everything but the minutes is optional | ||
71 | * | ||
72 | * This coincides with the format of "touch -t TIME" | ||
73 | */ | ||
74 | int len = strchrnul(date_str, '.') - date_str; | ||
75 | |||
76 | /* MM[.SS] */ | ||
77 | if (len == 2 && sscanf(date_str, "%2u%2u%2u%2u%2u%c" + 12, | ||
78 | &tm_time->tm_min, | ||
79 | &end) >= 1) { | ||
80 | } else | ||
81 | /* HHMM[.SS] */ | ||
82 | if (len == 4 && sscanf(date_str, "%2u%2u%2u%2u%2u%c" + 9, | ||
83 | &tm_time->tm_hour, | ||
84 | &tm_time->tm_min, | ||
85 | &end) >= 2) { | ||
86 | } else | ||
87 | /* ddHHMM[.SS] */ | ||
88 | if (len == 6 && sscanf(date_str, "%2u%2u%2u%2u%2u%c" + 6, | ||
89 | &tm_time->tm_mday, | ||
90 | &tm_time->tm_hour, | ||
91 | &tm_time->tm_min, | ||
92 | &end) >= 3) { | ||
93 | } else | ||
94 | /* mmddHHMM[.SS] */ | ||
95 | if (len == 8 && sscanf(date_str, "%2u%2u%2u%2u%2u%c" + 3, | ||
96 | &tm_time->tm_mon, | ||
97 | &tm_time->tm_mday, | ||
98 | &tm_time->tm_hour, | ||
99 | &tm_time->tm_min, | ||
100 | &end) >= 4) { | ||
101 | /* Adjust month from 1-12 to 0-11 */ | ||
102 | tm_time->tm_mon -= 1; | ||
103 | } else | ||
104 | /* yymmddHHMM[.SS] */ | ||
105 | if (len == 10 && sscanf(date_str, "%2u%2u%2u%2u%2u%c", | ||
106 | &tm_time->tm_year, | ||
107 | &tm_time->tm_mon, | ||
108 | &tm_time->tm_mday, | ||
109 | &tm_time->tm_hour, | ||
110 | &tm_time->tm_min, | ||
111 | &end) >= 5) { | ||
112 | /* Adjust month from 1-12 to 0-11 */ | ||
113 | tm_time->tm_mon -= 1; | ||
114 | } else | ||
115 | /* yyyymmddHHMM[.SS] */ | ||
116 | if (len == 12 && sscanf(date_str, "%4u%2u%2u%2u%2u%c", | ||
117 | &tm_time->tm_year, | ||
118 | &tm_time->tm_mon, | ||
119 | &tm_time->tm_mday, | ||
120 | &tm_time->tm_hour, | ||
121 | &tm_time->tm_min, | ||
122 | &end) >= 5) { | ||
123 | tm_time->tm_year -= 1900; /* Adjust years */ | ||
124 | tm_time->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | ||
125 | } else { | ||
55 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 126 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
56 | /* correct for century - minor Y2K problem here? */ | ||
57 | if (tm_time->tm_year >= 1900) { | ||
58 | tm_time->tm_year -= 1900; | ||
59 | } | 127 | } |
60 | /* adjust date */ | ||
61 | tm_time->tm_mon -= 1; | ||
62 | if (end == '.') { | 128 | if (end == '.') { |
129 | /* xxx.SS */ | ||
63 | if (sscanf(strchr(date_str, '.') + 1, "%u%c", | 130 | if (sscanf(strchr(date_str, '.') + 1, "%u%c", |
64 | &tm_time->tm_sec, &end) == 1) | 131 | &tm_time->tm_sec, &end) == 1) |
65 | end = '\0'; | 132 | end = '\0'; |