aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-07-18 04:49:20 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-07-18 04:49:20 +0200
commit38dd8aa657d80232d8bbce4ed359af2022f605c7 (patch)
treedf326bb4ee6a083cc5b435a7b12d8ecb1331df8c
parent7aca89a7a32a1e560c447952c28a8b1e7fb775fc (diff)
downloadbusybox-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.c6
-rw-r--r--include/usage.h8
-rw-r--r--libbb/time.c97
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';