/src/httpd/srclib/apr/time/unix/time.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Licensed to the Apache Software Foundation (ASF) under one or more |
2 | | * contributor license agreements. See the NOTICE file distributed with |
3 | | * this work for additional information regarding copyright ownership. |
4 | | * The ASF licenses this file to You under the Apache License, Version 2.0 |
5 | | * (the "License"); you may not use this file except in compliance with |
6 | | * the License. You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include "apr_portable.h" |
18 | | #include "apr_time.h" |
19 | | #include "apr_lib.h" |
20 | | #include "apr_private.h" |
21 | | #include "apr_strings.h" |
22 | | |
23 | | /* private APR headers */ |
24 | | #include "apr_arch_internal_time.h" |
25 | | |
26 | | /* System Headers required for time library */ |
27 | | #if APR_HAVE_SYS_TIME_H |
28 | | #include <sys/time.h> |
29 | | #endif |
30 | | #if APR_HAVE_UNISTD_H |
31 | | #include <unistd.h> |
32 | | #endif |
33 | | #ifdef HAVE_TIME_H |
34 | | #include <time.h> |
35 | | #endif |
36 | | /* End System Headers */ |
37 | | |
38 | | #if !defined(HAVE_STRUCT_TM_TM_GMTOFF) && !defined(HAVE_STRUCT_TM___TM_GMTOFF) |
39 | | static apr_int32_t server_gmt_offset; |
40 | | #define NO_GMTOFF_IN_STRUCT_TM |
41 | | #endif |
42 | | |
43 | | static apr_int32_t get_offset(struct tm *tm) |
44 | 0 | { |
45 | 0 | #if defined(HAVE_STRUCT_TM_TM_GMTOFF) |
46 | 0 | return tm->tm_gmtoff; |
47 | | #elif defined(HAVE_STRUCT_TM___TM_GMTOFF) |
48 | | return tm->__tm_gmtoff; |
49 | | #else |
50 | | #ifdef NETWARE |
51 | | /* Need to adjust the global variable each time otherwise |
52 | | the web server would have to be restarted when daylight |
53 | | savings changes. |
54 | | */ |
55 | | if (daylightOnOff) { |
56 | | return server_gmt_offset + daylightOffset; |
57 | | } |
58 | | #else |
59 | | if (tm->tm_isdst) |
60 | | return server_gmt_offset + 3600; |
61 | | #endif |
62 | | return server_gmt_offset; |
63 | | #endif |
64 | 0 | } |
65 | | |
66 | | APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, |
67 | | time_t input) |
68 | 3.79k | { |
69 | 3.79k | *result = (apr_time_t)input * APR_USEC_PER_SEC; |
70 | 3.79k | return APR_SUCCESS; |
71 | 3.79k | } |
72 | | |
73 | | /* NB NB NB NB This returns GMT!!!!!!!!!! */ |
74 | | APR_DECLARE(apr_time_t) apr_time_now(void) |
75 | 531 | { |
76 | 531 | struct timeval tv; |
77 | 531 | gettimeofday(&tv, NULL); |
78 | 531 | return tv.tv_sec * (apr_time_t)APR_USEC_PER_SEC + (apr_time_t)tv.tv_usec; |
79 | 531 | } |
80 | | |
81 | | static void explode_time(apr_time_exp_t *xt, apr_time_t t, |
82 | | apr_int32_t offset, int use_localtime) |
83 | 0 | { |
84 | 0 | struct tm tm; |
85 | 0 | time_t tt = (t / APR_USEC_PER_SEC) + offset; |
86 | 0 | xt->tm_usec = t % APR_USEC_PER_SEC; |
87 | |
|
88 | 0 | #if APR_HAS_THREADS && defined (_POSIX_THREAD_SAFE_FUNCTIONS) |
89 | 0 | if (use_localtime) |
90 | 0 | localtime_r(&tt, &tm); |
91 | 0 | else |
92 | 0 | gmtime_r(&tt, &tm); |
93 | | #else |
94 | | if (use_localtime) |
95 | | tm = *localtime(&tt); |
96 | | else |
97 | | tm = *gmtime(&tt); |
98 | | #endif |
99 | |
|
100 | 0 | xt->tm_sec = tm.tm_sec; |
101 | 0 | xt->tm_min = tm.tm_min; |
102 | 0 | xt->tm_hour = tm.tm_hour; |
103 | 0 | xt->tm_mday = tm.tm_mday; |
104 | 0 | xt->tm_mon = tm.tm_mon; |
105 | 0 | xt->tm_year = tm.tm_year; |
106 | 0 | xt->tm_wday = tm.tm_wday; |
107 | 0 | xt->tm_yday = tm.tm_yday; |
108 | 0 | xt->tm_isdst = tm.tm_isdst; |
109 | 0 | xt->tm_gmtoff = get_offset(&tm); |
110 | 0 | } |
111 | | |
112 | | APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, |
113 | | apr_time_t input, apr_int32_t offs) |
114 | 0 | { |
115 | 0 | explode_time(result, input, offs, 0); |
116 | 0 | result->tm_gmtoff = offs; |
117 | 0 | return APR_SUCCESS; |
118 | 0 | } |
119 | | |
120 | | APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result, |
121 | | apr_time_t input) |
122 | 0 | { |
123 | 0 | return apr_time_exp_tz(result, input, 0); |
124 | 0 | } |
125 | | |
126 | | APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result, |
127 | | apr_time_t input) |
128 | 0 | { |
129 | | #if defined(__EMX__) |
130 | | /* EMX gcc (OS/2) has a timezone global we can use */ |
131 | | return apr_time_exp_tz(result, input, -timezone); |
132 | | #else |
133 | 0 | explode_time(result, input, 0, 1); |
134 | 0 | return APR_SUCCESS; |
135 | 0 | #endif /* __EMX__ */ |
136 | 0 | } |
137 | | |
138 | | APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t, apr_time_exp_t *xt) |
139 | 0 | { |
140 | 0 | apr_time_t year = xt->tm_year; |
141 | 0 | apr_time_t days; |
142 | 0 | static const int dayoffset[12] = |
143 | 0 | {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; |
144 | |
|
145 | 0 | if (xt->tm_mon < 0 || xt->tm_mon >= 12) |
146 | 0 | return APR_EBADDATE; |
147 | | |
148 | | /* shift new year to 1st March in order to make leap year calc easy */ |
149 | | |
150 | 0 | if (xt->tm_mon < 2) |
151 | 0 | year--; |
152 | | |
153 | | /* Find number of days since 1st March 1900 (in the Gregorian calendar). */ |
154 | |
|
155 | 0 | days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; |
156 | 0 | days += dayoffset[xt->tm_mon] + xt->tm_mday - 1; |
157 | 0 | days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */ |
158 | 0 | days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec; |
159 | |
|
160 | 0 | if (days < 0) { |
161 | 0 | return APR_EBADDATE; |
162 | 0 | } |
163 | 0 | *t = days * APR_USEC_PER_SEC + xt->tm_usec; |
164 | 0 | return APR_SUCCESS; |
165 | 0 | } |
166 | | |
167 | | APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t, |
168 | | apr_time_exp_t *xt) |
169 | 0 | { |
170 | 0 | apr_status_t status = apr_time_exp_get(t, xt); |
171 | 0 | if (status == APR_SUCCESS) |
172 | 0 | *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC; |
173 | 0 | return status; |
174 | 0 | } |
175 | | |
176 | | APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime, |
177 | | apr_time_t *aprtime) |
178 | 0 | { |
179 | 0 | (*ostime)->tv_usec = *aprtime % APR_USEC_PER_SEC; |
180 | 0 | (*ostime)->tv_sec = *aprtime / APR_USEC_PER_SEC; |
181 | 0 | return APR_SUCCESS; |
182 | 0 | } |
183 | | |
184 | | APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, |
185 | | apr_time_exp_t *aprtime) |
186 | 0 | { |
187 | 0 | (*ostime)->tm_sec = aprtime->tm_sec; |
188 | 0 | (*ostime)->tm_min = aprtime->tm_min; |
189 | 0 | (*ostime)->tm_hour = aprtime->tm_hour; |
190 | 0 | (*ostime)->tm_mday = aprtime->tm_mday; |
191 | 0 | (*ostime)->tm_mon = aprtime->tm_mon; |
192 | 0 | (*ostime)->tm_year = aprtime->tm_year; |
193 | 0 | (*ostime)->tm_wday = aprtime->tm_wday; |
194 | 0 | (*ostime)->tm_yday = aprtime->tm_yday; |
195 | 0 | (*ostime)->tm_isdst = aprtime->tm_isdst; |
196 | |
|
197 | 0 | #if defined(HAVE_STRUCT_TM_TM_GMTOFF) |
198 | 0 | (*ostime)->tm_gmtoff = aprtime->tm_gmtoff; |
199 | | #elif defined(HAVE_STRUCT_TM___TM_GMTOFF) |
200 | | (*ostime)->__tm_gmtoff = aprtime->tm_gmtoff; |
201 | | #endif |
202 | |
|
203 | 0 | return APR_SUCCESS; |
204 | 0 | } |
205 | | |
206 | | APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime, |
207 | | apr_os_imp_time_t **ostime, |
208 | | apr_pool_t *cont) |
209 | 0 | { |
210 | 0 | *aprtime = (*ostime)->tv_sec * APR_USEC_PER_SEC + (*ostime)->tv_usec; |
211 | 0 | return APR_SUCCESS; |
212 | 0 | } |
213 | | |
214 | | APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime, |
215 | | apr_os_exp_time_t **ostime, |
216 | | apr_pool_t *cont) |
217 | 0 | { |
218 | 0 | aprtime->tm_sec = (*ostime)->tm_sec; |
219 | 0 | aprtime->tm_min = (*ostime)->tm_min; |
220 | 0 | aprtime->tm_hour = (*ostime)->tm_hour; |
221 | 0 | aprtime->tm_mday = (*ostime)->tm_mday; |
222 | 0 | aprtime->tm_mon = (*ostime)->tm_mon; |
223 | 0 | aprtime->tm_year = (*ostime)->tm_year; |
224 | 0 | aprtime->tm_wday = (*ostime)->tm_wday; |
225 | 0 | aprtime->tm_yday = (*ostime)->tm_yday; |
226 | 0 | aprtime->tm_isdst = (*ostime)->tm_isdst; |
227 | |
|
228 | 0 | #if defined(HAVE_STRUCT_TM_TM_GMTOFF) |
229 | 0 | aprtime->tm_gmtoff = (*ostime)->tm_gmtoff; |
230 | | #elif defined(HAVE_STRUCT_TM___TM_GMTOFF) |
231 | | aprtime->tm_gmtoff = (*ostime)->__tm_gmtoff; |
232 | | #endif |
233 | |
|
234 | 0 | return APR_SUCCESS; |
235 | 0 | } |
236 | | |
237 | | APR_DECLARE(void) apr_sleep(apr_interval_time_t t) |
238 | 0 | { |
239 | | #ifdef OS2 |
240 | | DosSleep((t + 999) / 1000); |
241 | | #elif defined(BEOS) |
242 | | snooze(t); |
243 | | #elif defined(NETWARE) |
244 | | delay((t + 999) / 1000); |
245 | | #elif defined(HAVE_NANOSLEEP) |
246 | 0 | struct timespec ts; |
247 | 0 | ts.tv_sec = t / APR_USEC_PER_SEC; |
248 | 0 | ts.tv_nsec = (t % APR_USEC_PER_SEC) * 1000; |
249 | 0 | nanosleep(&ts, NULL); |
250 | | #else |
251 | | struct timeval tv; |
252 | | tv.tv_usec = t % APR_USEC_PER_SEC; |
253 | | tv.tv_sec = t / APR_USEC_PER_SEC; |
254 | | select(0, NULL, NULL, NULL, &tv); |
255 | | #endif |
256 | 0 | } |
257 | | |
258 | | #ifdef OS2 |
259 | | APR_DECLARE(apr_status_t) apr_os2_time_to_apr_time(apr_time_t *result, |
260 | | FDATE os2date, |
261 | | FTIME os2time) |
262 | | { |
263 | | struct tm tmpdate; |
264 | | |
265 | | memset(&tmpdate, 0, sizeof(tmpdate)); |
266 | | tmpdate.tm_hour = os2time.hours; |
267 | | tmpdate.tm_min = os2time.minutes; |
268 | | tmpdate.tm_sec = os2time.twosecs * 2; |
269 | | |
270 | | tmpdate.tm_mday = os2date.day; |
271 | | tmpdate.tm_mon = os2date.month - 1; |
272 | | tmpdate.tm_year = os2date.year + 80; |
273 | | tmpdate.tm_isdst = -1; |
274 | | |
275 | | *result = mktime(&tmpdate) * APR_USEC_PER_SEC; |
276 | | return APR_SUCCESS; |
277 | | } |
278 | | |
279 | | APR_DECLARE(apr_status_t) apr_apr_time_to_os2_time(FDATE *os2date, |
280 | | FTIME *os2time, |
281 | | apr_time_t aprtime) |
282 | | { |
283 | | time_t ansitime = aprtime / APR_USEC_PER_SEC; |
284 | | struct tm *lt; |
285 | | lt = localtime(&ansitime); |
286 | | os2time->hours = lt->tm_hour; |
287 | | os2time->minutes = lt->tm_min; |
288 | | os2time->twosecs = lt->tm_sec / 2; |
289 | | |
290 | | os2date->day = lt->tm_mday; |
291 | | os2date->month = lt->tm_mon + 1; |
292 | | os2date->year = lt->tm_year - 80; |
293 | | return APR_SUCCESS; |
294 | | } |
295 | | #endif |
296 | | |
297 | | #ifdef NETWARE |
298 | | APR_DECLARE(void) apr_netware_setup_time(void) |
299 | | { |
300 | | tzset(); |
301 | | server_gmt_offset = -TZONE; |
302 | | } |
303 | | #else |
304 | | APR_DECLARE(void) apr_unix_setup_time(void) |
305 | 0 | { |
306 | | #ifdef NO_GMTOFF_IN_STRUCT_TM |
307 | | /* Precompute the offset from GMT on systems where it's not |
308 | | in struct tm. |
309 | | |
310 | | Note: This offset is normalized to be independent of daylight |
311 | | savings time; if the calculation happens to be done in a |
312 | | time/place where a daylight savings adjustment is in effect, |
313 | | the returned offset has the same value that it would have |
314 | | in the same location if daylight savings were not in effect. |
315 | | The reason for this is that the returned offset can be |
316 | | applied to a past or future timestamp in explode_time(), |
317 | | so the DST adjustment obtained from the current time won't |
318 | | necessarily be applicable. |
319 | | |
320 | | mktime() is the inverse of localtime(); so, presumably, |
321 | | passing in a struct tm made by gmtime() let's us calculate |
322 | | the true GMT offset. However, there's a catch: if daylight |
323 | | savings is in effect, gmtime()will set the tm_isdst field |
324 | | and confuse mktime() into returning a time that's offset |
325 | | by one hour. In that case, we must adjust the calculated GMT |
326 | | offset. |
327 | | |
328 | | */ |
329 | | |
330 | | struct timeval now; |
331 | | time_t t1, t2; |
332 | | struct tm t; |
333 | | |
334 | | gettimeofday(&now, NULL); |
335 | | t1 = now.tv_sec; |
336 | | t2 = 0; |
337 | | |
338 | | #if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
339 | | gmtime_r(&t1, &t); |
340 | | #else |
341 | | t = *gmtime(&t1); |
342 | | #endif |
343 | | t.tm_isdst = 0; /* we know this GMT time isn't daylight-savings */ |
344 | | t2 = mktime(&t); |
345 | | server_gmt_offset = (apr_int32_t) difftime(t1, t2); |
346 | | #endif /* NO_GMTOFF_IN_STRUCT_TM */ |
347 | 0 | } |
348 | | |
349 | | #endif |
350 | | |
351 | | /* A noop on all known Unix implementations */ |
352 | | APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p) |
353 | 0 | { |
354 | 0 | return; |
355 | 0 | } |
356 | | |
357 | | |