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

aremmell / libsir / 269

29 Aug 2023 01:25PM UTC coverage: 94.858% (-0.03%) from 94.892%
269

Pull #243

gitlab-ci

web-flow
Merge branch 'master' into johnsonjh/20230829/attr
Pull Request #243: Performance improvement via attribute hinting

2 of 2 new or added lines in 1 file covered. (100.0%)

3007 of 3170 relevant lines covered (94.86%)

600364.0 hits per line

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

94.4
/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_once cfg_once   = SIR_ONCE_INIT;
49

50
static sir_mutex fc_mutex  = SIR_MUTEX_INIT;
51
static sir_once fc_once    = SIR_ONCE_INIT;
52

53
static sir_mutex pc_mutex  = SIR_MUTEX_INIT;
54
static sir_once pc_once    = SIR_ONCE_INIT;
55

56
static sir_mutex ts_mutex  = SIR_MUTEX_INIT;
57
static sir_once ts_once    = SIR_ONCE_INIT;
58

59
static sir_once magic_once = SIR_ONCE_INIT;
60

61
#if defined(__HAVE_ATOMIC_H__)
62
static atomic_uint_fast32_t _sir_magic;
63
#else
64
static volatile uint32_t _sir_magic;
65
#endif
66

67
bool _sir_makeinit(sirinit* si) {
55✔
68
    bool retval = _sir_validptr(si);
55✔
69

70
    if (retval) {
55✔
71
        memset(si, 0, sizeof(sirinit));
49✔
72

73
        si->d_stdout.opts   = SIRO_DEFAULT;
55✔
74
        si->d_stdout.levels = SIRL_DEFAULT;
55✔
75

76
        si->d_stderr.opts   = SIRO_DEFAULT;
55✔
77
        si->d_stderr.levels = SIRL_DEFAULT;
55✔
78

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

88
    return retval;
55✔
89
}
90

91
bool _sir_init(sirinit* si) {
779✔
92
    (void)_sir_seterror(_SIR_E_NOERROR);
779✔
93
    _sir_once(&magic_once, _sir_initialize_once);
779✔
94

95
    if (!_sir_validptr(si))
779✔
96
        return false;
19✔
97

98
#if defined(__HAVE_ATOMIC_H__)
99
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
757✔
100
#else
101
    if (_SIR_MAGIC == _sir_magic)
102
#endif
103
        return _sir_seterror(_SIR_E_ALREADY);
23✔
104

105
    _sir_defaultlevels(&si->d_stdout.levels, sir_stdout_def_lvls);
734✔
106
    _sir_defaultopts(&si->d_stdout.opts, sir_stdout_def_opts);
632✔
107

108
    _sir_defaultlevels(&si->d_stderr.levels, sir_stderr_def_lvls);
632✔
109
    _sir_defaultopts(&si->d_stderr.opts, sir_stderr_def_opts);
632✔
110

111
#if !defined(SIR_NO_SYSTEM_LOGGERS)
112
    _sir_defaultlevels(&si->d_syslog.levels, sir_syslog_def_lvls);
452✔
113
    _sir_defaultopts(&si->d_syslog.opts, sir_syslog_def_opts);
452✔
114
#endif
115

116
    if (!_sir_init_sanity(si))
734✔
117
        return false;
19✔
118

119
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
712✔
120

121
#if !defined(__WIN__)
122
    tzset();
712✔
123
#endif
124

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

131
#if defined(__WIN__)
132
    _sir_initialize_stdio();
133
#endif
134

135
    _sir_setcolormode(SIRCM_16);
712✔
136

137
    if (!_sir_resettextstyles())
712✔
138
        _sir_selflog("error: failed to reset text styles!");
×
139

140
    memset(&_cfg->state, 0, sizeof(_cfg->state));
712✔
141
    memcpy(&_cfg->si, si, sizeof(sirinit));
712✔
142

143
    /* forcibly null-terminate the process name. */
144
    _cfg->si.name[SIR_MAXNAME - 1] = '\0';
712✔
145

146
    /* Store PID. */
147
    _cfg->state.pid = _sir_getpid();
712✔
148

149
    (void)snprintf(_cfg->state.pidbuf, SIR_MAXPID, SIR_PIDFORMAT,
712✔
150
        PID_CAST _cfg->state.pid);
151

152
#if !defined(SIR_NO_SYSTEM_LOGGERS)
153
    /* initialize system logger. */
154
    _sir_syslog_reset(&_cfg->si.d_syslog);
538✔
155

156
    if (_cfg->si.d_syslog.levels != SIRL_NONE) {
538✔
157
        if (!_sir_syslog_init(_cfg->si.name, &_cfg->si.d_syslog))
96✔
158
            _sir_selflog("failed to initialize system logger!");
×
159
    }
160
#endif
161

162
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
712✔
163

164
    return true;
712✔
165
}
166

167
bool _sir_cleanup(void) {
734✔
168
    if (!_sir_sanity())
734✔
169
        return false;
19✔
170

171
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
712✔
172
    bool cleanup   = true;
613✔
173
    bool destroyfc = _sir_fcache_destroy(sfc);
712✔
174
    SIR_ASSERT(destroyfc);
679✔
175

176
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
712✔
177
    cleanup &= destroyfc;
613✔
178

179
#if !defined(SIR_NO_PLUGINS)
180
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
671✔
181
    bool destroypc = _sir_plugin_cache_destroy(spc);
671✔
182
    SIR_ASSERT(destroypc);
638✔
183
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
671✔
184
    cleanup &= destroypc;
572✔
185
#endif
186

187
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
712✔
188

189
#if !defined(SIR_NO_SYSTEM_LOGGERS)
190
    if (!_sir_syslog_close(&_cfg->si.d_syslog)) {
538✔
191
        cleanup = false;
×
192
        _sir_selflog("error: failed to close system logger!");
×
193
    }
194

195
    _sir_syslog_reset(&_cfg->si.d_syslog);
538✔
196
#endif
197

198
    if (!_sir_resettextstyles()) {
712✔
199
        cleanup = false;
×
200
        _sir_selflog("error: failed to reset text styles!");
×
201
    }
202

203
#if defined(__HAVE_ATOMIC_H__)
204
    atomic_store(&_sir_magic, 0);
712✔
205
#else
206
    _sir_magic = 0u;
207
#endif
208

209
    memset(_cfg, 0ul, sizeof(sirconfig));
613✔
210
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
712✔
211

212
    _sir_selflog("cleanup: %s", (cleanup ? "successful" : "with errors"));
679✔
213

214
    SIR_ASSERT(cleanup);
679✔
215
    return cleanup;
613✔
216
}
217

218
bool _sir_sanity(void) {
2,498,789✔
219
#if defined(__HAVE_ATOMIC_H__)
220
    if (_SIR_MAGIC == atomic_load(&_sir_magic))
2,498,789✔
221
        return true;
2,418,545✔
222
#else
223
    if (_SIR_MAGIC == _sir_magic)
224
        return true;
225
#endif
226
    return _sir_seterror(_SIR_E_NOTREADY);
42✔
227
}
228

229
bool _sir_init_sanity(const sirinit* si) {
734✔
230
    if (!_sir_validptr(si))
734✔
231
        return false;
×
232

233
    bool levelcheck = true;
632✔
234
    levelcheck &= _sir_validlevels(si->d_stdout.levels);
734✔
235
    levelcheck &= _sir_validlevels(si->d_stderr.levels);
734✔
236

237
#if !defined(SIR_NO_SYSTEM_LOGGERS)
238
    levelcheck &= _sir_validlevels(si->d_syslog.levels);
554✔
239
#endif
240

241
    bool optscheck = true;
632✔
242
    optscheck &= _sir_validopts(si->d_stdout.opts);
734✔
243
    optscheck &= _sir_validopts(si->d_stderr.opts);
734✔
244

245
#if !defined(SIR_NO_SYSTEM_LOGGERS)
246
    optscheck &= _sir_validopts(si->d_syslog.opts);
554✔
247
#endif
248

249
    return levelcheck && optscheck;
734✔
250
}
251

252
static
253
bool _sir_updatelevels(const char* name, sir_levels* old, sir_levels* new) {
861✔
254
    if (*old != *new) {
861✔
255
        _sir_selflog("updating %s levels from %04"PRIx16" to %04"PRIx16, name, *old, *new);
778✔
256
        *old = *new;
823✔
257
    } else {
258
        _sir_selflog("skipped superfluous update of %s levels: %04"PRIx16, name, *old);
36✔
259
    }
260
    return true;
861✔
261
}
262

263
static
264
bool _sir_updateopts(const char* name, sir_options* old, sir_options* new) {
72,817✔
265
    if (*old != *new) {
72,817✔
266
        _sir_selflog("updating %s options from %08"PRIx32" to %08"PRIx32, name, *old, *new);
35,963✔
267
        *old = *new;
38,022✔
268
    } else {
269
        _sir_selflog("skipped superfluous update of %s options: %08"PRIx32, name, *old);
32,809✔
270
    }
271
    return true;
72,817✔
272
}
273

274
bool _sir_stdoutlevels(sirinit* si, sir_update_config_data* data) {
424✔
275
    return _sir_updatelevels(SIR_DESTNAME_STDOUT, &si->d_stdout.levels, data->levels);
424✔
276
}
277

278
bool _sir_stdoutopts(sirinit* si, sir_update_config_data* data) {
72,380✔
279
    return _sir_updateopts(SIR_DESTNAME_STDOUT, &si->d_stdout.opts, data->opts);
72,380✔
280
}
281

282
bool _sir_stderrlevels(sirinit* si, sir_update_config_data* data) {
380✔
283
    return _sir_updatelevels(SIR_DESTNAME_STDERR, &si->d_stderr.levels, data->levels);
380✔
284
}
285

286
bool _sir_stderropts(sirinit* si, sir_update_config_data* data) {
380✔
287
    return _sir_updateopts(SIR_DESTNAME_STDERR, &si->d_stderr.opts, data->opts);
380✔
288
}
289

290
bool _sir_sysloglevels(sirinit* si, sir_update_config_data* data) {
57✔
291
    bool updated = _sir_updatelevels(SIR_DESTNAME_SYSLOG, &si->d_syslog.levels, data->levels);
57✔
292
    if (updated) {
57✔
293
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
48✔
294
        updated = _sir_syslog_updated(si, data);
57✔
295
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_LEVELS);
48✔
296
    }
297
    return updated;
57✔
298
}
299

300
bool _sir_syslogopts(sirinit* si, sir_update_config_data* data) {
57✔
301
    bool updated = _sir_updateopts(SIR_DESTNAME_SYSLOG, &si->d_syslog.opts, data->opts);
57✔
302
    if (updated) {
57✔
303
        _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
48✔
304
        updated = _sir_syslog_updated(si, data);
57✔
305
        _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_OPTIONS);
48✔
306
    }
307
    return updated;
57✔
308
}
309

310
bool _sir_syslogid(sirinit* si, sir_update_config_data* data) {
118✔
311
    bool cur_valid = _sir_validstrnofail(si->d_syslog.identity);
118✔
312
    if (!cur_valid || 0 != strncmp(si->d_syslog.identity, data->sl_identity, SIR_MAX_SYSLOG_ID)) {
118✔
313
        _sir_selflog("updating %s identity from '%s' to '%s'", SIR_DESTNAME_SYSLOG,
68✔
314
            si->d_syslog.identity, data->sl_identity);
315
        _sir_strncpy(si->d_syslog.identity, SIR_MAX_SYSLOG_ID, data->sl_identity,
72✔
316
            strnlen(data->sl_identity, SIR_MAX_SYSLOG_ID));
317
    } else {
318
        _sir_selflog("skipped superfluous update of %s identity: '%s'", SIR_DESTNAME_SYSLOG,
43✔
319
            si->d_syslog.identity);
320
        return true;
43✔
321
    }
322

323
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
60✔
324
    bool updated = _sir_syslog_updated(si, data);
72✔
325
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_IDENTITY);
60✔
326

327
    return updated;
72✔
328
}
329

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

343
    _sir_setbitshigh(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
38✔
344
    bool updated = _sir_syslog_updated(si, data);
47✔
345
    _sir_setbitslow(&si->d_syslog._state.mask, SIRSL_UPDATED | SIRSL_CATEGORY);
38✔
346

347
    return updated;
47✔
348
}
349

350
bool _sir_writeinit(sir_update_config_data* data, sirinit_update update) {
73,883✔
351
    (void)_sir_seterror(_SIR_E_NOERROR);
73,883✔
352

353
    if (!_sir_sanity() || !_sir_validupdatedata(data) || !_sir_validfnptr(update))
73,885✔
354
        return false;
×
355

356
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
73,886✔
357

358
    bool updated = update(&_cfg->si, data);
73,890✔
359
    if (!updated)
69,785✔
360
        _sir_selflog("error: update routine failed!");
×
361

362
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
73,890✔
363
    return updated;
73,890✔
364
}
365

366
void* _sir_locksection(sir_mutex_id mid) {
9,058,048✔
367
    sir_mutex* m = NULL;
9,058,048✔
368
    void* sec    = NULL;
9,058,048✔
369

370
    bool enter = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexlock(m);
9,058,048✔
371
    SIR_ASSERT(enter);
9,003,448✔
372

373
    return enter ? sec : NULL;
9,058,883✔
374
}
375

376
void _sir_unlocksection(sir_mutex_id mid) {
9,058,974✔
377
    sir_mutex* m = NULL;
9,058,974✔
378
    void* sec    = NULL;
9,058,974✔
379

380
    bool leave = _sir_mapmutexid(mid, &m, &sec) && _sir_mutexunlock(m);
9,058,974✔
381
    SIR_ASSERT_UNUSED(leave, leave);
9,004,178✔
382
}
9,059,844✔
383

384
bool _sir_mapmutexid(sir_mutex_id mid, sir_mutex** m, void** section) {
18,113,727✔
385
    sir_mutex* tmpm;
386
    void* tmpsec;
387

388
    switch (mid) {
18,113,727✔
389
        case SIRMI_CONFIG:
8,777,518✔
390
            _sir_once(&cfg_once, _sir_initmutex_cfg_once);
8,777,518✔
391
            tmpm   = &cfg_mutex;
8,657,834✔
392
            tmpsec = &_sir_cfg;
8,657,834✔
393
            break;
8,777,541✔
394
        case SIRMI_FILECACHE:
4,472,701✔
395
            _sir_once(&fc_once, _sir_initmutex_fc_once);
4,472,701✔
396
            tmpm   = &fc_mutex;
4,397,111✔
397
            tmpsec = &_sir_fc;
4,397,111✔
398
            break;
4,472,764✔
399
        case SIRMI_PLUGINCACHE:
240,042✔
400
            _sir_once(&pc_once, _sir_initmutex_pc_once);
240,042✔
401
            tmpm   = &pc_mutex;
200,808✔
402
            tmpsec = &_sir_pc;
200,808✔
403
            break;
240,042✔
404
        case SIRMI_TEXTSTYLE:
4,628,980✔
405
            _sir_once(&ts_once, _sir_initmutex_ts_once);
4,628,980✔
406
            tmpm   = &ts_mutex;
4,529,786✔
407
            tmpsec = &sir_text_style_section;
4,529,786✔
408
            break;
4,629,000✔
409
        // GCOVR_EXCL_START
410
        default: /* this should never happen. */
411
            SIR_ASSERT("!invalid mutex id");
412
            tmpm   = NULL;
413
            tmpsec = NULL;
414
            break;
415
        // GCOVR_EXCL_STOP
416
    }
417

418
    *m = tmpm;
18,113,833✔
419

420
    if (section)
18,113,833✔
421
        *section = tmpsec;
18,113,814✔
422

423
    return *m != NULL && (!section || *section != NULL);
18,113,833✔
424
}
425

426
#if !defined(__WIN__)
427
void _sir_initialize_once(void) {
57✔
428
# if defined(__HAVE_ATOMIC_H__)
429
    atomic_init(&_sir_magic, 0);
57✔
430
# endif
431
}
57✔
432

433
void _sir_initmutex_cfg_once(void) {
57✔
434
    bool created = _sir_mutexcreate(&cfg_mutex);
57✔
435
    SIR_ASSERT_UNUSED(created, created);
55✔
436
}
57✔
437

438
void _sir_initmutex_fc_once(void) {
57✔
439
    bool created = _sir_mutexcreate(&fc_mutex);
57✔
440
    SIR_ASSERT_UNUSED(created, created);
55✔
441
}
57✔
442

443
void _sir_initmutex_pc_once(void) {
48✔
444
    bool created = _sir_mutexcreate(&pc_mutex);
48✔
445
    SIR_ASSERT_UNUSED(created, created);
46✔
446
}
48✔
447

448
void _sir_initmutex_ts_once(void) {
57✔
449
    bool created = _sir_mutexcreate(&ts_mutex);
57✔
450
    SIR_ASSERT_UNUSED(created, created);
55✔
451
}
57✔
452

453
#else /* __WIN__ */
454
BOOL CALLBACK _sir_initialize_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
455
    SIR_UNUSED(ponce);
456
    SIR_UNUSED(param);
457
    SIR_UNUSED(ctx);
458
    return TRUE;
459
}
460

461
BOOL CALLBACK _sir_initmutex_cfg_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
462
    SIR_UNUSED(ponce);
463
    SIR_UNUSED(param);
464
    SIR_UNUSED(ctx);
465

466
    if (!_sir_mutexcreate(&cfg_mutex)) {
467
        SIR_ASSERT(!"failed to create mutex!");
468
        return FALSE;
469
    }
470

471
    return TRUE;
472
}
473

474
BOOL CALLBACK _sir_initmutex_fc_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
475
    SIR_UNUSED(ponce);
476
    SIR_UNUSED(param);
477
    SIR_UNUSED(ctx);
478

479
    if (!_sir_mutexcreate(&fc_mutex)) {
480
        SIR_ASSERT(!"failed to create mutex!");
481
        return FALSE;
482
    }
483

484
    return TRUE;
485
}
486

487
BOOL CALLBACK _sir_initmutex_pc_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
488
    SIR_UNUSED(ponce);
489
    SIR_UNUSED(param);
490
    SIR_UNUSED(ctx);
491

492
    if (!_sir_mutexcreate(&pc_mutex)) {
493
        SIR_ASSERT(!"failed to create mutex!");
494
        return FALSE;
495
    }
496

497
    return TRUE;
498
}
499

500
BOOL CALLBACK _sir_initmutex_ts_once(PINIT_ONCE ponce, PVOID param, PVOID* ctx) {
501
    SIR_UNUSED(ponce);
502
    SIR_UNUSED(param);
503
    SIR_UNUSED(ctx);
504

505
    if (!_sir_mutexcreate(&ts_mutex)) {
506
        SIR_ASSERT(!"failed to create mutex!");
507
        return FALSE;
508
    }
509

510
    return TRUE;
511
}
512
#endif
513

514
bool _sir_once(sir_once* once, sir_once_fn func) {
18,113,411✔
515
#if !defined(__WIN__)
516
    int ret = pthread_once(once, func);
18,113,411✔
517
    return 0 == ret ? true : _sir_handleerr(ret);
18,114,035✔
518
#else /* __WIN__ */
519
    return (FALSE != InitOnceExecuteOnce(once, func, NULL, NULL)) ? true
520
        : _sir_handlewin32err(GetLastError());
521
#endif
522
}
523

524
FLATTEN_ATTR
525
PRINTF_FORMAT_ATTR(2, 0)
526
bool _sir_logv(sir_level level, PRINTF_FORMAT const char* format, va_list args) {
2,156,851✔
527
    if (!_sir_sanity() || !_sir_validlevel(level) || !_sir_validstr(format))
2,156,851✔
528
        return false;
44✔
529

530
    (void)_sir_seterror(_SIR_E_NOERROR);
2,156,807✔
531

532
    _SIR_LOCK_SECTION(sirconfig, _cfg, SIRMI_CONFIG, false);
2,156,807✔
533

534
    /* from time to time, update the host name in the config, just in case. */
535
    time_t now = -1;
2,156,811✔
536
    if (-1 != time(&now) &&
2,156,811✔
537
        (now - _cfg->state.last_hname_chk) > SIR_HNAME_CHK_INTERVAL) { //-V522
2,148,902✔
538
        _sir_selflog("updating hostname...");
8,277✔
539
        if (!_sir_gethostname(_cfg->state.hostname)) {
8,298✔
540
            _sir_selflog("error: failed to get hostname!");
7,909✔
541
        } else {
542
            _cfg->state.last_hname_chk = now;
389✔
543
            _sir_selflog("hostname: '%s'", _cfg->state.hostname);
368✔
544
        }
545
    }
546

547
    sirconfig cfg;
548
    memcpy(&cfg, _cfg, sizeof(sirconfig));
2,133,084✔
549
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,156,811✔
550

551
    sirbuf buf = {
2,156,810✔
552
        {0},
553
        {0},
554
        {0},
555
        cfg.state.hostname,
556
        cfg.state.pidbuf,
557
        NULL,
558
        cfg.si.name,
559
        {0},
560
        {0},
561
        {0},
562
         0
563
    };
564

565
    bool fmt              = false;
2,133,084✔
566
    const char* style_str = _sir_gettextstyle(level);
2,156,810✔
567

568
    SIR_ASSERT(NULL != style_str);
2,148,902✔
569
    if (NULL != style_str)
2,140,993✔
570
        fmt = (0 == _sir_strncpy(buf.style, SIR_MAXSTYLE, style_str,
2,156,811✔
571
            strnlen(style_str, SIR_MAXSTYLE)));
572
    SIR_ASSERT_UNUSED(fmt, fmt);
2,148,902✔
573

574
    now          = -1;
2,156,811✔
575
    long nowmsec = 0;
2,156,811✔
576
    bool gettime = _sir_clock_gettime(&now, &nowmsec);
2,156,811✔
577
    SIR_ASSERT(gettime);
2,148,902✔
578

579
    if (gettime) {
2,140,990✔
580
        fmt = _sir_formattime(now, buf.timestamp, SIR_TIMEFORMAT);
2,141,030✔
581
        SIR_ASSERT_UNUSED(fmt, fmt);
2,133,124✔
582

583
        (void)snprintf(buf.msec, SIR_MAXMSEC, SIR_MSECFORMAT, nowmsec);
2,141,033✔
584
    }
585

586
    buf.level = _sir_formattedlevelstr(level);
2,156,811✔
587

588
    pid_t tid = _sir_gettid();
2,156,811✔
589
    if (tid != cfg.state.pid)
2,156,804✔
590
        if (!_sir_getthreadname(buf.tid) || !_sir_validstrnofail(buf.tid))
72,146✔
591
            (void)snprintf(buf.tid, SIR_MAXPID, SIR_PIDFORMAT, PID_CAST tid);
×
592

593
    (void)vsnprintf(buf.message, SIR_MAXMESSAGE, format, args);
2,133,084✔
594

595
    if (!_sir_validstr(buf.message))
2,156,797✔
596
        return _sir_seterror(_SIR_E_INTERNAL);
22✔
597

598
    bool match             = false;
2,133,065✔
599
    bool exit_early        = false;
2,133,065✔
600
    bool update_last_props = true;
2,133,065✔
601
    uint64_t hash          = 0ull;
2,133,065✔
602

603
    if (cfg.state.last.prefix[0] == buf.message[0]  &&
2,156,775✔
604
        cfg.state.last.prefix[1] == buf.message[1]) {
2,102,573✔
605
        hash  = FNV64_1a(buf.message);
2,102,030✔
606
        match = cfg.state.last.hash == hash;
2,120,830✔
607
    }
608

609
    if (match) {
2,151,865✔
610
        cfg.state.last.counter++;
33,636✔
611

612
        /* _sir_selflog("message '%s' matches last; incremented counter to %zu", buf.message,
613
            cfg.state.last.counter); */
614

615
        if (cfg.state.last.counter >= cfg.state.last.threshold - 2) {
33,636✔
616
            size_t old_threshold = cfg.state.last.threshold;
915✔
617

618
            update_last_props = false;
915✔
619
            cfg.state.last.threshold *= SIR_SQUELCH_BACKOFF_FACTOR;
1,059✔
620
            cfg.state.last.squelch = true;
1,059✔
621

622
            _sir_selflog("hit squelch threshold of %zu; setting new threshold"
1,011✔
623
                         " to %zu (factor: %d)",
624
                old_threshold, cfg.state.last.threshold, SIR_SQUELCH_BACKOFF_FACTOR);
625

626
            (void)snprintf(buf.message, SIR_MAXMESSAGE, SIR_SQUELCH_MSG_FORMAT, old_threshold);
915✔
627
        } else if (cfg.state.last.squelch) {
32,577✔
628
            exit_early = true;
26,735✔
629
        }
630
    } else {
631
        cfg.state.last.squelch   = false;
2,123,139✔
632
        cfg.state.last.counter   = 0;
2,123,139✔
633
        cfg.state.last.threshold = SIR_SQUELCH_THRESHOLD;
2,123,139✔
634
        /* _sir_selflog("message '%s' does not match last; resetting", buf.message); */
635
    }
636

637
    _cfg = _sir_locksection(SIRMI_CONFIG);
2,156,775✔
638
    if (!_cfg)
2,156,789✔
639
        return _sir_seterror(_SIR_E_INTERNAL);
×
640

641
    _cfg->state.last.squelch = cfg.state.last.squelch;
2,156,789✔
642

643
    if (update_last_props) {
2,156,789✔
644
        _cfg->state.last.hash      = hash;
2,155,730✔
645
        _cfg->state.last.prefix[0] = buf.message[0];
2,155,730✔
646
        _cfg->state.last.prefix[1] = buf.message[1];
2,155,730✔
647
    }
648

649
    _cfg->state.last.counter   = cfg.state.last.counter;
2,156,789✔
650
    _cfg->state.last.threshold = cfg.state.last.threshold;
2,156,789✔
651

652
    _SIR_UNLOCK_SECTION(SIRMI_CONFIG);
2,156,789✔
653

654
    if (exit_early)
2,156,776✔
655
        return false;
26,735✔
656

657
    bool dispatched = _sir_dispatch(&cfg.si, level, &buf);
2,125,820✔
658
    return update_last_props ? dispatched : false;
2,125,833✔
659
}
660

661
bool _sir_dispatch(sirinit* si, sir_level level, sirbuf* buf) {
2,125,816✔
662
    bool retval       = true;
2,106,314✔
663
    size_t dispatched = 0;
2,106,314✔
664
    size_t wanted     = 0;
2,106,314✔
665

666
    if (_sir_bittest(si->d_stdout.levels, level)) {
4,232,130✔
667
        const char* write = _sir_format(true, si->d_stdout.opts, buf);
1,122,189✔
668
        bool wrote        = _sir_validstrnofail(write) &&
2,244,398✔
669
            _sir_write_stdout(write, buf->output_len);
2,206,572✔
670
        retval &= wrote;
1,122,199✔
671

672
        if (wrote)
1,122,199✔
673
            dispatched++;
1,097,077✔
674
        wanted++;
1,103,288✔
675
    }
676

677
    if (_sir_bittest(si->d_stderr.levels, level)) {
4,232,150✔
678
        const char* write = _sir_format(true, si->d_stderr.opts, buf);
1,099✔
679
        bool wrote        = _sir_validstrnofail(write) &&
2,198✔
680
            _sir_write_stderr(write, buf->output_len);
1,856✔
681
        retval &= wrote;
1,099✔
682

683
        if (wrote)
1,099✔
684
            dispatched++;
1,090✔
685
        wanted++;
1,099✔
686
    }
687

688
#if !defined(SIR_NO_SYSTEM_LOGGERS)
689
    if (_sir_bittest(si->d_syslog.levels, level)) {
4,163,430✔
690
        if (_sir_syslog_write(level, buf, &si->d_syslog))
594✔
691
            dispatched++;
594✔
692
        wanted++;
594✔
693
    }
694
#endif
695

696
    _SIR_LOCK_SECTION(sirfcache, sfc, SIRMI_FILECACHE, false);
2,125,826✔
697
    size_t fdispatched = 0;
2,125,833✔
698
    size_t fwanted     = 0;
2,125,833✔
699
    retval &= _sir_fcache_dispatch(sfc, level, buf, &fdispatched, &fwanted);
2,125,833✔
700
    _SIR_UNLOCK_SECTION(SIRMI_FILECACHE);
2,125,833✔
701

702
    dispatched += fdispatched;
2,125,833✔
703
    wanted += fwanted;
2,125,833✔
704

705
#if !defined(SIR_NO_PLUGINS)
706
    _SIR_LOCK_SECTION(sir_plugincache, spc, SIRMI_PLUGINCACHE, false);
119,257✔
707
    size_t pdispatched = 0;
119,257✔
708
    size_t pwanted     = 0;
119,257✔
709
    retval &= _sir_plugin_cache_dispatch(spc, level, buf, &pdispatched, &pwanted);
119,257✔
710
    _SIR_UNLOCK_SECTION(SIRMI_PLUGINCACHE);
119,257✔
711

712
    dispatched += pdispatched;
119,257✔
713
    wanted += pwanted;
119,257✔
714
#endif
715

716
    if (0 == wanted) {
2,125,833✔
717
        _sir_selflog("error: no destinations registered for level %04"PRIx16, level);
897✔
718
        return _sir_seterror(_SIR_E_NODEST);
950✔
719
    }
720

721
    return retval && (dispatched == wanted);
2,124,883✔
722
}
723

724
const char* _sir_format(bool styling, sir_options opts, sirbuf* buf) {
2,276,934✔
725
    if (_sir_validptr(buf)) {
2,276,934✔
726
        bool first = true;
2,231,959✔
727

728
        _sir_resetstr(buf->output);
2,231,959✔
729

730
        if (styling)
2,276,950✔
731
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->style, SIR_MAXSTYLE);
1,123,289✔
732

733
        if (!_sir_bittest(opts, SIRO_NOTIME)) {
2,276,936✔
734
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->timestamp, SIR_MAXTIME);
2,110,171✔
735
            first = false;
2,090,984✔
736

737
#if defined(SIR_MSEC_TIMER)
738
            if (!_sir_bittest(opts, SIRO_NOMSEC))
2,110,177✔
739
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->msec, SIR_MAXMSEC);
73,699✔
740
#endif
741
        }
742

743
        if (!_sir_bittest(opts, SIRO_NOHOST) && _sir_validstrnofail(buf->hostname)) {
2,276,962✔
744
            if (!first)
1,033,408✔
745
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,001,538✔
746
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->hostname, SIR_MAXHOST);
1,033,408✔
747
            first = false;
1,027,153✔
748
        }
749

750
        if (!_sir_bittest(opts, SIRO_NOLEVEL)) {
2,276,981✔
751
            if (!first)
2,160,640✔
752
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
2,110,341✔
753
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->level, SIR_MAXLEVEL);
2,160,632✔
754
            first = false;
2,134,526✔
755
        }
756

757
        bool name = false;
2,231,980✔
758
        if (!_sir_bittest(opts, SIRO_NONAME) && _sir_validstrnofail(buf->name)) {
2,277,012✔
759
            if (!first)
1,103,873✔
760
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,099,946✔
761
            _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->name, SIR_MAXNAME);
1,103,875✔
762
            first = false;
1,084,825✔
763
            name  = true;
1,084,825✔
764
        }
765

766
        bool wantpid = !_sir_bittest(opts, SIRO_NOPID) && _sir_validstrnofail(buf->pid);
2,277,033✔
767
        bool wanttid = !_sir_bittest(opts, SIRO_NOTID) && _sir_validstrnofail(buf->tid);
2,277,030✔
768

769
        if (wantpid || wanttid) {
2,277,026✔
770
            if (name)
2,146,961✔
771
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDPREFIX, 1);
1,102,090✔
772
            else if (!first)
1,044,871✔
773
                _sir_strncat(buf->output, SIR_MAXOUTPUT, " ", 1);
1,044,865✔
774

775
            if (wantpid)
2,146,964✔
776
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->pid, SIR_MAXPID);
2,076,349✔
777

778
            if (wanttid) {
2,146,957✔
779
                if (wantpid)
142,593✔
780
                    _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSEPARATOR, 1);
72,073✔
781
                _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->tid, SIR_MAXPID);
142,589✔
782
            }
783

784
            if (name)
2,147,000✔
785
                _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_PIDSUFFIX, 1);
1,102,097✔
786

787
            if (first)
2,121,655✔
788
                first = false;
6✔
789
        }
790

791
        if (!first)
2,251,720✔
792
            _sir_strncat(buf->output, SIR_MAXOUTPUT, ": ", 2);
2,196,313✔
793

794
        _sir_strncat(buf->output, SIR_MAXOUTPUT, buf->message, SIR_MAXMESSAGE);
2,276,970✔
795

796
        if (styling)
2,276,981✔
797
            _sir_strncat(buf->output, SIR_MAXOUTPUT, SIR_ESC_RST, SIR_MAXSTYLE);
1,123,287✔
798

799
        _sir_strncat(buf->output, SIR_MAXOUTPUT, "\n", 1);
2,276,978✔
800

801
        buf->output_len = strnlen(buf->output, SIR_MAXOUTPUT);
2,277,010✔
802

803
        return buf->output;
2,277,010✔
804
    }
805

806
    return NULL;
6✔
807
}
808

809
#if defined(SIR_NO_SYSTEM_LOGGERS)
810
CONST_ATTR
811
#endif
812
bool _sir_syslog_init(const char* name, sir_syslog_dest* ctx) {
225✔
813
#if !defined(SIR_NO_SYSTEM_LOGGERS)
814
    if (!_sir_validptr(name) || !_sir_validptr(ctx))
225✔
815
        return false;
×
816

817
    /* begin resolve identity. */
818
    if (!_sir_validstrnofail(ctx->identity)) {
225✔
819
        _sir_selflog("ctx->identity is no good; trying name");
47✔
820
        if (_sir_validstrnofail(name)) {
50✔
821
            _sir_selflog("using name");
28✔
822
            _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, name, strnlen(name, SIR_MAX_SYSLOG_ID));
30✔
823
        } else {
824
            _sir_selflog("name is no good; trying filename");
19✔
825
            char* appbasename = _sir_getappbasename();
20✔
826
            if (_sir_validstrnofail(appbasename)) {
20✔
827
                _sir_selflog("filename is good: %s", appbasename);
13✔
828
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, appbasename,
14✔
829
                    strnlen(appbasename, SIR_MAX_SYSLOG_ID));
830
            } else {
831
                _sir_selflog("filename no good; using fallback");
6✔
832
                _sir_strncpy(ctx->identity, SIR_MAX_SYSLOG_ID, SIR_FALLBACK_SYSLOG_ID,
6✔
833
                    strnlen(SIR_FALLBACK_SYSLOG_ID, SIR_MAX_SYSLOG_ID));
834
            }
835
            _sir_safefree(&appbasename);
20✔
836
        }
837
    } else {
838
        _sir_selflog("already have identity");
165✔
839
    }
840

841
    /* category */
842
    if (!_sir_validstrnofail(ctx->category)) {
225✔
843
        _sir_selflog("category not set; using fallback");
71✔
844
        _sir_strncpy(ctx->category, SIR_MAX_SYSLOG_CAT, SIR_FALLBACK_SYSLOG_CAT,
75✔
845
            strnlen(SIR_FALLBACK_SYSLOG_CAT, SIR_MAX_SYSLOG_CAT));
846
    } else {
847
        _sir_selflog("already have category");
141✔
848
    }
849

850
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_INIT);
186✔
851
    _sir_selflog("resolved (identity: '%s', category: '%s')", ctx->identity, ctx->category);
212✔
852

853
    return _sir_syslog_open(ctx);
225✔
854
#else
855
    SIR_UNUSED(name);
856
    SIR_UNUSED(ctx);
857
    return false;
×
858
#endif
859
}
860

861
#if defined(SIR_NO_SYSTEM_LOGGERS)
862
CONST_ATTR
863
#endif
864
bool _sir_syslog_open(sir_syslog_dest* ctx) {
225✔
865
#if !defined(SIR_NO_SYSTEM_LOGGERS)
866
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
411✔
867
        _sir_selflog("not initialized; ignoring");
×
868
        return _sir_seterror(_SIR_E_INVALID);
×
869
    }
870

871
    if (_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
411✔
872
        _sir_selflog("log already open; ignoring");
97✔
873
        return true;
97✔
874
    }
875

876
    _sir_selflog("opening log (levels: %04"PRIx16", options: %08"PRIx32")", ctx->levels,
115✔
877
        ctx->opts);
878

879
# if defined(SIR_OS_LOG_ENABLED)
880
    ctx->_state.logger = (void*)os_log_create(ctx->identity, ctx->category);
881
    _sir_selflog("opened os_log ('%s', '%s')", ctx->identity, ctx->category);
882
# elif defined(SIR_SYSLOG_ENABLED)
883
    int logopt   = LOG_NDELAY | (_sir_bittest(ctx->opts, SIRO_NOPID) ? 0 : LOG_PID);
223✔
884
    int facility = LOG_USER;
101✔
885

886
    openlog(ctx->identity, logopt, facility);
122✔
887
    _sir_selflog("opened syslog('%s', %x, %x)", ctx->identity, logopt, facility);
115✔
888
# endif
889

890
    _sir_setbitshigh(&ctx->_state.mask, SIRSL_IS_OPEN);
101✔
891
    return true;
122✔
892
#else
893
    SIR_UNUSED(ctx);
894
    return false;
×
895
#endif
896
}
897

898
#if defined(SIR_NO_SYSTEM_LOGGERS)
899
CONST_ATTR
900
#endif
901
bool _sir_syslog_write(sir_level level, const sirbuf* buf, sir_syslog_dest* ctx) {
594✔
902
#if !defined(SIR_NO_SYSTEM_LOGGERS)
903
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_INIT)) {
1,080✔
904
        _sir_selflog("not initialized; ignoring");
×
905
        return _sir_seterror(_SIR_E_INVALID);
×
906
    }
907

908
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
1,080✔
909
        _sir_selflog("log not open; ignoring");
×
910
        return _sir_seterror(_SIR_E_INVALID);
×
911
    }
912

913
# if defined(SIR_OS_LOG_ENABLED)
914
    if (SIRL_DEBUG == level)
915
        os_log_debug((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
916
    else if (SIRL_INFO == level || SIRL_NOTICE == level)
917
        os_log_info((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
918
    else if (SIRL_WARN == level || SIRL_ERROR == level)
919
        os_log_error((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
920
    else if (SIRL_ALERT == level || SIRL_CRIT == level || SIRL_EMERG == level)
921
        os_log_fault((os_log_t)ctx->_state.logger, SIR_OS_LOG_FORMAT, buf->message);
922

923
    return true;
924
# elif defined(SIR_SYSLOG_ENABLED)
925
    int syslog_level;
926
    switch (level) {
594✔
927
        case SIRL_DEBUG:  syslog_level = LOG_DEBUG; break;
25✔
928
        case SIRL_INFO:   syslog_level = LOG_INFO; break;
27✔
929
        case SIRL_NOTICE: syslog_level = LOG_NOTICE; break;
80✔
930
        case SIRL_WARN:   syslog_level = LOG_WARNING; break;
80✔
931
        case SIRL_ERROR:  syslog_level = LOG_ERR; break;
80✔
932
        case SIRL_CRIT:   syslog_level = LOG_CRIT; break;
106✔
933
        case SIRL_ALERT:  syslog_level = LOG_ALERT; break;
80✔
934
        case SIRL_EMERG:  syslog_level = LOG_EMERG; break;
106✔
935
        // GCOVR_EXCL_START
936
        case SIRL_NONE: /* this should never happen. */
937
        case SIRL_ALL:
938
        case SIRL_DEFAULT:
939
        default:
940
            SIR_ASSERT(!"invalid sir_level");
941
            syslog_level = LOG_DEBUG;
942
        // GCOVR_EXCL_STOP
943
    }
944

945
    syslog(syslog_level, "%s", buf->message);
594✔
946
    return true;
594✔
947
# endif
948
#else
949
    SIR_UNUSED(level);
950
    SIR_UNUSED(buf);
951
    SIR_UNUSED(ctx);
952
#endif
953
    return false;
×
954
}
955

956
#if defined(SIR_NO_SYSTEM_LOGGERS)
957
CONST_ATTR
958
#endif
959
bool _sir_syslog_updated(sirinit* si, sir_update_config_data* data) {
233✔
960
#if !defined(SIR_NO_SYSTEM_LOGGERS)
961
    if (!_sir_validptr(si) || !_sir_validptr(data))
233✔
962
        return false;
×
963

964
    if (_sir_bittest(si->d_syslog._state.mask, SIRSL_UPDATED)) {
427✔
965
        bool levels   = _sir_bittest(si->d_syslog._state.mask, SIRSL_LEVELS);
194✔
966
        bool options  = _sir_bittest(si->d_syslog._state.mask, SIRSL_OPTIONS);
194✔
967
        bool category = _sir_bittest(si->d_syslog._state.mask, SIRSL_CATEGORY);
194✔
968
        bool identity = _sir_bittest(si->d_syslog._state.mask, SIRSL_IDENTITY);
194✔
969
        bool is_init  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_INIT);
194✔
970
        bool is_open  = _sir_bittest(si->d_syslog._state.mask, SIRSL_IS_OPEN);
194✔
971

972
        _sir_selflog("config update: (levels: %u, options: %u, category: %u,"
220✔
973
                     " identity: %u, is_init: %u, is_open: %u)",
974
                     levels, options, category, identity, is_init, is_open);
975

976
        bool must_init = false;
194✔
977

978
# if defined(SIR_OS_LOG_ENABLED)
979
        /*
980
         * for os_log, if initialized and open already, only need to reconfigure
981
         * if identity or category changed.
982
         */
983
        must_init = (!is_init || !is_open) || (identity || category);
984
# elif defined(SIR_SYSLOG_ENABLED)
985
        /*
986
         * for os_log, if initialized and open already, only need to reconfigure
987
         * if identity or options changed.
988
         */
989
        must_init = (!is_init || !is_open) || (identity || options);
233✔
990
# endif
991
        bool init = true;
194✔
992
        if (must_init) {
194✔
993
            _sir_selflog("re-init...");
122✔
994
            init = _sir_syslog_init(si->name, &si->d_syslog);
129✔
995
            _sir_selflog("re-init %s", init ? "succeeded" : "failed");
122✔
996
        } else {
997
            _sir_selflog("no re-init necessary");
98✔
998
        }
999

1000
        return init;
233✔
1001
    } else {
1002
        _sir_selflog("BUG: called without 'updated' flag set!");
×
1003
        return false;
×
1004
    }
1005
#else
1006
    SIR_UNUSED(si);
1007
    SIR_UNUSED(data);
1008
    return false;
×
1009
#endif
1010
}
1011

1012
#if defined(SIR_NO_SYSTEM_LOGGERS)
1013
CONST_ATTR
1014
#endif
1015
bool _sir_syslog_close(sir_syslog_dest* ctx) {
538✔
1016
#if !defined(SIR_NO_SYSTEM_LOGGERS)
1017
    if (!_sir_validptr(ctx))
538✔
1018
        return false;
×
1019

1020
    if (!_sir_bittest(ctx->_state.mask, SIRSL_IS_OPEN)) {
977✔
1021
        _sir_selflog("log not open; ignoring");
390✔
1022
        return true;
390✔
1023
    }
1024

1025
# if defined(SIR_OS_LOG_ENABLED)
1026
    /* evidently, you don't need to close the handle returned from os_log_create(), and
1027
     * if you make that call again, you'll get the same cached value. so let's keep the
1028
     * value we've got in the global context. */
1029
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
1030
    _sir_selflog("log closure not necessary");
1031
    return true;
1032
# elif defined(SIR_SYSLOG_ENABLED)
1033
    closelog();
122✔
1034
    _sir_setbitslow(&ctx->_state.mask, SIRSL_IS_OPEN);
101✔
1035
    _sir_selflog("closed log");
115✔
1036
    return true;
122✔
1037
# endif
1038
#else
1039
    SIR_UNUSED(ctx);
1040
#endif
1041
    return false;
×
1042
}
1043

1044
void _sir_syslog_reset(sir_syslog_dest* ctx) {
1,076✔
1045
#if !defined(SIR_NO_SYSTEM_LOGGERS)
1046
    if (_sir_validptr(ctx)) {
1,076✔
1047
        uint32_t old       = ctx->_state.mask;
1,010✔
1048
        ctx->_state.mask   = 0u;
1,076✔
1049
        ctx->_state.logger = NULL;
1,076✔
1050
        _sir_selflog("state reset; mask was %08"PRIx32, old);
1,010✔
1051
    }
1052
#else
1053
    SIR_UNUSED(ctx);
1054
#endif
1055
}
1,076✔
1056

1057
#if !defined(__IMPORTC__)
1058
PURE_ATTR
1059
#endif
1060
const char* _sir_formattedlevelstr(sir_level level) {
2,156,807✔
1061
    static const size_t low  = 0;
1062
    static const size_t high = SIR_NUMLEVELS - 1;
1063

1064
    const char* retval = SIR_UNKNOWN;
2,133,084✔
1065

1066
    _SIR_DECLARE_BIN_SEARCH(low, high);
2,133,084✔
1067
    _SIR_BEGIN_BIN_SEARCH()
1068

1069
    if (sir_level_to_str_map[_mid].level == level) {
8,583,691✔
1070
        retval = sir_level_to_str_map[_mid].fmt;
2,156,807✔
1071
        break;
2,156,807✔
1072
    }
1073

1074
    _SIR_ITERATE_BIN_SEARCH((sir_level_to_str_map[_mid].level < level ? 1 : -1));
6,426,884✔
1075
    _SIR_END_BIN_SEARCH();
1076

1077
    return retval;
2,156,807✔
1078
}
1079

1080
#if defined(__GNUC__)
1081
__attribute__ ((format (strftime, 3, 0)))
1082
#endif
1083
bool _sir_formattime(time_t now, char* buffer, const char* format) {
2,177,574✔
1084
    if (0 == now || -1 == now)
2,177,574✔
1085
        return _sir_seterror(_SIR_E_INVALID);
2,061✔
1086

1087
    struct tm timebuf = {0};
2,175,513✔
1088
#if defined(__GNUC__) && !defined(__clang__) && \
1089
    !(defined(__OPEN64__) || defined(__OPENCC__))
1090
# pragma GCC diagnostic push
1091
# pragma GCC diagnostic ignored "-Wformat-nonliteral"
1092
#endif
1093
    size_t fmttime = strftime(buffer, SIR_MAXTIME, format,
2,175,516✔
1094
        _sir_localtime(&now, &timebuf));
2,175,513✔
1095
#if defined(__GNUC__) && !defined(__clang__) && \
1096
    !(defined(__OPEN64__) || defined(__OPENCC__))
1097
# pragma GCC diagnostic pop
1098
#endif
1099

1100
    SIR_ASSERT(0 != fmttime);
2,165,569✔
1101
    if (0 == fmttime)
2,145,664✔
1102
        _sir_selflog("error: strftime failed; format string: '%s'", format);
×
1103

1104
    return 0 != fmttime;
2,175,516✔
1105
}
1106

1107
bool _sir_clock_gettime(time_t* tbuf, long* msecbuf) {
2,156,810✔
1108
    if (tbuf) {
2,156,810✔
1109
        time_t ret = time(tbuf);
2,156,810✔
1110
        if ((time_t)-1 == ret) {
2,156,810✔
1111
            if (msecbuf)
7,909✔
1112
                *msecbuf = 0l;
7,909✔
1113
            return _sir_handleerr(errno);
7,909✔
1114
        }
1115
#if defined(SIR_MSEC_POSIX)
1116
        struct timespec ts = {0};
2,148,901✔
1117
        int clock          = clock_gettime(SIR_MSECCLOCK, &ts);
2,148,901✔
1118
        SIR_ASSERT(0 == clock);
2,140,993✔
1119

1120
        if (0 == clock) {
2,133,081✔
1121
            if (msecbuf)
2,141,030✔
1122
                *msecbuf = (long)(ts.tv_nsec / (long)1e6);
2,141,030✔
1123
        } else {
1124
            if (msecbuf)
7,869✔
1125
                *msecbuf = 0l;
7,869✔
1126
            return _sir_handleerr(errno);
7,869✔
1127
        }
1128
#elif defined(SIR_MSEC_MACH)
1129
        kern_return_t retval = KERN_SUCCESS;
1130
        mach_timespec_t mts  = {0};
1131
        clock_serv_t clock;
1132

1133
        host_get_clock_service(mach_host_self(), SIR_MSECCLOCK, &clock);
1134
        retval = clock_get_time(clock, &mts);
1135
        mach_port_deallocate(mach_task_self(), clock);
1136

1137
        if (KERN_SUCCESS == retval) {
1138
            if (msecbuf)
1139
                *msecbuf = (mts.tv_nsec / (long)1e6);
1140
        } else {
1141
            if (msecbuf)
1142
                *msecbuf = 0l;
1143
            return _sir_handleerr(retval);
1144
        }
1145
#elif defined(SIR_MSEC__WIN__)
1146
        static const ULONGLONG uepoch = (ULONGLONG)116444736e9ull;
1147

1148
        FILETIME ftutc = {0};
1149
        GetSystemTimePreciseAsFileTime(&ftutc);
1150

1151
        ULARGE_INTEGER ftnow = {0};
1152
        ftnow.HighPart = ftutc.dwHighDateTime;
1153
        ftnow.LowPart  = ftutc.dwLowDateTime;
1154
        ftnow.QuadPart = (ULONGLONG)((ftnow.QuadPart - uepoch) / 1e7);
1155

1156
        *tbuf = (time_t)ftnow.QuadPart;
1157

1158
        SYSTEMTIME st = {0};
1159
        if (FileTimeToSystemTime(&ftutc, &st)) {
1160
            if (msecbuf)
1161
                *msecbuf = st.wMilliseconds;
1162
        } else {
1163
            if (msecbuf)
1164
                *msecbuf = 0l;
1165
            return _sir_handlewin32err(GetLastError());
1166
        }
1167

1168
#else
1169
        time(tbuf);
1170
        if (msecbuf)
1171
            *msecbuf = 0l;
1172
#endif
1173
        return true;
2,141,030✔
1174
    }
1175
    return false;
×
1176
}
1177

1178
pid_t _sir_getpid(void) {
728✔
1179
#if !defined(__WIN__)
1180
    return getpid();
728✔
1181
#else /* __WIN__ */
1182
    return (pid_t)GetCurrentProcessId();
1183
#endif
1184
}
1185

1186
pid_t _sir_gettid(void) {
2,156,902✔
1187
    pid_t tid = 0;
2,133,165✔
1188
#if defined(__MACOS__)
1189
    uint64_t tid64 = 0ull;
1190
    int gettid     = pthread_threadid_np(NULL, &tid64);
1191
    if (0 != gettid)
1192
        (void)_sir_handleerr(gettid);
1193
    tid = (pid_t)tid64;
1194
#elif (defined(__BSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)) || \
1195
      defined(__DragonFly_getthreadid__)
1196
    tid = (pid_t)pthread_getthreadid_np();
1197
#elif defined(__OpenBSD__)
1198
    tid = (pid_t)getthrid();
1199
#elif defined(__SOLARIS__) || defined(__NetBSD__) || defined(__HURD__) || \
1200
      defined(__DragonFly__) || defined(__CYGWIN__) || defined(_AIX)
1201
    tid = (pid_t)pthread_self();
1202
#elif defined(__HAIKU__)
1203
    tid = get_pthread_thread_id(pthread_self());
1204
#elif defined(__linux__) || defined(__serenity__)
1205
# if (defined(__GLIBC__) && GLIBC_VERSION >= 23000) || \
1206
     defined(__serenity__)
1207
    tid = gettid();
2,156,902✔
1208
# else
1209
    tid = syscall(SYS_gettid);
1210
# endif
1211
#elif defined(__WIN__)
1212
    tid = (pid_t)GetCurrentThreadId();
1213
#else
1214
# error "cannot determine how to get thread id; please contact the author"
1215
#endif
1216
    return tid;
2,156,900✔
1217
}
1218

1219
bool _sir_getthreadname(char name[SIR_MAXPID]) {
72,146✔
1220
#if defined(__MACOS__) || \
1221
   (defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_12_2__)) || \
1222
   (defined(__GLIBC__) && GLIBC_VERSION >= 21200 && defined(_GNU_SOURCE)) || \
1223
    defined(USE_PTHREAD_GETNAME_NP)
1224
    int ret = pthread_getname_np(pthread_self(), name, SIR_MAXPID);
72,146✔
1225
    if (0 != ret)
72,146✔
1226
        return _sir_handleerr(ret);
×
1227

1228
# if defined(__HAIKU__)
1229
    if ((strncmp(name, "pthread_func", SIR_MAXPID)) || _sir_validstrnofail(name))
1230
        (void)snprintf(name, SIR_MAXPID, "%ld", (long)get_pthread_thread_id(pthread_self()));
1231
# endif
1232
    return _sir_validstrnofail(name);
72,146✔
1233
#elif defined(__BSD__) && defined(__FreeBSD_PTHREAD_NP_11_3__)
1234
    pthread_get_name_np(pthread_self(), name, SIR_MAXPID);
1235
    return _sir_validstrnofail(name);
1236
#else
1237
# if !defined(_AIX) && !defined(__HURD__)
1238
#  pragma message("unable to determine how to get 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,298✔
1246
#if !defined(__WIN__)
1247
    int ret = gethostname(name, SIR_MAXHOST - 1);
8,235✔
1248
    return 0 == ret ? true : _sir_handleerr(errno);
8,298✔
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