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