Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sal/osl/unx/time.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sal/config.h>
21
22
#include "saltime.hxx"
23
24
#include <osl/time.h>
25
#include <time.h>
26
#include <unistd.h>
27
28
#ifdef __MACH__
29
#include <mach/clock.h>
30
#include <mach/mach.h>
31
#endif
32
33
/* FIXME: detection should be done in configure script */
34
#if defined(MACOSX) || defined(IOS) || defined(FREEBSD) || defined(NETBSD) || \
35
    defined(LINUX) || defined(OPENBSD) || defined(DRAGONFLY)
36
#define STRUCT_TM_HAS_GMTOFF 1
37
38
#elif defined(__sun)
39
#define HAS_ALTZONE 1
40
#endif
41
42
#ifdef __MACH__
43
typedef mach_timespec_t osl_time_t;
44
#else
45
#if defined(_POSIX_TIMERS)
46
#define USE_CLOCK_GETTIME
47
typedef struct timespec osl_time_t;
48
#else
49
typedef struct timeval osl_time_t;
50
#endif
51
#endif
52
static osl_time_t startTime;
53
54
sal_Bool SAL_CALL osl_getSystemTime(TimeValue* tv)
55
9.15k
{
56
#ifdef __MACH__
57
    clock_serv_t cclock;
58
    mach_timespec_t mts;
59
60
    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
61
    clock_get_time(cclock, &mts);
62
    mach_port_deallocate(mach_task_self(), cclock);
63
64
    tv->Seconds = mts.tv_sec;
65
    tv->Nanosec = mts.tv_nsec;
66
#else
67
9.15k
    int res;
68
9.15k
    osl_time_t tp;
69
9.15k
#if defined(USE_CLOCK_GETTIME)
70
9.15k
    res = clock_gettime(CLOCK_REALTIME, &tp);
71
#else
72
    res = gettimeofday(&tp, NULL);
73
#endif
74
75
9.15k
    if (res != 0)
76
0
    {
77
0
        return false;
78
0
    }
79
80
9.15k
    tv->Seconds = tp.tv_sec;
81
9.15k
    #if defined(USE_CLOCK_GETTIME)
82
9.15k
    tv->Nanosec = tp.tv_nsec;
83
    #else
84
    tv->Nanosec = tp.tv_usec * 1000;
85
    #endif
86
9.15k
#endif
87
9.15k
    return true;
88
9.15k
}
89
90
sal_Bool SAL_CALL osl_getDateTimeFromTimeValue( const TimeValue* pTimeVal, oslDateTime* pDateTime )
91
132k
{
92
132k
    struct tm *pSystemTime;
93
132k
    struct tm tmBuf;
94
132k
    time_t atime;
95
96
132k
    atime = static_cast<time_t>(pTimeVal->Seconds);
97
98
    /* Convert time from type time_t to struct tm */
99
132k
    pSystemTime = gmtime_r( &atime, &tmBuf );
100
101
    /* Convert struct tm to struct oslDateTime */
102
132k
    if ( pSystemTime != nullptr )
103
132k
    {
104
132k
        pDateTime->NanoSeconds  =   pTimeVal->Nanosec;
105
132k
        pDateTime->Seconds      =   pSystemTime->tm_sec;
106
132k
        pDateTime->Minutes      =   pSystemTime->tm_min;
107
132k
        pDateTime->Hours        =   pSystemTime->tm_hour;
108
132k
        pDateTime->Day          =   pSystemTime->tm_mday;
109
132k
        pDateTime->DayOfWeek    =   pSystemTime->tm_wday;
110
132k
        pDateTime->Month        =   pSystemTime->tm_mon + 1;
111
132k
        pDateTime->Year         =   pSystemTime->tm_year  + 1900;
112
113
132k
        return true;
114
132k
    }
115
116
0
    return false;
117
132k
}
118
119
sal_Bool SAL_CALL osl_getTimeValueFromDateTime( const oslDateTime* pDateTime, TimeValue* pTimeVal )
120
18
{
121
18
    struct tm   aTime;
122
18
    time_t      nSeconds;
123
124
    /* Convert struct oslDateTime to struct tm */
125
18
    aTime.tm_sec  = pDateTime->Seconds;
126
18
    aTime.tm_min  = pDateTime->Minutes;
127
18
    aTime.tm_hour = pDateTime->Hours;
128
18
    aTime.tm_mday = pDateTime->Day;
129
130
18
    if ( pDateTime->Month > 0 )
131
18
        aTime.tm_mon = pDateTime->Month - 1;
132
0
    else
133
0
        return false;
134
135
18
    aTime.tm_year = pDateTime->Year - 1900;
136
137
18
    aTime.tm_isdst = -1;
138
18
    aTime.tm_wday  = 0;
139
18
    aTime.tm_yday  = 0;
140
141
18
#if defined(STRUCT_TM_HAS_GMTOFF)
142
18
    aTime.tm_gmtoff = 0;
143
18
#endif
144
145
    /* Convert time to calendar value */
146
18
    nSeconds = mktime( &aTime );
147
148
    /*
149
     * mktime expects the struct tm to be in local timezone, so we have to adjust
150
     * the returned value to be timezone neutral.
151
     */
152
153
18
    if ( nSeconds != time_t(-1) )
154
18
    {
155
18
        time_t bias;
156
157
        /* timezone corrections */
158
18
        tzset();
159
160
18
#if defined(STRUCT_TM_HAS_GMTOFF)
161
        /* members of struct tm are corrected by mktime */
162
18
        bias = 0 - aTime.tm_gmtoff;
163
164
#elif defined(HAS_ALTZONE)
165
        /* check if daylight saving time is in effect */
166
        bias = aTime.tm_isdst > 0 ? altzone : timezone;
167
#else
168
        /* expect daylight saving time to be one hour */
169
        bias = aTime.tm_isdst > 0 ? timezone - 3600 : timezone;
170
#endif
171
172
        // coverity[store_truncates_time_t] - TODO: sal_uInt32 TimeValue::Seconds is only large
173
        // enough for integer time_t values < 2^32 representing dates until year 2106:
174
18
        pTimeVal->Seconds = nSeconds;
175
18
        pTimeVal->Nanosec = pDateTime->NanoSeconds;
176
177
18
        if ( nSeconds > bias )
178
18
            pTimeVal->Seconds -= bias;
179
180
18
        return true;
181
18
    }
182
183
0
    return false;
184
18
}
185
186
sal_Bool SAL_CALL osl_getLocalTimeFromSystemTime( const TimeValue* pSystemTimeVal, TimeValue* pLocalTimeVal )
187
137k
{
188
137k
    struct tm *pLocalTime;
189
137k
    struct tm tmBuf;
190
137k
    time_t bias;
191
137k
    time_t atime;
192
193
137k
    atime = static_cast<time_t>(pSystemTimeVal->Seconds);
194
137k
    pLocalTime = localtime_r( &atime, &tmBuf );
195
196
137k
#if defined(STRUCT_TM_HAS_GMTOFF)
197
    /* members of struct tm are corrected by mktime */
198
137k
    bias = -pLocalTime->tm_gmtoff;
199
200
#elif defined(HAS_ALTZONE)
201
    /* check if daylight saving time is in effect */
202
    bias = pLocalTime->tm_isdst > 0 ? altzone : timezone;
203
#else
204
    /* expect daylight saving time to be one hour */
205
    bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone;
206
#endif
207
208
137k
    if ( static_cast<sal_Int64>(pSystemTimeVal->Seconds) > bias )
209
137k
    {
210
137k
        pLocalTimeVal->Seconds = pSystemTimeVal->Seconds - bias;
211
137k
        pLocalTimeVal->Nanosec = pSystemTimeVal->Nanosec;
212
213
137k
        return true;
214
137k
    }
215
216
0
    return false;
217
137k
}
218
219
sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime( const TimeValue* pLocalTimeVal, TimeValue* pSystemTimeVal )
220
0
{
221
0
    struct tm *pLocalTime;
222
0
    struct tm tmBuf;
223
0
    time_t bias;
224
0
    time_t atime;
225
226
0
    atime = static_cast<time_t>(pLocalTimeVal->Seconds);
227
228
    /* Convert atime, which is a local time, to its GMT equivalent. Then, get
229
     * the timezone offset for the local time for the GMT equivalent time. Note
230
     * that we cannot directly use local time to determine the timezone offset
231
     * because GMT is the only reliable time that we can determine timezone
232
     * offset from.
233
     */
234
235
0
    atime = mktime( gmtime_r( &atime, &tmBuf ) );
236
0
    pLocalTime = localtime_r( &atime, &tmBuf );
237
238
0
#if defined(STRUCT_TM_HAS_GMTOFF)
239
    /* members of struct tm are corrected by mktime */
240
0
    bias = 0 - pLocalTime->tm_gmtoff;
241
242
#elif defined(HAS_ALTZONE)
243
    /* check if daylight saving time is in effect */
244
    bias = pLocalTime->tm_isdst > 0 ? altzone : timezone;
245
#else
246
    /* expect daylight saving time to be one hour */
247
    bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone;
248
#endif
249
250
0
    if ( static_cast<sal_Int64>(pLocalTimeVal->Seconds) + bias > 0 )
251
0
    {
252
0
        pSystemTimeVal->Seconds = pLocalTimeVal->Seconds + bias;
253
0
        pSystemTimeVal->Nanosec = pLocalTimeVal->Nanosec;
254
255
0
        return true;
256
0
    }
257
258
0
    return false;
259
0
}
260
261
void sal_initGlobalTimer()
262
0
{
263
#ifdef __MACH__
264
  clock_serv_t cclock;
265
266
  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
267
  clock_get_time(cclock, &startTime);
268
  mach_port_deallocate(mach_task_self(), cclock);
269
#else /* ! (MACOSX || IOS) */
270
0
#if defined(USE_CLOCK_GETTIME)
271
0
  clock_gettime(CLOCK_REALTIME, &startTime);
272
#else /* Ndef USE_CLOCK_GETTIME */
273
  gettimeofday( &startTime, NULL );
274
#endif /* NDef USE_CLOCK_GETTIME */
275
0
#endif /* ! (MACOSX || IOS) */
276
0
}
277
278
sal_uInt32 SAL_CALL osl_getGlobalTimer()
279
8.31k
{
280
8.31k
    sal_uInt32 nSeconds;
281
282
#ifdef __MACH__
283
    clock_serv_t cclock;
284
    mach_timespec_t currentTime;
285
286
    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
287
    clock_get_time(cclock, &currentTime);
288
    mach_port_deallocate(mach_task_self(), cclock);
289
290
    nSeconds = ( currentTime.tv_sec - startTime.tv_sec );
291
    nSeconds = ( nSeconds * 1000 ) + static_cast<long>(( currentTime.tv_nsec - startTime.tv_nsec) / 1000000 );
292
#else
293
8.31k
    osl_time_t currentTime;
294
295
8.31k
#if defined(USE_CLOCK_GETTIME)
296
8.31k
    clock_gettime(CLOCK_REALTIME, &currentTime);
297
#else
298
    gettimeofday( &currentTime, NULL );
299
#endif
300
301
8.31k
    nSeconds = static_cast<sal_uInt32>( currentTime.tv_sec - startTime.tv_sec );
302
8.31k
#if defined(USE_CLOCK_GETTIME)
303
8.31k
    nSeconds = ( nSeconds * 1000 ) + static_cast<long>(( currentTime.tv_nsec - startTime.tv_nsec) / 1000000 );
304
#else
305
    nSeconds = ( nSeconds * 1000 ) + (long) (( currentTime.tv_usec - startTime.tv_usec) / 1000 );
306
#endif
307
8.31k
#endif
308
8.31k
    return nSeconds;
309
8.31k
}
310
311
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */