2014-11-18 01:54:34 +00:00
|
|
|
/*
|
|
|
|
* CiderPress
|
|
|
|
* Copyright (C) 2014 by CiderPress authors. All Rights Reserved.
|
|
|
|
* See the file LICENSE for distribution terms.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Debug log support.
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
|
|
DebugLog::DebugLog(const WCHAR* logFile)
|
|
|
|
: fLogFp(NULL)
|
|
|
|
{
|
|
|
|
fPid = getpid();
|
|
|
|
|
|
|
|
if (logFile == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PathName debugPath(logFile);
|
|
|
|
time_t now = time(NULL);
|
|
|
|
time_t when = debugPath.GetModWhen();
|
|
|
|
if (when > 0 && now - when > kStaleLog) {
|
|
|
|
/* log file is more than 8 hours old, remove it */
|
|
|
|
/* [consider opening it and truncating with chsize() instead, so we
|
|
|
|
don't hose somebody's custom access permissions. ++ATM 20041015] */
|
|
|
|
_wunlink(logFile);
|
|
|
|
}
|
|
|
|
fLogFp = _wfopen(logFile, L"a");
|
2014-11-18 05:13:13 +00:00
|
|
|
if (fLogFp == NULL) {
|
2014-11-18 22:30:51 +00:00
|
|
|
#ifdef _DEBUG
|
2014-11-18 01:54:34 +00:00
|
|
|
_CrtDbgReport(_CRT_WARN, __FILE__, __LINE__, NULL,
|
|
|
|
"Unable to open %ls: %d\n", logFile, errno);
|
2014-11-18 22:30:51 +00:00
|
|
|
#endif
|
2014-11-18 01:54:34 +00:00
|
|
|
} else {
|
|
|
|
// disable buffering so we don't lose anything if app crashes
|
2014-11-18 05:13:13 +00:00
|
|
|
setvbuf(fLogFp, NULL, _IONBF, 0);
|
2014-11-18 01:54:34 +00:00
|
|
|
|
|
|
|
fprintf(fLogFp, "\n");
|
|
|
|
if (when > 0) {
|
|
|
|
fprintf(fLogFp,
|
|
|
|
"(Log file was %.3f hours old; logs are reset after %.3f)\n",
|
|
|
|
(now - when) / 3600.0, kStaleLog / 3600.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DebugLog::~DebugLog() {
|
|
|
|
if (fLogFp != NULL) {
|
|
|
|
fclose(fLogFp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DebugLog::Log(LogSeverity severity, const char* file, int line,
|
2014-11-19 22:54:24 +00:00
|
|
|
_Printf_format_string_ const char* format, ...)
|
2014-11-18 01:54:34 +00:00
|
|
|
{
|
2014-11-18 22:30:51 +00:00
|
|
|
#ifndef _DEBUG
|
|
|
|
if (fLogFp == NULL) {
|
|
|
|
// nothing to do, don't waste time formatting the string
|
2014-11-18 01:54:34 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-11-18 22:30:51 +00:00
|
|
|
#endif
|
2014-11-18 01:54:34 +00:00
|
|
|
|
|
|
|
static const char kSeverityChars[] = "?VDIWE";
|
|
|
|
if (severity < 0 || severity > sizeof(kSeverityChars) - 1) {
|
|
|
|
severity = LOG_UNKNOWN;
|
|
|
|
}
|
2014-12-02 06:07:39 +00:00
|
|
|
if (severity == LOG_VERBOSE) {
|
|
|
|
// Globally disable. They still get compiled, which helps to
|
|
|
|
// prevent bit-rot. TODO: be fancier and have LOGV map to
|
|
|
|
// a do-nothing inline function that the compiler will effectively
|
|
|
|
// eliminate.
|
|
|
|
return;
|
|
|
|
}
|
2014-11-18 01:54:34 +00:00
|
|
|
|
|
|
|
va_list argptr;
|
2014-11-18 21:05:15 +00:00
|
|
|
char textBuf[4096];
|
|
|
|
|
2014-11-18 01:54:34 +00:00
|
|
|
va_start(argptr, format);
|
2014-11-18 21:05:15 +00:00
|
|
|
_vsnprintf(textBuf, NELEM(textBuf) - 1, format, argptr);
|
|
|
|
va_end(argptr);
|
|
|
|
textBuf[NELEM(textBuf) - 1] = '\0';
|
2014-11-18 01:54:34 +00:00
|
|
|
|
2014-11-18 21:05:15 +00:00
|
|
|
if (fLogFp) {
|
|
|
|
struct tm tmbuf;
|
|
|
|
time_t now = time(NULL);
|
|
|
|
localtime_s(&tmbuf, &now);
|
|
|
|
|
2014-11-19 01:10:23 +00:00
|
|
|
// The pid is useful when we spawn a new instance of CiderPress
|
|
|
|
// to handle a disk image or NuFX archive inside an archive. The
|
|
|
|
// file is opened in "append" mode, so we shouldn't collide.
|
|
|
|
fprintf(fLogFp, "%02d:%02d:%02d %05u %c %s\n", tmbuf.tm_hour,
|
|
|
|
tmbuf.tm_min, tmbuf.tm_sec, fPid, kSeverityChars[severity],
|
2014-11-18 21:05:15 +00:00
|
|
|
textBuf);
|
|
|
|
}
|
2014-11-18 22:30:51 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
if (_CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", textBuf) == 1) {
|
|
|
|
// "retry" button causes a debugger break
|
|
|
|
_CrtDbgBreak();
|
2014-11-18 21:05:15 +00:00
|
|
|
}
|
2014-11-18 22:30:51 +00:00
|
|
|
#endif
|
2014-11-18 01:54:34 +00:00
|
|
|
}
|