2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Cedric Le Goater <legoater@free.fr>
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.
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.
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
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <sys/types.h>
31 #define __USE_GNU /* for *_CLOEXEC */
39 #define LXC_LOG_PREFIX_SIZE 32
40 #define LXC_LOG_BUFFER_SIZE 512
43 static char log_prefix
[LXC_LOG_PREFIX_SIZE
] = "lxc";
44 static int lxc_loglevel_specified
= 0;
45 // if logfile was specifed on command line, it won't be overridden by lxc.logfile
46 static int lxc_log_specified
= 0;
48 lxc_log_define(lxc_log
, lxc
);
50 /*---------------------------------------------------------------------------*/
51 static int log_append_stderr(const struct lxc_log_appender
*appender
,
52 struct lxc_log_event
*event
)
54 if (event
->priority
< LXC_LOG_PRIORITY_ERROR
)
57 fprintf(stderr
, "%s: ", log_prefix
);
58 vfprintf(stderr
, event
->fmt
, *event
->vap
);
59 fprintf(stderr
, "\n");
63 /*---------------------------------------------------------------------------*/
64 static int log_append_logfile(const struct lxc_log_appender
*appender
,
65 struct lxc_log_event
*event
)
67 char buffer
[LXC_LOG_BUFFER_SIZE
];
73 n
= snprintf(buffer
, sizeof(buffer
),
74 "%15s %10ld.%03ld %-8s %s - ",
76 event
->timestamp
.tv_sec
,
77 event
->timestamp
.tv_usec
/ 1000,
78 lxc_log_priority_to_string(event
->priority
),
81 n
+= vsnprintf(buffer
+ n
, sizeof(buffer
) - n
, event
->fmt
,
84 if (n
>= sizeof(buffer
) - 1) {
85 WARN("truncated next event from %d to %zd bytes", n
,
87 n
= sizeof(buffer
) - 1;
92 return write(lxc_log_fd
, buffer
, n
+ 1);
95 static struct lxc_log_appender log_appender_stderr
= {
97 .append
= log_append_stderr
,
101 static struct lxc_log_appender log_appender_logfile
= {
103 .append
= log_append_logfile
,
107 static struct lxc_log_category log_root
= {
109 .priority
= LXC_LOG_PRIORITY_ERROR
,
114 struct lxc_log_category lxc_log_category_lxc
= {
116 .priority
= LXC_LOG_PRIORITY_ERROR
,
117 .appender
= &log_appender_stderr
,
121 /*---------------------------------------------------------------------------*/
122 extern void lxc_log_setprefix(const char *prefix
)
124 strncpy(log_prefix
, prefix
, sizeof(log_prefix
));
125 log_prefix
[sizeof(log_prefix
) - 1] = 0;
128 static int build_dir(const char *name
)
130 char *n
= strdup(name
); // because we'll be modifying it
135 ERROR("Out of memory while creating directory '%s'.", name
);
140 for (p
= n
+1; p
< e
; p
++) {
144 if (access(n
, F_OK
)) {
145 ret
= lxc_unpriv(mkdir(n
, 0755));
146 if (ret
&& errno
!= -EEXIST
) {
147 SYSERROR("failed to create directory '%s'.", n
);
158 /*---------------------------------------------------------------------------*/
159 static int log_open(const char *name
)
164 fd
= lxc_unpriv(open(name
, O_CREAT
| O_WRONLY
|
165 O_APPEND
| O_CLOEXEC
, 0666));
167 ERROR("failed to open log file \"%s\" : %s", name
,
175 newfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
177 ERROR("failed to dup log fd %d : %s", fd
, strerror(errno
));
183 static char *build_log_path(const char *name
)
189 * '$logpath' + '/' + '$name' + '.log' + '\0'
191 * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0'
192 * sizeof(LOGPATH) includes its \0
194 len
= sizeof(LOGPATH
) + strlen(name
) + 6;
195 #if USE_CONFIGPATH_LOGS
196 len
+= strlen(name
) + 1; /* add "/$container_name/" */
201 #if USE_CONFIGPATH_LOGS
202 ret
= snprintf(p
, len
, "%s/%s/%s.log", LOGPATH
, name
, name
);
204 ret
= snprintf(p
, len
, "%s/%s.log", LOGPATH
, name
);
206 if (ret
< 0 || ret
>= len
) {
213 int do_lxc_log_set_file(const char *fname
, int from_default
);
215 /*---------------------------------------------------------------------------*/
216 extern int lxc_log_init(const char *name
, const char *file
,
217 const char *priority
, const char *prefix
, int quiet
)
219 int lxc_priority
= LXC_LOG_PRIORITY_ERROR
;
221 char *tmpfile
= NULL
;
222 int want_lxc_log_specified
= 0;
224 if (lxc_log_fd
!= -1)
228 lxc_loglevel_specified
= 1;
229 lxc_priority
= lxc_log_priority_to_int(priority
);
231 if (lxc_priority
== LXC_LOG_PRIORITY_NOTSET
) {
232 ERROR("invalid log priority %s", priority
);
237 lxc_log_category_lxc
.priority
= lxc_priority
;
238 lxc_log_category_lxc
.appender
= &log_appender_logfile
;
241 lxc_log_category_lxc
.appender
->next
= &log_appender_stderr
;
244 lxc_log_setprefix(prefix
);
246 if (file
&& strcmp(file
, "none") == 0) {
247 want_lxc_log_specified
= 1;
252 tmpfile
= build_log_path(name
);
254 ERROR("could not build log path");
258 want_lxc_log_specified
= 1;
261 ret
= do_lxc_log_set_file(tmpfile
? tmpfile
: file
, !want_lxc_log_specified
);
263 if (want_lxc_log_specified
)
264 lxc_log_specified
= 1;
266 * If !want_lxc_log_specified, that is, if the user did not request
267 * this logpath, then ignore failures and continue logging to console
269 if (!want_lxc_log_specified
&& ret
!= 0) {
270 INFO("Ignoring failure to open default logfile.");
281 * This is called when we read a lxc.loglevel entry in a lxc.conf file. This
282 * happens after processing command line arguments, which override the .conf
283 * settings. So only set the level if previously unset.
285 extern int lxc_log_set_level(int level
)
287 if (lxc_loglevel_specified
)
289 if (level
< 0 || level
>= LXC_LOG_PRIORITY_NOTSET
) {
290 ERROR("invalid log priority %d", level
);
293 lxc_log_category_lxc
.priority
= level
;
297 char *log_fname
; // default to NULL, set in lxc_log_set_file.
299 * This can be called:
300 * 1. when a program calls lxc_log_init with no logfile parameter (in which
301 * case the default is used). In this case lxc.logfile can override this.
302 * 2. when a program calls lxc_log_init with a logfile parameter. In this
303 * case we don't want lxc.logfile to override this.
304 * 3. When a lxc.logfile entry is found in config file.
306 int do_lxc_log_set_file(const char *fname
, int from_default
)
308 if (lxc_log_specified
) {
309 INFO("lxc.logfile overriden by command line");
312 if (lxc_log_fd
!= -1) {
313 // we are overriding the default.
318 #if USE_CONFIGPATH_LOGS
319 // we don't build_dir for the default if the default is
320 // i.e. /var/lib/lxc/$container/$container.log
323 if (build_dir(fname
)) {
324 ERROR("failed to create dir for log file \"%s\" : %s", fname
,
329 lxc_log_fd
= log_open(fname
);
330 if (lxc_log_fd
== -1)
333 log_fname
= strdup(fname
);
337 extern int lxc_log_set_file(const char *fname
)
339 return do_lxc_log_set_file(fname
, 0);
342 extern int lxc_log_get_level(void)
344 if (!lxc_loglevel_specified
)
345 return LXC_LOG_PRIORITY_NOTSET
;
346 return lxc_log_category_lxc
.priority
;
349 extern const char *lxc_log_get_file(void)