21 #include "tdesycoca.h"
22 #include "tdesycocatype.h"
23 #include "tdesycocafactory.h"
25 #include <tqdatastream.h>
29 #include <tdeapplication.h>
30 #include <dcopclient.h>
31 #include <tdeglobal.h>
34 #include <kstandarddirs.h>
41 #ifdef HAVE_SYS_MMAN_H
45 #if defined(Q_OS_SOLARIS) && !defined(__dilos__)
48 extern int madvise(caddr_t,
size_t,
int);
53 #define MAP_FAILED ((void *) -1)
56 template class TQPtrList<KSycocaFactory>;
66 class KSycocaPrivate {
75 TQStringList changeList;
80 TQStringList allResourceDirs;
83 int KSycoca::version()
85 return TDESYCOCA_VERSION;
90 :
DCOPObject(
"tdesycoca"), m_lstFactories(0), m_str(0), m_barray(0), bNoDatabase(false),
91 m_sycoca_size(0), m_sycoca_mmap(0), m_timeStamp(0)
93 d =
new KSycocaPrivate;
95 if (kapp && !kapp->dcopClient()->isAttached())
97 kapp->dcopClient()->attach();
107 bool KSycoca::openDatabase(
bool openDummyIfNotFound )
115 TQCString tdesycoca_env = getenv(
"TDESYCOCA");
116 if (tdesycoca_env.isEmpty())
119 path = TQFile::decodeName(tdesycoca_env);
121 kdDebug(7011) <<
"Trying to open tdesycoca from " << path <<
endl;
122 TQFile *database =
new TQFile(path);
123 bool bOpen = database->open( IO_ReadOnly );
126 path =
locate(
"services",
"tdesycoca");
129 kdDebug(7011) <<
"Trying to open global tdesycoca from " << path <<
endl;
131 database =
new TQFile(path);
132 bOpen = database->open( IO_ReadOnly );
138 fcntl(database->handle(), F_SETFD, FD_CLOEXEC);
139 m_sycoca_size = database->size();
141 m_sycoca_mmap = (
const char *) mmap(0, m_sycoca_size,
142 PROT_READ, MAP_SHARED,
143 database->handle(), 0);
146 if (m_sycoca_mmap == (
const char*) MAP_FAILED || m_sycoca_mmap == 0)
148 kdDebug(7011) <<
"mmap failed. (length = " << m_sycoca_size <<
")" <<
endl;
150 m_str =
new TQDataStream(database);
156 (void) madvise((
char*)m_sycoca_mmap, m_sycoca_size, MADV_WILLNEED);
158 m_barray =
new TQByteArray();
159 m_barray->setRawData(m_sycoca_mmap, m_sycoca_size);
160 TQBuffer *buffer =
new TQBuffer( *m_barray );
161 buffer->open(IO_ReadWrite);
162 m_str =
new TQDataStream( buffer);
169 kdDebug(7011) <<
"Could not open tdesycoca" <<
endl;
176 if (openDummyIfNotFound)
180 TQBuffer *buffer =
new TQBuffer();
181 buffer->setBuffer(TQByteArray());
182 buffer->open(IO_ReadWrite);
183 m_str =
new TQDataStream( buffer);
184 (*m_str) << (TQ_INT32) TDESYCOCA_VERSION;
185 (*m_str) << (TQ_INT32) 0;
193 m_lstFactories->setAutoDelete(
true );
194 d->database = database;
199 KSycoca::KSycoca(
bool )
200 :
DCOPObject(
"tdesycoca_building"), m_lstFactories(0), m_str(0), m_barray(0), bNoDatabase(false),
201 m_sycoca_size(0), m_sycoca_mmap(0)
203 d =
new KSycocaPrivate;
205 m_lstFactories->setAutoDelete(
true );
209 static void delete_tdesycoca_self() {
210 delete KSycoca::_self;
213 KSycoca * KSycoca::self()
216 tqAddPostRoutine(delete_tdesycoca_self);
217 _self =
new KSycoca();
229 void KSycoca::closeDatabase()
231 TQIODevice *device = 0;
233 device = m_str->device();
235 if (device && m_sycoca_mmap)
237 TQBuffer *buf =
static_cast<TQBuffer*
>(device);
238 buf->buffer().resetRawData(m_sycoca_mmap, m_sycoca_size);
241 munmap((
char*) m_sycoca_mmap, m_sycoca_size);
249 if (d->database != device)
251 if (m_barray)
delete m_barray;
257 delete m_lstFactories;
261 void KSycoca::addFactory( KSycocaFactory *factory )
263 assert(m_lstFactories);
264 m_lstFactories->append(factory);
267 bool KSycoca::isChanged(
const char *type)
269 return self()->d->changeList.contains(type);
272 void KSycoca::notifyDatabaseChanged(
const TQStringList &changeList)
274 d->changeList = changeList;
283 emit databaseChanged();
286 TQDataStream * KSycoca::findEntry(
int offset,
KSycocaType &type)
291 m_str->device()->at(offset);
299 bool KSycoca::checkVersion(
bool abortOnError)
303 if( !openDatabase(
false ) )
309 m_str->device()->at(0);
311 (*m_str) >> aVersion;
312 if ( aVersion < TDESYCOCA_VERSION )
314 kdWarning(7011) <<
"Found version " << aVersion <<
", expecting version " << TDESYCOCA_VERSION <<
" or higher." <<
endl;
315 if (!abortOnError)
return false;
316 kdError(7011) <<
"Outdated database ! Stop kded and restart it !" <<
endl;
322 TQDataStream * KSycoca::findFactory(KSycocaFactoryId
id)
329 if ( !openDatabase(
false ) )
331 static bool triedLaunchingKdeinit =
false;
332 if (!triedLaunchingKdeinit)
334 triedLaunchingKdeinit =
true;
335 kdDebug(7011) <<
"findFactory: we have no database.... launching tdeinit" <<
endl;
336 TDEApplication::startKdeinit();
339 if (!openDatabase(
false))
344 if (!checkVersion(
false))
357 kdError(7011) <<
"Error, KSycocaFactory (id = " << int(
id) <<
") not found!" <<
endl;
364 m_str->device()->at(aOffset);
371 TQString KSycoca::kfsstnd_prefixes()
373 if (bNoDatabase)
return "";
374 if (!checkVersion(
false))
return "";
389 (*m_str) >> m_timeStamp;
391 (*m_str) >> d->updateSig;
396 TQ_UINT32 KSycoca::timeStamp()
399 (void) kfsstnd_prefixes();
403 TQ_UINT32 KSycoca::updateSignature()
406 (void) kfsstnd_prefixes();
410 TQString KSycoca::language()
412 if (d->language.isEmpty())
413 (void) kfsstnd_prefixes();
417 TQStringList KSycoca::allResourceDirs()
420 (void) kfsstnd_prefixes();
421 return d->allResourceDirs;
424 TQString KSycoca::determineRelativePath(
const TQString & _fullpath,
const char *_resource )
426 TQString sRelativeFilePath;
428 TQStringList::ConstIterator dirsit = dirs.begin();
429 for ( ; dirsit != dirs.end() && sRelativeFilePath.isEmpty(); ++dirsit ) {
431 if ( _fullpath.find( *dirsit ) == 0 )
432 sRelativeFilePath = _fullpath.mid( (*dirsit).length() );
434 if ( sRelativeFilePath.isEmpty() )
435 kdFatal(7011) << TQString(TQString(
"Couldn't find %1 in any %2 dir !!!").arg( _fullpath ).arg( _resource)) <<
endl;
439 return sRelativeFilePath;
442 KSycoca * KSycoca::_self = 0L;
444 void KSycoca::flagError()
446 tqWarning(
"ERROR: KSycoca database corruption!");
449 if (_self->d->readError)
451 _self->d->readError =
true;
452 if (_self->d->autoRebuild)
453 if(system(
"tdebuildsycoca") < 0)
454 tqWarning(
"ERROR: Running KSycoca failed.");
458 void KSycoca::disableAutoRebuild()
460 d->autoRebuild =
false;
463 bool KSycoca::readError()
468 b = _self->d->readError;
469 _self->d->readError =
false;
478 if ( bytes > 8192 ) {
479 if (bytes != 0xffffffff)
480 KSycoca::flagError();
481 str = TQString::null;
483 else if ( bytes > 0 ) {
486 TQChar* ch = (TQChar *) str.unicode();
489 s.readRawBytes( b, bytes );
491 *ch++ = (ushort) (((ushort)b[0])<<8) | (uchar)b[1];
506 KSycoca::flagError();
509 for(TQ_UINT32 i = 0; i < count; i++)
516 KSycoca::flagError();
522 void KSycoca::virtual_hook(
int id,
void* data )
523 { DCOPObject::virtual_hook(
id, data ); }
525 void KSycocaEntry::virtual_hook(
int,
void* )
528 #include "tdesycoca.moc"
KSycocaType
A KSycocaType is a code (out of the KSycocaType enum) assigned to each class type derived from KSycoc...
static void read(TQDataStream &s, TQString &str)
Safe demarshalling functions.
This, instead of a typedef, allows to declare "class ..." in header files.
static TDEStandardDirs * dirs()
Returns the application standard dirs object.
TQString saveLocation(const char *type, const TQString &suffix=TQString::null, bool create=true) const
Finds a location to save files into for the given type in the user's home directory.
TQStringList resourceDirs(const char *type) const
This function is used internally by almost all other function as it serves and fills the directories ...
kdbgstream kdFatal(int area=0)
Returns a fatal error stream.
kdbgstream kdWarning(int area=0)
Returns a warning stream.
kdbgstream kdError(int area=0)
Returns an error stream.
kdbgstream kdDebug(int area=0)
Returns a debug stream.
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
TQString locate(const char *type, const TQString &filename, const TDEInstance *instance=TDEGlobal::instance())