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