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