aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-07-18 03:40:35 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-07-18 03:40:35 +0200
commit73b71f381d24218cf6368364be723a7b5c9aeda9 (patch)
treefe3c6e1056417bbd2dc470cd5ad74daaf25542ea /coreutils
parentd23f64eba79a702c36d8d8cec23b49c320897138 (diff)
downloadbusybox-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.c134
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 56enum {
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
35static void maybe_set_utc(int opt) 66static 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");