4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "lvm-string.h"
28 static FILE *_log_file
;
29 static struct device _log_dev
;
30 static struct str_list _log_dev_alias
;
32 static int _syslog
= 0;
33 static int _log_to_file
= 0;
34 static int _log_direct
= 0;
35 static int _log_while_suspended
= 0;
36 static int _indent
= 1;
37 static int _log_suppress
= 0;
38 static char _msg_prefix
[30] = " ";
39 static int _already_logging
= 0;
41 static lvm2_log_fn_t _lvm2_log_fn
= NULL
;
43 static int _lvm_errno
= 0;
44 static int _store_errmsg
= 0;
45 static char *_lvm_errmsg
= NULL
;
47 void init_log_fn(lvm2_log_fn_t log_fn
)
50 _lvm2_log_fn
= log_fn
;
55 void init_log_file(const char *log_file
, int append
)
57 const char *open_mode
= append
? "a" : "w";
59 if (!(_log_file
= fopen(log_file
, open_mode
))) {
60 log_sys_error("fopen", log_file
);
67 void init_log_direct(const char *log_file
, int append
)
69 int open_flags
= append
? 0 : O_TRUNC
;
71 dev_create_file(log_file
, &_log_dev
, &_log_dev_alias
, 1);
72 if (!dev_open_flags(&_log_dev
, O_RDWR
| O_CREAT
| open_flags
, 1, 0))
78 void init_log_while_suspended(int log_while_suspended
)
80 _log_while_suspended
= log_while_suspended
;
83 void init_syslog(int facility
)
85 openlog("lvm", LOG_PID
, facility
);
89 int log_suppress(int suppress
)
91 int old_suppress
= _log_suppress
;
93 _log_suppress
= suppress
;
98 void release_log_memory(void)
103 dm_free((char *) _log_dev_alias
.str
);
104 _log_dev_alias
.str
= "activate_log file";
110 dev_close(&_log_dev
);
115 if (dm_fclose(_log_file
)) {
117 fprintf(stderr
, "failed to write log file: %s\n",
120 fprintf(stderr
, "failed to write log file\n");
134 void init_msg_prefix(const char *prefix
)
136 strncpy(_msg_prefix
, prefix
, sizeof(_msg_prefix
));
137 _msg_prefix
[sizeof(_msg_prefix
) - 1] = '\0';
140 void init_indent(int indent
)
145 void reset_lvm_errno(int store_errmsg
)
150 dm_free(_lvm_errmsg
);
154 _store_errmsg
= store_errmsg
;
157 int stored_errno(void)
162 const char *stored_errmsg(void)
164 return _lvm_errmsg
? : "";
167 void print_log(int level
, const char *file
, int line
, int dm_errno
,
168 const char *format
, ...)
171 char buf
[1024], buf2
[4096], locn
[4096];
174 const char *trformat
; /* Translated format string */
176 int use_stderr
= level
& _LOG_STDERR
;
178 level
&= ~_LOG_STDERR
;
180 if (_log_suppress
== 2)
183 if (level
<= _LOG_ERR
)
184 init_error_message_produced(1);
186 trformat
= _(format
);
188 if (dm_errno
&& !_lvm_errno
)
189 _lvm_errno
= dm_errno
;
191 if (_lvm2_log_fn
|| (_store_errmsg
&& (level
<= _LOG_ERR
))) {
192 va_start(ap
, format
);
193 n
= vsnprintf(buf2
, sizeof(buf2
) - 1, trformat
, ap
);
197 fprintf(stderr
, _("vsnprintf failed: skipping external "
198 "logging function"));
202 buf2
[sizeof(buf2
) - 1] = '\0';
206 if (_store_errmsg
&& (level
<= _LOG_ERR
)) {
208 _lvm_errmsg
= dm_strdup(message
);
209 else if ((newbuf
= dm_realloc(_lvm_errmsg
,
210 strlen(_lvm_errmsg
) +
211 strlen(message
) + 2))) {
212 _lvm_errmsg
= strcat(newbuf
, "\n");
213 _lvm_errmsg
= strcat(newbuf
, message
);
218 _lvm2_log_fn(level
, file
, line
, 0, message
);
224 if (!_log_suppress
) {
225 if (verbose_level() > _LOG_DEBUG
)
226 dm_snprintf(locn
, sizeof(locn
), "#%s:%d ",
231 va_start(ap
, format
);
234 if (!strcmp("<backtrace>", format
) &&
235 verbose_level() <= _LOG_DEBUG
)
237 if (verbose_level() >= _LOG_DEBUG
) {
238 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
241 fprintf(stderr
, " ");
242 vfprintf(stderr
, trformat
, ap
);
248 if (verbose_level() >= _LOG_INFO
) {
249 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
252 fprintf(stderr
, " ");
253 vfprintf(stderr
, trformat
, ap
);
258 if (verbose_level() >= _LOG_NOTICE
) {
259 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
262 fprintf(stderr
, " ");
263 vfprintf(stderr
, trformat
, ap
);
268 if (verbose_level() >= _LOG_WARN
) {
269 fprintf(use_stderr
? stderr
: stdout
, "%s%s",
270 log_command_name(), _msg_prefix
);
271 vfprintf(use_stderr
? stderr
: stdout
, trformat
, ap
);
272 fputc('\n', use_stderr
? stderr
: stdout
);
276 if (verbose_level() >= _LOG_ERR
) {
277 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
279 vfprintf(stderr
, trformat
, ap
);
285 if (verbose_level() >= _LOG_FATAL
) {
286 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
288 vfprintf(stderr
, trformat
, ap
);
296 if (level
> debug_level())
299 if (_log_to_file
&& (_log_while_suspended
|| !memlock())) {
300 fprintf(_log_file
, "%s:%d %s%s", file
, line
, log_command_name(),
303 va_start(ap
, format
);
304 vfprintf(_log_file
, trformat
, ap
);
307 fprintf(_log_file
, "\n");
311 if (_syslog
&& (_log_while_suspended
|| !memlock())) {
312 va_start(ap
, format
);
313 vsyslog(level
, trformat
, ap
);
317 /* FIXME This code is unfinished - pre-extend & condense. */
318 if (!_already_logging
&& _log_direct
&& memlock()) {
319 _already_logging
= 1;
320 memset(&buf
, ' ', sizeof(buf
));
322 if ((n
= dm_snprintf(buf
, sizeof(buf
) - bufused
- 1,
323 "%s:%d %s%s", file
, line
, log_command_name(),
329 va_start(ap
, format
);
330 n
= vsnprintf(buf
+ bufused
- 1, sizeof(buf
) - bufused
- 1,
336 buf
[bufused
- 1] = '\n';
338 buf
[sizeof(buf
) - 1] = '\n';
339 /* FIXME real size bufused */
340 dev_append(&_log_dev
, sizeof(buf
), buf
);
341 _already_logging
= 0;