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

aremmell / libsir / 30

31 Jul 2023 12:10AM UTC coverage: 94.83% (-0.2%) from 94.986%
30

push

gitlab-ci

johnsonjh
Try again to appease MSVC Analyzer

Signed-off-by: Jeffrey H. Johnson <trnsz@pobox.com>

3045 of 3211 relevant lines covered (94.83%)

1608502.28 hits per line

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

94.21
/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.2
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
# pragma comment(lib, "ws2_32.lib")
37
#endif
38

39
static sirconfig _sir_cfg      = {0};
40
static sirfcache _sir_fc       = {0};
41
static sir_plugincache _sir_pc = {0};
42

43
static sir_mutex cfg_mutex = SIR_MUTEX_INIT;
44
static sir_once cfg_once   = SIR_ONCE_INIT;
45

46
static sir_mutex fc_mutex  = SIR_MUTEX_INIT;
47
static sir_once fc_once    = SIR_ONCE_INIT;
48

49
static sir_mutex pc_mutex  = SIR_MUTEX_INIT;
50
static sir_once pc_once    = SIR_ONCE_INIT;
51

52
static sir_mutex ts_mutex  = SIR_MUTEX_INIT;
53
static sir_once ts_once    = SIR_ONCE_INIT;
54

55
static sir_once magic_once = SIR_ONCE_INIT;
56

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

63
bool _sir_makeinit(sirinit* si) {
54✔
64
    bool retval = _sir_validptr(si);
54✔
65

66
    if (retval) {
54✔
67
        memset(si, 0, sizeof(sirinit));
48✔
68

69
        si->d_stdout.opts   = SIRO_DEFAULT;
54✔
70
        si->d_stdout.levels = SIRL_DEFAULT;
54✔
71

72
        si->d_stderr.opts   = SIRO_DEFAULT;
54✔
73
        si->d_stderr.levels = SIRL_DEFAULT;
54✔
74

75
#if !defined(SIR_NO_SYSTEM_LOGGERS)
76
        si->d_syslog.opts   = SIRO_DEFAULT;
41✔
77
        si->d_syslog.levels = SIRL_DEFAULT;
41✔
78
#else
79
        si->d_syslog.opts   = SIRO_MSGONLY;
13✔
80
        si->d_syslog.levels = SIRL_NONE;
13✔
81
#endif
82
    }
83

84
    return retval;
54✔
85
}
86

87
bool _sir_init(sirinit* si) {
744✔
88
    (void)_sir_seterror(_SIR_E_NOERROR);
744✔
89
    _sir_once(&magic_once, _sir_initialize_once);
744✔
90

91
    if (!_sir_validptr(si))
744✔
92
        return false;
18✔
93

94
#if defined(__HAVE_ATOMIC_H__)
95
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
723✔
96
#else
97
    if (_SIR_MAGIC == _sir_magic)
98
#endif
99
        return _sir_seterror(_SIR_E_ALREADY);
22✔
100

101
    _sir_defaultlevels(&si->d_stdout.levels, sir_stdout_def_lvls);
701✔
102
    _sir_defaultopts(&si->d_stdout.opts, sir_stdout_def_opts);
701✔
103

104
    _sir_defaultlevels(&si->d_stderr.levels, sir_stderr_def_lvls);
701✔
105
    _sir_defaultopts(&si->d_stderr.opts, sir_stderr_def_opts);
701✔
106

107
#if !defined(SIR_NO_SYSTEM_LOGGERS)
108
    _sir_defaultlevels(&si->d_syslog.levels, sir_syslog_def_lvls);
521✔
109
    _sir_defaultopts(&si->d_syslog.opts, sir_syslog_def_opts);
521✔
110
#endif
111

112
    if (!_sir_init_sanity(si))
701✔
113
        return false;
18✔
114

115
#if defined(__WIN__)
116
    if (!_sir_initialize_stdio()) {
117
        _sir_selflog("error: failed to initialize stdio!");
118
        return false;
119
    }
120
#endif
121

122
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
680✔
123

124
#if defined(__HAVE_ATOMIC_H__)
125
    atomic_store(&_sir_magic, _SIR_MAGIC);
680✔
126
#else
127
    _sir_magic = _SIR_MAGIC;
128
#endif
129

130
    _sir_setcolormode(SIRCM_16);
680✔
131

132
    if (!_sir_resettextstyles())
680✔
133
        _sir_selflog("error: failed to reset text styles!");
×
134

135
    memset(&_cfg->state, 0, sizeof(_cfg->state));
680✔
136
    memcpy(&_cfg->si, si, sizeof(sirinit));
680✔
137

138
    /* forcibly null-terminate the process name. */
139
    _cfg->si.name[SIR_MAXNAME - 1] = '\0';
680✔
140

141
    /* Store PID. */
142
    _cfg->state.pid = _sir_getpid();
680✔
143

144
    (void)snprintf(_cfg->state.pidbuf, SIR_MAXPID, SIR_PIDFORMAT,
680✔
145
        PID_CAST _cfg->state.pid);
146

147
#if !defined(SIR_NO_SYSTEM_LOGGERS)
148
    /* initialize system logger. */
149
    _sir_syslog_reset(&_cfg->si.d_syslog);
506✔
150

151
    if (_cfg->si.d_syslog.levels != SIRL_NONE) {
506✔
152
        if (!_sir_syslog_init(_cfg->si.name, &_cfg->si.d_syslog))
90✔
153
            _sir_selflog("failed to initialize system logger!");
×
154
    }
155
#endif
156

157
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
680✔
158

159
    return true;
680✔
160
}
161

162
bool _sir_cleanup(void) {
701✔
163
    if (!_sir_sanity())
701✔
164
        return false;
18✔
165

166
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
680✔
167
    bool cleanup   = true;
581✔
168
    bool destroyfc = _sir_fcache_destroy(sfc);
680✔
169
    SIR_ASSERT(destroyfc);
647✔
170

171
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
680✔
172
    cleanup &= destroyfc;
581✔
173

174
#if !defined(SIR_NO_PLUGINS)
175
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
639✔
176
    bool destroypc = _sir_plugin_cache_destroy(spc);
639✔
177
    SIR_ASSERT(destroypc);
606✔
178
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
639✔
179
    cleanup &= destroypc;
540✔
180
#endif
181

182
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
680✔
183

184
#if !defined(SIR_NO_SYSTEM_LOGGERS)
185
    if (!_sir_syslog_close(&_cfg->si.d_syslog)) {
506✔
186
        cleanup = false;
×
187
        _sir_selflog("error: failed to close system logger!");
×
188
    }
189

190
    _sir_syslog_reset(&_cfg->si.d_syslog);
506✔
191
#endif
192

193
    if (!_sir_resettextstyles()) {
680✔
194
        cleanup = false;
×
195
        _sir_selflog("error: failed to reset text styles!");
×
196
    }
197

198
#if defined(__HAVE_ATOMIC_H__)
199
    atomic_store(&_sir_magic, 0);
680✔
200
#else
201
    _sir_magic = 0;
202
#endif
203

204
    memset(_cfg, 0, sizeof(sirconfig));
581✔
205
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
680✔
206

207
    _sir_selflog("cleanup: %s", (cleanup ? "successful" : "with errors"));
647✔
208

209
    SIR_ASSERT(cleanup);
647✔
210
    return cleanup;
614✔
211
}
212

213
bool _sir_sanity(void) {
2,471,882✔
214
#if defined(__HAVE_ATOMIC_H__)
215
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
2,471,882✔
216
        return true;
2,391,521✔
217
#else
218
    if (_SIR_MAGIC == _sir_magic)
219
        return true;
220
#endif
221
    return _sir_seterror(_SIR_E_NOTREADY);
51✔
222
}
223

224
bool _sir_init_sanity(const sirinit* si) {
701✔
225
    if (!_sir_validptr(si))
701✔
226
        return false;
×
227

228
    bool levelcheck = true;
599✔
229
    levelcheck &= _sir_validlevels(si->d_stdout.levels);
701✔
230
    levelcheck &= _sir_validlevels(si->d_stderr.levels);
701✔
231

232
#if !defined(SIR_NO_SYSTEM_LOGGERS)
233
    levelcheck &= _sir_validlevels(si->d_syslog.levels);
521✔
234
#endif
235

236
    bool optscheck = true;
599✔
237
    optscheck &= _sir_validopts(si->d_stdout.opts);
701✔
238
    optscheck &= _sir_validopts(si->d_stderr.opts);
701✔
239

240
#if !defined(SIR_NO_SYSTEM_LOGGERS)
241
    optscheck &= _sir_validopts(si->d_syslog.opts);
521✔
242
#endif
243

244
    return levelcheck && optscheck;
701✔
245
}
246

247
static
248
bool _sir_updatelevels(const char* name, sir_levels* old, sir_levels* new) {
817✔
249
    if (*old != *new) {
817✔
250
        _sir_selflog("updating %s levels from %04"PRIx16" to %04"PRIx16, name, *old, *new);
735✔
251
        *old = *new;
781✔
252
    } else {
253
        _sir_selflog("skipped superfluous update of %s levels: %04"PRIx16, name, *old);
34✔
254
    }
255
    return true;
817✔
256
}
257

258
static
259
bool _sir_updateopts(const char* name, sir_options* old, sir_options* new) {
68,775✔
260
    if (*old != *new) {
68,775✔
261
        _sir_selflog("updating %s options from %08"PRIx32" to %08"PRIx32, name, *old, *new);
31,954✔
262
        *old = *new;
34,109✔
263
    } else {
264
        _sir_selflog("skipped superfluous update of %s options: %08"PRIx32, name, *old);
32,775✔
265
    }
266
    return true;
68,775✔
267
}
268

269
bool _sir_stdoutlevels(sirinit* si, sir_update_config_data* data) {
401✔
270
    return _sir_updatelevels(SIR_DESTNAME_STDOUT, &si->d_stdout.levels, data->levels);
401✔
271
}
272

273
bool _sir_stdoutopts(sirinit* si, sir_update_config_data* data) {
68,359✔
274
    return _sir_updateopts(SIR_DESTNAME_STDOUT, &si->d_stdout.opts, data->opts);
68,359✔
275
}
276

277
bool _sir_stderrlevels(sirinit* si, sir_update_config_data* data) {
359✔
278
    return _sir_updatelevels(SIR_DESTNAME_STDERR, &si->d_stderr.levels, data->levels);
359✔
279
}
280

281
bool _sir_stderropts(sirinit* si, sir_update_config_data* data) {
359✔
282
    return _sir_updateopts(SIR_DESTNAME_STDERR, &si->d_stderr.opts, data->opts);
359✔
283
}
284

285
bool _sir_sysloglevels(sirinit* si, sir_update_config_data* data) {
57✔
286
    bool updated = _sir_updatelevels(SIR_DESTNAME_SYSLOG, &si->d_syslog.levels, data->levels);
57✔
287
    if (updated) {
57✔
288
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
57✔
289
        updated = _sir_syslog_updated(si, data);
57✔
290
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
57✔
291
    }
292
    return updated;
57✔
293
}
294

295
bool _sir_syslogopts(sirinit* si, sir_update_config_data* data) {
57✔
296
    bool updated = _sir_updateopts(SIR_DESTNAME_SYSLOG, &si->d_syslog.opts, data->opts);
57✔
297
    if (updated) {
57✔
298
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
57✔
299
        updated = _sir_syslog_updated(si, data);
57✔
300
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
57✔
301
    }
302
    return updated;
57✔
303
}
304

305
bool _sir_syslogid(sirinit* si, sir_update_config_data* data) {
98✔
306
    bool cur_valid = _sir_validstrnofail(si->d_syslog.identity);
98✔
307
    if (!cur_valid || 0 != strncmp(si->d_syslog.identity, data->sl_identity, SIR_MAX_SYSLOG_ID)) {
98✔
308
        _sir_selflog("updating %s identity from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
62✔
309
            si->d_syslog.identity, data->sl_identity);
310
        _sir_strncpy(si->d_syslog.identity, SIR_MAX_SYSLOG_ID, data->sl_identity,
62✔
311
            strnlen(data->sl_identity, SIR_MAX_SYSLOG_ID));
312
    } else {
313
        _sir_selflog("skipped superfluous update of %s identity: '%s'", SIR_DESTNAME_SYSLOG,
34✔
314
            si->d_syslog.identity);
315
        return true;
34✔
316
    }
317

318
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
62✔
319
    bool updated = _sir_syslog_updated(si, data);
62✔
320
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
62✔
321

322
    return updated;
62✔
323
}
324

325
bool _sir_syslogcat(sirinit* si, sir_update_config_data* data) {
94✔
326
    bool cur_valid = _sir_validstrnofail(si->d_syslog.category);
94✔
327
    if (!cur_valid || 0 != strncmp(si->d_syslog.category, data->sl_category, SIR_MAX_SYSLOG_CAT)) {
94✔
328
        _sir_selflog("updating %s category from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
47✔
329
            si->d_syslog.category, data->sl_category);
330
        _sir_strncpy(si->d_syslog.category, SIR_MAX_SYSLOG_CAT, data->sl_category,
47✔
331
            strnlen(data->sl_category, SIR_MAX_SYSLOG_CAT));
332
    } else {
333
        _sir_selflog("skipped superfluous update of %s category: '%s'", SIR_DESTNAME_SYSLOG,
43✔
334
            si->d_syslog.identity);
335
        return true;
43✔
336
    }
337

338
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
47✔
339
    bool updated = _sir_syslog_updated(si, data);
47✔
340
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
47✔
341

342
    return updated;
47✔
343
}
344

345
bool _sir_writeinit(sir_update_config_data* data, sirinit_update update) {
69,779✔
346
    (void)_sir_seterror(_SIR_E_NOERROR);
69,779✔
347

348
    if (!_sir_sanity() || !_sir_validupdatedata(data) || !_sir_validfnptr(update))
69,779✔
349
        return false;
×
350

351
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
69,778✔
352

353
    bool updated = update(&_cfg->si, data);
69,784✔
354
    if (!updated)
65,677✔
355
        _sir_selflog("error: update routine failed!");
×
356

357
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
69,784✔
358
    return updated;
69,784✔
359
}
360

361
void* _sir_locksection(sir_mutex_id mid) {
9,001,250✔
362
    sir_mutex* m = NULL;
9,001,250✔
363
    void* sec    = NULL;
9,001,250✔
364

365
    bool enter = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexlock(m);
9,001,250✔
366
    SIR_ASSERT(enter);
8,947,161✔
367

368
    return enter ? sec : NULL;
9,002,777✔
369
}
370

371
void _sir_unlocksection(sir_mutex_id mid) {
9,002,968✔
372
    sir_mutex* m = NULL;
9,002,968✔
373
    void* sec    = NULL;
9,002,968✔
374

375
    bool leave = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexunlock(m);
9,002,968✔
376
    SIR_ASSERT_UNUSED(leave, leave);
8,948,357✔
377
}
9,004,084✔
378

379
bool _sir_mapmutexid(sir_mutex_id mid, sir_mutex** m, void** section) {
17,999,624✔
380
    sir_mutex* tmpm;
381
    void* tmpsec;
382

383
    switch (mid) {
17,999,624✔
384
        case SIRMI_CONFIG:
8,737,250✔
385
            _sir_once(&cfg_once, _sir_initmutex_cfg_once);
8,737,250✔
386
            tmpm   = &cfg_mutex;
8,617,524✔
387
            tmpsec = &_sir_cfg;
8,617,524✔
388
            break;
8,737,292✔
389
        case SIRMI_FILECACHE:
4,446,946✔
390
            _sir_once(&fc_once, _sir_initmutex_fc_once);
4,446,946✔
391
            tmpm   = &fc_mutex;
4,371,200✔
392
            tmpsec = &_sir_fc;
4,371,200✔
393
            break;
4,446,998✔
394
        case SIRMI_PLUGINCACHE:
227,038✔
395
            _sir_once(&pc_once, _sir_initmutex_pc_once);
227,038✔
396
            tmpm   = &pc_mutex;
187,798✔
397
            tmpsec = &_sir_pc;
187,798✔
398
            break;
227,038✔
399
        case SIRMI_TEXTSTYLE:
4,596,029✔
400
            _sir_once(&ts_once, _sir_initmutex_ts_once);
4,596,029✔
401
            tmpm   = &ts_mutex;
4,496,834✔
402
            tmpsec = &sir_text_style_section;
4,496,834✔
403
            break;
4,596,032✔
404
        // GCOVR_EXCL_START
405
        default: /* this should never happen. */
406
            SIR_ASSERT("!invalid mutex id");
407
            tmpm   = NULL;
408
            tmpsec = NULL;
409
            break;
410
        // GCOVR_EXCL_STOP
411
    }
412

413
    *m = tmpm;
17,999,721✔
414

415
    if (section)
17,999,721✔
416
        *section = tmpsec;
17,999,618✔
417

418
    return *m != NULL && (!section || *section != NULL);
17,999,721✔
419
}
420

421
#if !defined(__WIN__)
422
void _sir_initialize_once(void) {
56✔
423
# if defined(__HAVE_ATOMIC_H__)
424
    atomic_init(&_sir_magic, 0);
56✔
425
# endif
426
}
56✔
427

428
void _sir_initmutex_cfg_once(void) {
56✔
429
    bool created = _sir_mutexcreate(&cfg_mutex);
56✔
430
    SIR_ASSERT_UNUSED(created, created);
54✔
431
}
56✔
432

433
void _sir_initmutex_fc_once(void) {
56✔
434
    bool created = _sir_mutexcreate(&fc_mutex);
56✔
435
    SIR_ASSERT_UNUSED(created, created);
54✔
436
}
56✔
437

438
void _sir_initmutex_pc_once(void) {
47✔
439
    bool created = _sir_mutexcreate(&pc_mutex);
47✔
440
    SIR_ASSERT_UNUSED(created, created);
45✔
441
}
47✔
442

443
void _sir_initmutex_ts_once(void) {
56✔
444
    bool created = _sir_mutexcreate(&ts_mutex);
56✔
445
    SIR_ASSERT_UNUSED(created, created);
54✔
446
}
56✔
447

448
#else /* __WIN__ */
449
BOOL CALLBACK _sir_initialize_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
450
    SIR_UNUSED(ponce);
451
    SIR_UNUSED(param);
452
    SIR_UNUSED(ctx);
453
    return TRUE;
454
}
455

456
BOOL CALLBACK _sir_initmutex_cfg_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
457
    SIR_UNUSED(ponce);
458
    SIR_UNUSED(param);
459
    SIR_UNUSED(ctx);
460

461
    if (!_sir_mutexcreate(&cfg_mutex)) {
462
        SIR_ASSERT(!"failed to create mutex!");
463
        return FALSE;
464
    }
465

466
    return TRUE;
467
}
468

469
BOOL CALLBACK _sir_initmutex_fc_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
470
    SIR_UNUSED(ponce);
471
    SIR_UNUSED(param);
472
    SIR_UNUSED(ctx);
473

474
    if (!_sir_mutexcreate(&fc_mutex)) {
475
        SIR_ASSERT(!"failed to create mutex!");
476
        return FALSE;
477
    }
478

479
    return TRUE;
480
}
481

482
BOOL CALLBACK _sir_initmutex_pc_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
483
    SIR_UNUSED(ponce);
484
    SIR_UNUSED(param);
485
    SIR_UNUSED(ctx);
486

487
    if (!_sir_mutexcreate(&pc_mutex)) {
488
        SIR_ASSERT(!"failed to create mutex!");
489
        return FALSE;
490
    }
491

492
    return TRUE;
493
}
494

495
BOOL CALLBACK _sir_initmutex_ts_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
496
    SIR_UNUSED(ponce);
497
    SIR_UNUSED(param);
498
    SIR_UNUSED(ctx);
499

500
    if (!_sir_mutexcreate(&ts_mutex)) {
501
        SIR_ASSERT(!"failed to create mutex!");
502
        return FALSE;
503
    }
504

505
    return TRUE;
506
}
507
#endif
508

509
bool _sir_once(sir_once* once, sir_once_fn func) {
17,998,170✔
510
#if !defined(__WIN__)
511
    int ret = pthread_once(once, func);
17,998,170✔
512
    return 0 == ret ? true : _sir_handleerr(ret);
17,998,836✔
513
#else /* __WIN__ */
514
    return (FALSE != InitOnceExecuteOnce(once, func, NULL, NULL)) ? true
515
        : _sir_handlewin32err(GetLastError());
516
#endif
517
}
518

519
PRINTF_FORMAT_ATTR(2, 0)
520
bool _sir_logv(sir_level level, PRINTF_FORMAT const char* format, va_list args) {
2,148,979✔
521
    if (!_sir_sanity() || !_sir_validlevel(level) || !_sir_validstr(format))
2,148,979✔
522
        return false;
42✔
523

524
    (void)_sir_seterror(_SIR_E_NOERROR);
2,148,937✔
525

526
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
2,148,937✔
527

528
    /* from time to time, update the host name in the config, just in case. */
529
    time_t now = -1;
2,148,937✔
530
    if (-1 != time(&now) &&
2,148,937✔
531
        (now - _cfg->state.last_hname_chk) > SIR_HNAME_CHK_INTERVAL) { //-V522
2,141,027✔
532
        _sir_selflog("updating hostname...");
8,258✔
533
        if (!_sir_gethostname(_cfg->state.hostname)) {
8,279✔
534
            _sir_selflog("error: failed to get hostname!");
7,910✔
535
        } else {
536
            _cfg->state.last_hname_chk = now;
369✔
537
            _sir_selflog("hostname: '%s'", _cfg->state.hostname);
348✔
538
        }
539
    }
540

541
    sirconfig cfg;
542
    memcpy(&cfg, _cfg, sizeof(sirconfig));
2,125,207✔
543
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,148,937✔
544

545
    sirbuf buf = {
2,148,936✔
546
        {0},
547
        {0},
548
        {0},
549
        cfg.state.hostname,
550
        cfg.state.pidbuf,
551
        NULL,
552
        cfg.si.name,
553
        {0},
554
        {0},
555
        {0},
556
         0
557
    };
558

559
    bool fmt              = false;
2,125,207✔
560
    const char* style_str = _sir_gettextstyle(level);
2,148,936✔
561

562
    SIR_ASSERT(NULL != style_str);
2,141,027✔
563
    if (NULL != style_str)
2,133,117✔
564
        fmt = (0 == _sir_strncpy(buf.style, SIR_MAXSTYLE, style_str,
2,148,937✔
565
            strnlen(style_str, SIR_MAXSTYLE)));
566
    SIR_ASSERT_UNUSED(fmt, fmt);
2,141,026✔
567

568
    now          = -1;
2,148,936✔
569
    long nowmsec = 0;
2,148,936✔
570
    bool gettime = _sir_clock_gettime(&now, &nowmsec);
2,148,936✔
571
    SIR_ASSERT(gettime);
2,141,026✔
572

573
    if (gettime) {
2,133,116✔
574
        fmt = _sir_formattime(now, buf.timestamp, SIR_TIMEFORMAT);
2,133,156✔
575
        SIR_ASSERT_UNUSED(fmt, fmt);
2,125,247✔
576

577
        (void)snprintf(buf.msec, SIR_MAXMSEC, SIR_MSECFORMAT, nowmsec);
2,133,157✔
578
    }
579

580
    buf.level = _sir_formattedlevelstr(level);
2,148,937✔
581

582
    pid_t tid = _sir_gettid();
2,148,937✔
583
    if (tid != cfg.state.pid)
2,148,937✔
584
        if (!_sir_getthreadname(buf.tid) || !_sir_validstrnofail(buf.tid))
68,152✔
585
            (void)snprintf(buf.tid, SIR_MAXPID, SIR_PIDFORMAT, PID_CAST tid);
×
586

587
    (void)vsnprintf(buf.message, SIR_MAXMESSAGE, format, args);
2,125,207✔
588

589
    if (!_sir_validstr(buf.message))
2,148,937✔
590
        return _sir_seterror(_SIR_E_INTERNAL);
21✔
591

592
    bool match             = false;
2,125,189✔
593
    bool exit_early        = false;
2,125,189✔
594
    bool update_last_props = true;
2,125,189✔
595
    uint64_t hash          = 0;
2,125,189✔
596

597
    if (cfg.state.last.prefix[0] == buf.message[0]  &&
2,148,916✔
598
        cfg.state.last.prefix[1] == buf.message[1]) {
2,096,360✔
599
        hash  = FNV64_1a(buf.message);
2,114,707✔
600
        match = cfg.state.last.hash == hash;
2,114,707✔
601
    }
602

603
    if (match) {
2,144,008✔
604
        cfg.state.last.counter++;
32,200✔
605

606
        /* _sir_selflog("message '%s' matches last; incremented counter to %zu", buf.message,
607
            cfg.state.last.counter); */
608

609
        if (cfg.state.last.counter >= cfg.state.last.threshold - 2) {
32,200✔
610
            size_t old_threshold = cfg.state.last.threshold;
865✔
611

612
            update_last_props = false;
865✔
613
            cfg.state.last.threshold *= SIR_SQUELCH_BACKOFF_FACTOR;
1,009✔
614
            cfg.state.last.squelch = true;
1,009✔
615

616
            _sir_selflog("hit squelch threshold of %zu; setting new threshold"
961✔
617
                         " to %zu (factor: %d)",
618
                old_threshold, cfg.state.last.threshold, SIR_SQUELCH_BACKOFF_FACTOR);
619

620
            (void)snprintf(buf.message, SIR_MAXMESSAGE, SIR_SQUELCH_MSG_FORMAT, old_threshold);
865✔
621
        } else if (cfg.state.last.squelch) {
31,191✔
622
            exit_early = true;
25,326✔
623
        }
624
    } else {
625
        cfg.state.last.squelch   = false;
2,116,716✔
626
        cfg.state.last.counter   = 0;
2,116,716✔
627
        cfg.state.last.threshold = SIR_SQUELCH_THRESHOLD;
2,116,716✔
628
        /* _sir_selflog("message '%s' does not match last; resetting", buf.message); */
629
    }
630

631
    _cfg = _sir_locksection(SIRMI_CONFIG);
2,148,916✔
632
    if (!_cfg)
2,148,916✔
633
        return _sir_seterror(_SIR_E_INTERNAL);
×
634

635
    _cfg->state.last.squelch = cfg.state.last.squelch;
2,148,916✔
636

637
    if (update_last_props) {
2,148,916✔
638
        _cfg->state.last.hash      = hash;
2,147,907✔
639
        _cfg->state.last.prefix[0] = buf.message[0];
2,147,907✔
640
        _cfg->state.last.prefix[1] = buf.message[1];
2,147,907✔
641
    }
642

643
    _cfg->state.last.counter   = cfg.state.last.counter;
2,148,916✔
644
    _cfg->state.last.threshold = cfg.state.last.threshold;
2,148,916✔
645

646
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,148,916✔
647

648
    if (exit_early)
2,148,916✔
649
        return false;
25,326✔
650

651
    bool dispatched = _sir_dispatch(&cfg.si, level, &buf);
2,119,369✔
652
    return update_last_props ? dispatched : false;
2,119,369✔
653
}
654

655
bool _sir_dispatch(sirinit* si, sir_level level, sirbuf* buf) {
2,119,368✔
656
    bool retval       = true;
2,099,863✔
657
    size_t dispatched = 0;
2,099,863✔
658
    size_t wanted     = 0;
2,099,863✔
659

660
    if (_sir_bittest(si->d_stdout.levels, level)) {
2,119,368✔
661
        const char* write = _sir_format(true, si->d_stdout.opts, buf);
1,115,930✔
662
        bool wrote        = _sir_validstrnofail(write) &&
2,231,857✔
663
            _sir_write_stdout(write, buf->output_len);
1,115,929✔
664
        retval &= wrote;
1,115,928✔
665

666
        if (wrote)
1,115,928✔
667
            dispatched++;
1,090,801✔
668
        wanted++;
1,097,013✔
669
    }
670

671
    if (_sir_bittest(si->d_stderr.levels, level)) {
2,119,364✔
672
        const char* write = _sir_format(true, si->d_stderr.opts, buf);
1,046✔
673
        bool wrote        = _sir_validstrnofail(write) &&
2,092✔
674
            _sir_write_stderr(write, buf->output_len);
1,046✔
675
        retval &= wrote;
1,046✔
676

677
        if (wrote)
1,046✔
678
            dispatched++;
1,037✔
679
        wanted++;
1,046✔
680
    }
681

682
#if !defined(SIR_NO_SYSTEM_LOGGERS)
683
    if (_sir_bittest(si->d_syslog.levels, level)) {
2,084,996✔
684
        if (_sir_syslog_write(level, buf, &si->d_syslog))
564✔
685
            dispatched++;
564✔
686
        wanted++;
564✔
687
    }
688
#endif
689

690
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
2,119,362✔
691
    size_t fdispatched = 0;
2,119,369✔
692
    size_t fwanted     = 0;
2,119,369✔
693
    retval &= _sir_fcache_dispatch(sfc, level, buf, &fdispatched, &fwanted);
2,119,369✔
694
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
2,119,369✔
695

696
    dispatched += fdispatched;
2,119,369✔
697
    wanted += fwanted;
2,119,369✔
698

699
#if !defined(SIR_NO_PLUGINS)
700
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
112,792✔
701
    size_t pdispatched = 0;
112,792✔
702
    size_t pwanted     = 0;
112,792✔
703
    retval &= _sir_plugin_cache_dispatch(spc, level, buf, &pdispatched, &pwanted);
112,792✔
704
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
112,792✔
705

706
    dispatched += pdispatched;
112,792✔
707
    wanted += pwanted;
112,792✔
708
#endif
709

710
    if (0 == wanted) {
2,119,369✔
711
        _sir_selflog("error: no destinations registered for level %04"PRIx32, level);
844✔
712
        return _sir_seterror(_SIR_E_NODEST);
897✔
713
    }
714

715
    return retval && (dispatched == wanted);
2,118,472✔
716
}
717

718
const char* _sir_format(bool styling, sir_options opts, sirbuf* buf) {
2,257,613✔
719
    if (_sir_validptr(buf)) {
2,257,613✔
720
        bool first = true;
2,212,958✔
721

722
        _sir_resetstr(buf->output);
2,257,462✔
723

724
        if (styling)
2,257,501✔
725
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->style, SIR_MAXSTYLE);
1,116,976✔
726

727
        if (!_sir_bittest(opts, SIRO_NOTIME)) {
2,257,498✔
728
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->timestamp, SIR_MAXTIME);
2,104,870✔
729
            first = false;
2,085,985✔
730

731
#if defined(SIR_MSEC_TIMER)
732
            if (!_sir_bittest(opts, SIRO_NOMSEC))
2,104,894✔
733
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->msec, SIR_MAXMSEC);
70,658✔
734
#endif
735
        }
736

737
        if (!_sir_bittest(opts, SIRO_NOHOST) && _sir_validstrnofail(buf->hostname)) {
2,257,686✔
738
            if (!first)
1,031,333✔
739
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,001,447✔
740
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->hostname, SIR_MAXHOST);
1,031,333✔
741
            first = false;
1,025,181✔
742
        }
743

744
        if (!_sir_bittest(opts, SIRO_NOLEVEL)) {
2,257,624✔
745
            if (!first)
2,153,037✔
746
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
2,104,969✔
747
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->level, SIR_MAXLEVEL);
2,153,098✔
748
            first = false;
2,127,253✔
749
        }
750

751
        bool name = false;
2,213,117✔
752
        if (!_sir_bittest(opts, SIRO_NONAME) && _sir_validstrnofail(buf->name)) {
2,257,663✔
753
            if (!first)
1,104,085✔
754
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,100,052✔
755
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->name, SIR_MAXNAME);
1,104,126✔
756
            first = false;
1,085,585✔
757
            name  = true;
1,085,585✔
758
        }
759

760
        bool wantpid = !_sir_bittest(opts, SIRO_NOPID) && _sir_validstrnofail(buf->pid);
2,257,674✔
761
        bool wanttid = !_sir_bittest(opts, SIRO_NOTID) && _sir_validstrnofail(buf->tid);
2,258,011✔
762

763
        if (wantpid || wanttid) {
2,257,823✔
764
            if (name)
2,139,785✔
765
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDPREFIX, 1);
1,102,399✔
766
            else if (!first)
1,037,386✔
767
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,037,380✔
768

769
            if (wantpid)
2,139,842✔
770
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->pid, SIR_MAXPID);
2,072,180✔
771

772
            if (wanttid) {
2,139,849✔
773
                if (wantpid)
135,631✔
774
                    _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSEPARATOR, 1);
68,105✔
775
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->tid, SIR_MAXPID);
135,627✔
776
            }
777

778
            if (name)
2,139,652✔
779
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSUFFIX, 1);
1,102,432✔
780

781
            if (first)
2,114,864✔
782
                first = false;
6✔
783
        }
784

785
        if (!first)
2,232,902✔
786
            _sir_strncat(buf->output, SIR_MAXOUTPUT, ": ", 2);
2,186,768✔
787

788
        _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->message, SIR_MAXMESSAGE);
2,257,704✔
789

790
        if (styling)
2,257,739✔
791
            _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_ESC_RST, SIR_MAXSTYLE);
1,116,971✔
792

793
        _sir_strncat(buf->output, SIR_MAXOUTPUT, "\n", 1);
2,257,733✔
794

795
        buf->output_len = strnlen(buf->output, SIR_MAXOUTPUT);
2,257,668✔
796

797
        return buf->output;
2,257,668✔
798
    }
799

800
    return NULL;
×
801
}
802

803
bool _sir_syslog_init(const char* name, sir_syslog_dest* ctx) {
209✔
804
#if !defined(SIR_NO_SYSTEM_LOGGERS)
805
    if (!_sir_validptr(name) || !_sir_validptr(ctx))
209✔
806
        return false;
×
807

808
    /* begin resolve identity. */
809
    if (!_sir_validstrnofail(ctx->identity)) {
209✔
810
        _sir_selflog("ctx->identity is no good; trying name");
50✔
811
        if (_sir_validstrnofail(name)) {
54✔
812
            _sir_selflog("using name");
18✔
813
            _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, name, strnlen(name, SIR_MAX_SYSLOG_ID));
21✔
814
        } else {
815
            _sir_selflog("name is no good; trying filename");
32✔
816
            char* appbasename = _sir_getappbasename();
33✔
817
            if (_sir_validstrnofail(appbasename)) {
33✔
818
                _sir_selflog("filename is good: %s", appbasename);
27✔
819
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, appbasename,
27✔
820
                    strnlen(appbasename, SIR_MAX_SYSLOG_ID));
821
            } else {
822
                _sir_selflog("filename no good; using fallback");
6✔
823
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, SIR_FALLBACK_SYSLOG_ID,
6✔
824
                    strnlen(SIR_FALLBACK_SYSLOG_ID, SIR_MAX_SYSLOG_ID));
825
            }
826
            _sir_safefree(&appbasename);
33✔
827
        }
828
    } else {
829
        _sir_selflog("already have identity");
146✔
830
    }
831

832
    /* category */
833
    if (!_sir_validstrnofail(ctx->category)) {
209✔
834
        _sir_selflog("category not set; using fallback");
66✔
835
        _sir_strncpy(ctx->category, SIR_MAX_SYSLOG_CAT, SIR_FALLBACK_SYSLOG_CAT,
69✔
836
            strnlen(SIR_FALLBACK_SYSLOG_CAT, SIR_MAX_SYSLOG_CAT));
837
    } else {
838
        _sir_selflog("already have category");
130✔
839
    }
840

841
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_INIT);
209✔
842
    _sir_selflog("resolved (identity: '%s', category: '%s')", ctx->identity, ctx->category);
196✔
843

844
    return _sir_syslog_open(ctx);
209✔
845
#else
846
    SIR_UNUSED(name);
847
    SIR_UNUSED(ctx);
848
    return false;
×
849
#endif
850
}
851

852
bool _sir_syslog_open(sir_syslog_dest* ctx) {
209✔
853
#if !defined(SIR_NO_SYSTEM_LOGGERS)
854
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
209✔
855
        _sir_selflog("not initialized; ignoring");
×
856
        return _sir_seterror(_SIR_E_INVALID);
×
857
    }
858

859
    if (_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
209✔
860
        _sir_selflog("log already open; ignoring");
87✔
861
        return true;
87✔
862
    }
863

864
    _sir_selflog("opening log (levels: %04"PRIx16", options: %08"PRIx32")", ctx->levels,
116✔
865
        ctx->opts);
866

867
# if defined(SIR_OS_LOG_ENABLED)
868
    ctx->_state.logger = (void*)os_log_create(ctx->identity, ctx->category);
869
    _sir_selflog("opened os_log ('%s', '%s')", ctx->identity, ctx->category);
870
# elif defined(SIR_SYSLOG_ENABLED)
871
    int logopt   = LOG_NDELAY | (_sir_bittest(ctx->opts, SIRO_NOPID) ? 0 : LOG_PID);
116✔
872
    int facility = LOG_USER;
95✔
873

874
    openlog(ctx->identity, logopt, facility);
116✔
875
    _sir_selflog("opened syslog('%s', %x, %x)", ctx->identity, logopt, facility);
109✔
876
# endif
877

878
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_OPEN);
116✔
879
    return true;
116✔
880
#else
881
    SIR_UNUSED(ctx);
882
    return false;
×
883
#endif
884
}
885

886
bool _sir_syslog_write(sir_level level, const sirbuf* buf, sir_syslog_dest* ctx) {
564✔
887
#if !defined(SIR_NO_SYSTEM_LOGGERS)
888
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
564✔
889
        _sir_selflog("not initialized; ignoring");
×
890
        return _sir_seterror(_SIR_E_INVALID);
×
891
    }
892

893
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
564✔
894
        _sir_selflog("log not open; ignoring");
×
895
        return _sir_seterror(_SIR_E_INVALID);
×
896
    }
897

898
# if defined(SIR_OS_LOG_ENABLED)
899
    if (SIRL_DEBUG == level)
900
        os_log_debug((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
901
    else if (SIRL_INFO == level || SIRL_NOTICE == level)
902
        os_log_info((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
903
    else if (SIRL_WARN == level || SIRL_ERROR == level)
904
        os_log_error((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
905
    else if (SIRL_ALERT == level || SIRL_CRIT == level || SIRL_EMERG == level)
906
        os_log_fault((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
907

908
    return true;
909
# elif defined(SIR_SYSLOG_ENABLED)
910
    int syslog_level;
911
    switch (level) {
564✔
912
        case SIRL_DEBUG:  syslog_level = LOG_DEBUG; break;
25✔
913
        case SIRL_INFO:   syslog_level = LOG_INFO; break;
28✔
914
        case SIRL_NOTICE: syslog_level = LOG_NOTICE; break;
75✔
915
        case SIRL_WARN:   syslog_level = LOG_WARNING; break;
75✔
916
        case SIRL_ERROR:  syslog_level = LOG_ERR; break;
75✔
917
        case SIRL_CRIT:   syslog_level = LOG_CRIT; break;
101✔
918
        case SIRL_ALERT:  syslog_level = LOG_ALERT; break;
75✔
919
        case SIRL_EMERG:  syslog_level = LOG_EMERG; break;
101✔
920
        // GCOVR_EXCL_START
921
        default: /* this should never happen. */
922
            SIR_ASSERT(!"invalid sir_level");
923
            syslog_level = LOG_DEBUG;
924
        // GCOVR_EXCL_STOP
925
    }
926

927
    syslog(syslog_level, "%s", buf->message);
564✔
928
    return true;
564✔
929
# endif
930
#else
931
    SIR_UNUSED(level);
932
    SIR_UNUSED(buf);
933
    SIR_UNUSED(ctx);
934
    return false;
×
935
#endif
936
}
937

938
bool _sir_syslog_updated(sirinit* si, sir_update_config_data* data) {
223✔
939
#if !defined(SIR_NO_SYSTEM_LOGGERS)
940
    if (!_sir_validptr(si) || !_sir_validptr(data))
223✔
941
        return false;
×
942

943
    if (_sir_bittest(si->d_syslog._state.mask, SIRSL_UPDATED)) {
223✔
944
        bool levels   = _sir_bittest(si->d_syslog._state.mask, SIRSL_LEVELS);
208✔
945
        bool options  = _sir_bittest(si->d_syslog._state.mask, SIRSL_OPTIONS);
223✔
946
        bool category = _sir_bittest(si->d_syslog._state.mask, SIRSL_CATEGORY);
208✔
947
        bool identity = _sir_bittest(si->d_syslog._state.mask, SIRSL_IDENTITY);
223✔
948
        bool is_init  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_INIT);
223✔
949
        bool is_open  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_OPEN);
223✔
950

951
        _sir_selflog("config update: (levels: %u, options: %u, category: %u,"
208✔
952
                     " identity: %u, is_init: %u, is_open: %u)",
953
                     levels, options, category, identity, is_init, is_open);
954

955
        bool must_init = false;
185✔
956

957
# if defined(SIR_OS_LOG_ENABLED)
958
        /*
959
         * for os_log, if initialized and open already, only need to reconfigure
960
         * if identity or category changed.
961
         */
962
        must_init = (!is_init || !is_open) || (identity || category);
963
# elif defined(SIR_SYSLOG_ENABLED)
964
        /*
965
         * for os_log, if initialized and open already, only need to reconfigure
966
         * if identity or options changed.
967
         */
968
        must_init = (!is_init || !is_open) || (identity || options);
223✔
969
# endif
970
        bool init = true;
185✔
971
        if (must_init) {
185✔
972
            _sir_selflog("re-init...");
112✔
973
            init = _sir_syslog_init(si->name, &si->d_syslog);
119✔
974
            _sir_selflog("re-init %s", init ? "succeeded" : "failed");
112✔
975
        } else {
976
            _sir_selflog("no re-init necessary");
96✔
977
        }
978

979
        return init;
223✔
980
    } else {
981
        _sir_selflog("BUG: called without 'updated' flag set!");
×
982
        return false;
×
983
    }
984
#else
985
    SIR_UNUSED(si);
986
    SIR_UNUSED(data);
987
    return false;
×
988
#endif
989
}
990

991
bool _sir_syslog_close(sir_syslog_dest* ctx) {
506✔
992
#if !defined(SIR_NO_SYSTEM_LOGGERS)
993
    if (!_sir_validptr(ctx))
506✔
994
        return false;
×
995

996
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
506✔
997
        _sir_selflog("log not open; ignoring");
364✔
998
        return true;
364✔
999
    }
1000

1001
# if defined(SIR_OS_LOG_ENABLED)
1002
    /* evidently, you don't need to close the handle returned from os_log_create(), and
1003
     * if you make that call again, you'll get the same cached value. so let's keep the
1004
     * value we've got in the global context. */
1005
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
1006
    _sir_selflog("log closure not necessary");
1007
    return true;
1008
# elif defined(SIR_SYSLOG_ENABLED)
1009
    closelog();
116✔
1010
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
116✔
1011
    _sir_selflog("closed log");
109✔
1012
    return true;
116✔
1013
# endif
1014
#else
1015
    SIR_UNUSED(ctx);
1016
    return false;
×
1017
#endif
1018
}
1019

1020
void _sir_syslog_reset(sir_syslog_dest* ctx) {
1,012✔
1021
#if !defined(SIR_NO_SYSTEM_LOGGERS)
1022
    if (_sir_validptr(ctx)) {
1,012✔
1023
        uint32_t old       = ctx->_state.mask;
946✔
1024
        ctx->_state.mask   = 0;
1,012✔
1025
        ctx->_state.logger = NULL;
1,012✔
1026
        _sir_selflog("state reset; mask was %08"PRIx32, old);
946✔
1027
    }
1028
#else
1029
    SIR_UNUSED(ctx);
1030
#endif
1031
}
1,012✔
1032

1033
const char* _sir_formattedlevelstr(sir_level level) {
2,148,937✔
1034
    static const size_t low  = 0;
1035
    static const size_t high = SIR_NUMLEVELS - 1;
1036

1037
    const char* retval = SIR_UNKNOWN;
2,125,207✔
1038

1039
    _SIR_DECLARE_BIN_SEARCH(low, high)
2,125,207✔
1040
    _SIR_BEGIN_BIN_SEARCH()
1041

1042
    if (sir_level_to_str_map[_mid].level == level) {
8,554,603✔
1043
        retval = sir_level_to_str_map[_mid].fmt;
2,148,937✔
1044
        break;
2,148,937✔
1045
    }
1046

1047
    _SIR_ITERATE_BIN_SEARCH((sir_level_to_str_map[_mid].level < level ? 1 : -1))
6,405,666✔
1048
    _SIR_END_BIN_SEARCH()
1049

1050
    return retval;
2,148,937✔
1051
}
1052

1053
#if defined(__GNUC__)
1054
__attribute__ ((format (strftime, 3, 0)))
1055
#endif
1056
bool _sir_formattime(time_t now, char* buffer, const char* format) {
2,167,978✔
1057
    if (0 == now || -1 == now)
2,167,978✔
1058
        return _sir_seterror(_SIR_E_INVALID);
1,998✔
1059

1060
    struct tm timebuf = {0};
2,165,980✔
1061
    size_t fmttime    = strftime(buffer, SIR_MAXTIME, format,
2,165,983✔
1062
        _sir_localtime(&now, &timebuf));
2,165,980✔
1063

1064
    SIR_ASSERT(0 != fmttime);
2,155,982✔
1065
    if (0 == fmttime)
2,136,008✔
1066
        _sir_selflog("error: strftime failed; format string: '%s'", format);
×
1067

1068
    return 0 != fmttime;
2,165,983✔
1069
}
1070

1071
bool _sir_clock_gettime(time_t* tbuf, long* msecbuf) {
2,148,936✔
1072
    if (tbuf) {
2,148,936✔
1073
        time_t ret = time(tbuf);
2,148,936✔
1074
        if ((time_t)-1 == ret) {
2,148,936✔
1075
            if (msecbuf)
7,910✔
1076
                *msecbuf = 0;
7,910✔
1077
            return _sir_handleerr(errno);
7,910✔
1078
        }
1079
#if defined(SIR_MSEC_POSIX)
1080
        struct timespec ts = {0};
2,141,026✔
1081
        int clock          = clock_gettime(SIR_MSECCLOCK, &ts);
2,141,026✔
1082
        SIR_ASSERT(0 == clock);
2,133,116✔
1083

1084
        if (0 == clock) {
2,125,206✔
1085
            if (msecbuf)
2,133,156✔
1086
                *msecbuf = (long)(ts.tv_nsec / (long)1e6);
2,133,156✔
1087
        } else {
1088
            if (msecbuf)
7,870✔
1089
                *msecbuf = 0;
7,870✔
1090
            return _sir_handleerr(errno);
7,870✔
1091
        }
1092
#elif defined(SIR_MSEC_MACH)
1093
        kern_return_t retval = KERN_SUCCESS;
1094
        mach_timespec_t mts  = {0};
1095
        clock_serv_t clock;
1096

1097
        host_get_clock_service(mach_host_self(), SIR_MSECCLOCK, &clock);
1098
        retval = clock_get_time(clock, &mts);
1099
        mach_port_deallocate(mach_task_self(), clock);
1100

1101
        if (KERN_SUCCESS == retval) {
1102
            if (msecbuf)
1103
                *msecbuf = (mts.tv_nsec / (long)1e6);
1104
        } else {
1105
            if (msecbuf)
1106
                *msecbuf = 0;
1107
            return _sir_handleerr(retval);
1108
        }
1109
#elif defined(SIR_MSEC__WIN__)
1110
        static const ULONGLONG uepoch = (ULONGLONG)116444736e9;
1111

1112
        FILETIME ftutc = {0};
1113
        GetSystemTimePreciseAsFileTime(&ftutc);
1114

1115
        ULARGE_INTEGER ftnow = {0};
1116
        ftnow.HighPart = ftutc.dwHighDateTime;
1117
        ftnow.LowPart  = ftutc.dwLowDateTime;
1118
        ftnow.QuadPart = (ULONGLONG)((ftnow.QuadPart - uepoch) / 1e7);
1119

1120
        *tbuf = (time_t)ftnow.QuadPart;
1121

1122
        SYSTEMTIME st = {0};
1123
        if (FileTimeToSystemTime(&ftutc, &st)) {
1124
            if (msecbuf)
1125
                *msecbuf = st.wMilliseconds;
1126
        } else {
1127
            if (msecbuf)
1128
                *msecbuf = 0;
1129
            return _sir_handlewin32err(GetLastError());
1130
        }
1131

1132
#else
1133
        time(tbuf);
1134
        if (msecbuf)
1135
            *msecbuf = 0;
1136
#endif
1137
        return true;
2,133,156✔
1138
    }
1139
    return false;
×
1140
}
1141

1142
pid_t _sir_getpid(void) {
680✔
1143
#if !defined(__WIN__)
1144
    return getpid();
680✔
1145
#else /* __WIN__ */
1146
    return (pid_t)GetCurrentProcessId();
1147
#endif
1148
}
1149

1150
pid_t _sir_gettid(void) {
2,149,013✔
1151
    pid_t tid = 0;
2,125,271✔
1152
#if defined(__MACOS__)
1153
    uint64_t tid64 = 0;
1154
    int gettid     = pthread_threadid_np(NULL, &tid64);
1155
    if (0 != gettid)
1156
        (void)_sir_handleerr(gettid);
1157
    tid = (pid_t)tid64;
1158
#elif (defined(__BSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)) || \
1159
      defined(__DragonFly_getthreadid__)
1160
    tid = (pid_t)pthread_getthreadid_np();
1161
#elif defined(__OpenBSD__)
1162
    tid = (pid_t)getthrid();
1163
#elif defined(__SOLARIS__) || defined(__NetBSD__) || \
1164
      defined(__DragonFly__) || defined(__CYGWIN__) || defined(_AIX)
1165
    tid = (pid_t)pthread_self();
1166
#elif defined(__HAIKU__)
1167
    tid = get_pthread_thread_id(pthread_self());
1168
#elif defined(__linux__) || defined(__serenity__)
1169
# if (defined(__GLIBC__) && (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 30)) || \
1170
     defined(__serenity__)
1171
    tid = gettid();
2,149,013✔
1172
# else
1173
    tid = syscall(SYS_gettid);
1174
# endif
1175
#elif defined(__WIN__)
1176
    tid = (pid_t)GetCurrentThreadId();
1177
#else
1178
# error "cannot determine how to get thread id; please contact the author"
1179
#endif
1180
    return tid;
2,149,013✔
1181
}
1182

1183
bool _sir_getthreadname(char name[SIR_MAXPID]) {
68,152✔
1184
#if (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1185
     (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \
1186
      defined(USE_PTHREAD_GETNAME_NP) || defined(__MACOS__)
1187
    int ret = pthread_getname_np(pthread_self(), name, SIR_MAXPID);
68,152✔
1188
    if (0 != ret)
68,152✔
1189
        return _sir_handleerr(ret);
×
1190

1191
# if defined(__HAIKU__)
1192
    if ((strncmp(name, "pthread_func", SIR_MAXPID)) || _sir_validstrnofail(name))
1193
        (void)snprintf(name, SIR_MAXPID, "%ld", (long)get_pthread_thread_id(pthread_self()));
1194
# endif
1195
    return _sir_validstrnofail(name);
68,152✔
1196
#elif defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1197
    pthread_get_name_np(pthread_self(), name, SIR_MAXPID);
1198
    return _sir_validstrnofail(name);
1199
#else
1200
# if !defined(_AIX)
1201
#  pragma message("unable to determine how to get a thread name")
1202
# endif
1203
    SIR_UNUSED(name);
1204
    return false;
1205
#endif
1206
}
1207

1208
bool _sir_gethostname(char name[SIR_MAXHOST]) {
8,279✔
1209
#if !defined(__WIN__)
1210
    int ret = gethostname(name, SIR_MAXHOST - 1);
8,216✔
1211
    return 0 == ret ? true : _sir_handleerr(errno);
8,279✔
1212
#else
1213
    WSADATA wsad = {0};
1214
    int ret      = WSAStartup(MAKEWORD(2, 2), &wsad);
1215
    if (0 != ret)
1216
        return _sir_handlewin32err(ret);
1217

1218
    if (SOCKET_ERROR == gethostname(name, SIR_MAXHOST)) {
1219
        int err = WSAGetLastError();
1220
        WSACleanup();
1221
        return _sir_handlewin32err(err);
1222
    }
1223

1224
    WSACleanup();
1225
    return true;
1226
#endif /* !__WIN__ */
1227
}
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