/* This file is part of the KDE libraries * Copyright (C) 1999 David Faure * Copyright (C) 2002-2003 Waldo Bastian * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation; * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. **/ #include #include #include #include "kbuildsycoca.h" #include "kresourcelist.h" #include "vfolder_menu.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build // GUI version of kbuildsycoca, so-called "kbuildsycocaw". # include # include bool silent; bool showprogress; #endif #include #include #include #include // auto_ptr typedef TQDict KBSEntryDict; typedef TQValueList KSycocaEntryListList; static TQ_UINT32 newTimestamp = 0; static KBuildServiceFactory *g_bsf = 0; static KBuildServiceGroupFactory *g_bsgf = 0; static KSycocaFactory *g_factory = 0; static KCTimeInfo *g_ctimeInfo = 0; static TQDict *g_ctimeDict = 0; static const char *g_resource = 0; static KBSEntryDict *g_entryDict = 0; static KBSEntryDict *g_serviceGroupEntryDict = 0; static KSycocaEntryListList *g_allEntries = 0; static TQStringList *g_changeList = 0; static TQStringList *g_allResourceDirs = 0; static bool g_changed = false; static KSycocaEntry::List g_tempStorage; static VFolderMenu *g_vfolder = 0; static const char *cSycocaPath = 0; static bool bGlobalDatabase = false; static bool bMenuTest = false; void crashHandler(int) { // If we crash while reading sycoca, we delete the database // in an attempt to recover. if (cSycocaPath) unlink(cSycocaPath); } static TQString sycocaPath() { TQString path; if (bGlobalDatabase) { path = KGlobal::dirs()->saveLocation("services")+"ksycoca"; } else { TQCString ksycoca_env = getenv("KDESYCOCA"); if (ksycoca_env.isEmpty()) path = KGlobal::dirs()->saveLocation("cache")+"ksycoca"; else path = TQFile::decodeName(ksycoca_env); } return path; } static TQString oldSycocaPath() { TQCString ksycoca_env = getenv("KDESYCOCA"); if (ksycoca_env.isEmpty()) return KGlobal::dirs()->saveLocation("tmp")+"ksycoca"; return TQString::null; } KBuildSycoca::KBuildSycoca() : KSycoca( true ) { } KBuildSycoca::~KBuildSycoca() { } void KBuildSycoca::processGnomeVfs() { TQString file = locate("app-reg", "gnome-vfs.applications"); if (file.isEmpty()) { // kdDebug(7021) << "gnome-vfs.applications not found." << endl; return; } TQString app; char line[1024*64]; FILE *f = fopen(TQFile::encodeName(file), "r"); while (!feof(f)) { if (!fgets(line, sizeof(line)-1, f)) { break; } if (line[0] != '\t') { app = TQString::tqfromLatin1(line); app.truncate(app.length()-1); } else if (strncmp(line+1, "mime_types=", 11) == 0) { TQString mimetypes = TQString::tqfromLatin1(line+12); mimetypes.truncate(mimetypes.length()-1); mimetypes.replace(TQRegExp("\\*"), "all"); KService *s = g_bsf->findServiceByName(app); if (!s) continue; TQStringList &serviceTypes = s->accessServiceTypes(); if (serviceTypes.count() <= 1) { serviceTypes += TQStringList::split(',', mimetypes); // kdDebug(7021) << "Adding gnome mimetypes for '" << app << "'.\n"; // kdDebug(7021) << "ServiceTypes=" << s->serviceTypes().join(":") << endl; } } } fclose( f ); } KSycocaEntry *KBuildSycoca::createEntry(const TQString &file, bool addToFactory) { TQ_UINT32 timeStamp = g_ctimeInfo->ctime(file); if (!timeStamp) { timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, file, true); } KSycocaEntry* entry = 0; if (g_allEntries) { assert(g_ctimeDict); TQ_UINT32 *timeP = (*g_ctimeDict)[file]; TQ_UINT32 oldTimestamp = timeP ? *timeP : 0; if (timeStamp && (timeStamp == oldTimestamp)) { // Re-use old entry if (g_factory == g_bsgf) // Strip .directory from service-group entries { entry = g_entryDict->find(file.left(file.length()-10)); } else if (g_factory == g_bsf) { entry = g_entryDict->find(file); } else { entry = g_entryDict->find(file); } // remove from g_ctimeDict; if g_ctimeDict is not empty // after all files have been processed, it means // some files were removed since last time g_ctimeDict->remove( file ); } else if (oldTimestamp) { g_changed = true; kdDebug(7021) << "modified: " << file << endl; } else { g_changed = true; kdDebug(7021) << "new: " << file << endl; } } g_ctimeInfo->addCTime(file, timeStamp ); if (!entry) { // Create a new entry entry = g_factory->createEntry( file, g_resource ); } if ( entry && entry->isValid() ) { if (addToFactory) g_factory->addEntry( entry, g_resource ); else g_tempStorage.append(entry); return entry; } return 0; } void KBuildSycoca::slotCreateEntry(const TQString &file, KService **service) { KSycocaEntry *entry = createEntry(file, false); *service = dynamic_cast(entry); } // returns false if the database is up to date bool KBuildSycoca::build() { typedef TQPtrList KBSEntryDictList; KBSEntryDictList *entryDictList = 0; KBSEntryDict *serviceEntryDict = 0; entryDictList = new KBSEntryDictList(); // Convert for each factory the entryList to a Dict. int i = 0; // For each factory for (KSycocaFactory *factory = m_lstFactories->first(); factory; factory = m_lstFactories->next() ) { KBSEntryDict *entryDict = new KBSEntryDict(); if (g_allEntries) { KSycocaEntry::List list = (*g_allEntries)[i++]; for( KSycocaEntry::List::Iterator it = list.begin(); it != list.end(); ++it) { entryDict->insert( (*it)->entryPath(), static_cast(*it)); } } if (factory == g_bsf) serviceEntryDict = entryDict; else if (factory == g_bsgf) g_serviceGroupEntryDict = entryDict; entryDictList->append(entryDict); } TQStringList allResources; // For each factory for (KSycocaFactory *factory = m_lstFactories->first(); factory; factory = m_lstFactories->next() ) { // For each resource the factory deals with const KSycocaResourceList *list = factory->resourceList(); if (!list) continue; for( KSycocaResourceList::ConstIterator it1 = list->begin(); it1 != list->end(); ++it1 ) { KSycocaResource res = (*it1); if (!allResources.contains(res.resource)) allResources.append(res.resource); } } g_ctimeInfo = new KCTimeInfo(); // This is a build factory too, don't delete!! bool uptodate = true; // For all resources for( TQStringList::ConstIterator it1 = allResources.begin(); it1 != allResources.end(); ++it1 ) { g_changed = false; g_resource = (*it1).ascii(); TQStringList relFiles; (void) KGlobal::dirs()->findAllResources( g_resource, TQString::null, true, // Recursive! true, // uniq relFiles); // Now find all factories that use this resource.... // For each factory g_entryDict = entryDictList->first(); for (g_factory = m_lstFactories->first(); g_factory; g_factory = m_lstFactories->next(), g_entryDict = entryDictList->next() ) { // For each resource the factory deals with const KSycocaResourceList *list = g_factory->resourceList(); if (!list) continue; for( KSycocaResourceList::ConstIterator it2 = list->begin(); it2 != list->end(); ++it2 ) { KSycocaResource res = (*it2); if (res.resource != (*it1)) continue; // For each file in the resource for( TQStringList::ConstIterator it3 = relFiles.begin(); it3 != relFiles.end(); ++it3 ) { // Check if file matches filter if ((*it3).endsWith(res.extension)) createEntry(*it3, true); } } if ((g_factory == g_bsf) && (strcmp(g_resource, "services") == 0)) processGnomeVfs(); } if (g_changed || !g_allEntries) { uptodate = false; g_changeList->append(g_resource); } } bool result = !uptodate || !g_ctimeDict->isEmpty(); if (result || bMenuTest) { g_resource = "apps"; g_factory = g_bsf; g_entryDict = serviceEntryDict; g_changed = false; g_vfolder = new VFolderMenu; if (!m_trackId.isEmpty()) g_vfolder->setTrackId(m_trackId); connect(g_vfolder, TQT_SIGNAL(newService(const TQString &, KService **)), this, TQT_SLOT(slotCreateEntry(const TQString &, KService **))); VFolderMenu::SubMenu *kdeMenu = g_vfolder->parseMenu("applications.menu", true); KServiceGroup *entry = g_bsgf->addNew("/", kdeMenu->directoryFile, 0, false); entry->setLayoutInfo(kdeMenu->layoutList); createMenu(TQString::null, TQString::null, kdeMenu); KServiceGroup::Ptr g(entry); (void) existingResourceDirs(); *g_allResourceDirs += g_vfolder->allDirectories(); disconnect(g_vfolder, TQT_SIGNAL(newService(const TQString &, KService **)), this, TQT_SLOT(slotCreateEntry(const TQString &, KService **))); if (g_changed || !g_allEntries) { uptodate = false; g_changeList->append(g_resource); } if (bMenuTest) return false; } return result; } void KBuildSycoca::createMenu(TQString caption, TQString name, VFolderMenu::SubMenu *menu) { for(VFolderMenu::SubMenu *subMenu = menu->subMenus.first(); subMenu; subMenu = menu->subMenus.next()) { TQString subName = name+subMenu->name+"/"; TQString directoryFile = subMenu->directoryFile; if (directoryFile.isEmpty()) directoryFile = subName+".directory"; TQ_UINT32 timeStamp = g_ctimeInfo->ctime(directoryFile); if (!timeStamp) { timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, directoryFile, true); } KServiceGroup* entry = 0; if (g_allEntries) { TQ_UINT32 *timeP = (*g_ctimeDict)[directoryFile]; TQ_UINT32 oldTimestamp = timeP ? *timeP : 0; if (timeStamp && (timeStamp == oldTimestamp)) { entry = dynamic_cast (g_serviceGroupEntryDict->find(subName)); if (entry && (entry->directoryEntryPath() != directoryFile)) entry = 0; // Can't reuse this one! } } g_ctimeInfo->addCTime(directoryFile, timeStamp); entry = g_bsgf->addNew(subName, subMenu->directoryFile, entry, subMenu->isDeleted); entry->setLayoutInfo(subMenu->layoutList); if (! (bMenuTest && entry->noDisplay()) ) createMenu(caption + entry->caption() + "/", subName, subMenu); } if (caption.isEmpty()) caption += "/"; if (name.isEmpty()) name += "/"; for(TQDictIterator it(menu->items); it.current(); ++it) { if (bMenuTest) { if (!menu->isDeleted && !it.current()->noDisplay()) printf("%s\t%s\t%s\n", caption.local8Bit().data(), it.current()->menuId().local8Bit().data(), locate("apps", it.current()->desktopEntryPath()).local8Bit().data()); } else { g_bsf->addEntry( it.current(), g_resource ); g_bsgf->addNewEntryTo(name, it.current()); } } } bool KBuildSycoca::recreate() { TQString path(sycocaPath()); #ifdef Q_WS_WIN printf("kbuildsycoca: path='%s'\n", (const char*)path); #endif // KSaveFile first writes to a temp file. // Upon close() it moves the stuff to the right place. std::auto_ptr database( new KSaveFile(path) ); if (database->status() == EACCES && TQFile::exists(path)) { TQFile::remove( path ); database.reset( new KSaveFile(path) ); // try again } if (database->status() != 0) { fprintf(stderr, "kbuildsycoca: ERROR creating database '%s'! %s\n", path.local8Bit().data(),strerror(database->status())); #ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build // GUI version of kbuildsycoca, so-called "kbuildsycocaw". if (!silent) KMessageBox::error(0, i18n("Error creating database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n").arg(path.local8Bit().data()), i18n("KBuildSycoca")); #endif return false; } m_str = database->dataStream(); kdDebug(7021) << "Recreating ksycoca file (" << path << ", version " << KSycoca::version() << ")" << endl; // It is very important to build the servicetype one first // Both are registered in KSycoca, no need to keep the pointers KSycocaFactory *stf = new KBuildServiceTypeFactory; g_bsgf = new KBuildServiceGroupFactory(); g_bsf = new KBuildServiceFactory(stf, g_bsgf); (void) new KBuildImageIOFactory(); (void) new KBuildProtocolInfoFactory(); if( build()) // Parse dirs { save(); // Save database if (m_str->tqdevice()->status()) database->abort(); // Error m_str = 0L; if (!database->close()) { fprintf(stderr, "kbuildsycoca: ERROR writing database '%s'!\n", database->name().local8Bit().data()); fprintf(stderr, "kbuildsycoca: Disk full?\n"); #ifdef KBUILDSYCOCA_GUI if (!silent) KMessageBox::error(0, i18n("Error writing database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n").arg(path.local8Bit().data()), i18n("KBuildSycoca")); #endif return false; } } else { m_str = 0L; database->abort(); if (bMenuTest) return true; kdDebug(7021) << "Database is up to date" << endl; } if (!bGlobalDatabase) { // update the timestamp file TQString stamppath = path + "stamp"; TQFile ksycocastamp(stamppath); ksycocastamp.open( IO_WriteOnly ); TQDataStream str( &ksycocastamp ); str << newTimestamp; str << existingResourceDirs(); if (g_vfolder) str << g_vfolder->allDirectories(); // Extra resource dirs } return true; } void KBuildSycoca::save() { // Write header (#pass 1) m_str->tqdevice()->tqat(0); (*m_str) << (TQ_INT32) KSycoca::version(); KSycocaFactory * servicetypeFactory = 0L; KSycocaFactory * serviceFactory = 0L; for(KSycocaFactory *factory = m_lstFactories->first(); factory; factory = m_lstFactories->next()) { TQ_INT32 aId; TQ_INT32 aOffset; aId = factory->factoryId(); if ( aId == KST_KServiceTypeFactory ) servicetypeFactory = factory; else if ( aId == KST_KServiceFactory ) serviceFactory = factory; aOffset = factory->offset(); (*m_str) << aId; (*m_str) << aOffset; } (*m_str) << (TQ_INT32) 0; // No more factories. // Write KDEDIRS (*m_str) << KGlobal::dirs()->kfsstnd_prefixes(); (*m_str) << newTimestamp; (*m_str) << KGlobal::locale()->language(); (*m_str) << KGlobal::dirs()->calcResourceHash("services", "update_ksycoca", true); (*m_str) << (*g_allResourceDirs); // Write factory data.... for(KSycocaFactory *factory = m_lstFactories->first(); factory; factory = m_lstFactories->next()) { factory->save(*m_str); if (m_str->tqdevice()->status()) return; // error } int endOfData = m_str->tqdevice()->tqat(); // Write header (#pass 2) m_str->tqdevice()->tqat(0); (*m_str) << (TQ_INT32) KSycoca::version(); for(KSycocaFactory *factory = m_lstFactories->first(); factory; factory = m_lstFactories->next()) { TQ_INT32 aId; TQ_INT32 aOffset; aId = factory->factoryId(); aOffset = factory->offset(); (*m_str) << aId; (*m_str) << aOffset; } (*m_str) << (TQ_INT32) 0; // No more factories. // Jump to end of database m_str->tqdevice()->tqat(endOfData); } bool KBuildSycoca::checkDirTimestamps( const TQString& dirname, const TQDateTime& stamp, bool top ) { if( top ) { TQFileInfo inf( dirname ); if( inf.lastModified() > stamp ) { kdDebug( 7021 ) << "timestamp changed:" << dirname << endl; return false; } } TQDir dir( dirname ); const TQFileInfoList *list = dir.entryInfoList( TQDir::DefaultFilter, TQDir::Unsorted ); if (!list) return true; for( TQFileInfoListIterator it( *list ); it.current() != NULL; ++it ) { TQFileInfo* fi = it.current(); if( fi->fileName() == "." || fi->fileName() == ".." ) continue; if( fi->lastModified() > stamp ) { kdDebug( 7201 ) << "timestamp changed:" << fi->filePath() << endl; return false; } if( fi->isDir() && !checkDirTimestamps( fi->filePath(), stamp, false )) return false; } return true; } // check times of last modification of all files on which ksycoca depens, // and also their directories // if all of them all older than the timestamp in file ksycocastamp, this // means that there's no need to rebuild ksycoca bool KBuildSycoca::checkTimestamps( TQ_UINT32 timestamp, const TQStringList &dirs ) { kdDebug( 7021 ) << "checking file timestamps" << endl; TQDateTime stamp; stamp.setTime_t( timestamp ); for( TQStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it ) { if( !checkDirTimestamps( *it, stamp, true )) return false; } kdDebug( 7021 ) << "timestamps check ok" << endl; return true; } TQStringList KBuildSycoca::existingResourceDirs() { static TQStringList* dirs = NULL; if( dirs != NULL ) return *dirs; dirs = new TQStringList; g_allResourceDirs = new TQStringList; // these are all resources cached by ksycoca TQStringList resources; resources += KBuildServiceTypeFactory::resourceTypes(); resources += KBuildServiceGroupFactory::resourceTypes(); resources += KBuildServiceFactory::resourceTypes(); resources += KBuildImageIOFactory::resourceTypes(); resources += KBuildProtocolInfoFactory::resourceTypes(); while( !resources.empty()) { TQString res = resources.front(); *dirs += KGlobal::dirs()->resourceDirs( res.latin1()); resources.remove( res ); // remove this 'res' and all its duplicates } *g_allResourceDirs = *dirs; for( TQStringList::Iterator it = dirs->begin(); it != dirs->end(); ) { TQFileInfo inf( *it ); if( !inf.exists() || !inf.isReadable() ) it = dirs->remove( it ); else ++it; } return *dirs; } static KCmdLineOptions options[] = { { "nosignal", I18N_NOOP("Do not signal applications to update"), 0 }, { "noincremental", I18N_NOOP("Disable incremental update, re-read everything"), 0 }, { "checkstamps", I18N_NOOP("Check file timestamps"), 0 }, { "nocheckfiles", I18N_NOOP("Disable checking files (dangerous)"), 0 }, { "global", I18N_NOOP("Create global database"), 0 }, { "menutest", I18N_NOOP("Perform menu generation test run only"), 0 }, { "track ", I18N_NOOP("Track menu id for debug purposes"), 0 }, #ifdef KBUILDSYCOCA_GUI { "silent", I18N_NOOP("Silent - work without windows and stderr"), 0 }, { "showprogress", I18N_NOOP("Show progress information (even if 'silent' mode is on)"), 0 }, #endif KCmdLineLastOption }; static const char appName[] = "kbuildsycoca"; static const char appVersion[] = "1.1"; class WaitForSignal : public QObject { public: ~WaitForSignal() { kapp->eventLoop()->exitLoop(); } }; extern "C" KDE_EXPORT int kdemain(int argc, char **argv) { KLocale::setMainCatalogue("kdelibs"); KAboutData d(appName, I18N_NOOP("KBuildSycoca"), appVersion, I18N_NOOP("Rebuilds the system configuration cache."), KAboutData::License_GPL, "(c) 1999-2002 KDE Developers"); d.addAuthor("David Faure", I18N_NOOP("Author"), "faure@kde.org"); d.addAuthor("Waldo Bastian", I18N_NOOP("Author"), "bastian@kde.org"); KCmdLineArgs::init(argc, argv, &d); KCmdLineArgs::addCmdLineOptions(options); KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); bGlobalDatabase = args->isSet("global"); bMenuTest = args->isSet("menutest"); if (bGlobalDatabase) { setenv("KDEHOME", "-", 1); setenv("KDEROOTHOME", "-", 1); } KApplication::disableAutoDcopRegistration(); #ifdef KBUILDSYCOCA_GUI KApplication k; #else KApplication k(false, false); #endif k.disableSessionManagement(); #ifdef KBUILDSYCOCA_GUI silent = args->isSet("silent"); showprogress = args->isSet("showprogress"); TQLabel progress( TQString("


%1
").arg( i18n("Reloading KDE configuration, please wait...") ), 0, "", Qt::WType_Dialog | Qt::WStyle_DialogBorder | Qt::WStyle_Customize| Qt::WStyle_Title ); TQString capt = i18n("KDE Configuration Manager"); if (!silent) { if (KMessageBox::No == KMessageBox::questionYesNo(0, i18n("Do you want to reload KDE configuration?"), capt, i18n("Reload"), i18n("Do Not Reload"))) return 0; } if (!silent || showprogress) { progress.setCaption( capt ); progress.show(); } #endif KCrash::setCrashHandler(KCrash::defaultCrashHandler); KCrash::setEmergencySaveFunction(crashHandler); KCrash::setApplicationName(TQString(appName)); // this program is in kdelibs so it uses kdelibs as catalog KLocale::setMainCatalogue("kdelibs"); // force generating of KLocale object. if not, the database will get // be translated KGlobal::locale(); KGlobal::dirs()->addResourceType("app-reg", "share/application-registry" ); DCOPClient *dcopClient = new DCOPClient(); while(true) { TQCString registeredName = dcopClient->registerAs(appName, false); if (registeredName.isEmpty()) { fprintf(stderr, "Warning: %s is unable to register with DCOP.\n", appName); break; } else if (registeredName == appName) { break; // Go } fprintf(stderr, "Waiting for already running %s to finish.\n", appName); dcopClient->setNotifications( true ); while (dcopClient->isApplicationRegistered(appName)) { WaitForSignal *obj = new WaitForSignal; obj->connect(dcopClient, TQT_SIGNAL(applicationRemoved(const TQCString &)), TQT_SLOT(deleteLater())); kapp->eventLoop()->enterLoop(); } dcopClient->setNotifications( false ); } fprintf(stderr, "%s running...\n", appName); bool checkfiles = bGlobalDatabase || args->isSet("checkfiles"); bool incremental = !bGlobalDatabase && args->isSet("incremental") && checkfiles; if (incremental || !checkfiles) { KSycoca::self()->disableAutoRebuild(); // Prevent deadlock TQString current_language = KGlobal::locale()->language(); TQString ksycoca_language = KSycoca::self()->language(); TQ_UINT32 current_update_sig = KGlobal::dirs()->calcResourceHash("services", "update_ksycoca", true); TQ_UINT32 ksycoca_update_sig = KSycoca::self()->updateSignature(); if ((current_update_sig != ksycoca_update_sig) || (current_language != ksycoca_language) || (KSycoca::self()->timeStamp() == 0)) { incremental = false; checkfiles = true; delete KSycoca::self(); } } g_changeList = new TQStringList; bool checkstamps = incremental && args->isSet("checkstamps") && checkfiles; TQ_UINT32 filestamp = 0; TQStringList oldresourcedirs; if( checkstamps && incremental ) { TQString path = sycocaPath()+"stamp"; TQCString qPath = TQFile::encodeName(path); cSycocaPath = qPath.data(); // Delete timestamps on crash TQFile ksycocastamp(path); if( ksycocastamp.open( IO_ReadOnly )) { TQDataStream str( &ksycocastamp ); if (!str.atEnd()) str >> filestamp; if (!str.atEnd()) { str >> oldresourcedirs; if( oldresourcedirs != KBuildSycoca::existingResourceDirs()) checkstamps = false; } else { checkstamps = false; } if (!str.atEnd()) { TQStringList extraResourceDirs; str >> extraResourceDirs; oldresourcedirs += extraResourceDirs; } } else { checkstamps = false; } cSycocaPath = 0; } newTimestamp = (TQ_UINT32) time(0); if( checkfiles && ( !checkstamps || !KBuildSycoca::checkTimestamps( filestamp, oldresourcedirs ))) { TQCString qSycocaPath = TQFile::encodeName(sycocaPath()); cSycocaPath = qSycocaPath.data(); g_allEntries = 0; g_ctimeDict = 0; if (incremental) { qWarning("Reusing existing ksycoca"); KSycoca *oldSycoca = KSycoca::self(); KSycocaFactoryList *factories = new KSycocaFactoryList; g_allEntries = new KSycocaEntryListList; g_ctimeDict = new TQDict(523); // Must be in same order as in KBuildSycoca::recreate()! factories->append( new KServiceTypeFactory ); factories->append( new KServiceGroupFactory ); factories->append( new KServiceFactory ); factories->append( new KImageIOFactory ); factories->append( new KProtocolInfoFactory ); // For each factory for (KSycocaFactory *factory = factories->first(); factory; factory = factories->next() ) { KSycocaEntry::List list; list = factory->allEntries(); g_allEntries->append( list ); } delete factories; factories = 0; KCTimeInfo *ctimeInfo = new KCTimeInfo; ctimeInfo->fillCTimeDict(*g_ctimeDict); delete oldSycoca; } cSycocaPath = 0; KBuildSycoca *sycoca= new KBuildSycoca; // Build data base if (args->isSet("track")) sycoca->setTrackId(TQString::fromLocal8Bit(args->getOption("track"))); if (!sycoca->recreate()) { #ifdef KBUILDSYCOCA_GUI if (!silent || showprogress) progress.close(); #endif return -1; } if (bGlobalDatabase) { // These directories may have been created with 0700 permission // better delete them if they are empty TQString applnkDir = KGlobal::dirs()->saveLocation("apps", TQString::null, false); ::rmdir(TQFile::encodeName(applnkDir)); TQString servicetypesDir = KGlobal::dirs()->saveLocation("servicetypes", TQString::null, false); ::rmdir(TQFile::encodeName(servicetypesDir)); } } if (!bGlobalDatabase) { // Recreate compatibility symlink TQString oldPath = oldSycocaPath(); if (!oldPath.isEmpty()) { KTempFile tmp; if (tmp.status() == 0) { TQString tmpFile = tmp.name(); tmp.unlink(); symlink(TQFile::encodeName(sycocaPath()), TQFile::encodeName(tmpFile)); rename(TQFile::encodeName(tmpFile), TQFile::encodeName(oldPath)); } } } if (args->isSet("signal")) { // Notify ALL applications that have a ksycoca object, using a broadcast TQByteArray data; TQDataStream stream(data, IO_WriteOnly); stream << *g_changeList; dcopClient->send( "*", "ksycoca", "notifyDatabaseChanged(TQStringList)", data ); } #ifdef KBUILDSYCOCA_GUI if (!silent) { progress.close(); KMessageBox::information(0, i18n("Configuration information reloaded successfully."), capt); } #endif return 0; } #include "kbuildsycoca.moc"