libzypp 17.37.10

ZYppFactory.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12 extern "C"
13{
14#include <sys/file.h>
15}
16#include <iostream>
17#include <fstream>
18#include <signal.h>
19
20#include <zypp/base/Logger.h>
21#include <zypp/base/LogControl.h>
22#include <zypp/base/Gettext.h>
23#include <zypp/base/IOStream.h>
24#include <zypp/base/Functional.h>
25#include <zypp/base/Backtrace.h>
26#include <zypp/base/LogControl.h>
27#include <zypp/PathInfo.h>
28#include <zypp/ZConfig.h>
29
30#include <zypp/ZYppFactory.h>
31#include <zypp/zypp_detail/ZYppImpl.h>
32
33#include <boost/interprocess/sync/file_lock.hpp>
34#include <boost/interprocess/sync/scoped_lock.hpp>
35#include <boost/interprocess/sync/sharable_lock.hpp>
36#include <utility>
37
38#include <iostream>
39
40 using boost::interprocess::file_lock;
41 using boost::interprocess::scoped_lock;
42 using boost::interprocess::sharable_lock;
43
44 using std::endl;
45
46 namespace zyppintern { void repoVariablesReset(); } // upon re-acquiring the lock...
47
49 namespace zypp
50{
51
52 namespace sighandler
53 {
55 template <int SIG>
56 class SigBacktraceHandler
57 {
58 static void backtraceHandler( int sig ) {
59 INT << "Error: signal " << SIG << endl << dumpBacktrace << endl;
60 base::LogControl::instance().emergencyShutdown();
61 ::signal( SIG, lastSigHandler );
62 }
63 static ::sighandler_t lastSigHandler;
64 };
65 template <int SIG>
66 ::sighandler_t SigBacktraceHandler<SIG>::lastSigHandler { ::signal( SIG, SigBacktraceHandler::backtraceHandler ) };
67
68 // Explicit instantiation installs the handler:
69 template class SigBacktraceHandler<SIGSEGV>;
70 template class SigBacktraceHandler<SIGABRT>;
71 }
72
73 namespace env
74 {
76 inline Pathname ZYPP_LOCKFILE_ROOT()
77 { return getenv("ZYPP_LOCKFILE_ROOT") ? getenv("ZYPP_LOCKFILE_ROOT") : "/"; }
78 }
79
81 namespace zypp_readonly_hack
82 {
83
84 static bool active = getenv("ZYPP_READONLY_HACK");
85
86 ZYPP_API void IWantIt() // see zypp/zypp_detail/ZYppReadOnlyHack.h
87 {
88 active = true;
89 MIL << "ZYPP_READONLY promised." << endl;
90 }
91
92 bool IGotIt()
93 {
94 return active;
95 }
96
98 } // namespace zypp_readonly_hack
100
106 class ZYppGlobalLock
107 {
108 public:
109 ZYppGlobalLock(Pathname &&lFilePath)
110 : _zyppLockFilePath(std::move(lFilePath)), _zyppLockFile(NULL),
111 _lockerPid(0), _cleanLock(false) {
112 filesystem::assert_dir(_zyppLockFilePath.dirname() );
113 }
114
115 ZYppGlobalLock(const ZYppGlobalLock &) = delete;
116 ZYppGlobalLock(ZYppGlobalLock &&) = delete;
117 ZYppGlobalLock &operator=(const ZYppGlobalLock &) = delete;
118 ZYppGlobalLock &operator=(ZYppGlobalLock &&) = delete;
119
120 ~ZYppGlobalLock()
121 {
122 if ( _cleanLock )
123 try {
124 // Exception safe access to the lockfile.
125 ScopedGuard closeOnReturn( accessLockFile() );
126 {
127 scoped_lock<file_lock> flock( _zyppLockFileLock ); // aquire write lock
128 // Truncate the file rather than deleting it. Other processes may
129 // still use it to synchronsize.
130 ftruncate( fileno(_zyppLockFile), 0 );
131 }
132 MIL << "Cleaned lock file. (" << getpid() << ")" << std::endl;
133 }
134 catch(...) {} // let no exception escape.
135 }
136
137 pid_t lockerPid() const
138 { return _lockerPid; }
139
140 const std::string & lockerName() const
141 { return _lockerName; }
142
143 const Pathname & zyppLockFilePath() const
144 { return _zyppLockFilePath; }
145
146
147 private:
148 Pathname _zyppLockFilePath;
149 file_lock _zyppLockFileLock;
150 FILE * _zyppLockFile;
151
152 pid_t _lockerPid;
153 std::string _lockerName;
154 bool _cleanLock;
155
156 private:
157 using ScopedGuard = shared_ptr<void>;
158
165 ScopedGuard accessLockFile()
166 {
167 _openLockFile();
168 return ScopedGuard( static_cast<void*>(0),
169 std::bind( std::mem_fn( &ZYppGlobalLock::_closeLockFile ), this ) );
170 }
171
173 void _openLockFile()
174 {
175 if ( _zyppLockFile != NULL )
176 return; // is open
177
178 // open pid file rw so we are sure it exist when creating the flock
179 _zyppLockFile = fopen( _zyppLockFilePath.c_str(), "a+" );
180 if ( _zyppLockFile == NULL )
181 ZYPP_THROW( Exception( "Cant open " + _zyppLockFilePath.asString() ) );
182 _zyppLockFileLock = _zyppLockFilePath.c_str();
183 MIL << "Open lockfile " << _zyppLockFilePath << endl;
184 }
185
187 void _closeLockFile()
188 {
189 if ( _zyppLockFile == NULL )
190 return; // is closed
191
192 clearerr( _zyppLockFile );
193 fflush( _zyppLockFile );
194 // http://www.boost.org/doc/libs/1_50_0/doc/html/interprocess/synchronization_mechanisms.html
195 // If you are using a std::fstream/native file handle to write to the file
196 // while using file locks on that file, don't close the file before releasing
197 // all the locks of the file.
198 _zyppLockFileLock = file_lock();
199 fclose( _zyppLockFile );
200 _zyppLockFile = NULL;
201 MIL << "Close lockfile " << _zyppLockFilePath << endl;
202 }
203
204
205 bool isProcessRunning( pid_t pid_r )
206 {
207 // it is another program, not me, see if it is still running
208 Pathname procdir( Pathname("/proc")/str::numstring(pid_r) );
209 PathInfo status( procdir );
210 MIL << "Checking " << status << endl;
211
212 if ( ! status.isDir() )
213 {
214 DBG << "No such process." << endl;
215 return false;
216 }
217
218 static char buffer[513];
219 buffer[0] = buffer[512] = 0;
220 // man proc(5): /proc/[pid]/cmdline is empty if zombie.
221 if ( std::ifstream( (procdir/"cmdline").c_str() ).read( buffer, 512 ).gcount() > 0 )
222 {
223 _lockerName = buffer;
224 DBG << "Is running: " << _lockerName << endl;
225 return true;
226 }
227
228 DBG << "In zombie state." << endl;
229 return false;
230 }
231
232 pid_t readLockFile()
233 {
234 clearerr( _zyppLockFile );
235 fseek( _zyppLockFile, 0, SEEK_SET );
236 long readpid = 0;
237 fscanf( _zyppLockFile, "%ld", &readpid );
238 MIL << "read: Lockfile " << _zyppLockFilePath << " has pid " << readpid << " (our pid: " << getpid() << ") "<< std::endl;
239 return (pid_t)readpid;
240 }
241
242 void writeLockFile()
243 {
244 clearerr( _zyppLockFile );
245 fseek( _zyppLockFile, 0, SEEK_SET );
246 ftruncate( fileno(_zyppLockFile), 0 );
247 fprintf(_zyppLockFile, "%ld\n", (long)getpid() );
248 fflush( _zyppLockFile );
249 _cleanLock = true; // cleanup on exit
250 MIL << "write: Lockfile " << _zyppLockFilePath << " got pid " << getpid() << std::endl;
251 }
252
256 bool safeCheckIsLocked()
257 {
258 _lockerPid = readLockFile();
259 if ( _lockerPid == 0 ) {
260 // no or empty lock file
261 return false;
262 } else if ( _lockerPid == getpid() ) {
263 // keep my own lock
264 return false;
265 } else {
266 // a foreign pid in lock
267 if ( isProcessRunning( _lockerPid ) ) {
268 WAR << _lockerPid << " is running and has a ZYpp lock. Sorry." << std::endl;
269 return true;
270 } else {
271 MIL << _lockerPid << " is dead. Ignoring the existing lock file." << std::endl;
272 return false;
273 }
274 }
275 }
276
277 public:
278
279 bool isZyppLocked()
280 {
281 if ( geteuid() != 0 )
282 return false; // no lock as non-root
283
284 // Exception safe access to the lockfile.
285 ScopedGuard closeOnReturn( accessLockFile() );
286 scoped_lock<file_lock> flock( _zyppLockFileLock ); // aquire write lock
287 return safeCheckIsLocked ();
288 }
289
293 bool zyppLocked()
294 {
295 if ( geteuid() != 0 )
296 return false; // no lock as non-root
297
298 // Exception safe access to the lockfile.
299 ScopedGuard closeOnReturn( accessLockFile() );
300 scoped_lock<file_lock> flock( _zyppLockFileLock ); // aquire write lock
301 if ( !safeCheckIsLocked() ) {
302 writeLockFile();
303 return false;
304 }
305 return true;
306 }
307
308 };
309
311 namespace
312 {
313 static weak_ptr<ZYpp> _theZYppInstance;
314 static scoped_ptr<ZYppGlobalLock> _theGlobalLock; // on/off in sync with _theZYppInstance
315
316 ZYppGlobalLock & globalLock()
317 {
318 if ( !_theGlobalLock )
319 _theGlobalLock.reset( new ZYppGlobalLock( ZYppFactory::lockfileDir() / "zypp.pid" ) );
320 return *_theGlobalLock;
321 }
322 } //namespace
324
326 //
327 // CLASS NAME : ZYpp
328 //
330
331 ZYpp::ZYpp( const Impl_Ptr & impl_r )
332 : _pimpl( impl_r )
333 {
334 ::zyppintern::repoVariablesReset(); // upon re-acquiring the lock...
335 MIL << "ZYpp is on..." << endl;
336 }
337
338 ZYpp::~ZYpp()
339 {
340 _theGlobalLock.reset();
341 MIL << "ZYpp is off..." << endl;
342 }
343
345 //
346 // CLASS NAME : ZYppFactoryException
347 //
349
350 ZYppFactoryException::ZYppFactoryException( std::string msg_r, pid_t lockerPid_r, std::string lockerName_r )
351 : Exception( std::move(msg_r) )
352 , _lockerPid( lockerPid_r )
353 , _lockerName(std::move( lockerName_r ))
354 {}
355
356 ZYppFactoryException::~ZYppFactoryException() throw ()
357 {}
358
360 //
361 // CLASS NAME : ZYppFactory
362 //
364
365 ZYppFactory ZYppFactory::instance()
366 { return ZYppFactory(); }
367
368 ZYppFactory::ZYppFactory()
369 {}
370
371 ZYppFactory::~ZYppFactory()
372 {}
373
375 //
376 ZYpp::Ptr ZYppFactory::getZYpp() const
377 {
378
379 const auto &makeLockedError = []( pid_t pid, const std::string &lockerName ){
380 const std::string &t = str::form(_("System management is locked by the application with pid %d (%s).\n"
381 "Close this application before trying again."), pid, lockerName.c_str() );
382 return ZYppFactoryException(t, pid, lockerName );
383 };
384
385 ZYpp::Ptr _instance = _theZYppInstance.lock();
386 if ( ! _instance )
387 {
388 if ( geteuid() != 0 )
389 {
390 MIL << "Running as user. Skip creating " << globalLock().zyppLockFilePath() << std::endl;
391 }
392 else if ( zypp_readonly_hack::active )
393 {
394 MIL << "ZYPP_READONLY active." << endl;
395 }
396 else if ( globalLock().zyppLocked() )
397 {
398 bool failed = true;
399 // bsc#1184399,1213231: A negative ZYPP_LOCK_TIMEOUT will wait forever.
400 const long LOCK_TIMEOUT = ZConfig::instance().lockTimeout();
401 if ( LOCK_TIMEOUT != 0 )
402 {
403 Date logwait = Date::now();
404 Date giveup; /* 0 = forever */
405 if ( LOCK_TIMEOUT > 0 ) {
406 giveup = logwait+LOCK_TIMEOUT;
407 MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Waiting for the zypp lock until " << giveup << endl;
408 }
409 else
410 MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Waiting for the zypp lock..." << endl;
411
412 unsigned delay = 0;
413 do {
414 if ( delay < 60 )
415 delay += 1;
416 else {
417 Date now { Date::now() };
418 if ( now - logwait > Date::day ) {
419 WAR << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Another day has passed waiting for the zypp lock..." << endl;
420 logwait = now;
421 }
422 }
423 sleep( delay );
424 {
425 zypp::base::LogControl::TmpLineWriter shutUp; // be quiet
426 failed = globalLock().zyppLocked();
427 }
428 } while ( failed && ( not giveup || Date::now() <= giveup ) );
429
430 if ( failed ) {
431 MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Gave up waiting for the zypp lock." << endl;
432 }
433 else {
434 MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Finally got the zypp lock." << endl;
435 }
436 }
437 if ( failed )
438 ZYPP_THROW( makeLockedError( globalLock().lockerPid(), globalLock().lockerName() ));
439
440 // we got the global lock, now make sure zypp-rpm is not still running
441 {
442 ZYppGlobalLock zyppRpmLock( ZYppFactory::lockfileDir() / "zypp-rpm.pid" );
443 if ( zyppRpmLock.isZyppLocked () ) {
444 // release global lock, we will exit now
445 _theGlobalLock.reset();
446 ZYPP_THROW( makeLockedError( zyppRpmLock.lockerPid(), zyppRpmLock.lockerName() ));
447 }
448 }
449 }
450
451 // Here we go...
452 static ZYpp::Impl_Ptr _theImplInstance; // for now created once
453 if ( !_theImplInstance )
454 _theImplInstance.reset( new ZYpp::Impl );
455 _instance.reset( new ZYpp( _theImplInstance ) );
456 _theZYppInstance = _instance;
457 }
458
459 return _instance;
460 }
461
463 //
464 bool ZYppFactory::haveZYpp() const
465 { return !_theZYppInstance.expired(); }
466
467 zypp::Pathname ZYppFactory::lockfileDir()
468 {
469 return env::ZYPP_LOCKFILE_ROOT() / "run";
470 }
471
472 /******************************************************************
473 **
474 ** FUNCTION NAME : operator<<
475 ** FUNCTION TYPE : std::ostream &
476 */
477 std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj )
478 {
479 return str << "ZYppFactory";
480 }
481
483} // namespace zypp
Backtrace.h
Functional.h
ZConfig.h
ZYppFactory.h
ZYppImpl.h
scoped_ptr
shared_ptr
weak_ptr
zypp::Date
Store and operate on date (time_t).
Definition Date.h:33
zypp::Date::day
static const ValueType day
Definition Date.h:44
zypp::Date::now
static Date now()
Return the current time.
Definition Date.h:78
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::Exception::Exception
Exception()
Default ctor.
Definition Exception.cc:94
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:940
zypp::ZConfig::lockTimeout
long lockTimeout() const
The number of seconds to wait for the zypp lock to become available.
Definition ZConfig.cc:965
zypp::ZYppFactoryException
Definition ZYppFactory.h:25
zypp::ZYppFactoryException::ZYppFactoryException
ZYppFactoryException(std::string msg_r, pid_t lockerPid_r, std::string lockerName_r)
Definition ZYppFactory.cc:350
zypp::ZYppFactoryException::~ZYppFactoryException
~ZYppFactoryException() override
Definition ZYppFactory.cc:356
zypp::ZYppFactoryException::_lockerName
std::string _lockerName
Definition ZYppFactory.h:34
zypp::ZYppFactoryException::_lockerPid
pid_t _lockerPid
Definition ZYppFactory.h:33
zypp::ZYppFactory::instance
static ZYppFactory instance()
Singleton ctor.
Definition ZYppFactory.cc:365
zypp::ZYppFactory::haveZYpp
bool haveZYpp() const
Whether the ZYpp instance is already created.
Definition ZYppFactory.cc:464
zypp::ZYppFactory::getZYpp
ZYpp::Ptr getZYpp() const
Definition ZYppFactory.cc:376
zypp::ZYppFactory::~ZYppFactory
~ZYppFactory()
Dtor.
Definition ZYppFactory.cc:371
zypp::ZYppFactory::ZYppFactory
ZYppFactory()
Default ctor.
Definition ZYppFactory.cc:368
zypp::ZYppFactory::lockfileDir
static zypp::Pathname lockfileDir()
Definition ZYppFactory.cc:467
zypp::ZYppGlobalLock
Our broken global lock.
Definition ZYppFactory.cc:107
zypp::ZYppGlobalLock::lockerName
const std::string & lockerName() const
Definition ZYppFactory.cc:140
zypp::ZYppGlobalLock::~ZYppGlobalLock
~ZYppGlobalLock()
Definition ZYppFactory.cc:120
zypp::ZYppGlobalLock::operator=
ZYppGlobalLock & operator=(const ZYppGlobalLock &)=delete
zypp::ZYppGlobalLock::isZyppLocked
bool isZyppLocked()
Definition ZYppFactory.cc:279
zypp::ZYppGlobalLock::_closeLockFile
void _closeLockFile()
Use accessLockFile.
Definition ZYppFactory.cc:187
zypp::ZYppGlobalLock::ScopedGuard
shared_ptr< void > ScopedGuard
Definition ZYppFactory.cc:157
zypp::ZYppGlobalLock::_lockerName
std::string _lockerName
Definition ZYppFactory.cc:153
zypp::ZYppGlobalLock::_zyppLockFileLock
file_lock _zyppLockFileLock
Definition ZYppFactory.cc:149
zypp::ZYppGlobalLock::writeLockFile
void writeLockFile()
Definition ZYppFactory.cc:242
zypp::ZYppGlobalLock::_openLockFile
void _openLockFile()
Use accessLockFile.
Definition ZYppFactory.cc:173
zypp::ZYppGlobalLock::_lockerPid
pid_t _lockerPid
Definition ZYppFactory.cc:152
zypp::ZYppGlobalLock::lockerPid
pid_t lockerPid() const
Definition ZYppFactory.cc:137
zypp::ZYppGlobalLock::readLockFile
pid_t readLockFile()
Definition ZYppFactory.cc:232
zypp::ZYppGlobalLock::zyppLocked
bool zyppLocked()
Try to aquire a lock.
Definition ZYppFactory.cc:293
zypp::ZYppGlobalLock::safeCheckIsLocked
bool safeCheckIsLocked()
Definition ZYppFactory.cc:256
zypp::ZYppGlobalLock::accessLockFile
ScopedGuard accessLockFile()
Exception safe access to the lockfile.
Definition ZYppFactory.cc:165
zypp::ZYppGlobalLock::_cleanLock
bool _cleanLock
Definition ZYppFactory.cc:154
zypp::ZYppGlobalLock::_zyppLockFilePath
Pathname _zyppLockFilePath
Definition ZYppFactory.cc:148
zypp::ZYppGlobalLock::_zyppLockFile
FILE * _zyppLockFile
Definition ZYppFactory.cc:150
zypp::ZYppGlobalLock::zyppLockFilePath
const Pathname & zyppLockFilePath() const
Definition ZYppFactory.cc:143
zypp::ZYppGlobalLock::isProcessRunning
bool isProcessRunning(pid_t pid_r)
Definition ZYppFactory.cc:205
zypp::ZYppGlobalLock::operator=
ZYppGlobalLock & operator=(ZYppGlobalLock &&)=delete
zypp::ZYppGlobalLock::ZYppGlobalLock
ZYppGlobalLock(const ZYppGlobalLock &)=delete
zypp::ZYppGlobalLock::ZYppGlobalLock
ZYppGlobalLock(ZYppGlobalLock &&)=delete
zypp::ZYppGlobalLock::ZYppGlobalLock
ZYppGlobalLock(Pathname &&lFilePath)
Definition ZYppFactory.cc:109
zypp::ZYpp
Definition ZYpp.h:58
zypp::ZYpp::Impl
zypp_detail::ZYppImpl Impl
Definition ZYpp.h:159
zypp::ZYpp::_pimpl
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition ZYpp.h:170
zypp::ZYpp::Impl_Ptr
shared_ptr< Impl > Impl_Ptr
Definition ZYpp.h:160
zypp::ZYpp::~ZYpp
~ZYpp()
Dtor.
Definition ZYppFactory.cc:338
zypp::ZYpp::ZYpp
ZYpp(const Impl_Ptr &impl_r)
Factory ctor.
Definition ZYppFactory.cc:331
zypp::ZYpp::Ptr
shared_ptr< ZYpp > Ptr
Definition ZYpp.h:62
zypp::base::LogControl::instance
static LogControl instance()
Singleton access.
Definition LogControl.h:102
zypp::base::LogControl::emergencyShutdown
void emergencyShutdown()
will cause the log thread to exit and flush all sockets
Definition LogControl.cc:926
zypp::filesystem::PathInfo
Wrapper class for stat/lstat.
Definition PathInfo.h:226
zypp::filesystem::PathInfo::isDir
bool isDir() const
Definition PathInfo.h:296
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:47
zypp::sighandler::SigBacktraceHandler
Signal handler logging a stack trace.
Definition ZYppFactory.cc:57
zypp::sighandler::SigBacktraceHandler::backtraceHandler
static void backtraceHandler(int sig)
Definition ZYppFactory.cc:58
zypp::sighandler::SigBacktraceHandler::lastSigHandler
::sighandler_t lastSigHandler
Definition ZYppFactory.cc:63
std
Definition Arch.h:364
str
String related utilities and Regular expression matching.
zypp::env::ZYPP_LOCKFILE_ROOT
Pathname ZYPP_LOCKFILE_ROOT()
Hack to circumvent the currently poor –root support.
Definition ZYppFactory.cc:76
zypp::filesystem::assert_dir
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:324
zypp::sighandler
Definition ZYppFactory.cc:53
zypp::str::numstring
std::string numstring(char n, int w=0)
Definition String.h:290
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
zypp::zypp_readonly_hack::IGotIt
bool IGotIt()
Definition ZYppFactory.cc:92
zypp::zypp_readonly_hack::active
static bool active
Definition ZYppFactory.cc:84
zypp::zypp_readonly_hack::IWantIt
void IWantIt() ZYPP_DEPRECATED
Definition ZYppFactory.cc:86
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition Application.cc:20
zypp::operator<<
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
Definition SerialNumber.cc:52
zypp::ZYPP_API
const Arch Arch_armv7hnl Arch_armv7nhl ZYPP_API
Definition Arch.h:247
zypp::dumpBacktrace
std::ostream & dumpBacktrace(std::ostream &stream_r)
Dump current stack trace to a stream.
Definition Backtrace.cc:24
zyppintern
Definition Package.cc:27
zyppintern::repoVariablesReset
void repoVariablesReset()
Definition RepoVariables.cc:596
zypp::base::LogControl::TmpLineWriter
Exchange LineWriter for the lifetime of this object.
Definition LogControl.h:191
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
_
#define _(MSG)
Definition Gettext.h:39
DBG
#define DBG
Definition Logger.h:99
MIL
#define MIL
Definition Logger.h:100
WAR
#define WAR
Definition Logger.h:101
INT
#define INT
Definition Logger.h:104
PathInfo.h
Gettext.h
Interface to gettext.
IOStream.h
LogControl.h
Logger.h