~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/time/win32/time.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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 "win32/apr_arch_atime.h"
 
18
#include "apr_time.h"
 
19
#include "apr_general.h"
 
20
#include "apr_lib.h"
 
21
#include "apr_portable.h"
 
22
#if APR_HAVE_TIME_H
 
23
#include <time.h>
 
24
#endif
 
25
#if APR_HAVE_ERRNO_H
 
26
#include <errno.h>
 
27
#endif
 
28
#include <string.h>
 
29
#include <winbase.h>
 
30
#include "apr_arch_misc.h"
 
31
 
 
32
/* Leap year is any year divisible by four, but not by 100 unless also
 
33
 * divisible by 400
 
34
 */
 
35
#define IsLeapYear(y) ((!(y % 4)) ? (((!(y % 400)) && (y % 100)) ? 1 : 0) : 0)
 
36
 
 
37
static DWORD get_local_timezone(TIME_ZONE_INFORMATION **tzresult)
 
38
{
 
39
    static TIME_ZONE_INFORMATION tz;
 
40
    static DWORD result;
 
41
    static int init = 0;
 
42
 
 
43
    if (!init) {
 
44
        result = GetTimeZoneInformation(&tz);
 
45
        init = 1;
 
46
    }
 
47
 
 
48
    *tzresult = &tz;
 
49
    return result;
 
50
}
 
51
 
 
52
static void SystemTimeToAprExpTime(apr_time_exp_t *xt, SYSTEMTIME *tm)
 
53
{
 
54
    static const int dayoffset[12] =
 
55
    {0, 31, 59, 90, 120, 151, 182, 212, 243, 273, 304, 334};
 
56
 
 
57
    /* Note; the caller is responsible for filling in detailed tm_usec,
 
58
     * tm_gmtoff and tm_isdst data when applicable.
 
59
     */
 
60
    xt->tm_usec = tm->wMilliseconds * 1000;
 
61
    xt->tm_sec  = tm->wSecond;
 
62
    xt->tm_min  = tm->wMinute;
 
63
    xt->tm_hour = tm->wHour;
 
64
    xt->tm_mday = tm->wDay;
 
65
    xt->tm_mon  = tm->wMonth - 1;
 
66
    xt->tm_year = tm->wYear - 1900;
 
67
    xt->tm_wday = tm->wDayOfWeek;
 
68
    xt->tm_yday = dayoffset[xt->tm_mon] + (tm->wDay - 1);
 
69
    xt->tm_isdst = 0;
 
70
    xt->tm_gmtoff = 0;
 
71
 
 
72
    /* If this is a leap year, and we're past the 28th of Feb. (the
 
73
     * 58th day after Jan. 1), we'll increment our tm_yday by one.
 
74
     */
 
75
    if (IsLeapYear(tm->wYear) && (xt->tm_yday > 58))
 
76
        xt->tm_yday++;
 
77
}
 
78
 
 
79
APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, 
 
80
                                                    time_t input)
 
81
{
 
82
    *result = (apr_time_t) input * APR_USEC_PER_SEC;
 
83
    return APR_SUCCESS;
 
84
}
 
85
 
 
86
/* Return micro-seconds since the Unix epoch (jan. 1, 1970) UTC */
 
87
APR_DECLARE(apr_time_t) apr_time_now(void)
 
88
{
 
89
    LONGLONG aprtime = 0;
 
90
    FILETIME time;
 
91
#ifndef _WIN32_WCE
 
92
    GetSystemTimeAsFileTime(&time);
 
93
#else
 
94
    SYSTEMTIME st;
 
95
    GetSystemTime(&st);
 
96
    SystemTimeToFileTime(&st, &time);
 
97
#endif
 
98
    FileTimeToAprTime(&aprtime, &time);
 
99
    return aprtime; 
 
100
}
 
101
 
 
102
APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result,
 
103
                                           apr_time_t input)
 
104
{
 
105
    FILETIME ft;
 
106
    SYSTEMTIME st;
 
107
    AprTimeToFileTime(&ft, input);
 
108
    FileTimeToSystemTime(&ft, &st);
 
109
    /* The Platform SDK documents that SYSTEMTIME/FILETIME are
 
110
     * generally UTC, so no timezone info needed
 
111
     */
 
112
    SystemTimeToAprExpTime(result, &st);
 
113
    result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
 
114
    return APR_SUCCESS;
 
115
}
 
116
 
 
117
APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, 
 
118
                                          apr_time_t input, 
 
119
                                          apr_int32_t offs)
 
120
{
 
121
    FILETIME ft;
 
122
    SYSTEMTIME st;
 
123
    AprTimeToFileTime(&ft, input + (offs *  APR_USEC_PER_SEC));
 
124
    FileTimeToSystemTime(&ft, &st);
 
125
    /* The Platform SDK documents that SYSTEMTIME/FILETIME are
 
126
     * generally UTC, so we will simply note the offs used.
 
127
     */
 
128
    SystemTimeToAprExpTime(result, &st);
 
129
    result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
 
130
    result->tm_gmtoff = offs;
 
131
    return APR_SUCCESS;
 
132
}
 
133
 
 
134
APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result,
 
135
                                          apr_time_t input)
 
136
{
 
137
    SYSTEMTIME st;
 
138
    FILETIME ft, localft;
 
139
 
 
140
    AprTimeToFileTime(&ft, input);
 
141
 
 
142
#if APR_HAS_UNICODE_FS
 
143
    IF_WIN_OS_IS_UNICODE
 
144
    {
 
145
        TIME_ZONE_INFORMATION *tz;
 
146
        SYSTEMTIME localst;
 
147
        apr_time_t localtime;
 
148
 
 
149
        get_local_timezone(&tz);
 
150
 
 
151
        FileTimeToSystemTime(&ft, &st);
 
152
 
 
153
        /* The Platform SDK documents that SYSTEMTIME/FILETIME are
 
154
         * generally UTC.  We use SystemTimeToTzSpecificLocalTime
 
155
         * because FileTimeToLocalFileFime is documented that the
 
156
         * resulting time local file time would have DST relative
 
157
         * to the *present* date, not the date converted.
 
158
         */
 
159
        SystemTimeToTzSpecificLocalTime(tz, &st, &localst);
 
160
        SystemTimeToAprExpTime(result, &localst);
 
161
        result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
 
162
 
 
163
 
 
164
        /* Recover the resulting time as an apr time and use the
 
165
         * delta for gmtoff in seconds (and ignore msec rounding) 
 
166
         */
 
167
        SystemTimeToFileTime(&localst, &localft);
 
168
        FileTimeToAprTime(&localtime, &localft);
 
169
        result->tm_gmtoff = (int)apr_time_sec(localtime) 
 
170
                          - (int)apr_time_sec(input);
 
171
 
 
172
        /* To compute the dst flag, we compare the expected 
 
173
         * local (standard) timezone bias to the delta.
 
174
         * [Note, in war time or double daylight time the
 
175
         * resulting tm_isdst is, desireably, 2 hours]
 
176
         */
 
177
        result->tm_isdst = (result->tm_gmtoff / 3600)
 
178
                         - (-(tz->Bias + tz->StandardBias) / 60);
 
179
    }
 
180
#endif
 
181
#if APR_HAS_ANSI_FS
 
182
    ELSE_WIN_OS_IS_ANSI
 
183
    {
 
184
        TIME_ZONE_INFORMATION tz;
 
185
        /* XXX: This code is simply *wrong*.  The time converted will always
 
186
         * map to the *now current* status of daylight savings time.
 
187
         */
 
188
 
 
189
        FileTimeToLocalFileTime(&ft, &localft);
 
190
        FileTimeToSystemTime(&localft, &st);
 
191
        SystemTimeToAprExpTime(result, &st);
 
192
        result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC);
 
193
 
 
194
        switch (GetTimeZoneInformation(&tz)) {
 
195
            case TIME_ZONE_ID_UNKNOWN:
 
196
                result->tm_isdst = 0;
 
197
                /* Bias = UTC - local time in minutes
 
198
                 * tm_gmtoff is seconds east of UTC
 
199
                 */
 
200
                result->tm_gmtoff = tz.Bias * -60;
 
201
                break;
 
202
            case TIME_ZONE_ID_STANDARD:
 
203
                result->tm_isdst = 0;
 
204
                result->tm_gmtoff = (tz.Bias + tz.StandardBias) * -60;
 
205
                break;
 
206
            case TIME_ZONE_ID_DAYLIGHT:
 
207
                result->tm_isdst = 1;
 
208
                result->tm_gmtoff = (tz.Bias + tz.DaylightBias) * -60;
 
209
                break;
 
210
            default:
 
211
                /* noop */;
 
212
        }
 
213
    }
 
214
#endif
 
215
 
 
216
    return APR_SUCCESS;
 
217
}
 
218
 
 
219
APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t,
 
220
                                           apr_time_exp_t *xt)
 
221
{
 
222
    apr_time_t year = xt->tm_year;
 
223
    apr_time_t days;
 
224
    static const int dayoffset[12] =
 
225
    {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
 
226
 
 
227
    /* shift new year to 1st March in order to make leap year calc easy */
 
228
 
 
229
    if (xt->tm_mon < 2)
 
230
        year--;
 
231
 
 
232
    /* Find number of days since 1st March 1900 (in the Gregorian calendar). */
 
233
 
 
234
    days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4;
 
235
    days += dayoffset[xt->tm_mon] + xt->tm_mday - 1;
 
236
    days -= 25508;              /* 1 jan 1970 is 25508 days since 1 mar 1900 */
 
237
 
 
238
    days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec;
 
239
 
 
240
    if (days < 0) {
 
241
        return APR_EBADDATE;
 
242
    }
 
243
    *t = days * APR_USEC_PER_SEC + xt->tm_usec;
 
244
    return APR_SUCCESS;
 
245
}
 
246
 
 
247
APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t,
 
248
                                               apr_time_exp_t *xt)
 
249
{
 
250
    apr_status_t status = apr_time_exp_get(t, xt);
 
251
    if (status == APR_SUCCESS)
 
252
        *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC;
 
253
    return status;
 
254
}
 
255
 
 
256
APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime,
 
257
                                              apr_time_t *aprtime)
 
258
{
 
259
    /* TODO: Consider not passing in pointer to apr_time_t (e.g., call by value) */
 
260
    AprTimeToFileTime(*ostime, *aprtime);
 
261
    return APR_SUCCESS;
 
262
}
 
263
 
 
264
APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, 
 
265
                                              apr_time_exp_t *aprexptime)
 
266
{
 
267
    (*ostime)->wYear = aprexptime->tm_year + 1900;
 
268
    (*ostime)->wMonth = aprexptime->tm_mon + 1;
 
269
    (*ostime)->wDayOfWeek = aprexptime->tm_wday;
 
270
    (*ostime)->wDay = aprexptime->tm_mday;
 
271
    (*ostime)->wHour = aprexptime->tm_hour;
 
272
    (*ostime)->wMinute = aprexptime->tm_min;
 
273
    (*ostime)->wSecond = aprexptime->tm_sec;
 
274
    (*ostime)->wMilliseconds = aprexptime->tm_usec / 1000;
 
275
    return APR_SUCCESS;
 
276
}
 
277
 
 
278
APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime,
 
279
                                              apr_os_imp_time_t **ostime,
 
280
                                              apr_pool_t *cont)
 
281
{
 
282
    /* XXX: sanity failure, what is file time, gmt or local ?
 
283
     */
 
284
    FileTimeToAprTime(aprtime, *ostime);
 
285
    return APR_SUCCESS;
 
286
}
 
287
 
 
288
APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime,
 
289
                                              apr_os_exp_time_t **ostime,
 
290
                                              apr_pool_t *cont)
 
291
{
 
292
    /* The Platform SDK documents that SYSTEMTIME/FILETIME are
 
293
     * generally UTC, so no timezone info needed
 
294
     */
 
295
    SystemTimeToAprExpTime(aprtime, *ostime);
 
296
    return APR_SUCCESS;
 
297
}
 
298
 
 
299
APR_DECLARE(void) apr_sleep(apr_interval_time_t t)
 
300
{
 
301
    /* One of the few sane situations for a cast, Sleep
 
302
     * is in ms, not us, and passed as a DWORD value
 
303
     */
 
304
    Sleep((DWORD)(t / 1000));
 
305
}
 
306
 
 
307
 
 
308
static apr_status_t clock_restore(void *unsetres)
 
309
{
 
310
    ULONG newRes;
 
311
    SetTimerResolution((ULONG)unsetres, FALSE, &newRes);
 
312
    return APR_SUCCESS;
 
313
}
 
314
 
 
315
APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p)
 
316
{
 
317
    ULONG newRes;
 
318
    /* Timer resolution is stated in 100ns units.  Note that TRUE requests the
 
319
     * new clock resolution, FALSE above releases the request.
 
320
     */
 
321
    if (SetTimerResolution(10000, TRUE, &newRes) == 0 /* STATUS_SUCCESS */) {
 
322
        /* register the cleanup... */
 
323
        apr_pool_cleanup_register(p, (void*)10000, clock_restore,
 
324
                                  apr_pool_cleanup_null);
 
325
    }
 
326
}