diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-07-18 03:40:35 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-07-18 03:40:35 +0200 |
commit | 73b71f381d24218cf6368364be723a7b5c9aeda9 (patch) | |
tree | fe3c6e1056417bbd2dc470cd5ad74daaf25542ea /coreutils | |
parent | d23f64eba79a702c36d8d8cec23b49c320897138 (diff) | |
download | busybox-w32-73b71f381d24218cf6368364be723a7b5c9aeda9.tar.gz busybox-w32-73b71f381d24218cf6368364be723a7b5c9aeda9.tar.bz2 busybox-w32-73b71f381d24218cf6368364be723a7b5c9aeda9.zip |
date: factor out date parsing (in preparation for touch -d)
function old new delta
parse_datestr - 391 +391
sha512_process_block128 1283 1310 +27
buffer_fill_and_print 179 196 +17
nexpr 826 840 +14
unzip_main 1931 1939 +8
popstring 134 140 +6
qrealloc 33 36 +3
builtin_umask 121 123 +2
evalvar 1365 1363 -2
changepath 194 192 -2
do_compress 1698 1688 -10
hwclock_main 340 329 -11
cmdputs 414 402 -12
identify 4343 4329 -14
date_main 1186 687 -499
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 7/7 up/down: 468/-550) Total: -82 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/date.c | 134 |
1 files changed, 54 insertions, 80 deletions
diff --git a/coreutils/date.c b/coreutils/date.c index 3a536dbe5..7f2a5b351 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
@@ -10,8 +10,6 @@ | |||
10 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 10 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "libbb.h" | ||
14 | |||
15 | /* This 'date' command supports only 2 time setting formats, | 13 | /* This 'date' command supports only 2 time setting formats, |
16 | all the GNU strftime stuff (its in libc, lets use it), | 14 | all the GNU strftime stuff (its in libc, lets use it), |
17 | setting time using UTC and displaying it, as well as | 15 | setting time using UTC and displaying it, as well as |
@@ -23,18 +21,51 @@ | |||
23 | 21 | ||
24 | /* Default input handling to save surprising some people */ | 22 | /* Default input handling to save surprising some people */ |
25 | 23 | ||
24 | /* GNU coreutils 6.9 man page: | ||
25 | * date [OPTION]... [+FORMAT] | ||
26 | * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] | ||
27 | * -d, --date=STRING | ||
28 | * display time described by STRING, not `now' | ||
29 | * -f, --file=DATEFILE | ||
30 | * like --date once for each line of DATEFILE | ||
31 | * -r, --reference=FILE | ||
32 | * display the last modification time of FILE | ||
33 | * -R, --rfc-2822 | ||
34 | * output date and time in RFC 2822 format. | ||
35 | * Example: Mon, 07 Aug 2006 12:34:56 -0600 | ||
36 | * --rfc-3339=TIMESPEC | ||
37 | * output date and time in RFC 3339 format. | ||
38 | * TIMESPEC='date', 'seconds', or 'ns' | ||
39 | * Date and time components are separated by a single space: | ||
40 | * 2006-08-07 12:34:56-06:00 | ||
41 | * -s, --set=STRING | ||
42 | * set time described by STRING | ||
43 | * -u, --utc, --universal | ||
44 | * print or set Coordinated Universal Time | ||
45 | * | ||
46 | * Busybox: | ||
47 | * long options are not supported | ||
48 | * -f is not supported | ||
49 | * -I seems to roughly match --rfc-3339, but -I has _optional_ param | ||
50 | * (thus "-I seconds" doesn't work, only "-Iseconds"), | ||
51 | * and does not support -Ins | ||
52 | * -D FMT is a bbox extension for _input_ conversion of -d DATE | ||
53 | */ | ||
54 | #include "libbb.h" | ||
26 | 55 | ||
27 | #define DATE_OPT_RFC2822 0x01 | 56 | enum { |
28 | #define DATE_OPT_SET 0x02 | 57 | OPT_RFC2822 = (1 << 0), /* R */ |
29 | #define DATE_OPT_UTC 0x04 | 58 | OPT_SET = (1 << 1), /* s */ |
30 | #define DATE_OPT_DATE 0x08 | 59 | OPT_UTC = (1 << 2), /* u */ |
31 | #define DATE_OPT_REFERENCE 0x10 | 60 | OPT_DATE = (1 << 3), /* d */ |
32 | #define DATE_OPT_TIMESPEC 0x20 | 61 | OPT_REFERENCE = (1 << 4), /* r */ |
33 | #define DATE_OPT_HINT 0x40 | 62 | OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ |
63 | OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ | ||
64 | }; | ||
34 | 65 | ||
35 | static void maybe_set_utc(int opt) | 66 | static void maybe_set_utc(int opt) |
36 | { | 67 | { |
37 | if (opt & DATE_OPT_UTC) | 68 | if (opt & OPT_UTC) |
38 | putenv((char*)"TZ=UTC0"); | 69 | putenv((char*)"TZ=UTC0"); |
39 | } | 70 | } |
40 | 71 | ||
@@ -60,7 +91,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
60 | argv += optind; | 91 | argv += optind; |
61 | maybe_set_utc(opt); | 92 | maybe_set_utc(opt); |
62 | 93 | ||
63 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) { | 94 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_TIMESPEC)) { |
64 | ifmt = 0; /* default is date */ | 95 | ifmt = 0; /* default is date */ |
65 | if (isofmt_arg) { | 96 | if (isofmt_arg) { |
66 | static const char isoformats[] ALIGN1 = | 97 | static const char isoformats[] ALIGN1 = |
@@ -76,8 +107,8 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
76 | fmt_dt2str = &argv[0][1]; /* Skip over the '+' */ | 107 | fmt_dt2str = &argv[0][1]; /* Skip over the '+' */ |
77 | argv++; | 108 | argv++; |
78 | } | 109 | } |
79 | if (!(opt & (DATE_OPT_SET | DATE_OPT_DATE))) { | 110 | if (!(opt & (OPT_SET | OPT_DATE))) { |
80 | opt |= DATE_OPT_SET; | 111 | opt |= OPT_SET; |
81 | date_str = argv[0]; /* can be NULL */ | 112 | date_str = argv[0]; /* can be NULL */ |
82 | if (date_str) | 113 | if (date_str) |
83 | argv++; | 114 | argv++; |
@@ -88,13 +119,14 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
88 | /* Now we have parsed all the information except the date format | 119 | /* Now we have parsed all the information except the date format |
89 | which depends on whether the clock is being set or read */ | 120 | which depends on whether the clock is being set or read */ |
90 | 121 | ||
91 | if (opt & DATE_OPT_REFERENCE) { | 122 | if (opt & OPT_REFERENCE) { |
92 | struct stat statbuf; | 123 | struct stat statbuf; |
93 | xstat(filename, &statbuf); | 124 | xstat(filename, &statbuf); |
94 | tm = statbuf.st_mtime; | 125 | tm = statbuf.st_mtime; |
95 | } else | 126 | } else { |
96 | time(&tm); | 127 | time(&tm); |
97 | memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); | 128 | } |
129 | localtime_r(&tm, &tm_time); | ||
98 | 130 | ||
99 | /* If date string is given, update tm_time, and maybe set date */ | 131 | /* If date string is given, update tm_time, and maybe set date */ |
100 | if (date_str != NULL) { | 132 | if (date_str != NULL) { |
@@ -104,72 +136,14 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
104 | tm_time.tm_hour = 0; | 136 | tm_time.tm_hour = 0; |
105 | 137 | ||
106 | /* Process any date input to UNIX time since 1 Jan 1970 */ | 138 | /* Process any date input to UNIX time since 1 Jan 1970 */ |
107 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) { | 139 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_HINT)) { |
108 | if (strptime(date_str, fmt_str2dt, &tm_time) == NULL) | 140 | if (strptime(date_str, fmt_str2dt, &tm_time) == NULL) |
109 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 141 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
110 | } else { | 142 | } else { |
111 | char end = '\0'; | 143 | parse_datestr(date_str, &tm_time); |
112 | const char *last_colon = strrchr(date_str, ':'); | ||
113 | |||
114 | if (last_colon != NULL) { | ||
115 | /* Parse input and assign appropriately to tm_time */ | ||
116 | |||
117 | if (sscanf(date_str, "%u:%u%c", | ||
118 | &tm_time.tm_hour, | ||
119 | &tm_time.tm_min, | ||
120 | &end) >= 2) { | ||
121 | /* no adjustments needed */ | ||
122 | } else if (sscanf(date_str, "%u.%u-%u:%u%c", | ||
123 | &tm_time.tm_mon, &tm_time.tm_mday, | ||
124 | &tm_time.tm_hour, &tm_time.tm_min, | ||
125 | &end) >= 4) { | ||
126 | /* Adjust dates from 1-12 to 0-11 */ | ||
127 | tm_time.tm_mon -= 1; | ||
128 | } else if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &tm_time.tm_year, | ||
129 | &tm_time.tm_mon, &tm_time.tm_mday, | ||
130 | &tm_time.tm_hour, &tm_time.tm_min, | ||
131 | &end) >= 5) { | ||
132 | tm_time.tm_year -= 1900; /* Adjust years */ | ||
133 | tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
134 | } else if (sscanf(date_str, "%u-%u-%u %u:%u%c", &tm_time.tm_year, | ||
135 | &tm_time.tm_mon, &tm_time.tm_mday, | ||
136 | &tm_time.tm_hour, &tm_time.tm_min, | ||
137 | &end) >= 5) { | ||
138 | tm_time.tm_year -= 1900; /* Adjust years */ | ||
139 | tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
140 | //TODO: coreutils 6.9 also accepts "YYYY-MM-DD HH" (no minutes) | ||
141 | } else { | ||
142 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | ||
143 | } | ||
144 | if (end == ':') { | ||
145 | if (sscanf(last_colon + 1, "%u%c", &tm_time.tm_sec, &end) == 1) | ||
146 | end = '\0'; | ||
147 | /* else end != NUL and we error out */ | ||
148 | } | ||
149 | } else { | ||
150 | if (sscanf(date_str, "%2u%2u%2u%2u%u%c", &tm_time.tm_mon, | ||
151 | &tm_time.tm_mday, &tm_time.tm_hour, &tm_time.tm_min, | ||
152 | &tm_time.tm_year, &end) < 4) | ||
153 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | ||
154 | /* correct for century - minor Y2K problem here? */ | ||
155 | if (tm_time.tm_year >= 1900) { | ||
156 | tm_time.tm_year -= 1900; | ||
157 | } | ||
158 | /* adjust date */ | ||
159 | tm_time.tm_mon -= 1; | ||
160 | if (end == '.') { | ||
161 | if (sscanf(strchr(date_str, '.') + 1, "%u%c", | ||
162 | &tm_time.tm_sec, &end) == 1) | ||
163 | end = '\0'; | ||
164 | /* else end != NUL and we error out */ | ||
165 | } | ||
166 | } | ||
167 | if (end != '\0') { | ||
168 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | ||
169 | } | ||
170 | } | 144 | } |
171 | /* Correct any day of week and day of year etc. fields */ | 145 | /* Correct any day of week and day of year etc. fields */ |
172 | tm_time.tm_isdst = -1; /* Be sure to recheck dst. */ | 146 | tm_time.tm_isdst = -1; /* Be sure to recheck dst */ |
173 | tm = mktime(&tm_time); | 147 | tm = mktime(&tm_time); |
174 | if (tm < 0) { | 148 | if (tm < 0) { |
175 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 149 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
@@ -177,7 +151,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
177 | maybe_set_utc(opt); | 151 | maybe_set_utc(opt); |
178 | 152 | ||
179 | /* if setting time, set it */ | 153 | /* if setting time, set it */ |
180 | if ((opt & DATE_OPT_SET) && stime(&tm) < 0) { | 154 | if ((opt & OPT_SET) && stime(&tm) < 0) { |
181 | bb_perror_msg("cannot set date"); | 155 | bb_perror_msg("cannot set date"); |
182 | } | 156 | } |
183 | } | 157 | } |
@@ -207,9 +181,9 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
207 | } | 181 | } |
208 | format_utc: | 182 | format_utc: |
209 | fmt_dt2str[i++] = '%'; | 183 | fmt_dt2str[i++] = '%'; |
210 | fmt_dt2str[i] = (opt & DATE_OPT_UTC) ? 'Z' : 'z'; | 184 | fmt_dt2str[i] = (opt & OPT_UTC) ? 'Z' : 'z'; |
211 | } | 185 | } |
212 | } else if (opt & DATE_OPT_RFC2822) { | 186 | } else if (opt & OPT_RFC2822) { |
213 | /* Undo busybox.c for date -R */ | 187 | /* Undo busybox.c for date -R */ |
214 | if (ENABLE_LOCALE_SUPPORT) | 188 | if (ENABLE_LOCALE_SUPPORT) |
215 | setlocale(LC_TIME, "C"); | 189 | setlocale(LC_TIME, "C"); |