diff --git a/WHATS_NEW b/WHATS_NEW index 3589ebbc3..7fe3a5b06 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.50 - ================================ + Store any errno and error messages issued while processing each command. Use log_error macro consistently throughout in place of log_err. Version 2.02.49 - 15th July 2009 diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c index d559b3a1f..1be07813c 100644 --- a/daemons/clvmd/lvm-functions.c +++ b/daemons/clvmd/lvm-functions.c @@ -714,7 +714,7 @@ static void *get_initial_state() return NULL; } -static void lvm2_log_fn(int level, const char *file, int line, +static void lvm2_log_fn(int level, const char *file, int line, int dm_errno, const char *message) { @@ -723,7 +723,7 @@ static void lvm2_log_fn(int level, const char *file, int line, We need to NULL the function ptr otherwise it will just call back into here! */ init_log_fn(NULL); - print_log(level, file, line, "%s", message); + print_log(level, file, line, dm_errno, "%s", message); init_log_fn(lvm2_log_fn); /* diff --git a/doc/example_cmdlib.c b/doc/example_cmdlib.c index d251fa92c..1fff36e29 100644 --- a/doc/example_cmdlib.c +++ b/doc/example_cmdlib.c @@ -15,7 +15,8 @@ #include "lvm2cmd.h" /* All output gets passed to this function line-by-line */ -void test_log_fn(int level, const char *file, int line, const char *format) +void test_log_fn(int level, int dm_errno, const char *file, int line, + const char *format) { /* Extract and process output here rather than printing it */ diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index c59ad55c1..dc7aa4063 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -190,7 +190,7 @@ static void _init_logging(struct cmd_context *cmd) /* Tell device-mapper about our logging */ #ifdef DEVMAPPER_SUPPORT - dm_log_init(print_log); + dm_log_with_errno_init(print_log); #endif } @@ -1161,6 +1161,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived, cmd->current_settings = cmd->default_settings; cmd->config_valid = 1; + reset_lvm_errno(1); /* FIXME Move to top when cmd returned on error */ return cmd; error: @@ -1288,6 +1289,8 @@ int refresh_toolcontext(struct cmd_context *cmd) persistent_filter_dump(cmd->filter); cmd->config_valid = 1; + + reset_lvm_errno(1); return 1; } @@ -1317,4 +1320,5 @@ void destroy_toolcontext(struct cmd_context *cmd) activation_exit(); fin_log(); fin_syslog(); + reset_lvm_errno(0); } diff --git a/lib/log/log.c b/lib/log/log.c index 1f67b3fed..21163f89e 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -38,6 +38,10 @@ static int _already_logging = 0; static lvm2_log_fn_t _lvm2_log_fn = NULL; +static int _lvm_errno = 0; +static int _store_errmsg = 0; +static char *_lvm_errmsg = NULL; + void init_log_fn(lvm2_log_fn_t log_fn) { if (log_fn) @@ -136,13 +140,37 @@ void init_indent(int indent) _indent = indent; } -void print_log(int level, const char *file, int line, const char *format, ...) +void reset_lvm_errno(int store_errmsg) +{ + _lvm_errno = 0; + + if (_lvm_errmsg) { + dm_free(_lvm_errmsg); + _lvm_errmsg = NULL; + } + + _store_errmsg = store_errmsg; +} + +int lvm_errno(void) +{ + return _lvm_errno; +} + +const char *lvm_errmsg(void) +{ + return _lvm_errmsg ? : ""; +} + +void print_log(int level, const char *file, int line, int dm_errno, + const char *format, ...) { va_list ap; char buf[1024], buf2[4096], locn[4096]; int bufused, n; const char *message; const char *trformat; /* Translated format string */ + char *newbuf; int use_stderr = level & _LOG_STDERR; level &= ~_LOG_STDERR; @@ -155,7 +183,10 @@ void print_log(int level, const char *file, int line, const char *format, ...) trformat = _(format); - if (_lvm2_log_fn) { + if (dm_errno && !_lvm_errno) + _lvm_errno = dm_errno; + + if (_lvm2_log_fn || (_store_errmsg && (level == _LOG_ERR))) { va_start(ap, format); n = vsnprintf(buf2, sizeof(buf2) - 1, trformat, ap); va_end(ap); @@ -168,8 +199,21 @@ void print_log(int level, const char *file, int line, const char *format, ...) buf2[sizeof(buf2) - 1] = '\0'; message = &buf2[0]; + } - _lvm2_log_fn(level, file, line, message); + if (_store_errmsg && (level == _LOG_ERR)) { + if (!_lvm_errmsg) + _lvm_errmsg = dm_strdup(message); + else if ((newbuf = dm_realloc(_lvm_errmsg, + strlen(_lvm_errmsg) + + strlen(message) + 2))) { + _lvm_errmsg = strcat(newbuf, "\n"); + _lvm_errmsg = strcat(newbuf, message); + } + } + + if (_lvm2_log_fn) { + _lvm2_log_fn(level, file, line, 0, message); return; } diff --git a/lib/log/lvm-logging.h b/lib/log/lvm-logging.h index d267e2336..a0933dd10 100644 --- a/lib/log/lvm-logging.h +++ b/lib/log/lvm-logging.h @@ -16,15 +16,16 @@ #ifndef _LVM_LOGGING_H #define _LVM_LOGGING_H -void print_log(int level, const char *file, int line, const char *format, ...) - __attribute__ ((format(printf, 4, 5))); +void print_log(int level, const char *file, int line, int dm_errno, + const char *format, ...) + __attribute__ ((format(printf, 5, 6))); -#define LOG_LINE(l, x...) print_log(l, __FILE__, __LINE__ , ## x) +#define LOG_LINE(l, x...) print_log(l, __FILE__, __LINE__ , 0, ## x) #include "log.h" typedef void (*lvm2_log_fn_t) (int level, const char *file, int line, - const char *message); + int dm_errno, const char *message); void init_log_fn(lvm2_log_fn_t log_fn); @@ -42,6 +43,9 @@ void init_syslog(int facility); void fin_syslog(void); int error_message_produced(void); +void reset_lvm_errno(int store_errmsg); +int lvm_errno(void); +const char *lvm_errmsg(void); /* Suppress messages to stdout/stderr (1) or everywhere (2) */ /* Returns previous setting */ diff --git a/po/pogen.h b/po/pogen.h index 6ab815451..66940b97a 100644 --- a/po/pogen.h +++ b/po/pogen.h @@ -19,8 +19,8 @@ * different architectures. */ -#define print_log(level, file, line, format, args...) print_log(format, args) +#define print_log(level, dm_errno, file, line, format, args...) print_log(format, args) #define dm_log(level, file, line, format, args...) dm_log(format, args) -#define dm_log_with_errno(level, file, line, format, dm_errno, args...) \ - dm_log(format, args) +#define dm_log_with_errno(level, dm_errno, file, line, format, args...) \ + dm_log(level, file, line, format, args) diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index efd996aee..33e549b1c 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -1054,6 +1054,8 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) */ dm_pool_empty(cmd->mem); + reset_lvm_errno(1); + return ret; }