/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 |