centralised logging system

edge.strict_endians
flatcap 2005-10-16 21:57:00 +00:00
parent 2436151e59
commit bde3e0063b
5 changed files with 575 additions and 0 deletions

View File

@ -139,6 +139,16 @@ if test "$enable_test" = "yes"; then
CFLAGS="$CFLAGS -DNTFS_TEST"
fi
AH_TEMPLATE([NTFS_DISABLE_DEBUG_LOGGING],
[Define this if you want to compile out the debug log messages.
This will reduce the size of the binaries.])
AC_ARG_ENABLE(debug-logging,
AS_HELP_STRING(--disable-debug-logging,Remove debug logging from the code),
if test "$enable_debug_logging" == "no"; then
AC_DEFINE(NTFS_DISABLE_DEBUG_LOGGING)
fi,
)
# Use GNU extensions if available.
AC_GNU_SOURCE

View File

@ -21,6 +21,7 @@ linux_ntfsinclude_HEADERS = \
lcnalloc.h \
list.h \
logfile.h \
logging.h \
mft.h \
mst.h \
runlist.h \

View File

@ -0,0 +1,114 @@
/*
* logging.h - Centralised logging. Part of the Linux-NTFS project.
*
* Copyright (c) 2005 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LOGGING_H_
#define _LOGGING_H_
#include "config.h"
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#include "types.h"
struct ntfs_logging;
/* Function prototype for the logging handlers */
typedef int (logging_handler) (const char *handler, const char *file, int line,
int level, FILE *stream, const char *format, va_list args);
/**
* struct ntfs_logging - Control info for the logging system
* @levels: Bitfield of logging levels
* @flags: Flags to affect the output style
* @handler: Function to perform the actual logging
*/
struct ntfs_logging {
u32 levels;
u32 flags;
logging_handler *handler;
};
extern struct ntfs_logging ntfs_log;
void ntfs_logging_set_handler (logging_handler *handler);
/* Enable/disable certain log levels */
u32 ntfs_logging_set_levels (u32 levels);
u32 ntfs_logging_clear_levels (u32 levels);
u32 ntfs_logging_get_levels (void);
/* Enable/disable certain log flags */
u32 ntfs_logging_set_flags (u32 flags);
u32 ntfs_logging_clear_flags (u32 flags);
u32 ntfs_logging_get_flags (void);
BOOL ntfs_logging_parse_option (const char *option);
int ntfs_logging_redirect (const char *handler, const char *file, int line,
int level, FILE *stream, const char *format, ...)
__attribute__ ((format (printf, 6, 7)));
/* Logging handlers */
logging_handler ntfs_logging_handler_printf __attribute__ ((format (printf, 6, 0)));
logging_handler ntfs_logging_handler_colour __attribute__ ((format (printf, 6, 0)));
/* Logging levels - Determine what gets logged */
#define LOG_LEVEL_DEBUG (1 << 0) /* x = 42 */
#define LOG_LEVEL_TRACE (1 << 1) /* Entering function x() */
#define LOG_LEVEL_QUIET (1 << 2) /* Quietable output */
#define LOG_LEVEL_INFO (1 << 3) /* Volume needs defragmenting */
#define LOG_LEVEL_VERBOSE (1 << 4) /* Forced to continue */
#define LOG_LEVEL_PROGRESS (1 << 5) /* 54% complete */
#define LOG_LEVEL_WARNING (1 << 6) /* You should backup before starting */
#define LOG_LEVEL_ERROR (1 << 7) /* Operation failed, no damage done */
#define LOG_LEVEL_PERROR (1 << 8) /* Message : standard error description */
#define LOG_LEVEL_CRITICAL (1 << 9) /* Operation failed,damage may have occurred */
/* Logging style flags - Manage the style of the output */
#define LOG_FLAG_PREFIX (1 << 0) /* Prefix messages with "ERROR: ", etc */
#define LOG_FLAG_FILENAME (1 << 1) /* Show the file origin of the message */
#define LOG_FLAG_LINE (1 << 2) /* Show the line number of the message */
#define LOG_FLAG_FUNCTION (1 << 3) /* Show the function name containing the message */
/* Macros to simplify logging. One for each level defined above.
* Note, if DEBUG isn't defined, then log_debug has no effect.
*/
#define log_crit(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_CRITICAL,NULL,FORMAT,##ARGS)
#define log_error(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_ERROR,NULL,FORMAT,##ARGS)
#define log_info(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_INFO,NULL,FORMAT,##ARGS)
#define log_perror(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_PERROR,NULL,FORMAT,##ARGS)
#define log_progress(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_PROGRESS,NULL,FORMAT,##ARGS)
#define log_quiet(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_QUIET,NULL,FORMAT,##ARGS)
#define log_verbose(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_VERBOSE,NULL,FORMAT,##ARGS)
#define log_warn(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_WARNING,NULL,FORMAT,##ARGS)
#ifdef NTFS_DISABLE_DEBUG_LOGGING
#define log_debug(FORMAT, ARGS...)do {} while (0)
#define log_trace(FORMAT, ARGS...)do {} while (0)
#else
#define log_debug(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_DEBUG,NULL,FORMAT,##ARGS)
#define log_trace(FORMAT, ARGS...) ntfs_logging_redirect (__FUNCTION__,__FILE__,__LINE__,LOG_LEVEL_TRACE,NULL,FORMAT,##ARGS)
#endif /* NTFS_DISABLE_DEBUG_LOGGING */
#endif /* _LOGGING_H_ */

View File

@ -51,6 +51,7 @@ libntfs_la_SOURCES = \
inode.c \
lcnalloc.c \
logfile.c \
logging.c \
mft.c \
mst.c \
runlist.c \

449
libntfs/logging.c 100644
View File

@ -0,0 +1,449 @@
/**
* logging.c - Centralised logging. Part of the Linux-NTFS project.
*
* Copyright (c) 2005 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "logging.h"
#ifndef PATH_SEP
#define PATH_SEP '/'
#endif
/**
* struct ntfs_logging
* This global struct controls all the logging within the library and tools.
*/
struct ntfs_logging ntfs_log =
{
#ifdef DEBUG
LOG_LEVEL_DEBUG | LOG_LEVEL_TRACE |
#endif
LOG_LEVEL_INFO | LOG_LEVEL_WARNING | LOG_LEVEL_ERROR | LOG_LEVEL_PERROR | LOG_LEVEL_CRITICAL,
LOG_FLAG_PREFIX,
ntfs_logging_handler_printf
};
/**
* ntfs_logging_get_levels - Get a list of the current logging levels
*
* Find out which logging levels are enabled.
*
* Returns: Log levels in a 32-bit field
*/
u32 ntfs_logging_get_levels (void)
{
return ntfs_log.levels;
}
/**
* ntfs_logging_set_levels - Enable extra logging levels
* @levels: 32-bit field of log levels to set
*
* Enable one or more logging levels.
* The logging levels are named: LOG_LEVEL_*.
*
* Returns: Log levels that were enabled before the call
*/
u32 ntfs_logging_set_levels (u32 levels)
{
u32 old;
old = ntfs_log.levels;
ntfs_log.levels |= levels;
return old;
}
/**
* ntfs_logging_clear_levels - Disable some logging levels
* @levels: 32-bit field of log levels to clear
*
* Disable one or more logging levels.
* The logging levels are named: LOG_LEVEL_*.
*
* Returns: Log levels that were enabled before the call
*/
u32 ntfs_logging_clear_levels (u32 levels)
{
u32 old;
old = ntfs_log.levels;
ntfs_log.levels &= (~levels);
return old;
}
/**
* ntfs_logging_get_flags - Get a list of logging style flags
*
* Find out which logging flags are enabled.
*
* Returns: Logging flags in a 32-bit field
*/
u32 ntfs_logging_get_flags (void)
{
return ntfs_log.flags;
}
/**
* ntfs_logging_set_flags - Enable extra logging style flags
* @flags: 32-bit field of logging flags to set
*
* Enable one or more logging flags.
* The log flags are named: LOG_LEVEL_*.
*
* Returns: Logging flags that were enabled before the call
*/
u32 ntfs_logging_set_flags (u32 flags)
{
u32 old;
old = ntfs_log.flags;
ntfs_log.flags |= flags;
return old;
}
/**
* ntfs_logging_clear_flags - Disable some logging styles
* @flags: 32-bit field of logging flags to clear
*
* Disable one or more logging flags.
* The log flags are named: LOG_LEVEL_*.
*
* Returns: Logging flags that were enabled before the call
*/
u32 ntfs_logging_clear_flags (u32 flags)
{
u32 old;
old = ntfs_log.flags;
ntfs_log.flags &= (~flags);
return old;
}
/**
* ntfs_logging_get_stream - Default output streams for logging levels
* @level: Log level
*
* By default, urgent messages are sent to "stderr".
* Other messages are sent to "stdout".
*
* Returns: "string" Prefix to be used
*/
static FILE * ntfs_logging_get_stream (int level)
{
FILE *stream;
switch (level) {
case LOG_LEVEL_INFO:
case LOG_LEVEL_QUIET:
case LOG_LEVEL_PROGRESS:
stream = stdout;
break;
case LOG_LEVEL_DEBUG:
case LOG_LEVEL_TRACE:
case LOG_LEVEL_WARNING:
case LOG_LEVEL_ERROR:
case LOG_LEVEL_CRITICAL:
case LOG_LEVEL_PERROR:
default:
stream = stderr;
break;
}
return stream;
}
/**
* ntfs_logging_get_prefix - Default prefixes for logging levels
* @level: Log level to be prefixed
*
* Prefixing the logging output can make it easier to parse.
*
* Returns: "string" Prefix to be used
*/
static const char * ntfs_logging_get_prefix (int level)
{
const char *prefix;
switch (level) {
case LOG_LEVEL_DEBUG:
prefix = "DEBUG: ";
break;
case LOG_LEVEL_TRACE:
prefix = "TRACE: ";
break;
case LOG_LEVEL_QUIET:
prefix = "QUIET: ";
break;
case LOG_LEVEL_INFO:
prefix = "INFO: ";
break;
case LOG_LEVEL_VERBOSE:
prefix = "VERBOSE: ";
break;
case LOG_LEVEL_PROGRESS:
prefix = "PROGRESS: ";
break;
case LOG_LEVEL_WARNING:
prefix = "WARNING: ";
break;
case LOG_LEVEL_ERROR:
prefix = "ERROR: ";
break;
case LOG_LEVEL_PERROR:
prefix = "ERROR: ";
break;
case LOG_LEVEL_CRITICAL:
prefix = "CRITICAL: ";
break;
default:
prefix = "";
break;
}
return prefix;
}
/**
* ntfs_logging_set_handler - Provide an alternate logging handler
* @handler: function to perform the logging
*
* This alternate handler will be called for all future logging requests.
* If no @handler is specified, logging will revert to the default handler.
*
* Returns: void
*/
void ntfs_logging_set_handler (logging_handler *handler)
{
if (handler)
ntfs_log.handler = handler;
else
ntfs_log.handler = ntfs_logging_handler_printf;
}
/**
* ntfs_logging_redirect - Pass on the request to the real handler
* @function: Function in which the log line occurred
* @file: File in which the log line occurred
* @line: Line number on which the log line occurred
* @level: Level at which the line is logged
* @stream: FILE stream to output to (may be NULL)
* @format: printf-style formatting string
* @...: Arguments to be formatted
*
* This is just a redirector function. The arguments are simply passed to the
* main logging handler (as defined in the global logging struct @ntfs_log).
*
* Note: If @stream is NULL, the output stream will be determined by the
* function: ntfs_logging_get_stream
*
* Returns: -1 Error occurred
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_logging_redirect (const char *function, const char *file,
int line, int level, FILE *stream, const char *format, ...)
{
int olderr = errno;
int ret;
va_list args;
if (!(ntfs_log.levels & level)) /* Don't log this message */
return 0;
va_start (args, format);
errno = olderr;
ret = ntfs_log.handler (function, file, line, level, stream, format, args);
va_end (args);
errno = olderr;
return ret;
}
/**
* ntfs_logging_handler_printf - Basic logging handler
* @function: Function in which the log line occurred
* @file: File in which the log line occurred
* @line: Line number on which the log line occurred
* @level: Level at which the line is logged
* @stream: FILE stream to output to (may be NULL)
* @format: printf-style formatting string
* @args: Arguments to be formatted
*
* A simple logging handler. This is where the log line is finally displayed.
*
* Note: If @stream is NULL, the output stream will be determined by the
* function: ntfs_logging_get_stream
*
* Returns: -1 Error occurred
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_logging_handler_printf (const char *function, const char *file,
int line, int level, FILE *stream, const char *format, va_list args)
{
int ret = 0;
int olderr = errno;
if (!stream)
stream = ntfs_logging_get_stream (level);
if (strchr (file, PATH_SEP)) /* Abbreviate the filename */
file = strrchr (file, PATH_SEP) + 1;
if (ntfs_log.flags & LOG_FLAG_PREFIX) /* Prefix the output */
ret += fprintf (stream, "%s", ntfs_logging_get_prefix (level));
if (ntfs_log.flags & LOG_FLAG_FILENAME) /* Source filename */
ret += fprintf (stream, "%s ", file);
if (ntfs_log.flags & LOG_FLAG_LINE) /* Source line number */
ret += fprintf (stream, "(%d) ", line);
if (ntfs_log.flags & LOG_FLAG_FUNCTION) /* Source function */
ret += fprintf (stream, ": %s : ", function);
if (level & LOG_LEVEL_PERROR) {
errno = olderr;
ret += fprintf (stream, "<%s> : ", strerror (olderr));
}
ret += vfprintf (stream, format, args);
errno = olderr;
return ret;
}
/**
* ntfs_logging_handler_colour - Colour-highlighting logging handler
* @function: Function in which the log line occurred
* @file: File in which the log line occurred
* @line: Line number on which the log line occurred
* @level: Level at which the line is logged
* @stream: FILE stream to output to (may be NULL)
* @format: printf-style formatting string
* @args: Arguments to be formatted
*
* This is a simple logging filter that prefixes/suffixes some logs.
* Warnings: yellow
* Errors: red
* Critical errors: red (inverse video)
*
* Note: This function calls ntfs_logging_handler_printf to do the main work.
*
* Note: If @stream is NULL, the output stream will be determined by the
* function: ntfs_logging_get_stream
*
* Returns: -1 Error occurred
* 0 Message wasn't logged
* num Number of output characters
*/
int ntfs_logging_handler_colour (const char *function, const char *file,
int line, int level, FILE *stream, const char *format, va_list args)
{
int ret = 0;
int olderr = errno;
const char *prefix = NULL;
const char *suffix = NULL;
const char *end = "\e[0m";
if (!stream)
stream = ntfs_logging_get_stream (level);
switch (level) {
case LOG_LEVEL_WARNING:
prefix = "\e[01;33m"; /* Yellow */
suffix = end;
break;
case LOG_LEVEL_ERROR:
case LOG_LEVEL_PERROR:
prefix = "\e[01;31m"; /* Red */
suffix = end;
break;
case LOG_LEVEL_CRITICAL:
prefix = "\e[01;07;31m"; /* Red, inverse */
suffix = end;
break;
}
if (prefix)
ret += fprintf (stream, prefix);
errno = olderr;
ret += ntfs_logging_handler_printf (function, file, line, level, stream, format, args);
if (suffix)
ret += fprintf (stream, suffix);
errno = olderr;
return ret;
}
/**
* ntfs_logging_parse_option - Act upon command line options
* @option: Option flag
*
* Delegate some of the work of parsing the command line. All the options begin
* with "--log-". Options cause log levels to be enabled in @ntfs_log (the
* global logging structure).
*
* Note: The "colour" option changes the logging handler.
*
* Returns: TRUE Option understood
* FALSE Invalid log option
*/
BOOL ntfs_logging_parse_option (const char *option)
{
if (strcmp (option, "--log-debug") == 0) {
ntfs_logging_set_levels (LOG_LEVEL_DEBUG);
return TRUE;
} else if (strcmp (option, "--log-verbose") == 0) {
ntfs_logging_set_levels (LOG_LEVEL_VERBOSE);
return TRUE;
} else if (strcmp (option, "--log-quiet") == 0) {
ntfs_logging_set_levels (LOG_LEVEL_QUIET);
return TRUE;
} else if (strcmp (option, "--log-trace") == 0) {
ntfs_logging_set_levels (LOG_LEVEL_TRACE);
return TRUE;
} else if ((strcmp (option, "--log-colour") == 0) ||
(strcmp (option, "--log-color") == 0)) {
ntfs_logging_set_handler (ntfs_logging_handler_colour);
return TRUE;
}
log_error ("Unknown logging option '%s'\n", option);
return FALSE;
}