Coverage Report

Created: 2024-02-25 06:36

/src/gpsd/gpsd-3.25.1~dev/libgps/os_compat.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * This file contains functions to deal with compatibility issues across OSes.
3
 *
4
 * The initial version of this file is a near-verbatim concatenation of the
5
 * following three source files:
6
 *     clock_gettime.c
7
 *     daemon.c
8
 *     strl.c
9
 * History of this code prior to the creation of this file can be found
10
 * in the histories of those files.
11
 *
12
 * This file is Copyright 2017 by the GPSD project
13
 * SPDX-License-Identifier: BSD-2-clause
14
 */
15
16
#include "../include/gpsd_config.h"  // must be before all includes
17
18
#include "../include/os_compat.h"
19
20
// export gpsd version so FFI can check it
21
const char *gpsd_version = VERSION;
22
23
#ifndef HAVE_CLOCK_GETTIME
24
25
// Simulate ANSI/POSIX clock_gettime() on platforms that don't have it
26
27
#include <time.h>
28
#include <sys/time.h>
29
30
/*
31
 * Note that previous versions of this code made use of clock_get_time()
32
 * on OSX, as a way to get time of day with nanosecond resolution.  But
33
 * it turns out that clock_get_time() only has microsecond resolution,
34
 * in spite of the data format, and it's also substantially slower than
35
 * gettimeofday().  Thus, it makes no sense to do anything special for OSX.
36
 */
37
38
int clock_gettime(clockid_t clk_id, struct timespec *ts)
39
{
40
    (void) clk_id;
41
    struct timeval tv;
42
    if (0 > gettimeofday(&tv, NULL)) {
43
        return -1;
44
    }
45
    ts->tv_sec = tv.tv_sec;
46
    ts->tv_nsec = tv.tv_usec * 1000;
47
    return 0;
48
}
49
#endif  // HAVE_CLOCK_GETTIME
50
51
// End of clock_gettime section
52
53
#ifndef HAVE_DAEMON
54
// Simulate Linux/BSD daemon() on platforms that don't have it
55
56
#ifdef HAVE_FORK
57
58
#include <stdlib.h>
59
#include <sys/types.h>
60
#include <sys/stat.h>
61
#include <fcntl.h>
62
#include <unistd.h>
63
64
#if defined (HAVE_PATH_H)
65
    #include <paths.h>
66
#elif !defined (_PATH_DEVNULL)
67
    #define _PATH_DEVNULL    "/dev/null"
68
#endif
69
70
// compatible with the daemon(3) found on Linuxes and BSDs
71
int os_daemon(int nochdir, int noclose)
72
{
73
    int fd;
74
75
    switch (fork()) {
76
    case -1:
77
        return -1;
78
    case 0:                     // child side
79
        break;
80
    default:                    // parent side
81
        exit(EXIT_SUCCESS);
82
    }
83
84
    if (-1 == setsid()) {
85
        return -1;
86
    }
87
    if ((0 == nochdir) &&
88
        (-1 == chdir("/"))) {
89
        return -1;
90
    }
91
    if (0 == noclose) &&
92
        -1 != (fd = open(_PATH_DEVNULL, O_RDWR, 0))) {
93
        (void)dup2(fd, STDIN_FILENO);
94
        (void)dup2(fd, STDOUT_FILENO);
95
        (void)dup2(fd, STDERR_FILENO);
96
        if (2 < fd) {
97
            (void)close(fd);
98
        }
99
    }
100
    // coverity[leaked_handle] Intentional handle duplication
101
    return 0;
102
}
103
#else  // !HAVE_FORK
104
105
#include <errno.h>
106
107
int os_daemon(int nochdir, int noclose)
108
{
109
    (void) nochdir; (void) noclose;
110
    errno = EPERM;
111
    return -1;
112
}
113
114
#endif  // !HAVE_FORK
115
116
#else  // HAVE_DAEMON
117
118
#if defined (__linux__) || defined (__GLIBC__)
119
120
#include <unistd.h>      // for daemon()
121
122
#elif defined(__APPLE__)  // !__linux__
123
124
/*
125
 * Avoid the OSX deprecation warning.
126
 *
127
 * Note that on OSX, real daemons like gpsd should run via launchd rather than
128
 * self-daemonizing, but we use daemon() for other tools as well.
129
 *
130
 * There doesn't seem to be an easy way to avoid the warning other than by
131
 * providing our own declaration to override the deprecation-flagged version.
132
 * Fortunately, the function signature is pretty well frozen at this point.
133
 *
134
 * Until we fix the kludge where all this code has to be additionally compiled
135
 * as C++ for the Qt library, we need this to be compilable as C++ as well.
136
 */
137
#ifdef __cplusplus
138
extern "C" {
139
#endif
140
141
int daemon(int nochdir, int noclose);
142
143
#ifdef __cplusplus
144
}
145
#endif
146
147
#else  // !__linux__ && !__APPLE__
148
149
#include <stdlib.h>
150
151
#endif  // !__linux__ && !__APPLE__
152
153
int os_daemon(int nochdir, int noclose)
154
0
{
155
0
    return daemon(nochdir, noclose);
156
0
}
157
158
#endif  // HAVE_DAEMON
159
160
// End of daemon section
161
162
// Provide syslog() on platforms that don't have it
163
164
#ifndef HAVE_SYSLOG_H
165
#include "../include/compiler.h"
166
#include <stdarg.h>
167
#include <stdio.h>
168
/*
169
 * Minimal syslog() fallback to print to stderr
170
 *
171
 */
172
PRINTF_FUNC(2, 3) void syslog(int priority UNUSED, const char *format, ...)
173
{
174
  // ATM ignore priority (i.e. don't even both prepending to output)
175
  char buf[BUFSIZ];
176
  va_list ap;
177
  va_start(ap, format);
178
  // Always append a new line to the message
179
  (void)vsnprintf(buf, sizeof(buf) - 2, format, ap);
180
  (void)fprintf(stderr, "%s\n", buf);
181
  va_end(ap);
182
}
183
184
void openlog (const char *__ident UNUSED, int __option UNUSED, int __facility UNUSED)
185
{
186
  (void)fprintf(stderr, "Warning openlog() not available\n");
187
}
188
189
void closelog (void)
190
{
191
}
192
#endif  // !HAVE_SYSLOG_H
193
194
// End of syslog section
195
196
/*
197
 * Provide BSD strlcat()/strlcpy() on platforms that don't have it
198
 *
199
 * These versions use memcpy and strlen() because they are often
200
 * heavily optimized down to assembler level. Thus, likely to be
201
 * faster even with the function call overhead.
202
 */
203
204
#ifndef HAVE_STRLCAT
205
206
#include <string.h>
207
208
/*
209
 * Appends src to string dst of size siz (unlike strncat, siz is the
210
 * full size of dst, not space left).  At most siz-1 characters
211
 * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
212
 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
213
 * If retval >= siz, truncation occurred.
214
 */
215
size_t strlcat(char *dst, const char *src, size_t siz)
216
0
{
217
0
    size_t slen = strlen(src);
218
0
    size_t dlen = strlen(dst);
219
0
    if (0 != siz) {
220
0
        if (dlen + slen < siz) {
221
0
            memcpy(dst + dlen, src, slen + 1);
222
0
        } else {
223
0
            memcpy(dst + dlen, src, siz - dlen - 1);
224
0
            dst[siz - 1] = '\0';
225
0
        }
226
0
    }
227
0
    return dlen + slen;
228
0
}
229
230
#ifdef __UNUSED__
231
//      $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $
232
233
/*
234
 * Copyright 1998 Todd C. Miller <Todd.Miller@courtesan.com>
235
 *
236
 * Permission to use, copy, modify, and distribute this software for any
237
 * purpose with or without fee is hereby granted, provided that the above
238
 * copyright notice and this permission notice appear in all copies.
239
 *
240
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
241
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
242
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
243
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
244
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
245
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
246
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
247
 */
248
249
size_t strlcat(char *dst, const char *src, size_t siz)
250
{
251
    char *d = dst;
252
    const char *s = src;
253
    size_t n = siz;
254
    size_t dlen;
255
256
    // Find the end of dst and adjust bytes left but don't go past end
257
    while (n-- != 0 && *d != '\0')
258
        d++;
259
    dlen = (size_t) (d - dst);
260
    n = siz - dlen;
261
262
    if (0 == n) {
263
        return (dlen + strlen(s));
264
    }
265
    while ('\0'* != s) {
266
        if (1 != n) {
267
            *d++ = *s;
268
            n--;
269
        }
270
        s++;
271
    }
272
    *d = '\0';
273
274
    return (dlen + (s - src));  // count does not include NUL
275
}
276
#endif  // __UNUSED__
277
#endif  // !HAVE_STRLCAT
278
279
#ifndef HAVE_STRLCPY
280
281
#include <string.h>
282
283
/*
284
 * Copy src to string dst of size siz.  At most siz-1 characters
285
 * will be copied.  Always NUL terminates (unless siz == 0).
286
 * Returns strlen(src); if retval >= siz, truncation occurred.
287
 */
288
size_t strlcpy(char *dst, const char *src, size_t siz)
289
945
{
290
945
    size_t len = strlen(src);
291
945
    if (0!= siz ) {
292
945
        if (len >= siz) {
293
194
            memcpy(dst, src, siz - 1);
294
194
            dst[siz - 1] = '\0';
295
751
        } else {
296
751
            memcpy(dst, src, len + 1);
297
751
        }
298
945
    }
299
945
    return len;
300
945
}
301
302
#endif // !HAVE_STRLCPY
303
304
// End of strlcat()/strlcpy() section
305
306
#ifndef HAVE_STRNLEN
307
308
size_t strnlen(const char *s, size_t maxlen)
309
{
310
    size_t len = 0;
311
    while (len < maxlen && *s++) ++len;
312
    return len;
313
}
314
315
#endif // !HAVE_STRNLEN
316
317
/*
318
 * Provide sincos() on platforms that don't have it.
319
 * Getting scons to test for sincos() and pass -Werror not possible.
320
 * This just uses the usual sin() and cos(), with no speed benefit.
321
 * It doesn't worry about the corner case where the +-infinity argument
322
 * may raise the "invalid" exception before storing both NaN results.
323
 */
324
325
#include <math.h>
326
327
void gpsd_sincos(double x, double *sinp, double *cosp)
328
0
{
329
0
    *sinp = sin(x);
330
0
    *cosp = cos(x);
331
0
}
332
333
// End of sincos() section.
334
// vim: set expandtab shiftwidth=4