/src/httpd/srclib/apr/time/unix/time.c
Line | Count | Source |
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 | | if (tm->tm_isdst) |
51 | | return server_gmt_offset + 3600; |
52 | | return server_gmt_offset; |
53 | | #endif |
54 | 0 | } |
55 | | |
56 | | APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, |
57 | | time_t input) |
58 | 3.69k | { |
59 | 3.69k | *result = (apr_time_t)input * APR_USEC_PER_SEC; |
60 | 3.69k | return APR_SUCCESS; |
61 | 3.69k | } |
62 | | |
63 | | /* NB NB NB NB This returns GMT!!!!!!!!!! */ |
64 | | APR_DECLARE(apr_time_t) apr_time_now(void) |
65 | 553 | { |
66 | 553 | struct timeval tv; |
67 | 553 | gettimeofday(&tv, NULL); |
68 | 553 | return tv.tv_sec * (apr_time_t)APR_USEC_PER_SEC + (apr_time_t)tv.tv_usec; |
69 | 553 | } |
70 | | |
71 | | static void explode_time(apr_time_exp_t *xt, apr_time_t t, |
72 | | apr_int32_t offset, int use_localtime) |
73 | 0 | { |
74 | 0 | struct tm tm; |
75 | 0 | time_t tt = (t / APR_USEC_PER_SEC) + offset; |
76 | 0 | xt->tm_usec = t % APR_USEC_PER_SEC; |
77 | |
|
78 | 0 | #if APR_HAS_THREADS && defined (_POSIX_THREAD_SAFE_FUNCTIONS) |
79 | 0 | if (use_localtime) |
80 | 0 | localtime_r(&tt, &tm); |
81 | 0 | else |
82 | 0 | gmtime_r(&tt, &tm); |
83 | | #else |
84 | | if (use_localtime) |
85 | | tm = *localtime(&tt); |
86 | | else |
87 | | tm = *gmtime(&tt); |
88 | | #endif |
89 | |
|
90 | 0 | xt->tm_sec = tm.tm_sec; |
91 | 0 | xt->tm_min = tm.tm_min; |
92 | 0 | xt->tm_hour = tm.tm_hour; |
93 | 0 | xt->tm_mday = tm.tm_mday; |
94 | 0 | xt->tm_mon = tm.tm_mon; |
95 | 0 | xt->tm_year = tm.tm_year; |
96 | 0 | xt->tm_wday = tm.tm_wday; |
97 | 0 | xt->tm_yday = tm.tm_yday; |
98 | 0 | xt->tm_isdst = tm.tm_isdst; |
99 | 0 | xt->tm_gmtoff = get_offset(&tm); |
100 | 0 | } |
101 | | |
102 | | APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, |
103 | | apr_time_t input, apr_int32_t offs) |
104 | 0 | { |
105 | 0 | explode_time(result, input, offs, 0); |
106 | 0 | result->tm_gmtoff = offs; |
107 | 0 | return APR_SUCCESS; |
108 | 0 | } |
109 | | |
110 | | APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result, |
111 | | apr_time_t input) |
112 | 0 | { |
113 | 0 | return apr_time_exp_tz(result, input, 0); |
114 | 0 | } |
115 | | |
116 | | APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result, |
117 | | apr_time_t input) |
118 | 0 | { |
119 | | #if defined(__EMX__) |
120 | | /* EMX gcc (OS/2) has a timezone global we can use */ |
121 | | return apr_time_exp_tz(result, input, -timezone); |
122 | | #else |
123 | 0 | explode_time(result, input, 0, 1); |
124 | 0 | return APR_SUCCESS; |
125 | 0 | #endif /* __EMX__ */ |
126 | 0 | } |
127 | | |
128 | | APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t, apr_time_exp_t *xt) |
129 | 0 | { |
130 | 0 | apr_time_t year = xt->tm_year; |
131 | 0 | apr_time_t days; |
132 | 0 | static const int dayoffset[12] = |
133 | 0 | {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; |
134 | |
|
135 | 0 | if (xt->tm_mon < 0 || xt->tm_mon >= 12) |
136 | 0 | return APR_EBADDATE; |
137 | | |
138 | | /* shift new year to 1st March in order to make leap year calc easy */ |
139 | | |
140 | 0 | if (xt->tm_mon < 2) |
141 | 0 | year--; |
142 | | |
143 | | /* Find number of days since 1st March 1900 (in the Gregorian calendar). */ |
144 | |
|
145 | 0 | days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; |
146 | 0 | days += dayoffset[xt->tm_mon] + xt->tm_mday - 1; |
147 | 0 | days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */ |
148 | 0 | days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec; |
149 | |
|
150 | 0 | if (days < 0) { |
151 | 0 | return APR_EBADDATE; |
152 | 0 | } |
153 | 0 | *t = days * APR_USEC_PER_SEC + xt->tm_usec; |
154 | 0 | return APR_SUCCESS; |
155 | 0 | } |
156 | | |
157 | | APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t, |
158 | | apr_time_exp_t *xt) |
159 | 0 | { |
160 | 0 | apr_status_t status = apr_time_exp_get(t, xt); |
161 | 0 | if (status == APR_SUCCESS) |
162 | 0 | *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC; |
163 | 0 | return status; |
164 | 0 | } |
165 | | |
166 | | APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime, |
167 | | apr_time_t *aprtime) |
168 | 0 | { |
169 | 0 | (*ostime)->tv_usec = *aprtime % APR_USEC_PER_SEC; |
170 | 0 | (*ostime)->tv_sec = *aprtime / APR_USEC_PER_SEC; |
171 | 0 | return APR_SUCCESS; |
172 | 0 | } |
173 | | |
174 | | APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, |
175 | | apr_time_exp_t *aprtime) |
176 | 0 | { |
177 | 0 | (*ostime)->tm_sec = aprtime->tm_sec; |
178 | 0 | (*ostime)->tm_min = aprtime->tm_min; |
179 | 0 | (*ostime)->tm_hour = aprtime->tm_hour; |
180 | 0 | (*ostime)->tm_mday = aprtime->tm_mday; |
181 | 0 | (*ostime)->tm_mon = aprtime->tm_mon; |
182 | 0 | (*ostime)->tm_year = aprtime->tm_year; |
183 | 0 | (*ostime)->tm_wday = aprtime->tm_wday; |
184 | 0 | (*ostime)->tm_yday = aprtime->tm_yday; |
185 | 0 | (*ostime)->tm_isdst = aprtime->tm_isdst; |
186 | |
|
187 | 0 | #if defined(HAVE_STRUCT_TM_TM_GMTOFF) |
188 | 0 | (*ostime)->tm_gmtoff = aprtime->tm_gmtoff; |
189 | | #elif defined(HAVE_STRUCT_TM___TM_GMTOFF) |
190 | | (*ostime)->__tm_gmtoff = aprtime->tm_gmtoff; |
191 | | #endif |
192 | |
|
193 | 0 | return APR_SUCCESS; |
194 | 0 | } |
195 | | |
196 | | APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime, |
197 | | apr_os_imp_time_t **ostime, |
198 | | apr_pool_t *cont) |
199 | 0 | { |
200 | 0 | *aprtime = (*ostime)->tv_sec * APR_USEC_PER_SEC + (*ostime)->tv_usec; |
201 | 0 | return APR_SUCCESS; |
202 | 0 | } |
203 | | |
204 | | APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime, |
205 | | apr_os_exp_time_t **ostime, |
206 | | apr_pool_t *cont) |
207 | 0 | { |
208 | 0 | aprtime->tm_sec = (*ostime)->tm_sec; |
209 | 0 | aprtime->tm_min = (*ostime)->tm_min; |
210 | 0 | aprtime->tm_hour = (*ostime)->tm_hour; |
211 | 0 | aprtime->tm_mday = (*ostime)->tm_mday; |
212 | 0 | aprtime->tm_mon = (*ostime)->tm_mon; |
213 | 0 | aprtime->tm_year = (*ostime)->tm_year; |
214 | 0 | aprtime->tm_wday = (*ostime)->tm_wday; |
215 | 0 | aprtime->tm_yday = (*ostime)->tm_yday; |
216 | 0 | aprtime->tm_isdst = (*ostime)->tm_isdst; |
217 | |
|
218 | 0 | #if defined(HAVE_STRUCT_TM_TM_GMTOFF) |
219 | 0 | aprtime->tm_gmtoff = (*ostime)->tm_gmtoff; |
220 | | #elif defined(HAVE_STRUCT_TM___TM_GMTOFF) |
221 | | aprtime->tm_gmtoff = (*ostime)->__tm_gmtoff; |
222 | | #endif |
223 | |
|
224 | 0 | return APR_SUCCESS; |
225 | 0 | } |
226 | | |
227 | | APR_DECLARE(void) apr_sleep(apr_interval_time_t t) |
228 | 0 | { |
229 | | #ifdef OS2 |
230 | | DosSleep((t + 999) / 1000); |
231 | | #elif defined(HAVE_NANOSLEEP) |
232 | | struct timespec ts; |
233 | 0 | ts.tv_sec = t / APR_USEC_PER_SEC; |
234 | 0 | ts.tv_nsec = (t % APR_USEC_PER_SEC) * 1000; |
235 | 0 | nanosleep(&ts, NULL); |
236 | | #else |
237 | | struct timeval tv; |
238 | | tv.tv_usec = t % APR_USEC_PER_SEC; |
239 | | tv.tv_sec = t / APR_USEC_PER_SEC; |
240 | | select(0, NULL, NULL, NULL, &tv); |
241 | | #endif |
242 | 0 | } |
243 | | |
244 | | #ifdef OS2 |
245 | | APR_DECLARE(apr_status_t) apr_os2_time_to_apr_time(apr_time_t *result, |
246 | | FDATE os2date, |
247 | | FTIME os2time) |
248 | | { |
249 | | struct tm tmpdate; |
250 | | |
251 | | memset(&tmpdate, 0, sizeof(tmpdate)); |
252 | | tmpdate.tm_hour = os2time.hours; |
253 | | tmpdate.tm_min = os2time.minutes; |
254 | | tmpdate.tm_sec = os2time.twosecs * 2; |
255 | | |
256 | | tmpdate.tm_mday = os2date.day; |
257 | | tmpdate.tm_mon = os2date.month - 1; |
258 | | tmpdate.tm_year = os2date.year + 80; |
259 | | tmpdate.tm_isdst = -1; |
260 | | |
261 | | *result = mktime(&tmpdate) * APR_USEC_PER_SEC; |
262 | | return APR_SUCCESS; |
263 | | } |
264 | | |
265 | | APR_DECLARE(apr_status_t) apr_apr_time_to_os2_time(FDATE *os2date, |
266 | | FTIME *os2time, |
267 | | apr_time_t aprtime) |
268 | | { |
269 | | time_t ansitime = aprtime / APR_USEC_PER_SEC; |
270 | | struct tm *lt; |
271 | | lt = localtime(&ansitime); |
272 | | os2time->hours = lt->tm_hour; |
273 | | os2time->minutes = lt->tm_min; |
274 | | os2time->twosecs = lt->tm_sec / 2; |
275 | | |
276 | | os2date->day = lt->tm_mday; |
277 | | os2date->month = lt->tm_mon + 1; |
278 | | os2date->year = lt->tm_year - 80; |
279 | | return APR_SUCCESS; |
280 | | } |
281 | | #endif |
282 | | |
283 | | APR_DECLARE(void) apr_unix_setup_time(void) |
284 | 0 | { |
285 | | #ifdef NO_GMTOFF_IN_STRUCT_TM |
286 | | /* Precompute the offset from GMT on systems where it's not |
287 | | in struct tm. |
288 | | |
289 | | Note: This offset is normalized to be independent of daylight |
290 | | savings time; if the calculation happens to be done in a |
291 | | time/place where a daylight savings adjustment is in effect, |
292 | | the returned offset has the same value that it would have |
293 | | in the same location if daylight savings were not in effect. |
294 | | The reason for this is that the returned offset can be |
295 | | applied to a past or future timestamp in explode_time(), |
296 | | so the DST adjustment obtained from the current time won't |
297 | | necessarily be applicable. |
298 | | |
299 | | mktime() is the inverse of localtime(); so, presumably, |
300 | | passing in a struct tm made by gmtime() let's us calculate |
301 | | the true GMT offset. However, there's a catch: if daylight |
302 | | savings is in effect, gmtime()will set the tm_isdst field |
303 | | and confuse mktime() into returning a time that's offset |
304 | | by one hour. In that case, we must adjust the calculated GMT |
305 | | offset. |
306 | | |
307 | | */ |
308 | | |
309 | | struct timeval now; |
310 | | time_t t1, t2; |
311 | | struct tm t; |
312 | | |
313 | | gettimeofday(&now, NULL); |
314 | | t1 = now.tv_sec; |
315 | | t2 = 0; |
316 | | |
317 | | #if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
318 | | gmtime_r(&t1, &t); |
319 | | #else |
320 | | t = *gmtime(&t1); |
321 | | #endif |
322 | | t.tm_isdst = 0; /* we know this GMT time isn't daylight-savings */ |
323 | | t2 = mktime(&t); |
324 | | server_gmt_offset = (apr_int32_t) difftime(t1, t2); |
325 | | #endif /* NO_GMTOFF_IN_STRUCT_TM */ |
326 | 0 | } |
327 | | |
328 | | |
329 | | /* A noop on all known Unix implementations */ |
330 | | APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p) |
331 | 0 | { |
332 | 0 | return; |
333 | 0 | } |
334 | | |
335 | | |