Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/date.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (13 years, 11 months ago) by niro
File MIME type: text/plain
File size: 6906 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * Mini date implementation for busybox
4     *
5     * by Matthew Grant <grantma@anathoth.gen.nz>
6     *
7     * iso-format handling added by Robert Griebl <griebl@gmx.de>
8 niro 816 * bugfixes and cleanup by Bernhard Reutner-Fischer
9 niro 532 *
10     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11     */
12    
13     /* This 'date' command supports only 2 time setting formats,
14     all the GNU strftime stuff (its in libc, lets use it),
15     setting time using UTC and displaying it, as well as
16     an RFC 2822 compliant date output for shell scripting
17     mail commands */
18    
19     /* Input parsing code is always bulky - used heavy duty libc stuff as
20     much as possible, missed out a lot of bounds checking */
21    
22     /* Default input handling to save surprising some people */
23    
24 niro 984 /* 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"
55 niro 532
56 niro 984 enum {
57     OPT_RFC2822 = (1 << 0), /* R */
58     OPT_SET = (1 << 1), /* s */
59     OPT_UTC = (1 << 2), /* u */
60     OPT_DATE = (1 << 3), /* d */
61     OPT_REFERENCE = (1 << 4), /* r */
62     OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
63     OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
64     };
65 niro 532
66     static void maybe_set_utc(int opt)
67     {
68 niro 984 if (opt & OPT_UTC)
69 niro 816 putenv((char*)"TZ=UTC0");
70 niro 532 }
71    
72 niro 984 #if ENABLE_LONG_OPTS
73     static const char date_longopts[] ALIGN1 =
74     "rfc-822\0" No_argument "R"
75     "rfc-2822\0" No_argument "R"
76     "set\0" Required_argument "s"
77     "utc\0" No_argument "u"
78     /* "universal\0" No_argument "u" */
79     "date\0" Required_argument "d"
80     "reference\0" Required_argument "r"
81     ;
82     #endif
83    
84 niro 816 int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
85     int date_main(int argc UNUSED_PARAM, char **argv)
86 niro 532 {
87 niro 816 struct tm tm_time;
88 niro 984 char buf_fmt_dt2str[64];
89 niro 532 time_t tm;
90     unsigned opt;
91     int ifmt = -1;
92 niro 816 char *date_str;
93     char *fmt_dt2str;
94     char *fmt_str2dt;
95     char *filename;
96     char *isofmt_arg = NULL;
97 niro 532
98 niro 816 opt_complementary = "d--s:s--d"
99 niro 984 IF_FEATURE_DATE_ISOFMT(":R--I:I--R");
100     IF_LONG_OPTS(applet_long_options = date_longopts;)
101 niro 816 opt = getopt32(argv, "Rs:ud:r:"
102 niro 984 IF_FEATURE_DATE_ISOFMT("I::D:"),
103 niro 532 &date_str, &date_str, &filename
104 niro 984 IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt));
105 niro 816 argv += optind;
106 niro 532 maybe_set_utc(opt);
107    
108 niro 984 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_TIMESPEC)) {
109 niro 816 ifmt = 0; /* default is date */
110     if (isofmt_arg) {
111     static const char isoformats[] ALIGN1 =
112 niro 984 "date\0""hours\0""minutes\0""seconds\0"; /* ns? */
113     ifmt = index_in_substrings(isoformats, isofmt_arg);
114 niro 816 if (ifmt < 0)
115 niro 532 bb_show_usage();
116     }
117     }
118    
119 niro 816 fmt_dt2str = NULL;
120     if (argv[0] && argv[0][0] == '+') {
121 niro 984 fmt_dt2str = &argv[0][1]; /* skip over the '+' */
122 niro 816 argv++;
123     }
124 niro 984 if (!(opt & (OPT_SET | OPT_DATE))) {
125     opt |= OPT_SET;
126 niro 816 date_str = argv[0]; /* can be NULL */
127 niro 984 if (date_str) {
128     #if ENABLE_FEATURE_DATE_COMPAT
129     int len = strspn(date_str, "0123456789");
130     if (date_str[len] == '\0'
131     || (date_str[len] == '.'
132     && isdigit(date_str[len+1])
133     && isdigit(date_str[len+2])
134     && date_str[len+3] == '\0'
135     )
136     ) {
137     /* Dreaded MMDDhhmm[[CC]YY][.ss] format!
138     * It does not match -d or -s format.
139     * Some users actually do use it.
140     */
141     len -= 8;
142     if (len < 0 || len > 4 || (len & 1))
143     bb_error_msg_and_die(bb_msg_invalid_date, date_str);
144     if (len != 0) { /* move YY or CCYY to front */
145     char buf[4];
146     memcpy(buf, date_str + 8, len);
147     memmove(date_str + len, date_str, 8);
148     memcpy(date_str, buf, len);
149     }
150     }
151     #endif
152 niro 816 argv++;
153 niro 984 }
154 niro 532 }
155 niro 816 if (*argv)
156     bb_show_usage();
157 niro 532
158     /* Now we have parsed all the information except the date format
159 niro 984 * which depends on whether the clock is being set or read */
160 niro 532
161 niro 984 if (opt & OPT_REFERENCE) {
162 niro 532 struct stat statbuf;
163     xstat(filename, &statbuf);
164     tm = statbuf.st_mtime;
165 niro 984 } else {
166 niro 532 time(&tm);
167 niro 984 }
168     localtime_r(&tm, &tm_time);
169 niro 816
170     /* If date string is given, update tm_time, and maybe set date */
171 niro 532 if (date_str != NULL) {
172 niro 816 /* Zero out fields - take her back to midnight! */
173 niro 532 tm_time.tm_sec = 0;
174     tm_time.tm_min = 0;
175     tm_time.tm_hour = 0;
176    
177     /* Process any date input to UNIX time since 1 Jan 1970 */
178 niro 984 if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_HINT)) {
179 niro 816 if (strptime(date_str, fmt_str2dt, &tm_time) == NULL)
180     bb_error_msg_and_die(bb_msg_invalid_date, date_str);
181     } else {
182 niro 984 parse_datestr(date_str, &tm_time);
183     }
184 niro 532
185 niro 984 /* Correct any day of week and day of year etc. fields */
186     tm_time.tm_isdst = -1; /* Be sure to recheck dst */
187     tm = validate_tm_time(date_str, &tm_time);
188 niro 816
189 niro 532 maybe_set_utc(opt);
190    
191     /* if setting time, set it */
192 niro 984 if ((opt & OPT_SET) && stime(&tm) < 0) {
193     bb_perror_msg("can't set date");
194 niro 532 }
195     }
196    
197     /* Display output */
198    
199     /* Deal with format string */
200 niro 816 if (fmt_dt2str == NULL) {
201 niro 532 int i;
202 niro 984 fmt_dt2str = buf_fmt_dt2str;
203 niro 532 if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) {
204 niro 984 /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds */
205     strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S");
206     i = 8 + 3 * ifmt;
207     if (ifmt != 0) {
208     /* TODO: if (ifmt==4) i += sprintf(&fmt_dt2str[i], ",%09u", nanoseconds); */
209 niro 816 format_utc:
210     fmt_dt2str[i++] = '%';
211 niro 984 fmt_dt2str[i++] = (opt & OPT_UTC) ? 'Z' : 'z';
212 niro 532 }
213 niro 984 fmt_dt2str[i] = '\0';
214     } else if (opt & OPT_RFC2822) {
215     /* -R. undo busybox.c setlocale */
216 niro 532 if (ENABLE_LOCALE_SUPPORT)
217     setlocale(LC_TIME, "C");
218 niro 816 strcpy(fmt_dt2str, "%a, %d %b %Y %H:%M:%S ");
219 niro 984 i = sizeof("%a, %d %b %Y %H:%M:%S ")-1;
220 niro 532 goto format_utc;
221 niro 984 } else { /* default case */
222 niro 816 fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y";
223 niro 984 }
224 niro 532 }
225    
226 niro 816 #define date_buf bb_common_bufsiz1
227     if (*fmt_dt2str == '\0') {
228 niro 532 /* With no format string, just print a blank line */
229 niro 816 date_buf[0] = '\0';
230 niro 532 } else {
231     /* Handle special conversions */
232 niro 816 if (strncmp(fmt_dt2str, "%f", 2) == 0) {
233     fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S";
234 niro 532 }
235     /* Generate output string */
236 niro 816 strftime(date_buf, sizeof(date_buf), fmt_dt2str, &tm_time);
237 niro 532 }
238 niro 816 puts(date_buf);
239 niro 532
240     return EXIT_SUCCESS;
241     }