1*7c604eeaShaad /* $NetBSD: log.c,v 1.1.1.2 2009/12/02 00:26:22 haad Exp $ */
256a34939Shaad
356a34939Shaad /*
456a34939Shaad * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
556a34939Shaad * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
656a34939Shaad *
756a34939Shaad * This file is part of LVM2.
856a34939Shaad *
956a34939Shaad * This copyrighted material is made available to anyone wishing to use,
1056a34939Shaad * modify, copy, or redistribute it subject to the terms and conditions
1156a34939Shaad * of the GNU Lesser General Public License v.2.1.
1256a34939Shaad *
1356a34939Shaad * You should have received a copy of the GNU Lesser General Public License
1456a34939Shaad * along with this program; if not, write to the Free Software Foundation,
1556a34939Shaad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1656a34939Shaad */
1756a34939Shaad
1856a34939Shaad #include "lib.h"
1956a34939Shaad #include "device.h"
2056a34939Shaad #include "memlock.h"
2156a34939Shaad #include "lvm-string.h"
2256a34939Shaad #include "lvm-file.h"
2356a34939Shaad #include "defaults.h"
2456a34939Shaad
2556a34939Shaad #include <stdarg.h>
2656a34939Shaad #include <syslog.h>
2756a34939Shaad
2856a34939Shaad static FILE *_log_file;
2956a34939Shaad static struct device _log_dev;
3056a34939Shaad static struct str_list _log_dev_alias;
3156a34939Shaad
3256a34939Shaad static int _syslog = 0;
3356a34939Shaad static int _log_to_file = 0;
3456a34939Shaad static int _log_direct = 0;
3556a34939Shaad static int _log_while_suspended = 0;
3656a34939Shaad static int _indent = 1;
3756a34939Shaad static int _log_suppress = 0;
3856a34939Shaad static char _msg_prefix[30] = " ";
3956a34939Shaad static int _already_logging = 0;
4056a34939Shaad
4156a34939Shaad static lvm2_log_fn_t _lvm2_log_fn = NULL;
4256a34939Shaad
43*7c604eeaShaad static int _lvm_errno = 0;
44*7c604eeaShaad static int _store_errmsg = 0;
45*7c604eeaShaad static char *_lvm_errmsg = NULL;
46*7c604eeaShaad
init_log_fn(lvm2_log_fn_t log_fn)4756a34939Shaad void init_log_fn(lvm2_log_fn_t log_fn)
4856a34939Shaad {
4956a34939Shaad if (log_fn)
5056a34939Shaad _lvm2_log_fn = log_fn;
5156a34939Shaad else
5256a34939Shaad _lvm2_log_fn = NULL;
5356a34939Shaad }
5456a34939Shaad
init_log_file(const char * log_file,int append)5556a34939Shaad void init_log_file(const char *log_file, int append)
5656a34939Shaad {
5756a34939Shaad const char *open_mode = append ? "a" : "w";
5856a34939Shaad
5956a34939Shaad if (!(_log_file = fopen(log_file, open_mode))) {
6056a34939Shaad log_sys_error("fopen", log_file);
6156a34939Shaad return;
6256a34939Shaad }
6356a34939Shaad
6456a34939Shaad _log_to_file = 1;
6556a34939Shaad }
6656a34939Shaad
init_log_direct(const char * log_file,int append)6756a34939Shaad void init_log_direct(const char *log_file, int append)
6856a34939Shaad {
6956a34939Shaad int open_flags = append ? 0 : O_TRUNC;
7056a34939Shaad
7156a34939Shaad dev_create_file(log_file, &_log_dev, &_log_dev_alias, 1);
7256a34939Shaad if (!dev_open_flags(&_log_dev, O_RDWR | O_CREAT | open_flags, 1, 0))
7356a34939Shaad return;
7456a34939Shaad
7556a34939Shaad _log_direct = 1;
7656a34939Shaad }
7756a34939Shaad
init_log_while_suspended(int log_while_suspended)7856a34939Shaad void init_log_while_suspended(int log_while_suspended)
7956a34939Shaad {
8056a34939Shaad _log_while_suspended = log_while_suspended;
8156a34939Shaad }
8256a34939Shaad
init_syslog(int facility)8356a34939Shaad void init_syslog(int facility)
8456a34939Shaad {
8556a34939Shaad openlog("lvm", LOG_PID, facility);
8656a34939Shaad _syslog = 1;
8756a34939Shaad }
8856a34939Shaad
log_suppress(int suppress)8956a34939Shaad int log_suppress(int suppress)
9056a34939Shaad {
9156a34939Shaad int old_suppress = _log_suppress;
9256a34939Shaad
9356a34939Shaad _log_suppress = suppress;
9456a34939Shaad
9556a34939Shaad return old_suppress;
9656a34939Shaad }
9756a34939Shaad
release_log_memory(void)9856a34939Shaad void release_log_memory(void)
9956a34939Shaad {
10056a34939Shaad if (!_log_direct)
10156a34939Shaad return;
10256a34939Shaad
10356a34939Shaad dm_free((char *) _log_dev_alias.str);
10456a34939Shaad _log_dev_alias.str = "activate_log file";
10556a34939Shaad }
10656a34939Shaad
fin_log(void)10756a34939Shaad void fin_log(void)
10856a34939Shaad {
10956a34939Shaad if (_log_direct) {
11056a34939Shaad dev_close(&_log_dev);
11156a34939Shaad _log_direct = 0;
11256a34939Shaad }
11356a34939Shaad
11456a34939Shaad if (_log_to_file) {
11556a34939Shaad if (dm_fclose(_log_file)) {
11656a34939Shaad if (errno)
11756a34939Shaad fprintf(stderr, "failed to write log file: %s\n",
11856a34939Shaad strerror(errno));
11956a34939Shaad else
12056a34939Shaad fprintf(stderr, "failed to write log file\n");
12156a34939Shaad
12256a34939Shaad }
12356a34939Shaad _log_to_file = 0;
12456a34939Shaad }
12556a34939Shaad }
12656a34939Shaad
fin_syslog()12756a34939Shaad void fin_syslog()
12856a34939Shaad {
12956a34939Shaad if (_syslog)
13056a34939Shaad closelog();
13156a34939Shaad _syslog = 0;
13256a34939Shaad }
13356a34939Shaad
init_msg_prefix(const char * prefix)13456a34939Shaad void init_msg_prefix(const char *prefix)
13556a34939Shaad {
13656a34939Shaad strncpy(_msg_prefix, prefix, sizeof(_msg_prefix));
13756a34939Shaad _msg_prefix[sizeof(_msg_prefix) - 1] = '\0';
13856a34939Shaad }
13956a34939Shaad
init_indent(int indent)14056a34939Shaad void init_indent(int indent)
14156a34939Shaad {
14256a34939Shaad _indent = indent;
14356a34939Shaad }
14456a34939Shaad
reset_lvm_errno(int store_errmsg)145*7c604eeaShaad void reset_lvm_errno(int store_errmsg)
146*7c604eeaShaad {
147*7c604eeaShaad _lvm_errno = 0;
148*7c604eeaShaad
149*7c604eeaShaad if (_lvm_errmsg) {
150*7c604eeaShaad dm_free(_lvm_errmsg);
151*7c604eeaShaad _lvm_errmsg = NULL;
152*7c604eeaShaad }
153*7c604eeaShaad
154*7c604eeaShaad _store_errmsg = store_errmsg;
155*7c604eeaShaad }
156*7c604eeaShaad
stored_errno(void)157*7c604eeaShaad int stored_errno(void)
158*7c604eeaShaad {
159*7c604eeaShaad return _lvm_errno;
160*7c604eeaShaad }
161*7c604eeaShaad
stored_errmsg(void)162*7c604eeaShaad const char *stored_errmsg(void)
163*7c604eeaShaad {
164*7c604eeaShaad return _lvm_errmsg ? : "";
165*7c604eeaShaad }
166*7c604eeaShaad
print_log(int level,const char * file,int line,int dm_errno,const char * format,...)167*7c604eeaShaad void print_log(int level, const char *file, int line, int dm_errno,
168*7c604eeaShaad const char *format, ...)
16956a34939Shaad {
17056a34939Shaad va_list ap;
17156a34939Shaad char buf[1024], buf2[4096], locn[4096];
17256a34939Shaad int bufused, n;
17356a34939Shaad const char *message;
17456a34939Shaad const char *trformat; /* Translated format string */
175*7c604eeaShaad char *newbuf;
17656a34939Shaad int use_stderr = level & _LOG_STDERR;
17756a34939Shaad
17856a34939Shaad level &= ~_LOG_STDERR;
17956a34939Shaad
18056a34939Shaad if (_log_suppress == 2)
18156a34939Shaad return;
18256a34939Shaad
18356a34939Shaad if (level <= _LOG_ERR)
18456a34939Shaad init_error_message_produced(1);
18556a34939Shaad
18656a34939Shaad trformat = _(format);
18756a34939Shaad
188*7c604eeaShaad if (dm_errno && !_lvm_errno)
189*7c604eeaShaad _lvm_errno = dm_errno;
190*7c604eeaShaad
191*7c604eeaShaad if (_lvm2_log_fn || (_store_errmsg && (level <= _LOG_ERR))) {
19256a34939Shaad va_start(ap, format);
19356a34939Shaad n = vsnprintf(buf2, sizeof(buf2) - 1, trformat, ap);
19456a34939Shaad va_end(ap);
19556a34939Shaad
19656a34939Shaad if (n < 0) {
19756a34939Shaad fprintf(stderr, _("vsnprintf failed: skipping external "
19856a34939Shaad "logging function"));
19956a34939Shaad goto log_it;
20056a34939Shaad }
20156a34939Shaad
20256a34939Shaad buf2[sizeof(buf2) - 1] = '\0';
20356a34939Shaad message = &buf2[0];
204*7c604eeaShaad }
20556a34939Shaad
206*7c604eeaShaad if (_store_errmsg && (level <= _LOG_ERR)) {
207*7c604eeaShaad if (!_lvm_errmsg)
208*7c604eeaShaad _lvm_errmsg = dm_strdup(message);
209*7c604eeaShaad else if ((newbuf = dm_realloc(_lvm_errmsg,
210*7c604eeaShaad strlen(_lvm_errmsg) +
211*7c604eeaShaad strlen(message) + 2))) {
212*7c604eeaShaad _lvm_errmsg = strcat(newbuf, "\n");
213*7c604eeaShaad _lvm_errmsg = strcat(newbuf, message);
214*7c604eeaShaad }
215*7c604eeaShaad }
216*7c604eeaShaad
217*7c604eeaShaad if (_lvm2_log_fn) {
218*7c604eeaShaad _lvm2_log_fn(level, file, line, 0, message);
21956a34939Shaad
22056a34939Shaad return;
22156a34939Shaad }
22256a34939Shaad
22356a34939Shaad log_it:
22456a34939Shaad if (!_log_suppress) {
22556a34939Shaad if (verbose_level() > _LOG_DEBUG)
22656a34939Shaad dm_snprintf(locn, sizeof(locn), "#%s:%d ",
22756a34939Shaad file, line);
22856a34939Shaad else
22956a34939Shaad locn[0] = '\0';
23056a34939Shaad
23156a34939Shaad va_start(ap, format);
23256a34939Shaad switch (level) {
23356a34939Shaad case _LOG_DEBUG:
23456a34939Shaad if (!strcmp("<backtrace>", format) &&
23556a34939Shaad verbose_level() <= _LOG_DEBUG)
23656a34939Shaad break;
23756a34939Shaad if (verbose_level() >= _LOG_DEBUG) {
23856a34939Shaad fprintf(stderr, "%s%s%s", locn, log_command_name(),
23956a34939Shaad _msg_prefix);
24056a34939Shaad if (_indent)
24156a34939Shaad fprintf(stderr, " ");
24256a34939Shaad vfprintf(stderr, trformat, ap);
24356a34939Shaad fputc('\n', stderr);
24456a34939Shaad }
24556a34939Shaad break;
24656a34939Shaad
24756a34939Shaad case _LOG_INFO:
24856a34939Shaad if (verbose_level() >= _LOG_INFO) {
24956a34939Shaad fprintf(stderr, "%s%s%s", locn, log_command_name(),
25056a34939Shaad _msg_prefix);
25156a34939Shaad if (_indent)
25256a34939Shaad fprintf(stderr, " ");
25356a34939Shaad vfprintf(stderr, trformat, ap);
25456a34939Shaad fputc('\n', stderr);
25556a34939Shaad }
25656a34939Shaad break;
25756a34939Shaad case _LOG_NOTICE:
25856a34939Shaad if (verbose_level() >= _LOG_NOTICE) {
25956a34939Shaad fprintf(stderr, "%s%s%s", locn, log_command_name(),
26056a34939Shaad _msg_prefix);
26156a34939Shaad if (_indent)
26256a34939Shaad fprintf(stderr, " ");
26356a34939Shaad vfprintf(stderr, trformat, ap);
26456a34939Shaad fputc('\n', stderr);
26556a34939Shaad }
26656a34939Shaad break;
26756a34939Shaad case _LOG_WARN:
26856a34939Shaad if (verbose_level() >= _LOG_WARN) {
26956a34939Shaad fprintf(use_stderr ? stderr : stdout, "%s%s",
27056a34939Shaad log_command_name(), _msg_prefix);
27156a34939Shaad vfprintf(use_stderr ? stderr : stdout, trformat, ap);
27256a34939Shaad fputc('\n', use_stderr ? stderr : stdout);
27356a34939Shaad }
27456a34939Shaad break;
27556a34939Shaad case _LOG_ERR:
27656a34939Shaad if (verbose_level() >= _LOG_ERR) {
27756a34939Shaad fprintf(stderr, "%s%s%s", locn, log_command_name(),
27856a34939Shaad _msg_prefix);
27956a34939Shaad vfprintf(stderr, trformat, ap);
28056a34939Shaad fputc('\n', stderr);
28156a34939Shaad }
28256a34939Shaad break;
28356a34939Shaad case _LOG_FATAL:
28456a34939Shaad default:
28556a34939Shaad if (verbose_level() >= _LOG_FATAL) {
28656a34939Shaad fprintf(stderr, "%s%s%s", locn, log_command_name(),
28756a34939Shaad _msg_prefix);
28856a34939Shaad vfprintf(stderr, trformat, ap);
28956a34939Shaad fputc('\n', stderr);
29056a34939Shaad }
29156a34939Shaad break;
29256a34939Shaad }
29356a34939Shaad va_end(ap);
29456a34939Shaad }
29556a34939Shaad
29656a34939Shaad if (level > debug_level())
29756a34939Shaad return;
29856a34939Shaad
29956a34939Shaad if (_log_to_file && (_log_while_suspended || !memlock())) {
30056a34939Shaad fprintf(_log_file, "%s:%d %s%s", file, line, log_command_name(),
30156a34939Shaad _msg_prefix);
30256a34939Shaad
30356a34939Shaad va_start(ap, format);
30456a34939Shaad vfprintf(_log_file, trformat, ap);
30556a34939Shaad va_end(ap);
30656a34939Shaad
30756a34939Shaad fprintf(_log_file, "\n");
30856a34939Shaad fflush(_log_file);
30956a34939Shaad }
31056a34939Shaad
31156a34939Shaad if (_syslog && (_log_while_suspended || !memlock())) {
31256a34939Shaad va_start(ap, format);
31356a34939Shaad vsyslog(level, trformat, ap);
31456a34939Shaad va_end(ap);
31556a34939Shaad }
31656a34939Shaad
31756a34939Shaad /* FIXME This code is unfinished - pre-extend & condense. */
31856a34939Shaad if (!_already_logging && _log_direct && memlock()) {
31956a34939Shaad _already_logging = 1;
32056a34939Shaad memset(&buf, ' ', sizeof(buf));
32156a34939Shaad bufused = 0;
32256a34939Shaad if ((n = dm_snprintf(buf, sizeof(buf) - bufused - 1,
32356a34939Shaad "%s:%d %s%s", file, line, log_command_name(),
32456a34939Shaad _msg_prefix)) == -1)
32556a34939Shaad goto done;
32656a34939Shaad
32756a34939Shaad bufused += n;
32856a34939Shaad
32956a34939Shaad va_start(ap, format);
33056a34939Shaad n = vsnprintf(buf + bufused - 1, sizeof(buf) - bufused - 1,
33156a34939Shaad trformat, ap);
33256a34939Shaad va_end(ap);
33356a34939Shaad bufused += n;
33456a34939Shaad
33556a34939Shaad done:
33656a34939Shaad buf[bufused - 1] = '\n';
33756a34939Shaad buf[bufused] = '\n';
33856a34939Shaad buf[sizeof(buf) - 1] = '\n';
33956a34939Shaad /* FIXME real size bufused */
34056a34939Shaad dev_append(&_log_dev, sizeof(buf), buf);
34156a34939Shaad _already_logging = 0;
34256a34939Shaad }
34356a34939Shaad }
344