]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/log.c
Merge pull request #1539 from brauner/2017-05-06/fix_abstract_unix_sockets
[mirror_lxc.git] / src / lxc / log.c
CommitLineData
e0b4037d
DL
1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Cedric Le Goater <legoater@free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e0b4037d 22 */
b4c42474
CB
23
24#define _GNU_SOURCE
65a9df89 25#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
65a9df89 26#include <stdint.h>
0ad19a3f 27#include <stdio.h>
28#include <errno.h>
65a9df89 29#include <inttypes.h>
cb8c5720
CLG
30#include <limits.h>
31#include <unistd.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <string.h>
858377e4 35#include <pthread.h>
02d25a9e 36#include <time.h>
cb8c5720 37
64c57ea1
BD
38#include <syslog.h>
39#include <stdio.h>
40
cb8c5720
CLG
41#include <fcntl.h>
42#include <stdlib.h>
43
28f602ff
DL
44#include "log.h"
45#include "caps.h"
ab1bf971 46#include "utils.h"
cb8c5720 47
c57dbb96
CB
48/* We're logging in seconds and nanoseconds. Assuming that the underlying
49 * datatype is currently at maximum a 64bit integer, we have a date string that
50 * is of maximum length (2^64 - 1) * 2 = (21 + 21) = 42.
51 */
eab15c1e 52#define LXC_LOG_TIME_SIZE ((LXC_NUMSTRLEN64)*2)
6a22e862 53
9f4f402a 54int lxc_log_fd = -1;
64c57ea1 55static int syslog_enable = 0;
858377e4
SH
56int lxc_quiet_specified;
57int lxc_log_use_global_fd;
58static int lxc_loglevel_specified;
59
6b9f3917 60static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
ab1bf971 61static char *log_fname = NULL;
64c57ea1 62static char *log_vmname = NULL;
cb8c5720
CLG
63
64lxc_log_define(lxc_log, lxc);
65
64c57ea1
BD
66static int lxc_log_priority_to_syslog(int priority)
67{
68 switch (priority) {
69 case LXC_LOG_PRIORITY_FATAL:
70 return LOG_EMERG;
71 case LXC_LOG_PRIORITY_ALERT:
72 return LOG_ALERT;
73 case LXC_LOG_PRIORITY_CRIT:
74 return LOG_CRIT;
75 case LXC_LOG_PRIORITY_ERROR:
76 return LOG_ERR;
77 case LXC_LOG_PRIORITY_WARN:
78 return LOG_WARNING;
79 case LXC_LOG_PRIORITY_NOTICE:
80 case LXC_LOG_PRIORITY_NOTSET:
81 return LOG_NOTICE;
82 case LXC_LOG_PRIORITY_INFO:
83 return LOG_INFO;
84 case LXC_LOG_PRIORITY_TRACE:
85 case LXC_LOG_PRIORITY_DEBUG:
86 return LOG_DEBUG;
87 }
88
89 /* Not reached */
90 return LOG_NOTICE;
91}
92
93/*---------------------------------------------------------------------------*/
94static int log_append_syslog(const struct lxc_log_appender *appender,
95 struct lxc_log_event *event)
96{
97 char *msg;
98 int rc, len;
99 va_list args;
100
101 if (!syslog_enable)
102 return 0;
103
104 va_copy(args, *event->vap);
105 len = vsnprintf(NULL, 0, event->fmt, args) + 1;
106 va_end(args);
107 msg = malloc(len * sizeof(char));
108 if (msg == NULL)
109 return 0;
110 rc = vsnprintf(msg, len, event->fmt, *event->vap);
111 if (rc == -1 || rc >= len) {
112 free(msg);
113 return 0;
114 }
115
116 syslog(lxc_log_priority_to_syslog(event->priority),
76d0127f 117 "%s%s %s - %s:%s:%d - %s" ,
64c57ea1 118 log_vmname ? log_vmname : "",
76d0127f 119 log_vmname ? ":" : "",
64c57ea1
BD
120 event->category,
121 event->locinfo->file, event->locinfo->func,
122 event->locinfo->line,
123 msg);
124 free(msg);
125 return 0;
126}
127
d737c074
MN
128/*---------------------------------------------------------------------------*/
129static int log_append_stderr(const struct lxc_log_appender *appender,
130 struct lxc_log_event *event)
131{
132 if (event->priority < LXC_LOG_PRIORITY_ERROR)
133 return 0;
134
c3ff6e24 135 fprintf(stderr, "%s: %s%s", log_prefix, log_vmname ? log_vmname : "", log_vmname ? ": " : "");
15bc516e 136 fprintf(stderr, "%s: %s: %d ", event->locinfo->file, event->locinfo->func, event->locinfo->line);
d737c074
MN
137 vfprintf(stderr, event->fmt, *event->vap);
138 fprintf(stderr, "\n");
139 return 0;
140}
141
cb8c5720 142/*---------------------------------------------------------------------------*/
65a9df89
CB
143int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time)
144{
d86c0d08
CB
145 int64_t epoch_to_days, z, era, doe, yoe, year, doy, mp, day, month,
146 d_in_s, hours, h_in_s, minutes, seconds;
eab15c1e 147 char nanosec[LXC_NUMSTRLEN64];
65a9df89
CB
148 int ret;
149
150 /* See https://howardhinnant.github.io/date_algorithms.html for an
151 * explanation of the algorithm used here.
152 */
d86c0d08
CB
153
154 /* Convert Epoch in seconds to number of days. */
155 epoch_to_days = time->tv_sec / 86400;
156
157 /* Shift the Epoch from 1970-01-01 to 0000-03-01. */
158 z = epoch_to_days + 719468;
159
160 /* compute the era from the serial date by simply dividing by the number
161 * of days in an era (146097).
162 */
65a9df89 163 era = (z >= 0 ? z : z - 146096) / 146097;
d86c0d08
CB
164
165 /* The day-of-era (doe) can then be found by subtracting the era number
166 * times the number of days per era, from the serial date.
167 */
65a9df89 168 doe = (z - era * 146097);
d86c0d08
CB
169
170 /* From the day-of-era (doe), the year-of-era (yoe, range [0, 399]) can
171 * be computed.
172 */
65a9df89 173 yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
d86c0d08
CB
174
175 /* Given year-of-era, and era, one can now compute the year. */
86698d38 176 year = yoe + era * 400;
d86c0d08
CB
177
178 /* Also the day-of-year, again with the year beginning on Mar. 1, can be
179 * computed from the day-of-era and year-of-era.
180 */
65a9df89 181 doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
d86c0d08
CB
182
183 /* Given day-of-year, find the month number. */
65a9df89 184 mp = (5 * doy + 2) / 153;
d86c0d08
CB
185
186 /* From day-of-year and month-of-year we can now easily compute
187 * day-of-month.
188 */
65a9df89 189 day = doy - (153 * mp + 2) / 5 + 1;
d86c0d08
CB
190
191 /* Transform the month number from the [0, 11] / [Mar, Feb] system to
192 * the civil system: [1, 12] to find the correct month.
193 */
65a9df89 194 month = mp + (mp < 10 ? 3 : -9);
d86c0d08 195
86698d38
CB
196 /* The algorithm assumes that a year begins on 1 March, so add 1 before
197 * that. */
198 if (month < 3)
199 year++;
200
d86c0d08
CB
201 /* Transform days in the epoch to seconds. */
202 d_in_s = epoch_to_days * 86400;
203
204 /* To find the current hour simply substract the Epoch_to_days from the
205 * total Epoch and divide by the number of seconds in an hour.
206 */
65a9df89 207 hours = (time->tv_sec - d_in_s) / 3600;
d86c0d08
CB
208
209 /* Transform hours to seconds. */
65a9df89 210 h_in_s = hours * 3600;
d86c0d08
CB
211
212 /* Calculate minutes by substracting the seconds for all days in the
213 * epoch and for all hours in the epoch and divide by the number of
214 * minutes in an hour.
215 */
65a9df89 216 minutes = (time->tv_sec - d_in_s - h_in_s) / 60;
d86c0d08
CB
217
218 /* Calculate the seconds by substracting the seconds for all days in the
219 * epoch, hours in the epoch and minutes in the epoch.
220 */
65a9df89
CB
221 seconds = (time->tv_sec - d_in_s - h_in_s - (minutes * 60));
222
d86c0d08 223 /* Make string from nanoseconds. */
eab15c1e
CB
224 ret = snprintf(nanosec, LXC_NUMSTRLEN64, "%ld", time->tv_nsec);
225 if (ret < 0 || ret >= LXC_NUMSTRLEN64)
65a9df89 226 return -1;
d86c0d08
CB
227
228 /* Create final timestamp for the log and shorten nanoseconds to 3
229 * digit precision.
230 */
9d7468fd
CB
231 ret = snprintf(buf, bufsize,
232 "%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64
233 "%02" PRId64 "%02" PRId64 ".%.3s",
65a9df89
CB
234 year, month, day, hours, minutes, seconds, nanosec);
235 if (ret < 0 || (size_t)ret >= bufsize)
236 return -1;
237
238 return 0;
239}
240
c57dbb96
CB
241/* This function needs to make extra sure that it is thread-safe. We had some
242 * problems with that before. This especially involves time-conversion
243 * functions. I don't want to find any localtime() or gmtime() functions or
244 * relatives in here. Not even localtime_r() or gmtime_r() or relatives. They
245 * all fiddle with global variables and locking in various libcs. They cause
246 * deadlocks when liblxc is used multi-threaded and no matter how smart you
247 * think you are, you __will__ cause trouble using them.
248 * (As a short example how this can cause trouble: LXD uses forkstart to fork
249 * off a new process that runs the container. At the same time the go runtime
250 * LXD relies on does its own multi-threading thing which we can't controll. The
251 * fork()ing + threading then seems to mess with the locking states in these
252 * time functions causing deadlocks.)
253 * The current solution is to be good old unix people and use the Epoch as our
254 * reference point and simply use the seconds and nanoseconds that have past
255 * since then. This relies on clock_gettime() which is explicitly marked MT-Safe
256 * with no restrictions! This way, anyone who is really strongly invested in
257 * getting the actual time the log entry was created, can just convert it for
258 * themselves. Our logging is mostly done for debugging purposes so don't try
259 * to make it pretty. Pretty might cost you thread-safety.
260 */
cb8c5720 261static int log_append_logfile(const struct lxc_log_appender *appender,
5fd8380b 262 struct lxc_log_event *event)
cb8c5720
CLG
263{
264 char buffer[LXC_LOG_BUFFER_SIZE];
e1378d35
CB
265 char date_time[LXC_LOG_TIME_SIZE];
266 int n;
858377e4 267 int fd_to_use = -1;
42e56013 268
858377e4
SH
269#ifndef NO_LXC_CONF
270 if (!lxc_log_use_global_fd && current_config)
271 fd_to_use = current_config->logfd;
272#endif
273
274 if (fd_to_use == -1)
275 fd_to_use = lxc_log_fd;
276
277 if (fd_to_use == -1)
cb8c5720
CLG
278 return 0;
279
e1378d35 280 if (lxc_unix_epoch_to_utc(date_time, LXC_LOG_TIME_SIZE, &event->timestamp) < 0)
c57dbb96
CB
281 return 0;
282
283 n = snprintf(buffer, sizeof(buffer),
e1378d35 284 "%15s%s%s %s %-8s %s - %s:%s:%d - ",
c57dbb96
CB
285 log_prefix,
286 log_vmname ? " " : "",
287 log_vmname ? log_vmname : "",
e1378d35 288 date_time,
c57dbb96
CB
289 lxc_log_priority_to_string(event->priority),
290 event->category,
291 event->locinfo->file, event->locinfo->func,
292 event->locinfo->line);
cb8c5720 293
f6c79610
LZ
294 if (n < 0)
295 return n;
cb8c5720 296
450b6d3d 297 if ((size_t)n < (sizeof(buffer) - 1))
0dcdbf8a
CB
298 n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt, *event->vap);
299 else
cb8c5720 300 n = sizeof(buffer) - 1;
cb8c5720
CLG
301
302 buffer[n] = '\n';
303
858377e4 304 return write(fd_to_use, buffer, n + 1);
cb8c5720
CLG
305}
306
64c57ea1
BD
307static struct lxc_log_appender log_appender_syslog = {
308 .name = "syslog",
309 .append = log_append_syslog,
310 .next = NULL,
311};
312
d737c074
MN
313static struct lxc_log_appender log_appender_stderr = {
314 .name = "stderr",
315 .append = log_append_stderr,
316 .next = NULL,
317};
318
cb8c5720
CLG
319static struct lxc_log_appender log_appender_logfile = {
320 .name = "logfile",
321 .append = log_append_logfile,
441e4963 322 .next = NULL,
cb8c5720
CLG
323};
324
325static struct lxc_log_category log_root = {
326 .name = "root",
327 .priority = LXC_LOG_PRIORITY_ERROR,
328 .appender = NULL,
329 .parent = NULL,
330};
331
332struct lxc_log_category lxc_log_category_lxc = {
333 .name = "lxc",
334 .priority = LXC_LOG_PRIORITY_ERROR,
858377e4 335 .appender = &log_appender_logfile,
cb8c5720
CLG
336 .parent = &log_root
337};
338
339/*---------------------------------------------------------------------------*/
5e1e7aaf
SH
340static int build_dir(const char *name)
341{
342 char *n = strdup(name); // because we'll be modifying it
343 char *p, *e;
344 int ret;
345
346 if (!n) {
347 ERROR("Out of memory while creating directory '%s'.", name);
348 return -1;
349 }
350
351 e = &n[strlen(n)];
352 for (p = n+1; p < e; p++) {
353 if (*p != '/')
354 continue;
355 *p = '\0';
356 if (access(n, F_OK)) {
357 ret = lxc_unpriv(mkdir(n, 0755));
8479c136 358 if (ret && errno != EEXIST) {
5e1e7aaf
SH
359 SYSERROR("failed to create directory '%s'.", n);
360 free(n);
361 return -1;
362 }
363 }
364 *p = '/';
365 }
366 free(n);
367 return 0;
368}
369
cb8c5720
CLG
370/*---------------------------------------------------------------------------*/
371static int log_open(const char *name)
372{
373 int fd;
374 int newfd;
375
28f602ff
DL
376 fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY |
377 O_APPEND | O_CLOEXEC, 0666));
cb8c5720
CLG
378 if (fd == -1) {
379 ERROR("failed to open log file \"%s\" : %s", name,
380 strerror(errno));
381 return -1;
382 }
383
384 if (fd > 2)
385 return fd;
386
387 newfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
388 if (newfd == -1)
389 ERROR("failed to dup log fd %d : %s", fd, strerror(errno));
390
391 close(fd);
392 return newfd;
393}
394
ab1bf971
DE
395/*
396 * Build the path to the log file
397 * @name : the name of the container
398 * @lxcpath : the lxcpath to use as a basename or NULL to use LOGPATH
ec64264d 399 * Returns malloced path on success, or NULL on failure
ab1bf971
DE
400 */
401static char *build_log_path(const char *name, const char *lxcpath)
5e1e7aaf
SH
402{
403 char *p;
ee25a44f
DE
404 int len, ret, use_dir;
405
74f052dd
SG
406 if (!name)
407 return NULL;
408
ee25a44f
DE
409#if USE_CONFIGPATH_LOGS
410 use_dir = 1;
411#else
412 use_dir = 0;
413#endif
5e1e7aaf
SH
414
415 /*
ee25a44f
DE
416 * If USE_CONFIGPATH_LOGS is true or lxcpath is given, the resulting
417 * path will be:
5e1e7aaf 418 * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0'
ab1bf971
DE
419 *
420 * If USE_CONFIGPATH_LOGS is false the resulting path will be:
421 * '$logpath' + '/' + '$name' + '.log' + '\0'
5e1e7aaf 422 */
ab1bf971 423 len = strlen(name) + 6; /* 6 == '/' + '.log' + '\0' */
ee25a44f
DE
424 if (lxcpath)
425 use_dir = 1;
426 else
ab1bf971 427 lxcpath = LOGPATH;
ee25a44f
DE
428
429 if (use_dir)
430 len += strlen(lxcpath) + 1 + strlen(name) + 1; /* add "/$container_name/" */
431 else
432 len += strlen(lxcpath) + 1;
5e1e7aaf
SH
433 p = malloc(len);
434 if (!p)
435 return p;
ee25a44f
DE
436
437 if (use_dir)
438 ret = snprintf(p, len, "%s/%s/%s.log", lxcpath, name, name);
439 else
440 ret = snprintf(p, len, "%s/%s.log", lxcpath, name);
441
5e1e7aaf
SH
442 if (ret < 0 || ret >= len) {
443 free(p);
444 return NULL;
445 }
446 return p;
447}
448
d9c9b180
SH
449extern void lxc_log_close(void)
450{
64c57ea1
BD
451 closelog();
452 free(log_vmname);
453 log_vmname = NULL;
d9c9b180
SH
454 if (lxc_log_fd == -1)
455 return;
456 close(lxc_log_fd);
457 lxc_log_fd = -1;
458 free(log_fname);
459 log_fname = NULL;
460}
461
ab1bf971
DE
462/*
463 * This can be called:
464 * 1. when a program calls lxc_log_init with no logfile parameter (in which
465 * case the default is used). In this case lxc.logfile can override this.
466 * 2. when a program calls lxc_log_init with a logfile parameter. In this
467 * case we don't want lxc.logfile to override this.
468 * 3. When a lxc.logfile entry is found in config file.
469 */
470static int __lxc_log_set_file(const char *fname, int create_dirs)
471{
472 if (lxc_log_fd != -1) {
473 // we are overriding the default.
d9c9b180 474 lxc_log_close();
ab1bf971
DE
475 }
476
97bc2422
CB
477 if (!fname)
478 return -1;
3f53c691
SH
479
480 if (strlen(fname) == 0) {
6edbfc86
SG
481 log_fname = NULL;
482 return 0;
483 }
484
ab1bf971
DE
485#if USE_CONFIGPATH_LOGS
486 // we don't build_dir for the default if the default is
487 // i.e. /var/lib/lxc/$container/$container.log
488 if (create_dirs)
489#endif
490 if (build_dir(fname)) {
491 ERROR("failed to create dir for log file \"%s\" : %s", fname,
492 strerror(errno));
493 return -1;
494 }
495
496 lxc_log_fd = log_open(fname);
497 if (lxc_log_fd == -1)
498 return -1;
499
500 log_fname = strdup(fname);
501 return 0;
502}
503
504static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_dirs)
505{
506 char *logfile;
507 int ret;
508
509 logfile = build_log_path(name, lxcpath);
510 if (!logfile) {
511 ERROR("could not build log path");
512 return -1;
513 }
514 ret = __lxc_log_set_file(logfile, create_dirs);
515 free(logfile);
516 return ret;
517}
5e1e7aaf 518
64c57ea1
BD
519extern int lxc_log_syslog(int facility)
520{
521 struct lxc_log_appender *appender;
522
523 openlog(log_prefix, LOG_PID, facility);
524 if (!lxc_log_category_lxc.appender) {
525 lxc_log_category_lxc.appender = &log_appender_syslog;
526 return 0;
527 }
528 appender = lxc_log_category_lxc.appender;
529 while (appender->next != NULL)
530 appender = appender->next;
531 appender->next = &log_appender_syslog;
532
533 return 0;
534}
535
536extern void lxc_log_enable_syslog(void)
537{
538 syslog_enable = 1;
539}
540
858377e4
SH
541/*
542 * lxc_log_init:
543 * Called from lxc front-end programs (like lxc-create, lxc-start) to
544 * initalize the log defaults.
545 */
5e1e7aaf 546extern int lxc_log_init(const char *name, const char *file,
ab1bf971
DE
547 const char *priority, const char *prefix, int quiet,
548 const char *lxcpath)
cb8c5720 549{
51cab631 550 int lxc_priority = LXC_LOG_PRIORITY_ERROR;
5e1e7aaf 551 int ret;
51cab631 552
ab1bf971
DE
553 if (lxc_log_fd != -1) {
554 WARN("lxc_log_init called with log already initialized");
2312f31b 555 return 0;
ab1bf971 556 }
2312f31b 557
af61c481 558 if (priority)
b12e1cb5 559 lxc_priority = lxc_log_priority_to_int(priority);
51cab631 560
858377e4
SH
561 if (!lxc_loglevel_specified) {
562 lxc_log_category_lxc.priority = lxc_priority;
563 lxc_loglevel_specified = 1;
564 }
cb8c5720 565
01db0197 566 if (!lxc_quiet_specified) {
01db0197
WD
567 if (!quiet)
568 lxc_log_category_lxc.appender->next = &log_appender_stderr;
569 }
441e4963 570
cb8c5720 571 if (prefix)
ab1bf971 572 lxc_log_set_prefix(prefix);
74476cf1 573
64c57ea1
BD
574 if (name)
575 log_vmname = strdup(name);
576
ab1bf971 577 if (file) {
ab1bf971
DE
578 if (strcmp(file, "none") == 0)
579 return 0;
580 ret = __lxc_log_set_file(file, 1);
858377e4 581 lxc_log_use_global_fd = 1;
5e1e7aaf 582 } else {
74f052dd
SG
583 /* if no name was specified, there nothing to do */
584 if (!name)
585 return 0;
586
ab1bf971
DE
587 ret = -1;
588
e0b0b533
DE
589 if (!lxcpath)
590 lxcpath = LOGPATH;
591
361e0e3c 592 /* try LOGPATH if lxcpath is the default for the privileged containers */
479bba8b 593 if (!geteuid() && strcmp(LXCPATH, lxcpath) == 0)
ab1bf971 594 ret = _lxc_log_set_file(name, NULL, 0);
5e1e7aaf 595
ab1bf971
DE
596 /* try in lxcpath */
597 if (ret < 0)
598 ret = _lxc_log_set_file(name, lxcpath, 1);
599
600 /* try LOGPATH in case its writable by the caller */
601 if (ret < 0)
602 ret = _lxc_log_set_file(name, NULL, 0);
603 }
5e1e7aaf 604
5e1e7aaf 605 /*
ab1bf971
DE
606 * If !file, that is, if the user did not request this logpath, then
607 * ignore failures and continue logging to console
5e1e7aaf 608 */
ab1bf971 609 if (!file && ret != 0) {
5e1e7aaf
SH
610 INFO("Ignoring failure to open default logfile.");
611 ret = 0;
612 }
613
5e1e7aaf 614 return ret;
cb8c5720 615}
4a85ce2a
SH
616
617/*
618 * This is called when we read a lxc.loglevel entry in a lxc.conf file. This
619 * happens after processing command line arguments, which override the .conf
620 * settings. So only set the level if previously unset.
621 */
858377e4 622extern int lxc_log_set_level(int *dest, int level)
4a85ce2a 623{
4a85ce2a
SH
624 if (level < 0 || level >= LXC_LOG_PRIORITY_NOTSET) {
625 ERROR("invalid log priority %d", level);
626 return -1;
627 }
858377e4 628 *dest = level;
4a85ce2a
SH
629 return 0;
630}
631
ab1bf971
DE
632extern int lxc_log_get_level(void)
633{
ab1bf971
DE
634 return lxc_log_category_lxc.priority;
635}
636
fabf7361
QH
637extern bool lxc_log_has_valid_level(void)
638{
639 int log_level = lxc_log_get_level();
640 if (log_level < 0 || log_level >= LXC_LOG_PRIORITY_NOTSET)
641 return false;
642 return true;
643}
644
4a85ce2a 645/*
ab1bf971
DE
646 * This is called when we read a lxc.logfile entry in a lxc.conf file. This
647 * happens after processing command line arguments, which override the .conf
648 * settings. So only set the file if previously unset.
4a85ce2a 649 */
858377e4 650extern int lxc_log_set_file(int *fd, const char *fname)
4a85ce2a 651{
858377e4
SH
652 if (*fd != -1) {
653 close(*fd);
654 *fd = -1;
655 }
656
657 if (build_dir(fname)) {
658 ERROR("failed to create dir for log file \"%s\" : %s", fname,
659 strerror(errno));
660 return -1;
661 }
662
663 *fd = log_open(fname);
664 if (*fd == -1)
665 return -errno;
666 return 0;
4a85ce2a 667}
9ea87d5d 668
ab1bf971 669extern const char *lxc_log_get_file(void)
5e1e7aaf 670{
ab1bf971 671 return log_fname;
5e1e7aaf
SH
672}
673
ab1bf971 674extern void lxc_log_set_prefix(const char *prefix)
9ea87d5d 675{
ab1bf971
DE
676 strncpy(log_prefix, prefix, sizeof(log_prefix));
677 log_prefix[sizeof(log_prefix) - 1] = 0;
9ea87d5d
SH
678}
679
ab1bf971 680extern const char *lxc_log_get_prefix(void)
9ea87d5d 681{
ab1bf971 682 return log_prefix;
9ea87d5d 683}
6edbfc86
SG
684
685extern void lxc_log_options_no_override()
686{
01db0197 687 lxc_quiet_specified = 1;
858377e4 688 lxc_loglevel_specified = 1;
6edbfc86 689}