xref: /netbsd-src/external/gpl2/lvm2/dist/lib/log/log.c (revision 7c604eea85b4f330dc75ffe65e947f4d73758aa0)
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