]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/log.h
4cb0b5795f8ff58bb9bb293bb701461e2c1a7769
[mirror_lxc.git] / src / lxc / log.h
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef __LXC_LOG_H
4 #define __LXC_LOG_H
5
6 #ifndef _GNU_SOURCE
7 #define _GNU_SOURCE 1
8 #endif
9 #include <errno.h>
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <sys/time.h>
13 #include <string.h>
14 #include <strings.h>
15 #include <stdbool.h>
16 #include <syslog.h>
17 #include <time.h>
18
19 #include "conf.h"
20 #include "config.h"
21
22 #ifndef O_CLOEXEC
23 #define O_CLOEXEC 02000000
24 #endif
25
26 #ifndef F_DUPFD_CLOEXEC
27 #define F_DUPFD_CLOEXEC 1030
28 #endif
29
30 #define LXC_LOG_PREFIX_SIZE 32
31 #define LXC_LOG_BUFFER_SIZE 4096
32
33 /* predefined lxc log priorities. */
34 enum lxc_loglevel {
35 LXC_LOG_LEVEL_TRACE,
36 LXC_LOG_LEVEL_DEBUG,
37 LXC_LOG_LEVEL_INFO,
38 LXC_LOG_LEVEL_NOTICE,
39 LXC_LOG_LEVEL_WARN,
40 LXC_LOG_LEVEL_ERROR,
41 LXC_LOG_LEVEL_CRIT,
42 LXC_LOG_LEVEL_ALERT,
43 LXC_LOG_LEVEL_FATAL,
44 LXC_LOG_LEVEL_NOTSET,
45 };
46
47 /* location information of the logging event */
48 struct lxc_log_locinfo {
49 const char *file;
50 const char *func;
51 int line;
52 };
53
54 #define LXC_LOG_LOCINFO_INIT \
55 { .file = __FILE__, .func = __func__, .line = __LINE__ }
56
57 /* brief logging event object */
58 struct lxc_log_event {
59 const char *category;
60 int priority;
61 struct timespec timestamp;
62 struct lxc_log_locinfo *locinfo;
63 const char *fmt;
64 va_list *vap;
65 };
66
67 /* log appender object */
68 struct lxc_log_appender {
69 const char *name;
70 int (*append)(const struct lxc_log_appender *, struct lxc_log_event *);
71
72 /*
73 * appenders can be stacked
74 */
75 struct lxc_log_appender *next;
76 };
77
78 /* log category object */
79 struct lxc_log_category {
80 const char *name;
81 int priority;
82 struct lxc_log_appender *appender;
83 const struct lxc_log_category *parent;
84 };
85
86 #ifndef NO_LXC_CONF
87 extern int lxc_log_use_global_fd;
88 #endif
89
90 /*
91 * Returns true if the chained priority is equal to or higher than
92 * given priority.
93 */
94 static inline int lxc_log_priority_is_enabled(const struct lxc_log_category *category,
95 int priority)
96 {
97 while (category->priority == LXC_LOG_LEVEL_NOTSET && category->parent)
98 category = category->parent;
99
100 int cmp_prio = category->priority;
101 #ifndef NO_LXC_CONF
102 if (!lxc_log_use_global_fd && current_config &&
103 current_config->loglevel != LXC_LOG_LEVEL_NOTSET)
104 cmp_prio = current_config->loglevel;
105 #endif
106
107 return priority >= cmp_prio;
108 }
109
110 /*
111 * converts a priority to a literal string
112 */
113 static inline const char *lxc_log_priority_to_string(int priority)
114 {
115 switch (priority) {
116 case LXC_LOG_LEVEL_TRACE:
117 return "TRACE";
118 case LXC_LOG_LEVEL_DEBUG:
119 return "DEBUG";
120 case LXC_LOG_LEVEL_INFO:
121 return "INFO";
122 case LXC_LOG_LEVEL_NOTICE:
123 return "NOTICE";
124 case LXC_LOG_LEVEL_WARN:
125 return "WARN";
126 case LXC_LOG_LEVEL_ERROR:
127 return "ERROR";
128 case LXC_LOG_LEVEL_CRIT:
129 return "CRIT";
130 case LXC_LOG_LEVEL_ALERT:
131 return "ALERT";
132 case LXC_LOG_LEVEL_FATAL:
133 return "FATAL";
134 }
135
136 return "NOTSET";
137 }
138
139 static inline const char *lxc_syslog_priority_to_string(int priority)
140 {
141 switch (priority) {
142 case LOG_DAEMON:
143 return "daemon";
144 case LOG_LOCAL0:
145 return "local0";
146 case LOG_LOCAL1:
147 return "local1";
148 case LOG_LOCAL2:
149 return "local2";
150 case LOG_LOCAL3:
151 return "local3";
152 case LOG_LOCAL4:
153 return "local4";
154 case LOG_LOCAL5:
155 return "local5";
156 case LOG_LOCAL6:
157 return "local6";
158 case LOG_LOCAL7:
159 return "local7";
160 }
161
162 return "NOTSET";
163 }
164
165 /*
166 * converts a literal priority to an int
167 */
168 static inline int lxc_log_priority_to_int(const char *name)
169 {
170 if (strcasecmp("TRACE", name) == 0)
171 return LXC_LOG_LEVEL_TRACE;
172 if (strcasecmp("DEBUG", name) == 0)
173 return LXC_LOG_LEVEL_DEBUG;
174 if (strcasecmp("INFO", name) == 0)
175 return LXC_LOG_LEVEL_INFO;
176 if (strcasecmp("NOTICE", name) == 0)
177 return LXC_LOG_LEVEL_NOTICE;
178 if (strcasecmp("WARN", name) == 0)
179 return LXC_LOG_LEVEL_WARN;
180 if (strcasecmp("ERROR", name) == 0)
181 return LXC_LOG_LEVEL_ERROR;
182 if (strcasecmp("CRIT", name) == 0)
183 return LXC_LOG_LEVEL_CRIT;
184 if (strcasecmp("ALERT", name) == 0)
185 return LXC_LOG_LEVEL_ALERT;
186 if (strcasecmp("FATAL", name) == 0)
187 return LXC_LOG_LEVEL_FATAL;
188
189 return LXC_LOG_LEVEL_NOTSET;
190 }
191
192 static inline int lxc_syslog_priority_to_int(const char *name)
193 {
194 if (strcasecmp("daemon", name) == 0)
195 return LOG_DAEMON;
196 if (strcasecmp("local0", name) == 0)
197 return LOG_LOCAL0;
198 if (strcasecmp("local1", name) == 0)
199 return LOG_LOCAL1;
200 if (strcasecmp("local2", name) == 0)
201 return LOG_LOCAL2;
202 if (strcasecmp("local3", name) == 0)
203 return LOG_LOCAL3;
204 if (strcasecmp("local4", name) == 0)
205 return LOG_LOCAL4;
206 if (strcasecmp("local5", name) == 0)
207 return LOG_LOCAL5;
208 if (strcasecmp("local6", name) == 0)
209 return LOG_LOCAL6;
210 if (strcasecmp("local7", name) == 0)
211 return LOG_LOCAL7;
212
213 return -EINVAL;
214 }
215
216 static inline void __lxc_log_append(const struct lxc_log_appender *appender,
217 struct lxc_log_event *event)
218 {
219 va_list va;
220 va_list *va_keep = event->vap;
221
222 while (appender) {
223 va_copy(va, *va_keep);
224 event->vap = &va;
225 appender->append(appender, event);
226 appender = appender->next;
227 va_end(va);
228 }
229 }
230
231 static inline void __lxc_log(const struct lxc_log_category *category,
232 struct lxc_log_event *event)
233 {
234 while (category) {
235 __lxc_log_append(category->appender, event);
236 category = category->parent;
237 }
238 }
239
240 /*
241 * Helper macro to define log functions.
242 */
243 #define lxc_log_priority_define(acategory, LEVEL) \
244 \
245 __lxc_unused __attribute__ ((format (printf, 2, 3))) \
246 static inline void LXC_##LEVEL(struct lxc_log_locinfo *, const char *, ...); \
247 \
248 __lxc_unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \
249 const char* format, ...) \
250 { \
251 if (lxc_log_priority_is_enabled(acategory, LXC_LOG_LEVEL_##LEVEL)) { \
252 va_list va_ref; \
253 int saved_errno; \
254 struct lxc_log_event evt = { \
255 .category = (acategory)->name, \
256 .priority = LXC_LOG_LEVEL_##LEVEL, \
257 .fmt = format, \
258 .locinfo = locinfo \
259 }; \
260 \
261 /* clock_gettime() is explicitly marked as MT-Safe \
262 * without restrictions. So let's use it for our \
263 * logging stamps. \
264 */ \
265 saved_errno = errno; \
266 (void)clock_gettime(CLOCK_REALTIME, &evt.timestamp); \
267 \
268 va_start(va_ref, format); \
269 evt.vap = &va_ref; \
270 __lxc_log(acategory, &evt); \
271 va_end(va_ref); \
272 errno = saved_errno; \
273 } \
274 }
275
276 /*
277 * Helper macro to define and use static categories.
278 */
279 #define lxc_log_category_define(name, parent) \
280 extern struct lxc_log_category lxc_log_category_##parent; \
281 struct lxc_log_category lxc_log_category_##name = { \
282 #name, \
283 LXC_LOG_LEVEL_NOTSET, \
284 NULL, \
285 &lxc_log_category_##parent \
286 };
287
288 #define lxc_log_define(name, parent) \
289 lxc_log_category_define(name, parent) \
290 \
291 lxc_log_priority_define(&lxc_log_category_##name, TRACE) \
292 lxc_log_priority_define(&lxc_log_category_##name, DEBUG) \
293 lxc_log_priority_define(&lxc_log_category_##name, INFO) \
294 lxc_log_priority_define(&lxc_log_category_##name, NOTICE) \
295 lxc_log_priority_define(&lxc_log_category_##name, WARN) \
296 lxc_log_priority_define(&lxc_log_category_##name, ERROR) \
297 lxc_log_priority_define(&lxc_log_category_##name, CRIT) \
298 lxc_log_priority_define(&lxc_log_category_##name, ALERT) \
299 lxc_log_priority_define(&lxc_log_category_##name, FATAL)
300
301 #define lxc_log_category_priority(name) \
302 (lxc_log_priority_to_string(lxc_log_category_##name.priority))
303
304 /*
305 * Helper macro to define errno string.
306 */
307 #if HAVE_STRERROR_R
308 #ifndef HAVE_DECL_STRERROR_R
309 #ifdef STRERROR_R_CHAR_P
310 char *strerror_r(int errnum, char *buf, size_t buflen);
311 #else
312 int strerror_r(int errnum, char *buf, size_t buflen);
313 #endif
314 #endif
315
316 #ifdef STRERROR_R_CHAR_P
317 #define lxc_log_strerror_r \
318 char errno_buf[PATH_MAX / 2] = {"Failed to get errno string"}; \
319 char *ptr = NULL; \
320 { \
321 int __saved_errno = errno; \
322 ptr = strerror_r(errno, errno_buf, sizeof(errno_buf)); \
323 errno = __saved_errno; \
324 if (!ptr) \
325 ptr = errno_buf; \
326 }
327 #else
328 #define lxc_log_strerror_r \
329 char errno_buf[PATH_MAX / 2] = {"Failed to get errno string"}; \
330 char *ptr = errno_buf; \
331 { \
332 int __saved_errno = errno; \
333 (void)strerror_r(errno, errno_buf, sizeof(errno_buf)); \
334 errno = __saved_errno; \
335 }
336 #endif
337 #elif ENFORCE_THREAD_SAFETY
338 #error ENFORCE_THREAD_SAFETY was set but cannot be guaranteed
339 #else
340 #define lxc_log_strerror_r \
341 char *ptr = NULL; \
342 { \
343 ptr = strerror(errno); \
344 }
345 #endif
346
347 /*
348 * top categories
349 */
350 #define TRACE(format, ...) do { \
351 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
352 LXC_TRACE(&locinfo, format, ##__VA_ARGS__); \
353 } while (0)
354
355 #define DEBUG(format, ...) do { \
356 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
357 LXC_DEBUG(&locinfo, format, ##__VA_ARGS__); \
358 } while (0)
359
360 #define INFO(format, ...) do { \
361 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
362 LXC_INFO(&locinfo, format, ##__VA_ARGS__); \
363 } while (0)
364
365 #define NOTICE(format, ...) do { \
366 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
367 LXC_NOTICE(&locinfo, format, ##__VA_ARGS__); \
368 } while (0)
369
370 #define WARN(format, ...) do { \
371 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
372 LXC_WARN(&locinfo, format, ##__VA_ARGS__); \
373 } while (0)
374
375 #define ERROR(format, ...) do { \
376 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
377 LXC_ERROR(&locinfo, format, ##__VA_ARGS__); \
378 } while (0)
379
380 #define CRIT(format, ...) do { \
381 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
382 LXC_CRIT(&locinfo, format, ##__VA_ARGS__); \
383 } while (0)
384
385 #define ALERT(format, ...) do { \
386 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
387 LXC_ALERT(&locinfo, format, ##__VA_ARGS__); \
388 } while (0)
389
390 #define FATAL(format, ...) do { \
391 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
392 LXC_FATAL(&locinfo, format, ##__VA_ARGS__); \
393 } while (0)
394
395 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
396 #define SYSTRACE(format, ...) \
397 TRACE("%m - " format, ##__VA_ARGS__)
398 #else
399 #define SYSTRACE(format, ...) \
400 do { \
401 lxc_log_strerror_r; \
402 TRACE("%s - " format, ptr, ##__VA_ARGS__); \
403 } while (0)
404 #endif
405
406 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
407 #define SYSDEBUG(format, ...) \
408 DEBUG("%m - " format, ##__VA_ARGS__)
409 #else
410 #define SYSDEBUG(format, ...) \
411 do { \
412 lxc_log_strerror_r; \
413 DEBUG("%s - " format, ptr, ##__VA_ARGS__); \
414 } while (0)
415 #endif
416
417
418 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
419 #define SYSINFO(format, ...) \
420 INFO("%m - " format, ##__VA_ARGS__)
421 #else
422 #define SYSINFO(format, ...) \
423 do { \
424 lxc_log_strerror_r; \
425 INFO("%s - " format, ptr, ##__VA_ARGS__); \
426 } while (0)
427 #endif
428
429 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
430 #define SYSNOTICE(format, ...) \
431 NOTICE("%m - " format, ##__VA_ARGS__)
432 #else
433 #define SYSNOTICE(format, ...) \
434 do { \
435 lxc_log_strerror_r; \
436 NOTICE("%s - " format, ptr, ##__VA_ARGS__); \
437 } while (0)
438 #endif
439
440 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
441 #define SYSWARN(format, ...) \
442 WARN("%m - " format, ##__VA_ARGS__)
443 #else
444 #define SYSWARN(format, ...) \
445 do { \
446 lxc_log_strerror_r; \
447 WARN("%s - " format, ptr, ##__VA_ARGS__); \
448 } while (0)
449 #endif
450
451 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
452 #define SYSERROR(format, ...) \
453 ERROR("%m - " format, ##__VA_ARGS__)
454 #else
455 #define SYSERROR(format, ...) \
456 do { \
457 lxc_log_strerror_r; \
458 ERROR("%s - " format, ptr, ##__VA_ARGS__); \
459 } while (0)
460 #endif
461
462 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
463 #define CMD_SYSERROR(format, ...) \
464 fprintf(stderr, "%s: %d: %s - %m - " format "\n", __FILE__, __LINE__, \
465 __func__, ##__VA_ARGS__);
466 #else
467 #define CMD_SYSERROR(format, ...) \
468 do { \
469 lxc_log_strerror_r; \
470 fprintf(stderr, "%s: %d: %s - %s - " format "\n", __FILE__, \
471 __LINE__, __func__, ptr, ##__VA_ARGS__); \
472 } while (0)
473 #endif
474
475 #if HAVE_M_FORMAT && !ENABLE_COVERITY_BUILD
476 #define CMD_SYSINFO(format, ...) \
477 printf("%s: %d: %s - %m - " format "\n", __FILE__, __LINE__, __func__, \
478 ##__VA_ARGS__);
479 #else
480 #define CMD_SYSINFO(format, ...) \
481 do { \
482 lxc_log_strerror_r; \
483 printf("%s: %d: %s - %s - " format "\n", __FILE__, __LINE__, \
484 __func__, ptr, ##__VA_ARGS__); \
485 } while (0)
486 #endif
487
488 #define log_error_errno(__ret__, __errno__, format, ...) \
489 ({ \
490 typeof(__ret__) __internal_ret__ = (__ret__); \
491 errno = (__errno__); \
492 SYSERROR(format, ##__VA_ARGS__); \
493 __internal_ret__; \
494 })
495
496 #define log_error(__ret__, format, ...) \
497 ({ \
498 typeof(__ret__) __internal_ret__ = (__ret__); \
499 ERROR(format, ##__VA_ARGS__); \
500 __internal_ret__; \
501 })
502
503 #define log_trace_errno(__ret__, __errno__, format, ...) \
504 ({ \
505 typeof(__ret__) __internal_ret__ = (__ret__); \
506 errno = __errno__; \
507 SYSTRACE(format, ##__VA_ARGS__); \
508 __internal_ret__; \
509 })
510
511 #define log_trace(__ret__, format, ...) \
512 ({ \
513 typeof(__ret__) __internal_ret__ = (__ret__); \
514 TRACE(format, ##__VA_ARGS__); \
515 __internal_ret__; \
516 })
517
518 #define log_warn_errno(__ret__, __errno__, format, ...) \
519 ({ \
520 typeof(__ret__) __internal_ret__ = (__ret__); \
521 errno = __errno__; \
522 SYSWARN(format, ##__VA_ARGS__); \
523 __internal_ret__; \
524 })
525
526 #define log_warn(__ret__, format, ...) \
527 ({ \
528 typeof(__ret__) __internal_ret__ = (__ret__); \
529 WARN(format, ##__VA_ARGS__); \
530 __internal_ret__; \
531 })
532
533 #define log_debug_errno(__ret__, __errno__, format, ...) \
534 ({ \
535 typeof(__ret__) __internal_ret__ = (__ret__); \
536 errno = __errno__; \
537 SYSDEBUG(format, ##__VA_ARGS__); \
538 __internal_ret__; \
539 })
540
541 #define log_debug(__ret__, format, ...) \
542 ({ \
543 typeof(__ret__) __internal_ret__ = (__ret__); \
544 DEBUG(format, ##__VA_ARGS__); \
545 __internal_ret__; \
546 })
547
548 #define log_info_errno(__ret__, __errno__, format, ...) \
549 ({ \
550 typeof(__ret__) __internal_ret__ = (__ret__); \
551 errno = __errno__; \
552 SYSINFO(format, ##__VA_ARGS__); \
553 __internal_ret__; \
554 })
555
556 #define log_info(__ret__, format, ...) \
557 ({ \
558 typeof(__ret__) __internal_ret__ = (__ret__); \
559 INFO(format, ##__VA_ARGS__); \
560 __internal_ret__; \
561 })
562
563 extern int lxc_log_fd;
564
565 extern int lxc_log_syslog(int facility);
566 extern void lxc_log_enable_syslog(void);
567 extern int lxc_log_set_level(int *dest, int level);
568 extern int lxc_log_get_level(void);
569 extern bool lxc_log_has_valid_level(void);
570 extern int lxc_log_set_file(int *fd, const char *fname);
571 extern const char *lxc_log_get_file(void);
572 extern void lxc_log_set_prefix(const char *prefix);
573 extern const char *lxc_log_get_prefix(void);
574 extern void lxc_log_options_no_override(void);
575 #endif