]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/log.c
storage/dir: cleanup mount code
[mirror_lxc.git] / src / lxc / log.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <inttypes.h>
10 #include <limits.h>
11 #include <pthread.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <syslog.h>
19 #include <unistd.h>
20
21 #include "caps.h"
22 #include "config.h"
23 #include "file_utils.h"
24 #include "log.h"
25 #include "lxccontainer.h"
26 #include "memory_utils.h"
27 #include "utils.h"
28
29 #ifndef HAVE_STRLCPY
30 #include "include/strlcpy.h"
31 #endif
32
33 #if HAVE_DLOG
34 #include <dlog.h>
35
36 #undef LOG_TAG
37 #define LOG_TAG "LXC"
38 #endif
39
40 /* We're logging in seconds and nanoseconds. Assuming that the underlying
41 * datatype is currently at maximum a 64bit integer, we have a date string that
42 * is of maximum length (2^64 - 1) * 2 = (21 + 21) = 42.
43 */
44 #define LXC_LOG_TIME_SIZE ((INTTYPE_TO_STRLEN(uint64_t)) * 2)
45
46 int lxc_log_fd = -EBADF;
47 static bool wants_syslog = false;
48 static int lxc_quiet_specified;
49 bool lxc_log_use_global_fd = false;
50 static int lxc_loglevel_specified;
51
52 static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
53 static char *log_fname = NULL;
54 static char *log_vmname = NULL;
55
56 lxc_log_define(log, lxc);
57
58 static int lxc_log_priority_to_syslog(int priority)
59 {
60 switch (priority) {
61 case LXC_LOG_LEVEL_FATAL:
62 return LOG_EMERG;
63 case LXC_LOG_LEVEL_ALERT:
64 return LOG_ALERT;
65 case LXC_LOG_LEVEL_CRIT:
66 return LOG_CRIT;
67 case LXC_LOG_LEVEL_ERROR:
68 return LOG_ERR;
69 case LXC_LOG_LEVEL_WARN:
70 return LOG_WARNING;
71 case LXC_LOG_LEVEL_NOTICE:
72 case LXC_LOG_LEVEL_NOTSET:
73 return LOG_NOTICE;
74 case LXC_LOG_LEVEL_INFO:
75 return LOG_INFO;
76 case LXC_LOG_LEVEL_TRACE:
77 case LXC_LOG_LEVEL_DEBUG:
78 return LOG_DEBUG;
79 }
80
81 /* Not reached */
82 return LOG_NOTICE;
83 }
84
85 static const char *lxc_log_get_container_name(void)
86 {
87 #ifndef NO_LXC_CONF
88 if (current_config && !log_vmname)
89 return current_config->name;
90 #endif
91
92 return log_vmname;
93 }
94
95 int lxc_log_get_fd(void)
96 {
97 int fd_log = -EBADF;
98
99 #ifndef NO_LXC_CONF
100 if (current_config && !lxc_log_use_global_fd)
101 fd_log = current_config->logfd;
102 #endif
103 if (fd_log < 0)
104 fd_log = lxc_log_fd;
105
106 return fd_log;
107 }
108
109 static char *lxc_log_get_va_msg(struct lxc_log_event *event)
110 {
111 __do_free char *msg = NULL;
112 int rc, len;
113 va_list args;
114
115 if (!event)
116 return ret_set_errno(NULL, EINVAL);
117
118 va_copy(args, *event->vap);
119 #pragma GCC diagnostic push
120 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
121 len = vsnprintf(NULL, 0, event->fmt, args) + 1;
122 #pragma GCC diagnostic pop
123 va_end(args);
124
125 msg = malloc(len * sizeof(char));
126 if (!msg)
127 return ret_set_errno(NULL, ENOMEM);
128
129 #pragma GCC diagnostic push
130 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
131 rc = vsnprintf(msg, len, event->fmt, *event->vap);
132 #pragma GCC diagnostic pop
133 if (rc < 0 || rc >= len)
134 return ret_set_errno(NULL, EIO);
135
136 return move_ptr(msg);
137 }
138
139 static int log_append_syslog(const struct lxc_log_appender *appender,
140 struct lxc_log_event *event)
141 {
142 __do_free char *msg = NULL;
143 const char *log_container_name;
144
145 if (!wants_syslog)
146 return 0;
147
148 log_container_name = lxc_log_get_container_name();
149
150 msg = lxc_log_get_va_msg(event);
151 if (!msg)
152 return 0;
153
154 syslog(lxc_log_priority_to_syslog(event->priority),
155 "%s%s %s - %s:%s:%d - %s" ,
156 log_container_name ? log_container_name : "",
157 log_container_name ? ":" : "",
158 event->category,
159 event->locinfo->file, event->locinfo->func,
160 event->locinfo->line,
161 msg);
162
163 return 0;
164 }
165
166 static int log_append_stderr(const struct lxc_log_appender *appender,
167 struct lxc_log_event *event)
168 {
169 const char *log_container_name;
170
171 if (event->priority < LXC_LOG_LEVEL_ERROR)
172 return 0;
173
174 log_container_name = lxc_log_get_container_name();
175
176 fprintf(stderr, "%s: %s%s", log_prefix,
177 log_container_name ? log_container_name : "",
178 log_container_name ? ": " : "");
179 fprintf(stderr, "%s: %s: %d ", event->locinfo->file,
180 event->locinfo->func, event->locinfo->line);
181 #pragma GCC diagnostic push
182 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
183 vfprintf(stderr, event->fmt, *event->vap);
184 #pragma GCC diagnostic pop
185 fprintf(stderr, "\n");
186
187 return 0;
188 }
189
190 static int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time)
191 {
192 int64_t epoch_to_days, z, era, doe, yoe, year, doy, mp, day, month,
193 d_in_s, hours, h_in_s, minutes, seconds;
194 char nanosec[INTTYPE_TO_STRLEN(int64_t)];
195 int ret;
196
197 /*
198 * See https://howardhinnant.github.io/date_algorithms.html for an
199 * explanation of the algorithm used here.
200 */
201
202 /* Convert Epoch in seconds to number of days. */
203 epoch_to_days = time->tv_sec / 86400;
204
205 /* Shift the Epoch from 1970-01-01 to 0000-03-01. */
206 z = epoch_to_days + 719468;
207
208 /*
209 * Compute the era from the serial date by simply dividing by the number
210 * of days in an era (146097).
211 */
212 era = (z >= 0 ? z : z - 146096) / 146097;
213
214 /*
215 * The day-of-era (doe) can then be found by subtracting the era number
216 * times the number of days per era, from the serial date.
217 */
218 doe = (z - era * 146097);
219
220 /*
221 * From the day-of-era (doe), the year-of-era (yoe, range [0, 399]) can
222 * be computed.
223 */
224 yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
225
226 /* Given year-of-era, and era, one can now compute the year. */
227 year = yoe + era * 400;
228
229 /*
230 * Also the day-of-year, again with the year beginning on Mar. 1, can be
231 * computed from the day-of-era and year-of-era.
232 */
233 doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
234
235 /* Given day-of-year, find the month number. */
236 mp = (5 * doy + 2) / 153;
237
238 /*
239 * From day-of-year and month-of-year we can now easily compute
240 * day-of-month.
241 */
242 day = doy - (153 * mp + 2) / 5 + 1;
243
244 /*
245 * Transform the month number from the [0, 11] / [Mar, Feb] system to
246 * the civil system: [1, 12] to find the correct month.
247 */
248 month = mp + (mp < 10 ? 3 : -9);
249
250 /*
251 * The algorithm assumes that a year begins on 1 March, so add 1 before
252 * that.
253 */
254 if (month < 3)
255 year++;
256
257 /* Transform days in the epoch to seconds. */
258 d_in_s = epoch_to_days * 86400;
259
260 /*
261 * To find the current hour simply substract the Epoch_to_days from the
262 * total Epoch and divide by the number of seconds in an hour.
263 */
264 hours = (time->tv_sec - d_in_s) / 3600;
265
266 /* Transform hours to seconds. */
267 h_in_s = hours * 3600;
268
269 /*
270 * Calculate minutes by subtracting the seconds for all days in the
271 * epoch and for all hours in the epoch and divide by the number of
272 * minutes in an hour.
273 */
274 minutes = (time->tv_sec - d_in_s - h_in_s) / 60;
275
276 /*
277 * Calculate the seconds by subtracting the seconds for all days in the
278 * epoch, hours in the epoch and minutes in the epoch.
279 */
280 seconds = (time->tv_sec - d_in_s - h_in_s - (minutes * 60));
281
282 /* Make string from nanoseconds. */
283 ret = strnprintf(nanosec, sizeof(nanosec), "%"PRId64, (int64_t)time->tv_nsec);
284 if (ret < 0)
285 return ret_errno(EIO);
286
287 /*
288 * Create final timestamp for the log and shorten nanoseconds to 3
289 * digit precision.
290 */
291 ret = strnprintf(buf, bufsize,
292 "%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64
293 "%02" PRId64 "%02" PRId64 ".%.3s",
294 year, month, day, hours, minutes, seconds, nanosec);
295 if (ret < 0)
296 return ret_errno(EIO);
297
298 return 0;
299 }
300
301 /*
302 * This function needs to make extra sure that it is thread-safe. We had some
303 * problems with that before. This especially involves time-conversion
304 * functions. I don't want to find any localtime() or gmtime() functions or
305 * relatives in here. Not even localtime_r() or gmtime_r() or relatives. They
306 * all fiddle with global variables and locking in various libcs. They cause
307 * deadlocks when liblxc is used multi-threaded and no matter how smart you
308 * think you are, you __will__ cause trouble using them.
309 * (As a short example how this can cause trouble: LXD uses forkstart to fork
310 * off a new process that runs the container. At the same time the go runtime
311 * LXD relies on does its own multi-threading thing which we can't control. The
312 * fork()ing + threading then seems to mess with the locking states in these
313 * time functions causing deadlocks.)
314 * The current solution is to be good old unix people and use the Epoch as our
315 * reference point and simply use the seconds and nanoseconds that have past
316 * since then. This relies on clock_gettime() which is explicitly marked MT-Safe
317 * with no restrictions! This way, anyone who is really strongly invested in
318 * getting the actual time the log entry was created, can just convert it for
319 * themselves. Our logging is mostly done for debugging purposes so don't try
320 * to make it pretty. Pretty might cost you thread-safety.
321 */
322 static int log_append_logfile(const struct lxc_log_appender *appender,
323 struct lxc_log_event *event)
324 {
325 int fd_to_use = -EBADF;
326 char buffer[LXC_LOG_BUFFER_SIZE];
327 char date_time[LXC_LOG_TIME_SIZE];
328 int n;
329 ssize_t ret;
330 const char *log_container_name;
331
332 #ifndef NO_LXC_CONF
333 if (current_config && !lxc_log_use_global_fd)
334 fd_to_use = current_config->logfd;
335 #endif
336
337 log_container_name = lxc_log_get_container_name();
338
339 if (fd_to_use < 0)
340 fd_to_use = lxc_log_fd;
341
342 if (fd_to_use < 0)
343 return 0;
344
345 ret = lxc_unix_epoch_to_utc(date_time, LXC_LOG_TIME_SIZE, &event->timestamp);
346 if (ret)
347 return ret;
348
349 /*
350 * We allow truncation here which is why we use snprintf() directly
351 * instead of strnprintf().
352 */
353 n = snprintf(buffer, sizeof(buffer),
354 "%s%s%s %s %-8s %s - %s:%s:%d - ",
355 log_prefix,
356 log_container_name ? " " : "",
357 log_container_name ? log_container_name : "",
358 date_time,
359 lxc_log_priority_to_string(event->priority),
360 event->category,
361 event->locinfo->file, event->locinfo->func,
362 event->locinfo->line);
363 if (n < 0)
364 return ret_errno(EIO);
365
366 if ((size_t)n < STRARRAYLEN(buffer)) {
367 #pragma GCC diagnostic push
368 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
369 ret = vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt, *event->vap);
370 #pragma GCC diagnostic pop
371 if (ret < 0)
372 return 0;
373
374 n += ret;
375 }
376
377 if ((size_t)n >= sizeof(buffer))
378 n = STRARRAYLEN(buffer);
379
380 buffer[n] = '\n';
381
382 return lxc_write_nointr(fd_to_use, buffer, n + 1);
383 }
384
385 #if HAVE_DLOG
386 static int log_append_dlog(const struct lxc_log_appender *appender,
387 struct lxc_log_event *event)
388 {
389 __do_free char *msg = NULL;
390 const char *log_container_name;
391
392 log_container_name = lxc_log_get_container_name();
393 msg = lxc_log_get_va_msg(event);
394
395 switch (event->priority) {
396 case LXC_LOG_LEVEL_TRACE:
397 case LXC_LOG_LEVEL_DEBUG:
398 print_log(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > [%s] %s",
399 event->locinfo->file, event->locinfo->func, event->locinfo->line,
400 log_container_name ? log_container_name : "-",
401 msg ? msg : "-");
402 break;
403 case LXC_LOG_LEVEL_INFO:
404 print_log(DLOG_INFO, LOG_TAG, "%s: %s(%d) > [%s] %s",
405 event->locinfo->file, event->locinfo->func, event->locinfo->line,
406 log_container_name ? log_container_name : "-",
407 msg ? msg : "-");
408 break;
409 case LXC_LOG_LEVEL_NOTICE:
410 case LXC_LOG_LEVEL_WARN:
411 print_log(DLOG_WARN, LOG_TAG, "%s: %s(%d) > [%s] %s",
412 event->locinfo->file, event->locinfo->func, event->locinfo->line,
413 log_container_name ? log_container_name : "-",
414 msg ? msg : "-");
415 break;
416 case LXC_LOG_LEVEL_ERROR:
417 print_log(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > [%s] %s",
418 event->locinfo->file, event->locinfo->func, event->locinfo->line,
419 log_container_name ? log_container_name : "-",
420 msg ? msg : "-");
421 break;
422 case LXC_LOG_LEVEL_CRIT:
423 case LXC_LOG_LEVEL_ALERT:
424 case LXC_LOG_LEVEL_FATAL:
425 print_log(DLOG_FATAL, LOG_TAG, "%s: %s(%d) > [%s] %s",
426 event->locinfo->file, event->locinfo->func, event->locinfo->line,
427 log_container_name ? log_container_name : "-",
428 msg ? msg : "-");
429 break;
430 default:
431 break;
432 }
433
434 return 0;
435 }
436 #endif
437
438 static struct lxc_log_appender log_appender_syslog = {
439 .name = "syslog",
440 .append = log_append_syslog,
441 .next = NULL,
442 };
443
444 static struct lxc_log_appender log_appender_stderr = {
445 .name = "stderr",
446 .append = log_append_stderr,
447 .next = NULL,
448 };
449
450 static struct lxc_log_appender log_appender_logfile = {
451 .name = "logfile",
452 .append = log_append_logfile,
453 .next = NULL,
454 };
455
456 #if HAVE_DLOG
457 static struct lxc_log_appender log_appender_dlog = {
458 .name = "dlog",
459 .append = log_append_dlog,
460 .next = NULL,
461 };
462 #endif
463
464 static struct lxc_log_category log_root = {
465 .name = "root",
466 .priority = LXC_LOG_LEVEL_ERROR,
467 .appender = NULL,
468 .parent = NULL,
469 };
470
471 #if HAVE_DLOG
472 struct lxc_log_category lxc_log_category_lxc = {
473 .name = "lxc",
474 .priority = LXC_LOG_LEVEL_TRACE,
475 .appender = &log_appender_dlog,
476 .parent = &log_root
477 };
478 #else
479 struct lxc_log_category lxc_log_category_lxc = {
480 .name = "lxc",
481 .priority = LXC_LOG_LEVEL_ERROR,
482 .appender = &log_appender_logfile,
483 .parent = &log_root
484 };
485 #endif
486
487 static int build_dir(const char *name)
488 {
489 __do_free char *n = NULL;
490 char *e, *p;
491
492 if (is_empty_string(name))
493 return ret_errno(EINVAL);
494
495 /* Make copy of the string since we'll be modifying it. */
496 n = strdup(name);
497 if (!n)
498 return ret_errno(ENOMEM);
499
500 e = &n[strlen(n)];
501 for (p = n + 1; p < e; p++) {
502 int ret;
503
504 if (*p != '/')
505 continue;
506 *p = '\0';
507
508 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
509 ret = lxc_unpriv(mkdir(n, 0755));
510 #else
511 ret = errno = EEXIST;
512 #endif /*!FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
513 *p = '/';
514 if (ret && errno != EEXIST)
515 return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", n);
516 }
517
518 return 0;
519 }
520
521 static int log_open(const char *name)
522 {
523 int newfd = -EBADF;
524 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
525 __do_close int fd = -EBADF;
526
527 fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0660));
528 if (fd < 0)
529 return log_error_errno(-errno, errno, "Failed to open log file \"%s\"", name);
530
531 if (fd > 2)
532 return move_fd(fd);
533
534 newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDERR_FILENO);
535 if (newfd < 0)
536 return log_error_errno(-errno, errno, "Failed to dup log fd %d", fd);
537 #endif /* !FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
538 return newfd;
539 }
540
541 /*
542 * Build the path to the log file
543 * @name : the name of the container
544 * @lxcpath : the lxcpath to use as a basename or NULL to use LOGPATH
545 * Returns malloced path on success, or NULL on failure
546 */
547 static char *build_log_path(const char *name, const char *lxcpath)
548 {
549 __do_free char *p = NULL;
550 int ret;
551 size_t len;
552 bool use_dir;
553
554 if (!name)
555 return ret_set_errno(NULL, EINVAL);
556
557 #if USE_CONFIGPATH_LOGS
558 use_dir = true;
559 #else
560 use_dir = false;
561 #endif
562
563 /*
564 * If USE_CONFIGPATH_LOGS is true or lxcpath is given, the resulting
565 * path will be:
566 * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0'
567 *
568 * If USE_CONFIGPATH_LOGS is false the resulting path will be:
569 * '$logpath' + '/' + '$name' + '.log' + '\0'
570 */
571 len = strlen(name) + 6; /* 6 == '/' + '.log' + '\0' */
572 if (lxcpath)
573 use_dir = true;
574 else
575 lxcpath = LOGPATH;
576
577 if (use_dir)
578 len += strlen(lxcpath) + 1 + strlen(name) + 1; /* add "/$container_name/" */
579 else
580 len += strlen(lxcpath) + 1;
581
582 p = malloc(len);
583 if (!p)
584 return ret_set_errno(NULL, ENOMEM);
585
586 if (use_dir)
587 ret = strnprintf(p, len, "%s/%s/%s.log", lxcpath, name, name);
588 else
589 ret = strnprintf(p, len, "%s/%s.log", lxcpath, name);
590 if (ret < 0)
591 return ret_set_errno(NULL, EIO);
592
593 return move_ptr(p);
594 }
595
596 /*
597 * This can be called:
598 * 1. when a program calls lxc_log_init with no logfile parameter (in which
599 * case the default is used). In this case lxc.loge can override this.
600 * 2. when a program calls lxc_log_init with a logfile parameter. In this
601 * case we don't want lxc.log to override this.
602 * 3. When a lxc.log entry is found in config file.
603 */
604 static int __lxc_log_set_file(const char *fname, int create_dirs)
605 {
606 /* we are overriding the default. */
607 if (lxc_log_fd >= 0)
608 lxc_log_close();
609
610 if (is_empty_string(fname))
611 return ret_errno(EINVAL);
612
613 if (strlen(fname) == 0) {
614 log_fname = NULL;
615 return ret_errno(EINVAL);
616 }
617
618 #if USE_CONFIGPATH_LOGS
619 /* We don't build_dir for the default if the default is i.e.
620 * /var/lib/lxc/$container/$container.log.
621 */
622 if (create_dirs)
623 #endif
624 if (build_dir(fname))
625 return log_error_errno(-errno, errno, "Failed to create dir for log file \"%s\"", fname);
626
627 lxc_log_fd = log_open(fname);
628 if (lxc_log_fd < 0)
629 return lxc_log_fd;
630
631 log_fname = strdup(fname);
632 return 0;
633 }
634
635 static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_dirs)
636 {
637 __do_free char *logfile = NULL;
638
639 logfile = build_log_path(name, lxcpath);
640 if (!logfile)
641 return log_error_errno(-errno, errno, "Could not build log path");
642
643 return __lxc_log_set_file(logfile, create_dirs);
644 }
645
646 /*
647 * lxc_log_init:
648 * Called from lxc front-end programs (like lxc-create, lxc-start) to
649 * initialize the log defaults.
650 */
651 int lxc_log_init(struct lxc_log *log)
652 {
653 int ret;
654 int lxc_priority = LXC_LOG_LEVEL_ERROR;
655
656 if (!log)
657 return ret_errno(EINVAL);
658
659 if (lxc_log_fd >= 0)
660 return log_warn_errno(0, EOPNOTSUPP, "Log already initialized");
661
662 if (log->level)
663 lxc_priority = lxc_log_priority_to_int(log->level);
664
665 if (!lxc_loglevel_specified) {
666 lxc_log_category_lxc.priority = lxc_priority;
667 lxc_loglevel_specified = 1;
668 }
669
670 if (!lxc_quiet_specified)
671 if (!log->quiet)
672 lxc_log_category_lxc.appender->next = &log_appender_stderr;
673
674 if (log->prefix)
675 lxc_log_set_prefix(log->prefix);
676
677 if (log->name)
678 log_vmname = strdup(log->name);
679
680 if (log->file) {
681 if (strequal(log->file, "none"))
682 return 0;
683
684 ret = __lxc_log_set_file(log->file, 1);
685 if (ret < 0)
686 return log_error_errno(-1, errno, "Failed to enable logfile");
687
688 lxc_log_use_global_fd = true;
689 } else {
690 /* if no name was specified, there nothing to do */
691 if (!log->name)
692 return 0;
693
694 ret = -1;
695
696 if (!log->lxcpath)
697 log->lxcpath = LOGPATH;
698
699 /* try LOGPATH if lxcpath is the default for the privileged containers */
700 if (!geteuid() && strequal(LXCPATH, log->lxcpath))
701 ret = _lxc_log_set_file(log->name, NULL, 0);
702
703 /* try in lxcpath */
704 if (ret < 0)
705 ret = _lxc_log_set_file(log->name, log->lxcpath, 1);
706
707 /* try LOGPATH in case its writable by the caller */
708 if (ret < 0)
709 ret = _lxc_log_set_file(log->name, NULL, 0);
710 }
711
712 /*
713 * If !file, that is, if the user did not request this logpath, then
714 * ignore failures and continue logging to console
715 */
716 if (!log->file && ret != 0) {
717 INFO("Ignoring failure to open default logfile");
718 ret = 0;
719 }
720
721 if (lxc_log_fd >= 0) {
722 lxc_log_category_lxc.appender = &log_appender_logfile;
723 lxc_log_category_lxc.appender->next = &log_appender_stderr;
724 }
725
726 return ret;
727 }
728
729 void lxc_log_close(void)
730 {
731 closelog();
732
733 free_disarm(log_vmname);
734
735 close_prot_errno_disarm(lxc_log_fd);
736
737 free_disarm(log_fname);
738 }
739
740 int lxc_log_syslog(int facility)
741 {
742 struct lxc_log_appender *appender;
743
744 openlog(log_prefix, LOG_PID, facility);
745 if (!lxc_log_category_lxc.appender) {
746 lxc_log_category_lxc.appender = &log_appender_syslog;
747 return 0;
748 }
749
750 appender = lxc_log_category_lxc.appender;
751 /* Check if syslog was already added, to avoid creating a loop */
752 while (appender) {
753 /* not an error: openlog re-opened the connection */
754 if (appender == &log_appender_syslog)
755 return 0;
756 appender = appender->next;
757 }
758
759 appender = lxc_log_category_lxc.appender;
760 while (appender->next != NULL)
761 appender = appender->next;
762 appender->next = &log_appender_syslog;
763
764 return 0;
765 }
766
767 void lxc_log_syslog_enable(void)
768 {
769 wants_syslog = true;
770 }
771
772 void lxc_log_syslog_disable(void)
773 {
774 wants_syslog = false;
775 }
776
777 /*
778 * This is called when we read a lxc.log.level entry in a lxc.conf file. This
779 * happens after processing command line arguments, which override the .conf
780 * settings. So only set the level if previously unset.
781 */
782 int lxc_log_set_level(int *dest, int level)
783 {
784 if (level < 0 || level >= LXC_LOG_LEVEL_NOTSET)
785 return log_error_errno(-EINVAL, EINVAL, "Invalid log priority %d", level);
786
787 *dest = level;
788 return 0;
789 }
790
791 int lxc_log_get_level(void)
792 {
793 int level = LXC_LOG_LEVEL_NOTSET;
794
795 #ifndef NO_LXC_CONF
796 if (current_config)
797 level = current_config->loglevel;
798 #endif
799 if (level == LXC_LOG_LEVEL_NOTSET)
800 level = lxc_log_category_lxc.priority;
801
802 return level;
803 }
804
805 bool lxc_log_has_valid_level(void)
806 {
807 int log_level;
808
809 log_level = lxc_log_get_level();
810 if (log_level < 0 || log_level >= LXC_LOG_LEVEL_NOTSET)
811 return ret_set_errno(false, EINVAL);
812
813 return true;
814 }
815
816 /*
817 * This is called when we read a lxc.logfile entry in a lxc.conf file. This
818 * happens after processing command line arguments, which override the .conf
819 * settings. So only set the file if previously unset.
820 */
821 int lxc_log_set_file(int *fd, const char *fname)
822 {
823 if (*fd >= 0)
824 close_prot_errno_disarm(*fd);
825
826 if (is_empty_string(fname))
827 return ret_errno(EINVAL);
828
829 if (build_dir(fname))
830 return -errno;
831
832 *fd = log_open(fname);
833 if (*fd < 0)
834 return -errno;
835 return 0;
836 }
837
838 inline const char *lxc_log_get_file(void)
839 {
840 return log_fname;
841 }
842
843 inline void lxc_log_set_prefix(const char *prefix)
844 {
845 /* We don't care if the prefix is truncated. */
846 (void)strlcpy(log_prefix, prefix, sizeof(log_prefix));
847 }
848
849 inline const char *lxc_log_get_prefix(void)
850 {
851 return log_prefix;
852 }
853
854 inline void lxc_log_options_no_override(void)
855 {
856 lxc_quiet_specified = 1;
857 lxc_loglevel_specified = 1;
858 }