GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/logging.cc
Date: 2026-10-04 02:40:33
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 44426162 void Append(const LogBufferEntry &entry) {
112 44426162 const MutexLockGuard lock_guard(lock_);
113 44426321 const size_t idx = next_id_++ % kBufferSize;
114
2/2
✓ Branch 1 taken 947 times.
✓ Branch 2 taken 44425374 times.
44426321 if (idx >= buffer_.size()) {
115
1/2
✓ Branch 1 taken 947 times.
✗ Branch 2 not taken.
947 buffer_.push_back(entry);
116 } else {
117
1/2
✓ Branch 2 taken 44425374 times.
✗ Branch 3 not taken.
44425374 buffer_[idx] = entry;
118 }
119 44426321 }
120
121 176 std::vector<LogBufferEntry> GetBuffer() {
122 // Return a buffer sorted from newest to oldest buffer
123 176 std::vector<LogBufferEntry> sorted_buffer;
124 176 const MutexLockGuard lock_guard(lock_);
125
2/2
✓ Branch 1 taken 716 times.
✓ Branch 2 taken 176 times.
892 for (unsigned i = 1; i <= buffer_.size(); ++i) {
126 716 const unsigned idx = (next_id_ - i) % kBufferSize;
127
1/2
✓ Branch 2 taken 716 times.
✗ Branch 3 not taken.
716 sorted_buffer.push_back(buffer_[idx]);
128 }
129 352 return sorted_buffer;
130 176 }
131
132 36 void Clear() {
133 36 const MutexLockGuard lock_guard(lock_);
134 36 next_id_ = 0;
135 36 buffer_.clear();
136 36 }
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 437 void SetLogSyslogLevel(const int level) {
153
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 437 times.
✗ Branch 3 not taken.
437 switch (level) {
154 ✗ case 1:
155 ✗ syslog_level = LOG_DEBUG;
156 ✗ break;
157 ✗ case 2:
158 ✗ syslog_level = LOG_INFO;
159 ✗ break;
160 437 case 3:
161 437 syslog_level = LOG_NOTICE;
162 437 break;
163 ✗ default:
164 ✗ syslog_level = LOG_NOTICE;
165 ✗ break;
166 }
167 437 }
168
169 141 int GetLogSyslogLevel() {
170
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
141 switch (syslog_level) {
171 ✗ case LOG_DEBUG:
172 ✗ return 1;
173 ✗ case LOG_INFO:
174 ✗ return 2;
175 141 default:
176 141 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 141 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 141 times.
141 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 141 default:
234 141 return -1;
235 }
236 }
237
238 /**
239 * The syslog prefix is used to distinguish multiple repositories in
240 * /var/log/messages
241 */
242 2630 void SetLogSyslogPrefix(const std::string &prefix) {
243
2/2
✓ Branch 0 taken 1328 times.
✓ Branch 1 taken 1302 times.
2630 if (syslog_prefix)
244 1328 free(syslog_prefix);
245
246
2/2
✓ Branch 1 taken 1276 times.
✓ Branch 2 taken 1354 times.
2630 if (prefix == "") {
247 1276 syslog_prefix = NULL;
248 } else {
249 1354 const unsigned len = prefix.length() + 1;
250 1354 syslog_prefix = static_cast<char *>(smalloc(len));
251 1354 syslog_prefix[len - 1] = '\0';
252 1354 memcpy(syslog_prefix, &prefix[0], prefix.length());
253 }
254 2630 }
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 24 void SetLogVerbosity(const LogLevels max_level) { max_log_level = max_level; }
264
265
266 37 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 1667 void SetLogMicroSyslog(const std::string &filename) {
273 1667 pthread_mutex_lock(&lock_usyslock);
274
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 1594 times.
1667 if (usyslog_fd >= 0) {
275
1/2
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
73 close(usyslog_fd);
276
1/2
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
73 close(usyslog_fd1);
277 73 usyslog_fd = -1;
278 73 usyslog_fd1 = -1;
279 }
280
281
2/2
✓ Branch 1 taken 1594 times.
✓ Branch 2 taken 73 times.
1667 if (filename == "") {
282
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 1521 times.
1594 delete usyslog_dest;
283 1594 usyslog_dest = NULL;
284 1594 pthread_mutex_unlock(&lock_usyslock);
285 1594 return;
286 }
287
288
1/2
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
73 usyslog_fd = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 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 73 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 73 times.
✗ Branch 6 not taken.
73 usyslog_fd1 = open((filename + ".1").c_str(), O_WRONLY | O_CREAT, 0600);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 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 73 const int retval = platform_fstat(usyslog_fd, &info);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 assert(retval == 0);
303 73 usyslog_size = info.st_size;
304
2/4
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
73 usyslog_dest = new string(filename);
305 73 pthread_mutex_unlock(&lock_usyslock);
306 }
307
308 98 std::string GetLogMicroSyslog() {
309 98 pthread_mutex_lock(&lock_usyslock);
310 98 string result;
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 if (usyslog_dest)
312 ✗ result = *usyslog_dest;
313 98 pthread_mutex_unlock(&lock_usyslock);
314 98 return result;
315 }
316
317 37144 static void LogMicroSyslog(const std::string &message) {
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37144 times.
37144 if (message.size() == 0)
319 ✗ return;
320
321 37144 pthread_mutex_lock(&lock_usyslock);
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37144 times.
37144 if (usyslog_fd < 0) {
323 ✗ pthread_mutex_unlock(&lock_usyslock);
324 ✗ return;
325 }
326
327 37144 const int written = write(usyslog_fd, message.data(), message.size());
328
3/6
✓ Branch 0 taken 37144 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 37144 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 37144 times.
37144 if ((written < 0) || (static_cast<unsigned>(written) != message.size())) {
329 ✗ close(usyslog_fd);
330 ✗ usyslog_fd = -1;
331 ✗ abort();
332 }
333 37144 int retval = fsync(usyslog_fd);
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37144 times.
37144 assert(retval == 0);
335 37144 usyslog_size += written;
336
337
2/2
✓ Branch 0 taken 333 times.
✓ Branch 1 taken 36811 times.
37144 if (usyslog_size >= gMicroSyslogMax) {
338 // Wipe out usyslog.1 file
339 333 retval = ftruncate(usyslog_fd1, 0);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 assert(retval == 0);
341
342 // Copy from usyslog to usyslog.1
343 333 retval = lseek(usyslog_fd, 0, SEEK_SET);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 assert(retval == 0);
345 unsigned char buf[4096];
346 int num_bytes;
347 do {
348
1/2
✓ Branch 1 taken 333 times.
✗ Branch 2 not taken.
333 num_bytes = read(usyslog_fd, buf, 4096);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 assert(num_bytes >= 0);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 if (num_bytes == 0)
351 ✗ break;
352
1/2
✓ Branch 1 taken 333 times.
✗ Branch 2 not taken.
333 const int written = write(usyslog_fd1, buf, num_bytes);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 assert(written == num_bytes);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 } while (num_bytes == 4096);
355 333 retval = lseek(usyslog_fd1, 0, SEEK_SET);
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 assert(retval == 0);
357
358 // Reset usyslog
359 333 retval = lseek(usyslog_fd, 0, SEEK_SET);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 assert(retval == 0);
361 333 retval = ftruncate(usyslog_fd, 0);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
333 assert(retval == 0);
363 333 usyslog_size = 0;
364 }
365 37144 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 1374 void SetLogDebugFile(const string &filename) {
373
1/2
✓ Branch 1 taken 1374 times.
✗ Branch 2 not taken.
1374 if (filename == "") {
374
2/4
✓ Branch 0 taken 1374 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1374 times.
1374 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 1374 times.
1374 delete path_debug;
379 1374 path_debug = NULL;
380 1374 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 190 string GetLogDebugFile() {
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
190 if (path_debug)
407 ✗ return *path_debug;
408
1/2
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
190 return "";
409 }
410 #endif
411
412 1399 void SetAltLogFunc(void (*fn)(const LogSource source, const int mask,
413 const char *msg)) {
414 1399 alt_log_func = fn;
415 1399 }
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 44704356 void vLogCvmfs(const LogSource source, const int mask, const char *format,
428 va_list variadic_list) {
429 44704356 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 44704356 const int retval = vasprintf(&msg, format, variadic_list);
444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44704207 times.
44703832 assert(retval != -1); // else: out of memory
445
446
2/2
✓ Branch 0 taken 279319 times.
✓ Branch 1 taken 44424888 times.
44704207 if (alt_log_func) {
447
1/2
✓ Branch 1 taken 279319 times.
✗ Branch 2 not taken.
279319 (*alt_log_func)(source, mask, msg);
448 279319 return;
449 }
450
451 #ifdef DEBUGMSG
452
2/2
✓ Branch 0 taken 37809799 times.
✓ Branch 1 taken 6615089 times.
44424888 if (mask & kLogDebug) {
453 37809799 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 37811171 times.
37811269 if (file_debug == NULL)
457 98 file_debug = stderr;
458
459 // Get timestamp
460 time_t rawtime;
461 37811269 time(&rawtime);
462 struct tm now;
463 37811269 localtime_r(&rawtime, &now);
464
465
1/2
✓ Branch 0 taken 37811269 times.
✗ Branch 1 not taken.
37811269 if (file_debug == stderr)
466 37811269 pthread_mutex_lock(&lock_stderr);
467 37811269 fprintf(file_debug, "(%s) %s [%02d-%02d-%04d %02d:%02d:%02d %s]\n",
468 37811269 module_names[source], msg, (now.tm_mon) + 1, now.tm_mday,
469
1/2
✓ Branch 1 taken 37811269 times.
✗ Branch 2 not taken.
37811269 (now.tm_year) + 1900, now.tm_hour, now.tm_min, now.tm_sec,
470 now.tm_zone);
471
1/2
✓ Branch 1 taken 37811269 times.
✗ Branch 2 not taken.
37811269 fflush(file_debug);
472
1/2
✓ Branch 0 taken 37811269 times.
✗ Branch 1 not taken.
37811269 if (file_debug == stderr)
473 37811269 pthread_mutex_unlock(&lock_stderr);
474
475 37811269 pthread_mutex_unlock(&lock_debug);
476 }
477 #endif
478
479
2/2
✓ Branch 0 taken 6399009 times.
✓ Branch 1 taken 38027349 times.
44426358 if (mask & kLogStdout) {
480 6399009 pthread_mutex_lock(&lock_stdout);
481
2/2
✓ Branch 0 taken 6392418 times.
✓ Branch 1 taken 6759 times.
6399177 if (mask & kLogShowSource)
482
1/2
✓ Branch 1 taken 6392418 times.
✗ Branch 2 not taken.
6392418 printf("(%s) ", module_names[source]);
483
1/2
✓ Branch 1 taken 6399177 times.
✗ Branch 2 not taken.
6399177 printf("%s", msg);
484
2/2
✓ Branch 0 taken 6399055 times.
✓ Branch 1 taken 122 times.
6399177 if (!(mask & kLogNoLinebreak))
485
1/2
✓ Branch 1 taken 6399055 times.
✗ Branch 2 not taken.
6399055 printf("\n");
486
1/2
✓ Branch 1 taken 6399177 times.
✗ Branch 2 not taken.
6399177 fflush(stdout);
487 6399177 pthread_mutex_unlock(&lock_stdout);
488 }
489
490
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 44426392 times.
44426526 if (mask & kLogStderr) {
491 134 pthread_mutex_lock(&lock_stderr);
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 134 times.
134 if (mask & kLogShowSource)
493 ✗ fprintf(stderr, "(%s) ", module_names[source]);
494
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 fprintf(stderr, "%s", msg);
495
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 if (!(mask & kLogNoLinebreak))
496
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 fprintf(stderr, "\n");
497
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 fflush(stderr);
498 134 pthread_mutex_unlock(&lock_stderr);
499 }
500
501
2/2
✓ Branch 0 taken 45043 times.
✓ Branch 1 taken 44381483 times.
44426526 if (mask & (kLogSyslog | kLogSyslogWarn | kLogSyslogErr)) {
502
2/2
✓ Branch 0 taken 37144 times.
✓ Branch 1 taken 7899 times.
45043 if (usyslog_dest) {
503
1/2
✓ Branch 2 taken 37144 times.
✗ Branch 3 not taken.
37144 string fmt_msg(msg);
504
1/2
✓ Branch 0 taken 37144 times.
✗ Branch 1 not taken.
37144 if (syslog_prefix)
505
4/8
✓ Branch 2 taken 37144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 37144 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 37144 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 37144 times.
✗ Branch 12 not taken.
37144 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
506 time_t rawtime;
507 37144 time(&rawtime);
508 char fmt_time[26];
509 37144 ctime_r(&rawtime, fmt_time);
510
3/6
✓ Branch 2 taken 37144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 37144 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 37144 times.
✗ Branch 9 not taken.
37144 fmt_msg = string(fmt_time, 24) + " " + fmt_msg;
511
1/2
✓ Branch 1 taken 37144 times.
✗ Branch 2 not taken.
37144 fmt_msg.push_back('\n');
512
1/2
✓ Branch 1 taken 37144 times.
✗ Branch 2 not taken.
37144 LogMicroSyslog(fmt_msg);
513 37144 } else {
514 7899 int level = syslog_level;
515
2/2
✓ Branch 0 taken 1243 times.
✓ Branch 1 taken 6656 times.
7899 if (mask & kLogSyslogWarn)
516 1243 level = LOG_WARNING;
517
2/2
✓ Branch 0 taken 2439 times.
✓ Branch 1 taken 5460 times.
7899 if (mask & kLogSyslogErr)
518 2439 level = LOG_ERR;
519
2/2
✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 6619 times.
7899 if (syslog_prefix) {
520
1/2
✓ Branch 1 taken 1280 times.
✗ Branch 2 not taken.
1280 syslog(syslog_facility | level, "(%s) %s", syslog_prefix, msg);
521 } else {
522
1/2
✓ Branch 1 taken 6291 times.
✗ Branch 2 not taken.
6619 syslog(syslog_facility | level, "%s", msg);
523 }
524 }
525 }
526
527
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 44426046 times.
44426198 if (mask & (kLogCustom0 | kLogCustom1 | kLogCustom2)) {
528
1/2
✓ Branch 2 taken 152 times.
✗ Branch 3 not taken.
152 string fmt_msg(msg);
529
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 114 times.
152 if (syslog_prefix)
530
4/8
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 38 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 38 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 38 times.
✗ Branch 12 not taken.
38 fmt_msg = "(" + string(syslog_prefix) + ") " + fmt_msg;
531
1/2
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
152 if (!(mask & kLogNoLinebreak))
532
1/2
✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
152 fmt_msg += "\n";
533
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 76 times.
152 if (mask & kLogCustom0)
534
1/2
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
76 LogCustom(0, fmt_msg);
535
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 114 times.
152 if (mask & kLogCustom1)
536
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 LogCustom(1, fmt_msg);
537
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 114 times.
152 if (mask & kLogCustom2)
538
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
38 LogCustom(2, fmt_msg);
539 152 }
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 44426162 times.
✓ Branch 1 taken 36 times.
44426198 if (!(mask & kLogSensitive))
545
3/6
✓ Branch 2 taken 44426321 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 44426321 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 44426309 times.
✗ Branch 9 not taken.
44426162 g_log_buffer.Append(LogBufferEntry(source, mask, msg));
546
547 44426357 free(msg);
548 }
549 CVMFS_EXPORT
550 44704455 void LogCvmfs(const LogSource source, const int mask, const char *format, ...) {
551 va_list variadic_list;
552 44704455 va_start(variadic_list, format);
553
1/2
✓ Branch 1 taken 44705676 times.
✗ Branch 2 not taken.
44704455 vLogCvmfs(source, mask, format, variadic_list);
554 44705676 va_end(variadic_list);
555 44705676 }
556
557 176 std::vector<LogBufferEntry> GetLogBuffer() { return g_log_buffer.GetBuffer(); }
558
559 36 void ClearLogBuffer() { g_log_buffer.Clear(); }
560
561 240 void PrintError(const string &message) {
562 240 LogCvmfs(kLogCvmfs, kLogStderr, "[ERROR] %s", message.c_str());
563 240 }
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 669 void SetLogCustomFile(unsigned id, const std::string &filename) {
574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 669 times.
669 assert(id < kMaxCustomlog);
575 669 pthread_mutex_lock(&customlog_locks[id]);
576
577
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 555 times.
669 if (customlog_fds[id] >= 0) {
578 114 close(customlog_fds[id]);
579 114 customlog_fds[id] = -1;
580 }
581
582
2/2
✓ Branch 1 taken 552 times.
✓ Branch 2 taken 117 times.
669 if (filename.empty()) {
583
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 438 times.
552 delete customlog_dests[id];
584 552 customlog_dests[id] = NULL;
585 552 pthread_mutex_unlock(&customlog_locks[id]);
586 552 return;
587 }
588
589 117 customlog_fds[id] = open(filename.c_str(), O_RDWR | O_APPEND | O_CREAT, 0600);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 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 117 times.
117 delete customlog_dests[id];
597
1/2
✓ Branch 2 taken 117 times.
✗ Branch 3 not taken.
117 customlog_dests[id] = new string(filename);
598
599 117 pthread_mutex_unlock(&customlog_locks[id]);
600 }
601
602
603 152 static void LogCustom(unsigned id, const std::string &message) {
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 assert(id < kMaxCustomlog);
605
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 152 times.
152 if (message.size() == 0)
606 ✗ return;
607
608 152 pthread_mutex_lock(&customlog_locks[id]);
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 assert(customlog_fds[id] >= 0);
610
611 152 const bool retval_b = SafeWrite(customlog_fds[id], message.data(),
612 message.size());
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 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 152 const int retval_i = fsync(customlog_fds[id]);
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 assert(retval_i == 0);
621
622 152 pthread_mutex_unlock(&customlog_locks[id]);
623 }
624
625
626 184 void LogShutdown() {
627
2/4
✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 184 times.
✗ Branch 6 not taken.
184 SetLogMicroSyslog("");
628
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 184 times.
736 for (unsigned i = 0; i < kMaxCustomlog; ++i)
629
2/4
✓ Branch 2 taken 552 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 552 times.
✗ Branch 6 not taken.
552 SetLogCustomFile(i, "");
630 184 }
631
632
633 #ifdef CVMFS_NAMESPACE_GUARD
634 } // namespace CVMFS_NAMESPACE_GUARD
635 #endif
636