• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kded
 

kded

  • kded
tdebuildsycoca.cpp
1 /* This file is part of the KDE libraries
2  * Copyright (C) 1999 David Faure <faure@kde.org>
3  * Copyright (C) 2002-2003 Waldo Bastian <bastian@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License version 2 as published by the Free Software Foundation;
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB. If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  **/
19 
20 #include <tqdir.h>
21 #include <tqeventloop.h>
22 #include <config.h>
23 
24 #include "tdebuildsycoca.h"
25 #include "kresourcelist.h"
26 #include "vfolder_menu.h"
27 
28 #include <kservice.h>
29 #include <kmimetype.h>
30 #include <kbuildservicetypefactory.h>
31 #include <kbuildservicefactory.h>
32 #include <kbuildservicegroupfactory.h>
33 #include <kbuildimageiofactory.h>
34 #include <kbuildprotocolinfofactory.h>
35 #include <kctimefactory.h>
36 #include <kdatastream.h>
37 
38 #include <tqdatastream.h>
39 #include <tqfile.h>
40 #include <tqtimer.h>
41 
42 #include <assert.h>
43 #include <tdeapplication.h>
44 #include <dcopclient.h>
45 #include <tdeglobal.h>
46 #include <kdebug.h>
47 #include <kdirwatch.h>
48 #include <kstandarddirs.h>
49 #include <ksavefile.h>
50 #include <tdelocale.h>
51 #include <tdeaboutdata.h>
52 #include <tdecmdlineargs.h>
53 #include <tdecrash.h>
54 
55 #ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build
56  // GUI version of tdebuildsycoca, so-called "tdebuildsycocaw".
57 # include <tqlabel.h>
58 # include <tdemessagebox.h>
59  bool silent;
60  bool showprogress;
61 #endif
62 
63 #include <stdlib.h>
64 #include <unistd.h>
65 #include <time.h>
66 #include <memory>
67 
68 typedef TQDict<KSycocaEntry> KBSEntryDict;
69 typedef TQValueList<KSycocaEntry::List> KSycocaEntryListList;
70 
71 static TQ_UINT32 newTimestamp = 0;
72 
73 static KBuildServiceFactory *g_bsf = 0;
74 static KBuildServiceGroupFactory *g_bsgf = 0;
75 static KSycocaFactory *g_factory = 0;
76 static KCTimeInfo *g_ctimeInfo = 0;
77 static TQDict<TQ_UINT32> *g_ctimeDict = 0;
78 static const char *g_resource = 0;
79 static KBSEntryDict *g_entryDict = 0;
80 static KBSEntryDict *g_serviceGroupEntryDict = 0;
81 static KSycocaEntryListList *g_allEntries = 0;
82 static TQStringList *g_changeList = 0;
83 static TQStringList *g_allResourceDirs = 0;
84 static bool g_changed = false;
85 static KSycocaEntry::List g_tempStorage;
86 static VFolderMenu *g_vfolder = 0;
87 
88 static const char *cSycocaPath = 0;
89 
90 static bool bGlobalDatabase = false;
91 static bool bMenuTest = false;
92 
93 void crashHandler(int)
94 {
95  // If we crash while reading sycoca, we delete the database
96  // in an attempt to recover.
97  if (cSycocaPath)
98  unlink(cSycocaPath);
99 }
100 
101 static TQString sycocaPath()
102 {
103  TQString path;
104 
105  if (bGlobalDatabase)
106  {
107  path = TDEGlobal::dirs()->saveLocation("services")+"tdesycoca";
108  }
109  else
110  {
111  TQCString tdesycoca_env = getenv("TDESYCOCA");
112  if (tdesycoca_env.isEmpty())
113  path = TDEGlobal::dirs()->saveLocation("cache")+"tdesycoca";
114  else
115  path = TQFile::decodeName(tdesycoca_env);
116  }
117 
118  return path;
119 }
120 
121 static TQString oldSycocaPath()
122 {
123  TQCString tdesycoca_env = getenv("TDESYCOCA");
124  if (tdesycoca_env.isEmpty())
125  return TDEGlobal::dirs()->saveLocation("tmp")+"tdesycoca";
126 
127  return TQString::null;
128 }
129 
130 KBuildSycoca::KBuildSycoca()
131  : KSycoca( true )
132 {
133 }
134 
135 KBuildSycoca::~KBuildSycoca()
136 {
137 
138 }
139 
140 void KBuildSycoca::processGnomeVfs()
141 {
142  TQString file = locate("app-reg", "gnome-vfs.applications");
143  if (file.isEmpty())
144  {
145 // kdDebug(7021) << "gnome-vfs.applications not found." << endl;
146  return;
147  }
148 
149  TQString app;
150 
151  char line[1024*64];
152 
153  FILE *f = fopen(TQFile::encodeName(file), "r");
154  while (!feof(f))
155  {
156  if (!fgets(line, sizeof(line)-1, f))
157  {
158  break;
159  }
160 
161  if (line[0] != '\t')
162  {
163  app = TQString::fromLatin1(line);
164  app.truncate(app.length()-1);
165  }
166  else if (strncmp(line+1, "mime_types=", 11) == 0)
167  {
168  TQString mimetypes = TQString::fromLatin1(line+12);
169  mimetypes.truncate(mimetypes.length()-1);
170  mimetypes.replace(TQRegExp("\\*"), "all");
171  KService *s = g_bsf->findServiceByName(app);
172  if (!s)
173  continue;
174 
175  TQStringList &serviceTypes = s->accessServiceTypes();
176  if (serviceTypes.count() <= 1)
177  {
178  serviceTypes += TQStringList::split(',', mimetypes);
179 // kdDebug(7021) << "Adding gnome mimetypes for '" << app << "'.\n";
180 // kdDebug(7021) << "ServiceTypes=" << s->serviceTypes().join(":") << endl;
181  }
182  }
183  }
184  fclose( f );
185 }
186 
187 KSycocaEntry *KBuildSycoca::createEntry(const TQString &file, bool addToFactory)
188 {
189  TQ_UINT32 timeStamp = g_ctimeInfo->ctime(file);
190  if (!timeStamp)
191  {
192  timeStamp = TDEGlobal::dirs()->calcResourceHash( g_resource, file, true);
193  }
194  KSycocaEntry* entry = 0;
195  if (g_allEntries)
196  {
197  assert(g_ctimeDict);
198  TQ_UINT32 *timeP = (*g_ctimeDict)[file];
199  TQ_UINT32 oldTimestamp = timeP ? *timeP : 0;
200 
201  if (timeStamp && (timeStamp == oldTimestamp))
202  {
203  // Re-use old entry
204  if (g_factory == g_bsgf) // Strip .directory from service-group entries
205  {
206  entry = g_entryDict->find(file.left(file.length()-10));
207  }
208  else if (g_factory == g_bsf)
209  {
210  entry = g_entryDict->find(file);
211  }
212  else
213  {
214  entry = g_entryDict->find(file);
215  }
216  // remove from g_ctimeDict; if g_ctimeDict is not empty
217  // after all files have been processed, it means
218  // some files were removed since last time
219  g_ctimeDict->remove( file );
220  }
221  else if (oldTimestamp)
222  {
223  g_changed = true;
224  kdDebug(7021) << "modified: " << file << endl;
225  }
226  else
227  {
228  g_changed = true;
229  kdDebug(7021) << "new: " << file << endl;
230  }
231  }
232  g_ctimeInfo->addCTime(file, timeStamp );
233  if (!entry)
234  {
235  // Create a new entry
236  entry = g_factory->createEntry( file, g_resource );
237  }
238  if ( entry && entry->isValid() )
239  {
240  if (addToFactory)
241  g_factory->addEntry( entry, g_resource );
242  else
243  g_tempStorage.append(entry);
244  return entry;
245  }
246  return 0;
247 }
248 
249 void KBuildSycoca::slotCreateEntry(const TQString &file, KService **service)
250 {
251  KSycocaEntry *entry = createEntry(file, false);
252  *service = dynamic_cast<KService *>(entry);
253 }
254 
255 // returns false if the database is up to date
256 bool KBuildSycoca::build()
257 {
258  typedef TQPtrList<KBSEntryDict> KBSEntryDictList;
259  KBSEntryDictList *entryDictList = 0;
260  KBSEntryDict *serviceEntryDict = 0;
261 
262  entryDictList = new KBSEntryDictList();
263  // Convert for each factory the entryList to a Dict.
264  int i = 0;
265  // For each factory
266  for (KSycocaFactory *factory = m_lstFactories->first();
267  factory;
268  factory = m_lstFactories->next() )
269  {
270  KBSEntryDict *entryDict = new KBSEntryDict();
271  if (g_allEntries)
272  {
273  KSycocaEntry::List list = (*g_allEntries)[i++];
274  for( KSycocaEntry::List::Iterator it = list.begin();
275  it != list.end();
276  ++it)
277  {
278  entryDict->insert( (*it)->entryPath(), static_cast<KSycocaEntry *>(*it));
279  }
280  }
281  if (factory == g_bsf)
282  serviceEntryDict = entryDict;
283  else if (factory == g_bsgf)
284  g_serviceGroupEntryDict = entryDict;
285  entryDictList->append(entryDict);
286  }
287 
288  TQStringList allResources;
289  // For each factory
290  for (KSycocaFactory *factory = m_lstFactories->first();
291  factory;
292  factory = m_lstFactories->next() )
293  {
294  // For each resource the factory deals with
295  const KSycocaResourceList *list = factory->resourceList();
296  if (!list) continue;
297 
298  for( KSycocaResourceList::ConstIterator it1 = list->begin();
299  it1 != list->end();
300  ++it1 )
301  {
302  KSycocaResource res = (*it1);
303  if (!allResources.contains(res.resource))
304  allResources.append(res.resource);
305  }
306  }
307 
308  g_ctimeInfo = new KCTimeInfo(); // This is a build factory too, don't delete!!
309  bool uptodate = true;
310  // For all resources
311  for( TQStringList::ConstIterator it1 = allResources.begin();
312  it1 != allResources.end();
313  ++it1 )
314  {
315  g_changed = false;
316  g_resource = (*it1).ascii();
317 
318  TQStringList relFiles;
319 
320  (void) TDEGlobal::dirs()->findAllResources( g_resource,
321  TQString::null,
322  true, // Recursive!
323  true, // uniq
324  relFiles);
325 
326 
327  // Now find all factories that use this resource....
328  // For each factory
329  g_entryDict = entryDictList->first();
330  for (g_factory = m_lstFactories->first();
331  g_factory;
332  g_factory = m_lstFactories->next(),
333  g_entryDict = entryDictList->next() )
334  {
335  // For each resource the factory deals with
336  const KSycocaResourceList *list = g_factory->resourceList();
337  if (!list) continue;
338 
339  for( KSycocaResourceList::ConstIterator it2 = list->begin();
340  it2 != list->end();
341  ++it2 )
342  {
343  KSycocaResource res = (*it2);
344  if (res.resource != (*it1)) continue;
345 
346  // For each file in the resource
347  for( TQStringList::ConstIterator it3 = relFiles.begin();
348  it3 != relFiles.end();
349  ++it3 )
350  {
351  // Check if file matches filter
352  if ((*it3).endsWith(res.extension))
353  createEntry(*it3, true);
354  }
355  }
356  if ((g_factory == g_bsf) && (strcmp(g_resource, "services") == 0))
357  processGnomeVfs();
358  }
359  if (g_changed || !g_allEntries)
360  {
361  uptodate = false;
362  g_changeList->append(g_resource);
363  }
364  }
365 
366  bool result = !uptodate || !g_ctimeDict->isEmpty();
367 
368  if (result || bMenuTest)
369  {
370  g_resource = "apps";
371  g_factory = g_bsf;
372  g_entryDict = serviceEntryDict;
373  g_changed = false;
374 
375  g_vfolder = new VFolderMenu;
376  if (!m_trackId.isEmpty())
377  g_vfolder->setTrackId(m_trackId);
378 
379  connect(g_vfolder, TQ_SIGNAL(newService(const TQString &, KService **)),
380  this, TQ_SLOT(slotCreateEntry(const TQString &, KService **)));
381 
382  VFolderMenu::SubMenu *kdeMenu = g_vfolder->parseMenu("tde-applications.menu", true);
383 
384  KServiceGroup *entry = g_bsgf->addNew("/", kdeMenu->directoryFile, 0, false);
385  entry->setLayoutInfo(kdeMenu->layoutList);
386  createMenu(TQString::null, TQString::null, kdeMenu);
387 
388  KServiceGroup::Ptr g(entry);
389 
390  (void) existingResourceDirs();
391  *g_allResourceDirs += g_vfolder->allDirectories();
392 
393  disconnect(g_vfolder, TQ_SIGNAL(newService(const TQString &, KService **)),
394  this, TQ_SLOT(slotCreateEntry(const TQString &, KService **)));
395 
396  if (g_changed || !g_allEntries)
397  {
398  uptodate = false;
399  g_changeList->append(g_resource);
400  }
401  if (bMenuTest)
402  return false;
403  }
404 
405  return result;
406 }
407 
408 void KBuildSycoca::createMenu(TQString caption, TQString name, VFolderMenu::SubMenu *menu)
409 {
410  for(VFolderMenu::SubMenu *subMenu = menu->subMenus.first(); subMenu; subMenu = menu->subMenus.next())
411  {
412  TQString subName = name+subMenu->name+"/";
413 
414  TQString directoryFile = subMenu->directoryFile;
415  if (directoryFile.isEmpty())
416  directoryFile = subName+".directory";
417  TQ_UINT32 timeStamp = g_ctimeInfo->ctime(directoryFile);
418  if (!timeStamp)
419  {
420  timeStamp = TDEGlobal::dirs()->calcResourceHash( g_resource, directoryFile, true);
421  }
422 
423  KServiceGroup* entry = 0;
424  if (g_allEntries)
425  {
426  TQ_UINT32 *timeP = (*g_ctimeDict)[directoryFile];
427  TQ_UINT32 oldTimestamp = timeP ? *timeP : 0;
428 
429  if (timeStamp && (timeStamp == oldTimestamp))
430  {
431  entry = dynamic_cast<KServiceGroup *> (g_serviceGroupEntryDict->find(subName));
432  if (entry && (entry->directoryEntryPath() != directoryFile))
433  entry = 0; // Can't reuse this one!
434  }
435  }
436  g_ctimeInfo->addCTime(directoryFile, timeStamp);
437 
438  entry = g_bsgf->addNew(subName, subMenu->directoryFile, entry, subMenu->isDeleted);
439  entry->setLayoutInfo(subMenu->layoutList);
440  if (! (bMenuTest && entry->noDisplay()) )
441  createMenu(caption + entry->caption() + "/", subName, subMenu);
442  }
443  if (caption.isEmpty())
444  caption += "/";
445  if (name.isEmpty())
446  name += "/";
447  for(TQDictIterator<KService> it(menu->items); it.current(); ++it)
448  {
449  if (bMenuTest)
450  {
451  if (!menu->isDeleted && !it.current()->noDisplay())
452  printf("%s\t%s\t%s\n", caption.local8Bit().data(), it.current()->menuId().local8Bit().data(), locate("apps", it.current()->desktopEntryPath()).local8Bit().data());
453  }
454  else
455  {
456  g_bsf->addEntry( it.current(), g_resource );
457  g_bsgf->addNewEntryTo(name, it.current());
458  }
459  }
460 }
461 
462 bool KBuildSycoca::recreate()
463 {
464  TQString path(sycocaPath());
465 #ifdef TQ_WS_WIN
466  printf("tdebuildsycoca: path='%s'\n", (const char*)path);
467 #endif
468 
469  // KSaveFile first writes to a temp file.
470  // Upon close() it moves the stuff to the right place.
471  std::unique_ptr<KSaveFile> database( new KSaveFile(path) );
472  if (database->status() == EACCES && TQFile::exists(path))
473  {
474  TQFile::remove( path );
475  database.reset( new KSaveFile(path) ); // try again
476  }
477  if (database->status() != 0)
478  {
479  fprintf(stderr, "[tdebuildsycoca] ERROR creating database '%s'! %s\n", path.local8Bit().data(),strerror(database->status()));
480 #ifdef KBUILDSYCOCA_GUI // KBUILDSYCOCA_GUI is used on win32 to build
481  // GUI version of tdebuildsycoca, so-called "tdebuildsycocaw".
482  if (!silent)
483  KMessageBox::error(0, i18n("Error creating database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n").arg(path.local8Bit().data()), i18n("KBuildSycoca"));
484 #endif
485  return false;
486  }
487 
488  m_str = database->dataStream();
489 
490  kdDebug(7021) << "Recreating tdesycoca file (" << path << ", version " << KSycoca::version() << ")" << endl;
491 
492  // It is very important to build the servicetype one first
493  // Both are registered in KSycoca, no need to keep the pointers
494  KSycocaFactory *stf = new KBuildServiceTypeFactory;
495  g_bsgf = new KBuildServiceGroupFactory();
496  g_bsf = new KBuildServiceFactory(stf, g_bsgf);
497  (void) new KBuildImageIOFactory();
498  (void) new KBuildProtocolInfoFactory();
499 
500  if( build()) // Parse dirs
501  {
502  save(); // Save database
503  if (m_str->device()->status())
504  database->abort(); // Error
505  m_str = 0L;
506  if (!database->close())
507  {
508  fprintf(stderr, "[tdebuildsycoca] ERROR writing database '%s'!\n", database->name().local8Bit().data());
509  fprintf(stderr, "[tdebuildsycoca] Disk full?\n");
510 #ifdef KBUILDSYCOCA_GUI
511  if (!silent)
512  KMessageBox::error(0, i18n("[tdebuildsycoca] Error writing database '%1'.\nCheck that the permissions are correct on the directory and the disk is not full.\n").arg(path.local8Bit().data()), i18n("KBuildSycoca"));
513 #endif
514  return false;
515  }
516  }
517  else
518  {
519  m_str = 0L;
520  database->abort();
521  if (bMenuTest)
522  return true;
523  kdDebug(7021) << "Database is up to date" << endl;
524  }
525 
526  if (!bGlobalDatabase)
527  {
528  // update the timestamp file
529  TQString stamppath = path + "stamp";
530  TQFile tdesycocastamp(stamppath);
531  tdesycocastamp.open( IO_WriteOnly );
532  TQDataStream str( &tdesycocastamp );
533  str << newTimestamp;
534  str << existingResourceDirs();
535  if (g_vfolder)
536  str << g_vfolder->allDirectories(); // Extra resource dirs
537  }
538  return true;
539 }
540 
541 void KBuildSycoca::save()
542 {
543  // Write header (#pass 1)
544  m_str->device()->at(0);
545 
546  (*m_str) << (TQ_INT32) KSycoca::version();
547  KSycocaFactory * servicetypeFactory = 0L;
548  KSycocaFactory * serviceFactory = 0L;
549  for(KSycocaFactory *factory = m_lstFactories->first();
550  factory;
551  factory = m_lstFactories->next())
552  {
553  TQ_INT32 aId;
554  TQ_INT32 aOffset;
555  aId = factory->factoryId();
556  if ( aId == KST_KServiceTypeFactory )
557  servicetypeFactory = factory;
558  else if ( aId == KST_KServiceFactory )
559  serviceFactory = factory;
560  aOffset = factory->offset();
561  (*m_str) << aId;
562  (*m_str) << aOffset;
563  }
564  (*m_str) << (TQ_INT32) 0; // No more factories.
565  // Write TDEDIRS
566  (*m_str) << TDEGlobal::dirs()->kfsstnd_prefixes();
567  (*m_str) << newTimestamp;
568  (*m_str) << TDEGlobal::locale()->language();
569  (*m_str) << TDEGlobal::dirs()->calcResourceHash("services", "update_tdesycoca", true);
570  (*m_str) << (*g_allResourceDirs);
571 
572  // Write factory data....
573  for(KSycocaFactory *factory = m_lstFactories->first();
574  factory;
575  factory = m_lstFactories->next())
576  {
577  factory->save(*m_str);
578  if (m_str->device()->status())
579  return; // error
580  }
581 
582  int endOfData = m_str->device()->at();
583 
584  // Write header (#pass 2)
585  m_str->device()->at(0);
586 
587  (*m_str) << (TQ_INT32) KSycoca::version();
588  for(KSycocaFactory *factory = m_lstFactories->first();
589  factory;
590  factory = m_lstFactories->next())
591  {
592  TQ_INT32 aId;
593  TQ_INT32 aOffset;
594  aId = factory->factoryId();
595  aOffset = factory->offset();
596  (*m_str) << aId;
597  (*m_str) << aOffset;
598  }
599  (*m_str) << (TQ_INT32) 0; // No more factories.
600 
601  // Jump to end of database
602  m_str->device()->at(endOfData);
603 }
604 
605 bool KBuildSycoca::checkDirTimestamps( const TQString& dirname, const TQDateTime& stamp, bool top )
606 {
607  if( top )
608  {
609  TQFileInfo inf( dirname );
610  if( inf.lastModified() > stamp )
611  {
612  kdDebug( 7021 ) << "timestamp changed:" << dirname << endl;
613  return false;
614  }
615  }
616  TQDir dir( dirname );
617  const TQFileInfoList *list = dir.entryInfoList( TQDir::DefaultFilter, TQDir::Unsorted );
618  if (!list)
619  return true;
620 
621  for( TQFileInfoListIterator it( *list );
622  it.current() != NULL;
623  ++it )
624  {
625  TQFileInfo* fi = it.current();
626  if( fi->fileName() == "." || fi->fileName() == ".." )
627  continue;
628  if( fi->lastModified() > stamp )
629  {
630  kdDebug( 7201 ) << "timestamp changed:" << fi->filePath() << endl;
631  return false;
632  }
633  if( fi->isDir() && !checkDirTimestamps( fi->filePath(), stamp, false ))
634  return false;
635  }
636  return true;
637 }
638 
639 // check times of last modification of all files on which tdesycoca depens,
640 // and also their directories
641 // if all of them all older than the timestamp in file tdesycocastamp, this
642 // means that there's no need to rebuild tdesycoca
643 bool KBuildSycoca::checkTimestamps( TQ_UINT32 timestamp, const TQStringList &dirs )
644 {
645  kdDebug( 7021 ) << "checking file timestamps" << endl;
646  TQDateTime stamp;
647  stamp.setTime_t( timestamp );
648  for( TQStringList::ConstIterator it = dirs.begin();
649  it != dirs.end();
650  ++it )
651  {
652  if( !checkDirTimestamps( *it, stamp, true ))
653  return false;
654  }
655  kdDebug( 7021 ) << "timestamps check ok" << endl;
656  return true;
657 }
658 
659 TQStringList KBuildSycoca::existingResourceDirs()
660 {
661  static TQStringList* dirs = NULL;
662  if( dirs != NULL )
663  return *dirs;
664  dirs = new TQStringList;
665  g_allResourceDirs = new TQStringList;
666  // these are all resources cached by tdesycoca
667  TQStringList resources;
668  resources += KBuildServiceTypeFactory::resourceTypes();
669  resources += KBuildServiceGroupFactory::resourceTypes();
670  resources += KBuildServiceFactory::resourceTypes();
671  resources += KBuildImageIOFactory::resourceTypes();
672  resources += KBuildProtocolInfoFactory::resourceTypes();
673  while( !resources.empty())
674  {
675  TQString res = resources.front();
676  *dirs += TDEGlobal::dirs()->resourceDirs( res.latin1());
677  resources.remove( res ); // remove this 'res' and all its duplicates
678  }
679 
680  *g_allResourceDirs = *dirs;
681 
682  for( TQStringList::Iterator it = dirs->begin();
683  it != dirs->end(); )
684  {
685  TQFileInfo inf( *it );
686  if( !inf.exists() || !inf.isReadable() )
687  it = dirs->remove( it );
688  else
689  ++it;
690  }
691  return *dirs;
692 }
693 
694 static TDECmdLineOptions options[] = {
695  { "nosignal", I18N_NOOP("Do not signal applications to update"), 0 },
696  { "noincremental", I18N_NOOP("Disable incremental update, re-read everything"), 0 },
697  { "checkstamps", I18N_NOOP("Check file timestamps"), 0 },
698  { "nocheckfiles", I18N_NOOP("Disable checking files (dangerous)"), 0 },
699  { "global", I18N_NOOP("Create global database"), 0 },
700  { "menutest", I18N_NOOP("Perform menu generation test run only"), 0 },
701  { "track <menu-id>", I18N_NOOP("Track menu id for debug purposes"), 0 },
702 #ifdef KBUILDSYCOCA_GUI
703  { "silent", I18N_NOOP("Silent - work without windows and stderr"), 0 },
704  { "showprogress", I18N_NOOP("Show progress information (even if 'silent' mode is on)"), 0 },
705 #endif
706  TDECmdLineLastOption
707 };
708 
709 static const char appName[] = "tdebuildsycoca";
710 static const char appVersion[] = "1.1";
711 
712 class WaitForSignal : public TQObject
713 {
714 public:
715  ~WaitForSignal() { kapp->eventLoop()->exitLoop(); }
716 };
717 
718 extern "C" TDE_EXPORT int kdemain(int argc, char **argv)
719 {
720  TDELocale::setMainCatalogue("tdelibs");
721  TDEAboutData d(appName, I18N_NOOP("KBuildSycoca"), appVersion,
722  I18N_NOOP("Rebuilds the system configuration cache."),
723  TDEAboutData::License_GPL, "(c) 1999-2002 KDE Developers");
724  d.addAuthor("David Faure", I18N_NOOP("Author"), "faure@kde.org");
725  d.addAuthor("Waldo Bastian", I18N_NOOP("Author"), "bastian@kde.org");
726 
727  TDECmdLineArgs::init(argc, argv, &d);
728  TDECmdLineArgs::addCmdLineOptions(options);
729  TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
730  bGlobalDatabase = args->isSet("global");
731  bMenuTest = args->isSet("menutest");
732 
733  if (bGlobalDatabase)
734  {
735  setenv("TDEHOME", "-", 1);
736  setenv("TDEROOTHOME", "-", 1);
737  }
738 
739  TDEApplication::disableAutoDcopRegistration();
740 #ifdef KBUILDSYCOCA_GUI
741  TDEApplication k;
742 #else
743  TDEApplication k(false, false);
744 #endif
745  k.disableSessionManagement();
746 
747 #ifdef KBUILDSYCOCA_GUI
748  silent = args->isSet("silent");
749  showprogress = args->isSet("showprogress");
750  TQLabel progress( TQString("<p><br><nobr> %1 </nobr><br>").arg( i18n("Reloading TDE configuration, please wait...") ), 0, "", TQt::WType_Dialog | TQt::WStyle_DialogBorder | TQt::WStyle_Customize| TQt::WStyle_Title );
751  TQString capt = i18n("TDE Configuration Manager");
752  if (!silent) {
753  if (KMessageBox::No == KMessageBox::questionYesNo(0, i18n("Do you want to reload TDE configuration?"), capt, i18n("Reload"), i18n("Do Not Reload")))
754  return 0;
755  }
756  if (!silent || showprogress) {
757  progress.setCaption( capt );
758  progress.show();
759  }
760 #endif
761 
762  TDECrash::setCrashHandler(TDECrash::defaultCrashHandler);
763  TDECrash::setEmergencySaveFunction(crashHandler);
764  TDECrash::setApplicationName(TQString(appName));
765 
766  // this program is in tdelibs so it uses tdelibs as catalog
767  TDELocale::setMainCatalogue("tdelibs");
768  // force generating of TDELocale object. if not, the database will get
769  // be translated
770  TDEGlobal::locale();
771  TDEGlobal::dirs()->addResourceType("app-reg", "share/application-registry" );
772 
773  DCOPClient *dcopClient = new DCOPClient();
774 
775  while(true)
776  {
777  TQCString registeredName = dcopClient->registerAs(appName, false);
778  if (registeredName.isEmpty())
779  {
780  fprintf(stderr, "[tdebuildsycoca] Warning: %s is unable to register with DCOP.\n", appName);
781  break;
782  }
783  else if (registeredName == appName)
784  {
785  break; // Go
786  }
787  fprintf(stderr, "[tdebuildsycoca] Waiting for already running %s to finish.\n", appName);
788 
789  dcopClient->setNotifications( true );
790  while (dcopClient->isApplicationRegistered(appName))
791  {
792  WaitForSignal *obj = new WaitForSignal;
793  obj->connect(dcopClient, TQ_SIGNAL(applicationRemoved(const TQCString &)),
794  TQ_SLOT(deleteLater()));
795  kapp->eventLoop()->enterLoop();
796  }
797  dcopClient->setNotifications( false );
798  }
799  fprintf(stderr, "[tdebuildsycoca] %s running...\n", appName);
800 
801  bool checkfiles = bGlobalDatabase || args->isSet("checkfiles");
802 
803  bool incremental = !bGlobalDatabase && args->isSet("incremental") && checkfiles;
804  if (incremental || !checkfiles)
805  {
806  KSycoca::self()->disableAutoRebuild(); // Prevent deadlock
807  TQString current_language = TDEGlobal::locale()->language();
808  TQString tdesycoca_language = KSycoca::self()->language();
809  TQ_UINT32 current_update_sig = TDEGlobal::dirs()->calcResourceHash("services", "update_tdesycoca", true);
810  TQ_UINT32 tdesycoca_update_sig = KSycoca::self()->updateSignature();
811 
812  if ((current_update_sig != tdesycoca_update_sig) ||
813  (current_language != tdesycoca_language) ||
814  (KSycoca::self()->timeStamp() == 0))
815  {
816  incremental = false;
817  checkfiles = true;
818  delete KSycoca::self();
819  }
820  }
821 
822  g_changeList = new TQStringList;
823 
824  bool checkstamps = incremental && args->isSet("checkstamps") && checkfiles;
825  TQ_UINT32 filestamp = 0;
826  TQStringList oldresourcedirs;
827  if( checkstamps && incremental )
828  {
829  TQString path = sycocaPath()+"stamp";
830  TQCString qPath = TQFile::encodeName(path);
831  cSycocaPath = qPath.data(); // Delete timestamps on crash
832  TQFile tdesycocastamp(path);
833  if( tdesycocastamp.open( IO_ReadOnly ))
834  {
835  TQDataStream str( &tdesycocastamp );
836  if (!str.atEnd())
837  str >> filestamp;
838  if (!str.atEnd())
839  {
840  str >> oldresourcedirs;
841  if( oldresourcedirs != KBuildSycoca::existingResourceDirs())
842  checkstamps = false;
843  }
844  else
845  {
846  checkstamps = false;
847  }
848  if (!str.atEnd())
849  {
850  TQStringList extraResourceDirs;
851  str >> extraResourceDirs;
852  oldresourcedirs += extraResourceDirs;
853  }
854  }
855  else
856  {
857  checkstamps = false;
858  }
859  cSycocaPath = 0;
860  }
861 
862  newTimestamp = (TQ_UINT32) time(0);
863 
864  if( checkfiles && ( !checkstamps || !KBuildSycoca::checkTimestamps( filestamp, oldresourcedirs )))
865  {
866  TQCString qSycocaPath = TQFile::encodeName(sycocaPath());
867  cSycocaPath = qSycocaPath.data();
868 
869  g_allEntries = 0;
870  g_ctimeDict = 0;
871  if (incremental)
872  {
873  tqWarning("[tdebuildsycoca] Reusing existing tdesycoca.");
874  KSycoca *oldSycoca = KSycoca::self();
875  KSycocaFactoryList *factories = new KSycocaFactoryList;
876  g_allEntries = new KSycocaEntryListList;
877  g_ctimeDict = new TQDict<TQ_UINT32>(523);
878 
879  // Must be in same order as in KBuildSycoca::recreate()!
880  factories->append( new KServiceTypeFactory );
881  factories->append( new KServiceGroupFactory );
882  factories->append( new KServiceFactory );
883  factories->append( new KImageIOFactory );
884  factories->append( new KProtocolInfoFactory );
885 
886  // For each factory
887  for (KSycocaFactory *factory = factories->first();
888  factory;
889  factory = factories->next() )
890  {
891  KSycocaEntry::List list;
892  list = factory->allEntries();
893  g_allEntries->append( list );
894  }
895  delete factories; factories = 0;
896  KCTimeInfo *ctimeInfo = new KCTimeInfo;
897  ctimeInfo->fillCTimeDict(*g_ctimeDict);
898  delete oldSycoca;
899  }
900  cSycocaPath = 0;
901 
902  KBuildSycoca *sycoca= new KBuildSycoca; // Build data base
903  if (args->isSet("track"))
904  sycoca->setTrackId(TQString::fromLocal8Bit(args->getOption("track")));
905  if (!sycoca->recreate()) {
906 #ifdef KBUILDSYCOCA_GUI
907  if (!silent || showprogress)
908  progress.close();
909 #endif
910  return -1;
911  }
912 
913  if (bGlobalDatabase)
914  {
915  // These directories may have been created with 0700 permission
916  // better delete them if they are empty
917  TQString applnkDir = TDEGlobal::dirs()->saveLocation("apps", TQString::null, false);
918  ::rmdir(TQFile::encodeName(applnkDir));
919  TQString servicetypesDir = TDEGlobal::dirs()->saveLocation("servicetypes", TQString::null, false);
920  ::rmdir(TQFile::encodeName(servicetypesDir));
921  }
922  }
923 
924  if (!bGlobalDatabase)
925  {
926  // Recreate compatibility symlink
927  TQString oldPath = oldSycocaPath();
928  if (!oldPath.isEmpty())
929  {
930  KTempFile tmp;
931  if (tmp.status() == 0)
932  {
933  TQString tmpFile = tmp.name();
934  tmp.unlink();
935  symlink(TQFile::encodeName(sycocaPath()), TQFile::encodeName(tmpFile));
936  rename(TQFile::encodeName(tmpFile), TQFile::encodeName(oldPath));
937  }
938  }
939  }
940 
941  if (args->isSet("signal"))
942  {
943  // Notify ALL applications that have a tdesycoca object, using a broadcast
944  TQByteArray data;
945  TQDataStream stream(data, IO_WriteOnly);
946  stream << *g_changeList;
947  dcopClient->send( "*", "tdesycoca", "notifyDatabaseChanged(TQStringList)", data );
948  }
949 
950 #ifdef KBUILDSYCOCA_GUI
951  if (!silent) {
952  progress.close();
953  KMessageBox::information(0, i18n("[tdebuildsycoca] Configuration information reloaded successfully."), capt);
954  }
955 #endif
956  return 0;
957 }
958 
959 #include "tdebuildsycoca.moc"
KBuildImageIOFactory
Service group factory for building tdesycoca.
Definition: kbuildimageiofactory.h:30
KBuildImageIOFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildimageiofactory.cpp:41
KBuildProtocolInfoFactory
Protocol Info factory for building tdesycoca.
Definition: kbuildprotocolinfofactory.h:31
KBuildProtocolInfoFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildprotocolinfofactory.cpp:40
KBuildServiceFactory
Service factory for building tdesycoca.
Definition: kbuildservicefactory.h:36
KBuildServiceFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicefactory.cpp:50
KBuildServiceFactory::addEntry
void addEntry(KSycocaEntry *newEntry, const char *resource)
Add a new entry.
Definition: kbuildservicefactory.cpp:228
KBuildServiceGroupFactory
Service group factory for building tdesycoca.
Definition: kbuildservicegroupfactory.h:31
KBuildServiceGroupFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicegroupfactory.cpp:40
KBuildServiceGroupFactory::addNew
KServiceGroup * addNew(const TQString &menuName, const TQString &file, KServiceGroup *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:75
KBuildServiceGroupFactory::addNewEntryTo
void addNewEntryTo(const TQString &menuName, KService *newEntry)
Adds the entry newEntry to the menu menuName.
Definition: kbuildservicegroupfactory.cpp:59
KBuildServiceTypeFactory
Service-type factory for building tdesycoca.
Definition: kbuildservicetypefactory.h:31
KBuildServiceTypeFactory::resourceTypes
static TQStringList resourceTypes()
Returns all resource types for this service factory.
Definition: kbuildservicetypefactory.cpp:47
KCTimeInfo
Service group factory for building tdesycoca.
Definition: kctimefactory.h:30

kded

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

kded

Skip menu "kded"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kded by doxygen 1.9.1
This website is maintained by Timothy Pearson.