2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "lvm-string.h"
27 static FILE *_log_file
;
28 static struct device _log_dev
;
29 static struct str_list _log_dev_alias
;
31 static int _syslog
= 0;
32 static int _log_to_file
= 0;
33 static int _log_direct
= 0;
34 static int _log_while_suspended
= 0;
35 static int _indent
= 1;
36 static int _log_suppress
= 0;
37 static char _msg_prefix
[30] = " ";
38 static int _already_logging
= 0;
39 static int _abort_on_internal_errors
= 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
;
46 static size_t _lvm_errmsg_size
= 0;
47 static size_t _lvm_errmsg_len
= 0;
48 #define MAX_ERRMSG_LEN (512 * 1024) /* Max size of error buffer 512KB */
50 void init_log_fn(lvm2_log_fn_t log_fn
)
53 _lvm2_log_fn
= log_fn
;
58 void init_log_file(const char *log_file
, int append
)
60 const char *open_mode
= append
? "a" : "w";
62 if (!(_log_file
= fopen(log_file
, open_mode
))) {
63 log_sys_error("fopen", log_file
);
70 void init_log_direct(const char *log_file
, int append
)
72 int open_flags
= append
? 0 : O_TRUNC
;
74 dev_create_file(log_file
, &_log_dev
, &_log_dev_alias
, 1);
75 if (!dev_open_flags(&_log_dev
, O_RDWR
| O_CREAT
| open_flags
, 1, 0))
81 void init_log_while_suspended(int log_while_suspended
)
83 _log_while_suspended
= log_while_suspended
;
86 void init_syslog(int facility
)
88 openlog("lvm", LOG_PID
, facility
);
92 int log_suppress(int suppress
)
94 int old_suppress
= _log_suppress
;
96 _log_suppress
= suppress
;
101 void release_log_memory(void)
106 dm_free((char *) _log_dev_alias
.str
);
107 _log_dev_alias
.str
= "activate_log file";
113 (void) dev_close(&_log_dev
);
118 if (dm_fclose(_log_file
)) {
120 fprintf(stderr
, "failed to write log file: %s\n",
123 fprintf(stderr
, "failed to write log file\n");
130 void fin_syslog(void)
137 void init_msg_prefix(const char *prefix
)
139 strncpy(_msg_prefix
, prefix
, sizeof(_msg_prefix
) - 1);
140 _msg_prefix
[sizeof(_msg_prefix
) - 1] = '\0';
143 void init_indent(int indent
)
148 void init_abort_on_internal_errors(int fatal
)
150 _abort_on_internal_errors
= fatal
;
153 void reset_lvm_errno(int store_errmsg
)
158 dm_free(_lvm_errmsg
);
160 _lvm_errmsg_size
= _lvm_errmsg_len
= 0;
163 _store_errmsg
= store_errmsg
;
166 int stored_errno(void)
171 const char *stored_errmsg(void)
173 return _lvm_errmsg
? : "";
176 static struct dm_hash_table
*_duplicated
= NULL
;
178 void reset_log_duplicated(void) {
180 dm_hash_destroy(_duplicated
);
185 void print_log(int level
, const char *file
, int line
, int dm_errno
,
186 const char *format
, ...)
189 char buf
[1024], locn
[4096];
192 const char *trformat
; /* Translated format string */
194 int use_stderr
= level
& _LOG_STDERR
;
195 int log_once
= level
& _LOG_ONCE
;
196 int fatal_internal_error
= 0;
199 level
&= ~(_LOG_STDERR
|_LOG_ONCE
);
201 if (_abort_on_internal_errors
&&
202 !strncmp(format
, INTERNAL_ERROR
,
203 strlen(INTERNAL_ERROR
))) {
204 fatal_internal_error
= 1;
205 /* Internal errors triggering abort cannot be suppressed. */
210 if (_log_suppress
== 2)
213 if (level
<= _LOG_ERR
)
214 init_error_message_produced(1);
216 trformat
= _(format
);
218 if (dm_errno
&& !_lvm_errno
)
219 _lvm_errno
= dm_errno
;
222 (_store_errmsg
&& (level
<= _LOG_ERR
)) ||
224 va_start(ap
, format
);
225 n
= vsnprintf(locn
, sizeof(locn
) - 1, trformat
, ap
);
229 fprintf(stderr
, _("vsnprintf failed: skipping external "
230 "logging function"));
234 locn
[sizeof(locn
) - 1] = '\0';
238 /* FIXME Avoid pointless use of message buffer when it'll never be read! */
239 if (_store_errmsg
&& (level
<= _LOG_ERR
) &&
240 _lvm_errmsg_len
< MAX_ERRMSG_LEN
) {
241 msglen
= strlen(message
);
242 if ((_lvm_errmsg_len
+ msglen
+ 1) >= _lvm_errmsg_size
) {
243 _lvm_errmsg_size
= 2 * (_lvm_errmsg_len
+ msglen
+ 1);
244 if ((newbuf
= dm_realloc(_lvm_errmsg
,
246 _lvm_errmsg
= newbuf
;
248 _lvm_errmsg_size
= _lvm_errmsg_len
;
251 (_lvm_errmsg_len
+ msglen
+ 2) < _lvm_errmsg_size
) {
252 /* prepend '\n' and copy with '\0' but do not count in */
254 _lvm_errmsg
[_lvm_errmsg_len
++] = '\n';
255 memcpy(_lvm_errmsg
+ _lvm_errmsg_len
, message
, msglen
+ 1);
256 _lvm_errmsg_len
+= msglen
;
262 _duplicated
= dm_hash_create(128);
264 if (dm_hash_lookup(_duplicated
, message
))
266 (void) dm_hash_insert(_duplicated
, message
, (void*)1);
271 _lvm2_log_fn(level
, file
, line
, 0, message
);
272 if (fatal_internal_error
)
278 if (!_log_suppress
) {
279 if (verbose_level() > _LOG_DEBUG
)
280 (void) dm_snprintf(locn
, sizeof(locn
), "#%s:%d ",
285 va_start(ap
, format
);
288 if (!strcmp("<backtrace>", format
) &&
289 verbose_level() <= _LOG_DEBUG
)
291 if (verbose_level() >= _LOG_DEBUG
) {
292 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
295 fprintf(stderr
, " ");
296 vfprintf(stderr
, trformat
, ap
);
302 if (verbose_level() >= _LOG_INFO
) {
303 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
306 fprintf(stderr
, " ");
307 vfprintf(stderr
, trformat
, ap
);
312 if (verbose_level() >= _LOG_NOTICE
) {
313 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
316 fprintf(stderr
, " ");
317 vfprintf(stderr
, trformat
, ap
);
322 if (verbose_level() >= _LOG_WARN
) {
323 fprintf(use_stderr
? stderr
: stdout
, "%s%s",
324 log_command_name(), _msg_prefix
);
325 vfprintf(use_stderr
? stderr
: stdout
, trformat
, ap
);
326 fputc('\n', use_stderr
? stderr
: stdout
);
330 if (verbose_level() >= _LOG_ERR
) {
331 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
333 vfprintf(stderr
, trformat
, ap
);
339 if (verbose_level() >= _LOG_FATAL
) {
340 fprintf(stderr
, "%s%s%s", locn
, log_command_name(),
342 vfprintf(stderr
, trformat
, ap
);
350 if (fatal_internal_error
)
353 if (level
> debug_level())
356 if (_log_to_file
&& (_log_while_suspended
|| !critical_section())) {
357 fprintf(_log_file
, "%s:%d %s%s", file
, line
, log_command_name(),
360 va_start(ap
, format
);
361 vfprintf(_log_file
, trformat
, ap
);
364 fprintf(_log_file
, "\n");
368 if (_syslog
&& (_log_while_suspended
|| !critical_section())) {
369 va_start(ap
, format
);
370 vsyslog(level
, trformat
, ap
);
374 /* FIXME This code is unfinished - pre-extend & condense. */
375 if (!_already_logging
&& _log_direct
&& critical_section()) {
376 _already_logging
= 1;
377 memset(&buf
, ' ', sizeof(buf
));
379 if ((n
= dm_snprintf(buf
, sizeof(buf
) - 1,
380 "%s:%d %s%s", file
, line
, log_command_name(),
386 va_start(ap
, format
);
387 n
= vsnprintf(buf
+ bufused
- 1, sizeof(buf
) - bufused
- 1,
392 buf
[bufused
- 1] = '\n';
395 buf
[sizeof(buf
) - 1] = '\n';
396 /* FIXME real size bufused */
397 dev_append(&_log_dev
, sizeof(buf
), buf
);
398 _already_logging
= 0;