00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kbuildsycoca.h"
00022 #include "ksycoca_p.h"
00023 #include "kresourcelist.h"
00024 #include "vfolder_menu.h"
00025
00026 #include <config.h>
00027
00028 #include <kservice.h>
00029 #include <kmimetype.h>
00030 #include "kbuildservicetypefactory.h"
00031 #include "kbuildmimetypefactory.h"
00032 #include "kbuildservicefactory.h"
00033 #include "kbuildservicegroupfactory.h"
00034 #include "kbuildprotocolinfofactory.h"
00035 #include "kctimefactory.h"
00036 #include <ktemporaryfile.h>
00037 #include <QtCore/QDataStream>
00038 #include <QtCore/QDir>
00039 #include <QtCore/QEventLoop>
00040 #include <QtCore/QFile>
00041 #include <QtCore/QTimer>
00042 #include <QtDBus/QtDBus>
00043 #include <errno.h>
00044
00045 #include <assert.h>
00046 #include <kapplication.h>
00047 #include <kglobal.h>
00048 #include <kdebug.h>
00049 #include <kdirwatch.h>
00050 #include <kstandarddirs.h>
00051 #include <ksavefile.h>
00052 #include <klocale.h>
00053 #include <kaboutdata.h>
00054 #include <kcmdlineargs.h>
00055 #include <kcrash.h>
00056 #include <kmemfile.h>
00057
00058 #ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build
00059
00060 # include <qlabel.h>
00061 # include <kmessagebox.h>
00062 bool silent;
00063 bool showprogress;
00064 #endif
00065
00066 #include <stdlib.h>
00067 #include <unistd.h>
00068 #include <time.h>
00069 #include <memory>
00070
00071 typedef QHash<QString, KSycocaEntry::Ptr> KBSEntryDict;
00072 typedef QList<KSycocaEntry::List> KSycocaEntryListList;
00073
00074 static quint32 newTimestamp = 0;
00075
00076 static KBuildServiceFactory *g_bsf = 0;
00077 static KBuildServiceGroupFactory *g_bsgf = 0;
00078 static KSycocaFactory *g_factory = 0;
00079 static KCTimeInfo *g_ctimeInfo = 0;
00080 static QHash<QString, quint32> *g_ctimeDict = 0;
00081 static QByteArray g_resource = 0;
00082 static KBSEntryDict *g_entryDict = 0;
00083 static KBSEntryDict *g_serviceGroupEntryDict = 0;
00084 static KSycocaEntryListList *g_allEntries = 0;
00085 static QStringList *g_changeList = 0;
00086 static QStringList *g_allResourceDirs = 0;
00087 static bool g_changed = false;
00088 static KSycocaEntry::List g_tempStorage;
00089 static VFolderMenu *g_vfolder = 0;
00090
00091 static const char *cSycocaPath = 0;
00092
00093 static bool bGlobalDatabase = false;
00094 static bool bMenuTest = false;
00095
00096 void crashHandler(int)
00097 {
00098
00099
00100 if (cSycocaPath)
00101 unlink(cSycocaPath);
00102 }
00103
00104 static QString sycocaPath()
00105 {
00106 return KSycoca::absoluteFilePath(bGlobalDatabase ? KSycoca::GlobalDatabase : KSycoca::LocalDatabase);
00107 }
00108
00109 KBuildSycoca::KBuildSycoca()
00110 : KSycoca( true )
00111 {
00112 }
00113
00114 KBuildSycoca::~KBuildSycoca()
00115 {
00116
00117 }
00118
00119 KSycocaEntry::Ptr KBuildSycoca::createEntry(const QString &file, bool addToFactory)
00120 {
00121 quint32 timeStamp = g_ctimeInfo->ctime(file);
00122 if (!timeStamp)
00123 {
00124 timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, file,
00125 KStandardDirs::Recursive);
00126 }
00127 KSycocaEntry::Ptr entry;
00128 if (g_allEntries)
00129 {
00130 assert(g_ctimeDict);
00131 quint32 oldTimestamp = g_ctimeDict->value( file, 0 );
00132
00133 if (timeStamp && (timeStamp == oldTimestamp))
00134 {
00135
00136 if (g_factory == g_bsgf)
00137 {
00138 entry = g_entryDict->value(file.left(file.length()-10));
00139 } else {
00140 entry = g_entryDict->value(file);
00141 }
00142
00143
00144
00145 g_ctimeDict->remove( file );
00146 }
00147 else if (oldTimestamp)
00148 {
00149 g_changed = true;
00150 kDebug(7021) << "modified:" << file;
00151 }
00152 else
00153 {
00154 g_changed = true;
00155 kDebug(7021) << "new:" << file;
00156 }
00157 }
00158 g_ctimeInfo->addCTime(file, timeStamp );
00159 if (!entry)
00160 {
00161
00162 entry = g_factory->createEntry( file, g_resource );
00163 }
00164 if ( entry && entry->isValid() )
00165 {
00166 if (addToFactory)
00167 g_factory->addEntry(entry);
00168 else
00169 g_tempStorage.append(entry);
00170 return entry;
00171 }
00172 return KSycocaEntry::Ptr();
00173 }
00174
00175
00176 void KBuildSycoca::slotCreateEntry(const QString &file, KService::Ptr *service)
00177 {
00178 KSycocaEntry::Ptr entry = createEntry(file, false);
00179 *service = KService::Ptr::staticCast( entry );
00180 }
00181
00182
00183 bool KBuildSycoca::build()
00184 {
00185 typedef QLinkedList<KBSEntryDict *> KBSEntryDictList;
00186 KBSEntryDictList entryDictList;
00187 KBSEntryDict *serviceEntryDict = 0;
00188
00189
00190 int i = 0;
00191
00192 for (KSycocaFactoryList::Iterator factory = factories()->begin();
00193 factory != factories()->end();
00194 ++factory)
00195 {
00196 KBSEntryDict *entryDict = new KBSEntryDict;
00197 if (g_allEntries)
00198 {
00199 const KSycocaEntry::List list = (*g_allEntries)[i++];
00200 for( KSycocaEntry::List::const_iterator it = list.begin();
00201 it != list.end();
00202 ++it)
00203 {
00204 entryDict->insert( (*it)->entryPath(), *it );
00205 }
00206 }
00207 if ((*factory) == g_bsf)
00208 serviceEntryDict = entryDict;
00209 else if ((*factory) == g_bsgf)
00210 g_serviceGroupEntryDict = entryDict;
00211 entryDictList.append(entryDict);
00212 }
00213
00214 QStringList allResources;
00215
00216 for (KSycocaFactoryList::Iterator factory = factories()->begin();
00217 factory != factories()->end();
00218 ++factory)
00219 {
00220
00221 const KSycocaResourceList *list = (*factory)->resourceList();
00222 if (!list) continue;
00223
00224 for( KSycocaResourceList::ConstIterator it1 = list->constBegin();
00225 it1 != list->constEnd();
00226 ++it1 )
00227 {
00228 KSycocaResource res = (*it1);
00229 if (!allResources.contains(res.resource))
00230 allResources.append(res.resource);
00231 }
00232 }
00233
00234 g_ctimeInfo = new KCTimeInfo();
00235 bool uptodate = true;
00236
00237 for( QStringList::ConstIterator it1 = allResources.constBegin();
00238 it1 != allResources.constEnd();
00239 ++it1 )
00240 {
00241 g_changed = false;
00242 g_resource = (*it1).toLatin1();
00243
00244 QStringList relFiles;
00245
00246 (void) KGlobal::dirs()->findAllResources( g_resource,
00247 QString(),
00248 KStandardDirs::Recursive |
00249 KStandardDirs::NoDuplicates,
00250 relFiles);
00251
00252
00253
00254
00255 KBSEntryDictList::const_iterator ed_it = entryDictList.begin();
00256 const KBSEntryDictList::const_iterator ed_end = entryDictList.end();
00257 KSycocaFactoryList::const_iterator it = factories()->constBegin();
00258 const KSycocaFactoryList::const_iterator end = factories()->constEnd();
00259 for ( ; it != end; ++it, ++ed_it )
00260 {
00261 g_factory = (*it);
00262
00263 g_entryDict = ed_it == ed_end ? 0 : *ed_it;
00264
00265 const KSycocaResourceList *list = g_factory->resourceList();
00266 if (!list) continue;
00267
00268 for( KSycocaResourceList::ConstIterator it2 = list->constBegin();
00269 it2 != list->constEnd();
00270 ++it2 )
00271 {
00272 KSycocaResource res = (*it2);
00273 if (res.resource != (*it1)) continue;
00274
00275
00276 for( QStringList::ConstIterator it3 = relFiles.constBegin();
00277 it3 != relFiles.constEnd();
00278 ++it3 )
00279 {
00280
00281 if ((*it3).endsWith(res.extension))
00282 createEntry(*it3, true);
00283 }
00284 }
00285 }
00286 if (g_changed || !g_allEntries)
00287 {
00288 uptodate = false;
00289 g_changeList->append(g_resource);
00290 }
00291 }
00292
00293 bool result = !uptodate || (g_ctimeDict && !g_ctimeDict->isEmpty());
00294
00295 if (result || bMenuTest)
00296 {
00297 g_resource = "apps";
00298 g_factory = g_bsf;
00299 g_entryDict = serviceEntryDict;
00300 g_changed = false;
00301
00302 g_vfolder = new VFolderMenu(g_bsf);
00303 if (!m_trackId.isEmpty())
00304 g_vfolder->setTrackId(m_trackId);
00305
00306 connect(g_vfolder, SIGNAL(newService(const QString &, KService::Ptr *)),
00307 this, SLOT(slotCreateEntry(const QString &, KService::Ptr *)));
00308
00309 VFolderMenu::SubMenu *kdeMenu = g_vfolder->parseMenu("applications.menu", true);
00310
00311 KServiceGroup::Ptr entry = g_bsgf->addNew("/", kdeMenu->directoryFile, KServiceGroup::Ptr(), false);
00312 entry->setLayoutInfo(kdeMenu->layoutList);
00313 createMenu(QString(), QString(), kdeMenu);
00314
00315 (void) existingResourceDirs();
00316 *g_allResourceDirs += g_vfolder->allDirectories();
00317
00318 disconnect(g_vfolder, SIGNAL(newService(const QString &, KService::Ptr *)),
00319 this, SLOT(slotCreateEntry(const QString &, KService::Ptr *)));
00320
00321 if (g_changed || !g_allEntries)
00322 {
00323 uptodate = false;
00324 g_changeList->append(g_resource);
00325 }
00326 if (bMenuTest) {
00327 result = false;
00328 }
00329 }
00330
00331 qDeleteAll(entryDictList);
00332 return result;
00333 }
00334
00335 void KBuildSycoca::createMenu(const QString &caption_, const QString &name_, VFolderMenu::SubMenu *menu)
00336 {
00337 QString caption = caption_;
00338 QString name = name_;
00339 foreach (VFolderMenu::SubMenu *subMenu, menu->subMenus)
00340 {
00341 QString subName = name+subMenu->name+'/';
00342
00343 QString directoryFile = subMenu->directoryFile;
00344 if (directoryFile.isEmpty())
00345 directoryFile = subName+".directory";
00346 quint32 timeStamp = g_ctimeInfo->ctime(directoryFile);
00347 if (!timeStamp) {
00348 timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, directoryFile,
00349 KStandardDirs::Recursive );
00350 }
00351
00352 KServiceGroup::Ptr entry;
00353 if (g_allEntries)
00354 {
00355 quint32 oldTimestamp = g_ctimeDict->value( directoryFile, 0 );
00356
00357 if (timeStamp && (timeStamp == oldTimestamp))
00358 {
00359 KSycocaEntry::Ptr group = g_serviceGroupEntryDict->value(subName);
00360 if ( group )
00361 {
00362 entry = KServiceGroup::Ptr::staticCast( group );
00363 if (entry->directoryEntryPath() != directoryFile)
00364 entry = 0;
00365 }
00366 }
00367 }
00368 g_ctimeInfo->addCTime(directoryFile, timeStamp);
00369
00370 entry = g_bsgf->addNew(subName, subMenu->directoryFile, entry, subMenu->isDeleted);
00371 entry->setLayoutInfo(subMenu->layoutList);
00372 if (! (bMenuTest && entry->noDisplay()) )
00373 createMenu(caption + entry->caption() + '/', subName, subMenu);
00374 }
00375 if (caption.isEmpty())
00376 caption += '/';
00377 if (name.isEmpty())
00378 name += '/';
00379 foreach (const KService::Ptr &p, menu->items)
00380 {
00381 if (bMenuTest)
00382 {
00383 if (!menu->isDeleted && !p->noDisplay())
00384 printf("%s\t%s\t%s\n", qPrintable( caption ), qPrintable( p->menuId() ), qPrintable( KStandardDirs::locate("apps", p->entryPath() ) ) );
00385 }
00386 else
00387 {
00388 g_bsgf->addNewEntryTo( name, p );
00389 }
00390 }
00391 }
00392
00393 bool KBuildSycoca::recreate()
00394 {
00395 QString path(sycocaPath());
00396
00397
00398
00399 KSaveFile database(path);
00400 bool openedOK = database.open();
00401 if (!openedOK && database.error() == QFile::PermissionsError && QFile::exists(path))
00402 {
00403 QFile::remove( path );
00404 openedOK = database.open();
00405 }
00406 if (!openedOK)
00407 {
00408 fprintf(stderr, "kbuildsycoca4: ERROR creating database '%s'! %s\n",
00409 path.toLocal8Bit().data(), database.errorString().toLocal8Bit().data());
00410 #ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build
00411
00412 if (!silent)
00413 KMessageBox::error(0, i18n("Error creating database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n", path.toLocal8Bit().data()), i18n("KBuildSycoca"));
00414 #endif
00415 return false;
00416 }
00417
00418 QDataStream* str = new QDataStream(&database);
00419 str->setVersion(QDataStream::Qt_3_1);
00420
00421 kDebug(7021).nospace() << "Recreating ksycoca file (" << path << ", version " << KSycoca::version() << ")";
00422
00423
00424
00425 KSycocaFactory *stf = new KBuildServiceTypeFactory;
00426 KBuildMimeTypeFactory *mtf = new KBuildMimeTypeFactory;
00427 g_bsgf = new KBuildServiceGroupFactory();
00428 g_bsf = new KBuildServiceFactory(stf, mtf, g_bsgf);
00429 (void) new KBuildProtocolInfoFactory();
00430
00431 if( build())
00432 {
00433 save(str);
00434 if (str->status() != QDataStream::Ok)
00435 database.abort();
00436 delete str;
00437 str = 0;
00438 if (!database.finalize())
00439 {
00440 fprintf(stderr, "kbuildsycoca4: ERROR writing database '%s'!\n", database.fileName().toLocal8Bit().data());
00441 fprintf(stderr, "kbuildsycoca4: Disk full?\n");
00442 #ifdef KBUILDSYCOCA_GUI
00443 if (!silent)
00444 KMessageBox::error(0, i18n("Error writing database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n", path.toLocal8Bit().data()), i18n("KBuildSycoca"));
00445 #endif
00446 return false;
00447 }
00448 }
00449 else
00450 {
00451 delete str;
00452 str = 0;
00453 database.abort();
00454 if (bMenuTest)
00455 return true;
00456 kDebug(7021) << "Database is up to date";
00457 }
00458
00459 if (!bGlobalDatabase)
00460 {
00461
00462 QString stamppath = path + "stamp";
00463 QFile ksycocastamp(stamppath);
00464 ksycocastamp.open( QIODevice::WriteOnly );
00465 QDataStream str( &ksycocastamp );
00466 str.setVersion(QDataStream::Qt_3_1);
00467 str << newTimestamp;
00468 str << existingResourceDirs();
00469 if (g_vfolder)
00470 str << g_vfolder->allDirectories();
00471 }
00472 if (d->m_sycocaStrategy == KSycocaPrivate::StrategyMemFile)
00473 KMemFile::fileContentsChanged(path);
00474
00475 return true;
00476 }
00477
00478 void KBuildSycoca::save(QDataStream* str)
00479 {
00480
00481 str->device()->seek(0);
00482
00483 (*str) << (qint32) KSycoca::version();
00484 KSycocaFactory * servicetypeFactory = 0;
00485 KBuildMimeTypeFactory * mimeTypeFactory = 0;
00486 KBuildServiceFactory * serviceFactory = 0;
00487 for(KSycocaFactoryList::Iterator factory = factories()->begin();
00488 factory != factories()->end();
00489 ++factory)
00490 {
00491 qint32 aId;
00492 qint32 aOffset;
00493 aId = (*factory)->factoryId();
00494 if ( aId == KST_KServiceTypeFactory )
00495 servicetypeFactory = *factory;
00496 else if ( aId == KST_KMimeTypeFactory )
00497 mimeTypeFactory = static_cast<KBuildMimeTypeFactory *>( *factory );
00498 else if ( aId == KST_KServiceFactory )
00499 serviceFactory = static_cast<KBuildServiceFactory *>( *factory );
00500 aOffset = (*factory)->offset();
00501 (*str) << aId;
00502 (*str) << aOffset;
00503 }
00504 (*str) << (qint32) 0;
00505
00506 (*str) << KGlobal::dirs()->kfsstnd_prefixes();
00507 (*str) << newTimestamp;
00508 (*str) << KGlobal::locale()->language();
00509 (*str) << KGlobal::dirs()->calcResourceHash("services", "update_ksycoca",
00510 KStandardDirs::Recursive );
00511 (*str) << (*g_allResourceDirs);
00512
00513
00514 mimeTypeFactory->parseSubclasses();
00515 serviceFactory->postProcessServices();
00516
00517
00518 kDebug(7021) << "Saving";
00519
00520
00521 for(KSycocaFactoryList::Iterator factory = factories()->begin();
00522 factory != factories()->end();
00523 ++factory)
00524 {
00525 (*factory)->save(*str);
00526 if (str->status() != QDataStream::Ok)
00527 return;
00528 }
00529
00530 int endOfData = str->device()->pos();
00531
00532
00533 str->device()->seek(0);
00534
00535 (*str) << (qint32) KSycoca::version();
00536 for(KSycocaFactoryList::Iterator factory = factories()->begin();
00537 factory != factories()->end(); ++factory)
00538 {
00539 qint32 aId;
00540 qint32 aOffset;
00541 aId = (*factory)->factoryId();
00542 aOffset = (*factory)->offset();
00543 (*str) << aId;
00544 (*str) << aOffset;
00545 }
00546 (*str) << (qint32) 0;
00547
00548
00549 str->device()->seek(endOfData);
00550 }
00551
00552 bool KBuildSycoca::checkDirTimestamps( const QString& dirname, const QDateTime& stamp, bool top )
00553 {
00554 if( top )
00555 {
00556 QFileInfo inf( dirname );
00557 if( inf.lastModified() > stamp ) {
00558 kDebug( 7021 ) << "timestamp changed:" << dirname;
00559 return false;
00560 }
00561 }
00562 QDir dir( dirname );
00563 const QFileInfoList list = dir.entryInfoList( QDir::NoFilter, QDir::Unsorted );
00564 if (list.isEmpty())
00565 return true;
00566
00567 foreach ( const QFileInfo& fi, list ) {
00568 if( fi.fileName() == "." || fi.fileName() == ".." )
00569 continue;
00570 if( fi.lastModified() > stamp )
00571 {
00572 kDebug( 7201 ) << "timestamp changed:" << fi.filePath();
00573 return false;
00574 }
00575 if( fi.isDir() && !checkDirTimestamps( fi.filePath(), stamp, false ))
00576 return false;
00577 }
00578 return true;
00579 }
00580
00581
00582
00583
00584
00585 bool KBuildSycoca::checkTimestamps( quint32 timestamp, const QStringList &dirs )
00586 {
00587 kDebug( 7021 ) << "checking file timestamps";
00588 QDateTime stamp;
00589 stamp.setTime_t( timestamp );
00590 for( QStringList::ConstIterator it = dirs.begin();
00591 it != dirs.end();
00592 ++it )
00593 {
00594 if( !checkDirTimestamps( *it, stamp, true ))
00595 return false;
00596 }
00597 kDebug( 7021 ) << "timestamps check ok";
00598 return true;
00599 }
00600
00601 QStringList KBuildSycoca::existingResourceDirs()
00602 {
00603 static QStringList* dirs = NULL;
00604 if( dirs != NULL )
00605 return *dirs;
00606 dirs = new QStringList;
00607 g_allResourceDirs = new QStringList;
00608
00609 QStringList resources;
00610 resources += KBuildServiceTypeFactory::resourceTypes();
00611 resources += KBuildMimeTypeFactory::resourceTypes();
00612 resources += KBuildServiceGroupFactory::resourceTypes();
00613 resources += KBuildServiceFactory::resourceTypes();
00614 resources += KBuildProtocolInfoFactory::resourceTypes();
00615 while( !resources.empty())
00616 {
00617 QString res = resources.front();
00618 *dirs += KGlobal::dirs()->resourceDirs( res.toLatin1());
00619 resources.removeAll( res );
00620 }
00621
00622 *g_allResourceDirs = *dirs;
00623
00624 for( QStringList::Iterator it = dirs->begin();
00625 it != dirs->end(); )
00626 {
00627 QFileInfo inf( *it );
00628 if( !inf.exists() || !inf.isReadable() )
00629 it = dirs->erase( it );
00630 else
00631 ++it;
00632 }
00633 return *dirs;
00634 }
00635
00636 static const char appFullName[] = "org.kde.kbuildsycoca";
00637 static const char appName[] = "kbuildsycoca4";
00638 static const char appVersion[] = "1.1";
00639
00640 extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
00641 {
00642 KAboutData d(appName, "kdelibs4", ki18n("KBuildSycoca"), appVersion,
00643 ki18n("Rebuilds the system configuration cache."),
00644 KAboutData::License_GPL, ki18n("(c) 1999-2002 KDE Developers"));
00645 d.addAuthor(ki18n("David Faure"), ki18n("Author"), "faure@kde.org");
00646 d.addAuthor(ki18n("Waldo Bastian"), ki18n("Author"), "bastian@kde.org");
00647
00648 KCmdLineOptions options;
00649 options.add("nosignal", ki18n("Do not signal applications to update"));
00650 options.add("noincremental", ki18n("Disable incremental update, re-read everything"));
00651 options.add("checkstamps", ki18n("Check file timestamps"));
00652 options.add("nocheckfiles", ki18n("Disable checking files (dangerous)"));
00653 options.add("global", ki18n("Create global database"));
00654 options.add("menutest", ki18n("Perform menu generation test run only"));
00655 options.add("track <menu-id>", ki18n("Track menu id for debug purposes"));
00656 #ifdef KBUILDSYCOCA_GUI
00657 options.add("silent", ki18n("Silent - work without windows and stderr"));
00658 options.add("showprogress", ki18n("Show progress information (even if 'silent' mode is on)"));
00659 #endif
00660
00661 KCmdLineArgs::init(argc, argv, &d);
00662 KCmdLineArgs::addCmdLineOptions(options);
00663 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00664 bGlobalDatabase = args->isSet("global");
00665 bMenuTest = args->isSet("menutest");
00666
00667 if (bGlobalDatabase)
00668 {
00669 setenv("KDEHOME", "-", 1);
00670 setenv("KDEROOTHOME", "-", 1);
00671 }
00672
00673 #ifdef KBUILDSYCOCA_GUI
00674 KApplication k;
00675 #else
00676 KApplication k(false);
00677 #endif
00678 k.disableSessionManagement();
00679
00680 #ifdef KBUILDSYCOCA_GUI
00681 silent = args->isSet("silent");
00682 showprogress = args->isSet("showprogress");
00683 QLabel progress( QString("<p><br><nobr> %1 </nobr><br>").arg( i18n("Reloading KDE configuration, please wait...") ), 0, "", Qt::WType_Dialog | Qt::WStyle_DialogBorder | Qt::WStyle_Customize| Qt::WStyle_Title );
00684 QString capt = i18n("KDE Configuration Manager");
00685 if (!silent) {
00686 if (KMessageBox::No == KMessageBox::questionYesNo(0, i18n("Do you want to reload KDE configuration?"), capt, i18nc("Reload KDE configuration messagebox", "Reload"), i18n("Do Not Reload")))
00687 return 0;
00688 }
00689 if (!silent || showprogress) {
00690 progress.setCaption( capt );
00691 progress.show();
00692 }
00693 #endif
00694
00695 KCrash::setCrashHandler(KCrash::defaultCrashHandler);
00696 KCrash::setEmergencySaveFunction(crashHandler);
00697 KCrash::setApplicationName(QString(appName));
00698
00699
00700
00701 KGlobal::locale();
00702 KGlobal::dirs()->addResourceType("app-reg", 0, "share/application-registry" );
00703
00704 while(QDBusConnection::sessionBus().isConnected())
00705 {
00706
00707
00708 if (QDBusConnection::sessionBus().interface()->registerService(appFullName, QDBusConnectionInterface::QueueService)
00709 != QDBusConnectionInterface::ServiceQueued)
00710 {
00711 break;
00712 }
00713 fprintf(stderr, "Waiting for already running %s to finish.\n", appName);
00714
00715 QEventLoop eventLoop;
00716 QObject::connect(QDBusConnection::sessionBus().interface(), SIGNAL(serviceRegistered(QString)),
00717 &eventLoop, SLOT(quit()));
00718 eventLoop.exec( QEventLoop::ExcludeUserInputEvents );
00719 }
00720 fprintf(stderr, "%s running...\n", appName);
00721
00722 bool checkfiles = bGlobalDatabase || args->isSet("checkfiles");
00723
00724 bool incremental = !bGlobalDatabase && args->isSet("incremental") && checkfiles;
00725 if (incremental || !checkfiles)
00726 {
00727 KSycoca::disableAutoRebuild();
00728 QString current_language = KGlobal::locale()->language();
00729 QString ksycoca_language = KSycoca::self()->language();
00730 quint32 current_update_sig = KGlobal::dirs()->calcResourceHash("services", "update_ksycoca",
00731 KStandardDirs::Recursive );
00732 quint32 ksycoca_update_sig = KSycoca::self()->updateSignature();
00733 QString current_prefixes = KGlobal::dirs()->kfsstnd_prefixes();
00734 QString ksycoca_prefixes = KSycoca::self()->kfsstnd_prefixes();
00735
00736 if ((current_update_sig != ksycoca_update_sig) ||
00737 (current_language != ksycoca_language) ||
00738 (current_prefixes != ksycoca_prefixes) ||
00739 (KSycoca::self()->timeStamp() == 0))
00740 {
00741 incremental = false;
00742 checkfiles = true;
00743 KBuildSycoca::clearCaches();
00744 }
00745 }
00746
00747 g_changeList = new QStringList;
00748
00749 bool checkstamps = incremental && args->isSet("checkstamps") && checkfiles;
00750 quint32 filestamp = 0;
00751 QStringList oldresourcedirs;
00752 if( checkstamps && incremental )
00753 {
00754 QString path = sycocaPath()+"stamp";
00755 QByteArray qPath = QFile::encodeName(path);
00756 cSycocaPath = qPath.data();
00757 QFile ksycocastamp(path);
00758 if( ksycocastamp.open( QIODevice::ReadOnly ))
00759 {
00760 QDataStream str( &ksycocastamp );
00761 str.setVersion(QDataStream::Qt_3_1);
00762
00763 if (!str.atEnd())
00764 str >> filestamp;
00765 if (!str.atEnd())
00766 {
00767 str >> oldresourcedirs;
00768 if( oldresourcedirs != KBuildSycoca::existingResourceDirs())
00769 checkstamps = false;
00770 }
00771 else
00772 {
00773 checkstamps = false;
00774 }
00775 if (!str.atEnd())
00776 {
00777 QStringList extraResourceDirs;
00778 str >> extraResourceDirs;
00779 oldresourcedirs += extraResourceDirs;
00780 }
00781 }
00782 else
00783 {
00784 checkstamps = false;
00785 }
00786 cSycocaPath = 0;
00787 }
00788
00789 newTimestamp = (quint32) time(0);
00790
00791 if( checkfiles && ( !checkstamps || !KBuildSycoca::checkTimestamps( filestamp, oldresourcedirs )))
00792 {
00793 QByteArray qSycocaPath = QFile::encodeName(sycocaPath());
00794 cSycocaPath = qSycocaPath.data();
00795
00796 g_allEntries = 0;
00797 g_ctimeDict = 0;
00798 if (incremental)
00799 {
00800 kDebug(7021) << "Reusing existing ksycoca";
00801 KSycoca::self();
00802 KSycocaFactoryList *factories = new KSycocaFactoryList;
00803 g_allEntries = new KSycocaEntryListList;
00804 g_ctimeDict = new QHash<QString, quint32>;
00805
00806
00807 factories->append( new KServiceTypeFactory );
00808 factories->append( new KMimeTypeFactory );
00809 factories->append( new KServiceGroupFactory );
00810 factories->append( new KServiceFactory );
00811 factories->append( new KProtocolInfoFactory );
00812
00813
00814 for (KSycocaFactoryList::Iterator factory = factories->begin();
00815 factory != factories->end(); ++factory)
00816 {
00817 const KSycocaEntry::List list = (*factory)->allEntries();
00818 g_allEntries->append( list );
00819 }
00820 delete factories; factories = 0;
00821 KCTimeInfo *ctimeInfo = new KCTimeInfo;
00822 ctimeInfo->fillCTimeDict(*g_ctimeDict);
00823 }
00824 cSycocaPath = 0;
00825
00826 KBuildSycoca *sycoca = new KBuildSycoca;
00827 if (args->isSet("track"))
00828 sycoca->setTrackId(args->getOption("track"));
00829 if (!sycoca->recreate()) {
00830 #ifdef KBUILDSYCOCA_GUI
00831 if (!silent || showprogress)
00832 progress.close();
00833 #endif
00834 return -1;
00835 }
00836
00837 if (bGlobalDatabase)
00838 {
00839
00840
00841 QString applnkDir = KGlobal::dirs()->saveLocation("apps", QString(), false);
00842 ::rmdir(QFile::encodeName(applnkDir));
00843 QString servicetypesDir = KGlobal::dirs()->saveLocation("servicetypes", QString(), false);
00844 ::rmdir(QFile::encodeName(servicetypesDir));
00845 }
00846 }
00847
00848 if (args->isSet("signal"))
00849 {
00850
00851 QDBusMessage signal = QDBusMessage::createSignal("/", "org.kde.KSycoca", "notifyDatabaseChanged" );
00852 signal << *g_changeList;
00853
00854 if (QDBusConnection::sessionBus().isConnected()) {
00855 kDebug() << "Emitting notifyDatabaseChanged" << *g_changeList;
00856 QDBusConnection::sessionBus().send(signal);
00857 qApp->processEvents();
00858 }
00859 }
00860
00861 #ifdef KBUILDSYCOCA_GUI
00862 if (!silent) {
00863 progress.close();
00864 KMessageBox::information(0, i18n("Configuration information reloaded successfully."), capt);
00865 }
00866 #endif
00867 return 0;
00868 }
00869
00870 #include "kbuildsycoca.moc"