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