]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
doc: VerifyFile checks all hashes instead of best only
[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-depends.h>
47 #include <apt-private/private-show.h>
48 #include <apt-private/private-search.h>
49 #include <apt-private/private-main.h>
50
51 #include <regex.h>
52 #include <stddef.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <unistd.h>
56 #include <algorithm>
57 #include <cstring>
58 #include <iomanip>
59 #include <iostream>
60 #include <list>
61 #include <map>
62 #include <set>
63 #include <string>
64 #include <vector>
65
66 #include <apti18n.h>
67 /*}}}*/
68
69 using namespace std;
70
71 // UnMet - Show unmet dependencies /*{{{*/
72 // ---------------------------------------------------------------------
73 /* */
74 static bool ShowUnMet(pkgCache::VerIterator const &V, bool const Important)
75 {
76 bool Header = false;
77 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
78 {
79 // Collect or groups
80 pkgCache::DepIterator Start;
81 pkgCache::DepIterator End;
82 D.GlobOr(Start,End);
83
84 // Important deps only
85 if (Important == true)
86 if (End->Type != pkgCache::Dep::PreDepends &&
87 End->Type != pkgCache::Dep::Depends)
88 continue;
89
90 // Skip conflicts and replaces
91 if (End.IsNegative() == true || End->Type == pkgCache::Dep::Replaces)
92 continue;
93
94 // Verify the or group
95 bool OK = false;
96 pkgCache::DepIterator RealStart = Start;
97 do
98 {
99 // See if this dep is Ok
100 pkgCache::Version **VList = Start.AllTargets();
101 if (*VList != 0)
102 {
103 OK = true;
104 delete [] VList;
105 break;
106 }
107 delete [] VList;
108
109 if (Start == End)
110 break;
111 ++Start;
112 }
113 while (1);
114
115 // The group is OK
116 if (OK == true)
117 continue;
118
119 // Oops, it failed..
120 if (Header == false)
121 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
122 V.ParentPkg().FullName(true).c_str(),V.VerStr());
123 Header = true;
124
125 // Print out the dep type
126 cout << " " << End.DepType() << ": ";
127
128 // Show the group
129 Start = RealStart;
130 do
131 {
132 cout << Start.TargetPkg().FullName(true);
133 if (Start.TargetVer() != 0)
134 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
135 ")";
136 if (Start == End)
137 break;
138 cout << " | ";
139 ++Start;
140 }
141 while (1);
142
143 cout << endl;
144 }
145 return true;
146 }
147 static bool UnMet(CommandLine &CmdL)
148 {
149 bool const Important = _config->FindB("APT::Cache::Important",false);
150
151 pkgCacheFile CacheFile;
152 if (unlikely(CacheFile.GetPkgCache() == NULL))
153 return false;
154
155 if (CmdL.FileSize() <= 1)
156 {
157 for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; ++P)
158 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
159 if (ShowUnMet(V, Important) == false)
160 return false;
161 }
162 else
163 {
164 CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
165 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1,
166 APT::CacheSetHelper::CANDIDATE, helper);
167 for (APT::VersionList::iterator V = verset.begin(); V != verset.end(); ++V)
168 if (ShowUnMet(V, Important) == false)
169 return false;
170 }
171 return true;
172 }
173 /*}}}*/
174 // DumpPackage - Show a dump of a package record /*{{{*/
175 // ---------------------------------------------------------------------
176 /* */
177 static bool DumpPackage(CommandLine &CmdL)
178 {
179 pkgCacheFile CacheFile;
180 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
181 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
182
183 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
184 {
185 cout << "Package: " << Pkg.FullName(true) << endl;
186 cout << "Versions: " << endl;
187 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
188 {
189 cout << Cur.VerStr();
190 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; ++Vf)
191 cout << " (" << Vf.File().FileName() << ")";
192 cout << endl;
193 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; ++D)
194 {
195 cout << " Description Language: " << D.LanguageCode() << endl
196 << " File: " << D.FileList().File().FileName() << endl
197 << " MD5: " << D.md5() << endl;
198 }
199 cout << endl;
200 }
201
202 cout << endl;
203
204 cout << "Reverse Depends: " << endl;
205 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D)
206 {
207 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
208 if (D->Version != 0)
209 cout << ' ' << DeNull(D.TargetVer()) << endl;
210 else
211 cout << endl;
212 }
213
214 cout << "Dependencies: " << endl;
215 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
216 {
217 cout << Cur.VerStr() << " - ";
218 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; ++Dep)
219 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
220 cout << endl;
221 }
222
223 cout << "Provides: " << endl;
224 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
225 {
226 cout << Cur.VerStr() << " - ";
227 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; ++Prv)
228 cout << Prv.ParentPkg().FullName(true) << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ") ";
229 cout << endl;
230 }
231 cout << "Reverse Provides: " << endl;
232 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; ++Prv)
233 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ")"<< endl;
234 }
235
236 return true;
237 }
238 /*}}}*/
239 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
240 // ---------------------------------------------------------------------
241 /* */
242 static map_pointer_t PackageNext(pkgCache::Package const * const P) { return P->NextPackage; }
243 static map_pointer_t GroupNext(pkgCache::Group const * const G) { return G->Next; }
244 template<class T>
245 static void ShowHashTableStats(std::string Type,
246 T *StartP,
247 map_pointer_t *Hashtable,
248 unsigned long Size,
249 map_pointer_t(*Next)(T const * const))
250 {
251 // hashtable stats for the HashTable
252 unsigned long NumBuckets = Size;
253 unsigned long UsedBuckets = 0;
254 unsigned long UnusedBuckets = 0;
255 unsigned long LongestBucket = 0;
256 unsigned long ShortestBucket = NumBuckets;
257 unsigned long Entries = 0;
258 for (unsigned int i=0; i < NumBuckets; ++i)
259 {
260 T *P = StartP + Hashtable[i];
261 if(P == 0 || P == StartP)
262 {
263 ++UnusedBuckets;
264 continue;
265 }
266 ++UsedBuckets;
267 unsigned long ThisBucketSize = 0;
268 for (; P != StartP; P = StartP + Next(P))
269 ++ThisBucketSize;
270 Entries += ThisBucketSize;
271 LongestBucket = std::max(ThisBucketSize, LongestBucket);
272 ShortestBucket = std::min(ThisBucketSize, ShortestBucket);
273 }
274 cout << "Total buckets in " << Type << ": " << NumBuckets << std::endl;
275 cout << " Unused: " << UnusedBuckets << std::endl;
276 cout << " Used: " << UsedBuckets << std::endl;
277 cout << " Average entries: " << Entries/(double)NumBuckets << std::endl;
278 cout << " Longest: " << LongestBucket << std::endl;
279 cout << " Shortest: " << ShortestBucket << std::endl;
280 }
281 /*}}}*/
282 // Stats - Dump some nice statistics /*{{{*/
283 // ---------------------------------------------------------------------
284 /* */
285 static bool Stats(CommandLine &CmdL)
286 {
287 if (CmdL.FileSize() > 1) {
288 _error->Error(_("apt-cache stats does not take any arguments"));
289 return false;
290 }
291
292 pkgCacheFile CacheFile;
293 pkgCache *Cache = CacheFile.GetPkgCache();
294
295 if (unlikely(Cache == NULL))
296 return false;
297
298 cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
299 SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
300 << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
301 SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
302
303 int Normal = 0;
304 int Virtual = 0;
305 int NVirt = 0;
306 int DVirt = 0;
307 int Missing = 0;
308 pkgCache::PkgIterator I = Cache->PkgBegin();
309 for (;I.end() != true; ++I)
310 {
311 if (I->VersionList != 0 && I->ProvidesList == 0)
312 {
313 Normal++;
314 continue;
315 }
316
317 if (I->VersionList != 0 && I->ProvidesList != 0)
318 {
319 NVirt++;
320 continue;
321 }
322
323 if (I->VersionList == 0 && I->ProvidesList != 0)
324 {
325 // Only 1 provides
326 if (I.ProvidesList()->NextProvides == 0)
327 {
328 DVirt++;
329 }
330 else
331 Virtual++;
332 continue;
333 }
334 if (I->VersionList == 0 && I->ProvidesList == 0)
335 {
336 Missing++;
337 continue;
338 }
339 }
340 cout << _(" Normal packages: ") << Normal << endl;
341 cout << _(" Pure virtual packages: ") << Virtual << endl;
342 cout << _(" Single virtual packages: ") << DVirt << endl;
343 cout << _(" Mixed virtual packages: ") << NVirt << endl;
344 cout << _(" Missing: ") << Missing << endl;
345
346 cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
347 SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
348 cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
349 SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
350 cout << _("Total dependencies: ") << Cache->Head().DependsCount << "/" << Cache->Head().DependsDataCount << " (" <<
351 SizeToStr((Cache->Head().DependsCount*Cache->Head().DependencySz) +
352 (Cache->Head().DependsDataCount*Cache->Head().DependencyDataSz)) << ')' << endl;
353 cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
354 SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
355 cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
356 SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
357 cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
358 SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
359
360 // String list stats
361 std::set<map_stringitem_t> stritems;
362 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
363 stritems.insert(G->Name);
364 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
365 {
366 stritems.insert(P->Arch);
367 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
368 {
369 if (V->VerStr != 0)
370 stritems.insert(V->VerStr);
371 if (V->Section != 0)
372 stritems.insert(V->Section);
373 stritems.insert(V->SourcePkgName);
374 stritems.insert(V->SourceVerStr);
375 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
376 {
377 if (D->Version != 0)
378 stritems.insert(D->Version);
379 }
380 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
381 {
382 stritems.insert(D->md5sum);
383 stritems.insert(D->language_code);
384 }
385 }
386 for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
387 {
388 if (Prv->ProvideVersion != 0)
389 stritems.insert(Prv->ProvideVersion);
390 }
391 }
392 for (pkgCache::RlsFileIterator F = Cache->RlsFileBegin(); F != Cache->RlsFileEnd(); ++F)
393 {
394 stritems.insert(F->FileName);
395 stritems.insert(F->Archive);
396 stritems.insert(F->Codename);
397 stritems.insert(F->Version);
398 stritems.insert(F->Origin);
399 stritems.insert(F->Label);
400 stritems.insert(F->Site);
401 }
402 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
403 {
404 stritems.insert(F->FileName);
405 stritems.insert(F->Architecture);
406 stritems.insert(F->Component);
407 stritems.insert(F->IndexType);
408 }
409
410 unsigned long Size = 0;
411 for (std::set<map_stringitem_t>::const_iterator i = stritems.begin(); i != stritems.end(); ++i)
412 Size += strlen(Cache->StrP + *i) + 1;
413 cout << _("Total globbed strings: ") << stritems.size() << " (" << SizeToStr(Size) << ')' << endl;
414 stritems.clear();
415
416 unsigned long Slack = 0;
417 for (int I = 0; I != 7; I++)
418 Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
419 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
420
421 unsigned long Total = 0;
422 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
423 Total = Slack + Size +
424 APT_CACHESIZE(GroupCount, GroupSz) +
425 APT_CACHESIZE(PackageCount, PackageSz) +
426 APT_CACHESIZE(VersionCount, VersionSz) +
427 APT_CACHESIZE(DescriptionCount, DescriptionSz) +
428 APT_CACHESIZE(DependsCount, DependencySz) +
429 APT_CACHESIZE(DependsDataCount, DependencyDataSz) +
430 APT_CACHESIZE(ReleaseFileCount, ReleaseFileSz) +
431 APT_CACHESIZE(PackageFileCount, PackageFileSz) +
432 APT_CACHESIZE(VerFileCount, VerFileSz) +
433 APT_CACHESIZE(DescFileCount, DescFileSz) +
434 APT_CACHESIZE(ProvidesCount, ProvidesSz) +
435 (2 * Cache->Head().GetHashTableSize() * sizeof(map_id_t));
436 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
437 #undef APT_CACHESIZE
438
439 // hashtable stats
440 ShowHashTableStats<pkgCache::Package>("PkgHashTable", Cache->PkgP, Cache->Head().PkgHashTableP(), Cache->Head().GetHashTableSize(), PackageNext);
441 ShowHashTableStats<pkgCache::Group>("GrpHashTable", Cache->GrpP, Cache->Head().GrpHashTableP(), Cache->Head().GetHashTableSize(), GroupNext);
442
443 return true;
444 }
445 /*}}}*/
446 // Dump - show everything /*{{{*/
447 // ---------------------------------------------------------------------
448 /* This is worthless except fer debugging things */
449 static bool Dump(CommandLine &)
450 {
451 pkgCacheFile CacheFile;
452 pkgCache *Cache = CacheFile.GetPkgCache();
453 if (unlikely(Cache == NULL))
454 return false;
455
456 std::cout << "Using Versioning System: " << Cache->VS->Label << std::endl;
457
458 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
459 {
460 std::cout << "Package: " << P.FullName(true) << std::endl;
461 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
462 {
463 std::cout << " Version: " << V.VerStr() << std::endl;
464 std::cout << " File: " << V.FileList().File().FileName() << std::endl;
465 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
466 std::cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
467 DeNull(D.TargetVer()) << std::endl;
468 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
469 {
470 std::cout << " Description Language: " << D.LanguageCode() << std::endl
471 << " File: " << D.FileList().File().FileName() << std::endl
472 << " MD5: " << D.md5() << std::endl;
473 }
474 }
475 }
476
477 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
478 {
479 std::cout << "File: " << F.FileName() << std::endl;
480 std::cout << " Type: " << F.IndexType() << std::endl;
481 std::cout << " Size: " << F->Size << std::endl;
482 std::cout << " ID: " << F->ID << std::endl;
483 std::cout << " Flags: " << F->Flags << std::endl;
484 std::cout << " Time: " << TimeRFC1123(F->mtime) << std::endl;
485 std::cout << " Archive: " << DeNull(F.Archive()) << std::endl;
486 std::cout << " Component: " << DeNull(F.Component()) << std::endl;
487 std::cout << " Version: " << DeNull(F.Version()) << std::endl;
488 std::cout << " Origin: " << DeNull(F.Origin()) << std::endl;
489 std::cout << " Site: " << DeNull(F.Site()) << std::endl;
490 std::cout << " Label: " << DeNull(F.Label()) << std::endl;
491 std::cout << " Architecture: " << DeNull(F.Architecture()) << std::endl;
492 }
493
494 return true;
495 }
496 /*}}}*/
497 // DumpAvail - Print out the available list /*{{{*/
498 // ---------------------------------------------------------------------
499 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
500 make this run really fast, perhaps I went a little overboard.. */
501 static bool DumpAvail(CommandLine &)
502 {
503 pkgCacheFile CacheFile;
504 pkgCache *Cache = CacheFile.GetPkgCache();
505 if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
506 return false;
507
508 unsigned long Count = Cache->HeaderP->PackageCount+1;
509 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
510 memset(VFList,0,sizeof(*VFList)*Count);
511
512 // Map versions that we want to write out onto the VerList array.
513 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
514 {
515 if (P->VersionList == 0)
516 continue;
517
518 /* Find the proper version to use. If the policy says there are no
519 possible selections we return the installed version, if available..
520 This prevents dselect from making it obsolete. */
521 pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
522 if (V.end() == true)
523 {
524 if (P->CurrentVer == 0)
525 continue;
526 V = P.CurrentVer();
527 }
528
529 pkgCache::VerFileIterator VF = V.FileList();
530 for (; VF.end() == false ; ++VF)
531 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
532 break;
533
534 /* Okay, here we have a bit of a problem.. The policy has selected the
535 currently installed package - however it only exists in the
536 status file.. We need to write out something or dselect will mark
537 the package as obsolete! Thus we emit the status file entry, but
538 below we remove the status line to make it valid for the
539 available file. However! We only do this if their do exist *any*
540 non-source versions of the package - that way the dselect obsolete
541 handling works OK. */
542 if (VF.end() == true)
543 {
544 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; ++Cur)
545 {
546 for (VF = Cur.FileList(); VF.end() == false; ++VF)
547 {
548 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
549 {
550 VF = V.FileList();
551 break;
552 }
553 }
554
555 if (VF.end() == false)
556 break;
557 }
558 }
559
560 VFList[P->ID] = VF;
561 }
562
563 LocalitySort(VFList,Count,sizeof(*VFList));
564
565 std::vector<pkgTagSection::Tag> RW;
566 RW.push_back(pkgTagSection::Tag::Remove("Status"));
567 RW.push_back(pkgTagSection::Tag::Remove("Config-Version"));
568 FileFd stdoutfd;
569 stdoutfd.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false);
570
571 // Iterate over all the package files and write them out.
572 char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
573 for (pkgCache::VerFile **J = VFList; *J != 0;)
574 {
575 pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
576 if (File.IsOk() == false)
577 {
578 _error->Error(_("Package file %s is out of sync."),File.FileName());
579 break;
580 }
581
582 FileFd PkgF(File.FileName(),FileFd::ReadOnly, FileFd::Extension);
583 if (_error->PendingError() == true)
584 break;
585
586 /* Write all of the records from this package file, since we
587 already did locality sorting we can now just seek through the
588 file in read order. We apply 1 more optimization here, since often
589 there will be < 1 byte gaps between records (for the \n) we read that
590 into the next buffer and offset a bit.. */
591 unsigned long Pos = 0;
592 for (; *J != 0; J++)
593 {
594 if ((*J)->File + Cache->PkgFileP != File)
595 break;
596
597 const pkgCache::VerFile &VF = **J;
598
599 // Read the record and then write it out again.
600 unsigned long Jitter = VF.Offset - Pos;
601 if (Jitter > 8)
602 {
603 if (PkgF.Seek(VF.Offset) == false)
604 break;
605 Jitter = 0;
606 }
607
608 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
609 break;
610 Buffer[VF.Size + Jitter] = '\n';
611
612 // See above..
613 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
614 {
615 pkgTagSection Tags;
616 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
617 Tags.Write(stdoutfd, NULL, RW) == false ||
618 stdoutfd.Write("\n", 1) == false)
619 {
620 _error->Error("Internal Error, Unable to parse a package record");
621 break;
622 }
623 }
624 else
625 {
626 if (stdoutfd.Write(Buffer + Jitter, VF.Size + 1) == false)
627 break;
628 }
629
630 Pos = VF.Offset + VF.Size;
631 }
632
633 if (_error->PendingError() == true)
634 break;
635 }
636
637 delete [] Buffer;
638 delete [] VFList;
639 return !_error->PendingError();
640 }
641 /*}}}*/
642 // xvcg - Generate a graph for xvcg /*{{{*/
643 // ---------------------------------------------------------------------
644 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
645
646 static bool XVcg(CommandLine &CmdL)
647 {
648 pkgCacheFile CacheFile;
649 pkgCache *Cache = CacheFile.GetPkgCache();
650 if (unlikely(Cache == NULL))
651 return false;
652
653 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
654
655 /* Normal packages are boxes
656 Pure Provides are triangles
657 Mixed are diamonds
658 rhomb are missing packages*/
659 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
660
661 /* Initialize the list of packages to show.
662 1 = To Show
663 2 = To Show no recurse
664 3 = Emitted no recurse
665 4 = Emitted
666 0 = None */
667 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
668 enum TheFlags {ForceNR=(1<<0)};
669 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
670 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
671 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
672
673 // Show everything if no arguments given
674 if (CmdL.FileList[1] == 0)
675 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
676 Show[I] = ToShow;
677 else
678 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
679 Show[I] = None;
680 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
681
682 // Map the shapes
683 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
684 {
685 if (Pkg->VersionList == 0)
686 {
687 // Missing
688 if (Pkg->ProvidesList == 0)
689 ShapeMap[Pkg->ID] = 0;
690 else
691 ShapeMap[Pkg->ID] = 1;
692 }
693 else
694 {
695 // Normal
696 if (Pkg->ProvidesList == 0)
697 ShapeMap[Pkg->ID] = 2;
698 else
699 ShapeMap[Pkg->ID] = 3;
700 }
701 }
702
703 // Load the list of packages from the command line into the show list
704 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
705 std::list<APT::CacheSetHelper::PkgModifier> mods;
706 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
707 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
708 std::map<unsigned short, APT::PackageSet> pkgsets =
709 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
710
711 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
712 Pkg != pkgsets[0].end(); ++Pkg)
713 Show[Pkg->ID] = ToShow;
714 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
715 Pkg != pkgsets[1].end(); ++Pkg)
716 {
717 Show[Pkg->ID] = ToShow;
718 Flags[Pkg->ID] |= ForceNR;
719 }
720
721 // Little header
722 cout << "graph: { title: \"packages\"" << endl <<
723 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
724 "layout_downfactor: 8" << endl;
725
726 bool Act = true;
727 while (Act == true)
728 {
729 Act = false;
730 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
731 {
732 // See we need to show this package
733 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
734 continue;
735
736 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
737
738 // Colour as done
739 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
740 {
741 // Pure Provides and missing packages have no deps!
742 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
743 Show[Pkg->ID] = Done;
744 else
745 Show[Pkg->ID] = DoneNR;
746 }
747 else
748 Show[Pkg->ID] = Done;
749 Act = true;
750
751 // No deps to map out
752 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
753 continue;
754
755 pkgCache::VerIterator Ver = Pkg.VersionList();
756 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
757 {
758 // See if anything can meet this dep
759 // Walk along the actual package providing versions
760 bool Hit = false;
761 pkgCache::PkgIterator DPkg = D.TargetPkg();
762 for (pkgCache::VerIterator I = DPkg.VersionList();
763 I.end() == false && Hit == false; ++I)
764 {
765 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
766 Hit = true;
767 }
768
769 // Follow all provides
770 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
771 I.end() == false && Hit == false; ++I)
772 {
773 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
774 Hit = true;
775 }
776
777
778 // Only graph critical deps
779 if (D.IsCritical() == true)
780 {
781 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
782
783 // Colour the node for recursion
784 if (Show[D.TargetPkg()->ID] <= DoneNR)
785 {
786 /* If a conflicts does not meet anything in the database
787 then show the relation but do not recurse */
788 if (Hit == false && D.IsNegative() == true)
789 {
790 if (Show[D.TargetPkg()->ID] == None &&
791 Show[D.TargetPkg()->ID] != ToShow)
792 Show[D.TargetPkg()->ID] = ToShowNR;
793 }
794 else
795 {
796 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
797 Show[D.TargetPkg()->ID] = ToShowNR;
798 else
799 Show[D.TargetPkg()->ID] = ToShow;
800 }
801 }
802
803 // Edge colour
804 switch(D->Type)
805 {
806 case pkgCache::Dep::Conflicts:
807 printf("label: \"conflicts\" color: lightgreen }\n");
808 break;
809 case pkgCache::Dep::DpkgBreaks:
810 printf("label: \"breaks\" color: lightgreen }\n");
811 break;
812 case pkgCache::Dep::Obsoletes:
813 printf("label: \"obsoletes\" color: lightgreen }\n");
814 break;
815
816 case pkgCache::Dep::PreDepends:
817 printf("label: \"predepends\" color: blue }\n");
818 break;
819
820 default:
821 printf("}\n");
822 break;
823 }
824 }
825 }
826 }
827 }
828
829 /* Draw the box colours after the fact since we can not tell what colour
830 they should be until everything is finished drawing */
831 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
832 {
833 if (Show[Pkg->ID] < DoneNR)
834 continue;
835
836 if (Show[Pkg->ID] == DoneNR)
837 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
838 Shapes[ShapeMap[Pkg->ID]]);
839 else
840 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
841 Shapes[ShapeMap[Pkg->ID]]);
842
843 }
844
845 delete[] Show;
846 delete[] Flags;
847 delete[] ShapeMap;
848
849 printf("}\n");
850 return true;
851 }
852 /*}}}*/
853 // Dotty - Generate a graph for Dotty /*{{{*/
854 // ---------------------------------------------------------------------
855 /* Dotty is the graphvis program for generating graphs. It is a fairly
856 simple queuing algorithm that just writes dependencies and nodes.
857 http://www.research.att.com/sw/tools/graphviz/ */
858 static bool Dotty(CommandLine &CmdL)
859 {
860 pkgCacheFile CacheFile;
861 pkgCache *Cache = CacheFile.GetPkgCache();
862 if (unlikely(Cache == NULL))
863 return false;
864
865 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
866
867 /* Normal packages are boxes
868 Pure Provides are triangles
869 Mixed are diamonds
870 Hexagons are missing packages*/
871 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
872
873 /* Initialize the list of packages to show.
874 1 = To Show
875 2 = To Show no recurse
876 3 = Emitted no recurse
877 4 = Emitted
878 0 = None */
879 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
880 enum TheFlags {ForceNR=(1<<0)};
881 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
882 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
883 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
884
885 // Show everything if no arguments given
886 if (CmdL.FileList[1] == 0)
887 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
888 Show[I] = ToShow;
889 else
890 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
891 Show[I] = None;
892 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
893
894 // Map the shapes
895 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
896 {
897 if (Pkg->VersionList == 0)
898 {
899 // Missing
900 if (Pkg->ProvidesList == 0)
901 ShapeMap[Pkg->ID] = 0;
902 else
903 ShapeMap[Pkg->ID] = 1;
904 }
905 else
906 {
907 // Normal
908 if (Pkg->ProvidesList == 0)
909 ShapeMap[Pkg->ID] = 2;
910 else
911 ShapeMap[Pkg->ID] = 3;
912 }
913 }
914
915 // Load the list of packages from the command line into the show list
916 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
917 std::list<APT::CacheSetHelper::PkgModifier> mods;
918 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
919 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
920 std::map<unsigned short, APT::PackageSet> pkgsets =
921 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
922
923 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
924 Pkg != pkgsets[0].end(); ++Pkg)
925 Show[Pkg->ID] = ToShow;
926 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
927 Pkg != pkgsets[1].end(); ++Pkg)
928 {
929 Show[Pkg->ID] = ToShow;
930 Flags[Pkg->ID] |= ForceNR;
931 }
932
933 // Little header
934 printf("digraph packages {\n");
935 printf("concentrate=true;\n");
936 printf("size=\"30,40\";\n");
937
938 bool Act = true;
939 while (Act == true)
940 {
941 Act = false;
942 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
943 {
944 // See we need to show this package
945 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
946 continue;
947
948 // Colour as done
949 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
950 {
951 // Pure Provides and missing packages have no deps!
952 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
953 Show[Pkg->ID] = Done;
954 else
955 Show[Pkg->ID] = DoneNR;
956 }
957 else
958 Show[Pkg->ID] = Done;
959 Act = true;
960
961 // No deps to map out
962 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
963 continue;
964
965 pkgCache::VerIterator Ver = Pkg.VersionList();
966 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
967 {
968 // See if anything can meet this dep
969 // Walk along the actual package providing versions
970 bool Hit = false;
971 pkgCache::PkgIterator DPkg = D.TargetPkg();
972 for (pkgCache::VerIterator I = DPkg.VersionList();
973 I.end() == false && Hit == false; ++I)
974 {
975 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
976 Hit = true;
977 }
978
979 // Follow all provides
980 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
981 I.end() == false && Hit == false; ++I)
982 {
983 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
984 Hit = true;
985 }
986
987 // Only graph critical deps
988 if (D.IsCritical() == true)
989 {
990 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
991
992 // Colour the node for recursion
993 if (Show[D.TargetPkg()->ID] <= DoneNR)
994 {
995 /* If a conflicts does not meet anything in the database
996 then show the relation but do not recurse */
997 if (Hit == false && D.IsNegative() == true)
998 {
999 if (Show[D.TargetPkg()->ID] == None &&
1000 Show[D.TargetPkg()->ID] != ToShow)
1001 Show[D.TargetPkg()->ID] = ToShowNR;
1002 }
1003 else
1004 {
1005 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1006 Show[D.TargetPkg()->ID] = ToShowNR;
1007 else
1008 Show[D.TargetPkg()->ID] = ToShow;
1009 }
1010 }
1011
1012 // Edge colour
1013 switch(D->Type)
1014 {
1015 case pkgCache::Dep::Conflicts:
1016 case pkgCache::Dep::Obsoletes:
1017 case pkgCache::Dep::DpkgBreaks:
1018 printf("[color=springgreen];\n");
1019 break;
1020
1021 case pkgCache::Dep::PreDepends:
1022 printf("[color=blue];\n");
1023 break;
1024
1025 default:
1026 printf(";\n");
1027 break;
1028 }
1029 }
1030 }
1031 }
1032 }
1033
1034 /* Draw the box colours after the fact since we can not tell what colour
1035 they should be until everything is finished drawing */
1036 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
1037 {
1038 if (Show[Pkg->ID] < DoneNR)
1039 continue;
1040
1041 // Orange box for early recursion stoppage
1042 if (Show[Pkg->ID] == DoneNR)
1043 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
1044 Shapes[ShapeMap[Pkg->ID]]);
1045 else
1046 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
1047 Shapes[ShapeMap[Pkg->ID]]);
1048 }
1049
1050 printf("}\n");
1051 delete[] Show;
1052 delete[] Flags;
1053 delete[] ShapeMap;
1054 return true;
1055 }
1056 /*}}}*/
1057 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1058 static bool ShowAuto(CommandLine &)
1059 {
1060 pkgCacheFile CacheFile;
1061 pkgCache *Cache = CacheFile.GetPkgCache();
1062 pkgDepCache *DepCache = CacheFile.GetDepCache();
1063 if (unlikely(Cache == NULL || DepCache == NULL))
1064 return false;
1065
1066 std::vector<string> packages;
1067 packages.reserve(Cache->HeaderP->PackageCount / 3);
1068
1069 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
1070 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
1071 packages.push_back(P.Name());
1072
1073 std::sort(packages.begin(), packages.end());
1074
1075 for (vector<string>::iterator I = packages.begin(); I != packages.end(); ++I)
1076 cout << *I << "\n";
1077
1078 _error->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1079 return true;
1080 }
1081 /*}}}*/
1082 // ShowPkgNames - Show package names /*{{{*/
1083 // ---------------------------------------------------------------------
1084 /* This does a prefix match on the first argument */
1085 static bool ShowPkgNames(CommandLine &CmdL)
1086 {
1087 pkgCacheFile CacheFile;
1088 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1089 return false;
1090 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
1091 bool const All = _config->FindB("APT::Cache::AllNames","false");
1092
1093 if (CmdL.FileList[1] != 0)
1094 {
1095 for (;I.end() != true; ++I)
1096 {
1097 if (All == false && I->FirstPackage == 0)
1098 continue;
1099 if (I.FindPkg("any")->VersionList == 0)
1100 continue;
1101 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1102 cout << I.Name() << endl;
1103 }
1104
1105 return true;
1106 }
1107
1108 // Show all pkgs
1109 for (;I.end() != true; ++I)
1110 {
1111 if (All == false && I->FirstPackage == 0)
1112 continue;
1113 if (I.FindPkg("any")->VersionList == 0)
1114 continue;
1115 cout << I.Name() << endl;
1116 }
1117
1118 return true;
1119 }
1120 /*}}}*/
1121 // Madison - Look a bit like katie's madison /*{{{*/
1122 // ---------------------------------------------------------------------
1123 /* */
1124 static bool Madison(CommandLine &CmdL)
1125 {
1126 pkgCacheFile CacheFile;
1127 pkgSourceList *SrcList = CacheFile.GetSourceList();
1128
1129 if (SrcList == 0)
1130 return false;
1131
1132 // Create the src text record parsers and ignore errors about missing
1133 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1134 pkgSrcRecords SrcRecs(*SrcList);
1135 if (_error->PendingError() == true)
1136 _error->Discard();
1137
1138 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1139 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1140 {
1141 _error->PushToStack();
1142 APT::PackageList pkgset = APT::PackageList::FromString(CacheFile, *I, helper);
1143 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
1144 {
1145 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; ++V)
1146 {
1147 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
1148 {
1149 // This might be nice, but wouldn't uniquely identify the source -mdz
1150 // if (VF.File().Archive() != 0)
1151 // {
1152 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1153 // << VF.File().Archive() << endl;
1154 // }
1155
1156 // Locate the associated index files so we can derive a description
1157 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S)
1158 {
1159 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1160 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
1161 IF != Indexes->end(); ++IF)
1162 {
1163 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1164 {
1165 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
1166 << (*IF)->Describe(true) << endl;
1167 }
1168 }
1169 }
1170 }
1171 }
1172 }
1173
1174 SrcRecs.Restart();
1175 pkgSrcRecords::Parser *SrcParser;
1176 bool foundSomething = false;
1177 while ((SrcParser = SrcRecs.Find(*I, false)) != 0)
1178 {
1179 foundSomething = true;
1180 // Maybe support Release info here too eventually
1181 cout << setw(10) << SrcParser->Package() << " | "
1182 << setw(10) << SrcParser->Version() << " | "
1183 << SrcParser->Index().Describe(true) << endl;
1184 }
1185 if (foundSomething == true)
1186 _error->RevertToStack();
1187 else
1188 _error->MergeWithStack();
1189 }
1190
1191 return true;
1192 }
1193 /*}}}*/
1194 // GenCaches - Call the main cache generator /*{{{*/
1195 // ---------------------------------------------------------------------
1196 /* */
1197 static bool GenCaches(CommandLine &)
1198 {
1199 OpTextProgress Progress(*_config);
1200
1201 pkgCacheFile CacheFile;
1202 return CacheFile.BuildCaches(&Progress, true);
1203 }
1204 /*}}}*/
1205 bool ShowHelp(CommandLine &) /*{{{*/
1206 {
1207 std::cout <<
1208 _("Usage: apt-cache [options] command\n"
1209 " apt-cache [options] show pkg1 [pkg2 ...]\n"
1210 "\n"
1211 "apt-cache queries and displays available information about installed\n"
1212 "and installable packages. It works exclusively on the data acquired\n"
1213 "into the local cache via the 'update' command of e.g. apt-get. The\n"
1214 "displayed information may therefore be outdated if the last update was\n"
1215 "too long ago, but in exchange apt-cache works independently of the\n"
1216 "availability of the configured sources (e.g. offline).\n");
1217 return true;
1218 }
1219 /*}}}*/
1220 std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
1221 {
1222 return {
1223 {"gencaches",&GenCaches, nullptr},
1224 {"showsrc",&ShowSrcPackage, _("Show source records")},
1225 {"showpkg",&DumpPackage, nullptr},
1226 {"stats",&Stats, nullptr},
1227 {"dump",&Dump, nullptr},
1228 {"dumpavail",&DumpAvail, nullptr},
1229 {"unmet",&UnMet, nullptr},
1230 {"search",&DoSearch, _("Search the package list for a regex pattern")},
1231 {"depends",&Depends, _("Show raw dependency information for a package")},
1232 {"rdepends",&RDepends, _("Show reverse dependency information for a package")},
1233 {"dotty",&Dotty, nullptr},
1234 {"xvcg",&XVcg, nullptr},
1235 {"show",&ShowPackage, _("Show a readable record for the package")},
1236 {"pkgnames",&ShowPkgNames, _("List the names of all packages in the system")},
1237 {"showauto",&ShowAuto, nullptr},
1238 {"policy",&Policy, _("Show policy settings")},
1239 {"madison",&Madison, nullptr},
1240 {nullptr, nullptr, nullptr}
1241 };
1242 }
1243 /*}}}*/
1244 int main(int argc,const char *argv[]) /*{{{*/
1245 {
1246 InitLocale();
1247
1248 // Parse the command line and initialize the package library
1249 CommandLine CmdL;
1250 auto const Cmds = ParseCommandLine(CmdL, APT_CMD::APT_CACHE, &_config, &_system, argc, argv);
1251
1252 InitOutput();
1253
1254 if (_config->Exists("APT::Cache::Generate") == true)
1255 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1256
1257 return DispatchCommandLine(CmdL, Cmds);
1258 }
1259 /*}}}*/