• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aremmell / libsir / 501

07 Sep 2023 03:38PM UTC coverage: 94.721% (-0.06%) from 94.782%
501

push

gitlab-ci

web-flow
fix logic error in _sir_andeql, rename to _sir_eqland (#267)

307 of 307 new or added lines in 4 files covered. (100.0%)

3104 of 3277 relevant lines covered (94.72%)

616870.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.09
/src/sirinternal.c
1
/*
2
 * sirinternal.c
3
 *
4
 * Author:    Ryan M. Lederman <lederman@gmail.com>
5
 * Copyright: Copyright (c) 2018-2023
6
 * Version:   2.2.3
7
 * License:   The MIT License (MIT)
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
10
 * this software and associated documentation files (the "Software"), to deal in
11
 * the Software without restriction, including without limitation the rights to
12
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13
 * the Software, and to permit persons to whom the Software is furnished to do so,
14
 * subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
#include "sir/internal.h"
27
#include "sir/console.h"
28
#include "sir/defaults.h"
29
#include "sir/filecache.h"
30
#include "sir/plugins.h"
31
#include "sir/textstyle.h"
32
#include "sir/filesystem.h"
33
#include "sir/mutex.h"
34

35
#if defined(__WIN__)
36
# if defined(__EMBARCADEROC__) && defined(_WIN64)
37
#  pragma comment(lib, "ws2_32.a")
38
# else
39
#  pragma comment(lib, "ws2_32.lib")
40
# endif
41
#endif
42

43
static sirconfig _sir_cfg      = {0};
44
static sirfcache _sir_fc       = {0};
45
static sir_plugincache _sir_pc = {0};
46

47
static sir_mutex cfg_mutex  = SIR_MUTEX_INIT;
48
static sir_mutex fc_mutex   = SIR_MUTEX_INIT;
49
static sir_mutex pc_mutex   = SIR_MUTEX_INIT;
50
static sir_mutex ts_mutex   = SIR_MUTEX_INIT;
51
static sir_once static_once = SIR_ONCE_INIT;
52

53
#if defined(__WIN__)
54
static LARGE_INTEGER _sir_perfcntr_freq = {0};
55
#endif
56

57
#if defined(__HAVE_ATOMIC_H__)
58
static atomic_uint_fast32_t _sir_magic;
59
#else
60
static volatile uint32_t _sir_magic = 0U;
61
#endif
62

63
static _sir_thread_local char _sir_tid[SIR_MAXPID]   = {0};
64
static _sir_thread_local sir_time _sir_last_thrd_chk = {0};
65

66
bool _sir_makeinit(sirinit* si) {
56✔
67
    bool retval = _sir_validptr(si);
56✔
68

69
    if (retval) {
56✔
70
        memset(si, 0, sizeof(sirinit));
50✔
71

72
        si->d_stdout.opts   = SIRO_DEFAULT;
56✔
73
        si->d_stdout.levels = SIRL_DEFAULT;
56✔
74

75
        si->d_stderr.opts   = SIRO_DEFAULT;
56✔
76
        si->d_stderr.levels = SIRL_DEFAULT;
56✔
77

78
#if !defined(SIR_NO_SYSTEM_LOGGERS)
79
        si->d_syslog.opts   = SIRO_DEFAULT;
43✔
80
        si->d_syslog.levels = SIRL_DEFAULT;
43✔
81
#else
82
        si->d_syslog.opts   = SIRO_MSGONLY;
13✔
83
        si->d_syslog.levels = SIRL_NONE;
13✔
84
#endif
85
    }
86

87
    return retval;
56✔
88
}
89

90
bool _sir_init(sirinit* si) {
824✔
91
    (void)_sir_seterror(_SIR_E_NOERROR);
824✔
92

93
    /* can only fail on Windows. */
94
    bool once_init = _sir_once(&static_once, _sir_init_static_once);
824✔
95
#if !defined(__WIN__)
96
    SIR_UNUSED(once_init);
97
#else
98
    if (!once_init) {
99
        _sir_selflog("error: static data initialization routine failed!");
100
        return false;
101
    }
102
#endif
103

104
    if (!_sir_validptr(si))
824✔
105
        return false;
19✔
106

107
#if defined(__HAVE_ATOMIC_H__)
108
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
802✔
109
#else
110
    if (_SIR_MAGIC == _sir_magic)
111
#endif
112
        return _sir_seterror(_SIR_E_ALREADY);
23✔
113

114
    _sir_defaultlevels(&si->d_stdout.levels, sir_stdout_def_lvls);
779✔
115
    _sir_defaultopts(&si->d_stdout.opts, sir_stdout_def_opts);
779✔
116

117
    _sir_defaultlevels(&si->d_stderr.levels, sir_stderr_def_lvls);
779✔
118
    _sir_defaultopts(&si->d_stderr.opts, sir_stderr_def_opts);
779✔
119

120
#if !defined(SIR_NO_SYSTEM_LOGGERS)
121
    _sir_defaultlevels(&si->d_syslog.levels, sir_syslog_def_lvls);
587✔
122
    _sir_defaultopts(&si->d_syslog.opts, sir_syslog_def_opts);
587✔
123
#endif
124

125
    if (!_sir_init_sanity(si))
779✔
126
        return false;
19✔
127

128
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
757✔
129

130
#if !defined(__WIN__)
131
    tzset();
757✔
132
#endif
133

134
#if defined(__HAVE_ATOMIC_H__)
135
    atomic_store(&_sir_magic, _SIR_MAGIC);
757✔
136
#else
137
    _sir_magic = _SIR_MAGIC;
138
#endif
139

140
#if defined(__WIN__)
141
    _sir_initialize_stdio();
142
#endif
143

144
    _sir_setcolormode(SIRCM_16);
757✔
145

146
    if (!_sir_resettextstyles())
757✔
147
        _sir_selflog("error: failed to reset text styles!");
×
148

149
    memset(&_cfg->state, 0, sizeof(_cfg->state));
757✔
150
    memcpy(&_cfg->si, si, sizeof(sirinit));
757✔
151

152
    /* forcibly null-terminate the process name. */
153
    _cfg->si.name[SIR_MAXNAME - 1] = '\0';
757✔
154

155
    /* Store PID. */
156
    _cfg->state.pid = _sir_getpid();
757✔
157

158
    (void)snprintf(_cfg->state.pidbuf, SIR_MAXPID, SIR_PIDFORMAT,
757✔
159
        PID_CAST _cfg->state.pid);
160

161
#if !defined(SIR_NO_SYSTEM_LOGGERS)
162
    /* initialize system logger. */
163
    _sir_syslog_reset(&_cfg->si.d_syslog);
571✔
164

165
    if (_cfg->si.d_syslog.levels != SIRL_NONE &&
583✔
166
        !_sir_syslog_init(_cfg->si.name, &_cfg->si.d_syslog)) {
96✔
167
        _sir_selflog("failed to initialize system logger!");
×
168
    }
169
#endif
170

171
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
757✔
172

173
    return true;
757✔
174
}
175

176
bool _sir_cleanup(void) {
779✔
177
    if (!_sir_sanity())
779✔
178
        return false;
19✔
179

180
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
757✔
181
    bool cleanup   = true;
652✔
182
    bool destroyfc = _sir_fcache_destroy(sfc);
757✔
183
    SIR_ASSERT(destroyfc);
722✔
184

185
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
757✔
186
    _sir_eqland(cleanup, destroyfc);
652✔
187

188
#if !defined(SIR_NO_PLUGINS)
189
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
714✔
190
    bool destroypc = _sir_plugin_cache_destroy(spc);
714✔
191
    SIR_ASSERT(destroypc);
679✔
192
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
714✔
193
    _sir_eqland(cleanup, destroypc);
714✔
194
#endif
195

196
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
757✔
197

198
#if !defined(SIR_NO_SYSTEM_LOGGERS)
199
    if (!_sir_syslog_close(&_cfg->si.d_syslog)) {
571✔
200
        cleanup = false;
×
201
        _sir_selflog("error: failed to close system logger!");
×
202
    }
203

204
    _sir_syslog_reset(&_cfg->si.d_syslog);
571✔
205
#endif
206

207
    if (!_sir_resettextstyles()) {
757✔
208
        cleanup = false;
×
209
        _sir_selflog("error: failed to reset text styles!");
×
210
    }
211

212
#if defined(__HAVE_ATOMIC_H__)
213
    atomic_store(&_sir_magic, 0);
757✔
214
#else
215
    _sir_magic = 0U;
216
#endif
217

218
    memset(_cfg, 0, sizeof(sirconfig));
652✔
219
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
757✔
220

221
    _sir_selflog("cleanup: %s", (cleanup ? "successful" : "with errors"));
722✔
222

223
    SIR_ASSERT(cleanup);
722✔
224
    return cleanup;
687✔
225
}
226

227
bool _sir_sanity(void) {
2,498,584✔
228
#if defined(__HAVE_ATOMIC_H__)
229
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
2,498,584✔
230
        return true;
2,418,338✔
231
#else
232
    if (_SIR_MAGIC == _sir_magic)
233
        return true;
234
#endif
235
    return _sir_seterror(_SIR_E_NOTREADY);
45✔
236
}
237

238
bool _sir_init_sanity(const sirinit* si) {
779✔
239
    if (!_sir_validptr(si))
779✔
240
        return false;
×
241

242
    bool levelcheck = true;
671✔
243
    _sir_eqland(levelcheck, _sir_validlevels(si->d_stdout.levels));
779✔
244
    _sir_eqland(levelcheck, _sir_validlevels(si->d_stderr.levels));
779✔
245

246
#if !defined(SIR_NO_SYSTEM_LOGGERS)
247
    _sir_eqland(levelcheck, _sir_validlevels(si->d_syslog.levels));
587✔
248
#endif
249

250
    bool optscheck = true;
671✔
251
    _sir_eqland(optscheck, _sir_validopts(si->d_stdout.opts));
779✔
252
    _sir_eqland(optscheck, _sir_validopts(si->d_stderr.opts));
779✔
253

254
#if !defined(SIR_NO_SYSTEM_LOGGERS)
255
    _sir_eqland(optscheck, _sir_validopts(si->d_syslog.opts));
587✔
256
#endif
257

258
    return levelcheck && optscheck;
779✔
259
}
260

261
static
262
bool _sir_updatelevels(const char* name, sir_levels* old, const sir_levels* new) {
862✔
263
    if (*old != *new) {
862✔
264
        _sir_selflog("updating %s levels from %04"PRIx16" to %04"PRIx16, name, *old, *new);
779✔
265
        *old = *new;
824✔
266
    } else {
267
        _sir_selflog("skipped superfluous update of %s levels: %04"PRIx16, name, *old);
36✔
268
    }
269
    return true;
862✔
270
}
271

272
static
273
bool _sir_updateopts(const char* name, sir_options* old, const sir_options* new) {
72,818✔
274
    if (*old != *new) {
72,818✔
275
        _sir_selflog("updating %s options from %08"PRIx32" to %08"PRIx32, name, *old, *new);
36,135✔
276
        *old = *new;
38,190✔
277
    } else {
278
        _sir_selflog("skipped superfluous update of %s options: %08"PRIx32, name, *old);
32,638✔
279
    }
280
    return true;
72,818✔
281
}
282

283
bool _sir_stdoutlevels(sirinit* si, const sir_update_config_data* data) {
424✔
284
    return _sir_updatelevels(SIR_DESTNAME_STDOUT, &si->d_stdout.levels, data->levels);
424✔
285
}
286

287
bool _sir_stdoutopts(sirinit* si, const sir_update_config_data* data) {
72,380✔
288
    return _sir_updateopts(SIR_DESTNAME_STDOUT, &si->d_stdout.opts, data->opts);
72,380✔
289
}
290

291
bool _sir_stderrlevels(sirinit* si, const sir_update_config_data* data) {
380✔
292
    return _sir_updatelevels(SIR_DESTNAME_STDERR, &si->d_stderr.levels, data->levels);
380✔
293
}
294

295
bool _sir_stderropts(sirinit* si, const sir_update_config_data* data) {
380✔
296
    return _sir_updateopts(SIR_DESTNAME_STDERR, &si->d_stderr.opts, data->opts);
380✔
297
}
298

299
bool _sir_sysloglevels(sirinit* si, const sir_update_config_data* data) {
58✔
300
    bool updated = _sir_updatelevels(SIR_DESTNAME_SYSLOG, &si->d_syslog.levels, data->levels);
58✔
301
    if (updated) {
58✔
302
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
58✔
303
        updated = _sir_syslog_updated(si, data);
58✔
304
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
58✔
305
    }
306
    return updated;
58✔
307
}
308

309
bool _sir_syslogopts(sirinit* si, const sir_update_config_data* data) {
58✔
310
    bool updated = _sir_updateopts(SIR_DESTNAME_SYSLOG, &si->d_syslog.opts, data->opts);
58✔
311
    if (updated) {
58✔
312
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
58✔
313
        updated = _sir_syslog_updated(si, data);
58✔
314
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
58✔
315
    }
316
    return updated;
58✔
317
}
318

319
bool _sir_syslogid(sirinit* si, const sir_update_config_data* data) {
119✔
320
    bool cur_valid = _sir_validstrnofail(si->d_syslog.identity);
119✔
321
    if (!cur_valid || 0 != strncmp(si->d_syslog.identity, data->sl_identity, SIR_MAX_SYSLOG_ID)) {
119✔
322
        _sir_selflog("updating %s identity from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
73✔
323
            si->d_syslog.identity, data->sl_identity);
324
        _sir_strncpy(si->d_syslog.identity, SIR_MAX_SYSLOG_ID, data->sl_identity,
73✔
325
            strnlen(data->sl_identity, SIR_MAX_SYSLOG_ID));
69✔
326
    } else {
327
        _sir_selflog("skipped superfluous update of %s identity: '%s'", SIR_DESTNAME_SYSLOG,
43✔
328
            si->d_syslog.identity);
329
        return true;
43✔
330
    }
331

332
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
73✔
333
    bool updated = _sir_syslog_updated(si, data);
73✔
334
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
73✔
335

336
    return updated;
73✔
337
}
338

339
bool _sir_syslogcat(sirinit* si, const sir_update_config_data* data) {
94✔
340
    bool cur_valid = _sir_validstrnofail(si->d_syslog.category);
94✔
341
    if (!cur_valid || 0 != strncmp(si->d_syslog.category, data->sl_category, SIR_MAX_SYSLOG_CAT)) {
94✔
342
        _sir_selflog("updating %s category from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
47✔
343
            si->d_syslog.category, data->sl_category);
344
        _sir_strncpy(si->d_syslog.category, SIR_MAX_SYSLOG_CAT, data->sl_category,
47✔
345
            strnlen(data->sl_category, SIR_MAX_SYSLOG_CAT));
44✔
346
    } else {
347
        _sir_selflog("skipped superfluous update of %s category: '%s'", SIR_DESTNAME_SYSLOG,
44✔
348
            si->d_syslog.identity);
349
        return true;
44✔
350
    }
351

352
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
47✔
353
    bool updated = _sir_syslog_updated(si, data);
47✔
354
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
47✔
355

356
    return updated;
47✔
357
}
358

359
bool _sir_writeinit(const sir_update_config_data* data, sirinit_update update) {
73,890✔
360
    (void)_sir_seterror(_SIR_E_NOERROR);
73,890✔
361

362
    if (!_sir_sanity() || !_sir_validupdatedata(data) || !_sir_validfnptr(update))
73,889✔
363
        return false;
×
364

365
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
73,883✔
366

367
    bool updated = update(&_cfg->si, data);
73,893✔
368
    if (!updated)
69,788✔
369
        _sir_selflog("error: update routine failed!");
×
370

371
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
73,893✔
372
    return updated;
73,893✔
373
}
374

375
void* _sir_locksection(sir_mutex_id mid) {
9,058,328✔
376
    sir_mutex* m = NULL;
9,058,328✔
377
    void* sec    = NULL;
9,058,328✔
378

379
    bool enter = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexlock(m);
9,058,328✔
380
    SIR_ASSERT(enter);
9,003,657✔
381

382
    return enter ? sec : NULL;
9,059,204✔
383
}
384

385
void _sir_unlocksection(sir_mutex_id mid) {
9,059,117✔
386
    sir_mutex* m = NULL;
9,059,117✔
387
    void* sec    = NULL;
9,059,117✔
388

389
    bool leave = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexunlock(m);
9,059,117✔
390
    SIR_ASSERT_UNUSED(leave, leave);
9,004,551✔
391
}
9,060,258✔
392

393
bool _sir_mapmutexid(sir_mutex_id mid, sir_mutex** m, void** section) {
18,113,303✔
394
    sir_mutex* tmpm;
395
    void* tmpsec;
396

397
    switch (mid) {
18,113,303✔
398
        case SIRMI_CONFIG:
8,658,368✔
399
            tmpm   = &cfg_mutex;
8,658,368✔
400
            tmpsec = &_sir_cfg;
8,658,368✔
401
            break;
8,658,368✔
402
        case SIRMI_FILECACHE:
4,472,226✔
403
            tmpm   = &fc_mutex;
4,396,542✔
404
            tmpsec = &_sir_fc;
4,396,542✔
405
            break;
4,472,226✔
406
        case SIRMI_PLUGINCACHE:
240,325✔
407
            tmpm   = &pc_mutex;
201,056✔
408
            tmpsec = &_sir_pc;
201,056✔
409
            break;
240,325✔
410
        case SIRMI_TEXTSTYLE:
4,629,211✔
411
            tmpm   = &ts_mutex;
4,530,013✔
412
            tmpsec = &sir_text_style_section;
4,530,013✔
413
            break;
4,629,211✔
414
        // GCOVR_EXCL_START
415
        default: /* this should never happen. */
416
            SIR_ASSERT(mid);
417
            tmpm   = NULL;
418
            tmpsec = NULL;
419
            break;
420
        // GCOVR_EXCL_STOP
421
    }
422

423
    *m = tmpm;
18,120,009✔
424

425
    if (section)
18,120,009✔
426
        *section = tmpsec;
18,113,467✔
427

428
    return *m != NULL && (!section || *section != NULL);
18,120,009✔
429
}
430

431
#if !defined(__WIN__)
432
void _sir_init_static_once(void) {
58✔
433
    (void)_sir_init_common_static();
58✔
434
}
58✔
435
#else /* __WIN__ */
436
BOOL CALLBACK _sir_init_static_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
437
    SIR_UNUSED(ponce);
438
    SIR_UNUSED(param);
439
    SIR_UNUSED(ctx);
440
    return _sir_init_common_static() ? TRUE : FALSE;
441
}
442
#endif
443

444
bool _sir_init_common_static(void) {
58✔
445
#if defined(__HAVE_ATOMIC_H__)
446
    atomic_init(&_sir_magic, 0);
58✔
447
#endif
448

449
#if defined(__WIN__)
450
    (void)QueryPerformanceFrequency(&_sir_perfcntr_freq);
451
#endif
452

453
    bool created = _sir_mutexcreate(&cfg_mutex);
58✔
454
    SIR_ASSERT(created);
56✔
455

456
    _sir_eqland(created, _sir_mutexcreate(&fc_mutex));
58✔
457
    SIR_ASSERT(created);
56✔
458

459
    _sir_eqland(created, _sir_mutexcreate(&pc_mutex));
58✔
460
    SIR_ASSERT(created);
56✔
461

462
    _sir_eqland(created, _sir_mutexcreate(&ts_mutex));
58✔
463
    SIR_ASSERT(created);
56✔
464

465
    return created;
58✔
466
}
467

468
bool _sir_once(sir_once* once, sir_once_fn func) {
824✔
469
#if !defined(__WIN__)
470
    int ret = pthread_once(once, func);
824✔
471
    return 0 == ret ? true : _sir_handleerr(ret);
824✔
472
#else /* __WIN__ */
473
    return (FALSE != InitOnceExecuteOnce(once, func, NULL, NULL)) ? true
474
        : _sir_handlewin32err(GetLastError());
475
#endif
476
}
477

478
PRINTF_FORMAT_ATTR(2, 0)
479
bool _sir_logv(sir_level level, PRINTF_FORMAT const char* format, va_list args) {
2,156,954✔
480
    if (!_sir_sanity() || !_sir_validlevel(level) || !_sir_validstr(format))
2,156,954✔
481
        return false;
44✔
482

483
    (void)_sir_seterror(_SIR_E_NOERROR);
2,156,910✔
484

485
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
2,156,907✔
486

487
    sirbuf buf = {0};
2,156,913✔
488

489
    /* from time to time, update the host name in the config, just in case. */
490
    time_t now_sec = -1;
2,156,913✔
491
    if (-1 != time(&now_sec) &&
2,156,913✔
492
        (now_sec - _cfg->state.last_hname_chk) > SIR_HNAME_CHK_INTERVAL) { //-V522
2,149,000✔
493
        _sir_selflog("updating hostname...");
8,320✔
494
        if (!_sir_gethostname(_cfg->state.hostname)) {
8,343✔
495
            _sir_selflog("error: failed to get hostname!");
7,913✔
496
        } else {
497
            _cfg->state.last_hname_chk = now_sec;
430✔
498
            _sir_selflog("hostname: '%s'", _cfg->state.hostname);
407✔
499
        }
500
    }
501

502
    /* format timestamp. */
503
    long now_msec = 0L;
2,156,913✔
504
    bool gettime = _sir_clock_gettime(SIR_WALLCLOCK, &now_sec, &now_msec);
2,156,913✔
505
    SIR_ASSERT_UNUSED(gettime, gettime);
2,149,000✔
506

507
    /* milliseconds. */
508
    _sir_snprintf_trunc(buf.msec, SIR_MAXMSEC, SIR_MSECFORMAT, now_msec);
2,156,913✔
509

510
    /* hours/minutes/seconds. */
511
    bool fmt = _sir_formattime(now_sec, _cfg->state.timestamp, SIR_TIMEFORMAT);
2,156,913✔
512
    SIR_ASSERT_UNUSED(fmt, fmt);
2,149,000✔
513

514
    /* check elapsed time since updating thread identifier/name. */
515
    sir_time thrd_chk;
516
    double msec_since_thrd_chk = _sir_msec_since(&_sir_last_thrd_chk, &thrd_chk);
2,156,913✔
517

518
    /* update the thread identifier/name if enough time has elapsed. */
519
    if (msec_since_thrd_chk > SIR_THRD_CHK_INTERVAL) {
2,156,913✔
520
        _sir_last_thrd_chk = thrd_chk;
367✔
521

522
        pid_t tid         = _sir_gettid();
367✔
523
        bool resolved_tid = false;
313✔
524

525
        /* prefer thread names. */
526
        resolved_tid = _sir_getthreadname(_sir_tid);
367✔
527

528
        /* if tid is identical to pid... */
529
        if (!resolved_tid && tid == _cfg->state.pid) {
367✔
530
            /* don't use anything to identify the thread. */
531
            _sir_resetstr(_sir_tid);
21✔
532
            resolved_tid = true;
18✔
533
        }
534

535
        /* fall back on tid. */
536
        if (!resolved_tid)
313✔
537
            _sir_snprintf_trunc(_sir_tid, SIR_MAXPID, SIR_PIDFORMAT,
×
538
                PID_CAST tid);
539
    }
540

541
    sirconfig cfg;
542
    memcpy(&cfg, _cfg, sizeof(sirconfig));
2,133,174✔
543
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,156,913✔
544

545
    buf.timestamp = cfg.state.timestamp;
2,156,913✔
546
    buf.hostname  = cfg.state.hostname;
2,156,913✔
547
    buf.pid       = cfg.state.pidbuf;
2,156,913✔
548
    buf.name      = cfg.si.name;
2,156,913✔
549

550
    const char* style_str = _sir_gettextstyle(level);
2,156,913✔
551

552
    SIR_ASSERT(NULL != style_str);
2,149,000✔
553
    if (NULL != style_str)
2,141,087✔
554
        (void)_sir_strncpy(buf.style, SIR_MAXSTYLE, style_str,
2,156,913✔
555
            strnlen(style_str, SIR_MAXSTYLE));
556

557
    buf.level = _sir_formattedlevelstr(level);
2,156,913✔
558

559
    (void)_sir_strncpy(buf.tid, SIR_MAXPID, _sir_tid, SIR_MAXPID);
2,156,913✔
560

561
    (void)vsnprintf(buf.message, SIR_MAXMESSAGE, format, args);
2,133,174✔
562

563
    if (!_sir_validstr(buf.message))
2,156,913✔
564
        return _sir_seterror(_SIR_E_INTERNAL);
22✔
565

566
    bool match             = false;
2,133,155✔
567
    bool exit_early        = false;
2,133,155✔
568
    bool update_last_props = true;
2,133,155✔
569
    uint64_t hash          = 0ULL;
2,133,155✔
570

571
    if (cfg.state.last.prefix[0] == buf.message[0]  &&
2,156,891✔
572
        cfg.state.last.prefix[1] == buf.message[1]) {
2,102,606✔
573
        hash  = FNV64_1a(buf.message);
2,120,791✔
574
        match = cfg.state.last.hash == hash;
2,120,791✔
575
    }
576

577
    if (match) {
2,151,976✔
578
        cfg.state.last.counter++;
33,562✔
579

580
        /* _sir_selflog("message '%s' matches last; incremented counter to %zu", buf.message,
581
            cfg.state.last.counter); */
582

583
        if (cfg.state.last.counter >= cfg.state.last.threshold - 2) {
33,562✔
584
            size_t old_threshold = cfg.state.last.threshold;
917✔
585

586
            update_last_props = false;
917✔
587
            cfg.state.last.threshold *= SIR_SQUELCH_BACKOFF_FACTOR;
1,061✔
588
            cfg.state.last.squelch = true;
1,061✔
589

590
            _sir_selflog("hit squelch threshold of %zu; setting new threshold"
1,013✔
591
                         " to %zu (factor: %d)",
592
                old_threshold, cfg.state.last.threshold, SIR_SQUELCH_BACKOFF_FACTOR);
593

594
            (void)snprintf(buf.message, SIR_MAXMESSAGE, SIR_SQUELCH_MSG_FORMAT, old_threshold);
917✔
595
        } else if (cfg.state.last.squelch) {
32,501✔
596
            exit_early = true;
26,733✔
597
        }
598
    } else {
599
        cfg.state.last.squelch   = false;
2,123,329✔
600
        cfg.state.last.counter   = 0;
2,123,329✔
601
        cfg.state.last.threshold = SIR_SQUELCH_THRESHOLD;
2,123,329✔
602
        /* _sir_selflog("message '%s' does not match last; resetting", buf.message); */
603
    }
604

605
    _cfg = _sir_locksection(SIRMI_CONFIG);
2,156,891✔
606
    if (!_cfg)
2,156,891✔
607
        return _sir_seterror(_SIR_E_INTERNAL);
×
608

609
    _cfg->state.last.squelch = cfg.state.last.squelch;
2,156,891✔
610

611
    if (update_last_props) {
2,156,891✔
612
        _cfg->state.last.hash      = hash;
2,155,830✔
613
        _cfg->state.last.prefix[0] = buf.message[0];
2,155,830✔
614
        _cfg->state.last.prefix[1] = buf.message[1];
2,155,830✔
615
    }
616

617
    _cfg->state.last.counter   = cfg.state.last.counter;
2,156,891✔
618
    _cfg->state.last.threshold = cfg.state.last.threshold;
2,156,891✔
619

620
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,156,891✔
621

622
    if (exit_early)
2,156,883✔
623
        return false;
26,733✔
624

625
    bool dispatched = _sir_dispatch(&cfg.si, level, &buf);
2,125,929✔
626
    return update_last_props ? dispatched : false;
2,125,936✔
627
}
628

629
bool _sir_dispatch(const sirinit* si, sir_level level, sirbuf* buf) {
2,125,927✔
630
    bool retval       = true;
2,106,412✔
631
    size_t dispatched = 0;
2,106,412✔
632
    size_t wanted     = 0;
2,106,412✔
633

634
    if (_sir_bittest(si->d_stdout.levels, level)) {
2,125,927✔
635
        const char* write = _sir_format(true, si->d_stdout.opts, buf);
1,122,293✔
636
        bool wrote        = _sir_validstrnofail(write) &&
2,244,595✔
637
            _sir_write_stdout(write, buf->output_len);
1,122,296✔
638
        _sir_eqland(retval, wrote);
1,103,376✔
639

640
        if (wrote)
1,103,376✔
641
            dispatched++;
1,097,160✔
642
        wanted++;
1,103,376✔
643
    }
644

645
    if (_sir_bittest(si->d_stderr.levels, level)) {
2,125,932✔
646
        const char* write = _sir_format(true, si->d_stderr.opts, buf);
1,103✔
647
        bool wrote        = _sir_validstrnofail(write) &&
2,206✔
648
            _sir_write_stderr(write, buf->output_len);
1,103✔
649
        _sir_eqland(retval, wrote);
1,103✔
650

651
        if (wrote)
1,103✔
652
            dispatched++;
1,094✔
653
        wanted++;
1,103✔
654
    }
655

656
#if !defined(SIR_NO_SYSTEM_LOGGERS)
657
    if (_sir_bittest(si->d_syslog.levels, level)) {
2,091,544✔
658
        if (_sir_syslog_write(level, buf, &si->d_syslog))
596✔
659
            dispatched++;
596✔
660
        wanted++;
596✔
661
    }
662
#endif
663

664
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
2,125,931✔
665
    size_t fdispatched = 0;
2,125,937✔
666
    size_t fwanted     = 0;
2,125,937✔
667
    _sir_eqland(retval, _sir_fcache_dispatch(sfc, level, buf, &fdispatched, &fwanted));
2,125,937✔
668
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
2,125,937✔
669

670
    dispatched += fdispatched;
2,125,937✔
671
    wanted += fwanted;
2,125,937✔
672

673
#if !defined(SIR_NO_PLUGINS)
674
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
119,357✔
675
    size_t pdispatched = 0;
119,357✔
676
    size_t pwanted     = 0;
119,357✔
677
    _sir_eqland(retval, _sir_plugin_cache_dispatch(spc, level, buf, &pdispatched, &pwanted));
119,357✔
678
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
119,357✔
679

680
    dispatched += pdispatched;
119,357✔
681
    wanted += pwanted;
119,357✔
682
#endif
683

684
    if (0 == wanted) {
2,125,937✔
685
        _sir_selflog("error: no destinations registered for level %04"PRIx16, level);
897✔
686
        return _sir_seterror(_SIR_E_NODEST);
950✔
687
    }
688

689
    return retval && (dispatched == wanted);
2,124,987✔
690
}
691

692
const char* _sir_format(bool styling, sir_options opts, sirbuf* buf) {
2,277,804✔
693
    if (_sir_validptr(buf)) {
2,277,804✔
694
        bool first = true;
2,232,426✔
695

696
        _sir_resetstr(buf->output);
2,277,736✔
697

698
        if (styling)
2,277,728✔
699
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->style, SIR_MAXSTYLE);
1,123,394✔
700

701
        if (!_sir_bittest(opts, SIRO_NOTIME)) {
2,277,723✔
702
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->timestamp, SIR_MAXTIME);
2,113,227✔
703
            first = false;
2,093,976✔
704

705
#if defined(SIR_MSEC_TIMER)
706
            if (!_sir_bittest(opts, SIRO_NOMSEC))
2,113,231✔
707
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->msec, SIR_MAXMSEC);
77,008✔
708
#endif
709
        }
710

711
        if (!_sir_bittest(opts, SIRO_NOHOST) && _sir_validstrnofail(buf->hostname)) {
2,277,829✔
712
            if (!first)
1,033,632✔
713
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,001,538✔
714
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->hostname, SIR_MAXHOST);
1,033,632✔
715
            first = false;
1,027,385✔
716
        }
717

718
        if (!_sir_bittest(opts, SIRO_NOLEVEL)) {
2,277,665✔
719
            if (!first)
2,163,784✔
720
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
2,113,347✔
721
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->level, SIR_MAXLEVEL);
2,163,788✔
722
            first = false;
2,137,623✔
723
        }
724

725
        bool name = false;
2,232,283✔
726
        if (!_sir_bittest(opts, SIRO_NONAME) && _sir_validstrnofail(buf->name)) {
2,277,656✔
727
            if (!first)
1,112,542✔
728
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,108,612✔
729
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->name, SIR_MAXNAME);
1,112,546✔
730
            first = false;
1,093,498✔
731
            name  = true;
1,093,498✔
732
        }
733

734
        bool wantpid = !_sir_bittest(opts, SIRO_NOPID) && _sir_validstrnofail(buf->pid);
2,277,716✔
735
        bool wanttid = !_sir_bittest(opts, SIRO_NOTID) && _sir_validstrnofail(buf->tid);
2,278,131✔
736

737
        if (wantpid || wanttid) {
2,277,986✔
738
            if (name)
2,146,542✔
739
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDPREFIX, 1);
1,107,067✔
740
            else if (!first)
1,039,475✔
741
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,039,469✔
742

743
            if (wantpid)
2,146,550✔
744
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->pid, SIR_MAXPID);
2,076,436✔
745

746
            if (wanttid) {
2,146,550✔
747
                if (wantpid)
2,141,066✔
748
                    _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSEPARATOR, 1);
2,071,052✔
749
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->tid, SIR_MAXPID);
2,141,066✔
750
            }
751

752
            if (name)
2,146,469✔
753
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSUFFIX, 1);
1,107,063✔
754

755
            if (first)
2,121,164✔
756
                first = false;
6✔
757
        }
758

759
        if (!first)
2,252,608✔
760
            _sir_strncat(buf->output, SIR_MAXOUTPUT, ": ", 2);
2,199,468✔
761

762
        _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->message, SIR_MAXMESSAGE);
2,277,920✔
763

764
        if (styling)
2,277,795✔
765
            _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_ESC_RST, SIR_MAXSTYLE);
1,123,370✔
766

767
        _sir_strncat(buf->output, SIR_MAXOUTPUT, "\n", 1);
2,277,796✔
768

769
        buf->output_len = strnlen(buf->output, SIR_MAXOUTPUT);
2,277,765✔
770

771
        return buf->output;
2,277,765✔
772
    }
773

774
    return NULL;
×
775
}
776

777
bool _sir_syslog_init(const char* name, sir_syslog_dest* ctx) {
227✔
778
#if !defined(SIR_NO_SYSTEM_LOGGERS)
779
    if (!_sir_validptr(name) || !_sir_validptr(ctx))
227✔
780
        return false;
×
781

782
    /* begin resolve identity. */
783
    if (!_sir_validstrnofail(ctx->identity)) {
227✔
784
        _sir_selflog("ctx->identity is no good; trying name");
47✔
785
        if (_sir_validstrnofail(name)) {
50✔
786
            _sir_selflog("using name");
28✔
787
            _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, name, strnlen(name, SIR_MAX_SYSLOG_ID));
30✔
788
        } else {
789
            _sir_selflog("name is no good; trying filename");
19✔
790
            char* appbasename = _sir_getappbasename();
20✔
791
            if (_sir_validstrnofail(appbasename)) {
20✔
792
                _sir_selflog("filename is good: %s", appbasename);
14✔
793
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, appbasename,
14✔
794
                    strnlen(appbasename, SIR_MAX_SYSLOG_ID));
795
            } else {
796
                _sir_selflog("filename no good; using fallback");
6✔
797
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, SIR_FALLBACK_SYSLOG_ID,
6✔
798
                    strnlen(SIR_FALLBACK_SYSLOG_ID, SIR_MAX_SYSLOG_ID));
799
            }
800
            _sir_safefree(&appbasename);
20✔
801
        }
802
    } else {
803
        _sir_selflog("already have identity");
167✔
804
    }
805

806
    /* category */
807
    if (!_sir_validstrnofail(ctx->category)) {
227✔
808
        _sir_selflog("category not set; using fallback");
72✔
809
        _sir_strncpy(ctx->category, SIR_MAX_SYSLOG_CAT, SIR_FALLBACK_SYSLOG_CAT,
76✔
810
            strnlen(SIR_FALLBACK_SYSLOG_CAT, SIR_MAX_SYSLOG_CAT));
811
    } else {
812
        _sir_selflog("already have category");
142✔
813
    }
814

815
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_INIT);
227✔
816
    _sir_selflog("resolved (identity: '%s', category: '%s')", ctx->identity, ctx->category);
214✔
817

818
    return _sir_syslog_open(ctx);
227✔
819
#else
820
    SIR_UNUSED(name);
821
    SIR_UNUSED(ctx);
822
    return false;
×
823
#endif
824
}
825

826
bool _sir_syslog_open(sir_syslog_dest* ctx) {
227✔
827
#if !defined(SIR_NO_SYSTEM_LOGGERS)
828
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
227✔
829
        _sir_selflog("not initialized; ignoring");
×
830
        return _sir_seterror(_SIR_E_INVALID);
×
831
    }
832

833
    if (_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
227✔
834
        _sir_selflog("log already open; ignoring");
98✔
835
        return true;
98✔
836
    }
837

838
    _sir_selflog("opening log (levels: %04"PRIx16", options: %08"PRIx32")", ctx->levels,
123✔
839
        ctx->opts);
840

841
# if defined(SIR_OS_LOG_ENABLED)
842
    ctx->_state.logger = (void*)os_log_create(ctx->identity, ctx->category);
843
    _sir_selflog("opened os_log ('%s', '%s')", ctx->identity, ctx->category);
844
# elif defined(SIR_SYSLOG_ENABLED)
845
    int logopt   = LOG_NDELAY | (_sir_bittest(ctx->opts, SIRO_NOPID) ? 0 : LOG_PID);
123✔
846
    int facility = LOG_USER;
102✔
847

848
    openlog(ctx->identity, logopt, facility);
123✔
849
    _sir_selflog("opened syslog('%s', %x, %x)", ctx->identity, logopt, facility);
116✔
850
# endif
851

852
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_OPEN);
123✔
853
    return true;
123✔
854
#else
855
    SIR_UNUSED(ctx);
856
    return false;
×
857
#endif
858
}
859

860
bool _sir_syslog_write(sir_level level, const sirbuf* buf, const sir_syslog_dest* ctx) {
596✔
861
#if !defined(SIR_NO_SYSTEM_LOGGERS)
862
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
596✔
863
        _sir_selflog("not initialized; ignoring");
×
864
        return _sir_seterror(_SIR_E_INVALID);
×
865
    }
866

867
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
596✔
868
        _sir_selflog("log not open; ignoring");
×
869
        return _sir_seterror(_SIR_E_INVALID);
×
870
    }
871

872
# if defined(SIR_OS_LOG_ENABLED)
873
    if (SIRL_DEBUG == level)
874
        os_log_debug((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
875
    else if (SIRL_INFO == level || SIRL_NOTICE == level)
876
        os_log_info((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
877
    else if (SIRL_WARN == level || SIRL_ERROR == level)
878
        os_log_error((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
879
    else if (SIRL_ALERT == level || SIRL_CRIT == level || SIRL_EMERG == level)
880
        os_log_fault((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
881

882
    return true;
883
# elif defined(SIR_SYSLOG_ENABLED)
884
    int syslog_level;
885
    switch (level) {
596✔
886
        case SIRL_DEBUG:  syslog_level = LOG_DEBUG; break;
25✔
887
        case SIRL_INFO:   syslog_level = LOG_INFO; break;
27✔
888
        case SIRL_NOTICE: syslog_level = LOG_NOTICE; break;
80✔
889
        case SIRL_WARN:   syslog_level = LOG_WARNING; break;
80✔
890
        case SIRL_ERROR:  syslog_level = LOG_ERR; break;
80✔
891
        case SIRL_CRIT:   syslog_level = LOG_CRIT; break;
107✔
892
        case SIRL_ALERT:  syslog_level = LOG_ALERT; break;
80✔
893
        case SIRL_EMERG:  syslog_level = LOG_EMERG; break;
107✔
894
        // GCOVR_EXCL_START
895
        default: /* this should never happen. */
896
            SIR_ASSERT(false);
897
            syslog_level = LOG_DEBUG;
898
        // GCOVR_EXCL_STOP
899
    }
900

901
    syslog(syslog_level, "%s", buf->message);
596✔
902
    return true;
596✔
903
# endif
904
#else
905
    SIR_UNUSED(level);
906
    SIR_UNUSED(buf);
907
    SIR_UNUSED(ctx);
908
    return false;
×
909
#endif
910
}
911

912
bool _sir_syslog_updated(sirinit* si, const sir_update_config_data* data) {
236✔
913
#if !defined(SIR_NO_SYSTEM_LOGGERS)
914
    if (!_sir_validptr(si) || !_sir_validptr(data))
236✔
915
        return false;
×
916

917
    if (_sir_bittest(si->d_syslog._state.mask, SIRSL_UPDATED)) {
236✔
918
        bool levels   = _sir_bittest(si->d_syslog._state.mask, SIRSL_LEVELS);
223✔
919
        bool options  = _sir_bittest(si->d_syslog._state.mask, SIRSL_OPTIONS);
236✔
920
        bool category = _sir_bittest(si->d_syslog._state.mask, SIRSL_CATEGORY);
223✔
921
        bool identity = _sir_bittest(si->d_syslog._state.mask, SIRSL_IDENTITY);
236✔
922
        bool is_init  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_INIT);
236✔
923
        bool is_open  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_OPEN);
236✔
924

925
        _sir_selflog("config update: (levels: %u, options: %u, category: %u,"
223✔
926
                     " identity: %u, is_init: %u, is_open: %u)",
927
                     levels, options, category, identity, is_init, is_open);
928

929
        bool must_init = false;
197✔
930

931
# if defined(SIR_OS_LOG_ENABLED)
932
        /*
933
         * for os_log, if initialized and open already, only need to reconfigure
934
         * if identity or category changed.
935
         */
936
        must_init = (!is_init || !is_open) || (identity || category);
937
# elif defined(SIR_SYSLOG_ENABLED)
938
        /*
939
         * for os_log, if initialized and open already, only need to reconfigure
940
         * if identity or options changed.
941
         */
942
        must_init = (!is_init || !is_open) || (identity || options);
236✔
943
# endif
944
        bool init = true;
197✔
945
        if (must_init) {
197✔
946
            _sir_selflog("re-init...");
124✔
947
            init = _sir_syslog_init(si->name, &si->d_syslog);
131✔
948
            _sir_selflog("re-init %s", init ? "succeeded" : "failed");
124✔
949
        } else {
950
            _sir_selflog("no re-init necessary");
99✔
951
        }
952

953
        return init;
236✔
954
    } else {
955
        _sir_selflog("BUG: called without 'updated' flag set!");
×
956
        return false;
×
957
    }
958
#else
959
    SIR_UNUSED(si);
960
    SIR_UNUSED(data);
961
    return false;
×
962
#endif
963
}
964

965
bool _sir_syslog_close(sir_syslog_dest* ctx) {
571✔
966
#if !defined(SIR_NO_SYSTEM_LOGGERS)
967
    if (!_sir_validptr(ctx))
571✔
968
        return false;
×
969

970
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
571✔
971
        _sir_selflog("log not open; ignoring");
420✔
972
        return true;
420✔
973
    }
974

975
# if defined(SIR_OS_LOG_ENABLED)
976
    /* evidently, you don't need to close the handle returned from os_log_create(), and
977
     * if you make that call again, you'll get the same cached value. so let's keep the
978
     * value we've got in the global context. */
979
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
980
    _sir_selflog("log closure not necessary");
981
    return true;
982
# elif defined(SIR_SYSLOG_ENABLED)
983
    closelog();
123✔
984
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
123✔
985
    _sir_selflog("closed log");
116✔
986
    return true;
123✔
987
# endif
988
#else
989
    SIR_UNUSED(ctx);
990
    return false;
×
991
#endif
992
}
993

994
void _sir_syslog_reset(sir_syslog_dest* ctx) {
1,142✔
995
#if !defined(SIR_NO_SYSTEM_LOGGERS)
996
    if (_sir_validptr(ctx)) {
1,142✔
997
        uint32_t old       = ctx->_state.mask;
1,072✔
998
        ctx->_state.mask   = 0U;
1,142✔
999
        ctx->_state.logger = NULL;
1,142✔
1000
        _sir_selflog("state reset; mask was %08"PRIx32, old);
1,072✔
1001
    }
1002
#else
1003
    SIR_UNUSED(ctx);
1004
#endif
1005
}
1,142✔
1006

1007
const char* _sir_formattedlevelstr(sir_level level) {
2,156,913✔
1008
    static const size_t low  = 0;
1009
    static const size_t high = SIR_NUMLEVELS - 1;
1010

1011
    const char* retval = SIR_UNKNOWN;
2,133,174✔
1012

1013
    _SIR_DECLARE_BIN_SEARCH(low, high);
2,133,174✔
1014
    _SIR_BEGIN_BIN_SEARCH()
1015

1016
    if (sir_level_to_str_map[_mid].level == level) {
8,584,109✔
1017
        retval = sir_level_to_str_map[_mid].fmt;
2,156,913✔
1018
        break;
2,156,913✔
1019
    }
1020

1021
    _SIR_ITERATE_BIN_SEARCH((sir_level_to_str_map[_mid].level < level ? 1 : -1));
6,427,196✔
1022
    _SIR_END_BIN_SEARCH();
1023

1024
    return retval;
2,156,913✔
1025
}
1026

1027
bool _sir_clock_gettime(int clock, time_t* tbuf, long* msecbuf) {
6,313,902✔
1028
    if (tbuf) {
6,313,902✔
1029
#if defined(SIR_MSEC_POSIX)
1030
        struct timespec ts = {0};
6,313,902✔
1031
        int ret            = clock_gettime(clock, &ts);
6,313,902✔
1032
        SIR_ASSERT(0 == ret);
6,298,073✔
1033

1034
        if (0 == ret) {
6,282,244✔
1035
            *tbuf = ts.tv_sec;
6,298,153✔
1036
            if (msecbuf)
6,298,153✔
1037
                *msecbuf = ts.tv_nsec / 1000000L;
6,298,153✔
1038
        } else {
1039
            if (msecbuf)
15,749✔
1040
                *msecbuf = 0L;
15,749✔
1041
            return _sir_handleerr(errno);
15,749✔
1042
        }
1043
#elif defined(SIR_MSEC_WIN32)
1044
        SIR_UNUSED(clock);
1045
        static const ULONGLONG uepoch = (ULONGLONG)116444736e9;
1046

1047
        FILETIME ftutc = {0};
1048
        GetSystemTimePreciseAsFileTime(&ftutc);
1049

1050
        ULARGE_INTEGER ftnow = {0};
1051
        ftnow.HighPart = ftutc.dwHighDateTime;
1052
        ftnow.LowPart  = ftutc.dwLowDateTime;
1053
        ftnow.QuadPart = (ULONGLONG)((ftnow.QuadPart - uepoch) / 10000000ULL);
1054

1055
        *tbuf = (time_t)ftnow.QuadPart;
1056

1057
        SYSTEMTIME st = {0};
1058
        if (FileTimeToSystemTime(&ftutc, &st)) {
1059
            if (msecbuf)
1060
                *msecbuf = (long)st.wMilliseconds;
1061
        } else {
1062
            if (msecbuf)
1063
                *msecbuf = 0L;
1064
            return _sir_handlewin32err(GetLastError());
1065
        }
1066
#else
1067
        SIR_UNUSED(clock);
1068
        time(tbuf);
1069
        if (msecbuf)
1070
            *msecbuf = 0L;
1071
#endif
1072
        return true;
6,298,153✔
1073
    }
1074
    return false;
×
1075
}
1076

1077
double _sir_msec_since(const sir_time* when, sir_time* out) {
4,156,989✔
1078
    if (!_sir_validptr(out))
4,156,989✔
1079
        return 0.0;
×
1080
#if !defined(__WIN__) || defined(__ORANGEC__)
1081
    out->sec = 0;
4,156,989✔
1082
    out->msec = 0L;
4,156,989✔
1083

1084
    bool gettime = _sir_clock_gettime(SIR_INTERVALCLOCK, &out->sec, &out->msec);
4,156,989✔
1085
    SIR_ASSERT(gettime);
4,149,073✔
1086

1087
    if (!_sir_validptrnofail(when) || !gettime || (out->sec < when->sec ||
4,156,989✔
1088
        (out->sec == when->sec && out->msec < when->msec)))
4,149,012✔
1089
        return 0.0;
7,917✔
1090

1091
    return ((((double)out->sec) * 1e3) + (double)out->msec) -
4,149,066✔
1092
           ((((double)when->sec) * 1e3) + (double)when->msec);
4,149,066✔
1093
#else /* __WIN__ */
1094
    SIR_ASSERT(_sir_perfcntr_freq.QuadPart > 0LL);
1095

1096
    if (_sir_perfcntr_freq.QuadPart <= 0LL)
1097
        (void)QueryPerformanceFrequency(&_sir_perfcntr_freq);
1098

1099
    (void)QueryPerformanceCounter(&out->counter);
1100

1101
    if (!_sir_validptrnofail(when) || out->counter.QuadPart <= when->counter.QuadPart)
1102
        return 0.0;
1103

1104
    double msec_ratio = ((double)_sir_perfcntr_freq.QuadPart) / 1e3;
1105
    return ((double)(out->counter.QuadPart - when->counter.QuadPart)) / msec_ratio;
1106
#endif
1107
}
1108

1109
pid_t _sir_getpid(void) {
773✔
1110
#if !defined(__WIN__)
1111
    return getpid();
773✔
1112
#else /* __WIN__ */
1113
    return (pid_t)GetCurrentProcessId();
1114
#endif
1115
}
1116

1117
pid_t _sir_gettid(void) {
501✔
1118
    pid_t tid = 0;
426✔
1119
#if defined(__MACOS__)
1120
    uint64_t tid64 = 0ULL;
1121
    int gettid     = pthread_threadid_np(NULL, &tid64);
1122
    if (0 != gettid)
1123
        (void)_sir_handleerr(gettid);
1124
    tid = (pid_t)tid64;
1125
#elif (defined(__BSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)) || \
1126
      defined(__DragonFly_getthreadid__)
1127
    tid = (pid_t)pthread_getthreadid_np();
1128
#elif defined(__OpenBSD__)
1129
    tid = (pid_t)getthrid();
1130
#elif defined(__SOLARIS__) || defined(__NetBSD__) || defined(__HURD__) || \
1131
      defined(__DragonFly__) || defined(__CYGWIN__) || defined(_AIX)
1132
    tid = (pid_t)pthread_self();
1133
#elif defined(__HAIKU__)
1134
    tid = get_pthread_thread_id(pthread_self());
1135
#elif defined(__linux__) || defined(__serenity__)
1136
# if (defined(__GLIBC__) && GLIBC_VERSION >= 23000) || defined(__serenity__)
1137
    tid = gettid();
501✔
1138
# else
1139
    tid = syscall(SYS_gettid);
1140
# endif
1141
#elif defined(__WIN__)
1142
    tid = (pid_t)GetCurrentThreadId();
1143
#else
1144
# error "unable to determine how to get a thread identifier"
1145
#endif
1146
    return tid;
501✔
1147
}
1148

1149
bool _sir_getthreadname(char name[SIR_MAXPID]) {
367✔
1150
    _sir_resetstr(name);
367✔
1151
#if defined(__MACOS__) || (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1152
    (defined(__GLIBC__) && GLIBC_VERSION >= 21200 && defined(_GNU_SOURCE)) || \
1153
    (defined(__ANDROID__) &&  __ANDROID_API__ >= 26) || defined(SIR_PTHREAD_GETNAME_NP) || \
1154
    defined(__serenity__) || (defined(__linux__) && !defined(__GLIBC__) && \
1155
    defined(_GNU_SOURCE) && defined(__NEED_pthread_t))
1156
    int ret = pthread_getname_np(pthread_self(), name, SIR_MAXPID);
367✔
1157
    if (0 != ret)
367✔
1158
        return _sir_handleerr(ret);
×
1159
# if defined(__HAIKU__)
1160
    if (!(strncmp(name, "pthread func", SIR_MAXPID)))
1161
        (void)snprintf(name, SIR_MAXPID, "%ld", (long)get_pthread_thread_id(pthread_self()));
1162
# endif
1163
    return _sir_validstrnofail(name);
367✔
1164
#elif defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1165
    pthread_get_name_np(pthread_self(), name, SIR_MAXPID);
1166
    return _sir_validstrnofail(name);
1167
#elif defined(__WIN__) && !defined(__ORANGEC__)
1168
    wchar_t* wname = NULL;
1169
    HRESULT hr     = GetThreadDescription(GetCurrentThread(), &wname);
1170
    if (FAILED(hr))
1171
        return _sir_handlewin32err(GetLastError());
1172
    bool success = true;
1173
# if defined(__HAVE_STDC_SECURE_OR_EXT1__)
1174
    size_t wlen = wcsnlen_s(wname, SIR_MAXPID);
1175
# elif defined(__EMBARCADEROC__)
1176
    size_t wlen = wcslen(wname);
1177
# else
1178
    size_t wlen = wcsnlen(wname, SIR_MAXPID);
1179
# endif
1180
    if (wlen > 0) {
1181
        if (!WideCharToMultiByte(CP_UTF8, 0UL, wname, (int)wlen, name,
1182
            SIR_MAXPID, NULL, NULL)) {
1183
            success = false;
1184
            (void)_sir_handlewin32err(GetLastError());
1185
        }
1186
    }
1187
    (void)LocalFree(wname);
1188
    return success && _sir_validstrnofail(name);
1189
#else
1190
# if !defined(_AIX) && !defined(__HURD__) && !defined(SUNLINT)
1191
#  pragma message("unable to determine how to get a thread name")
1192
# endif
1193
    SIR_UNUSED(name);
1194
    return false;
1195
#endif
1196
}
1197

1198
bool _sir_setthreadname(const char* name) {
44✔
1199
    if (!_sir_validptr(name))
44✔
1200
        return false;
×
1201
#if defined(__MACOS__)
1202
    int ret = pthread_setname_np(name);
1203
    return (0 != ret) ? _sir_handleerr(ret) : true;
1204
#elif defined(__HAIKU__)
1205
    status_t ret = rename_thread(find_thread(NULL), name);
1206
    return (B_OK != ret) ? _sir_handleerr((int)ret) : true;
1207
#elif defined(__NetBSD__)
1208
    int ret = pthread_setname_np(pthread_self(), "%s", name);
1209
    return (0 != ret) ? _sir_handleerr(ret) : true;
1210
#elif (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1211
      (defined(__GLIBC__) && GLIBC_VERSION >= 21200 && defined(_GNU_SOURCE)) || \
1212
       defined(__QNXNTO__) || defined(__SOLARIS__) || defined(SIR_PTHREAD_GETNAME_NP) || \
1213
       defined(__ANDROID__) && !defined(__OpenBSD__) || defined(__serenity__) || \
1214
      (defined(__linux__) && !defined(__GLIBC__) && \
1215
       defined(_GNU_SOURCE) && defined(__NEED_pthread_t))
1216
    int ret = pthread_setname_np(pthread_self(), name);
44✔
1217
    return (0 != ret) ? _sir_handleerr(ret) : true;
44✔
1218
#elif defined(__OpenBSD__) || defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1219
    pthread_set_name_np(pthread_self(), name);
1220
    return true;
1221
#elif defined(__WIN__) && !defined(__ORANGEC__)
1222
# if defined(__HAVE_STDC_SECURE_OR_EXT1__)
1223
    size_t name_len = strnlen_s(name, SIR_MAXPID);
1224
# else
1225
    size_t name_len = strnlen(name, SIR_MAXPID);
1226
# endif
1227
    if (0 == name_len)
1228
        name_len = 1;
1229

1230
    wchar_t buf[SIR_MAXPID] = {0};
1231
    if (!MultiByteToWideChar(CP_UTF8, 0UL, name, (int)name_len, buf, SIR_MAXPID))
1232
        return _sir_handlewin32err(GetLastError());
1233

1234
    HRESULT hr = SetThreadDescription(GetCurrentThread(), buf);
1235
    return FAILED(hr) ? _sir_handlewin32err(hr) : true;
1236
#else
1237
# if !defined(SUNLINT)
1238
#  pragma message("unable to determine how to set a thread name")
1239
# endif
1240
    SIR_UNUSED(name);
1241
    return false;
1242
#endif
1243
}
1244

1245
bool _sir_gethostname(char name[SIR_MAXHOST]) {
8,343✔
1246
#if !defined(__WIN__)
1247
    int ret = gethostname(name, SIR_MAXHOST - 1);
8,274✔
1248
    return 0 == ret ? true : _sir_handleerr(errno);
8,343✔
1249
#else
1250
    WSADATA wsad = {0};
1251
    int ret      = WSAStartup(MAKEWORD(2, 2), &wsad);
1252
    if (0 != ret)
1253
        return _sir_handlewin32err(ret);
1254

1255
    if (SOCKET_ERROR == gethostname(name, SIR_MAXHOST)) {
1256
        int err = WSAGetLastError();
1257
        WSACleanup();
1258
        return _sir_handlewin32err(err);
1259
    }
1260

1261
    WSACleanup();
1262
    return true;
1263
#endif /* !__WIN__ */
1264
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc