]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
82cb45acdc4ee05776a4a2d2f732401d2ecc4a72
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
4 /* ######################################################################
5
6 apt-cache - Manages the cache files
7
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools.
10
11 Returns 100 on failure, 0 on success.
12
13 ##################################################################### */
14 /*}}}*/
15 // Include Files /*{{{*/
16 #include<config.h>
17
18 #include <apt-pkg/algorithms.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/indexfile.h>
25 #include <apt-pkg/init.h>
26 #include <apt-pkg/metaindex.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/pkgsystem.h>
29 #include <apt-pkg/policy.h>
30 #include <apt-pkg/progress.h>
31 #include <apt-pkg/sourcelist.h>
32 #include <apt-pkg/sptr.h>
33 #include <apt-pkg/srcrecords.h>
34 #include <apt-pkg/strutl.h>
35 #include <apt-pkg/tagfile.h>
36 #include <apt-pkg/version.h>
37 #include <apt-pkg/cacheiterators.h>
38 #include <apt-pkg/configuration.h>
39 #include <apt-pkg/depcache.h>
40 #include <apt-pkg/macros.h>
41 #include <apt-pkg/mmap.h>
42 #include <apt-pkg/pkgcache.h>
43
44 #include <apt-private/private-cacheset.h>
45 #include <apt-private/private-cmndline.h>
46 #include <apt-private/private-show.h>
47
48 #include <regex.h>
49 #include <stddef.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <unistd.h>
53 #include <algorithm>
54 #include <cstring>
55 #include <iomanip>
56 #include <iostream>
57 #include <list>
58 #include <map>
59 #include <set>
60 #include <string>
61 #include <vector>
62
63 #include <apti18n.h>
64 /*}}}*/
65
66 using namespace std;
67
68 // LocalitySort - Sort a version list by package file locality /*{{{*/
69 // ---------------------------------------------------------------------
70 /* */
71 static int LocalityCompare(const void *a, const void *b)
72 {
73 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
74 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
75
76 if (A == 0 && B == 0)
77 return 0;
78 if (A == 0)
79 return 1;
80 if (B == 0)
81 return -1;
82
83 if (A->File == B->File)
84 return A->Offset - B->Offset;
85 return A->File - B->File;
86 }
87
88 static void LocalitySort(pkgCache::VerFile **begin,
89 unsigned long Count,size_t Size)
90 {
91 qsort(begin,Count,Size,LocalityCompare);
92 }
93
94 static void LocalitySort(pkgCache::DescFile **begin,
95 unsigned long Count,size_t Size)
96 {
97 qsort(begin,Count,Size,LocalityCompare);
98 }
99 /*}}}*/
100 // UnMet - Show unmet dependencies /*{{{*/
101 // ---------------------------------------------------------------------
102 /* */
103 static bool ShowUnMet(pkgCache::VerIterator const &V, bool const Important)
104 {
105 bool Header = false;
106 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
107 {
108 // Collect or groups
109 pkgCache::DepIterator Start;
110 pkgCache::DepIterator End;
111 D.GlobOr(Start,End);
112
113 // Important deps only
114 if (Important == true)
115 if (End->Type != pkgCache::Dep::PreDepends &&
116 End->Type != pkgCache::Dep::Depends)
117 continue;
118
119 // Skip conflicts and replaces
120 if (End.IsNegative() == true || End->Type == pkgCache::Dep::Replaces)
121 continue;
122
123 // Verify the or group
124 bool OK = false;
125 pkgCache::DepIterator RealStart = Start;
126 do
127 {
128 // See if this dep is Ok
129 pkgCache::Version **VList = Start.AllTargets();
130 if (*VList != 0)
131 {
132 OK = true;
133 delete [] VList;
134 break;
135 }
136 delete [] VList;
137
138 if (Start == End)
139 break;
140 ++Start;
141 }
142 while (1);
143
144 // The group is OK
145 if (OK == true)
146 continue;
147
148 // Oops, it failed..
149 if (Header == false)
150 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
151 V.ParentPkg().FullName(true).c_str(),V.VerStr());
152 Header = true;
153
154 // Print out the dep type
155 cout << " " << End.DepType() << ": ";
156
157 // Show the group
158 Start = RealStart;
159 do
160 {
161 cout << Start.TargetPkg().FullName(true);
162 if (Start.TargetVer() != 0)
163 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
164 ")";
165 if (Start == End)
166 break;
167 cout << " | ";
168 ++Start;
169 }
170 while (1);
171
172 cout << endl;
173 }
174 return true;
175 }
176 static bool UnMet(CommandLine &CmdL)
177 {
178 bool const Important = _config->FindB("APT::Cache::Important",false);
179
180 pkgCacheFile CacheFile;
181 if (unlikely(CacheFile.GetPkgCache() == NULL))
182 return false;
183
184 if (CmdL.FileSize() <= 1)
185 {
186 for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; ++P)
187 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
188 if (ShowUnMet(V, Important) == false)
189 return false;
190 }
191 else
192 {
193 CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
194 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1,
195 APT::CacheSetHelper::CANDIDATE, helper);
196 for (APT::VersionList::iterator V = verset.begin(); V != verset.end(); ++V)
197 if (ShowUnMet(V, Important) == false)
198 return false;
199 }
200 return true;
201 }
202 /*}}}*/
203 // DumpPackage - Show a dump of a package record /*{{{*/
204 // ---------------------------------------------------------------------
205 /* */
206 static bool DumpPackage(CommandLine &CmdL)
207 {
208 pkgCacheFile CacheFile;
209 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
210 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
211
212 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
213 {
214 cout << "Package: " << Pkg.FullName(true) << endl;
215 cout << "Versions: " << endl;
216 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
217 {
218 cout << Cur.VerStr();
219 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; ++Vf)
220 cout << " (" << Vf.File().FileName() << ")";
221 cout << endl;
222 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; ++D)
223 {
224 cout << " Description Language: " << D.LanguageCode() << endl
225 << " File: " << D.FileList().File().FileName() << endl
226 << " MD5: " << D.md5() << endl;
227 }
228 cout << endl;
229 }
230
231 cout << endl;
232
233 cout << "Reverse Depends: " << endl;
234 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D)
235 {
236 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
237 if (D->Version != 0)
238 cout << ' ' << DeNull(D.TargetVer()) << endl;
239 else
240 cout << endl;
241 }
242
243 cout << "Dependencies: " << endl;
244 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
245 {
246 cout << Cur.VerStr() << " - ";
247 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; ++Dep)
248 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
249 cout << endl;
250 }
251
252 cout << "Provides: " << endl;
253 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
254 {
255 cout << Cur.VerStr() << " - ";
256 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; ++Prv)
257 cout << Prv.ParentPkg().FullName(true) << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ") ";
258 cout << endl;
259 }
260 cout << "Reverse Provides: " << endl;
261 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; ++Prv)
262 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ")"<< endl;
263 }
264
265 return true;
266 }
267 /*}}}*/
268 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
269 // ---------------------------------------------------------------------
270 /* */
271 static map_pointer_t PackageNext(pkgCache::Package const * const P) { return P->NextPackage; }
272 static map_pointer_t GroupNext(pkgCache::Group const * const G) { return G->Next; }
273 template<class T>
274 static void ShowHashTableStats(std::string Type,
275 T *StartP,
276 map_pointer_t *Hashtable,
277 unsigned long Size,
278 map_pointer_t(*Next)(T const * const))
279 {
280 // hashtable stats for the HashTable
281 unsigned long NumBuckets = Size;
282 unsigned long UsedBuckets = 0;
283 unsigned long UnusedBuckets = 0;
284 unsigned long LongestBucket = 0;
285 unsigned long ShortestBucket = NumBuckets;
286 unsigned long Entries = 0;
287 for (unsigned int i=0; i < NumBuckets; ++i)
288 {
289 T *P = StartP + Hashtable[i];
290 if(P == 0 || P == StartP)
291 {
292 ++UnusedBuckets;
293 continue;
294 }
295 ++UsedBuckets;
296 unsigned long ThisBucketSize = 0;
297 for (; P != StartP; P = StartP + Next(P))
298 ++ThisBucketSize;
299 Entries += ThisBucketSize;
300 LongestBucket = std::max(ThisBucketSize, LongestBucket);
301 ShortestBucket = std::min(ThisBucketSize, ShortestBucket);
302 }
303 cout << "Total buckets in " << Type << ": " << NumBuckets << std::endl;
304 cout << " Unused: " << UnusedBuckets << std::endl;
305 cout << " Used: " << UsedBuckets << std::endl;
306 cout << " Average entries: " << Entries/(double)NumBuckets << std::endl;
307 cout << " Longest: " << LongestBucket << std::endl;
308 cout << " Shortest: " << ShortestBucket << std::endl;
309 }
310 /*}}}*/
311 // Stats - Dump some nice statistics /*{{{*/
312 // ---------------------------------------------------------------------
313 /* */
314 static bool Stats(CommandLine &CmdL)
315 {
316 if (CmdL.FileSize() > 1) {
317 _error->Error(_("apt-cache stats does not take any arguments"));
318 return false;
319 }
320
321 pkgCacheFile CacheFile;
322 pkgCache *Cache = CacheFile.GetPkgCache();
323
324 if (unlikely(Cache == NULL))
325 return false;
326
327 cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
328 SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
329 << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
330 SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
331
332 int Normal = 0;
333 int Virtual = 0;
334 int NVirt = 0;
335 int DVirt = 0;
336 int Missing = 0;
337 pkgCache::PkgIterator I = Cache->PkgBegin();
338 for (;I.end() != true; ++I)
339 {
340 if (I->VersionList != 0 && I->ProvidesList == 0)
341 {
342 Normal++;
343 continue;
344 }
345
346 if (I->VersionList != 0 && I->ProvidesList != 0)
347 {
348 NVirt++;
349 continue;
350 }
351
352 if (I->VersionList == 0 && I->ProvidesList != 0)
353 {
354 // Only 1 provides
355 if (I.ProvidesList()->NextProvides == 0)
356 {
357 DVirt++;
358 }
359 else
360 Virtual++;
361 continue;
362 }
363 if (I->VersionList == 0 && I->ProvidesList == 0)
364 {
365 Missing++;
366 continue;
367 }
368 }
369 cout << _(" Normal packages: ") << Normal << endl;
370 cout << _(" Pure virtual packages: ") << Virtual << endl;
371 cout << _(" Single virtual packages: ") << DVirt << endl;
372 cout << _(" Mixed virtual packages: ") << NVirt << endl;
373 cout << _(" Missing: ") << Missing << endl;
374
375 cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
376 SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
377 cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
378 SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
379 cout << _("Total dependencies: ") << Cache->Head().DependsCount << "/" << Cache->Head().DependsDataCount << " (" <<
380 SizeToStr((Cache->Head().DependsCount*Cache->Head().DependencySz) +
381 (Cache->Head().DependsDataCount*Cache->Head().DependencyDataSz)) << ')' << endl;
382 cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
383 SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
384 cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
385 SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
386 cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
387 SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
388
389 // String list stats
390 std::set<map_stringitem_t> stritems;
391 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
392 stritems.insert(G->Name);
393 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
394 {
395 stritems.insert(P->Arch);
396 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
397 {
398 if (V->VerStr != 0)
399 stritems.insert(V->VerStr);
400 if (V->Section != 0)
401 stritems.insert(V->Section);
402 stritems.insert(V->SourcePkgName);
403 stritems.insert(V->SourceVerStr);
404 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
405 {
406 if (D->Version != 0)
407 stritems.insert(D->Version);
408 }
409 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
410 {
411 stritems.insert(D->md5sum);
412 stritems.insert(D->language_code);
413 }
414 }
415 for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
416 {
417 if (Prv->ProvideVersion != 0)
418 stritems.insert(Prv->ProvideVersion);
419 }
420 }
421 for (pkgCache::RlsFileIterator F = Cache->RlsFileBegin(); F != Cache->RlsFileEnd(); ++F)
422 {
423 stritems.insert(F->FileName);
424 stritems.insert(F->Archive);
425 stritems.insert(F->Codename);
426 stritems.insert(F->Version);
427 stritems.insert(F->Origin);
428 stritems.insert(F->Label);
429 stritems.insert(F->Site);
430 }
431 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
432 {
433 stritems.insert(F->FileName);
434 stritems.insert(F->Architecture);
435 stritems.insert(F->Component);
436 stritems.insert(F->IndexType);
437 }
438
439 unsigned long Size = 0;
440 for (std::set<map_stringitem_t>::const_iterator i = stritems.begin(); i != stritems.end(); ++i)
441 Size += strlen(Cache->StrP + *i) + 1;
442 cout << _("Total globbed strings: ") << stritems.size() << " (" << SizeToStr(Size) << ')' << endl;
443 stritems.clear();
444
445 unsigned long Slack = 0;
446 for (int I = 0; I != 7; I++)
447 Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
448 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
449
450 unsigned long Total = 0;
451 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
452 Total = Slack + Size +
453 APT_CACHESIZE(GroupCount, GroupSz) +
454 APT_CACHESIZE(PackageCount, PackageSz) +
455 APT_CACHESIZE(VersionCount, VersionSz) +
456 APT_CACHESIZE(DescriptionCount, DescriptionSz) +
457 APT_CACHESIZE(DependsCount, DependencySz) +
458 APT_CACHESIZE(DependsDataCount, DependencyDataSz) +
459 APT_CACHESIZE(ReleaseFileCount, ReleaseFileSz) +
460 APT_CACHESIZE(PackageFileCount, PackageFileSz) +
461 APT_CACHESIZE(VerFileCount, VerFileSz) +
462 APT_CACHESIZE(DescFileCount, DescFileSz) +
463 APT_CACHESIZE(ProvidesCount, ProvidesSz) +
464 (2 * Cache->Head().GetHashTableSize() * sizeof(map_id_t));
465 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
466 #undef APT_CACHESIZE
467
468 // hashtable stats
469 ShowHashTableStats<pkgCache::Package>("PkgHashTable", Cache->PkgP, Cache->Head().PkgHashTableP(), Cache->Head().GetHashTableSize(), PackageNext);
470 ShowHashTableStats<pkgCache::Group>("GrpHashTable", Cache->GrpP, Cache->Head().GrpHashTableP(), Cache->Head().GetHashTableSize(), GroupNext);
471
472 return true;
473 }
474 /*}}}*/
475 // Dump - show everything /*{{{*/
476 // ---------------------------------------------------------------------
477 /* This is worthless except fer debugging things */
478 static bool Dump(CommandLine &)
479 {
480 pkgCacheFile CacheFile;
481 pkgCache *Cache = CacheFile.GetPkgCache();
482 if (unlikely(Cache == NULL))
483 return false;
484
485 std::cout << "Using Versioning System: " << Cache->VS->Label << std::endl;
486
487 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
488 {
489 std::cout << "Package: " << P.FullName(true) << std::endl;
490 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
491 {
492 std::cout << " Version: " << V.VerStr() << std::endl;
493 std::cout << " File: " << V.FileList().File().FileName() << std::endl;
494 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
495 std::cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
496 DeNull(D.TargetVer()) << std::endl;
497 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
498 {
499 std::cout << " Description Language: " << D.LanguageCode() << std::endl
500 << " File: " << D.FileList().File().FileName() << std::endl
501 << " MD5: " << D.md5() << std::endl;
502 }
503 }
504 }
505
506 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
507 {
508 std::cout << "File: " << F.FileName() << std::endl;
509 std::cout << " Type: " << F.IndexType() << std::endl;
510 std::cout << " Size: " << F->Size << std::endl;
511 std::cout << " ID: " << F->ID << std::endl;
512 std::cout << " Flags: " << F->Flags << std::endl;
513 std::cout << " Time: " << TimeRFC1123(F->mtime) << std::endl;
514 std::cout << " Archive: " << DeNull(F.Archive()) << std::endl;
515 std::cout << " Component: " << DeNull(F.Component()) << std::endl;
516 std::cout << " Version: " << DeNull(F.Version()) << std::endl;
517 std::cout << " Origin: " << DeNull(F.Origin()) << std::endl;
518 std::cout << " Site: " << DeNull(F.Site()) << std::endl;
519 std::cout << " Label: " << DeNull(F.Label()) << std::endl;
520 std::cout << " Architecture: " << DeNull(F.Architecture()) << std::endl;
521 }
522
523 return true;
524 }
525 /*}}}*/
526 // DumpAvail - Print out the available list /*{{{*/
527 // ---------------------------------------------------------------------
528 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
529 make this run really fast, perhaps I went a little overboard.. */
530 static bool DumpAvail(CommandLine &)
531 {
532 pkgCacheFile CacheFile;
533 pkgCache *Cache = CacheFile.GetPkgCache();
534 if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
535 return false;
536
537 unsigned long Count = Cache->HeaderP->PackageCount+1;
538 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
539 memset(VFList,0,sizeof(*VFList)*Count);
540
541 // Map versions that we want to write out onto the VerList array.
542 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
543 {
544 if (P->VersionList == 0)
545 continue;
546
547 /* Find the proper version to use. If the policy says there are no
548 possible selections we return the installed version, if available..
549 This prevents dselect from making it obsolete. */
550 pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
551 if (V.end() == true)
552 {
553 if (P->CurrentVer == 0)
554 continue;
555 V = P.CurrentVer();
556 }
557
558 pkgCache::VerFileIterator VF = V.FileList();
559 for (; VF.end() == false ; ++VF)
560 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
561 break;
562
563 /* Okay, here we have a bit of a problem.. The policy has selected the
564 currently installed package - however it only exists in the
565 status file.. We need to write out something or dselect will mark
566 the package as obsolete! Thus we emit the status file entry, but
567 below we remove the status line to make it valid for the
568 available file. However! We only do this if their do exist *any*
569 non-source versions of the package - that way the dselect obsolete
570 handling works OK. */
571 if (VF.end() == true)
572 {
573 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; ++Cur)
574 {
575 for (VF = Cur.FileList(); VF.end() == false; ++VF)
576 {
577 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
578 {
579 VF = V.FileList();
580 break;
581 }
582 }
583
584 if (VF.end() == false)
585 break;
586 }
587 }
588
589 VFList[P->ID] = VF;
590 }
591
592 LocalitySort(VFList,Count,sizeof(*VFList));
593
594 std::vector<pkgTagSection::Tag> RW;
595 RW.push_back(pkgTagSection::Tag::Remove("Status"));
596 RW.push_back(pkgTagSection::Tag::Remove("Config-Version"));
597 FileFd stdoutfd;
598 stdoutfd.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false);
599
600 // Iterate over all the package files and write them out.
601 char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
602 for (pkgCache::VerFile **J = VFList; *J != 0;)
603 {
604 pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
605 if (File.IsOk() == false)
606 {
607 _error->Error(_("Package file %s is out of sync."),File.FileName());
608 break;
609 }
610
611 FileFd PkgF(File.FileName(),FileFd::ReadOnly, FileFd::Extension);
612 if (_error->PendingError() == true)
613 break;
614
615 /* Write all of the records from this package file, since we
616 already did locality sorting we can now just seek through the
617 file in read order. We apply 1 more optimization here, since often
618 there will be < 1 byte gaps between records (for the \n) we read that
619 into the next buffer and offset a bit.. */
620 unsigned long Pos = 0;
621 for (; *J != 0; J++)
622 {
623 if ((*J)->File + Cache->PkgFileP != File)
624 break;
625
626 const pkgCache::VerFile &VF = **J;
627
628 // Read the record and then write it out again.
629 unsigned long Jitter = VF.Offset - Pos;
630 if (Jitter > 8)
631 {
632 if (PkgF.Seek(VF.Offset) == false)
633 break;
634 Jitter = 0;
635 }
636
637 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
638 break;
639 Buffer[VF.Size + Jitter] = '\n';
640
641 // See above..
642 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
643 {
644 pkgTagSection Tags;
645 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
646 Tags.Write(stdoutfd, NULL, RW) == false ||
647 stdoutfd.Write("\n", 1) == false)
648 {
649 _error->Error("Internal Error, Unable to parse a package record");
650 break;
651 }
652 }
653 else
654 {
655 if (stdoutfd.Write(Buffer + Jitter, VF.Size + 1) == false)
656 break;
657 }
658
659 Pos = VF.Offset + VF.Size;
660 }
661
662 if (_error->PendingError() == true)
663 break;
664 }
665
666 delete [] Buffer;
667 delete [] VFList;
668 return !_error->PendingError();
669 }
670 /*}}}*/
671 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
672 static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
673 {
674 pkgCacheFile CacheFile;
675 pkgCache *Cache = CacheFile.GetPkgCache();
676 if (unlikely(Cache == NULL))
677 return false;
678
679 CacheSetHelperVirtuals helper(false);
680 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
681 if (verset.empty() == true && helper.virtualPkgs.empty() == true)
682 return _error->Error(_("No packages found"));
683 std::vector<bool> Shown(Cache->Head().PackageCount);
684
685 bool const Recurse = _config->FindB("APT::Cache::RecurseDepends", false);
686 bool const Installed = _config->FindB("APT::Cache::Installed", false);
687 bool const Important = _config->FindB("APT::Cache::Important", false);
688 bool const ShowDepType = _config->FindB("APT::Cache::ShowDependencyType", RevDepends == false);
689 bool const ShowVersion = _config->FindB("APT::Cache::ShowVersion", false);
690 bool const ShowPreDepends = _config->FindB("APT::Cache::ShowPre-Depends", true);
691 bool const ShowDepends = _config->FindB("APT::Cache::ShowDepends", true);
692 bool const ShowRecommends = _config->FindB("APT::Cache::ShowRecommends", Important == false);
693 bool const ShowSuggests = _config->FindB("APT::Cache::ShowSuggests", Important == false);
694 bool const ShowReplaces = _config->FindB("APT::Cache::ShowReplaces", Important == false);
695 bool const ShowConflicts = _config->FindB("APT::Cache::ShowConflicts", Important == false);
696 bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
697 bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
698 bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false);
699 bool const ShowImplicit = _config->FindB("APT::Cache::ShowImplicit", false);
700
701 while (verset.empty() != true)
702 {
703 pkgCache::VerIterator Ver = *verset.begin();
704 verset.erase(verset.begin());
705 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
706 Shown[Pkg->ID] = true;
707
708 cout << Pkg.FullName(true) << endl;
709
710 if (RevDepends == true)
711 cout << "Reverse Depends:" << endl;
712 for (pkgCache::DepIterator D = RevDepends ? Pkg.RevDependsList() : Ver.DependsList();
713 D.end() == false; ++D)
714 {
715 switch (D->Type) {
716 case pkgCache::Dep::PreDepends: if (!ShowPreDepends) continue; break;
717 case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
718 case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
719 case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break;
720 case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break;
721 case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
722 case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
723 case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
724 }
725 if (ShowImplicit == false && D.IsImplicit())
726 continue;
727
728 pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg();
729
730 if((Installed && Trg->CurrentVer != 0) || !Installed)
731 {
732
733 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or && ShowOnlyFirstOr == false)
734 cout << " |";
735 else
736 cout << " ";
737
738 // Show the package
739 if (ShowDepType == true)
740 cout << D.DepType() << ": ";
741 if (Trg->VersionList == 0)
742 cout << "<" << Trg.FullName(true) << ">";
743 else
744 cout << Trg.FullName(true);
745 if (ShowVersion == true && D->Version != 0)
746 cout << " (" << pkgCache::CompTypeDeb(D->CompareOp) << ' ' << D.TargetVer() << ')';
747 cout << std::endl;
748
749 if (Recurse == true && Shown[Trg->ID] == false)
750 {
751 Shown[Trg->ID] = true;
752 verset.insert(APT::VersionSet::FromPackage(CacheFile, Trg, APT::CacheSetHelper::CANDIDATE, helper));
753 }
754
755 }
756
757 // Display all solutions
758 std::unique_ptr<pkgCache::Version *[]> List(D.AllTargets());
759 pkgPrioSortList(*Cache,List.get());
760 for (pkgCache::Version **I = List.get(); *I != 0; I++)
761 {
762 pkgCache::VerIterator V(*Cache,*I);
763 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
764 V->ParentPkg == D->Package)
765 continue;
766 cout << " " << V.ParentPkg().FullName(true) << endl;
767
768 if (Recurse == true && Shown[V.ParentPkg()->ID] == false)
769 {
770 Shown[V.ParentPkg()->ID] = true;
771 verset.insert(APT::VersionSet::FromPackage(CacheFile, V.ParentPkg(), APT::CacheSetHelper::CANDIDATE, helper));
772 }
773 }
774
775 if (ShowOnlyFirstOr == true)
776 while ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) ++D;
777 }
778 }
779
780 for (APT::PackageSet::const_iterator Pkg = helper.virtualPkgs.begin();
781 Pkg != helper.virtualPkgs.end(); ++Pkg)
782 cout << '<' << Pkg.FullName(true) << '>' << endl;
783
784 return true;
785 }
786 /*}}}*/
787 // Depends - Print out a dependency tree /*{{{*/
788 // ---------------------------------------------------------------------
789 /* */
790 static bool Depends(CommandLine &CmdL)
791 {
792 return ShowDepends(CmdL, false);
793 }
794 /*}}}*/
795 // RDepends - Print out a reverse dependency tree /*{{{*/
796 // ---------------------------------------------------------------------
797 /* */
798 static bool RDepends(CommandLine &CmdL)
799 {
800 return ShowDepends(CmdL, true);
801 }
802 /*}}}*/
803 // xvcg - Generate a graph for xvcg /*{{{*/
804 // ---------------------------------------------------------------------
805 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
806
807 static bool XVcg(CommandLine &CmdL)
808 {
809 pkgCacheFile CacheFile;
810 pkgCache *Cache = CacheFile.GetPkgCache();
811 if (unlikely(Cache == NULL))
812 return false;
813
814 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
815
816 /* Normal packages are boxes
817 Pure Provides are triangles
818 Mixed are diamonds
819 rhomb are missing packages*/
820 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
821
822 /* Initialize the list of packages to show.
823 1 = To Show
824 2 = To Show no recurse
825 3 = Emitted no recurse
826 4 = Emitted
827 0 = None */
828 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
829 enum TheFlags {ForceNR=(1<<0)};
830 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
831 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
832 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
833
834 // Show everything if no arguments given
835 if (CmdL.FileList[1] == 0)
836 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
837 Show[I] = ToShow;
838 else
839 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
840 Show[I] = None;
841 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
842
843 // Map the shapes
844 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
845 {
846 if (Pkg->VersionList == 0)
847 {
848 // Missing
849 if (Pkg->ProvidesList == 0)
850 ShapeMap[Pkg->ID] = 0;
851 else
852 ShapeMap[Pkg->ID] = 1;
853 }
854 else
855 {
856 // Normal
857 if (Pkg->ProvidesList == 0)
858 ShapeMap[Pkg->ID] = 2;
859 else
860 ShapeMap[Pkg->ID] = 3;
861 }
862 }
863
864 // Load the list of packages from the command line into the show list
865 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
866 std::list<APT::CacheSetHelper::PkgModifier> mods;
867 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
868 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
869 std::map<unsigned short, APT::PackageSet> pkgsets =
870 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
871
872 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
873 Pkg != pkgsets[0].end(); ++Pkg)
874 Show[Pkg->ID] = ToShow;
875 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
876 Pkg != pkgsets[1].end(); ++Pkg)
877 {
878 Show[Pkg->ID] = ToShow;
879 Flags[Pkg->ID] |= ForceNR;
880 }
881
882 // Little header
883 cout << "graph: { title: \"packages\"" << endl <<
884 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
885 "layout_downfactor: 8" << endl;
886
887 bool Act = true;
888 while (Act == true)
889 {
890 Act = false;
891 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
892 {
893 // See we need to show this package
894 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
895 continue;
896
897 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
898
899 // Colour as done
900 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
901 {
902 // Pure Provides and missing packages have no deps!
903 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
904 Show[Pkg->ID] = Done;
905 else
906 Show[Pkg->ID] = DoneNR;
907 }
908 else
909 Show[Pkg->ID] = Done;
910 Act = true;
911
912 // No deps to map out
913 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
914 continue;
915
916 pkgCache::VerIterator Ver = Pkg.VersionList();
917 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
918 {
919 // See if anything can meet this dep
920 // Walk along the actual package providing versions
921 bool Hit = false;
922 pkgCache::PkgIterator DPkg = D.TargetPkg();
923 for (pkgCache::VerIterator I = DPkg.VersionList();
924 I.end() == false && Hit == false; ++I)
925 {
926 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
927 Hit = true;
928 }
929
930 // Follow all provides
931 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
932 I.end() == false && Hit == false; ++I)
933 {
934 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
935 Hit = true;
936 }
937
938
939 // Only graph critical deps
940 if (D.IsCritical() == true)
941 {
942 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
943
944 // Colour the node for recursion
945 if (Show[D.TargetPkg()->ID] <= DoneNR)
946 {
947 /* If a conflicts does not meet anything in the database
948 then show the relation but do not recurse */
949 if (Hit == false && D.IsNegative() == true)
950 {
951 if (Show[D.TargetPkg()->ID] == None &&
952 Show[D.TargetPkg()->ID] != ToShow)
953 Show[D.TargetPkg()->ID] = ToShowNR;
954 }
955 else
956 {
957 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
958 Show[D.TargetPkg()->ID] = ToShowNR;
959 else
960 Show[D.TargetPkg()->ID] = ToShow;
961 }
962 }
963
964 // Edge colour
965 switch(D->Type)
966 {
967 case pkgCache::Dep::Conflicts:
968 printf("label: \"conflicts\" color: lightgreen }\n");
969 break;
970 case pkgCache::Dep::DpkgBreaks:
971 printf("label: \"breaks\" color: lightgreen }\n");
972 break;
973 case pkgCache::Dep::Obsoletes:
974 printf("label: \"obsoletes\" color: lightgreen }\n");
975 break;
976
977 case pkgCache::Dep::PreDepends:
978 printf("label: \"predepends\" color: blue }\n");
979 break;
980
981 default:
982 printf("}\n");
983 break;
984 }
985 }
986 }
987 }
988 }
989
990 /* Draw the box colours after the fact since we can not tell what colour
991 they should be until everything is finished drawing */
992 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
993 {
994 if (Show[Pkg->ID] < DoneNR)
995 continue;
996
997 if (Show[Pkg->ID] == DoneNR)
998 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
999 Shapes[ShapeMap[Pkg->ID]]);
1000 else
1001 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
1002 Shapes[ShapeMap[Pkg->ID]]);
1003
1004 }
1005
1006 delete[] Show;
1007 delete[] Flags;
1008 delete[] ShapeMap;
1009
1010 printf("}\n");
1011 return true;
1012 }
1013 /*}}}*/
1014 // Dotty - Generate a graph for Dotty /*{{{*/
1015 // ---------------------------------------------------------------------
1016 /* Dotty is the graphvis program for generating graphs. It is a fairly
1017 simple queuing algorithm that just writes dependencies and nodes.
1018 http://www.research.att.com/sw/tools/graphviz/ */
1019 static bool Dotty(CommandLine &CmdL)
1020 {
1021 pkgCacheFile CacheFile;
1022 pkgCache *Cache = CacheFile.GetPkgCache();
1023 if (unlikely(Cache == NULL))
1024 return false;
1025
1026 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
1027
1028 /* Normal packages are boxes
1029 Pure Provides are triangles
1030 Mixed are diamonds
1031 Hexagons are missing packages*/
1032 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
1033
1034 /* Initialize the list of packages to show.
1035 1 = To Show
1036 2 = To Show no recurse
1037 3 = Emitted no recurse
1038 4 = Emitted
1039 0 = None */
1040 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
1041 enum TheFlags {ForceNR=(1<<0)};
1042 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
1043 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
1044 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
1045
1046 // Show everything if no arguments given
1047 if (CmdL.FileList[1] == 0)
1048 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
1049 Show[I] = ToShow;
1050 else
1051 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
1052 Show[I] = None;
1053 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
1054
1055 // Map the shapes
1056 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
1057 {
1058 if (Pkg->VersionList == 0)
1059 {
1060 // Missing
1061 if (Pkg->ProvidesList == 0)
1062 ShapeMap[Pkg->ID] = 0;
1063 else
1064 ShapeMap[Pkg->ID] = 1;
1065 }
1066 else
1067 {
1068 // Normal
1069 if (Pkg->ProvidesList == 0)
1070 ShapeMap[Pkg->ID] = 2;
1071 else
1072 ShapeMap[Pkg->ID] = 3;
1073 }
1074 }
1075
1076 // Load the list of packages from the command line into the show list
1077 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1078 std::list<APT::CacheSetHelper::PkgModifier> mods;
1079 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
1080 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
1081 std::map<unsigned short, APT::PackageSet> pkgsets =
1082 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
1083
1084 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
1085 Pkg != pkgsets[0].end(); ++Pkg)
1086 Show[Pkg->ID] = ToShow;
1087 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
1088 Pkg != pkgsets[1].end(); ++Pkg)
1089 {
1090 Show[Pkg->ID] = ToShow;
1091 Flags[Pkg->ID] |= ForceNR;
1092 }
1093
1094 // Little header
1095 printf("digraph packages {\n");
1096 printf("concentrate=true;\n");
1097 printf("size=\"30,40\";\n");
1098
1099 bool Act = true;
1100 while (Act == true)
1101 {
1102 Act = false;
1103 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
1104 {
1105 // See we need to show this package
1106 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
1107 continue;
1108
1109 // Colour as done
1110 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
1111 {
1112 // Pure Provides and missing packages have no deps!
1113 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
1114 Show[Pkg->ID] = Done;
1115 else
1116 Show[Pkg->ID] = DoneNR;
1117 }
1118 else
1119 Show[Pkg->ID] = Done;
1120 Act = true;
1121
1122 // No deps to map out
1123 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
1124 continue;
1125
1126 pkgCache::VerIterator Ver = Pkg.VersionList();
1127 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
1128 {
1129 // See if anything can meet this dep
1130 // Walk along the actual package providing versions
1131 bool Hit = false;
1132 pkgCache::PkgIterator DPkg = D.TargetPkg();
1133 for (pkgCache::VerIterator I = DPkg.VersionList();
1134 I.end() == false && Hit == false; ++I)
1135 {
1136 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
1137 Hit = true;
1138 }
1139
1140 // Follow all provides
1141 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
1142 I.end() == false && Hit == false; ++I)
1143 {
1144 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
1145 Hit = true;
1146 }
1147
1148 // Only graph critical deps
1149 if (D.IsCritical() == true)
1150 {
1151 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
1152
1153 // Colour the node for recursion
1154 if (Show[D.TargetPkg()->ID] <= DoneNR)
1155 {
1156 /* If a conflicts does not meet anything in the database
1157 then show the relation but do not recurse */
1158 if (Hit == false && D.IsNegative() == true)
1159 {
1160 if (Show[D.TargetPkg()->ID] == None &&
1161 Show[D.TargetPkg()->ID] != ToShow)
1162 Show[D.TargetPkg()->ID] = ToShowNR;
1163 }
1164 else
1165 {
1166 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1167 Show[D.TargetPkg()->ID] = ToShowNR;
1168 else
1169 Show[D.TargetPkg()->ID] = ToShow;
1170 }
1171 }
1172
1173 // Edge colour
1174 switch(D->Type)
1175 {
1176 case pkgCache::Dep::Conflicts:
1177 case pkgCache::Dep::Obsoletes:
1178 case pkgCache::Dep::DpkgBreaks:
1179 printf("[color=springgreen];\n");
1180 break;
1181
1182 case pkgCache::Dep::PreDepends:
1183 printf("[color=blue];\n");
1184 break;
1185
1186 default:
1187 printf(";\n");
1188 break;
1189 }
1190 }
1191 }
1192 }
1193 }
1194
1195 /* Draw the box colours after the fact since we can not tell what colour
1196 they should be until everything is finished drawing */
1197 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
1198 {
1199 if (Show[Pkg->ID] < DoneNR)
1200 continue;
1201
1202 // Orange box for early recursion stoppage
1203 if (Show[Pkg->ID] == DoneNR)
1204 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
1205 Shapes[ShapeMap[Pkg->ID]]);
1206 else
1207 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
1208 Shapes[ShapeMap[Pkg->ID]]);
1209 }
1210
1211 printf("}\n");
1212 delete[] Show;
1213 delete[] Flags;
1214 delete[] ShapeMap;
1215 return true;
1216 }
1217 /*}}}*/
1218 struct ExDescFile
1219 {
1220 pkgCache::DescFile *Df;
1221 pkgCache::VerIterator V;
1222 map_id_t ID;
1223 };
1224
1225 // Search - Perform a search /*{{{*/
1226 // ---------------------------------------------------------------------
1227 /* This searches the package names and package descriptions for a pattern */
1228 static bool Search(CommandLine &CmdL)
1229 {
1230 bool const ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1231 bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
1232 unsigned int const NumPatterns = CmdL.FileSize() -1;
1233
1234 pkgCacheFile CacheFile;
1235 pkgCache *Cache = CacheFile.GetPkgCache();
1236 pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
1237 if (unlikely(Cache == NULL || Plcy == NULL))
1238 return false;
1239
1240 // Make sure there is at least one argument
1241 if (NumPatterns < 1)
1242 return _error->Error(_("You must give at least one search pattern"));
1243
1244 // Compile the regex pattern
1245 regex_t *Patterns = new regex_t[NumPatterns];
1246 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1247 for (unsigned I = 0; I != NumPatterns; I++)
1248 {
1249 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1250 REG_NOSUB) != 0)
1251 {
1252 for (; I != 0; I--)
1253 regfree(&Patterns[I]);
1254 return _error->Error("Regex compilation error");
1255 }
1256 }
1257
1258 if (_error->PendingError() == true)
1259 {
1260 for (unsigned I = 0; I != NumPatterns; I++)
1261 regfree(&Patterns[I]);
1262 return false;
1263 }
1264
1265 size_t const descCount = Cache->HeaderP->GroupCount + 1;
1266 ExDescFile *DFList = new ExDescFile[descCount];
1267 memset(DFList,0,sizeof(*DFList) * descCount);
1268
1269 bool *PatternMatch = new bool[descCount * NumPatterns];
1270 memset(PatternMatch,false,sizeof(*PatternMatch) * descCount * NumPatterns);
1271
1272 // Map versions that we want to write out onto the VerList array.
1273 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
1274 {
1275 size_t const PatternOffset = G->ID * NumPatterns;
1276 size_t unmatched = 0, matched = 0;
1277 for (unsigned I = 0; I < NumPatterns; ++I)
1278 {
1279 if (PatternMatch[PatternOffset + I] == true)
1280 ++matched;
1281 else if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
1282 PatternMatch[PatternOffset + I] = true;
1283 else
1284 ++unmatched;
1285 }
1286
1287 // already dealt with this package?
1288 if (matched == NumPatterns)
1289 continue;
1290
1291 // Doing names only, drop any that don't match..
1292 if (NamesOnly == true && unmatched == NumPatterns)
1293 continue;
1294
1295 // Find the proper version to use
1296 pkgCache::PkgIterator P = G.FindPreferredPkg();
1297 if (P.end() == true)
1298 continue;
1299 pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
1300 if (V.end() == false)
1301 {
1302 pkgCache::DescIterator const D = V.TranslatedDescription();
1303 //FIXME: packages without a description can't be found
1304 if (D.end() == true)
1305 continue;
1306 DFList[G->ID].Df = D.FileList();
1307 DFList[G->ID].V = V;
1308 DFList[G->ID].ID = G->ID;
1309 }
1310
1311 if (unmatched == NumPatterns)
1312 continue;
1313
1314 // Include all the packages that provide matching names too
1315 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; ++Prv)
1316 {
1317 pkgCache::VerIterator V = Plcy->GetCandidateVer(Prv.OwnerPkg());
1318 if (V.end() == true)
1319 continue;
1320
1321 unsigned long id = Prv.OwnerPkg().Group()->ID;
1322 pkgCache::DescIterator const D = V.TranslatedDescription();
1323 //FIXME: packages without a description can't be found
1324 if (D.end() == true)
1325 continue;
1326 DFList[id].Df = D.FileList();
1327 DFList[id].V = V;
1328 DFList[id].ID = id;
1329
1330 size_t const PrvPatternOffset = id * NumPatterns;
1331 for (unsigned I = 0; I < NumPatterns; ++I)
1332 PatternMatch[PrvPatternOffset + I] |= PatternMatch[PatternOffset + I];
1333 }
1334 }
1335
1336 LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
1337
1338 // Create the text record parser
1339 pkgRecords Recs(*Cache);
1340 // Iterate over all the version records and check them
1341 for (ExDescFile *J = DFList; J->Df != 0; ++J)
1342 {
1343 pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
1344 size_t const PatternOffset = J->ID * NumPatterns;
1345
1346 if (NamesOnly == false)
1347 {
1348 string const LongDesc = P.LongDesc();
1349 for (unsigned I = 0; I < NumPatterns; ++I)
1350 {
1351 if (PatternMatch[PatternOffset + I] == true)
1352 continue;
1353 else if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
1354 PatternMatch[PatternOffset + I] = true;
1355 }
1356 }
1357
1358 bool matchedAll = true;
1359 for (unsigned I = 0; I < NumPatterns; ++I)
1360 if (PatternMatch[PatternOffset + I] == false)
1361 {
1362 matchedAll = false;
1363 break;
1364 }
1365
1366 if (matchedAll == true)
1367 {
1368 if (ShowFull == true)
1369 DisplayRecordV1(CacheFile, J->V, std::cout);
1370 else
1371 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1372 }
1373 }
1374
1375 delete [] DFList;
1376 delete [] PatternMatch;
1377 for (unsigned I = 0; I != NumPatterns; I++)
1378 regfree(&Patterns[I]);
1379 delete [] Patterns;
1380 if (ferror(stdout))
1381 return _error->Error("Write to stdout failed");
1382 return true;
1383 }
1384 /*}}}*/
1385 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1386 static bool ShowAuto(CommandLine &)
1387 {
1388 pkgCacheFile CacheFile;
1389 pkgCache *Cache = CacheFile.GetPkgCache();
1390 pkgDepCache *DepCache = CacheFile.GetDepCache();
1391 if (unlikely(Cache == NULL || DepCache == NULL))
1392 return false;
1393
1394 std::vector<string> packages;
1395 packages.reserve(Cache->HeaderP->PackageCount / 3);
1396
1397 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
1398 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
1399 packages.push_back(P.Name());
1400
1401 std::sort(packages.begin(), packages.end());
1402
1403 for (vector<string>::iterator I = packages.begin(); I != packages.end(); ++I)
1404 cout << *I << "\n";
1405
1406 _error->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1407 return true;
1408 }
1409 /*}}}*/
1410 // ShowPkgNames - Show package names /*{{{*/
1411 // ---------------------------------------------------------------------
1412 /* This does a prefix match on the first argument */
1413 static bool ShowPkgNames(CommandLine &CmdL)
1414 {
1415 pkgCacheFile CacheFile;
1416 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1417 return false;
1418 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
1419 bool const All = _config->FindB("APT::Cache::AllNames","false");
1420
1421 if (CmdL.FileList[1] != 0)
1422 {
1423 for (;I.end() != true; ++I)
1424 {
1425 if (All == false && I->FirstPackage == 0)
1426 continue;
1427 if (I.FindPkg("any")->VersionList == 0)
1428 continue;
1429 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1430 cout << I.Name() << endl;
1431 }
1432
1433 return true;
1434 }
1435
1436 // Show all pkgs
1437 for (;I.end() != true; ++I)
1438 {
1439 if (All == false && I->FirstPackage == 0)
1440 continue;
1441 if (I.FindPkg("any")->VersionList == 0)
1442 continue;
1443 cout << I.Name() << endl;
1444 }
1445
1446 return true;
1447 }
1448 /*}}}*/
1449 // ShowSrcPackage - Show source package records /*{{{*/
1450 // ---------------------------------------------------------------------
1451 /* */
1452 static bool ShowSrcPackage(CommandLine &CmdL)
1453 {
1454 pkgCacheFile CacheFile;
1455 pkgSourceList *List = CacheFile.GetSourceList();
1456 if (unlikely(List == NULL))
1457 return false;
1458
1459 // Create the text record parsers
1460 pkgSrcRecords SrcRecs(*List);
1461 if (_error->PendingError() == true)
1462 return false;
1463
1464 unsigned found = 0;
1465 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1466 {
1467 SrcRecs.Restart();
1468
1469 pkgSrcRecords::Parser *Parse;
1470 unsigned found_this = 0;
1471 while ((Parse = SrcRecs.Find(*I,false)) != 0) {
1472 // SrcRecs.Find() will find both binary and source names
1473 if (_config->FindB("APT::Cache::Only-Source", false) == true)
1474 if (Parse->Package() != *I)
1475 continue;
1476 cout << Parse->AsStr() << endl;;
1477 found++;
1478 found_this++;
1479 }
1480 if (found_this == 0) {
1481 _error->Warning(_("Unable to locate package %s"),*I);
1482 continue;
1483 }
1484 }
1485 if (found == 0)
1486 _error->Notice(_("No packages found"));
1487 return true;
1488 }
1489 /*}}}*/
1490 // Policy - Show the results of the preferences file /*{{{*/
1491 // ---------------------------------------------------------------------
1492 /* */
1493 static bool Policy(CommandLine &CmdL)
1494 {
1495 pkgCacheFile CacheFile;
1496 pkgCache *Cache = CacheFile.GetPkgCache();
1497 pkgPolicy *Plcy = CacheFile.GetPolicy();
1498 pkgSourceList *SrcList = CacheFile.GetSourceList();
1499 if (unlikely(Cache == NULL || Plcy == NULL || SrcList == NULL))
1500 return false;
1501
1502 /* Should the MultiArchKiller be run to see which pseudo packages for an
1503 arch all package are currently installed? Activating it gives a speed
1504 penality for no real gain beside enhanced debugging, so in general no. */
1505 if (_config->FindB("APT::Cache::Policy::DepCache", false) == true)
1506 CacheFile.GetDepCache();
1507
1508 // Print out all of the package files
1509 if (CmdL.FileList[1] == 0)
1510 {
1511 cout << _("Package files:") << endl;
1512 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
1513 {
1514 if (F.Flagged(pkgCache::Flag::NoPackages))
1515 continue;
1516 // Locate the associated index files so we can derive a description
1517 pkgIndexFile *Indx;
1518 if (SrcList->FindIndex(F,Indx) == false &&
1519 _system->FindIndex(F,Indx) == false)
1520 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1521
1522 printf("%4i %s\n",
1523 Plcy->GetPriority(F),Indx->Describe(true).c_str());
1524
1525 // Print the reference information for the package
1526 string Str = F.RelStr();
1527 if (Str.empty() == false)
1528 printf(" release %s\n",F.RelStr().c_str());
1529 if (F.Site() != 0 && F.Site()[0] != 0)
1530 printf(" origin %s\n",F.Site());
1531 }
1532
1533 // Show any packages have explicit pins
1534 cout << _("Pinned packages:") << endl;
1535 pkgCache::PkgIterator I = Cache->PkgBegin();
1536 for (;I.end() != true; ++I)
1537 {
1538 // Old code for debugging
1539 if (_config->FindI("APT::Policy", 1) < 1) {
1540 if (Plcy->GetPriority(I) == 0)
1541 continue;
1542
1543 // Print the package name and the version we are forcing to
1544 cout << " " << I.FullName(true) << " -> ";
1545
1546 pkgCache::VerIterator V = Plcy->GetMatch(I);
1547 if (V.end() == true)
1548 cout << _("(not found)") << endl;
1549 else
1550 cout << V.VerStr() << endl;
1551
1552 continue;
1553 }
1554 // New code
1555 for (pkgCache::VerIterator V = I.VersionList(); !V.end(); V++) {
1556 auto Prio = Plcy->GetPriority(V, false);
1557 if (Prio == 0)
1558 continue;
1559
1560 cout << " ";
1561 // Print the package name and the version we are forcing to
1562 ioprintf(cout, _("%s -> %s with priority %d\n"), I.FullName(true).c_str(), V.VerStr(), Prio);
1563 }
1564 }
1565 return true;
1566 }
1567
1568 char const * const msgInstalled = _(" Installed: ");
1569 char const * const msgCandidate = _(" Candidate: ");
1570 short const InstalledLessCandidate =
1571 mbstowcs(NULL, msgInstalled, 0) - mbstowcs(NULL, msgCandidate, 0);
1572 short const deepInstalled =
1573 (InstalledLessCandidate < 0 ? (InstalledLessCandidate*-1) : 0) - 1;
1574 short const deepCandidate =
1575 (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
1576
1577 // Print out detailed information for each package
1578 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1579 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1580 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
1581 {
1582 cout << Pkg.FullName(true) << ":" << endl;
1583
1584 // Installed version
1585 cout << msgInstalled << OutputInDepth(deepInstalled, " ");
1586 if (Pkg->CurrentVer == 0)
1587 cout << _("(none)") << endl;
1588 else
1589 cout << Pkg.CurrentVer().VerStr() << endl;
1590
1591 // Candidate Version
1592 cout << msgCandidate << OutputInDepth(deepCandidate, " ");
1593 pkgCache::VerIterator V = Plcy->GetCandidateVer(Pkg);
1594 if (V.end() == true)
1595 cout << _("(none)") << endl;
1596 else
1597 cout << V.VerStr() << endl;
1598
1599 // Pinned version
1600 if (_config->FindI("APT::Policy", 1) < 1 && Plcy->GetPriority(Pkg) != 0)
1601 {
1602 cout << _(" Package pin: ");
1603 V = Plcy->GetMatch(Pkg);
1604 if (V.end() == true)
1605 cout << _("(not found)") << endl;
1606 else
1607 cout << V.VerStr() << endl;
1608 }
1609
1610 // Show the priority tables
1611 cout << _(" Version table:") << endl;
1612 for (V = Pkg.VersionList(); V.end() == false; ++V)
1613 {
1614 if (Pkg.CurrentVer() == V)
1615 cout << " *** " << V.VerStr();
1616 else
1617 cout << " " << V.VerStr();
1618 if (_config->FindI("APT::Policy", 1) < 1)
1619 cout << " " << Plcy->GetPriority(Pkg) << endl;
1620 else
1621 cout << " " << Plcy->GetPriority(V) << endl;
1622 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
1623 {
1624 // Locate the associated index files so we can derive a description
1625 pkgIndexFile *Indx;
1626 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1627 _system->FindIndex(VF.File(),Indx) == false)
1628 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1629 printf(" %4i %s\n",Plcy->GetPriority(VF.File()),
1630 Indx->Describe(true).c_str());
1631 }
1632 }
1633 }
1634
1635 return true;
1636 }
1637 /*}}}*/
1638 // Madison - Look a bit like katie's madison /*{{{*/
1639 // ---------------------------------------------------------------------
1640 /* */
1641 static bool Madison(CommandLine &CmdL)
1642 {
1643 pkgCacheFile CacheFile;
1644 pkgSourceList *SrcList = CacheFile.GetSourceList();
1645
1646 if (SrcList == 0)
1647 return false;
1648
1649 // Create the src text record parsers and ignore errors about missing
1650 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1651 pkgSrcRecords SrcRecs(*SrcList);
1652 if (_error->PendingError() == true)
1653 _error->Discard();
1654
1655 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1656 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1657 {
1658 _error->PushToStack();
1659 APT::PackageList pkgset = APT::PackageList::FromString(CacheFile, *I, helper);
1660 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
1661 {
1662 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; ++V)
1663 {
1664 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
1665 {
1666 // This might be nice, but wouldn't uniquely identify the source -mdz
1667 // if (VF.File().Archive() != 0)
1668 // {
1669 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1670 // << VF.File().Archive() << endl;
1671 // }
1672
1673 // Locate the associated index files so we can derive a description
1674 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S)
1675 {
1676 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1677 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
1678 IF != Indexes->end(); ++IF)
1679 {
1680 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1681 {
1682 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
1683 << (*IF)->Describe(true) << endl;
1684 }
1685 }
1686 }
1687 }
1688 }
1689 }
1690
1691 SrcRecs.Restart();
1692 pkgSrcRecords::Parser *SrcParser;
1693 bool foundSomething = false;
1694 while ((SrcParser = SrcRecs.Find(*I, false)) != 0)
1695 {
1696 foundSomething = true;
1697 // Maybe support Release info here too eventually
1698 cout << setw(10) << SrcParser->Package() << " | "
1699 << setw(10) << SrcParser->Version() << " | "
1700 << SrcParser->Index().Describe(true) << endl;
1701 }
1702 if (foundSomething == true)
1703 _error->RevertToStack();
1704 else
1705 _error->MergeWithStack();
1706 }
1707
1708 return true;
1709 }
1710 /*}}}*/
1711 // GenCaches - Call the main cache generator /*{{{*/
1712 // ---------------------------------------------------------------------
1713 /* */
1714 static bool GenCaches(CommandLine &)
1715 {
1716 OpTextProgress Progress(*_config);
1717
1718 pkgCacheFile CacheFile;
1719 return CacheFile.BuildCaches(&Progress, true);
1720 }
1721 /*}}}*/
1722 // ShowHelp - Show a help screen /*{{{*/
1723 // ---------------------------------------------------------------------
1724 /* */
1725 static bool ShowHelp(CommandLine &)
1726 {
1727 ioprintf(cout, "%s %s (%s)\n", PACKAGE, PACKAGE_VERSION, COMMON_ARCH);
1728
1729 if (_config->FindB("version") == true)
1730 return true;
1731
1732 cout <<
1733 _("Usage: apt-cache [options] command\n"
1734 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1735 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1736 "\n"
1737 "apt-cache is a low-level tool used to query information\n"
1738 "from APT's binary cache files\n"
1739 "\n"
1740 "Commands:\n"
1741 " gencaches - Build both the package and source cache\n"
1742 " showpkg - Show some general information for a single package\n"
1743 " showsrc - Show source records\n"
1744 " stats - Show some basic statistics\n"
1745 " dump - Show the entire file in a terse form\n"
1746 " dumpavail - Print an available file to stdout\n"
1747 " unmet - Show unmet dependencies\n"
1748 " search - Search the package list for a regex pattern\n"
1749 " show - Show a readable record for the package\n"
1750 " depends - Show raw dependency information for a package\n"
1751 " rdepends - Show reverse dependency information for a package\n"
1752 " pkgnames - List the names of all packages in the system\n"
1753 " dotty - Generate package graphs for GraphViz\n"
1754 " xvcg - Generate package graphs for xvcg\n"
1755 " policy - Show policy settings\n"
1756 "\n"
1757 "Options:\n"
1758 " -h This help text.\n"
1759 " -p=? The package cache.\n"
1760 " -s=? The source cache.\n"
1761 " -q Disable progress indicator.\n"
1762 " -i Show only important deps for the unmet command.\n"
1763 " -c=? Read this configuration file\n"
1764 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1765 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1766 return true;
1767 }
1768 /*}}}*/
1769 int main(int argc,const char *argv[]) /*{{{*/
1770 {
1771 CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
1772 {"gencaches",&GenCaches},
1773 {"showsrc",&ShowSrcPackage},
1774 {"showpkg",&DumpPackage},
1775 {"stats",&Stats},
1776 {"dump",&Dump},
1777 {"dumpavail",&DumpAvail},
1778 {"unmet",&UnMet},
1779 {"search",&Search},
1780 {"depends",&Depends},
1781 {"rdepends",&RDepends},
1782 {"dotty",&Dotty},
1783 {"xvcg",&XVcg},
1784 {"show",&ShowPackage},
1785 {"pkgnames",&ShowPkgNames},
1786 {"showauto",&ShowAuto},
1787 {"policy",&Policy},
1788 {"madison",&Madison},
1789 {0,0}};
1790
1791 std::vector<CommandLine::Args> Args = getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds, argc, argv));
1792
1793 // Set up gettext support
1794 setlocale(LC_ALL,"");
1795 textdomain(PACKAGE);
1796
1797 // Parse the command line and initialize the package library
1798 CommandLine CmdL;
1799 ParseCommandLine(CmdL, Cmds, Args.data(), &_config, &_system, argc, argv, ShowHelp);
1800
1801 InitOutput();
1802
1803 if (_config->Exists("APT::Cache::Generate") == true)
1804 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1805
1806 // Match the operation
1807 CmdL.DispatchArg(Cmds);
1808
1809 // Print any errors or warnings found during parsing
1810 bool const Errors = _error->PendingError();
1811 if (_config->FindI("quiet",0) > 0)
1812 _error->DumpErrors();
1813 else
1814 _error->DumpErrors(GlobalError::DEBUG);
1815 return Errors == true ? 100 : 0;
1816 }
1817 /*}}}*/