GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2026-10-11 02:40:02
Exec Total Coverage
Lines: 233 343 67.9%
Branches: 156 303 51.5%

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 int syslog_facility = LOG_USER;
79 int syslog_level = LOG_NOTICE;
80 char *syslog_prefix = NULL;
81
82 string *usyslog_dest = NULL;
83 int usyslog_fd = -1;
84 int usyslog_fd1 = -1;
85 unsigned usyslog_size = 0;
86 pthread_mutex_t lock_usyslock = PTHREAD_MUTEX_INITIALIZER;
87
88 const unsigned kMaxCustomlog = 3;
89 string *customlog_dests[] = {NULL, NULL, NULL};
90 int customlog_fds[] = {-1, -1, -1};
91 pthread_mutex_t customlog_locks[] = {PTHREAD_MUTEX_INITIALIZER,
92 PTHREAD_MUTEX_INITIALIZER,
93 PTHREAD_MUTEX_INITIALIZER};
94
95 LogLevels max_log_level = kLogNormal;
96 static void (*alt_log_func)(const LogSource source, const int mask,
97 const char *msg) = NULL;
98
99 /**
100 * Circular buffer of the last $n$ calls to LogCvmfs(). Thread-safe class.
101 */
102 class LogBuffer : SingleCopy {
103 public:
104 51 LogBuffer() : next_id_(0) {
105 51 const int retval = pthread_mutex_init(&lock_, NULL);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 assert(retval == 0);
107 51 }
108
109 57 ~LogBuffer() { pthread_mutex_destroy(&lock_); }
110
111 26636241 void Append(const LogBufferEntry &entry) {
112 26636241 const MutexLockGuard lock_guard(lock_);
113 26636278 const size_t idx = next_id_++ % kBufferSize;
114
2/2
✓ Branch 1 taken 747 times.
✓ Branch 2 taken 26635531 times.
26636278 if (idx >= buffer_.size()) {
115
1/2
✓ Branch 1 taken 747 times.
✗ Branch 2 not taken.
747 buffer_.push_back(entry);
116 } else {
117
1/2
✓ Branch 2 taken 26635531 times.
✗ Branch 3 not taken.
26635531 buffer_[idx] = entry;
118 }
119 26636278 }
120
121 152 std::vector<LogBufferEntry> GetBuffer() {
122 // Return a buffer sorted from newest to oldest buffer
123 152 std::vector<LogBufferEntry> sorted_buffer;
124 152 const MutexLockGuard lock_guard(lock_);
125
2/2
✓ Branch 1 taken 1056 times.
✓ Branch 2 taken 152 times.
1208 for (unsigned i = 1; i <= buffer_.size(); ++i) {
126 1056 const unsigned idx = (next_id_ - i) % kBufferSize;
127
1/2
✓ Branch 2 taken 1056 times.
✗ Branch 3 not taken.
1056 sorted_buffer.push_back(buffer_[idx]);
128 }
129 304 return sorted_buffer;
130 152 }
131
132 16 void Clear() {
133 16 const MutexLockGuard lock_guard(lock_);
134 16 next_id_ = 0;
135 16 buffer_.clear();
136 16 }
137
138 private:
139 static const unsigned kBufferSize = 10;
140 pthread_mutex_t lock_;
141 int next_id_;
142 std::vector<LogBufferEntry> buffer_;
143 };
144
145 LogBuffer g_log_buffer;
146
147 } // namespace
148
149 /**
150 * Sets the level that is used for all messages to the syslog facility.
151 */
152 30 void SetLogSyslogLevel(const int level) {
153
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
30 switch (level) {
154 ✗ case 1:
155 ✗ syslog_level = LOG_DEBUG;
156 ✗ break;
157 ✗ case 2:
158 ✗ syslog_level = LOG_INFO;
159 ✗ break;
160 30 case 3:
161 30 syslog_level = LOG_NOTICE;
162 30 break;
163 ✗ default:
164 ✗ syslog_level = LOG_NOTICE;
165 ✗ break;
166 }
167 30 }
168
169 105 int GetLogSyslogLevel() {
170
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 105 times.
105 switch (syslog_level) {
171 ✗ case LOG_DEBUG:
172 ✗ return 1;
173 ✗ case LOG_INFO:
174 ✗ return 2;
175 105 default:
176 105 return 3;
177 }
178 }
179
180 /**
181 * Sets the syslog facility to one of local0 .. local7.
182 * Falls back to LOG_USER if local_facility is not in [0..7]
183 */
184 ✗ void SetLogSyslogFacility(const int local_facility) {
185 ✗ switch (local_facility) {
186 ✗ case 0:
187 ✗ syslog_facility = LOG_LOCAL0;
188 ✗ break;
189 ✗ case 1:
190 ✗ syslog_facility = LOG_LOCAL1;
191 ✗ break;
192 ✗ case 2:
193 ✗ syslog_facility = LOG_LOCAL2;
194 ✗ break;
195 ✗ case 3:
196 ✗ syslog_facility = LOG_LOCAL3;
197 ✗ break;
198 ✗ case 4:
199 ✗ syslog_facility = LOG_LOCAL4;
200 ✗ break;
201 ✗ case 5:
202 ✗ syslog_facility = LOG_LOCAL5;
203 ✗ break;
204 ✗ case 6:
205 ✗ syslog_facility = LOG_LOCAL6;
206 ✗ break;
207 ✗ case 7:
208 ✗ syslog_facility = LOG_LOCAL7;
209 ✗ break;
210 ✗ default:
211 ✗ syslog_facility = LOG_USER;
212 }
213 }
214
215 105 int GetLogSyslogFacility() {
216
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) {
217 ✗ case LOG_LOCAL0:
218 ✗ return 0;
219 ✗ case LOG_LOCAL1:
220 ✗ return 1;
221 ✗ case LOG_LOCAL2:
222 ✗ return 2;
223 ✗ case LOG_LOCAL3:
224 ✗ return 3;
225 ✗ case LOG_LOCAL4:
226 ✗ return 4;
227 ✗ case LOG_LOCAL5:
228 ✗ return 5;
229 ✗ case LOG_LOCAL6:
230 ✗ return 6;
231 ✗ case LOG_LOCAL7:
232 ✗ return 7;
233 105 default:
234 105 return -1;
235 }
236 }
237
238 /**
239 * The syslog prefix is used to distinguish multiple repositories in
240 * /var/log/messages
241 */
242 4547 void SetLogSyslogPrefix(const std::string &prefix) {
243
2/2
✓ Branch 0 taken 2273 times.
✓ Branch 1 taken 2274 times.
4547 if (syslog_prefix)
244 2273 free(syslog_prefix);
245
246
2/2
✓ Branch 1 taken 2259 times.
✓ Branch 2 taken 2288 times.
4547 if (prefix == "") {
247 2259 syslog_prefix = NULL;
248 } else {
249 2288 const unsigned len = prefix.length() + 1;
250 2288 syslog_prefix = static_cast<char *>(smalloc(len));
251 2288 syslog_prefix[len - 1] = '\0';
252 2288 memcpy(syslog_prefix, &prefix[0], prefix.length());
253 }
254 4547 }
255
256 ✗ void SetLogSyslogShowPID(bool flag) {
257 ✗ openlog(NULL, flag ? LOG_PID : 0, GetLogSyslogFacility());
258 }
259
260 /**
261 * Set the maximum verbosity level. By default kLogNormal.
262 */
263 74 void SetLogVerbosity(const LogLevels max_level) { max_log_level = max_level; }
264
265
266 16 void SetLogMicroSyslogMaxSize(unsigned bytes) { gMicroSyslogMax = bytes; }
267
268 /**
269 * "Micro-Syslog" write kLogSyslog messages into filename. It rotates this
270 * file. Requires for µCernVM
271 */
272 2469 void SetLogMicroSyslog(const std::string &filename) {
273 2469 pthread_mutex_lock(&lock_usyslock);
274
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2438 times.
2469 if (usyslog_fd >= 0) {
275
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 close(usyslog_fd);
276
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 close(usyslog_fd1);
277 31 usyslog_fd = -1;
278 31 usyslog_fd1 = -1;
279 }
280
281
2/2
✓ Branch 1 taken 2438 times.
✓ Branch 2 taken 31 times.
2469 if (filename == "") {
282
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2407 times.
2438 delete usyslog_dest;
283 2438 usyslog_dest = NULL;
284 2438 pthread_mutex_unlock(&lock_usyslock);
285 2438 return;
286 }
287
288
1/2
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
31 usyslog_fd = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (usyslog_fd < 0) {
290 ✗ fprintf(stderr, "could not open usyslog file %s (%d), aborting\n",
291 ✗ filename.c_str(), errno);
292 ✗ abort();
293 }
294
2/4
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 31 times.
✗ Branch 6 not taken.
31 usyslog_fd1 = open((filename + ".1").c_str(), O_WRONLY | O_CREAT, 0600);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (usyslog_fd1 < 0) {
296 ✗ fprintf(stderr, "could not open usyslog.1 file %s.1 (%d), aborting\n",
297 ✗ filename.c_str(), errno);
298 ✗ abort();
299 }
300 platform_stat64 info;
301 31 const int retval = platform_fstat(usyslog_fd, &info);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 assert(retval == 0);
303 31 usyslog_size = info.st_size;
304
2/4
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
31 usyslog_dest = new string(filename);
305 31 pthread_mutex_unlock(&lock_usyslock);
306 }
307
308 68 std::string GetLogMicroSyslog() {
309 68 pthread_mutex_lock(&lock_usyslock);
310 68 string result;
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (usyslog_dest)
312 ✗ result = *usyslog_dest;
313 68 pthread_mutex_unlock(&lock_usyslock);
314 68 return result;
315 }
316
317 16060 static void LogMicroSyslog(const std::string &message) {
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16060 times.
16060 if (message.size() == 0)
319 ✗ return;
320
321 16060 pthread_mutex_lock(&lock_usyslock);
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16060 times.
16060 if (usyslog_fd < 0) {
323 ✗ pthread_mutex_unlock(&lock_usyslock);
324 ✗ return;
325 }
326
327 16060 const int written = write(usyslog_fd, message.data(), message.size());
328
3/6
✓ Branch 0 taken 16060 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16060 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16060 times.
16060 if ((written < 0) || (static_cast<unsigned>(written) != message.size())) {
329 ✗ close(usyslog_fd);
330 ✗ usyslog_fd = -1;
331 ✗ abort();
332 }
333 16060 int retval = fsync(usyslog_fd);
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16060 times.
16060 assert(retval == 0);
335 16060 usyslog_size += written;
336
337
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 15948 times.
16060 if (usyslog_size >= gMicroSyslogMax) {
338 // Wipe out usyslog.1 file
339 112 retval = ftruncate(usyslog_fd1, 0);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(retval == 0);
341
342 // Copy from usyslog to usyslog.1
343 112 retval = lseek(usyslog_fd, 0, SEEK_SET);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(retval == 0);
345 unsigned char buf[4096];
346 int num_bytes;
347 do {
348
1/2
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
112 num_bytes = read(usyslog_fd, buf, 4096);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(num_bytes >= 0);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (num_bytes == 0)
351 ✗ break;
352
1/2
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
112 const int written = write(usyslog_fd1, buf, num_bytes);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(written == num_bytes);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 } while (num_bytes == 4096);
355 112 retval = lseek(usyslog_fd1, 0, SEEK_SET);
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(retval == 0);
357
358 // Reset usyslog
359 112 retval = lseek(usyslog_fd, 0, SEEK_SET);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(retval == 0);
361 112 retval = ftruncate(usyslog_fd, 0);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(retval == 0);
363 112 usyslog_size = 0;
364 }
365 16060 pthread_mutex_unlock(&lock_usyslock);
366 }
367
368 /**
369 * Changes the debug log file from stderr. No effect if DEBUGMSG is undefined.
370 */
371 #ifdef DEBUGMSG
372 2357 void SetLogDebugFile(const string &filename) {
373
1/2
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
2357 if (filename == "") {
374
2/4
✓ Branch 0 taken 2357 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2357 times.
2357 if ((file_debug != NULL) && (file_debug != stderr)) {
375 ✗ fclose(file_debug);
376 ✗ file_debug = NULL;
377 }
378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2357 times.
2357 delete path_debug;
379 2357 path_debug = NULL;
380 2357 return;
381 }
382
383 ✗ if ((file_debug != NULL) && (file_debug != stderr)) {
384 ✗ if ((fclose(file_debug) < 0)) {
385 ✗ fprintf(stderr, "could not close current log file (%d), aborting\n",
386 ✗ errno);
387
388 ✗ abort();
389 }
390 }
391 ✗ const int fd = open(filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0600);
392 ✗ if ((fd < 0) || ((file_debug = fdopen(fd, "a")) == NULL)) {
393 ✗ fprintf(stderr, "could not open debug log file %s (%d), aborting\n",
394 ✗ filename.c_str(), errno);
395 ✗ syslog(syslog_facility | LOG_ERR,
396 "could not open debug log file %s (%d), "
397 "aborting\n",
398 ✗ filename.c_str(), errno);
399 ✗ abort();
400 }
401 ✗ delete path_debug;
402 ✗ path_debug = new string(filename);
403 }
404
405 154 string GetLogDebugFile() {
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (path_debug)
407 ✗ return *path_debug;
408
1/2
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
154 return "";
409 }
410 #endif
411
412 249 void SetAltLogFunc(void (*fn)(const LogSource source, const int mask,
413 const char *msg)) {
414 249 alt_log_func = fn;
415 249 }
416
417
418 /**
419 * Logs a message to one or multiple facilities specified by mask.
420 * Mask can be extended by a log level in the future, using the higher bits.
421 *
422 * @param[in] source Component that triggers the logging
423 * @param[in] mask Bit mask of log facilities
424 * @param[in] format Format string followed by arguments like printf
425 */
426 CVMFS_EXPORT
427 26655007 void vLogCvmfs(const LogSource source, const int mask, const char *format,
428 va_list variadic_list) {
429 26655007 char *msg = NULL;
430
431 // Log level check, no flag set in mask means kLogNormal
432 #ifndef DEBUGMSG
433 ✗ int log_level = mask & ((2 * kLogNone - 1) ^ (kLogLevel0 - 1));
434 ✗ if (!log_level)
435 ✗ log_level = kLogNormal;
436 ✗ if (log_level == kLogNone)
437 ✗ return;
438 ✗ if (log_level > max_log_level)
439 ✗ return;
440 #endif
441
442 // Format the message string
443 26655007 const int retval = vasprintf(&msg, format, variadic_list);
444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26655187 times.
26654731 assert(retval != -1); // else: out of memory
445
446
2/2
✓ Branch 0 taken 19378 times.
✓ Branch 1 taken 26635809 times.
26655187 if (alt_log_func) {
447
1/2
✓ Branch 1 taken 19378 times.
✗ Branch 2 not taken.
19378 (*alt_log_func)(source, mask, msg);
448 19378 return;
449 }
450
451 #ifdef DEBUGMSG
452
2/2
✓ Branch 0 taken 18623391 times.
✓ Branch 1 taken 8012418 times.
26635809 if (mask & kLogDebug) {
453 18623391 pthread_mutex_lock(&lock_debug);
454
455 // Set the file pointer for debugging to stderr, if necessary
456
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 18623616 times.
18623714 if (file_debug == NULL)
457 98 file_debug = stderr;
458
459 // Get timestamp
460 time_t rawtime;
461 18623714 time(&rawtime);
462 struct tm now;
463 18623714 localtime_r(&rawtime, &now);
464
465
1/2
✓ Branch 0 taken 18623714 times.
✗ Branch 1 not taken.
18623714 if (file_debug == stderr)
466 18623714 pthread_mutex_lock(&lock_stderr);
467 18623714 fprintf(file_debug, "(%s) %s [%02d-%02d-%04d %02d:%02d:%02d %s]\n",
468 18623714 module_names[source], msg, (now.tm_mon) + 1, now.tm_mday,
469
1/2
✓ Branch 1 taken 18623714 times.
✗ Branch 2 not taken.
18623714 (now.tm_year) + 1900, now.tm_hour, now.tm_min, now.tm_sec,
470 now.tm_zone);
471
1/2
✓ Branch 1 taken 18623714 times.
✗ Branch 2 not taken.
18623714 fflush(file_debug);
472
1/2
✓ Branch 0 taken 18623714 times.
✗ Branch 1 not taken.
18623714 if (file_debug == stderr)
473 18623714 pthread_mutex_unlock(&lock_stderr);
474
475 18623714 pthread_mutex_unlock(&lock_debug);
476 }
477 #endif
478
479
2/2
✓ Branch 0 taken 7915690 times.
✓ Branch 1 taken 18720442 times.
26636132 if (mask & kLogStdout) {
480 7915690 pthread_mutex_lock(&lock_stdout);
481
2/2
✓ Branch 0 taken 7914709 times.
✓ Branch 1 taken 1359 times.
7916068 if (mask & kLogShowSource)
482
1/2
✓ Branch 1 taken 7914709 times.
✗ Branch 2 not taken.
7914709 printf("(%s) ", module_names[source]);
483
1/2
✓ Branch 1 taken 7916068 times.
✗ Branch 2 not taken.
7916068 printf("%s", msg);
484
2/2
✓ Branch 0 taken 7915743 times.
✓ Branch 1 taken 325 times.
7916068 if (!(mask & kLogNoLinebreak))
485
1/2
✓ Branch 1 taken 7915743 times.
✗ Branch 2 not taken.
7915743 printf("\n");
486
1/2
✓ Branch 1 taken 7916068 times.
✗ Branch 2 not taken.
7916068 fflush(stdout);
487 7916068 pthread_mutex_unlock(&lock_stdout);
488 }
489
490
2/2
✓ Branch 0 taken 417 times.
✓ Branch 1 taken 26636093 times.
26636510 if (mask & kLogStderr) {
491 417 pthread_mutex_lock(&lock_stderr);
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 417 times.
417 if (mask & kLogShowSource)
493 ✗ fprintf(stderr, "(%s) ", module_names[source]);
494
1/2
✓ Branch 1 taken 417 times.
✗ Branch 2 not taken.
417 fprintf(stderr, "%s", msg);
495
1/2
✓ Branch 0 taken 417 times.
✗ Branch 1 not taken.
417 if (!(mask & kLogNoLinebreak))
496
1/2
✓ Branch 1 taken 417 times.
✗ Branch 2 not taken.
417 fprintf(stderr, "\n");
497
1/2
✓ Branch 1 taken 417 times.
✗ Branch 2 not taken.
417 fflush(stderr);
498 417 pthread_mutex_unlock(&lock_stderr);
499 }
500
501
2/2
✓ Branch 0 taken 25825 times.
✓ Branch 1 taken 26610685 times.
26636510 if (mask & (kLogSyslog | kLogSyslogWarn | kLogSyslogErr)) {
502
2/2
✓ Branch 0 taken 16060 times.
✓ Branch 1 taken 9765 times.
25825 if (usyslog_dest) {
503
1/2
✓ Branch 2 taken 16060 times.
✗ Branch 3 not taken.
16060 string fmt_msg(msg);
504
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 16015 times.
16060 if (syslog_prefix)
505
4/8
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 45 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 45 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 45 times.
✗ Branch 12 not taken.
45 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
506 time_t rawtime;
507 16060 time(&rawtime);
508 char fmt_time[26];
509 16060 ctime_r(&rawtime, fmt_time);
510
3/6
✓ Branch 2 taken 16060 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 16060 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 16060 times.
✗ Branch 9 not taken.
16060 fmt_msg = string(fmt_time, 24) + " " + fmt_msg;
511
1/2
✓ Branch 1 taken 16060 times.
✗ Branch 2 not taken.
16060 fmt_msg.push_back('\n');
512
1/2
✓ Branch 1 taken 16060 times.
✗ Branch 2 not taken.
16060 LogMicroSyslog(fmt_msg);
513 16060 } else {
514 9765 int level = syslog_level;
515
2/2
✓ Branch 0 taken 4044 times.
✓ Branch 1 taken 5721 times.
9765 if (mask & kLogSyslogWarn)
516 4044 level = LOG_WARNING;
517
2/2
✓ Branch 0 taken 2384 times.
✓ Branch 1 taken 7381 times.
9765 if (mask & kLogSyslogErr)
518 2384 level = LOG_ERR;
519
2/2
✓ Branch 0 taken 4339 times.
✓ Branch 1 taken 5426 times.
9765 if (syslog_prefix) {
520
1/2
✓ Branch 1 taken 4339 times.
✗ Branch 2 not taken.
4339 syslog(syslog_facility | level, "(%s) %s", syslog_prefix, msg);
521 } else {
522
1/2
✓ Branch 1 taken 5075 times.
✗ Branch 2 not taken.
5426 syslog(syslog_facility | level, "%s", msg);
523 }
524 }
525 }
526
527
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 26636119 times.
26636159 if (mask & (kLogCustom0 | kLogCustom1 | kLogCustom2)) {
528
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 string fmt_msg(msg);
529
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (syslog_prefix)
530
4/8
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 40 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 40 times.
✗ Branch 12 not taken.
40 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
531
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (!(mask & kLogNoLinebreak))
532
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 fmt_msg += "\n";
533
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (mask & kLogCustom0)
534
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 LogCustom(0, fmt_msg);
535
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 30 times.
40 if (mask & kLogCustom1)
536
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 LogCustom(1, fmt_msg);
537
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 30 times.
40 if (mask & kLogCustom2)
538
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 LogCustom(2, fmt_msg);
539 40 }
540
541 // The log buffer can be read via extended attributes from cvmfs, therefore
542 // we provide an option to hide entries from the buffer if they contain
543 // sensitive information
544
2/2
✓ Branch 0 taken 26636107 times.
✓ Branch 1 taken 52 times.
26636159 if (!(mask & kLogSensitive))
545
3/6
✓ Branch 2 taken 26636107 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 26636241 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 26636259 times.
✗ Branch 9 not taken.
26636107 g_log_buffer.Append(LogBufferEntry(source, mask, msg));
546
547 26636294 free(msg);
548 }
549 CVMFS_EXPORT
550 26654965 void LogCvmfs(const LogSource source, const int mask, const char *format, ...) {
551 va_list variadic_list;
552 26654965 va_start(variadic_list, format);
553
1/2
✓ Branch 1 taken 26655636 times.
✗ Branch 2 not taken.
26654965 vLogCvmfs(source, mask, format, variadic_list);
554 26655636 va_end(variadic_list);
555 26655636 }
556
557 152 std::vector<LogBufferEntry> GetLogBuffer() { return g_log_buffer.GetBuffer(); }
558
559 16 void ClearLogBuffer() { g_log_buffer.Clear(); }
560
561 15 void PrintError(const string &message) {
562 15 LogCvmfs(kLogCvmfs, kLogStderr, "[ERROR] %s", message.c_str());
563 15 }
564
565 ✗ void PrintWarning(const string &message) {
566 ✗ LogCvmfs(kLogCvmfs, kLogStderr, "[WARNING] %s", message.c_str());
567 }
568
569
570 /**
571 * Opens a custom log file
572 */
573 231 void SetLogCustomFile(unsigned id, const std::string &filename) {
574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 assert(id < kMaxCustomlog);
575 231 pthread_mutex_lock(&customlog_locks[id]);
576
577
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 201 times.
231 if (customlog_fds[id] >= 0) {
578 30 close(customlog_fds[id]);
579 30 customlog_fds[id] = -1;
580 }
581
582
2/2
✓ Branch 1 taken 198 times.
✓ Branch 2 taken 33 times.
231 if (filename.empty()) {
583
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 168 times.
198 delete customlog_dests[id];
584 198 customlog_dests[id] = NULL;
585 198 pthread_mutex_unlock(&customlog_locks[id]);
586 198 return;
587 }
588
589 33 customlog_fds[id] = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (customlog_fds[id] < 0) {
591 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
592 "could not open log file %s (%d), aborting", filename.c_str(),
593 ✗ errno);
594 ✗ abort();
595 }
596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 delete customlog_dests[id];
597
1/2
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 customlog_dests[id] = new string(filename);
598
599 33 pthread_mutex_unlock(&customlog_locks[id]);
600 }
601
602
603 40 static void LogCustom(unsigned id, const std::string &message) {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 assert(id < kMaxCustomlog);
605
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 if (message.size() == 0)
606 ✗ return;
607
608 40 pthread_mutex_lock(&customlog_locks[id]);
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 assert(customlog_fds[id] >= 0);
610
611 40 const bool retval_b = SafeWrite(customlog_fds[id], message.data(),
612 message.size());
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!retval_b) {
614 ✗ LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr,
615 "could not write into log file %s (%d), aborting - lost: %s",
616 ✗ customlog_dests[id]->c_str(), errno, message.c_str());
617 ✗ abort();
618 }
619 40 const int retval_i = fsync(customlog_fds[id]);
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 assert(retval_i == 0);
621
622 40 pthread_mutex_unlock(&customlog_locks[id]);
623 }
624
625
626 66 void LogShutdown() {
627
2/4
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 66 times.
✗ Branch 6 not taken.
66 SetLogMicroSyslog("");
628
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 66 times.
264 for (unsigned i = 0; i < kMaxCustomlog; ++i)
629
2/4
✓ Branch 2 taken 198 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 198 times.
✗ Branch 6 not taken.
198 SetLogCustomFile(i, "");
630 66 }
631
632
633 #ifdef CVMFS_NAMESPACE_GUARD
634 } // namespace CVMFS_NAMESPACE_GUARD
635 #endif
636