Coverage Report

Created: 2023-03-26 06:28

/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