]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/log.h
Merge pull request #3059 from brauner/2019-06-21/seccomp_notify
[mirror_lxc.git] / src / lxc / log.h
CommitLineData
e0b4037d
DL
1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
e0b4037d
DL
8 * Cedric Le Goater <legoater@free.fr>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
250b1eec 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e0b4037d 23 */
f1a4a029
ÇO
24#ifndef __LXC_LOG_H
25#define __LXC_LOG_H
0ad19a3f 26
76d0127f 27#include <errno.h>
cb8c5720
CLG
28#include <stdarg.h>
29#include <stdio.h>
30#include <sys/time.h>
31#include <string.h>
65441ac9 32#include <strings.h>
fabf7361 33#include <stdbool.h>
76d0127f 34#include <syslog.h>
c57dbb96 35#include <time.h>
cb8c5720 36
858377e4
SH
37#include "conf.h"
38
eabbb2f0
MN
39#ifndef O_CLOEXEC
40#define O_CLOEXEC 02000000
41#endif
42
43#ifndef F_DUPFD_CLOEXEC
44#define F_DUPFD_CLOEXEC 1030
45#endif
46
47#define LXC_LOG_PREFIX_SIZE 32
ed408e66 48#define LXC_LOG_BUFFER_SIZE 4096
eabbb2f0 49
13aad0ae
SG
50/* This attribute is required to silence clang warnings */
51#if defined(__GNUC__)
52#define ATTR_UNUSED __attribute__ ((unused))
53#else
54#define ATTR_UNUSED
55#endif
56
76d0127f 57/* predefined lxc log priorities. */
4a85ce2a 58enum lxc_loglevel {
4b73005c
CB
59 LXC_LOG_LEVEL_TRACE,
60 LXC_LOG_LEVEL_DEBUG,
61 LXC_LOG_LEVEL_INFO,
62 LXC_LOG_LEVEL_NOTICE,
63 LXC_LOG_LEVEL_WARN,
64 LXC_LOG_LEVEL_ERROR,
65 LXC_LOG_LEVEL_CRIT,
66 LXC_LOG_LEVEL_ALERT,
67 LXC_LOG_LEVEL_FATAL,
68 LXC_LOG_LEVEL_NOTSET,
cb8c5720
CLG
69};
70
71/* location information of the logging event */
72struct lxc_log_locinfo {
eba1ae76
CB
73 const char *file;
74 const char *func;
75 int line;
cb8c5720
CLG
76};
77
78#define LXC_LOG_LOCINFO_INIT \
79 { .file = __FILE__, .func = __func__, .line = __LINE__ }
80
81/* brief logging event object */
82struct lxc_log_event {
eba1ae76
CB
83 const char *category;
84 int priority;
85 struct timespec timestamp;
86 struct lxc_log_locinfo *locinfo;
87 const char *fmt;
88 va_list *vap;
cb8c5720
CLG
89};
90
91/* log appender object */
92struct lxc_log_appender {
eba1ae76 93 const char *name;
5fd8380b 94 int (*append)(const struct lxc_log_appender *, struct lxc_log_event *);
cb8c5720
CLG
95
96 /*
97 * appenders can be stacked
98 */
eba1ae76 99 struct lxc_log_appender *next;
cb8c5720
CLG
100};
101
102/* log category object */
103struct lxc_log_category {
eba1ae76
CB
104 const char *name;
105 int priority;
106 struct lxc_log_appender *appender;
107 const struct lxc_log_category *parent;
cb8c5720
CLG
108};
109
858377e4
SH
110#ifndef NO_LXC_CONF
111extern int lxc_log_use_global_fd;
112#endif
113
cb8c5720
CLG
114/*
115 * Returns true if the chained priority is equal to or higher than
116 * given priority.
117 */
eba1ae76
CB
118static inline int lxc_log_priority_is_enabled(const struct lxc_log_category *category,
119 int priority)
cb8c5720 120{
eba1ae76 121 while (category->priority == LXC_LOG_LEVEL_NOTSET && category->parent)
cb8c5720
CLG
122 category = category->parent;
123
858377e4
SH
124 int cmp_prio = category->priority;
125#ifndef NO_LXC_CONF
126 if (!lxc_log_use_global_fd && current_config &&
eba1ae76 127 current_config->loglevel != LXC_LOG_LEVEL_NOTSET)
858377e4
SH
128 cmp_prio = current_config->loglevel;
129#endif
130
131 return priority >= cmp_prio;
cb8c5720
CLG
132}
133
134/*
135 * converts a priority to a literal string
136 */
eba1ae76 137static inline const char *lxc_log_priority_to_string(int priority)
cb8c5720
CLG
138{
139 switch (priority) {
eba1ae76
CB
140 case LXC_LOG_LEVEL_TRACE:
141 return "TRACE";
142 case LXC_LOG_LEVEL_DEBUG:
143 return "DEBUG";
144 case LXC_LOG_LEVEL_INFO:
145 return "INFO";
146 case LXC_LOG_LEVEL_NOTICE:
147 return "NOTICE";
148 case LXC_LOG_LEVEL_WARN:
149 return "WARN";
150 case LXC_LOG_LEVEL_ERROR:
151 return "ERROR";
152 case LXC_LOG_LEVEL_CRIT:
153 return "CRIT";
154 case LXC_LOG_LEVEL_ALERT:
155 return "ALERT";
156 case LXC_LOG_LEVEL_FATAL:
157 return "FATAL";
cb8c5720 158 }
eba1ae76
CB
159
160 return "NOTSET";
cb8c5720 161}
76d0127f 162
eba1ae76 163static inline const char *lxc_syslog_priority_to_string(int priority)
76d0127f
CB
164{
165 switch (priority) {
eba1ae76
CB
166 case LOG_DAEMON:
167 return "daemon";
168 case LOG_LOCAL0:
169 return "local0";
170 case LOG_LOCAL1:
171 return "local1";
172 case LOG_LOCAL2:
173 return "local2";
174 case LOG_LOCAL3:
175 return "local3";
176 case LOG_LOCAL4:
177 return "local4";
178 case LOG_LOCAL5:
179 return "local5";
180 case LOG_LOCAL6:
181 return "local6";
182 case LOG_LOCAL7:
183 return "local7";
76d0127f 184 }
eba1ae76
CB
185
186 return "NOTSET";
76d0127f
CB
187}
188
cb8c5720
CLG
189/*
190 * converts a literal priority to an int
191 */
eba1ae76 192static inline int lxc_log_priority_to_int(const char *name)
cb8c5720 193{
eba1ae76
CB
194 if (strcasecmp("TRACE", name) == 0)
195 return LXC_LOG_LEVEL_TRACE;
196 if (strcasecmp("DEBUG", name) == 0)
197 return LXC_LOG_LEVEL_DEBUG;
198 if (strcasecmp("INFO", name) == 0)
199 return LXC_LOG_LEVEL_INFO;
200 if (strcasecmp("NOTICE", name) == 0)
201 return LXC_LOG_LEVEL_NOTICE;
202 if (strcasecmp("WARN", name) == 0)
203 return LXC_LOG_LEVEL_WARN;
204 if (strcasecmp("ERROR", name) == 0)
205 return LXC_LOG_LEVEL_ERROR;
206 if (strcasecmp("CRIT", name) == 0)
207 return LXC_LOG_LEVEL_CRIT;
208 if (strcasecmp("ALERT", name) == 0)
209 return LXC_LOG_LEVEL_ALERT;
210 if (strcasecmp("FATAL", name) == 0)
211 return LXC_LOG_LEVEL_FATAL;
4b73005c
CB
212
213 return LXC_LOG_LEVEL_NOTSET;
cb8c5720
CLG
214}
215
eba1ae76 216static inline int lxc_syslog_priority_to_int(const char *name)
76d0127f 217{
eba1ae76
CB
218 if (strcasecmp("daemon", name) == 0)
219 return LOG_DAEMON;
220 if (strcasecmp("local0", name) == 0)
221 return LOG_LOCAL0;
222 if (strcasecmp("local1", name) == 0)
223 return LOG_LOCAL1;
224 if (strcasecmp("local2", name) == 0)
225 return LOG_LOCAL2;
226 if (strcasecmp("local3", name) == 0)
227 return LOG_LOCAL3;
228 if (strcasecmp("local4", name) == 0)
229 return LOG_LOCAL4;
230 if (strcasecmp("local5", name) == 0)
231 return LOG_LOCAL5;
232 if (strcasecmp("local6", name) == 0)
233 return LOG_LOCAL6;
234 if (strcasecmp("local7", name) == 0)
235 return LOG_LOCAL7;
76d0127f
CB
236
237 return -EINVAL;
238}
239
eba1ae76
CB
240static inline void __lxc_log_append(const struct lxc_log_appender *appender,
241 struct lxc_log_event *event)
cb8c5720 242{
eba1ae76
CB
243 va_list va;
244 va_list *va_keep = event->vap;
5fd8380b 245
cb8c5720 246 while (appender) {
5fd8380b
MN
247 va_copy(va, *va_keep);
248 event->vap = &va;
cb8c5720
CLG
249 appender->append(appender, event);
250 appender = appender->next;
5fd8380b 251 va_end(va);
cb8c5720
CLG
252 }
253}
254
eba1ae76
CB
255static inline void __lxc_log(const struct lxc_log_category *category,
256 struct lxc_log_event *event)
cb8c5720
CLG
257{
258 while (category) {
259 __lxc_log_append(category->appender, event);
260 category = category->parent;
261 }
262}
263
264/*
e6a19d26 265 * Helper macro to define log functions.
cb8c5720 266 */
eba1ae76
CB
267#define lxc_log_priority_define(acategory, LEVEL) \
268 \
269ATTR_UNUSED __attribute__ ((format (printf, 2, 3))) \
270static inline void LXC_##LEVEL(struct lxc_log_locinfo *, const char *, ...); \
271 \
4b73005c 272ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo, \
eba1ae76
CB
273 const char* format, ...) \
274{ \
275 if (lxc_log_priority_is_enabled(acategory, LXC_LOG_LEVEL_##LEVEL)) { \
276 va_list va_ref; \
b7051eb7 277 int saved_errno; \
eba1ae76
CB
278 struct lxc_log_event evt = { \
279 .category = (acategory)->name, \
280 .priority = LXC_LOG_LEVEL_##LEVEL, \
281 .fmt = format, \
282 .locinfo = locinfo \
283 }; \
284 \
285 /* clock_gettime() is explicitly marked as MT-Safe \
286 * without restrictions. So let's use it for our \
287 * logging stamps. \
288 */ \
b7051eb7 289 saved_errno = errno; \
eba1ae76
CB
290 (void)clock_gettime(CLOCK_REALTIME, &evt.timestamp); \
291 \
292 va_start(va_ref, format); \
293 evt.vap = &va_ref; \
294 __lxc_log(acategory, &evt); \
295 va_end(va_ref); \
b7051eb7 296 errno = saved_errno; \
eba1ae76 297 } \
cb8c5720
CLG
298}
299
300/*
301 * Helper macro to define and use static categories.
302 */
303#define lxc_log_category_define(name, parent) \
304 extern struct lxc_log_category lxc_log_category_##parent; \
305 struct lxc_log_category lxc_log_category_##name = { \
306 #name, \
eba1ae76 307 LXC_LOG_LEVEL_NOTSET, \
cb8c5720
CLG
308 NULL, \
309 &lxc_log_category_##parent \
310 };
311
312#define lxc_log_define(name, parent) \
313 lxc_log_category_define(name, parent) \
314 \
315 lxc_log_priority_define(&lxc_log_category_##name, TRACE) \
316 lxc_log_priority_define(&lxc_log_category_##name, DEBUG) \
317 lxc_log_priority_define(&lxc_log_category_##name, INFO) \
318 lxc_log_priority_define(&lxc_log_category_##name, NOTICE) \
319 lxc_log_priority_define(&lxc_log_category_##name, WARN) \
320 lxc_log_priority_define(&lxc_log_category_##name, ERROR) \
321 lxc_log_priority_define(&lxc_log_category_##name, CRIT) \
322 lxc_log_priority_define(&lxc_log_category_##name, ALERT) \
323 lxc_log_priority_define(&lxc_log_category_##name, FATAL)
324
325#define lxc_log_category_priority(name) \
326 (lxc_log_priority_to_string(lxc_log_category_##name.priority))
327
9d465140 328/*
329 * Helper macro to define errno string.
330 */
607e3fca
CB
331#if HAVE_STRERROR_R
332 #ifndef HAVE_DECL_STRERROR_R
333 #ifdef STRERROR_R_CHAR_P
334 char *strerror_r(int errnum, char *buf, size_t buflen);
335 #else
336 int strerror_r(int errnum, char *buf, size_t buflen);
337 #endif
338 #endif
339
340 #ifdef STRERROR_R_CHAR_P
341 #define lxc_log_strerror_r \
52539fcc 342 char errno_buf[PATH_MAX / 2] = {"Failed to get errno string"}; \
607e3fca
CB
343 char *ptr = NULL; \
344 { \
a7547c5c 345 int __saved_errno = errno; \
607e3fca 346 ptr = strerror_r(errno, errno_buf, sizeof(errno_buf)); \
a7547c5c 347 errno = __saved_errno; \
607e3fca
CB
348 if (!ptr) \
349 ptr = errno_buf; \
350 }
351 #else
352 #define lxc_log_strerror_r \
52539fcc 353 char errno_buf[PATH_MAX / 2] = {"Failed to get errno string"}; \
607e3fca
CB
354 char *ptr = errno_buf; \
355 { \
a7547c5c 356 int __saved_errno = errno; \
607e3fca 357 (void)strerror_r(errno, errno_buf, sizeof(errno_buf)); \
a7547c5c 358 errno = __saved_errno; \
607e3fca
CB
359 }
360 #endif
d6457631
CB
361#elif ENFORCE_THREAD_SAFETY
362 #error ENFORCE_THREAD_SAFETY was set but cannot be guaranteed
9d465140 363#else
52539fcc
CB
364 #define lxc_log_strerror_r \
365 char *ptr = NULL; \
366 { \
367 ptr = strerror(errno); \
607e3fca 368 }
9d465140 369#endif
370
cb8c5720
CLG
371/*
372 * top categories
373 */
cb8c5720
CLG
374#define TRACE(format, ...) do { \
375 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
376 LXC_TRACE(&locinfo, format, ##__VA_ARGS__); \
377} while (0)
378
379#define DEBUG(format, ...) do { \
380 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
381 LXC_DEBUG(&locinfo, format, ##__VA_ARGS__); \
382} while (0)
383
384#define INFO(format, ...) do { \
385 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
386 LXC_INFO(&locinfo, format, ##__VA_ARGS__); \
387} while (0)
388
389#define NOTICE(format, ...) do { \
390 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
391 LXC_NOTICE(&locinfo, format, ##__VA_ARGS__); \
392} while (0)
393
394#define WARN(format, ...) do { \
395 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
396 LXC_WARN(&locinfo, format, ##__VA_ARGS__); \
397} while (0)
398
399#define ERROR(format, ...) do { \
400 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
401 LXC_ERROR(&locinfo, format, ##__VA_ARGS__); \
402} while (0)
403
404#define CRIT(format, ...) do { \
405 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
406 LXC_CRIT(&locinfo, format, ##__VA_ARGS__); \
407} while (0)
408
409#define ALERT(format, ...) do { \
410 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
411 LXC_ALERT(&locinfo, format, ##__VA_ARGS__); \
412} while (0)
413
414#define FATAL(format, ...) do { \
415 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
416 LXC_FATAL(&locinfo, format, ##__VA_ARGS__); \
417} while (0)
418
a1d652c2
RK
419#if HAVE_M_FORMAT
420#define SYSTRACE(format, ...) \
9a719a64 421 TRACE("%m - " format, ##__VA_ARGS__)
a1d652c2 422#else
9d465140 423#define SYSTRACE(format, ...) \
424 do { \
425 lxc_log_strerror_r; \
426 TRACE("%s - " format, ptr, ##__VA_ARGS__); \
427 } while (0)
a1d652c2 428#endif
9d465140 429
a1d652c2
RK
430#if HAVE_M_FORMAT
431#define SYSDEBUG(format, ...) \
432 DEBUG("%m - " format, ##__VA_ARGS__)
433#else
9d465140 434#define SYSDEBUG(format, ...) \
435 do { \
436 lxc_log_strerror_r; \
437 DEBUG("%s - " format, ptr, ##__VA_ARGS__); \
438 } while (0)
a1d652c2
RK
439#endif
440
9d465140 441
a1d652c2
RK
442#if HAVE_M_FORMAT
443#define SYSINFO(format, ...) \
444 INFO("%m - " format, ##__VA_ARGS__)
445#else
9d465140 446#define SYSINFO(format, ...) \
447 do { \
448 lxc_log_strerror_r; \
449 INFO("%s - " format, ptr, ##__VA_ARGS__); \
450 } while (0)
a1d652c2 451#endif
9d465140 452
a1d652c2
RK
453#if HAVE_M_FORMAT
454#define SYSNOTICE(format, ...) \
455 NOTICE("%m - " format, ##__VA_ARGS__)
456#else
9d465140 457#define SYSNOTICE(format, ...) \
458 do { \
459 lxc_log_strerror_r; \
460 NOTICE("%s - " format, ptr, ##__VA_ARGS__); \
461 } while (0)
a1d652c2 462#endif
9d465140 463
a1d652c2
RK
464#if HAVE_M_FORMAT
465#define SYSWARN(format, ...) \
466 WARN("%m - " format, ##__VA_ARGS__)
467#else
9d465140 468#define SYSWARN(format, ...) \
469 do { \
470 lxc_log_strerror_r; \
471 WARN("%s - " format, ptr, ##__VA_ARGS__); \
472 } while (0)
a1d652c2 473#endif
9d465140 474
a1d652c2
RK
475#if HAVE_M_FORMAT
476#define SYSERROR(format, ...) \
477 ERROR("%m - " format, ##__VA_ARGS__)
478#else
9d465140 479#define SYSERROR(format, ...) \
480 do { \
481 lxc_log_strerror_r; \
482 ERROR("%s - " format, ptr, ##__VA_ARGS__); \
483 } while (0)
a1d652c2 484#endif
cb8c5720 485
a1d652c2
RK
486#if HAVE_M_FORMAT
487#define CMD_SYSERROR(format, ...) \
488 fprintf(stderr, "%m - " format, ##__VA_ARGS__)
489#else
bb9623e7
CB
490#define CMD_SYSERROR(format, ...) \
491 do { \
492 lxc_log_strerror_r; \
493 fprintf(stderr, "%s - " format, ptr, ##__VA_ARGS__); \
494 } while (0)
a1d652c2 495#endif
bb9623e7 496
a1d652c2
RK
497#if HAVE_M_FORMAT
498#define CMD_SYSINFO(format, ...) \
499 printf("%m - " format, ##__VA_ARGS__)
500#else
20029ee3
CB
501#define CMD_SYSINFO(format, ...) \
502 do { \
503 lxc_log_strerror_r; \
504 printf("%s - " format, ptr, ##__VA_ARGS__); \
505 } while (0)
a1d652c2 506#endif
20029ee3 507
641c20a6
CLG
508extern int lxc_log_fd;
509
64c57ea1
BD
510extern int lxc_log_syslog(int facility);
511extern void lxc_log_enable_syslog(void);
858377e4 512extern int lxc_log_set_level(int *dest, int level);
ab1bf971 513extern int lxc_log_get_level(void);
fabf7361 514extern bool lxc_log_has_valid_level(void);
8273ba47 515extern int lxc_log_set_file(int *fd, const char *fname);
516extern const char *lxc_log_get_file(void);
517extern void lxc_log_set_prefix(const char *prefix);
ab1bf971 518extern const char *lxc_log_get_prefix(void);
246736be 519extern void lxc_log_options_no_override(void);
0ad19a3f 520#endif