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