GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2026-10-25 02:40:14
Exec Total Coverage
Lines: 233 343 67.9%
Branches: 157 303 51.8%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * LogCvmfs() handles all message output. It works like printf.
5 * It can log to a debug log file, stdout, stderr, and syslog.
6 * The tracer is a separate module, messages do not overlap with logging.
7 *
8 * The syslog setter routines are not thread-safe. They are meant to be
9 * invoked at the very first, single-threaded stage.
10 *
11 * If DEBUGMSG is undefined, pure debug messages are compiled into no-ops.
12 */
13
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <pthread.h>
17 #include <sys/syslog.h>
18 #include <stdio.h>
19 #include <stdio.h>
20 #include <syslog.h>
21 #include <time.h>
22 #include <unistd.h>
23
24 #include <cassert>
25 #include <cstdarg>
26 #include <cstdio>
27 #include <cstdlib>
28 #include <cstring>
29 #include <ctime>
30 #include <string>
31 #include <vector>
32
33 #include "util/export.h"
34 #include "util/logging_internal.h" // NOLINT(build/include)
35 #include "util/mutex.h"
36 #include "util/platform.h"
37 #include "util/posix.h"
38 #include "util/single_copy.h"
39 #include "util/smalloc.h"
40
41 using namespace std; // NOLINT
42
43 #ifdef CVMFS_NAMESPACE_GUARD
44 namespace CVMFS_NAMESPACE_GUARD {
45 #endif
46
47 static void LogCustom(unsigned id, const std::string &message);
48
49 LogFacilities DefaultLogging::info = kLogSyslog;
50 LogFacilities DefaultLogging::error = kLogSyslogErr;
51
52 ✗ void DefaultLogging::Set(LogFacilities info, LogFacilities error) {
53 ✗ DefaultLogging::info = info;
54 ✗ DefaultLogging::error = error;
55 }
56
57 namespace {
58
59 unsigned gMicroSyslogMax = 500 * 1024; // default: rotate after 500kB
60
61 pthread_mutex_t lock_stdout = PTHREAD_MUTEX_INITIALIZER;
62 pthread_mutex_t lock_stderr = PTHREAD_MUTEX_INITIALIZER;
63 #ifdef DEBUGMSG
64 pthread_mutex_t lock_debug = PTHREAD_MUTEX_INITIALIZER;
65 FILE *file_debug = NULL;
66 string *path_debug = NULL;
67 #endif
68 const char *module_names[] = {
69 "unknown", "cache", "catalog", "sql",
70 "cvmfs", "hash", "download", "compress",
71 "quota", "talk", "monitor", "lru",
72 "fuse stub", "signature", "fs traversal", "catalog traversal",
73 "nfs maps", "publish", "spooler", "concurrency",
74 "utility", "glue buffer", "history", "unionfs",
75 "pathspec", "receiver", "upload s3", "upload http",
76 "s3fanout", "gc", "dns", "authz",
77 "reflog", "kvstore", "telemetry", "curl",
78 "bundle mgr"};
79 int syslog_facility = LOG_USER;
80 int syslog_level = LOG_NOTICE;
81 char *syslog_prefix = NULL;
82
83 string *usyslog_dest = NULL;
84 int usyslog_fd = -1;
85 int usyslog_fd1 = -1;
86 unsigned usyslog_size = 0;
87 pthread_mutex_t lock_usyslock = PTHREAD_MUTEX_INITIALIZER;
88
89 const unsigned kMaxCustomlog = 3;
90 string *customlog_dests[] = {NULL, NULL, NULL};
91 int customlog_fds[] = {-1, -1, -1};
92 pthread_mutex_t customlog_locks[] = {PTHREAD_MUTEX_INITIALIZER,
93 PTHREAD_MUTEX_INITIALIZER,
94 PTHREAD_MUTEX_INITIALIZER};
95
96 LogLevels max_log_level = kLogNormal;
97 static void (*alt_log_func)(const LogSource source, const int mask,
98 const char *msg) = NULL;
99
100 /**
101 * Circular buffer of the last $n$ calls to LogCvmfs(). Thread-safe class.
102 */
103 class LogBuffer : SingleCopy {
104 public:
105 51 LogBuffer() : next_id_(0) {
106 51 const int retval = pthread_mutex_init(&lock_, NULL);
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 assert(retval == 0);
108 51 }
109
110 57 ~LogBuffer() { pthread_mutex_destroy(&lock_); }
111
112 19934584 void Append(const LogBufferEntry &entry) {
113 19934584 const MutexLockGuard lock_guard(lock_);
114 19934707 const size_t idx = next_id_++ % kBufferSize;
115
2/2
✓ Branch 1 taken 1067 times.
✓ Branch 2 taken 19933640 times.
19934707 if (idx >= buffer_.size()) {
116
1/2
✓ Branch 1 taken 1067 times.
✗ Branch 2 not taken.
1067 buffer_.push_back(entry);
117 } else {
118
1/2
✓ Branch 2 taken 19933640 times.
✗ Branch 3 not taken.
19933640 buffer_[idx] = entry;
119 }
120 19934707 }
121
122 290 std::vector<LogBufferEntry> GetBuffer() {
123 // Return a buffer sorted from newest to oldest buffer
124 290 std::vector<LogBufferEntry> sorted_buffer;
125 290 const MutexLockGuard lock_guard(lock_);
126
2/2
✓ Branch 1 taken 1508 times.
✓ Branch 2 taken 290 times.
1798 for (unsigned i = 1; i <= buffer_.size(); ++i) {
127 1508 const unsigned idx = (next_id_ - i) % kBufferSize;
128
1/2
✓ Branch 2 taken 1508 times.
✗ Branch 3 not taken.
1508 sorted_buffer.push_back(buffer_[idx]);
129 }
130 580 return sorted_buffer;
131 290 }
132
133 48 void Clear() {
134 48 const MutexLockGuard lock_guard(lock_);
135 48 next_id_ = 0;
136 48 buffer_.clear();
137 48 }
138
139 private:
140 static const unsigned kBufferSize = 10;
141 pthread_mutex_t lock_;
142 int next_id_;
143 std::vector<LogBufferEntry> buffer_;
144 };
145
146 LogBuffer g_log_buffer;
147
148 } // namespace
149
150 /**
151 * Sets the level that is used for all messages to the syslog facility.
152 */
153 84 void SetLogSyslogLevel(const int level) {
154
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
84 switch (level) {
155 ✗ case 1:
156 ✗ syslog_level = LOG_DEBUG;
157 ✗ break;
158 ✗ case 2:
159 ✗ syslog_level = LOG_INFO;
160 ✗ break;
161 84 case 3:
162 84 syslog_level = LOG_NOTICE;
163 84 break;
164 ✗ default:
165 ✗ syslog_level = LOG_NOTICE;
166 ✗ break;
167 }
168 84 }
169
170 105 int GetLogSyslogLevel() {
171
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 105 times.
105 switch (syslog_level) {
172 ✗ case LOG_DEBUG:
173 ✗ return 1;
174 ✗ case LOG_INFO:
175 ✗ return 2;
176 105 default:
177 105 return 3;
178 }
179 }
180
181 /**
182 * Sets the syslog facility to one of local0 .. local7.
183 * Falls back to LOG_USER if local_facility is not in [0..7]
184 */
185 ✗ void SetLogSyslogFacility(const int local_facility) {
186 ✗ switch (local_facility) {
187 ✗ case 0:
188 ✗ syslog_facility = LOG_LOCAL0;
189 ✗ break;
190 ✗ case 1:
191 ✗ syslog_facility = LOG_LOCAL1;
192 ✗ break;
193 ✗ case 2:
194 ✗ syslog_facility = LOG_LOCAL2;
195 ✗ break;
196 ✗ case 3:
197 ✗ syslog_facility = LOG_LOCAL3;
198 ✗ break;
199 ✗ case 4:
200 ✗ syslog_facility = LOG_LOCAL4;
201 ✗ break;
202 ✗ case 5:
203 ✗ syslog_facility = LOG_LOCAL5;
204 ✗ break;
205 ✗ case 6:
206 ✗ syslog_facility = LOG_LOCAL6;
207 ✗ break;
208 ✗ case 7:
209 ✗ syslog_facility = LOG_LOCAL7;
210 ✗ break;
211 ✗ default:
212 ✗ syslog_facility = LOG_USER;
213 }
214 }
215
216 105 int GetLogSyslogFacility() {
217
1/9
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 105 times.
105 switch (syslog_facility) {
218 ✗ case LOG_LOCAL0:
219 ✗ return 0;
220 ✗ case LOG_LOCAL1:
221 ✗ return 1;
222 ✗ case LOG_LOCAL2:
223 ✗ return 2;
224 ✗ case LOG_LOCAL3:
225 ✗ return 3;
226 ✗ case LOG_LOCAL4:
227 ✗ return 4;
228 ✗ case LOG_LOCAL5:
229 ✗ return 5;
230 ✗ case LOG_LOCAL6:
231 ✗ return 6;
232 ✗ case LOG_LOCAL7:
233 ✗ return 7;
234 105 default:
235 105 return -1;
236 }
237 }
238
239 /**
240 * The syslog prefix is used to distinguish multiple repositories in
241 * /var/log/messages
242 */
243 5589 void SetLogSyslogPrefix(const std::string &prefix) {
244
2/2
✓ Branch 0 taken 2800 times.
✓ Branch 1 taken 2789 times.
5589 if (syslog_prefix)
245 2800 free(syslog_prefix);
246
247
2/2
✓ Branch 1 taken 2748 times.
✓ Branch 2 taken 2841 times.
5589 if (prefix == "") {
248 2748 syslog_prefix = NULL;
249 } else {
250 2841 const unsigned len = prefix.length() + 1;
251 2841 syslog_prefix = static_cast<char *>(smalloc(len));
252 2841 syslog_prefix[len - 1] = '\0';
253 2841 memcpy(syslog_prefix, &prefix[0], prefix.length());
254 }
255 5589 }
256
257 ✗ void SetLogSyslogShowPID(bool flag) {
258 ✗ openlog(NULL, flag ? LOG_PID : 0, GetLogSyslogFacility());
259 }
260
261 /**
262 * Set the maximum verbosity level. By default kLogNormal.
263 */
264 6 void SetLogVerbosity(const LogLevels max_level) { max_log_level = max_level; }
265
266
267 47 void SetLogMicroSyslogMaxSize(unsigned bytes) { gMicroSyslogMax = bytes; }
268
269 /**
270 * "Micro-Syslog" write kLogSyslog messages into filename. It rotates this
271 * file. Requires for µCernVM
272 */
273 3212 void SetLogMicroSyslog(const std::string &filename) {
274 3212 pthread_mutex_lock(&lock_usyslock);
275
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 3118 times.
3212 if (usyslog_fd >= 0) {
276
1/2
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
94 close(usyslog_fd);
277
1/2
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
94 close(usyslog_fd1);
278 94 usyslog_fd = -1;
279 94 usyslog_fd1 = -1;
280 }
281
282
2/2
✓ Branch 1 taken 3118 times.
✓ Branch 2 taken 94 times.
3212 if (filename == "") {
283
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 3024 times.
3118 delete usyslog_dest;
284 3118 usyslog_dest = NULL;
285 3118 pthread_mutex_unlock(&lock_usyslock);
286 3118 return;
287 }
288
289
1/2
✓ Branch 2 taken 94 times.
✗ Branch 3 not taken.
94 usyslog_fd = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 if (usyslog_fd < 0) {
291 ✗ fprintf(stderr, "could not open usyslog file %s (%d), aborting\n",
292 ✗ filename.c_str(), errno);
293 ✗ abort();
294 }
295
2/4
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 94 times.
✗ Branch 6 not taken.
94 usyslog_fd1 = open((filename + ".1").c_str(), O_WRONLY | O_CREAT, 0600);
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 if (usyslog_fd1 < 0) {
297 ✗ fprintf(stderr, "could not open usyslog.1 file %s.1 (%d), aborting\n",
298 ✗ filename.c_str(), errno);
299 ✗ abort();
300 }
301 platform_stat64 info;
302 94 const int retval = platform_fstat(usyslog_fd, &info);
303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 assert(retval == 0);
304 94 usyslog_size = info.st_size;
305
2/4
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 94 times.
✗ Branch 5 not taken.
94 usyslog_dest = new string(filename);
306 94 pthread_mutex_unlock(&lock_usyslock);
307 }
308
309 58 std::string GetLogMicroSyslog() {
310 58 pthread_mutex_lock(&lock_usyslock);
311 58 string result;
312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (usyslog_dest)
313 ✗ result = *usyslog_dest;
314 58 pthread_mutex_unlock(&lock_usyslock);
315 58 return result;
316 }
317
318 47188 static void LogMicroSyslog(const std::string &message) {
319
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47188 times.
47188 if (message.size() == 0)
320 ✗ return;
321
322 47188 pthread_mutex_lock(&lock_usyslock);
323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47188 times.
47188 if (usyslog_fd < 0) {
324 ✗ pthread_mutex_unlock(&lock_usyslock);
325 ✗ return;
326 }
327
328 47188 const int written = write(usyslog_fd, message.data(), message.size());
329
3/6
✓ Branch 0 taken 47188 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 47188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 47188 times.
47188 if ((written < 0) || (static_cast<unsigned>(written) != message.size())) {
330 ✗ close(usyslog_fd);
331 ✗ usyslog_fd = -1;
332 ✗ abort();
333 }
334 47188 int retval = fsync(usyslog_fd);
335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47188 times.
47188 assert(retval == 0);
336 47188 usyslog_size += written;
337
338
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 46765 times.
47188 if (usyslog_size >= gMicroSyslogMax) {
339 // Wipe out usyslog.1 file
340 423 retval = ftruncate(usyslog_fd1, 0);
341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(retval == 0);
342
343 // Copy from usyslog to usyslog.1
344 423 retval = lseek(usyslog_fd, 0, SEEK_SET);
345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(retval == 0);
346 unsigned char buf[4096];
347 int num_bytes;
348 do {
349
1/2
✓ Branch 1 taken 423 times.
✗ Branch 2 not taken.
423 num_bytes = read(usyslog_fd, buf, 4096);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(num_bytes >= 0);
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 if (num_bytes == 0)
352 ✗ break;
353
1/2
✓ Branch 1 taken 423 times.
✗ Branch 2 not taken.
423 const int written = write(usyslog_fd1, buf, num_bytes);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(written == num_bytes);
355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 } while (num_bytes == 4096);
356 423 retval = lseek(usyslog_fd1, 0, SEEK_SET);
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(retval == 0);
358
359 // Reset usyslog
360 423 retval = lseek(usyslog_fd, 0, SEEK_SET);
361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(retval == 0);
362 423 retval = ftruncate(usyslog_fd, 0);
363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(retval == 0);
364 423 usyslog_size = 0;
365 }
366 47188 pthread_mutex_unlock(&lock_usyslock);
367 }
368
369 /**
370 * Changes the debug log file from stderr. No effect if DEBUGMSG is undefined.
371 */
372 #ifdef DEBUGMSG
373 2846 void SetLogDebugFile(const string &filename) {
374
1/2
✓ Branch 1 taken 2846 times.
✗ Branch 2 not taken.
2846 if (filename == "") {
375
2/4
✓ Branch 0 taken 2846 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2846 times.
2846 if ((file_debug != NULL) && (file_debug != stderr)) {
376 ✗ fclose(file_debug);
377 ✗ file_debug = NULL;
378 }
379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2846 times.
2846 delete path_debug;
380 2846 path_debug = NULL;
381 2846 return;
382 }
383
384 ✗ if ((file_debug != NULL) && (file_debug != stderr)) {
385 ✗ if ((fclose(file_debug) < 0)) {
386 ✗ fprintf(stderr, "could not close current log file (%d), aborting\n",
387 ✗ errno);
388
389 ✗ abort();
390 }
391 }
392 ✗ const int fd = open(filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0600);
393 ✗ if ((fd < 0) || ((file_debug = fdopen(fd, "a")) == NULL)) {
394 ✗ fprintf(stderr, "could not open debug log file %s (%d), aborting\n",
395 ✗ filename.c_str(), errno);
396 ✗ syslog(syslog_facility | LOG_ERR,
397 "could not open debug log file %s (%d), "
398 "aborting\n",
399 ✗ filename.c_str(), errno);
400 ✗ abort();
401 }
402 ✗ delete path_debug;
403 ✗ path_debug = new string(filename);
404 }
405
406 154 string GetLogDebugFile() {
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (path_debug)
408 ✗ return *path_debug;
409
1/2
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
154 return "";
410 }
411 #endif
412
413 313 void SetAltLogFunc(void (*fn)(const LogSource source, const int mask,
414 const char *msg)) {
415 313 alt_log_func = fn;
416 313 }
417
418
419 /**
420 * Logs a message to one or multiple facilities specified by mask.
421 * Mask can be extended by a log level in the future, using the higher bits.
422 *
423 * @param[in] source Component that triggers the logging
424 * @param[in] mask Bit mask of log facilities
425 * @param[in] format Format string followed by arguments like printf
426 */
427 CVMFS_EXPORT
428 19987449 void vLogCvmfs(const LogSource source, const int mask, const char *format,
429 va_list variadic_list) {
430 19987449 char *msg = NULL;
431
432 // Log level check, no flag set in mask means kLogNormal
433 #ifndef DEBUGMSG
434 ✗ int log_level = mask & ((2 * kLogNone - 1) ^ (kLogLevel0 - 1));
435 ✗ if (!log_level)
436 ✗ log_level = kLogNormal;
437 ✗ if (log_level == kLogNone)
438 ✗ return;
439 ✗ if (log_level > max_log_level)
440 ✗ return;
441 #endif
442
443 // Format the message string
444 19987449 const int retval = vasprintf(&msg, format, variadic_list);
445
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 19988085 times.
19988118 assert(retval != -1); // else: out of memory
446
447
2/2
✓ Branch 0 taken 53567 times.
✓ Branch 1 taken 19934518 times.
19988085 if (alt_log_func) {
448
1/2
✓ Branch 1 taken 53567 times.
✗ Branch 2 not taken.
53567 (*alt_log_func)(source, mask, msg);
449 53567 return;
450 }
451
452 #ifdef DEBUGMSG
453
2/2
✓ Branch 0 taken 8390522 times.
✓ Branch 1 taken 11543996 times.
19934518 if (mask & kLogDebug) {
454 8390522 pthread_mutex_lock(&lock_debug);
455
456 // Set the file pointer for debugging to stderr, if necessary
457
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 8391156 times.
8391254 if (file_debug == NULL)
458 98 file_debug = stderr;
459
460 // Get timestamp
461 time_t rawtime;
462 8391254 time(&rawtime);
463 struct tm now;
464 8391254 localtime_r(&rawtime, &now);
465
466
1/2
✓ Branch 0 taken 8391254 times.
✗ Branch 1 not taken.
8391254 if (file_debug == stderr)
467 8391254 pthread_mutex_lock(&lock_stderr);
468 8391254 fprintf(file_debug, "(%s) %s [%02d-%02d-%04d %02d:%02d:%02d %s]\n",
469 8391254 module_names[source], msg, (now.tm_mon) + 1, now.tm_mday,
470
1/2
✓ Branch 1 taken 8391254 times.
✗ Branch 2 not taken.
8391254 (now.tm_year) + 1900, now.tm_hour, now.tm_min, now.tm_sec,
471 now.tm_zone);
472
1/2
✓ Branch 1 taken 8391254 times.
✗ Branch 2 not taken.
8391254 fflush(file_debug);
473
1/2
✓ Branch 0 taken 8391254 times.
✗ Branch 1 not taken.
8391254 if (file_debug == stderr)
474 8391254 pthread_mutex_unlock(&lock_stderr);
475
476 8391254 pthread_mutex_unlock(&lock_debug);
477 }
478 #endif
479
480
2/2
✓ Branch 0 taken 11256282 times.
✓ Branch 1 taken 8678950 times.
19935232 if (mask & kLogStdout) {
481 11256282 pthread_mutex_lock(&lock_stdout);
482
2/2
✓ Branch 0 taken 11249982 times.
✓ Branch 1 taken 6696 times.
11256678 if (mask & kLogShowSource)
483
1/2
✓ Branch 1 taken 11249982 times.
✗ Branch 2 not taken.
11249982 printf("(%s) ", module_names[source]);
484
1/2
✓ Branch 1 taken 11256678 times.
✗ Branch 2 not taken.
11256678 printf("%s", msg);
485
2/2
✓ Branch 0 taken 11256434 times.
✓ Branch 1 taken 244 times.
11256678 if (!(mask & kLogNoLinebreak))
486
1/2
✓ Branch 1 taken 11256434 times.
✗ Branch 2 not taken.
11256434 printf("\n");
487
1/2
✓ Branch 1 taken 11256678 times.
✗ Branch 2 not taken.
11256678 fflush(stdout);
488 11256678 pthread_mutex_unlock(&lock_stdout);
489 }
490
491
2/2
✓ Branch 0 taken 647 times.
✓ Branch 1 taken 19934981 times.
19935628 if (mask & kLogStderr) {
492 647 pthread_mutex_lock(&lock_stderr);
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 647 times.
647 if (mask & kLogShowSource)
494 ✗ fprintf(stderr, "(%s) ", module_names[source]);
495
1/2
✓ Branch 1 taken 647 times.
✗ Branch 2 not taken.
647 fprintf(stderr, "%s", msg);
496
1/2
✓ Branch 0 taken 647 times.
✗ Branch 1 not taken.
647 if (!(mask & kLogNoLinebreak))
497
1/2
✓ Branch 1 taken 647 times.
✗ Branch 2 not taken.
647 fprintf(stderr, "\n");
498
1/2
✓ Branch 1 taken 647 times.
✗ Branch 2 not taken.
647 fflush(stderr);
499 647 pthread_mutex_unlock(&lock_stderr);
500 }
501
502
2/2
✓ Branch 0 taken 57031 times.
✓ Branch 1 taken 19878597 times.
19935628 if (mask & (kLogSyslog | kLogSyslogWarn | kLogSyslogErr)) {
503
2/2
✓ Branch 0 taken 47188 times.
✓ Branch 1 taken 9843 times.
57031 if (usyslog_dest) {
504
1/2
✓ Branch 2 taken 47188 times.
✗ Branch 3 not taken.
47188 string fmt_msg(msg);
505
2/2
✓ Branch 0 taken 47141 times.
✓ Branch 1 taken 47 times.
47188 if (syslog_prefix)
506
4/8
✓ Branch 2 taken 47141 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 47141 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 47141 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 47141 times.
✗ Branch 12 not taken.
47141 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
507 time_t rawtime;
508 47188 time(&rawtime);
509 char fmt_time[26];
510 47188 ctime_r(&rawtime, fmt_time);
511
3/6
✓ Branch 2 taken 47188 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 47188 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 47188 times.
✗ Branch 9 not taken.
47188 fmt_msg = string(fmt_time, 24) + " " + fmt_msg;
512
1/2
✓ Branch 1 taken 47188 times.
✗ Branch 2 not taken.
47188 fmt_msg.push_back('\n');
513
1/2
✓ Branch 1 taken 47188 times.
✗ Branch 2 not taken.
47188 LogMicroSyslog(fmt_msg);
514 47188 } else {
515 9843 int level = syslog_level;
516
2/2
✓ Branch 0 taken 4238 times.
✓ Branch 1 taken 5605 times.
9843 if (mask & kLogSyslogWarn)
517 4238 level = LOG_WARNING;
518
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 7188 times.
9843 if (mask & kLogSyslogErr)
519 2655 level = LOG_ERR;
520
2/2
✓ Branch 0 taken 6491 times.
✓ Branch 1 taken 3352 times.
9843 if (syslog_prefix) {
521
1/2
✓ Branch 1 taken 6491 times.
✗ Branch 2 not taken.
6491 syslog(syslog_facility | level, "(%s) %s", syslog_prefix, msg);
522 } else {
523
1/2
✓ Branch 1 taken 2461 times.
✗ Branch 2 not taken.
3352 syslog(syslog_facility | level, "%s", msg);
524 }
525 }
526 }
527
528
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 19934569 times.
19934737 if (mask & (kLogCustom0 | kLogCustom1 | kLogCustom2)) {
529
1/2
✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
168 string fmt_msg(msg);
530
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (syslog_prefix)
531
4/8
✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 168 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 168 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 168 times.
✗ Branch 12 not taken.
168 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
532
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (!(mask & kLogNoLinebreak))
533
1/2
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
168 fmt_msg += "\n";
534
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 if (mask & kLogCustom0)
535
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 LogCustom(0, fmt_msg);
536
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 126 times.
168 if (mask & kLogCustom1)
537
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 LogCustom(1, fmt_msg);
538
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 126 times.
168 if (mask & kLogCustom2)
539
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 LogCustom(2, fmt_msg);
540 168 }
541
542 // The log buffer can be read via extended attributes from cvmfs, therefore
543 // we provide an option to hide entries from the buffer if they contain
544 // sensitive information
545
2/2
✓ Branch 0 taken 19934689 times.
✓ Branch 1 taken 48 times.
19934737 if (!(mask & kLogSensitive))
546
3/6
✓ Branch 2 taken 19934698 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 19934698 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 19934563 times.
✗ Branch 9 not taken.
19934689 g_log_buffer.Append(LogBufferEntry(source, mask, msg));
547
548 19934755 free(msg);
549 }
550 CVMFS_EXPORT
551 19987326 void LogCvmfs(const LogSource source, const int mask, const char *format, ...) {
552 va_list variadic_list;
553 19987326 va_start(variadic_list, format);
554
1/2
✓ Branch 1 taken 19988232 times.
✗ Branch 2 not taken.
19987326 vLogCvmfs(source, mask, format, variadic_list);
555 19988232 va_end(variadic_list);
556 19988232 }
557
558 290 std::vector<LogBufferEntry> GetLogBuffer() { return g_log_buffer.GetBuffer(); }
559
560 48 void ClearLogBuffer() { g_log_buffer.Clear(); }
561
562 45 void PrintError(const string &message) {
563 45 LogCvmfs(kLogCvmfs, kLogStderr, "[ERROR] %s", message.c_str());
564 45 }
565
566 ✗ void PrintWarning(const string &message) {
567 ✗ LogCvmfs(kLogCvmfs, kLogStderr, "[WARNING] %s", message.c_str());
568 }
569
570
571 /**
572 * Opens a custom log file
573 */
574 804 void SetLogCustomFile(unsigned id, const std::string &filename) {
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 804 times.
804 assert(id < kMaxCustomlog);
576 804 pthread_mutex_lock(&customlog_locks[id]);
577
578
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 678 times.
804 if (customlog_fds[id] >= 0) {
579 126 close(customlog_fds[id]);
580 126 customlog_fds[id] = -1;
581 }
582
583
2/2
✓ Branch 1 taken 675 times.
✓ Branch 2 taken 129 times.
804 if (filename.empty()) {
584
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 549 times.
675 delete customlog_dests[id];
585 675 customlog_dests[id] = NULL;
586 675 pthread_mutex_unlock(&customlog_locks[id]);
587 675 return;
588 }
589
590 129 customlog_fds[id] = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
129 if (customlog_fds[id] < 0) {
592 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
593 "could not open log file %s (%d), aborting", filename.c_str(),
594 ✗ errno);
595 ✗ abort();
596 }
597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 129 times.
129 delete customlog_dests[id];
598
1/2
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
129 customlog_dests[id] = new string(filename);
599
600 129 pthread_mutex_unlock(&customlog_locks[id]);
601 }
602
603
604 168 static void LogCustom(unsigned id, const std::string &message) {
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 assert(id < kMaxCustomlog);
606
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
168 if (message.size() == 0)
607 ✗ return;
608
609 168 pthread_mutex_lock(&customlog_locks[id]);
610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 assert(customlog_fds[id] >= 0);
611
612 168 const bool retval_b = SafeWrite(customlog_fds[id], message.data(),
613 message.size());
614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (!retval_b) {
615 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
616 "could not write into log file %s (%d), aborting - lost: %s",
617 ✗ customlog_dests[id]->c_str(), errno, message.c_str());
618 ✗ abort();
619 }
620 168 const int retval_i = fsync(customlog_fds[id]);
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 assert(retval_i == 0);
622
623 168 pthread_mutex_unlock(&customlog_locks[id]);
624 }
625
626
627 225 void LogShutdown() {
628
2/4
✓ Branch 2 taken 225 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 225 times.
✗ Branch 6 not taken.
225 SetLogMicroSyslog("");
629
2/2
✓ Branch 0 taken 675 times.
✓ Branch 1 taken 225 times.
900 for (unsigned i = 0; i < kMaxCustomlog; ++i)
630
2/4
✓ Branch 2 taken 675 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 675 times.
✗ Branch 6 not taken.
675 SetLogCustomFile(i, "");
631 225 }
632
633
634 #ifdef CVMFS_NAMESPACE_GUARD
635 } // namespace CVMFS_NAMESPACE_GUARD
636 #endif
637