]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/log.c
Merge pull request #1224 from evgeni/python-utf8
[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 */
3f53c691 23#include <assert.h>
0ad19a3f 24#include <stdio.h>
25#include <errno.h>
cb8c5720
CLG
26#include <limits.h>
27#include <unistd.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <string.h>
858377e4 31#include <pthread.h>
02d25a9e 32#include <time.h>
cb8c5720
CLG
33
34#define __USE_GNU /* for *_CLOEXEC */
35
64c57ea1
BD
36#include <syslog.h>
37#include <stdio.h>
38
cb8c5720
CLG
39#include <fcntl.h>
40#include <stdlib.h>
41
28f602ff
DL
42#include "log.h"
43#include "caps.h"
ab1bf971 44#include "utils.h"
cb8c5720 45
02d25a9e 46#define LXC_LOG_DATEFOMAT_SIZE 15
6b9f3917 47
9f4f402a 48int lxc_log_fd = -1;
64c57ea1 49static int syslog_enable = 0;
858377e4
SH
50int lxc_quiet_specified;
51int lxc_log_use_global_fd;
52static int lxc_loglevel_specified;
53
6b9f3917 54static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
ab1bf971 55static char *log_fname = NULL;
64c57ea1 56static char *log_vmname = NULL;
cb8c5720
CLG
57
58lxc_log_define(lxc_log, lxc);
59
64c57ea1
BD
60static int lxc_log_priority_to_syslog(int priority)
61{
62 switch (priority) {
63 case LXC_LOG_PRIORITY_FATAL:
64 return LOG_EMERG;
65 case LXC_LOG_PRIORITY_ALERT:
66 return LOG_ALERT;
67 case LXC_LOG_PRIORITY_CRIT:
68 return LOG_CRIT;
69 case LXC_LOG_PRIORITY_ERROR:
70 return LOG_ERR;
71 case LXC_LOG_PRIORITY_WARN:
72 return LOG_WARNING;
73 case LXC_LOG_PRIORITY_NOTICE:
74 case LXC_LOG_PRIORITY_NOTSET:
75 return LOG_NOTICE;
76 case LXC_LOG_PRIORITY_INFO:
77 return LOG_INFO;
78 case LXC_LOG_PRIORITY_TRACE:
79 case LXC_LOG_PRIORITY_DEBUG:
80 return LOG_DEBUG;
81 }
82
83 /* Not reached */
84 return LOG_NOTICE;
85}
86
87/*---------------------------------------------------------------------------*/
88static int log_append_syslog(const struct lxc_log_appender *appender,
89 struct lxc_log_event *event)
90{
91 char *msg;
92 int rc, len;
93 va_list args;
94
95 if (!syslog_enable)
96 return 0;
97
98 va_copy(args, *event->vap);
99 len = vsnprintf(NULL, 0, event->fmt, args) + 1;
100 va_end(args);
101 msg = malloc(len * sizeof(char));
102 if (msg == NULL)
103 return 0;
104 rc = vsnprintf(msg, len, event->fmt, *event->vap);
105 if (rc == -1 || rc >= len) {
106 free(msg);
107 return 0;
108 }
109
110 syslog(lxc_log_priority_to_syslog(event->priority),
76d0127f 111 "%s%s %s - %s:%s:%d - %s" ,
64c57ea1 112 log_vmname ? log_vmname : "",
76d0127f 113 log_vmname ? ":" : "",
64c57ea1
BD
114 event->category,
115 event->locinfo->file, event->locinfo->func,
116 event->locinfo->line,
117 msg);
118 free(msg);
119 return 0;
120}
121
d737c074
MN
122/*---------------------------------------------------------------------------*/
123static int log_append_stderr(const struct lxc_log_appender *appender,
124 struct lxc_log_event *event)
125{
126 if (event->priority < LXC_LOG_PRIORITY_ERROR)
127 return 0;
128
c3ff6e24 129 fprintf(stderr, "%s: %s%s", log_prefix, log_vmname ? log_vmname : "", log_vmname ? ": " : "");
15bc516e 130 fprintf(stderr, "%s: %s: %d ", event->locinfo->file, event->locinfo->func, event->locinfo->line);
d737c074
MN
131 vfprintf(stderr, event->fmt, *event->vap);
132 fprintf(stderr, "\n");
133 return 0;
134}
135
cb8c5720
CLG
136/*---------------------------------------------------------------------------*/
137static int log_append_logfile(const struct lxc_log_appender *appender,
5fd8380b 138 struct lxc_log_event *event)
cb8c5720 139{
02d25a9e 140 char date[LXC_LOG_DATEFOMAT_SIZE] = "20150427012246";
cb8c5720 141 char buffer[LXC_LOG_BUFFER_SIZE];
02d25a9e 142 const struct tm *t;
cb8c5720 143 int n;
97c94afb 144 int ms;
858377e4 145 int fd_to_use = -1;
42e56013 146
858377e4
SH
147#ifndef NO_LXC_CONF
148 if (!lxc_log_use_global_fd && current_config)
149 fd_to_use = current_config->logfd;
150#endif
151
152 if (fd_to_use == -1)
153 fd_to_use = lxc_log_fd;
154
155 if (fd_to_use == -1)
cb8c5720
CLG
156 return 0;
157
02d25a9e 158 t = localtime(&event->timestamp.tv_sec);
d16ccca8 159 strftime(date, sizeof(date), "%Y%m%d%H%M%S", t);
97c94afb 160 ms = event->timestamp.tv_usec / 1000;
cb8c5720 161 n = snprintf(buffer, sizeof(buffer),
64c57ea1 162 "%15s%s%s %10s.%03d %-8s %s - %s:%s:%d - ",
cb8c5720 163 log_prefix,
64c57ea1
BD
164 log_vmname ? " " : "",
165 log_vmname ? log_vmname : "",
02d25a9e 166 date,
97c94afb 167 ms,
cb8c5720 168 lxc_log_priority_to_string(event->priority),
15bc516e
SH
169 event->category,
170 event->locinfo->file, event->locinfo->func,
171 event->locinfo->line);
cb8c5720
CLG
172
173 n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt,
5fd8380b 174 *event->vap);
cb8c5720
CLG
175
176 if (n >= sizeof(buffer) - 1) {
5fd8380b 177 WARN("truncated next event from %d to %zd bytes", n,
cb8c5720
CLG
178 sizeof(buffer));
179 n = sizeof(buffer) - 1;
180 }
181
182 buffer[n] = '\n';
183
858377e4 184 return write(fd_to_use, buffer, n + 1);
cb8c5720
CLG
185}
186
64c57ea1
BD
187static struct lxc_log_appender log_appender_syslog = {
188 .name = "syslog",
189 .append = log_append_syslog,
190 .next = NULL,
191};
192
d737c074
MN
193static struct lxc_log_appender log_appender_stderr = {
194 .name = "stderr",
195 .append = log_append_stderr,
196 .next = NULL,
197};
198
cb8c5720
CLG
199static struct lxc_log_appender log_appender_logfile = {
200 .name = "logfile",
201 .append = log_append_logfile,
441e4963 202 .next = NULL,
cb8c5720
CLG
203};
204
205static struct lxc_log_category log_root = {
206 .name = "root",
207 .priority = LXC_LOG_PRIORITY_ERROR,
208 .appender = NULL,
209 .parent = NULL,
210};
211
212struct lxc_log_category lxc_log_category_lxc = {
213 .name = "lxc",
214 .priority = LXC_LOG_PRIORITY_ERROR,
858377e4 215 .appender = &log_appender_logfile,
cb8c5720
CLG
216 .parent = &log_root
217};
218
219/*---------------------------------------------------------------------------*/
5e1e7aaf
SH
220static int build_dir(const char *name)
221{
222 char *n = strdup(name); // because we'll be modifying it
223 char *p, *e;
224 int ret;
225
226 if (!n) {
227 ERROR("Out of memory while creating directory '%s'.", name);
228 return -1;
229 }
230
231 e = &n[strlen(n)];
232 for (p = n+1; p < e; p++) {
233 if (*p != '/')
234 continue;
235 *p = '\0';
236 if (access(n, F_OK)) {
237 ret = lxc_unpriv(mkdir(n, 0755));
8479c136 238 if (ret && errno != EEXIST) {
5e1e7aaf
SH
239 SYSERROR("failed to create directory '%s'.", n);
240 free(n);
241 return -1;
242 }
243 }
244 *p = '/';
245 }
246 free(n);
247 return 0;
248}
249
cb8c5720
CLG
250/*---------------------------------------------------------------------------*/
251static int log_open(const char *name)
252{
253 int fd;
254 int newfd;
255
28f602ff
DL
256 fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY |
257 O_APPEND | O_CLOEXEC, 0666));
cb8c5720
CLG
258 if (fd == -1) {
259 ERROR("failed to open log file \"%s\" : %s", name,
260 strerror(errno));
261 return -1;
262 }
263
264 if (fd > 2)
265 return fd;
266
267 newfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
268 if (newfd == -1)
269 ERROR("failed to dup log fd %d : %s", fd, strerror(errno));
270
271 close(fd);
272 return newfd;
273}
274
ab1bf971
DE
275/*
276 * Build the path to the log file
277 * @name : the name of the container
278 * @lxcpath : the lxcpath to use as a basename or NULL to use LOGPATH
ec64264d 279 * Returns malloced path on success, or NULL on failure
ab1bf971
DE
280 */
281static char *build_log_path(const char *name, const char *lxcpath)
5e1e7aaf
SH
282{
283 char *p;
ee25a44f
DE
284 int len, ret, use_dir;
285
74f052dd
SG
286 if (!name)
287 return NULL;
288
ee25a44f
DE
289#if USE_CONFIGPATH_LOGS
290 use_dir = 1;
291#else
292 use_dir = 0;
293#endif
5e1e7aaf
SH
294
295 /*
ee25a44f
DE
296 * If USE_CONFIGPATH_LOGS is true or lxcpath is given, the resulting
297 * path will be:
5e1e7aaf 298 * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0'
ab1bf971
DE
299 *
300 * If USE_CONFIGPATH_LOGS is false the resulting path will be:
301 * '$logpath' + '/' + '$name' + '.log' + '\0'
5e1e7aaf 302 */
ab1bf971 303 len = strlen(name) + 6; /* 6 == '/' + '.log' + '\0' */
ee25a44f
DE
304 if (lxcpath)
305 use_dir = 1;
306 else
ab1bf971 307 lxcpath = LOGPATH;
ee25a44f
DE
308
309 if (use_dir)
310 len += strlen(lxcpath) + 1 + strlen(name) + 1; /* add "/$container_name/" */
311 else
312 len += strlen(lxcpath) + 1;
5e1e7aaf
SH
313 p = malloc(len);
314 if (!p)
315 return p;
ee25a44f
DE
316
317 if (use_dir)
318 ret = snprintf(p, len, "%s/%s/%s.log", lxcpath, name, name);
319 else
320 ret = snprintf(p, len, "%s/%s.log", lxcpath, name);
321
5e1e7aaf
SH
322 if (ret < 0 || ret >= len) {
323 free(p);
324 return NULL;
325 }
326 return p;
327}
328
d9c9b180
SH
329extern void lxc_log_close(void)
330{
64c57ea1
BD
331 closelog();
332 free(log_vmname);
333 log_vmname = NULL;
d9c9b180
SH
334 if (lxc_log_fd == -1)
335 return;
336 close(lxc_log_fd);
337 lxc_log_fd = -1;
338 free(log_fname);
339 log_fname = NULL;
340}
341
ab1bf971
DE
342/*
343 * This can be called:
344 * 1. when a program calls lxc_log_init with no logfile parameter (in which
345 * case the default is used). In this case lxc.logfile can override this.
346 * 2. when a program calls lxc_log_init with a logfile parameter. In this
347 * case we don't want lxc.logfile to override this.
348 * 3. When a lxc.logfile entry is found in config file.
349 */
350static int __lxc_log_set_file(const char *fname, int create_dirs)
351{
352 if (lxc_log_fd != -1) {
353 // we are overriding the default.
d9c9b180 354 lxc_log_close();
ab1bf971
DE
355 }
356
3f53c691
SH
357 assert(fname != NULL);
358
359 if (strlen(fname) == 0) {
6edbfc86
SG
360 log_fname = NULL;
361 return 0;
362 }
363
ab1bf971
DE
364#if USE_CONFIGPATH_LOGS
365 // we don't build_dir for the default if the default is
366 // i.e. /var/lib/lxc/$container/$container.log
367 if (create_dirs)
368#endif
369 if (build_dir(fname)) {
370 ERROR("failed to create dir for log file \"%s\" : %s", fname,
371 strerror(errno));
372 return -1;
373 }
374
375 lxc_log_fd = log_open(fname);
376 if (lxc_log_fd == -1)
377 return -1;
378
379 log_fname = strdup(fname);
380 return 0;
381}
382
383static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_dirs)
384{
385 char *logfile;
386 int ret;
387
388 logfile = build_log_path(name, lxcpath);
389 if (!logfile) {
390 ERROR("could not build log path");
391 return -1;
392 }
393 ret = __lxc_log_set_file(logfile, create_dirs);
394 free(logfile);
395 return ret;
396}
5e1e7aaf 397
64c57ea1
BD
398extern int lxc_log_syslog(int facility)
399{
400 struct lxc_log_appender *appender;
401
402 openlog(log_prefix, LOG_PID, facility);
403 if (!lxc_log_category_lxc.appender) {
404 lxc_log_category_lxc.appender = &log_appender_syslog;
405 return 0;
406 }
407 appender = lxc_log_category_lxc.appender;
408 while (appender->next != NULL)
409 appender = appender->next;
410 appender->next = &log_appender_syslog;
411
412 return 0;
413}
414
415extern void lxc_log_enable_syslog(void)
416{
417 syslog_enable = 1;
418}
419
858377e4
SH
420/*
421 * lxc_log_init:
422 * Called from lxc front-end programs (like lxc-create, lxc-start) to
423 * initalize the log defaults.
424 */
5e1e7aaf 425extern int lxc_log_init(const char *name, const char *file,
ab1bf971
DE
426 const char *priority, const char *prefix, int quiet,
427 const char *lxcpath)
cb8c5720 428{
51cab631 429 int lxc_priority = LXC_LOG_PRIORITY_ERROR;
5e1e7aaf 430 int ret;
51cab631 431
ab1bf971
DE
432 if (lxc_log_fd != -1) {
433 WARN("lxc_log_init called with log already initialized");
2312f31b 434 return 0;
ab1bf971 435 }
2312f31b 436
af61c481 437 if (priority)
b12e1cb5 438 lxc_priority = lxc_log_priority_to_int(priority);
51cab631 439
858377e4
SH
440 if (!lxc_loglevel_specified) {
441 lxc_log_category_lxc.priority = lxc_priority;
442 lxc_loglevel_specified = 1;
443 }
cb8c5720 444
01db0197 445 if (!lxc_quiet_specified) {
01db0197
WD
446 if (!quiet)
447 lxc_log_category_lxc.appender->next = &log_appender_stderr;
448 }
441e4963 449
cb8c5720 450 if (prefix)
ab1bf971 451 lxc_log_set_prefix(prefix);
74476cf1 452
64c57ea1
BD
453 if (name)
454 log_vmname = strdup(name);
455
ab1bf971 456 if (file) {
ab1bf971
DE
457 if (strcmp(file, "none") == 0)
458 return 0;
459 ret = __lxc_log_set_file(file, 1);
858377e4 460 lxc_log_use_global_fd = 1;
5e1e7aaf 461 } else {
74f052dd
SG
462 /* if no name was specified, there nothing to do */
463 if (!name)
464 return 0;
465
ab1bf971
DE
466 ret = -1;
467
e0b0b533
DE
468 if (!lxcpath)
469 lxcpath = LOGPATH;
470
361e0e3c 471 /* try LOGPATH if lxcpath is the default for the privileged containers */
479bba8b 472 if (!geteuid() && strcmp(LXCPATH, lxcpath) == 0)
ab1bf971 473 ret = _lxc_log_set_file(name, NULL, 0);
5e1e7aaf 474
ab1bf971
DE
475 /* try in lxcpath */
476 if (ret < 0)
477 ret = _lxc_log_set_file(name, lxcpath, 1);
478
479 /* try LOGPATH in case its writable by the caller */
480 if (ret < 0)
481 ret = _lxc_log_set_file(name, NULL, 0);
482 }
5e1e7aaf 483
5e1e7aaf 484 /*
ab1bf971
DE
485 * If !file, that is, if the user did not request this logpath, then
486 * ignore failures and continue logging to console
5e1e7aaf 487 */
ab1bf971 488 if (!file && ret != 0) {
5e1e7aaf
SH
489 INFO("Ignoring failure to open default logfile.");
490 ret = 0;
491 }
492
5e1e7aaf 493 return ret;
cb8c5720 494}
4a85ce2a
SH
495
496/*
497 * This is called when we read a lxc.loglevel entry in a lxc.conf file. This
498 * happens after processing command line arguments, which override the .conf
499 * settings. So only set the level if previously unset.
500 */
858377e4 501extern int lxc_log_set_level(int *dest, int level)
4a85ce2a 502{
4a85ce2a
SH
503 if (level < 0 || level >= LXC_LOG_PRIORITY_NOTSET) {
504 ERROR("invalid log priority %d", level);
505 return -1;
506 }
858377e4 507 *dest = level;
4a85ce2a
SH
508 return 0;
509}
510
ab1bf971
DE
511extern int lxc_log_get_level(void)
512{
ab1bf971
DE
513 return lxc_log_category_lxc.priority;
514}
515
fabf7361
QH
516extern bool lxc_log_has_valid_level(void)
517{
518 int log_level = lxc_log_get_level();
519 if (log_level < 0 || log_level >= LXC_LOG_PRIORITY_NOTSET)
520 return false;
521 return true;
522}
523
4a85ce2a 524/*
ab1bf971
DE
525 * This is called when we read a lxc.logfile entry in a lxc.conf file. This
526 * happens after processing command line arguments, which override the .conf
527 * settings. So only set the file if previously unset.
4a85ce2a 528 */
858377e4 529extern int lxc_log_set_file(int *fd, const char *fname)
4a85ce2a 530{
858377e4
SH
531 if (*fd != -1) {
532 close(*fd);
533 *fd = -1;
534 }
535
536 if (build_dir(fname)) {
537 ERROR("failed to create dir for log file \"%s\" : %s", fname,
538 strerror(errno));
539 return -1;
540 }
541
542 *fd = log_open(fname);
543 if (*fd == -1)
544 return -errno;
545 return 0;
4a85ce2a 546}
9ea87d5d 547
ab1bf971 548extern const char *lxc_log_get_file(void)
5e1e7aaf 549{
ab1bf971 550 return log_fname;
5e1e7aaf
SH
551}
552
ab1bf971 553extern void lxc_log_set_prefix(const char *prefix)
9ea87d5d 554{
ab1bf971
DE
555 strncpy(log_prefix, prefix, sizeof(log_prefix));
556 log_prefix[sizeof(log_prefix) - 1] = 0;
9ea87d5d
SH
557}
558
ab1bf971 559extern const char *lxc_log_get_prefix(void)
9ea87d5d 560{
ab1bf971 561 return log_prefix;
9ea87d5d 562}
6edbfc86
SG
563
564extern void lxc_log_options_no_override()
565{
01db0197 566 lxc_quiet_specified = 1;
858377e4 567 lxc_loglevel_specified = 1;
6edbfc86 568}