• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDED

  • kded
kbuildsycoca.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 3 -*-
2/* This file is part of the KDE libraries
3 * Copyright (C) 1999 David Faure <faure@kde.org>
4 * Copyright (C) 2002-2003 Waldo Bastian <bastian@kde.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License version 2 as published by the Free Software Foundation;
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 **/
20
21#include "kbuildsycoca.h"
22#include "ksycoca_p.h"
23#include "ksycocaresourcelist.h"
24#include "vfolder_menu.h"
25
26#include <config.h>
27#include <config-kded.h>
28
29#include <kservice.h>
30#include <kmimetype.h>
31#include "kbuildservicetypefactory.h"
32#include "kbuildmimetypefactory.h"
33#include "kbuildservicefactory.h"
34#include "kbuildservicegroupfactory.h"
35#include "kbuildprotocolinfofactory.h"
36#include "kctimefactory.h"
37#include <ktemporaryfile.h>
38#include <QtCore/QDataStream>
39#include <QtCore/QDir>
40#include <QtCore/QEventLoop>
41#include <QtCore/QFile>
42#include <QtCore/QTimer>
43#include <QtDBus/QtDBus>
44#include <errno.h>
45
46#include <assert.h>
47#include <kapplication.h>
48#include <kglobal.h>
49#include <kdebug.h>
50#include <kdirwatch.h>
51#include <kstandarddirs.h>
52#include <ksavefile.h>
53#include <klocale.h>
54#include <kaboutdata.h>
55#include <kcmdlineargs.h>
56#ifndef KBUILDSYCOCA_NO_KCRASH
57#include <kcrash.h>
58#endif
59#include <kmemfile.h>
60
61#include <stdlib.h>
62#include <unistd.h>
63#include <time.h>
64#include <memory> // auto_ptr
65
66typedef QHash<QString, KSycocaEntry::Ptr> KBSEntryDict;
67typedef QList<KSycocaEntry::List> KSycocaEntryListList;
68
69static quint32 newTimestamp = 0;
70
71static KBuildServiceFactory *g_serviceFactory = 0;
72static KBuildServiceGroupFactory *g_buildServiceGroupFactory = 0;
73static KSycocaFactory *g_currentFactory = 0;
74static KCTimeInfo *g_ctimeInfo = 0; // factory
75static KCTimeDict *g_ctimeDict = 0; // old timestamps
76static QByteArray g_resource = 0;
77static KBSEntryDict *g_currentEntryDict = 0;
78static KBSEntryDict *g_serviceGroupEntryDict = 0;
79static KSycocaEntryListList *g_allEntries = 0; // entries from existing ksycoca
80static QStringList *g_allResourceDirs = 0;
81static bool g_changed = false;
82static KSycocaEntry::List g_tempStorage;
83static VFolderMenu *g_vfolder = 0;
84
85static const char *cSycocaPath = 0;
86
87static bool bGlobalDatabase = false;
88static bool bMenuTest = false;
89
90void crashHandler(int)
91{
92 // If we crash while reading sycoca, we delete the database
93 // in an attempt to recover.
94 if (cSycocaPath)
95 unlink(cSycocaPath);
96}
97
98static QString sycocaPath()
99{
100 return KSycoca::absoluteFilePath(bGlobalDatabase ? KSycoca::GlobalDatabase : KSycoca::LocalDatabase);
101}
102
103KBuildSycoca::KBuildSycoca()
104 : KSycoca( true )
105{
106}
107
108KBuildSycoca::~KBuildSycoca()
109{
110
111}
112
113KSycocaEntry::Ptr KBuildSycoca::createEntry(const QString &file, bool addToFactory)
114{
115 quint32 timeStamp = g_ctimeInfo->dict()->ctime(file, g_resource);
116 if (!timeStamp)
117 {
118 timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, file,
119 KStandardDirs::Recursive);
120 }
121 KSycocaEntry::Ptr entry;
122 if (g_allEntries)
123 {
124 assert(g_ctimeDict);
125 quint32 oldTimestamp = g_ctimeDict->ctime(file, g_resource);
126
127 if (timeStamp && (timeStamp == oldTimestamp))
128 {
129 // Re-use old entry
130 if (g_currentFactory == g_buildServiceGroupFactory) // Strip .directory from service-group entries
131 {
132 entry = g_currentEntryDict->value(file.left(file.length()-10));
133 } else {
134 entry = g_currentEntryDict->value(file);
135 }
136 // remove from g_ctimeDict; if g_ctimeDict is not empty
137 // after all files have been processed, it means
138 // some files were removed since last time
139 if (file.contains("fake"))
140 kDebug(7021) << g_resource << "reusing (and removing) old entry [\"fake\"] for:" << file;
141 g_ctimeDict->remove(file, g_resource);
142 }
143 else if (oldTimestamp)
144 {
145 g_changed = true;
146 g_ctimeDict->remove(file, g_resource);
147 kDebug(7021) << "modified:" << file << "in" << g_resource.constData();
148 }
149 else
150 {
151 g_changed = true;
152 kDebug(7021) << "new:" << file << "in" << g_resource.constData();
153 }
154 }
155 g_ctimeInfo->dict()->addCTime(file, g_resource, timeStamp);
156 if (!entry)
157 {
158 // Create a new entry
159 entry = g_currentFactory->createEntry( file, g_resource );
160 }
161 if ( entry && entry->isValid() )
162 {
163 if (addToFactory)
164 g_currentFactory->addEntry(entry);
165 else
166 g_tempStorage.append(entry);
167 return entry;
168 }
169 return KSycocaEntry::Ptr();
170}
171
172KService::Ptr KBuildSycoca::createService(const QString &path)
173{
174 KSycocaEntry::Ptr entry = createEntry(path, false);
175 return KService::Ptr::staticCast(entry);
176}
177
178// returns false if the database is up to date, true if it needs to be saved
179bool KBuildSycoca::build()
180{
181 typedef QLinkedList<KBSEntryDict *> KBSEntryDictList;
182 KBSEntryDictList entryDictList;
183 KBSEntryDict *serviceEntryDict = 0;
184
185 // Convert for each factory the entryList to a Dict.
186 int i = 0;
187 // For each factory
188 for (KSycocaFactoryList::Iterator factory = factories()->begin();
189 factory != factories()->end();
190 ++factory)
191 {
192 KBSEntryDict *entryDict = new KBSEntryDict;
193 if (g_allEntries)
194 {
195 const KSycocaEntry::List list = (*g_allEntries)[i++];
196 for( KSycocaEntry::List::const_iterator it = list.begin();
197 it != list.end();
198 ++it)
199 {
200 entryDict->insert( (*it)->entryPath(), *it );
201 }
202 }
203 if ((*factory) == g_serviceFactory)
204 serviceEntryDict = entryDict;
205 else if ((*factory) == g_buildServiceGroupFactory)
206 g_serviceGroupEntryDict = entryDict;
207 entryDictList.append(entryDict);
208 }
209
210 QStringList allResources; // we could use QSet<QString> - does order matter?
211 // For each factory
212 for (KSycocaFactoryList::Iterator factory = factories()->begin();
213 factory != factories()->end();
214 ++factory)
215 {
216 // For each resource the factory deals with
217 const KSycocaResourceList *list = (*factory)->resourceList();
218 if (!list) continue;
219
220 for( KSycocaResourceList::ConstIterator it1 = list->constBegin();
221 it1 != list->constEnd();
222 ++it1 )
223 {
224 KSycocaResource res = (*it1);
225 if (!allResources.contains(res.resource))
226 allResources.append(res.resource);
227 }
228 }
229
230 g_ctimeInfo = new KCTimeInfo(); // This is a build factory too, don't delete!!
231 bool uptodate = true;
232 // For all resources
233 for( QStringList::ConstIterator it1 = allResources.constBegin();
234 it1 != allResources.constEnd();
235 ++it1 )
236 {
237 g_changed = false;
238 g_resource = (*it1).toLatin1();
239
240 QStringList relFiles;
241
242 (void) KGlobal::dirs()->findAllResources( g_resource,
243 QString(),
244 KStandardDirs::Recursive |
245 KStandardDirs::NoDuplicates,
246 relFiles);
247
248
249 // Now find all factories that use this resource....
250 // For each factory
251 KBSEntryDictList::const_iterator ed_it = entryDictList.begin();
252 const KBSEntryDictList::const_iterator ed_end = entryDictList.end();
253 KSycocaFactoryList::const_iterator it = factories()->constBegin();
254 const KSycocaFactoryList::const_iterator end = factories()->constEnd();
255 for ( ; it != end; ++it, ++ed_it )
256 {
257 g_currentFactory = (*it);
258 // g_ctimeInfo gets created after the initial loop, so it has no entryDict.
259 g_currentEntryDict = ed_it == ed_end ? 0 : *ed_it;
260 // For each resource the factory deals with
261 const KSycocaResourceList *list = g_currentFactory->resourceList();
262 if (!list) continue;
263
264 for( KSycocaResourceList::ConstIterator it2 = list->constBegin();
265 it2 != list->constEnd();
266 ++it2 )
267 {
268 KSycocaResource res = (*it2);
269 if (res.resource != (*it1)) continue;
270
271 // For each file in the resource
272 for( QStringList::ConstIterator it3 = relFiles.constBegin();
273 it3 != relFiles.constEnd();
274 ++it3 )
275 {
276 // Check if file matches filter
277 if ((*it3).endsWith(res.extension))
278 createEntry(*it3, true);
279 }
280 }
281 }
282 if (g_changed || !g_allEntries)
283 {
284 uptodate = false;
285 //kDebug() << "CHANGED:" << g_resource;
286 m_changedResources.append(g_resource);
287 }
288 }
289
290 bool result = !uptodate || (g_ctimeDict && !g_ctimeDict->isEmpty());
291 if (g_ctimeDict && !g_ctimeDict->isEmpty()) {
292 //kDebug() << "Still in time dict:";
293 //g_ctimeDict->dump();
294 // ## It seems entries filtered out by vfolder are still in there,
295 // so we end up always saving ksycoca, i.e. this method never returns false
296
297 // Get the list of resources from which some files were deleted
298 const QStringList resources = g_ctimeDict->resourceList();
299 kDebug() << "Still in the time dict (i.e. deleted files)" << resources;
300 m_changedResources += resources;
301 }
302
303 if (result || bMenuTest)
304 {
305 g_resource = "apps";
306 g_currentFactory = g_serviceFactory;
307 g_currentEntryDict = serviceEntryDict;
308 g_changed = false;
309
310 g_vfolder = new VFolderMenu(g_serviceFactory, this);
311 if (!m_trackId.isEmpty())
312 g_vfolder->setTrackId(m_trackId);
313
314 VFolderMenu::SubMenu *kdeMenu = g_vfolder->parseMenu("applications.menu", true);
315
316 KServiceGroup::Ptr entry = g_buildServiceGroupFactory->addNew("/", kdeMenu->directoryFile, KServiceGroup::Ptr(), false);
317 entry->setLayoutInfo(kdeMenu->layoutList);
318 createMenu(QString(), QString(), kdeMenu);
319
320 (void) existingResourceDirs();
321 *g_allResourceDirs += g_vfolder->allDirectories();
322
323 if (g_changed || !g_allEntries)
324 {
325 uptodate = false;
326 //kDebug() << "CHANGED:" << g_resource;
327 m_changedResources.append(g_resource);
328 }
329 if (bMenuTest) {
330 result = false;
331 }
332 }
333
334 qDeleteAll(entryDictList);
335 return result;
336}
337
338void KBuildSycoca::createMenu(const QString &caption_, const QString &name_, VFolderMenu::SubMenu *menu)
339{
340 QString caption = caption_;
341 QString name = name_;
342 foreach (VFolderMenu::SubMenu *subMenu, menu->subMenus)
343 {
344 QString subName = name+subMenu->name+'/';
345
346 QString directoryFile = subMenu->directoryFile;
347 if (directoryFile.isEmpty())
348 directoryFile = subName+".directory";
349 quint32 timeStamp = g_ctimeInfo->dict()->ctime(directoryFile, g_resource);
350 if (!timeStamp) {
351 timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, directoryFile,
352 KStandardDirs::Recursive );
353 }
354
355 KServiceGroup::Ptr entry;
356 if (g_allEntries)
357 {
358 const quint32 oldTimestamp = g_ctimeDict->ctime(directoryFile, g_resource);
359
360 if (timeStamp && (timeStamp == oldTimestamp))
361 {
362 KSycocaEntry::Ptr group = g_serviceGroupEntryDict->value(subName);
363 if ( group )
364 {
365 entry = KServiceGroup::Ptr::staticCast( group );
366 if (entry->directoryEntryPath() != directoryFile)
367 entry = 0; // Can't reuse this one!
368 }
369 }
370 }
371 g_ctimeInfo->dict()->addCTime(directoryFile, g_resource, timeStamp);
372
373 entry = g_buildServiceGroupFactory->addNew(subName, subMenu->directoryFile, entry, subMenu->isDeleted);
374 entry->setLayoutInfo(subMenu->layoutList);
375 if (! (bMenuTest && entry->noDisplay()) )
376 createMenu(caption + entry->caption() + '/', subName, subMenu);
377 }
378 if (caption.isEmpty())
379 caption += '/';
380 if (name.isEmpty())
381 name += '/';
382 foreach (const KService::Ptr &p, menu->items)
383 {
384 if (bMenuTest)
385 {
386 if (!menu->isDeleted && !p->noDisplay())
387 printf("%s\t%s\t%s\n", qPrintable( caption ), qPrintable( p->menuId() ), qPrintable( KStandardDirs::locate("apps", p->entryPath() ) ) );
388 }
389 else
390 {
391 g_buildServiceGroupFactory->addNewEntryTo( name, p );
392 }
393 }
394}
395
396bool KBuildSycoca::recreate()
397{
398 QString path(sycocaPath());
399
400 // KSaveFile first writes to a temp file.
401 // Upon finalize() it moves the stuff to the right place.
402 KSaveFile database(path);
403 bool openedOK = database.open();
404 if (!openedOK && database.error() == QFile::PermissionsError && QFile::exists(path))
405 {
406 QFile::remove( path );
407 openedOK = database.open();
408 }
409 if (!openedOK)
410 {
411 fprintf(stderr, "kbuildsycoca4: ERROR creating database '%s'! %s\n",
412 path.toLocal8Bit().data(), database.errorString().toLocal8Bit().data());
413 return false;
414 }
415
416 QDataStream* str = new QDataStream(&database);
417 str->setVersion(QDataStream::Qt_3_1);
418
419 kDebug(7021).nospace() << "Recreating ksycoca file (" << path << ", version " << KSycoca::version() << ")";
420
421 // It is very important to build the servicetype one first
422 // Both are registered in KSycoca, no need to keep the pointers
423 KSycocaFactory *stf = new KBuildServiceTypeFactory;
424 KBuildMimeTypeFactory* mimeTypeFactory = new KBuildMimeTypeFactory;
425 g_buildServiceGroupFactory = new KBuildServiceGroupFactory();
426 g_serviceFactory = new KBuildServiceFactory(stf, mimeTypeFactory, g_buildServiceGroupFactory);
427 (void) new KBuildProtocolInfoFactory();
428
429 if( build()) // Parse dirs
430 {
431 save(str); // Save database
432 if (str->status() != QDataStream::Ok) // ######## TODO: does this detect write errors, e.g. disk full?
433 database.abort(); // Error
434 delete str;
435 str = 0;
436 if (!database.finalize())
437 {
438 fprintf(stderr, "kbuildsycoca4: ERROR writing database '%s'!\n", database.fileName().toLocal8Bit().data());
439 fprintf(stderr, "kbuildsycoca4: Disk full?\n");
440 return false;
441 }
442 }
443 else
444 {
445 delete str;
446 str = 0;
447 database.abort();
448 if (bMenuTest)
449 return true;
450 kDebug(7021) << "Database is up to date";
451 }
452
453 if (!bGlobalDatabase)
454 {
455 // update the timestamp file
456 QString stamppath = path + "stamp";
457 QFile ksycocastamp(stamppath);
458 ksycocastamp.open( QIODevice::WriteOnly );
459 QDataStream str( &ksycocastamp );
460 str.setVersion(QDataStream::Qt_3_1);
461 str << newTimestamp;
462 str << existingResourceDirs();
463 if (g_vfolder)
464 str << g_vfolder->allDirectories(); // Extra resource dirs
465 }
466 if (d->m_sycocaStrategy == KSycocaPrivate::StrategyMemFile)
467 KMemFile::fileContentsChanged(path);
468
469 return true;
470}
471
472void KBuildSycoca::save(QDataStream* str)
473{
474 // Write header (#pass 1)
475 str->device()->seek(0);
476
477 (*str) << (qint32) KSycoca::version();
478 KSycocaFactory * servicetypeFactory = 0;
479 KBuildMimeTypeFactory * mimeTypeFactory = 0;
480 KBuildServiceFactory * serviceFactory = 0;
481 for(KSycocaFactoryList::Iterator factory = factories()->begin();
482 factory != factories()->end();
483 ++factory)
484 {
485 qint32 aId;
486 qint32 aOffset;
487 aId = (*factory)->factoryId();
488 if ( aId == KST_KServiceTypeFactory )
489 servicetypeFactory = *factory;
490 else if ( aId == KST_KMimeTypeFactory )
491 mimeTypeFactory = static_cast<KBuildMimeTypeFactory *>( *factory );
492 else if ( aId == KST_KServiceFactory )
493 serviceFactory = static_cast<KBuildServiceFactory *>( *factory );
494 aOffset = (*factory)->offset(); // not set yet, so always 0
495 (*str) << aId;
496 (*str) << aOffset;
497 }
498 (*str) << (qint32) 0; // No more factories.
499 // Write KDEDIRS
500 (*str) << KGlobal::dirs()->kfsstnd_prefixes();
501 (*str) << newTimestamp;
502 (*str) << KGlobal::locale()->language();
503 (*str) << KGlobal::dirs()->calcResourceHash("services", "update_ksycoca",
504 KStandardDirs::Recursive );
505 (*str) << (*g_allResourceDirs);
506
507 // Calculate per-servicetype/mimetype data
508 serviceFactory->postProcessServices();
509
510 // Here so that it's the last debug message
511 kDebug(7021) << "Saving";
512
513 // Write factory data....
514 for(KSycocaFactoryList::Iterator factory = factories()->begin();
515 factory != factories()->end();
516 ++factory)
517 {
518 (*factory)->save(*str);
519 if (str->status() != QDataStream::Ok) // ######## TODO: does this detect write errors, e.g. disk full?
520 return; // error
521 }
522
523 int endOfData = str->device()->pos();
524
525 // Write header (#pass 2)
526 str->device()->seek(0);
527
528 (*str) << (qint32) KSycoca::version();
529 for(KSycocaFactoryList::Iterator factory = factories()->begin();
530 factory != factories()->end(); ++factory)
531 {
532 qint32 aId;
533 qint32 aOffset;
534 aId = (*factory)->factoryId();
535 aOffset = (*factory)->offset();
536 (*str) << aId;
537 (*str) << aOffset;
538 }
539 (*str) << (qint32) 0; // No more factories.
540
541 // Jump to end of database
542 str->device()->seek(endOfData);
543}
544
545bool KBuildSycoca::checkDirTimestamps( const QString& dirname, const QDateTime& stamp, bool top )
546{
547 if( top )
548 {
549 QFileInfo inf( dirname );
550 if( inf.lastModified() > stamp ) {
551 kDebug( 7021 ) << "timestamp changed:" << dirname;
552 return false;
553 }
554 }
555 QDir dir( dirname );
556 const QFileInfoList list = dir.entryInfoList( QDir::NoFilter, QDir::Unsorted );
557 if (list.isEmpty())
558 return true;
559
560 foreach ( const QFileInfo& fi, list ) {
561 if( fi.fileName() == "." || fi.fileName() == ".." )
562 continue;
563 if( fi.lastModified() > stamp )
564 {
565 kDebug( 7201 ) << "timestamp changed:" << fi.filePath();
566 return false;
567 }
568 if( fi.isDir() && !checkDirTimestamps( fi.filePath(), stamp, false ))
569 return false;
570 }
571 return true;
572}
573
574// check times of last modification of all files on which ksycoca depens,
575// and also their directories
576// if all of them are older than the timestamp in file ksycocastamp, this
577// means that there's no need to rebuild ksycoca
578bool KBuildSycoca::checkTimestamps( quint32 timestamp, const QStringList &dirs )
579{
580 kDebug( 7021 ) << "checking file timestamps";
581 QDateTime stamp;
582 stamp.setTime_t( timestamp );
583 for( QStringList::ConstIterator it = dirs.begin();
584 it != dirs.end();
585 ++it )
586 {
587 if( !checkDirTimestamps( *it, stamp, true ))
588 return false;
589 }
590 kDebug( 7021 ) << "timestamps check ok";
591 return true;
592}
593
594QStringList KBuildSycoca::existingResourceDirs()
595{
596 static QStringList* dirs = NULL;
597 if( dirs != NULL )
598 return *dirs;
599 dirs = new QStringList;
600 g_allResourceDirs = new QStringList;
601 // these are all resources cached by ksycoca
602 QStringList resources;
603 resources += KBuildServiceTypeFactory::resourceTypes();
604 resources += KBuildMimeTypeFactory::resourceTypes();
605 resources += KBuildServiceGroupFactory::resourceTypes();
606 resources += KBuildServiceFactory::resourceTypes();
607 resources += KBuildProtocolInfoFactory::resourceTypes();
608 while( !resources.empty())
609 {
610 QString res = resources.front();
611 *dirs += KGlobal::dirs()->resourceDirs( res.toLatin1());
612 resources.removeAll( res );
613 }
614
615 *g_allResourceDirs = *dirs;
616
617 for( QStringList::Iterator it = dirs->begin();
618 it != dirs->end(); )
619 {
620 QFileInfo inf( *it );
621 if( !inf.exists() || !inf.isReadable() )
622 it = dirs->erase( it );
623 else
624 ++it;
625 }
626 return *dirs;
627}
628
629static const char appFullName[] = "org.kde.kbuildsycoca";
630static const char appName[] = "kbuildsycoca4";
631static const char appVersion[] = "1.1";
632
633extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
634{
635 KAboutData d(appName, "kdelibs4", ki18n("KBuildSycoca"), appVersion,
636 ki18n("Rebuilds the system configuration cache."),
637 KAboutData::License_GPL, ki18n("(c) 1999-2002 KDE Developers"));
638 d.addAuthor(ki18n("David Faure"), ki18n("Author"), "faure@kde.org");
639 d.addAuthor(ki18n("Waldo Bastian"), ki18n("Author"), "bastian@kde.org");
640
641 KCmdLineOptions options;
642 options.add("nosignal", ki18n("Do not signal applications to update"));
643 options.add("noincremental", ki18n("Disable incremental update, re-read everything"));
644 options.add("checkstamps", ki18n("Check file timestamps"));
645 options.add("nocheckfiles", ki18n("Disable checking files (dangerous)"));
646 options.add("global", ki18n("Create global database"));
647 options.add("menutest", ki18n("Perform menu generation test run only"));
648 options.add("track <menu-id>", ki18n("Track menu id for debug purposes"));
649
650 KCmdLineArgs::init(argc, argv, &d);
651 KCmdLineArgs::addCmdLineOptions(options);
652 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
653 bGlobalDatabase = args->isSet("global");
654 bMenuTest = args->isSet("menutest");
655
656 if (bGlobalDatabase)
657 {
658 setenv("KDEHOME", "-", 1);
659 setenv("KDEROOTHOME", "-", 1);
660 }
661
662 QCoreApplication k(argc, argv);
663 KComponentData mainComponent(d);
664
665#ifndef KBUILDSYCOCA_NO_KCRASH
666 KCrash::setCrashHandler(KCrash::defaultCrashHandler);
667 KCrash::setEmergencySaveFunction(crashHandler);
668 KCrash::setApplicationName(QString(appName));
669#endif
670
671 // force generating of KLocale object. if not, the database will get
672 // be translated
673 KGlobal::locale();
674 KGlobal::dirs()->addResourceType("app-reg", 0, "share/application-registry" );
675
676 while(QDBusConnection::sessionBus().isConnected())
677 {
678 // kapp registered already, but with the PID in the name.
679 // We need to re-register without it, to detect already-running kbuildsycoca instances.
680 if (QDBusConnection::sessionBus().interface()->registerService(appFullName, QDBusConnectionInterface::QueueService)
681 != QDBusConnectionInterface::ServiceQueued)
682 {
683 break; // Go
684 }
685 fprintf(stderr, "Waiting for already running %s to finish.\n", appName);
686
687 QEventLoop eventLoop;
688 QObject::connect(QDBusConnection::sessionBus().interface(), SIGNAL(serviceRegistered(QString)),
689 &eventLoop, SLOT(quit()));
690 eventLoop.exec( QEventLoop::ExcludeUserInputEvents );
691 }
692 fprintf(stderr, "%s running...\n", appName);
693
694 bool checkfiles = bGlobalDatabase || args->isSet("checkfiles");
695
696 bool incremental = !bGlobalDatabase && args->isSet("incremental") && checkfiles;
697 if (incremental || !checkfiles)
698 {
699 KSycoca::disableAutoRebuild(); // Prevent deadlock
700 QString current_language = KGlobal::locale()->language();
701 QString ksycoca_language = KSycoca::self()->language();
702 quint32 current_update_sig = KGlobal::dirs()->calcResourceHash("services", "update_ksycoca",
703 KStandardDirs::Recursive );
704 quint32 ksycoca_update_sig = KSycoca::self()->updateSignature();
705 QString current_prefixes = KGlobal::dirs()->kfsstnd_prefixes();
706 QString ksycoca_prefixes = KSycoca::self()->kfsstnd_prefixes();
707
708 if ((current_update_sig != ksycoca_update_sig) ||
709 (current_language != ksycoca_language) ||
710 (current_prefixes != ksycoca_prefixes) ||
711 (KSycoca::self()->timeStamp() == 0))
712 {
713 incremental = false;
714 checkfiles = true;
715 KBuildSycoca::clearCaches();
716 }
717 }
718
719 bool checkstamps = incremental && args->isSet("checkstamps") && checkfiles;
720 quint32 filestamp = 0;
721 QStringList oldresourcedirs;
722 if( checkstamps && incremental )
723 {
724 QString path = sycocaPath()+"stamp";
725 QByteArray qPath = QFile::encodeName(path);
726 cSycocaPath = qPath.data(); // Delete timestamps on crash
727 QFile ksycocastamp(path);
728 if( ksycocastamp.open( QIODevice::ReadOnly ))
729 {
730 QDataStream str( &ksycocastamp );
731 str.setVersion(QDataStream::Qt_3_1);
732
733 if (!str.atEnd())
734 str >> filestamp;
735 if (!str.atEnd())
736 {
737 str >> oldresourcedirs;
738 if( oldresourcedirs != KBuildSycoca::existingResourceDirs())
739 checkstamps = false;
740 }
741 else
742 {
743 checkstamps = false;
744 }
745 if (!str.atEnd())
746 {
747 QStringList extraResourceDirs;
748 str >> extraResourceDirs;
749 oldresourcedirs += extraResourceDirs;
750 }
751 }
752 else
753 {
754 checkstamps = false;
755 }
756 cSycocaPath = 0;
757 }
758
759 newTimestamp = (quint32) time(0);
760 QStringList changedResources;
761
762 if( checkfiles && ( !checkstamps || !KBuildSycoca::checkTimestamps( filestamp, oldresourcedirs )))
763 {
764 QByteArray qSycocaPath = QFile::encodeName(sycocaPath());
765 cSycocaPath = qSycocaPath.data();
766
767 g_allEntries = 0;
768 g_ctimeDict = 0;
769 if (incremental)
770 {
771 kDebug(7021) << "Reusing existing ksycoca";
772 KSycoca::self();
773 KSycocaFactoryList *factories = new KSycocaFactoryList;
774 g_allEntries = new KSycocaEntryListList;
775 g_ctimeDict = new KCTimeDict;
776
777 // Must be in same order as in KBuildSycoca::recreate()!
778 factories->append( new KServiceTypeFactory );
779 factories->append( new KMimeTypeFactory );
780 factories->append( new KServiceGroupFactory );
781 factories->append( new KServiceFactory );
782 factories->append( new KProtocolInfoFactory );
783
784 // For each factory
785 for (KSycocaFactoryList::Iterator factory = factories->begin();
786 factory != factories->end(); ++factory)
787 {
788 const KSycocaEntry::List list = (*factory)->allEntries();
789 g_allEntries->append( list );
790 }
791 delete factories; factories = 0;
792 KCTimeInfo *ctimeInfo = new KCTimeInfo;
793 *g_ctimeDict = ctimeInfo->loadDict();
794 }
795 cSycocaPath = 0;
796
797 KBuildSycoca *sycoca = new KBuildSycoca; // Build data base (deletes oldSycoca)
798 if (args->isSet("track"))
799 sycoca->setTrackId(args->getOption("track"));
800 if (!sycoca->recreate()) {
801 return -1;
802 }
803 changedResources = sycoca->changedResources();
804
805 if (bGlobalDatabase)
806 {
807 // These directories may have been created with 0700 permission
808 // better delete them if they are empty
809 QString applnkDir = KGlobal::dirs()->saveLocation("apps", QString(), false);
810 ::rmdir(QFile::encodeName(applnkDir));
811 QString servicetypesDir = KGlobal::dirs()->saveLocation("servicetypes", QString(), false);
812 ::rmdir(QFile::encodeName(servicetypesDir));
813 }
814 }
815
816 if (args->isSet("signal"))
817 {
818 // Notify ALL applications that have a ksycoca object, using a signal
819 QDBusMessage signal = QDBusMessage::createSignal("/", "org.kde.KSycoca", "notifyDatabaseChanged" );
820 signal << changedResources;
821
822 if (QDBusConnection::sessionBus().isConnected()) {
823 kDebug() << "Emitting notifyDatabaseChanged" << changedResources;
824 QDBusConnection::sessionBus().send(signal);
825 qApp->processEvents(); // make sure the dbus signal is sent before we quit.
826 }
827 }
828
829 return 0;
830}
831
832#include "kbuildsycoca.moc"
KAboutData
KAboutData::addAuthor
KAboutData & addAuthor(const KLocalizedString &name, const KLocalizedString &task, const QByteArray &emailAddress, const QByteArray &webAddress, const QByteArray &ocsUsername)
KAboutData::License_GPL
License_GPL
KBuildMimeTypeFactory
Mime-type factory for building ksycoca.
Definition: kbuildmimetypefactory.h:33
KBuildMimeTypeFactory::resourceTypes
static QStringList resourceTypes()
Returns all resource types for this factory.
Definition: kbuildmimetypefactory.cpp:43
KBuildProtocolInfoFactory
Protocol Info factory for building ksycoca.
Definition: kbuildprotocolinfofactory.h:31
KBuildProtocolInfoFactory::resourceTypes
static QStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildprotocolinfofactory.cpp:39
KBuildServiceFactory
Service factory for building ksycoca.
Definition: kbuildservicefactory.h:38
KBuildServiceFactory::resourceTypes
static QStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicefactory.cpp:60
KBuildServiceFactory::postProcessServices
void postProcessServices()
Definition: kbuildservicefactory.cpp:192
KBuildServiceGroupFactory
Service group factory for building ksycoca.
Definition: kbuildservicegroupfactory.h:31
KBuildServiceGroupFactory::addNew
KServiceGroup::Ptr addNew(const QString &menuName, const QString &file, KServiceGroup::Ptr entry, bool isDeleted)
Add new menu menuName defined by file When entry is non-null it is re-used, otherwise a new group is ...
Definition: kbuildservicegroupfactory.cpp:78
KBuildServiceGroupFactory::resourceTypes
static QStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicegroupfactory.cpp:43
KBuildServiceGroupFactory::addNewEntryTo
void addNewEntryTo(const QString &menuName, const KService::Ptr &newEntry)
Adds the entry newEntry to the menu menuName.
Definition: kbuildservicegroupfactory.cpp:62
KBuildServiceTypeFactory
Service-type factory for building ksycoca.
Definition: kbuildservicetypefactory.h:31
KBuildServiceTypeFactory::resourceTypes
static QStringList resourceTypes()
Returns all resource types for this factory.
Definition: kbuildservicetypefactory.cpp:42
KBuildSycoca
Definition: kbuildsycoca.h:40
KBuildSycoca::~KBuildSycoca
virtual ~KBuildSycoca()
Definition: kbuildsycoca.cpp:108
KBuildSycoca::clearCaches
static void clearCaches()
Definition: kbuildsycoca.h:60
KBuildSycoca::existingResourceDirs
static QStringList existingResourceDirs()
Definition: kbuildsycoca.cpp:594
KBuildSycoca::setTrackId
void setTrackId(const QString &id)
Definition: kbuildsycoca.h:55
KBuildSycoca::KBuildSycoca
KBuildSycoca()
Definition: kbuildsycoca.cpp:103
KBuildSycoca::recreate
bool recreate()
Recreate the database file.
Definition: kbuildsycoca.cpp:396
KBuildSycoca::checkTimestamps
static bool checkTimestamps(quint32 timestamp, const QStringList &dirs)
Definition: kbuildsycoca.cpp:578
KBuildSycoca::changedResources
QStringList changedResources() const
Definition: kbuildsycoca.h:57
KCTimeDict
Simple dict for assocating a timestamp with each file in ksycoca.
Definition: kctimefactory.h:29
KCTimeDict::ctime
quint32 ctime(const QString &path, const QByteArray &resource) const
Definition: kctimefactory.cpp:37
KCTimeDict::isEmpty
bool isEmpty() const
Definition: kctimefactory.h:35
KCTimeDict::resourceList
QStringList resourceList() const
Definition: kctimefactory.cpp:52
KCTimeDict::remove
void remove(const QString &path, const QByteArray &resource)
Definition: kctimefactory.cpp:42
KCTimeDict::addCTime
void addCTime(const QString &path, const QByteArray &resource, quint32 ctime)
Definition: kctimefactory.cpp:31
KCTimeInfo
Internal factory for storing the timestamp of each file in ksycoca.
Definition: kctimefactory.h:50
KCTimeInfo::dict
KCTimeDict * dict()
Definition: kctimefactory.h:78
KCTimeInfo::loadDict
KCTimeDict loadDict() const
Definition: kctimefactory.cpp:124
KCmdLineArgs
KCmdLineArgs::isSet
bool isSet(const QByteArray &option) const
KCmdLineArgs::init
static void init(const KAboutData *about)
KCmdLineArgs::parsedArgs
static KCmdLineArgs * parsedArgs(const QByteArray &id=QByteArray())
KCmdLineArgs::addCmdLineOptions
static void addCmdLineOptions(const KCmdLineOptions &options, const KLocalizedString &name=KLocalizedString(), const QByteArray &id=QByteArray(), const QByteArray &afterId=QByteArray())
KCmdLineArgs::getOption
QString getOption(const QByteArray &option) const
KCmdLineOptions
KCmdLineOptions::add
KCmdLineOptions & add(const KCmdLineOptions &options)
KComponentData
KLocale::language
QString language() const
KMemFile::fileContentsChanged
static void fileContentsChanged(const QString &filename)
KMimeTypeFactory
KProtocolInfoFactory
KSaveFile
KSaveFile::finalize
bool finalize()
KSaveFile::fileName
QString fileName() const
KSaveFile::open
virtual bool open(OpenMode flags=QIODevice::ReadWrite)
KSaveFile::error
QFile::FileError error() const
KSaveFile::errorString
QString errorString() const
KSaveFile::abort
void abort()
KServiceFactory
KServiceGroupFactory
KServiceTypeFactory
KSharedPtr
KSharedPtr< KService >::staticCast
static KSharedPtr< T > staticCast(const KSharedPtr< U > &o)
KStandardDirs::findAllResources
QStringList findAllResources(const char *type, const QString &filter, SearchOptions options, QStringList &relPaths) const
KStandardDirs::Recursive
Recursive
KStandardDirs::NoDuplicates
NoDuplicates
KStandardDirs::addResourceType
bool addResourceType(const char *type, const char *basetype, const char *relativename, bool priority=true)
KStandardDirs::kfsstnd_prefixes
QString kfsstnd_prefixes()
KStandardDirs::saveLocation
QString saveLocation(const char *type, const QString &suffix=QString(), bool create=true) const
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
KStandardDirs::calcResourceHash
quint32 calcResourceHash(const char *type, const QString &filename, SearchOptions options=NoSearchOptions) const
KStandardDirs::resourceDirs
QStringList resourceDirs(const char *type) const
KSycocaEntry::Ptr
KSharedPtr< KSycocaEntry > Ptr
KSycocaFactoryList
KSycocaFactory
KSycocaFactory::resourceList
const KSycocaResourceList * resourceList() const
KSycocaFactory::offset
int offset() const
KSycocaFactory::addEntry
virtual void addEntry(const KSycocaEntry::Ptr &newEntry)
KSycocaFactory::createEntry
virtual KSycocaEntry * createEntry(const QString &file, const char *resource) const=0
KSycocaFactory::factoryId
virtual KSycocaFactoryId factoryId() const=0
KSycocaPrivate::StrategyMemFile
StrategyMemFile
KSycocaResourceList
Definition: ksycocaresourcelist.h:33
KSycoca
KSycoca::timeStamp
quint32 timeStamp()
KSycoca::language
QString language()
KSycoca::version
static int version()
KSycoca::self
static KSycoca * self()
KSycoca::updateSignature
quint32 updateSignature()
KSycoca::factories
KSycocaFactoryList * factories()
KSycoca::kfsstnd_prefixes
QString kfsstnd_prefixes()
KSycoca::absoluteFilePath
static QString absoluteFilePath(DatabaseType type=LocalDatabase)
KSycoca::GlobalDatabase
GlobalDatabase
KSycoca::LocalDatabase
LocalDatabase
KSycoca::disableAutoRebuild
static void disableAutoRebuild()
QHash
QLinkedList
QList
VFolderMenu::SubMenu
Definition: vfolder_menu.h:40
VFolderMenu::SubMenu::name
QString name
Definition: vfolder_menu.h:46
VFolderMenu::SubMenu::items
QHash< QString, KService::Ptr > items
Definition: vfolder_menu.h:49
VFolderMenu::SubMenu::layoutList
QStringList layoutList
Definition: vfolder_menu.h:54
VFolderMenu::SubMenu::directoryFile
QString directoryFile
Definition: vfolder_menu.h:47
VFolderMenu::SubMenu::subMenus
QList< SubMenu * > subMenus
Definition: vfolder_menu.h:48
VFolderMenu::SubMenu::isDeleted
bool isDeleted
Definition: vfolder_menu.h:53
VFolderMenu
Definition: vfolder_menu.h:36
VFolderMenu::allDirectories
QStringList allDirectories()
Returns a list of all directories involved in the last call to parseMenu(), excluding the KDE Legacy ...
Definition: vfolder_menu.cpp:88
VFolderMenu::parseMenu
SubMenu * parseMenu(const QString &file, bool forceLegacyLoad=false)
Parses VFolder menu definition and generates a menu layout.
Definition: vfolder_menu.cpp:1590
VFolderMenu::setTrackId
void setTrackId(const QString &id)
Debug function to enable tracking of what happens with a specific menu item id.
Definition: vfolder_menu.cpp:1651
kDebug
#define kDebug
kaboutdata.h
kapplication.h
kbuildmimetypefactory.h
kbuildprotocolinfofactory.h
kbuildservicefactory.h
kbuildservicegroupfactory.h
kbuildservicetypefactory.h
g_currentFactory
static KSycocaFactory * g_currentFactory
Definition: kbuildsycoca.cpp:73
newTimestamp
static quint32 newTimestamp
Definition: kbuildsycoca.cpp:69
g_currentEntryDict
static KBSEntryDict * g_currentEntryDict
Definition: kbuildsycoca.cpp:77
g_tempStorage
static KSycocaEntry::List g_tempStorage
Definition: kbuildsycoca.cpp:82
g_buildServiceGroupFactory
static KBuildServiceGroupFactory * g_buildServiceGroupFactory
Definition: kbuildsycoca.cpp:72
bMenuTest
static bool bMenuTest
Definition: kbuildsycoca.cpp:88
appName
static const char appName[]
Definition: kbuildsycoca.cpp:630
g_ctimeDict
static KCTimeDict * g_ctimeDict
Definition: kbuildsycoca.cpp:75
g_vfolder
static VFolderMenu * g_vfolder
Definition: kbuildsycoca.cpp:83
g_ctimeInfo
static KCTimeInfo * g_ctimeInfo
Definition: kbuildsycoca.cpp:74
KBSEntryDict
QHash< QString, KSycocaEntry::Ptr > KBSEntryDict
Definition: kbuildsycoca.cpp:66
g_changed
static bool g_changed
Definition: kbuildsycoca.cpp:81
KSycocaEntryListList
QList< KSycocaEntry::List > KSycocaEntryListList
Definition: kbuildsycoca.cpp:67
bGlobalDatabase
static bool bGlobalDatabase
Definition: kbuildsycoca.cpp:87
kdemain
int kdemain(int argc, char **argv)
Definition: kbuildsycoca.cpp:633
sycocaPath
static QString sycocaPath()
Definition: kbuildsycoca.cpp:98
g_serviceGroupEntryDict
static KBSEntryDict * g_serviceGroupEntryDict
Definition: kbuildsycoca.cpp:78
appVersion
static const char appVersion[]
Definition: kbuildsycoca.cpp:631
g_resource
static QByteArray g_resource
Definition: kbuildsycoca.cpp:76
appFullName
static const char appFullName[]
Definition: kbuildsycoca.cpp:629
g_allResourceDirs
static QStringList * g_allResourceDirs
Definition: kbuildsycoca.cpp:80
g_serviceFactory
static KBuildServiceFactory * g_serviceFactory
Definition: kbuildsycoca.cpp:71
g_allEntries
static KSycocaEntryListList * g_allEntries
Definition: kbuildsycoca.cpp:79
cSycocaPath
static const char * cSycocaPath
Definition: kbuildsycoca.cpp:85
kbuildsycoca.h
kcmdlineargs.h
kcrash.h
kctimefactory.h
kdebug.h
kdirwatch.h
kglobal.h
klocale.h
ki18n
KLocalizedString ki18n(const char *msg)
kmemfile.h
kmimetype.h
ksavefile.h
kservice.h
kstandarddirs.h
ksycoca_p.h
ksycocaresourcelist.h
ktemporaryfile.h
KCrash::setCrashHandler
void setCrashHandler(HandlerType handler=defaultCrashHandler)
crashHandler
HandlerType crashHandler()
KCrash::defaultCrashHandler
void defaultCrashHandler(int signal)
KCrash::setEmergencySaveFunction
void setEmergencySaveFunction(HandlerType saveFunction=0)
KCrash::setApplicationName
void setApplicationName(const QString &name)
mainComponent
const KComponentData & mainComponent()
KGlobal::dirs
KStandardDirs * dirs()
KGlobal::locale
KLocale * locale()
caption
QString caption()
group
group
dir
QString dir(const QString &fileClass)
list
QStringList list(const QString &fileClass)
quit
KAction * quit(const QObject *recvr, const char *slot, QObject *parent)
name
const char * name(StandardAction id)
begin
const KShortcut & begin()
end
const KShortcut & end()
KSycocaResource
Definition: ksycocaresourcelist.h:27
KSycocaResource::extension
QString extension
Definition: ksycocaresourcelist.h:29
KSycocaResource::resource
QString resource
Definition: ksycocaresourcelist.h:28
vfolder_menu.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDED

Skip menu "KDED"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal