1 // distribution boxbackup-0.11_trunk_2979 (svn version: 2979)
2 // Box Backup, http://www.boxbackup.org/
3 //
4 // Copyright (c) 2003-2010, Ben Summers and contributors.
5 // All rights reserved.
6 //
7 // Note that this project uses mixed licensing. Any file with this license
8 // attached, or where the code LICENSE-DUAL appears on the first line, falls
9 // under this license. See the file COPYING.txt for more information.
10 //
11 // This file is dual licensed. You may use and distribute it providing that you
12 // comply EITHER with the terms of the BSD license, OR the GPL license. It is
13 // not necessary to comply with both licenses, only one.
14 //
15 // The BSD license option follows:
16 //
17 // Redistribution and use in source and binary forms, with or without
18 // modification, are permitted provided that the following conditions are met:
19 //
20 // 1. Redistributions of source code must retain the above copyright
21 //    notice, this list of conditions and the following disclaimer.
22 //
23 // 2. Redistributions in binary form must reproduce the above copyright
24 //    notice, this list of conditions and the following disclaimer in the
25 //    documentation and/or other materials provided with the distribution.
26 //
27 // 3. Neither the name of the Box Backup nor the names of its contributors may
28 //    be used to endorse or promote products derived from this software without
29 //    specific prior written permission.
30 //
31 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
35 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 //
42 // [http://en.wikipedia.org/wiki/BSD_licenses#3-clause_license_.28.22New_BSD_License.22.29]
43 //
44 // The GPL license option follows:
45 //
46 // This program is free software; you can redistribute it and/or
47 // modify it under the terms of the GNU General Public License
48 // as published by the Free Software Foundation; either version 2
49 // of the License, or (at your option) any later version.
50 //
51 // This program is distributed in the hope that it will be useful,
52 // but WITHOUT ANY WARRANTY; without even the implied warranty of
53 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54 // GNU General Public License for more details.
55 //
56 // You should have received a copy of the GNU General Public License
57 // along with this program; if not, write to the Free Software
58 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
59 //
60 // [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC4]
61 // --------------------------------------------------------------------------
62 //
63 // File
64 //		Name:    Logging.h
65 //		Purpose: Generic logging core routines declarations and macros
66 //		Created: 2006/12/16
67 //
68 // --------------------------------------------------------------------------
69 
70 #ifndef LOGGING__H
71 #define LOGGING__H
72 
73 #include <cerrno>
74 #include <cstring>
75 #include <iomanip>
76 #include <sstream>
77 #include <vector>
78 
79 #include "FileStream.h"
80 
81 #define BOX_LOG(level, stuff) \
82 { \
83 	std::ostringstream _box_log_line; \
84 	_box_log_line << stuff; \
85 	Logging::Log(level, __FILE__, __LINE__, _box_log_line.str()); \
86 }
87 
88 #define BOX_SYSLOG(level, stuff) \
89 { \
90 	std::ostringstream _box_log_line; \
91 	_box_log_line << stuff; \
92 	Logging::LogToSyslog(level, __FILE__, __LINE__, _box_log_line.str()); \
93 }
94 
95 #define BOX_FATAL(stuff)   BOX_LOG(Log::FATAL,   stuff)
96 #define BOX_ERROR(stuff)   BOX_LOG(Log::ERROR,   stuff)
97 #define BOX_WARNING(stuff) BOX_LOG(Log::WARNING, stuff)
98 #define BOX_NOTICE(stuff)  BOX_LOG(Log::NOTICE,  stuff)
99 #define BOX_INFO(stuff)    BOX_LOG(Log::INFO,    stuff)
100 #define BOX_TRACE(stuff)   \
101 	if (Logging::IsEnabled(Log::TRACE)) \
102 	{ BOX_LOG(Log::TRACE, stuff) }
103 
104 #define BOX_SYS_ERRNO_MESSAGE(error_number, stuff) \
105 	stuff << ": " << std::strerror(error_number) << \
106 	" (" << error_number << ")"
107 
108 #define BOX_FILE_MESSAGE(filename, message) \
109 	message << ": " << filename
110 
111 #define BOX_SYS_FILE_ERRNO_MESSAGE(filename, error_number, message) \
112 	BOX_SYS_ERRNO_MESSAGE(error_number, BOX_FILE_MESSAGE(filename, message))
113 
114 #define BOX_SYS_ERROR_MESSAGE(stuff) \
115 	BOX_SYS_ERRNO_MESSAGE(errno, stuff)
116 
117 #define BOX_LOG_SYS_WARNING(stuff) \
118 	BOX_WARNING(BOX_SYS_ERROR_MESSAGE(stuff))
119 #define BOX_LOG_SYS_ERROR(stuff) \
120 	BOX_ERROR(BOX_SYS_ERROR_MESSAGE(stuff))
121 #define BOX_LOG_SYS_ERRNO(error_number, stuff) \
122 	BOX_ERROR(BOX_SYS_ERRNO_MESSAGE(error_number, stuff))
123 #define BOX_LOG_SYS_FATAL(stuff) \
124 	BOX_FATAL(BOX_SYS_ERROR_MESSAGE(stuff))
125 
126 #define THROW_SYS_ERROR_NUMBER(message, error_number, exception, subtype) \
127 	THROW_EXCEPTION_MESSAGE(exception, subtype, \
128 		BOX_SYS_ERRNO_MESSAGE(error_number, message))
129 
130 #define THROW_SYS_ERROR(message, exception, subtype) \
131 	THROW_SYS_ERROR_NUMBER(message, errno, exception, subtype)
132 
133 #define THROW_SYS_FILE_ERROR(message, filename, exception, subtype) \
134 	THROW_SYS_ERROR_NUMBER(BOX_FILE_MESSAGE(filename, message), \
135 		errno, exception, subtype)
136 
137 #define THROW_SYS_FILE_ERRNO(message, filename, error_number, exception, subtype) \
138 	THROW_SYS_ERROR_NUMBER(BOX_FILE_MESSAGE(filename, message), \
139 		error_number, exception, subtype)
140 
141 #define THROW_FILE_ERROR(message, filename, exception, subtype) \
142 	THROW_EXCEPTION_MESSAGE(exception, subtype, \
143 		BOX_FILE_MESSAGE(filename, message))
144 
GetNativeErrorMessage()145 inline std::string GetNativeErrorMessage()
146 {
147 #ifdef WIN32
148 	return GetErrorMessage(GetLastError());
149 #else
150 	std::ostringstream _box_log_line;
151 	_box_log_line << std::strerror(errno) << " (" << errno << ")";
152 	return _box_log_line.str();
153 #endif
154 }
155 
156 #ifdef WIN32
157 	#define BOX_LOG_WIN_ERROR(stuff) \
158 		BOX_ERROR(stuff << ": " << GetErrorMessage(GetLastError()))
159 	#define BOX_LOG_WIN_WARNING(stuff) \
160 		BOX_WARNING(stuff << ": " << GetErrorMessage(GetLastError()))
161 	#define BOX_LOG_WIN_ERROR_NUMBER(stuff, number) \
162 		BOX_ERROR(stuff << ": " << GetErrorMessage(number))
163 	#define BOX_LOG_WIN_WARNING_NUMBER(stuff, number) \
164 		BOX_WARNING(stuff << ": " << GetErrorMessage(number))
165 	#define BOX_LOG_NATIVE_ERROR(stuff)   BOX_LOG_WIN_ERROR(stuff)
166 	#define BOX_LOG_NATIVE_WARNING(stuff) BOX_LOG_WIN_WARNING(stuff)
167 	#define BOX_WIN_ERRNO_MESSAGE(error_number, stuff) \
168 		stuff << ": " << GetErrorMessage(error_number) << " (" << error_number << ")"
169 	#define THROW_WIN_ERROR_NUMBER(message, error_number, exception, subtype) \
170 		THROW_EXCEPTION_MESSAGE(exception, subtype, \
171 			BOX_WIN_ERRNO_MESSAGE(error_number, message))
172 	#define THROW_WIN_FILE_ERRNO(message, filename, error_number, exception, subtype) \
173 		THROW_WIN_ERROR_NUMBER(BOX_FILE_MESSAGE(filename, message), \
174 			error_number, exception, subtype)
175 #else
176 	#define BOX_LOG_NATIVE_ERROR(stuff)   BOX_LOG_SYS_ERROR(stuff)
177 	#define BOX_LOG_NATIVE_WARNING(stuff) BOX_LOG_SYS_WARNING(stuff)
178 #endif
179 
180 #define BOX_LOG_SOCKET_ERROR(_type, _name, _port, stuff) \
181 	BOX_LOG_NATIVE_ERROR(stuff << " (type " << _type << ", name " << \
182 		_name << ", port " << _port << ")")
183 
184 #define BOX_FORMAT_HEX32(number) \
185 	std::hex << \
186 	std::showbase << \
187 	std::internal << \
188 	std::setw(10) << \
189 	std::setfill('0') << \
190 	(number) << \
191 	std::dec
192 
193 #define BOX_FORMAT_ACCOUNT(accno) \
194 	BOX_FORMAT_HEX32(accno)
195 
196 #define BOX_FORMAT_OBJECTID(objectid) \
197 	std::hex << \
198 	std::showbase << \
199 	(objectid) << \
200 	std::dec
201 
202 #define BOX_FORMAT_TIMESPEC(timespec) \
203 	timespec.tv_sec << \
204 	std::setw(6) << \
205 	timespec.tv_usec
206 
207 #undef ERROR
208 
209 namespace Log
210 {
211 	enum Level
212 	{
213 		NOTHING = 1,
214 		FATAL,
215 		ERROR,
216 		WARNING,
217 		NOTICE,
218 		INFO,
219 		TRACE,
220 		EVERYTHING,
221 		INVALID = -1
222 	};
223 }
224 
225 // --------------------------------------------------------------------------
226 //
227 // Class
228 //		Name:    Logger
229 //		Purpose: Abstract base class for log targets
230 //		Created: 2006/12/16
231 //
232 // --------------------------------------------------------------------------
233 
234 class Logger
235 {
236 	private:
237 	Log::Level mCurrentLevel;
238 
239 	public:
240 	Logger();
241 	Logger(Log::Level level);
242 	virtual ~Logger();
243 
244 	virtual bool Log(Log::Level level, const std::string& rFile,
245 		int line, std::string& rMessage) = 0;
246 
Filter(Log::Level level)247 	void Filter(Log::Level level)
248 	{
249 		mCurrentLevel = level;
250 	}
251 
252 	virtual const char* GetType() = 0;
GetLevel()253 	Log::Level GetLevel() { return mCurrentLevel; }
254 
255 	virtual void SetProgramName(const std::string& rProgramName) = 0;
256 };
257 
258 // --------------------------------------------------------------------------
259 //
260 // Class
261 //		Name:    Console
262 //		Purpose: Console logging target
263 //		Created: 2006/12/16
264 //
265 // --------------------------------------------------------------------------
266 
267 class Console : public Logger
268 {
269 	private:
270 	static bool sShowTag;
271 	static bool sShowTime;
272 	static bool sShowTimeMicros;
273 	static bool sShowPID;
274 	static std::string sTag;
275 
276 	public:
277 	virtual bool Log(Log::Level level, const std::string& rFile,
278 		int line, std::string& rMessage);
GetType()279 	virtual const char* GetType() { return "Console"; }
280 	virtual void SetProgramName(const std::string& rProgramName);
281 
282 	static void SetShowTag(bool enabled);
283 	static void SetShowTime(bool enabled);
284 	static void SetShowTimeMicros(bool enabled);
285 	static void SetShowPID(bool enabled);
286 };
287 
288 // --------------------------------------------------------------------------
289 //
290 // Class
291 //		Name:    Syslog
292 //		Purpose: Syslog (or Windows Event Viewer) logging target
293 //		Created: 2006/12/16
294 //
295 // --------------------------------------------------------------------------
296 
297 class Syslog : public Logger
298 {
299 	private:
300 	std::string mName;
301 	int mFacility;
302 
303 	public:
304 	Syslog();
305 	virtual ~Syslog();
306 
307 	virtual bool Log(Log::Level level, const std::string& rFile,
308 		int line, std::string& rMessage);
GetType()309 	virtual const char* GetType() { return "Syslog"; }
310 	virtual void SetProgramName(const std::string& rProgramName);
311 	virtual void SetFacility(int facility);
312 	static int GetNamedFacility(const std::string& rFacility);
313 };
314 
315 // --------------------------------------------------------------------------
316 //
317 // Class
318 //		Name:    Logging
319 //		Purpose: Static logging helper, keeps track of enabled loggers
320 //			 and distributes log messages to them.
321 //		Created: 2006/12/16
322 //
323 // --------------------------------------------------------------------------
324 
325 class Logging
326 {
327 	private:
328 	static std::vector<Logger*> sLoggers;
329 	static bool sLogToSyslog, sLogToConsole;
330 	static std::string sContext;
331 	static bool sContextSet;
332 	static Console* spConsole;
333 	static Syslog*  spSyslog;
334 	static Log::Level sGlobalLevel;
335 	static Logging    sGlobalLogging;
336 	static std::string sProgramName;
337 
338 	public:
339 	Logging ();
340 	~Logging();
341 	static void ToSyslog  (bool enabled);
342 	static void ToConsole (bool enabled);
343 	static void FilterSyslog  (Log::Level level);
344 	static void FilterConsole (Log::Level level);
345 	static void Add    (Logger* pNewLogger);
346 	static void Remove (Logger* pOldLogger);
347 	static void Log(Log::Level level, const std::string& rFile,
348 		int line, const std::string& rMessage);
349 	static void LogToSyslog(Log::Level level, const std::string& rFile,
350 		int line, const std::string& rMessage);
351 	static void SetContext(std::string context);
352 	static void ClearContext();
SetGlobalLevel(Log::Level level)353 	static void SetGlobalLevel(Log::Level level) { sGlobalLevel = level; }
GetGlobalLevel()354 	static Log::Level GetGlobalLevel() { return sGlobalLevel; }
355 	static Log::Level GetNamedLevel(const std::string& rName);
IsEnabled(Log::Level level)356 	static bool IsEnabled(Log::Level level)
357 	{
358 		return (int)sGlobalLevel >= (int)level;
359 	}
360 	static void SetProgramName(const std::string& rProgramName);
GetProgramName()361 	static std::string GetProgramName() { return sProgramName; }
362 	static void SetFacility(int facility);
363 
364 	class Guard
365 	{
366 		private:
367 		Log::Level mOldLevel;
368 
369 		public:
Guard(Log::Level newLevel)370 		Guard(Log::Level newLevel)
371 		{
372 			mOldLevel = Logging::GetGlobalLevel();
373 			Logging::SetGlobalLevel(newLevel);
374 		}
~Guard()375 		~Guard()
376 		{
377 			Logging::SetGlobalLevel(mOldLevel);
378 		}
379 	};
380 
381 	class Tagger
382 	{
383 		private:
384 		std::string mOldTag;
385 
386 		public:
Tagger(const std::string & rTempTag)387 		Tagger(const std::string& rTempTag)
388 		{
389 			mOldTag = Logging::GetProgramName();
390 			Logging::SetProgramName(mOldTag + " " + rTempTag);
391 		}
~Tagger()392 		~Tagger()
393 		{
394 			Logging::SetProgramName(mOldTag);
395 		}
396 	};
397 };
398 
399 class FileLogger : public Logger
400 {
401 	private:
402 	FileStream mLogFile;
FileLogger(const FileLogger & forbidden)403 	FileLogger(const FileLogger& forbidden)
404 	: mLogFile("") { /* do not call */ }
405 
406 	public:
FileLogger(const std::string & rFileName,Log::Level Level)407 	FileLogger(const std::string& rFileName, Log::Level Level)
408 	: Logger(Level),
409 	  mLogFile(rFileName, O_WRONLY | O_CREAT | O_APPEND)
410 	{ }
411 
412 	virtual bool Log(Log::Level Level, const std::string& rFile,
413 		int Line, std::string& rMessage);
414 
GetType()415 	virtual const char* GetType() { return "FileLogger"; }
SetProgramName(const std::string & rProgramName)416 	virtual void SetProgramName(const std::string& rProgramName) { }
417 };
418 
419 class HideExceptionMessageGuard
420 {
421 	public:
HideExceptionMessageGuard()422 	HideExceptionMessageGuard()
423 	{
424 		mOldHiddenState = sHiddenState;
425 		sHiddenState = true;
426 	}
~HideExceptionMessageGuard()427 	~HideExceptionMessageGuard()
428 	{
429 		sHiddenState = mOldHiddenState;
430 	}
ExceptionsHidden()431 	static bool ExceptionsHidden() { return sHiddenState; }
432 
433 	private:
434 	static bool sHiddenState;
435 	bool mOldHiddenState;
436 };
437 
438 std::string PrintEscapedBinaryData(const std::string& rInput);
439 
440 #endif // LOGGING__H
441