Contents of /tags/mkinitrd-6_2_1/busybox/libbb/time.c
Parent Directory | Revision Log
Revision 999 -
(show annotations)
(download)
Sun May 30 12:16:23 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 5547 byte(s)
Sun May 30 12:16:23 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 5547 byte(s)
tagged 'mkinitrd-6_2_1'
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Utility routines. |
4 | * |
5 | * Copyright (C) 2007 Denys Vlasenko |
6 | * |
7 | * Licensed under GPL version 2, see file LICENSE in this tarball for details. |
8 | */ |
9 | #include "libbb.h" |
10 | |
11 | void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) |
12 | { |
13 | char end = '\0'; |
14 | const char *last_colon = strrchr(date_str, ':'); |
15 | |
16 | if (last_colon != NULL) { |
17 | /* Parse input and assign appropriately to ptm */ |
18 | |
19 | /* HH:MM */ |
20 | if (sscanf(date_str, "%u:%u%c", |
21 | &ptm->tm_hour, |
22 | &ptm->tm_min, |
23 | &end) >= 2) { |
24 | /* no adjustments needed */ |
25 | } else |
26 | /* mm.dd-HH:MM */ |
27 | if (sscanf(date_str, "%u.%u-%u:%u%c", |
28 | &ptm->tm_mon, &ptm->tm_mday, |
29 | &ptm->tm_hour, &ptm->tm_min, |
30 | &end) >= 4) { |
31 | /* Adjust month from 1-12 to 0-11 */ |
32 | ptm->tm_mon -= 1; |
33 | } else |
34 | /* yyyy.mm.dd-HH:MM */ |
35 | if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &ptm->tm_year, |
36 | &ptm->tm_mon, &ptm->tm_mday, |
37 | &ptm->tm_hour, &ptm->tm_min, |
38 | &end) >= 5) { |
39 | ptm->tm_year -= 1900; /* Adjust years */ |
40 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
41 | } else |
42 | /* yyyy-mm-dd HH:MM */ |
43 | if (sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year, |
44 | &ptm->tm_mon, &ptm->tm_mday, |
45 | &ptm->tm_hour, &ptm->tm_min, |
46 | &end) >= 5) { |
47 | ptm->tm_year -= 1900; /* Adjust years */ |
48 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
49 | //TODO: coreutils 6.9 also accepts "yyyy-mm-dd HH" (no minutes) |
50 | } else { |
51 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
52 | } |
53 | if (end == ':') { |
54 | /* xxx:SS */ |
55 | if (sscanf(last_colon + 1, "%u%c", &ptm->tm_sec, &end) == 1) |
56 | end = '\0'; |
57 | /* else end != NUL and we error out */ |
58 | } |
59 | } else { |
60 | /* Googled the following on an old date manpage: |
61 | * |
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 | &ptm->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 | &ptm->tm_hour, |
84 | &ptm->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 | &ptm->tm_mday, |
90 | &ptm->tm_hour, |
91 | &ptm->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 | &ptm->tm_mon, |
97 | &ptm->tm_mday, |
98 | &ptm->tm_hour, |
99 | &ptm->tm_min, |
100 | &end) >= 4) { |
101 | /* Adjust month from 1-12 to 0-11 */ |
102 | ptm->tm_mon -= 1; |
103 | } else |
104 | /* yymmddHHMM[.SS] */ |
105 | if (len == 10 && sscanf(date_str, "%2u%2u%2u%2u%2u%c", |
106 | &ptm->tm_year, |
107 | &ptm->tm_mon, |
108 | &ptm->tm_mday, |
109 | &ptm->tm_hour, |
110 | &ptm->tm_min, |
111 | &end) >= 5) { |
112 | /* Adjust month from 1-12 to 0-11 */ |
113 | ptm->tm_mon -= 1; |
114 | } else |
115 | /* ccyymmddHHMM[.SS] */ |
116 | if (len == 12 && sscanf(date_str, "%4u%2u%2u%2u%2u%c", |
117 | &ptm->tm_year, |
118 | &ptm->tm_mon, |
119 | &ptm->tm_mday, |
120 | &ptm->tm_hour, |
121 | &ptm->tm_min, |
122 | &end) >= 5) { |
123 | ptm->tm_year -= 1900; /* Adjust years */ |
124 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
125 | } else { |
126 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
127 | } |
128 | if (end == '.') { |
129 | /* xxx.SS */ |
130 | if (sscanf(strchr(date_str, '.') + 1, "%u%c", |
131 | &ptm->tm_sec, &end) == 1) |
132 | end = '\0'; |
133 | /* else end != NUL and we error out */ |
134 | } |
135 | } |
136 | if (end != '\0') { |
137 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
138 | } |
139 | } |
140 | |
141 | time_t FAST_FUNC validate_tm_time(const char *date_str, struct tm *ptm) |
142 | { |
143 | time_t t = mktime(ptm); |
144 | if (t == (time_t) -1L) { |
145 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
146 | } |
147 | return t; |
148 | } |
149 | |
150 | #if ENABLE_MONOTONIC_SYSCALL |
151 | |
152 | #include <sys/syscall.h> |
153 | /* Old glibc (< 2.3.4) does not provide this constant. We use syscall |
154 | * directly so this definition is safe. */ |
155 | #ifndef CLOCK_MONOTONIC |
156 | #define CLOCK_MONOTONIC 1 |
157 | #endif |
158 | |
159 | /* libc has incredibly messy way of doing this, |
160 | * typically requiring -lrt. We just skip all this mess */ |
161 | static void get_mono(struct timespec *ts) |
162 | { |
163 | if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts)) |
164 | bb_error_msg_and_die("clock_gettime(MONOTONIC) failed"); |
165 | } |
166 | unsigned long long FAST_FUNC monotonic_ns(void) |
167 | { |
168 | struct timespec ts; |
169 | get_mono(&ts); |
170 | return ts.tv_sec * 1000000000ULL + ts.tv_nsec; |
171 | } |
172 | unsigned long long FAST_FUNC monotonic_us(void) |
173 | { |
174 | struct timespec ts; |
175 | get_mono(&ts); |
176 | return ts.tv_sec * 1000000ULL + ts.tv_nsec/1000; |
177 | } |
178 | unsigned long long FAST_FUNC monotonic_ms(void) |
179 | { |
180 | struct timespec ts; |
181 | get_mono(&ts); |
182 | return ts.tv_sec * 1000ULL + ts.tv_nsec/1000000; |
183 | } |
184 | unsigned FAST_FUNC monotonic_sec(void) |
185 | { |
186 | struct timespec ts; |
187 | get_mono(&ts); |
188 | return ts.tv_sec; |
189 | } |
190 | |
191 | #else |
192 | |
193 | unsigned long long FAST_FUNC monotonic_ns(void) |
194 | { |
195 | struct timeval tv; |
196 | gettimeofday(&tv, NULL); |
197 | return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; |
198 | } |
199 | unsigned long long FAST_FUNC monotonic_us(void) |
200 | { |
201 | struct timeval tv; |
202 | gettimeofday(&tv, NULL); |
203 | return tv.tv_sec * 1000000ULL + tv.tv_usec; |
204 | } |
205 | unsigned long long FAST_FUNC monotonic_ms(void) |
206 | { |
207 | struct timeval tv; |
208 | gettimeofday(&tv, NULL); |
209 | return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; |
210 | } |
211 | unsigned FAST_FUNC monotonic_sec(void) |
212 | { |
213 | return time(NULL); |
214 | } |
215 | |
216 | #endif |