1987da915Sopenharmony_ci/** 2987da915Sopenharmony_ci * logging.c - Centralised logging. Originated from the Linux-NTFS project. 3987da915Sopenharmony_ci * 4987da915Sopenharmony_ci * Copyright (c) 2005 Richard Russon 5987da915Sopenharmony_ci * Copyright (c) 2005-2008 Szabolcs Szakacsits 6987da915Sopenharmony_ci * Copyright (c) 2010 Jean-Pierre Andre 7987da915Sopenharmony_ci * 8987da915Sopenharmony_ci * This program/include file is free software; you can redistribute it and/or 9987da915Sopenharmony_ci * modify it under the terms of the GNU General Public License as published 10987da915Sopenharmony_ci * by the Free Software Foundation; either version 2 of the License, or 11987da915Sopenharmony_ci * (at your option) any later version. 12987da915Sopenharmony_ci * 13987da915Sopenharmony_ci * This program/include file is distributed in the hope that it will be 14987da915Sopenharmony_ci * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15987da915Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16987da915Sopenharmony_ci * GNU General Public License for more details. 17987da915Sopenharmony_ci * 18987da915Sopenharmony_ci * You should have received a copy of the GNU General Public License 19987da915Sopenharmony_ci * along with this program (in the main directory of the NTFS-3G 20987da915Sopenharmony_ci * distribution in the file COPYING); if not, write to the Free Software 21987da915Sopenharmony_ci * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22987da915Sopenharmony_ci */ 23987da915Sopenharmony_ci 24987da915Sopenharmony_ci#ifdef HAVE_CONFIG_H 25987da915Sopenharmony_ci#include "config.h" 26987da915Sopenharmony_ci#endif 27987da915Sopenharmony_ci 28987da915Sopenharmony_ci#ifdef HAVE_STDIO_H 29987da915Sopenharmony_ci#include <stdio.h> 30987da915Sopenharmony_ci#endif 31987da915Sopenharmony_ci#ifdef HAVE_ERRNO_H 32987da915Sopenharmony_ci#include <errno.h> 33987da915Sopenharmony_ci#endif 34987da915Sopenharmony_ci#ifdef HAVE_STDARG_H 35987da915Sopenharmony_ci#include <stdarg.h> 36987da915Sopenharmony_ci#endif 37987da915Sopenharmony_ci#ifdef HAVE_STRING_H 38987da915Sopenharmony_ci#include <string.h> 39987da915Sopenharmony_ci#endif 40987da915Sopenharmony_ci#ifdef HAVE_STDLIB_H 41987da915Sopenharmony_ci#include <stdlib.h> 42987da915Sopenharmony_ci#endif 43987da915Sopenharmony_ci#ifdef HAVE_SYSLOG_H 44987da915Sopenharmony_ci#include <syslog.h> 45987da915Sopenharmony_ci#endif 46987da915Sopenharmony_ci 47987da915Sopenharmony_ci#include "logging.h" 48987da915Sopenharmony_ci#include "misc.h" 49987da915Sopenharmony_ci 50987da915Sopenharmony_ci#ifndef PATH_SEP 51987da915Sopenharmony_ci#define PATH_SEP '/' 52987da915Sopenharmony_ci#endif 53987da915Sopenharmony_ci 54987da915Sopenharmony_ci#ifdef DEBUG 55987da915Sopenharmony_cistatic int tab; 56987da915Sopenharmony_ci#endif 57987da915Sopenharmony_ci 58987da915Sopenharmony_ci/* Some gcc 3.x, 4.[01].X crash with internal compiler error. */ 59987da915Sopenharmony_ci#if __GNUC__ <= 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 1) 60987da915Sopenharmony_ci# define BROKEN_GCC_FORMAT_ATTRIBUTE 61987da915Sopenharmony_ci#else 62987da915Sopenharmony_ci# define BROKEN_GCC_FORMAT_ATTRIBUTE __attribute__((format(printf, 6, 0))) 63987da915Sopenharmony_ci#endif 64987da915Sopenharmony_ci 65987da915Sopenharmony_ci/** 66987da915Sopenharmony_ci * struct ntfs_logging - Control info for the logging system 67987da915Sopenharmony_ci * @levels: Bitfield of logging levels 68987da915Sopenharmony_ci * @flags: Flags which affect the output style 69987da915Sopenharmony_ci * @handler: Function to perform the actual logging 70987da915Sopenharmony_ci */ 71987da915Sopenharmony_cistruct ntfs_logging { 72987da915Sopenharmony_ci u32 levels; 73987da915Sopenharmony_ci u32 flags; 74987da915Sopenharmony_ci ntfs_log_handler *handler BROKEN_GCC_FORMAT_ATTRIBUTE; 75987da915Sopenharmony_ci}; 76987da915Sopenharmony_ci 77987da915Sopenharmony_ci/** 78987da915Sopenharmony_ci * ntfs_log 79987da915Sopenharmony_ci * This struct controls all the logging within the library and tools. 80987da915Sopenharmony_ci */ 81987da915Sopenharmony_cistatic struct ntfs_logging ntfs_log = { 82987da915Sopenharmony_ci#ifdef DEBUG 83987da915Sopenharmony_ci NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER | 84987da915Sopenharmony_ci NTFS_LOG_LEVEL_LEAVE | 85987da915Sopenharmony_ci#endif 86987da915Sopenharmony_ci NTFS_LOG_LEVEL_INFO | NTFS_LOG_LEVEL_QUIET | NTFS_LOG_LEVEL_WARNING | 87987da915Sopenharmony_ci NTFS_LOG_LEVEL_ERROR | NTFS_LOG_LEVEL_PERROR | NTFS_LOG_LEVEL_CRITICAL | 88987da915Sopenharmony_ci NTFS_LOG_LEVEL_PROGRESS, 89987da915Sopenharmony_ci NTFS_LOG_FLAG_ONLYNAME, 90987da915Sopenharmony_ci#ifdef DEBUG 91987da915Sopenharmony_ci ntfs_log_handler_outerr 92987da915Sopenharmony_ci#else 93987da915Sopenharmony_ci ntfs_log_handler_null 94987da915Sopenharmony_ci#endif 95987da915Sopenharmony_ci}; 96987da915Sopenharmony_ci 97987da915Sopenharmony_ci 98987da915Sopenharmony_ci/** 99987da915Sopenharmony_ci * ntfs_log_get_levels - Get a list of the current logging levels 100987da915Sopenharmony_ci * 101987da915Sopenharmony_ci * Find out which logging levels are enabled. 102987da915Sopenharmony_ci * 103987da915Sopenharmony_ci * Returns: Log levels in a 32-bit field 104987da915Sopenharmony_ci */ 105987da915Sopenharmony_ciu32 ntfs_log_get_levels(void) 106987da915Sopenharmony_ci{ 107987da915Sopenharmony_ci return ntfs_log.levels; 108987da915Sopenharmony_ci} 109987da915Sopenharmony_ci 110987da915Sopenharmony_ci/** 111987da915Sopenharmony_ci * ntfs_log_set_levels - Enable extra logging levels 112987da915Sopenharmony_ci * @levels: 32-bit field of log levels to set 113987da915Sopenharmony_ci * 114987da915Sopenharmony_ci * Enable one or more logging levels. 115987da915Sopenharmony_ci * The logging levels are named: NTFS_LOG_LEVEL_*. 116987da915Sopenharmony_ci * 117987da915Sopenharmony_ci * Returns: Log levels that were enabled before the call 118987da915Sopenharmony_ci */ 119987da915Sopenharmony_ciu32 ntfs_log_set_levels(u32 levels) 120987da915Sopenharmony_ci{ 121987da915Sopenharmony_ci u32 old; 122987da915Sopenharmony_ci old = ntfs_log.levels; 123987da915Sopenharmony_ci ntfs_log.levels |= levels; 124987da915Sopenharmony_ci return old; 125987da915Sopenharmony_ci} 126987da915Sopenharmony_ci 127987da915Sopenharmony_ci/** 128987da915Sopenharmony_ci * ntfs_log_clear_levels - Disable some logging levels 129987da915Sopenharmony_ci * @levels: 32-bit field of log levels to clear 130987da915Sopenharmony_ci * 131987da915Sopenharmony_ci * Disable one or more logging levels. 132987da915Sopenharmony_ci * The logging levels are named: NTFS_LOG_LEVEL_*. 133987da915Sopenharmony_ci * 134987da915Sopenharmony_ci * Returns: Log levels that were enabled before the call 135987da915Sopenharmony_ci */ 136987da915Sopenharmony_ciu32 ntfs_log_clear_levels(u32 levels) 137987da915Sopenharmony_ci{ 138987da915Sopenharmony_ci u32 old; 139987da915Sopenharmony_ci old = ntfs_log.levels; 140987da915Sopenharmony_ci ntfs_log.levels &= (~levels); 141987da915Sopenharmony_ci return old; 142987da915Sopenharmony_ci} 143987da915Sopenharmony_ci 144987da915Sopenharmony_ci 145987da915Sopenharmony_ci/** 146987da915Sopenharmony_ci * ntfs_log_get_flags - Get a list of logging style flags 147987da915Sopenharmony_ci * 148987da915Sopenharmony_ci * Find out which logging flags are enabled. 149987da915Sopenharmony_ci * 150987da915Sopenharmony_ci * Returns: Logging flags in a 32-bit field 151987da915Sopenharmony_ci */ 152987da915Sopenharmony_ciu32 ntfs_log_get_flags(void) 153987da915Sopenharmony_ci{ 154987da915Sopenharmony_ci return ntfs_log.flags; 155987da915Sopenharmony_ci} 156987da915Sopenharmony_ci 157987da915Sopenharmony_ci/** 158987da915Sopenharmony_ci * ntfs_log_set_flags - Enable extra logging style flags 159987da915Sopenharmony_ci * @flags: 32-bit field of logging flags to set 160987da915Sopenharmony_ci * 161987da915Sopenharmony_ci * Enable one or more logging flags. 162987da915Sopenharmony_ci * The log flags are named: NTFS_LOG_LEVEL_*. 163987da915Sopenharmony_ci * 164987da915Sopenharmony_ci * Returns: Logging flags that were enabled before the call 165987da915Sopenharmony_ci */ 166987da915Sopenharmony_ciu32 ntfs_log_set_flags(u32 flags) 167987da915Sopenharmony_ci{ 168987da915Sopenharmony_ci u32 old; 169987da915Sopenharmony_ci old = ntfs_log.flags; 170987da915Sopenharmony_ci ntfs_log.flags |= flags; 171987da915Sopenharmony_ci return old; 172987da915Sopenharmony_ci} 173987da915Sopenharmony_ci 174987da915Sopenharmony_ci/** 175987da915Sopenharmony_ci * ntfs_log_clear_flags - Disable some logging styles 176987da915Sopenharmony_ci * @flags: 32-bit field of logging flags to clear 177987da915Sopenharmony_ci * 178987da915Sopenharmony_ci * Disable one or more logging flags. 179987da915Sopenharmony_ci * The log flags are named: NTFS_LOG_LEVEL_*. 180987da915Sopenharmony_ci * 181987da915Sopenharmony_ci * Returns: Logging flags that were enabled before the call 182987da915Sopenharmony_ci */ 183987da915Sopenharmony_ciu32 ntfs_log_clear_flags(u32 flags) 184987da915Sopenharmony_ci{ 185987da915Sopenharmony_ci u32 old; 186987da915Sopenharmony_ci old = ntfs_log.flags; 187987da915Sopenharmony_ci ntfs_log.flags &= (~flags); 188987da915Sopenharmony_ci return old; 189987da915Sopenharmony_ci} 190987da915Sopenharmony_ci 191987da915Sopenharmony_ci 192987da915Sopenharmony_ci/** 193987da915Sopenharmony_ci * ntfs_log_get_stream - Default output streams for logging levels 194987da915Sopenharmony_ci * @level: Log level 195987da915Sopenharmony_ci * 196987da915Sopenharmony_ci * By default, urgent messages are sent to "stderr". 197987da915Sopenharmony_ci * Other messages are sent to "stdout". 198987da915Sopenharmony_ci * 199987da915Sopenharmony_ci * Returns: "string" Prefix to be used 200987da915Sopenharmony_ci */ 201987da915Sopenharmony_cistatic FILE * ntfs_log_get_stream(u32 level) 202987da915Sopenharmony_ci{ 203987da915Sopenharmony_ci FILE *stream; 204987da915Sopenharmony_ci 205987da915Sopenharmony_ci switch (level) { 206987da915Sopenharmony_ci case NTFS_LOG_LEVEL_INFO: 207987da915Sopenharmony_ci case NTFS_LOG_LEVEL_QUIET: 208987da915Sopenharmony_ci case NTFS_LOG_LEVEL_PROGRESS: 209987da915Sopenharmony_ci case NTFS_LOG_LEVEL_VERBOSE: 210987da915Sopenharmony_ci stream = stdout; 211987da915Sopenharmony_ci break; 212987da915Sopenharmony_ci 213987da915Sopenharmony_ci case NTFS_LOG_LEVEL_DEBUG: 214987da915Sopenharmony_ci case NTFS_LOG_LEVEL_TRACE: 215987da915Sopenharmony_ci case NTFS_LOG_LEVEL_ENTER: 216987da915Sopenharmony_ci case NTFS_LOG_LEVEL_LEAVE: 217987da915Sopenharmony_ci case NTFS_LOG_LEVEL_WARNING: 218987da915Sopenharmony_ci case NTFS_LOG_LEVEL_ERROR: 219987da915Sopenharmony_ci case NTFS_LOG_LEVEL_CRITICAL: 220987da915Sopenharmony_ci case NTFS_LOG_LEVEL_PERROR: 221987da915Sopenharmony_ci default: 222987da915Sopenharmony_ci stream = stderr; 223987da915Sopenharmony_ci break; 224987da915Sopenharmony_ci } 225987da915Sopenharmony_ci 226987da915Sopenharmony_ci return stream; 227987da915Sopenharmony_ci} 228987da915Sopenharmony_ci 229987da915Sopenharmony_ci/** 230987da915Sopenharmony_ci * ntfs_log_get_prefix - Default prefixes for logging levels 231987da915Sopenharmony_ci * @level: Log level to be prefixed 232987da915Sopenharmony_ci * 233987da915Sopenharmony_ci * Prefixing the logging output can make it easier to parse. 234987da915Sopenharmony_ci * 235987da915Sopenharmony_ci * Returns: "string" Prefix to be used 236987da915Sopenharmony_ci */ 237987da915Sopenharmony_cistatic const char * ntfs_log_get_prefix(u32 level) 238987da915Sopenharmony_ci{ 239987da915Sopenharmony_ci const char *prefix; 240987da915Sopenharmony_ci 241987da915Sopenharmony_ci switch (level) { 242987da915Sopenharmony_ci case NTFS_LOG_LEVEL_DEBUG: 243987da915Sopenharmony_ci prefix = "DEBUG: "; 244987da915Sopenharmony_ci break; 245987da915Sopenharmony_ci case NTFS_LOG_LEVEL_TRACE: 246987da915Sopenharmony_ci prefix = "TRACE: "; 247987da915Sopenharmony_ci break; 248987da915Sopenharmony_ci case NTFS_LOG_LEVEL_QUIET: 249987da915Sopenharmony_ci prefix = "QUIET: "; 250987da915Sopenharmony_ci break; 251987da915Sopenharmony_ci case NTFS_LOG_LEVEL_INFO: 252987da915Sopenharmony_ci prefix = "INFO: "; 253987da915Sopenharmony_ci break; 254987da915Sopenharmony_ci case NTFS_LOG_LEVEL_VERBOSE: 255987da915Sopenharmony_ci prefix = "VERBOSE: "; 256987da915Sopenharmony_ci break; 257987da915Sopenharmony_ci case NTFS_LOG_LEVEL_PROGRESS: 258987da915Sopenharmony_ci prefix = "PROGRESS: "; 259987da915Sopenharmony_ci break; 260987da915Sopenharmony_ci case NTFS_LOG_LEVEL_WARNING: 261987da915Sopenharmony_ci prefix = "WARNING: "; 262987da915Sopenharmony_ci break; 263987da915Sopenharmony_ci case NTFS_LOG_LEVEL_ERROR: 264987da915Sopenharmony_ci prefix = "ERROR: "; 265987da915Sopenharmony_ci break; 266987da915Sopenharmony_ci case NTFS_LOG_LEVEL_PERROR: 267987da915Sopenharmony_ci prefix = "ERROR: "; 268987da915Sopenharmony_ci break; 269987da915Sopenharmony_ci case NTFS_LOG_LEVEL_CRITICAL: 270987da915Sopenharmony_ci prefix = "CRITICAL: "; 271987da915Sopenharmony_ci break; 272987da915Sopenharmony_ci default: 273987da915Sopenharmony_ci prefix = ""; 274987da915Sopenharmony_ci break; 275987da915Sopenharmony_ci } 276987da915Sopenharmony_ci 277987da915Sopenharmony_ci return prefix; 278987da915Sopenharmony_ci} 279987da915Sopenharmony_ci 280987da915Sopenharmony_ci 281987da915Sopenharmony_ci/** 282987da915Sopenharmony_ci * ntfs_log_set_handler - Provide an alternate logging handler 283987da915Sopenharmony_ci * @handler: function to perform the logging 284987da915Sopenharmony_ci * 285987da915Sopenharmony_ci * This alternate handler will be called for all future logging requests. 286987da915Sopenharmony_ci * If no @handler is specified, logging will revert to the default handler. 287987da915Sopenharmony_ci */ 288987da915Sopenharmony_civoid ntfs_log_set_handler(ntfs_log_handler *handler) 289987da915Sopenharmony_ci{ 290987da915Sopenharmony_ci if (handler) { 291987da915Sopenharmony_ci ntfs_log.handler = handler; 292987da915Sopenharmony_ci#ifdef HAVE_SYSLOG_H 293987da915Sopenharmony_ci if (handler == ntfs_log_handler_syslog) 294987da915Sopenharmony_ci openlog("ntfs-3g", LOG_PID, LOG_USER); 295987da915Sopenharmony_ci#endif 296987da915Sopenharmony_ci } else 297987da915Sopenharmony_ci ntfs_log.handler = ntfs_log_handler_null; 298987da915Sopenharmony_ci} 299987da915Sopenharmony_ci 300987da915Sopenharmony_ci/** 301987da915Sopenharmony_ci * ntfs_log_redirect - Pass on the request to the real handler 302987da915Sopenharmony_ci * @function: Function in which the log line occurred 303987da915Sopenharmony_ci * @file: File in which the log line occurred 304987da915Sopenharmony_ci * @line: Line number on which the log line occurred 305987da915Sopenharmony_ci * @level: Level at which the line is logged 306987da915Sopenharmony_ci * @data: User specified data, possibly specific to a handler 307987da915Sopenharmony_ci * @format: printf-style formatting string 308987da915Sopenharmony_ci * @...: Arguments to be formatted 309987da915Sopenharmony_ci * 310987da915Sopenharmony_ci * This is just a redirector function. The arguments are simply passed to the 311987da915Sopenharmony_ci * main logging handler (as defined in the global logging struct @ntfs_log). 312987da915Sopenharmony_ci * 313987da915Sopenharmony_ci * Returns: -1 Error occurred 314987da915Sopenharmony_ci * 0 Message wasn't logged 315987da915Sopenharmony_ci * num Number of output characters 316987da915Sopenharmony_ci */ 317987da915Sopenharmony_ciint ntfs_log_redirect(const char *function, const char *file, 318987da915Sopenharmony_ci int line, u32 level, void *data, const char *format, ...) 319987da915Sopenharmony_ci{ 320987da915Sopenharmony_ci int olderr = errno; 321987da915Sopenharmony_ci int ret; 322987da915Sopenharmony_ci va_list args; 323987da915Sopenharmony_ci 324987da915Sopenharmony_ci if (!(ntfs_log.levels & level)) /* Don't log this message */ 325987da915Sopenharmony_ci return 0; 326987da915Sopenharmony_ci 327987da915Sopenharmony_ci va_start(args, format); 328987da915Sopenharmony_ci errno = olderr; 329987da915Sopenharmony_ci ret = ntfs_log.handler(function, file, line, level, data, format, args); 330987da915Sopenharmony_ci va_end(args); 331987da915Sopenharmony_ci 332987da915Sopenharmony_ci errno = olderr; 333987da915Sopenharmony_ci return ret; 334987da915Sopenharmony_ci} 335987da915Sopenharmony_ci 336987da915Sopenharmony_ci 337987da915Sopenharmony_ci/** 338987da915Sopenharmony_ci * ntfs_log_handler_syslog - syslog logging handler 339987da915Sopenharmony_ci * @function: Function in which the log line occurred 340987da915Sopenharmony_ci * @file: File in which the log line occurred 341987da915Sopenharmony_ci * @line: Line number on which the log line occurred 342987da915Sopenharmony_ci * @level: Level at which the line is logged 343987da915Sopenharmony_ci * @data: User specified data, possibly specific to a handler 344987da915Sopenharmony_ci * @format: printf-style formatting string 345987da915Sopenharmony_ci * @args: Arguments to be formatted 346987da915Sopenharmony_ci * 347987da915Sopenharmony_ci * A simple syslog logging handler. Ignores colors. 348987da915Sopenharmony_ci * 349987da915Sopenharmony_ci * Returns: -1 Error occurred 350987da915Sopenharmony_ci * 0 Message wasn't logged 351987da915Sopenharmony_ci * num Number of output characters 352987da915Sopenharmony_ci */ 353987da915Sopenharmony_ci 354987da915Sopenharmony_ci 355987da915Sopenharmony_ci#ifdef HAVE_SYSLOG_H 356987da915Sopenharmony_ci 357987da915Sopenharmony_ci#define LOG_LINE_LEN 512 358987da915Sopenharmony_ci 359987da915Sopenharmony_ciint ntfs_log_handler_syslog(const char *function __attribute__((unused)), 360987da915Sopenharmony_ci const char *file __attribute__((unused)), 361987da915Sopenharmony_ci int line __attribute__((unused)), u32 level, 362987da915Sopenharmony_ci void *data __attribute__((unused)), 363987da915Sopenharmony_ci const char *format, va_list args) 364987da915Sopenharmony_ci{ 365987da915Sopenharmony_ci char logbuf[LOG_LINE_LEN]; 366987da915Sopenharmony_ci int ret, olderr = errno; 367987da915Sopenharmony_ci 368987da915Sopenharmony_ci#ifndef DEBUG 369987da915Sopenharmony_ci if ((level & NTFS_LOG_LEVEL_PERROR) && errno == ENOSPC) 370987da915Sopenharmony_ci return 1; 371987da915Sopenharmony_ci#endif 372987da915Sopenharmony_ci ret = vsnprintf(logbuf, LOG_LINE_LEN, format, args); 373987da915Sopenharmony_ci if (ret < 0) { 374987da915Sopenharmony_ci vsyslog(LOG_NOTICE, format, args); 375987da915Sopenharmony_ci ret = 1; 376987da915Sopenharmony_ci goto out; 377987da915Sopenharmony_ci } 378987da915Sopenharmony_ci 379987da915Sopenharmony_ci if ((LOG_LINE_LEN > ret + 3) && (level & NTFS_LOG_LEVEL_PERROR)) { 380987da915Sopenharmony_ci strncat(logbuf, ": ", LOG_LINE_LEN - ret - 1); 381987da915Sopenharmony_ci strncat(logbuf, strerror(olderr), LOG_LINE_LEN - (ret + 3)); 382987da915Sopenharmony_ci ret = strlen(logbuf); 383987da915Sopenharmony_ci } 384987da915Sopenharmony_ci 385987da915Sopenharmony_ci syslog(LOG_NOTICE, "%s", logbuf); 386987da915Sopenharmony_ciout: 387987da915Sopenharmony_ci errno = olderr; 388987da915Sopenharmony_ci return ret; 389987da915Sopenharmony_ci} 390987da915Sopenharmony_ci#endif 391987da915Sopenharmony_ci 392987da915Sopenharmony_ci/* 393987da915Sopenharmony_ci * Early logging before the logs are redirected 394987da915Sopenharmony_ci * 395987da915Sopenharmony_ci * (not quite satisfactory : this appears before the ntfs-g banner, 396987da915Sopenharmony_ci * and with a different pid) 397987da915Sopenharmony_ci */ 398987da915Sopenharmony_ci 399987da915Sopenharmony_civoid ntfs_log_early_error(const char *format, ...) 400987da915Sopenharmony_ci{ 401987da915Sopenharmony_ci va_list args; 402987da915Sopenharmony_ci 403987da915Sopenharmony_ci va_start(args, format); 404987da915Sopenharmony_ci#ifdef HAVE_SYSLOG_H 405987da915Sopenharmony_ci openlog("ntfs-3g", LOG_PID, LOG_USER); 406987da915Sopenharmony_ci ntfs_log_handler_syslog(NULL, NULL, 0, 407987da915Sopenharmony_ci NTFS_LOG_LEVEL_ERROR, NULL, 408987da915Sopenharmony_ci format, args); 409987da915Sopenharmony_ci#else 410987da915Sopenharmony_ci vfprintf(stderr,format,args); 411987da915Sopenharmony_ci#endif 412987da915Sopenharmony_ci va_end(args); 413987da915Sopenharmony_ci} 414987da915Sopenharmony_ci 415987da915Sopenharmony_ci/** 416987da915Sopenharmony_ci * ntfs_log_handler_fprintf - Basic logging handler 417987da915Sopenharmony_ci * @function: Function in which the log line occurred 418987da915Sopenharmony_ci * @file: File in which the log line occurred 419987da915Sopenharmony_ci * @line: Line number on which the log line occurred 420987da915Sopenharmony_ci * @level: Level at which the line is logged 421987da915Sopenharmony_ci * @data: User specified data, possibly specific to a handler 422987da915Sopenharmony_ci * @format: printf-style formatting string 423987da915Sopenharmony_ci * @args: Arguments to be formatted 424987da915Sopenharmony_ci * 425987da915Sopenharmony_ci * A simple logging handler. This is where the log line is finally displayed. 426987da915Sopenharmony_ci * It is more likely that you will want to set the handler to either 427987da915Sopenharmony_ci * ntfs_log_handler_outerr or ntfs_log_handler_stderr. 428987da915Sopenharmony_ci * 429987da915Sopenharmony_ci * Note: For this handler, @data is a pointer to a FILE output stream. 430987da915Sopenharmony_ci * If @data is NULL, nothing will be displayed. 431987da915Sopenharmony_ci * 432987da915Sopenharmony_ci * Returns: -1 Error occurred 433987da915Sopenharmony_ci * 0 Message wasn't logged 434987da915Sopenharmony_ci * num Number of output characters 435987da915Sopenharmony_ci */ 436987da915Sopenharmony_ciint ntfs_log_handler_fprintf(const char *function, const char *file, 437987da915Sopenharmony_ci int line, u32 level, void *data, const char *format, va_list args) 438987da915Sopenharmony_ci{ 439987da915Sopenharmony_ci#ifdef DEBUG 440987da915Sopenharmony_ci int i; 441987da915Sopenharmony_ci#endif 442987da915Sopenharmony_ci int ret = 0; 443987da915Sopenharmony_ci int olderr = errno; 444987da915Sopenharmony_ci FILE *stream; 445987da915Sopenharmony_ci 446987da915Sopenharmony_ci if (!data) /* Interpret data as a FILE stream. */ 447987da915Sopenharmony_ci return 0; /* If it's NULL, we can't do anything. */ 448987da915Sopenharmony_ci stream = (FILE*)data; 449987da915Sopenharmony_ci 450987da915Sopenharmony_ci#ifdef DEBUG 451987da915Sopenharmony_ci if (level == NTFS_LOG_LEVEL_LEAVE) { 452987da915Sopenharmony_ci if (tab) 453987da915Sopenharmony_ci tab--; 454987da915Sopenharmony_ci return 0; 455987da915Sopenharmony_ci } 456987da915Sopenharmony_ci 457987da915Sopenharmony_ci for (i = 0; i < tab; i++) 458987da915Sopenharmony_ci ret += fprintf(stream, " "); 459987da915Sopenharmony_ci#endif 460987da915Sopenharmony_ci if ((ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME) && 461987da915Sopenharmony_ci (strchr(file, PATH_SEP))) /* Abbreviate the filename */ 462987da915Sopenharmony_ci file = strrchr(file, PATH_SEP) + 1; 463987da915Sopenharmony_ci 464987da915Sopenharmony_ci if (ntfs_log.flags & NTFS_LOG_FLAG_PREFIX) /* Prefix the output */ 465987da915Sopenharmony_ci ret += fprintf(stream, "%s", ntfs_log_get_prefix(level)); 466987da915Sopenharmony_ci 467987da915Sopenharmony_ci if (ntfs_log.flags & NTFS_LOG_FLAG_FILENAME) /* Source filename */ 468987da915Sopenharmony_ci ret += fprintf(stream, "%s ", file); 469987da915Sopenharmony_ci 470987da915Sopenharmony_ci if (ntfs_log.flags & NTFS_LOG_FLAG_LINE) /* Source line number */ 471987da915Sopenharmony_ci ret += fprintf(stream, "(%d) ", line); 472987da915Sopenharmony_ci 473987da915Sopenharmony_ci if ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) || /* Source function */ 474987da915Sopenharmony_ci (level & NTFS_LOG_LEVEL_TRACE) || (level & NTFS_LOG_LEVEL_ENTER)) 475987da915Sopenharmony_ci ret += fprintf(stream, "%s(): ", function); 476987da915Sopenharmony_ci 477987da915Sopenharmony_ci ret += vfprintf(stream, format, args); 478987da915Sopenharmony_ci 479987da915Sopenharmony_ci if (level & NTFS_LOG_LEVEL_PERROR) 480987da915Sopenharmony_ci ret += fprintf(stream, ": %s\n", strerror(olderr)); 481987da915Sopenharmony_ci 482987da915Sopenharmony_ci#ifdef DEBUG 483987da915Sopenharmony_ci if (level == NTFS_LOG_LEVEL_ENTER) 484987da915Sopenharmony_ci tab++; 485987da915Sopenharmony_ci#endif 486987da915Sopenharmony_ci fflush(stream); 487987da915Sopenharmony_ci errno = olderr; 488987da915Sopenharmony_ci return ret; 489987da915Sopenharmony_ci} 490987da915Sopenharmony_ci 491987da915Sopenharmony_ci/** 492987da915Sopenharmony_ci * ntfs_log_handler_null - Null logging handler (no output) 493987da915Sopenharmony_ci * @function: Function in which the log line occurred 494987da915Sopenharmony_ci * @file: File in which the log line occurred 495987da915Sopenharmony_ci * @line: Line number on which the log line occurred 496987da915Sopenharmony_ci * @level: Level at which the line is logged 497987da915Sopenharmony_ci * @data: User specified data, possibly specific to a handler 498987da915Sopenharmony_ci * @format: printf-style formatting string 499987da915Sopenharmony_ci * @args: Arguments to be formatted 500987da915Sopenharmony_ci * 501987da915Sopenharmony_ci * This handler produces no output. It provides a way to temporarily disable 502987da915Sopenharmony_ci * logging, without having to change the levels and flags. 503987da915Sopenharmony_ci * 504987da915Sopenharmony_ci * Returns: 0 Message wasn't logged 505987da915Sopenharmony_ci */ 506987da915Sopenharmony_ciint ntfs_log_handler_null(const char *function __attribute__((unused)), const char *file __attribute__((unused)), 507987da915Sopenharmony_ci int line __attribute__((unused)), u32 level __attribute__((unused)), void *data __attribute__((unused)), 508987da915Sopenharmony_ci const char *format __attribute__((unused)), va_list args __attribute__((unused))) 509987da915Sopenharmony_ci{ 510987da915Sopenharmony_ci return 0; 511987da915Sopenharmony_ci} 512987da915Sopenharmony_ci 513987da915Sopenharmony_ci/** 514987da915Sopenharmony_ci * ntfs_log_handler_stdout - All logs go to stdout 515987da915Sopenharmony_ci * @function: Function in which the log line occurred 516987da915Sopenharmony_ci * @file: File in which the log line occurred 517987da915Sopenharmony_ci * @line: Line number on which the log line occurred 518987da915Sopenharmony_ci * @level: Level at which the line is logged 519987da915Sopenharmony_ci * @data: User specified data, possibly specific to a handler 520987da915Sopenharmony_ci * @format: printf-style formatting string 521987da915Sopenharmony_ci * @args: Arguments to be formatted 522987da915Sopenharmony_ci * 523987da915Sopenharmony_ci * Display a log message to stdout. 524987da915Sopenharmony_ci * 525987da915Sopenharmony_ci * Note: For this handler, @data is a pointer to a FILE output stream. 526987da915Sopenharmony_ci * If @data is NULL, then stdout will be used. 527987da915Sopenharmony_ci * 528987da915Sopenharmony_ci * Note: This function calls ntfs_log_handler_fprintf to do the main work. 529987da915Sopenharmony_ci * 530987da915Sopenharmony_ci * Returns: -1 Error occurred 531987da915Sopenharmony_ci * 0 Message wasn't logged 532987da915Sopenharmony_ci * num Number of output characters 533987da915Sopenharmony_ci */ 534987da915Sopenharmony_ciint ntfs_log_handler_stdout(const char *function, const char *file, 535987da915Sopenharmony_ci int line, u32 level, void *data, const char *format, va_list args) 536987da915Sopenharmony_ci{ 537987da915Sopenharmony_ci if (!data) 538987da915Sopenharmony_ci data = stdout; 539987da915Sopenharmony_ci 540987da915Sopenharmony_ci return ntfs_log_handler_fprintf(function, file, line, level, data, format, args); 541987da915Sopenharmony_ci} 542987da915Sopenharmony_ci 543987da915Sopenharmony_ci/** 544987da915Sopenharmony_ci * ntfs_log_handler_outerr - Logs go to stdout/stderr depending on level 545987da915Sopenharmony_ci * @function: Function in which the log line occurred 546987da915Sopenharmony_ci * @file: File in which the log line occurred 547987da915Sopenharmony_ci * @line: Line number on which the log line occurred 548987da915Sopenharmony_ci * @level: Level at which the line is logged 549987da915Sopenharmony_ci * @data: User specified data, possibly specific to a handler 550987da915Sopenharmony_ci * @format: printf-style formatting string 551987da915Sopenharmony_ci * @args: Arguments to be formatted 552987da915Sopenharmony_ci * 553987da915Sopenharmony_ci * Display a log message. The output stream will be determined by the log 554987da915Sopenharmony_ci * level. 555987da915Sopenharmony_ci * 556987da915Sopenharmony_ci * Note: For this handler, @data is a pointer to a FILE output stream. 557987da915Sopenharmony_ci * If @data is NULL, the function ntfs_log_get_stream will be called 558987da915Sopenharmony_ci * 559987da915Sopenharmony_ci * Note: This function calls ntfs_log_handler_fprintf to do the main work. 560987da915Sopenharmony_ci * 561987da915Sopenharmony_ci * Returns: -1 Error occurred 562987da915Sopenharmony_ci * 0 Message wasn't logged 563987da915Sopenharmony_ci * num Number of output characters 564987da915Sopenharmony_ci */ 565987da915Sopenharmony_ciint ntfs_log_handler_outerr(const char *function, const char *file, 566987da915Sopenharmony_ci int line, u32 level, void *data, const char *format, va_list args) 567987da915Sopenharmony_ci{ 568987da915Sopenharmony_ci if (!data) 569987da915Sopenharmony_ci data = ntfs_log_get_stream(level); 570987da915Sopenharmony_ci 571987da915Sopenharmony_ci return ntfs_log_handler_fprintf(function, file, line, level, data, format, args); 572987da915Sopenharmony_ci} 573987da915Sopenharmony_ci 574987da915Sopenharmony_ci/** 575987da915Sopenharmony_ci * ntfs_log_handler_stderr - All logs go to stderr 576987da915Sopenharmony_ci * @function: Function in which the log line occurred 577987da915Sopenharmony_ci * @file: File in which the log line occurred 578987da915Sopenharmony_ci * @line: Line number on which the log line occurred 579987da915Sopenharmony_ci * @level: Level at which the line is logged 580987da915Sopenharmony_ci * @data: User specified data, possibly specific to a handler 581987da915Sopenharmony_ci * @format: printf-style formatting string 582987da915Sopenharmony_ci * @args: Arguments to be formatted 583987da915Sopenharmony_ci * 584987da915Sopenharmony_ci * Display a log message to stderr. 585987da915Sopenharmony_ci * 586987da915Sopenharmony_ci * Note: For this handler, @data is a pointer to a FILE output stream. 587987da915Sopenharmony_ci * If @data is NULL, then stdout will be used. 588987da915Sopenharmony_ci * 589987da915Sopenharmony_ci * Note: This function calls ntfs_log_handler_fprintf to do the main work. 590987da915Sopenharmony_ci * 591987da915Sopenharmony_ci * Returns: -1 Error occurred 592987da915Sopenharmony_ci * 0 Message wasn't logged 593987da915Sopenharmony_ci * num Number of output characters 594987da915Sopenharmony_ci */ 595987da915Sopenharmony_ciint ntfs_log_handler_stderr(const char *function, const char *file, 596987da915Sopenharmony_ci int line, u32 level, void *data, const char *format, va_list args) 597987da915Sopenharmony_ci{ 598987da915Sopenharmony_ci if (!data) 599987da915Sopenharmony_ci data = stderr; 600987da915Sopenharmony_ci 601987da915Sopenharmony_ci return ntfs_log_handler_fprintf(function, file, line, level, data, format, args); 602987da915Sopenharmony_ci} 603987da915Sopenharmony_ci 604987da915Sopenharmony_ci 605987da915Sopenharmony_ci/** 606987da915Sopenharmony_ci * ntfs_log_parse_option - Act upon command line options 607987da915Sopenharmony_ci * @option: Option flag 608987da915Sopenharmony_ci * 609987da915Sopenharmony_ci * Delegate some of the work of parsing the command line. All the options begin 610987da915Sopenharmony_ci * with "--log-". Options cause log levels to be enabled in @ntfs_log (the 611987da915Sopenharmony_ci * global logging structure). 612987da915Sopenharmony_ci * 613987da915Sopenharmony_ci * Note: The "colour" option changes the logging handler. 614987da915Sopenharmony_ci * 615987da915Sopenharmony_ci * Returns: TRUE Option understood 616987da915Sopenharmony_ci * FALSE Invalid log option 617987da915Sopenharmony_ci */ 618987da915Sopenharmony_ciBOOL ntfs_log_parse_option(const char *option) 619987da915Sopenharmony_ci{ 620987da915Sopenharmony_ci if (strcmp(option, "--log-debug") == 0) { 621987da915Sopenharmony_ci ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG); 622987da915Sopenharmony_ci return TRUE; 623987da915Sopenharmony_ci } else if (strcmp(option, "--log-verbose") == 0) { 624987da915Sopenharmony_ci ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); 625987da915Sopenharmony_ci return TRUE; 626987da915Sopenharmony_ci } else if (strcmp(option, "--log-quiet") == 0) { 627987da915Sopenharmony_ci ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); 628987da915Sopenharmony_ci return TRUE; 629987da915Sopenharmony_ci } else if (strcmp(option, "--log-trace") == 0) { 630987da915Sopenharmony_ci ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE); 631987da915Sopenharmony_ci return TRUE; 632987da915Sopenharmony_ci } 633987da915Sopenharmony_ci 634987da915Sopenharmony_ci ntfs_log_debug("Unknown logging option '%s'\n", option); 635987da915Sopenharmony_ci return FALSE; 636987da915Sopenharmony_ci} 637987da915Sopenharmony_ci 638