]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
072cf4ef7798a098802ae5c3abca7815a57122b3
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
4 /* ######################################################################
6 apt-cache - Manages the cache files
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools.
11 Returns 100 on failure, 0 on success.
13 ##################################################################### */
15 // Include Files /*{{{*/
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>
44 #include <apt-private/private-cacheset.h>
45 #include <apt-private/private-cmndline.h>
67 // LocalitySort - Sort a version list by package file locality /*{{{*/
68 // ---------------------------------------------------------------------
70 static int LocalityCompare(const void *a
, const void *b
)
72 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
73 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
82 if (A
->File
== B
->File
)
83 return A
->Offset
- B
->Offset
;
84 return A
->File
- B
->File
;
87 static void LocalitySort(pkgCache::VerFile
**begin
,
88 unsigned long Count
,size_t Size
)
90 qsort(begin
,Count
,Size
,LocalityCompare
);
93 static void LocalitySort(pkgCache::DescFile
**begin
,
94 unsigned long Count
,size_t Size
)
96 qsort(begin
,Count
,Size
,LocalityCompare
);
99 // UnMet - Show unmet dependencies /*{{{*/
100 // ---------------------------------------------------------------------
102 static bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const Important
)
105 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
108 pkgCache::DepIterator Start
;
109 pkgCache::DepIterator End
;
112 // Important deps only
113 if (Important
== true)
114 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
115 End
->Type
!= pkgCache::Dep::Depends
)
118 // Skip conflicts and replaces
119 if (End
.IsNegative() == true)
122 // Verify the or group
124 pkgCache::DepIterator RealStart
= Start
;
127 // See if this dep is Ok
128 pkgCache::Version
**VList
= Start
.AllTargets();
149 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
150 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
153 // Print out the dep type
154 cout
<< " " << End
.DepType() << ": ";
160 cout
<< Start
.TargetPkg().FullName(true);
161 if (Start
.TargetVer() != 0)
162 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
175 static bool UnMet(CommandLine
&CmdL
)
177 bool const Important
= _config
->FindB("APT::Cache::Important",false);
179 pkgCacheFile CacheFile
;
180 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
183 if (CmdL
.FileSize() <= 1)
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)
192 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
193 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
194 APT::VersionList::CANDIDATE
, helper
);
195 for (APT::VersionList::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
196 if (ShowUnMet(V
, Important
) == false)
202 // DumpPackage - Show a dump of a package record /*{{{*/
203 // ---------------------------------------------------------------------
205 static bool DumpPackage(CommandLine
&CmdL
)
207 pkgCacheFile CacheFile
;
208 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
209 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
211 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
213 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
214 cout
<< "Versions: " << endl
;
215 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
217 cout
<< Cur
.VerStr();
218 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
219 cout
<< " (" << Vf
.File().FileName() << ")";
221 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
223 cout
<< " Description Language: " << D
.LanguageCode() << endl
224 << " File: " << D
.FileList().File().FileName() << endl
225 << " MD5: " << D
.md5() << endl
;
232 cout
<< "Reverse Depends: " << endl
;
233 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
235 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
237 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
242 cout
<< "Dependencies: " << endl
;
243 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
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()) << ") ";
251 cout
<< "Provides: " << endl
;
252 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
254 cout
<< Cur
.VerStr() << " - ";
255 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
256 cout
<< Prv
.ParentPkg().FullName(true) << " ";
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
;
267 // Stats - Dump some nice statistics /*{{{*/
268 // ---------------------------------------------------------------------
270 static bool Stats(CommandLine
&)
272 pkgCacheFile CacheFile
;
273 pkgCache
*Cache
= CacheFile
.GetPkgCache();
274 if (unlikely(Cache
== NULL
))
277 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
278 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
279 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
280 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
287 pkgCache::PkgIterator I
= Cache
->PkgBegin();
288 for (;I
.end() != true; ++I
)
290 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
296 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
302 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
305 if (I
.ProvidesList()->NextProvides
== 0)
313 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
319 cout
<< _(" Normal packages: ") << Normal
<< endl
;
320 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
321 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
322 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
323 cout
<< _(" Missing: ") << Missing
<< endl
;
325 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
326 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
327 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
328 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
329 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
330 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
332 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
333 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
334 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
335 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
336 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
337 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
340 unsigned long Size
= 0;
341 unsigned long Count
= 0;
342 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
343 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
346 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
348 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
350 unsigned long DepVerSize
= 0;
351 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
353 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
355 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
358 DepVerSize
+= strlen(D
.TargetVer()) + 1;
362 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
364 unsigned long Slack
= 0;
365 for (int I
= 0; I
!= 7; I
++)
366 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
367 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
369 unsigned long Total
= 0;
370 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
371 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
372 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
373 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
374 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
375 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
377 // hashtable stats for the PkgHashTable
378 long NumBuckets
= sizeof(Cache
->HeaderP
->PkgHashTable
)/sizeof(map_ptrloc
);
379 long UsedBuckets
= 0;
380 long UnusedBuckets
= 0;
381 long LongestBucket
= 0;
382 long ShortestBucket
= NumBuckets
;
383 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
385 pkgCache::Package
*Pkg
= Cache
->PkgP
+ Cache
->HeaderP
->PkgHashTable
[i
];
386 if(Pkg
== 0 || Pkg
== Cache
->PkgP
)
391 long ThisBucketSize
= 0;
392 for (; Pkg
!= Cache
->PkgP
; Pkg
= Cache
->PkgP
+ Pkg
->NextPackage
)
394 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
395 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
396 UsedBuckets
+= ThisBucketSize
;
398 cout
<< "Total PkgHashTable buckets: " << SizeToStr(NumBuckets
) << std::endl
;
399 cout
<< " Unused: " << SizeToStr(UnusedBuckets
) << std::endl
;
400 cout
<< " Used: " << UsedBuckets
<< std::endl
;
401 cout
<< " Average entries: " << UsedBuckets
/(double)NumBuckets
<< std::endl
;
402 cout
<< " Longest: " << LongestBucket
<< std::endl
;
403 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
405 // hashtable stats for the GrpHashTable
406 NumBuckets
= sizeof(Cache
->HeaderP
->GrpHashTable
)/sizeof(map_ptrloc
);
410 ShortestBucket
= NumBuckets
;
411 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
413 pkgCache::Group
*Grp
= Cache
->GrpP
+ Cache
->HeaderP
->GrpHashTable
[i
];
414 if(Grp
== 0 || Grp
== Cache
->GrpP
)
419 long ThisBucketSize
= 0;
420 for (; Grp
!= Cache
->GrpP
; Grp
= Cache
->GrpP
+ Grp
->Next
)
422 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
423 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
424 UsedBuckets
+= ThisBucketSize
;
426 cout
<< "Total GrpHashTable buckets: " << SizeToStr(NumBuckets
) << std::endl
;
427 cout
<< " Unused: " << SizeToStr(UnusedBuckets
) << std::endl
;
428 cout
<< " Used: " << UsedBuckets
<< std::endl
;
429 cout
<< " Average entries: " << UsedBuckets
/(double)NumBuckets
<< std::endl
;
430 cout
<< " Longest: " << LongestBucket
<< std::endl
;
431 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
436 // Dump - show everything /*{{{*/
437 // ---------------------------------------------------------------------
438 /* This is worthless except fer debugging things */
439 static bool Dump(CommandLine
&)
441 pkgCacheFile CacheFile
;
442 pkgCache
*Cache
= CacheFile
.GetPkgCache();
443 if (unlikely(Cache
== NULL
))
446 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
448 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
450 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
451 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
453 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
454 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
455 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
456 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
457 DeNull(D
.TargetVer()) << std::endl
;
458 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
460 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
461 << " File: " << D
.FileList().File().FileName() << std::endl
462 << " MD5: " << D
.md5() << std::endl
;
467 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
469 std::cout
<< "File: " << F
.FileName() << std::endl
;
470 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
471 std::cout
<< " Size: " << F
->Size
<< std::endl
;
472 std::cout
<< " ID: " << F
->ID
<< std::endl
;
473 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
474 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
475 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
476 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
477 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
478 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
479 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
480 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
481 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
487 // DumpAvail - Print out the available list /*{{{*/
488 // ---------------------------------------------------------------------
489 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
490 make this run really fast, perhaps I went a little overboard.. */
491 static bool DumpAvail(CommandLine
&)
493 pkgCacheFile CacheFile
;
494 pkgCache
*Cache
= CacheFile
.GetPkgCache();
495 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
498 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
499 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
500 memset(VFList
,0,sizeof(*VFList
)*Count
);
502 // Map versions that we want to write out onto the VerList array.
503 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
505 if (P
->VersionList
== 0)
508 /* Find the proper version to use. If the policy says there are no
509 possible selections we return the installed version, if available..
510 This prevents dselect from making it obsolete. */
511 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
514 if (P
->CurrentVer
== 0)
519 pkgCache::VerFileIterator VF
= V
.FileList();
520 for (; VF
.end() == false ; ++VF
)
521 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
524 /* Okay, here we have a bit of a problem.. The policy has selected the
525 currently installed package - however it only exists in the
526 status file.. We need to write out something or dselect will mark
527 the package as obsolete! Thus we emit the status file entry, but
528 below we remove the status line to make it valid for the
529 available file. However! We only do this if their do exist *any*
530 non-source versions of the package - that way the dselect obsolete
531 handling works OK. */
532 if (VF
.end() == true)
534 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
536 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
538 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
545 if (VF
.end() == false)
553 LocalitySort(VFList
,Count
,sizeof(*VFList
));
555 // Iterate over all the package files and write them out.
556 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
557 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
559 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
560 if (File
.IsOk() == false)
562 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
566 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
567 if (_error
->PendingError() == true)
570 /* Write all of the records from this package file, since we
571 already did locality sorting we can now just seek through the
572 file in read order. We apply 1 more optimization here, since often
573 there will be < 1 byte gaps between records (for the \n) we read that
574 into the next buffer and offset a bit.. */
575 unsigned long Pos
= 0;
578 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
581 const pkgCache::VerFile
&VF
= **J
;
583 // Read the record and then write it out again.
584 unsigned long Jitter
= VF
.Offset
- Pos
;
587 if (PkgF
.Seek(VF
.Offset
) == false)
592 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
594 Buffer
[VF
.Size
+ Jitter
] = '\n';
597 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
600 TFRewriteData RW
[] = {{"Status", NULL
, NULL
},{"Config-Version", NULL
, NULL
},{NULL
, NULL
, NULL
}};
601 const char *Zero
= 0;
602 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
603 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
605 _error
->Error("Internal Error, Unable to parse a package record");
612 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
616 Pos
= VF
.Offset
+ VF
.Size
;
620 if (_error
->PendingError() == true)
626 return !_error
->PendingError();
629 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
630 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
632 pkgCacheFile CacheFile
;
633 pkgCache
*Cache
= CacheFile
.GetPkgCache();
634 if (unlikely(Cache
== NULL
))
637 CacheSetHelperVirtuals
helper(false);
638 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionList::CANDIDATE
, helper
);
639 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
640 return _error
->Error(_("No packages found"));
641 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
643 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
644 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
645 bool const Important
= _config
->FindB("APT::Cache::Important", false);
646 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
647 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
648 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
649 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
650 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
651 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
652 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
653 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
654 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
655 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
656 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
658 while (verset
.empty() != true)
660 pkgCache::VerIterator Ver
= *verset
.begin();
661 verset
.erase(verset
.begin());
662 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
663 Shown
[Pkg
->ID
] = true;
665 cout
<< Pkg
.FullName(true) << endl
;
667 if (RevDepends
== true)
668 cout
<< "Reverse Depends:" << endl
;
669 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
670 D
.end() == false; ++D
)
673 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
674 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
675 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
676 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
677 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
678 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
679 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
682 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
684 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
687 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
693 if (ShowDepType
== true)
694 cout
<< D
.DepType() << ": ";
695 if (Trg
->VersionList
== 0)
696 cout
<< "<" << Trg
.FullName(true) << ">";
698 cout
<< Trg
.FullName(true);
699 if (ShowVersion
== true && D
->Version
!= 0)
700 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
703 if (Recurse
== true && Shown
[Trg
->ID
] == false)
705 Shown
[Trg
->ID
] = true;
706 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
711 // Display all solutions
712 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
713 pkgPrioSortList(*Cache
,List
);
714 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
716 pkgCache::VerIterator
V(*Cache
,*I
);
717 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
718 V
->ParentPkg
== D
->Package
)
720 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
722 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
724 Shown
[V
.ParentPkg()->ID
] = true;
725 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
729 if (ShowOnlyFirstOr
== true)
730 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
734 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
735 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
736 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
741 // Depends - Print out a dependency tree /*{{{*/
742 // ---------------------------------------------------------------------
744 static bool Depends(CommandLine
&CmdL
)
746 return ShowDepends(CmdL
, false);
749 // RDepends - Print out a reverse dependency tree /*{{{*/
750 // ---------------------------------------------------------------------
752 static bool RDepends(CommandLine
&CmdL
)
754 return ShowDepends(CmdL
, true);
757 // xvcg - Generate a graph for xvcg /*{{{*/
758 // ---------------------------------------------------------------------
759 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
761 static bool XVcg(CommandLine
&CmdL
)
763 pkgCacheFile CacheFile
;
764 pkgCache
*Cache
= CacheFile
.GetPkgCache();
765 if (unlikely(Cache
== NULL
))
768 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
770 /* Normal packages are boxes
771 Pure Provides are triangles
773 rhomb are missing packages*/
774 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
776 /* Initialize the list of packages to show.
778 2 = To Show no recurse
779 3 = Emitted no recurse
782 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
783 enum TheFlags
{ForceNR
=(1<<0)};
784 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
785 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
786 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
788 // Show everything if no arguments given
789 if (CmdL
.FileList
[1] == 0)
790 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
793 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
795 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
798 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
800 if (Pkg
->VersionList
== 0)
803 if (Pkg
->ProvidesList
== 0)
804 ShapeMap
[Pkg
->ID
] = 0;
806 ShapeMap
[Pkg
->ID
] = 1;
811 if (Pkg
->ProvidesList
== 0)
812 ShapeMap
[Pkg
->ID
] = 2;
814 ShapeMap
[Pkg
->ID
] = 3;
818 // Load the list of packages from the command line into the show list
819 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
820 std::list
<APT::PackageSet::Modifier
> mods
;
821 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
822 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
823 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
824 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
826 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
827 Pkg
!= pkgsets
[0].end(); ++Pkg
)
828 Show
[Pkg
->ID
] = ToShow
;
829 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
830 Pkg
!= pkgsets
[1].end(); ++Pkg
)
832 Show
[Pkg
->ID
] = ToShow
;
833 Flags
[Pkg
->ID
] |= ForceNR
;
837 cout
<< "graph: { title: \"packages\"" << endl
<<
838 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
839 "layout_downfactor: 8" << endl
;
845 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
847 // See we need to show this package
848 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
851 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
854 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
856 // Pure Provides and missing packages have no deps!
857 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
858 Show
[Pkg
->ID
] = Done
;
860 Show
[Pkg
->ID
] = DoneNR
;
863 Show
[Pkg
->ID
] = Done
;
866 // No deps to map out
867 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
870 pkgCache::VerIterator Ver
= Pkg
.VersionList();
871 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
873 // See if anything can meet this dep
874 // Walk along the actual package providing versions
876 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
877 for (pkgCache::VerIterator I
= DPkg
.VersionList();
878 I
.end() == false && Hit
== false; ++I
)
880 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
884 // Follow all provides
885 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
886 I
.end() == false && Hit
== false; ++I
)
888 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
893 // Only graph critical deps
894 if (D
.IsCritical() == true)
896 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
898 // Colour the node for recursion
899 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
901 /* If a conflicts does not meet anything in the database
902 then show the relation but do not recurse */
903 if (Hit
== false && D
.IsNegative() == true)
905 if (Show
[D
.TargetPkg()->ID
] == None
&&
906 Show
[D
.TargetPkg()->ID
] != ToShow
)
907 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
911 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
912 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
914 Show
[D
.TargetPkg()->ID
] = ToShow
;
921 case pkgCache::Dep::Conflicts
:
922 printf("label: \"conflicts\" color: lightgreen }\n");
924 case pkgCache::Dep::DpkgBreaks
:
925 printf("label: \"breaks\" color: lightgreen }\n");
927 case pkgCache::Dep::Obsoletes
:
928 printf("label: \"obsoletes\" color: lightgreen }\n");
931 case pkgCache::Dep::PreDepends
:
932 printf("label: \"predepends\" color: blue }\n");
944 /* Draw the box colours after the fact since we can not tell what colour
945 they should be until everything is finished drawing */
946 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
948 if (Show
[Pkg
->ID
] < DoneNR
)
951 if (Show
[Pkg
->ID
] == DoneNR
)
952 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
953 Shapes
[ShapeMap
[Pkg
->ID
]]);
955 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
956 Shapes
[ShapeMap
[Pkg
->ID
]]);
968 // Dotty - Generate a graph for Dotty /*{{{*/
969 // ---------------------------------------------------------------------
970 /* Dotty is the graphvis program for generating graphs. It is a fairly
971 simple queuing algorithm that just writes dependencies and nodes.
972 http://www.research.att.com/sw/tools/graphviz/ */
973 static bool Dotty(CommandLine
&CmdL
)
975 pkgCacheFile CacheFile
;
976 pkgCache
*Cache
= CacheFile
.GetPkgCache();
977 if (unlikely(Cache
== NULL
))
980 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
982 /* Normal packages are boxes
983 Pure Provides are triangles
985 Hexagons are missing packages*/
986 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
988 /* Initialize the list of packages to show.
990 2 = To Show no recurse
991 3 = Emitted no recurse
994 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
995 enum TheFlags
{ForceNR
=(1<<0)};
996 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
997 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
998 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1000 // Show everything if no arguments given
1001 if (CmdL
.FileList
[1] == 0)
1002 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1005 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1007 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1010 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1012 if (Pkg
->VersionList
== 0)
1015 if (Pkg
->ProvidesList
== 0)
1016 ShapeMap
[Pkg
->ID
] = 0;
1018 ShapeMap
[Pkg
->ID
] = 1;
1023 if (Pkg
->ProvidesList
== 0)
1024 ShapeMap
[Pkg
->ID
] = 2;
1026 ShapeMap
[Pkg
->ID
] = 3;
1030 // Load the list of packages from the command line into the show list
1031 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1032 std::list
<APT::PackageSet::Modifier
> mods
;
1033 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1034 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1035 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1036 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1038 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1039 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1040 Show
[Pkg
->ID
] = ToShow
;
1041 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1042 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1044 Show
[Pkg
->ID
] = ToShow
;
1045 Flags
[Pkg
->ID
] |= ForceNR
;
1049 printf("digraph packages {\n");
1050 printf("concentrate=true;\n");
1051 printf("size=\"30,40\";\n");
1057 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1059 // See we need to show this package
1060 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1064 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1066 // Pure Provides and missing packages have no deps!
1067 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1068 Show
[Pkg
->ID
] = Done
;
1070 Show
[Pkg
->ID
] = DoneNR
;
1073 Show
[Pkg
->ID
] = Done
;
1076 // No deps to map out
1077 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1080 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1081 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1083 // See if anything can meet this dep
1084 // Walk along the actual package providing versions
1086 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1087 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1088 I
.end() == false && Hit
== false; ++I
)
1090 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1094 // Follow all provides
1095 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1096 I
.end() == false && Hit
== false; ++I
)
1098 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1102 // Only graph critical deps
1103 if (D
.IsCritical() == true)
1105 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1107 // Colour the node for recursion
1108 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1110 /* If a conflicts does not meet anything in the database
1111 then show the relation but do not recurse */
1112 if (Hit
== false && D
.IsNegative() == true)
1114 if (Show
[D
.TargetPkg()->ID
] == None
&&
1115 Show
[D
.TargetPkg()->ID
] != ToShow
)
1116 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1120 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1121 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1123 Show
[D
.TargetPkg()->ID
] = ToShow
;
1130 case pkgCache::Dep::Conflicts
:
1131 case pkgCache::Dep::Obsoletes
:
1132 case pkgCache::Dep::DpkgBreaks
:
1133 printf("[color=springgreen];\n");
1136 case pkgCache::Dep::PreDepends
:
1137 printf("[color=blue];\n");
1149 /* Draw the box colours after the fact since we can not tell what colour
1150 they should be until everything is finished drawing */
1151 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1153 if (Show
[Pkg
->ID
] < DoneNR
)
1156 // Orange box for early recursion stoppage
1157 if (Show
[Pkg
->ID
] == DoneNR
)
1158 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1159 Shapes
[ShapeMap
[Pkg
->ID
]]);
1161 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1162 Shapes
[ShapeMap
[Pkg
->ID
]]);
1172 // DisplayRecord - Displays the complete record for the package /*{{{*/
1173 // ---------------------------------------------------------------------
1174 /* This displays the package record from the proper package index file.
1175 It is not used by DumpAvail for performance reasons. */
1177 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1179 char const * const TagName
= "\nDescription";
1180 size_t const TagLen
= strlen(TagName
);
1181 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1183 if (DescP
[1] == ' ')
1185 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1194 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1196 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1197 if (unlikely(Cache
== NULL
))
1200 // Find an appropriate file
1201 pkgCache::VerFileIterator Vf
= V
.FileList();
1202 for (; Vf
.end() == false; ++Vf
)
1203 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1205 if (Vf
.end() == true)
1208 // Check and load the package list file
1209 pkgCache::PkgFileIterator I
= Vf
.File();
1210 if (I
.IsOk() == false)
1211 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1214 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1217 // Read the record (and ensure that it ends with a newline and NUL)
1218 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1219 Buffer
[Vf
->Size
] = '\n';
1220 Buffer
[Vf
->Size
+1] = '\0';
1221 if (PkgF
.Seek(Vf
->Offset
) == false ||
1222 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1228 // Get a pointer to start of Description field
1229 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1233 DescP
= Buffer
+ Vf
->Size
;
1235 // Write all but Description
1236 size_t const length
= DescP
- Buffer
;
1237 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1243 // Show the right description
1244 pkgRecords
Recs(*Cache
);
1245 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1246 if (Desc
.end() == false)
1248 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1249 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1250 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1252 // Find the first field after the description (if there is any)
1253 DescP
= skipDescriptionFields(DescP
);
1255 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1257 // write the rest of the buffer, but skip mixed in Descriptions* fields
1258 while (DescP
!= NULL
)
1260 const unsigned char * const Start
= DescP
;
1261 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1264 End
= &Buffer
[Vf
->Size
];
1269 ++End
; // get the newline into the output
1270 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1272 size_t const length
= End
- Start
;
1273 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1280 // write a final newline after the last field
1289 pkgCache::DescFile
*Df
;
1293 // Search - Perform a search /*{{{*/
1294 // ---------------------------------------------------------------------
1295 /* This searches the package names and package descriptions for a pattern */
1296 static bool Search(CommandLine
&CmdL
)
1298 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1299 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1300 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1302 pkgCacheFile CacheFile
;
1303 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1304 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1305 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1308 // Make sure there is at least one argument
1309 if (NumPatterns
< 1)
1310 return _error
->Error(_("You must give at least one search pattern"));
1312 // Compile the regex pattern
1313 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1314 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1315 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1317 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1321 regfree(&Patterns
[I
]);
1322 return _error
->Error("Regex compilation error");
1326 if (_error
->PendingError() == true)
1328 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1329 regfree(&Patterns
[I
]);
1333 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1334 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1335 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1337 bool PatternMatch
[descCount
* NumPatterns
];
1338 memset(PatternMatch
,false,sizeof(PatternMatch
));
1340 // Map versions that we want to write out onto the VerList array.
1341 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1343 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1344 size_t unmatched
= 0, matched
= 0;
1345 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1347 if (PatternMatch
[PatternOffset
+ I
] == true)
1349 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1350 PatternMatch
[PatternOffset
+ I
] = true;
1355 // already dealt with this package?
1356 if (matched
== NumPatterns
)
1359 // Doing names only, drop any that don't match..
1360 if (NamesOnly
== true && unmatched
== NumPatterns
)
1363 // Find the proper version to use
1364 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1365 if (P
.end() == true)
1367 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1368 if (V
.end() == false)
1370 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1371 //FIXME: packages without a description can't be found
1372 if (D
.end() == true)
1374 DFList
[G
->ID
].Df
= D
.FileList();
1375 DFList
[G
->ID
].ID
= G
->ID
;
1378 if (unmatched
== NumPatterns
)
1381 // Include all the packages that provide matching names too
1382 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1384 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1385 if (V
.end() == true)
1388 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1389 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1390 //FIXME: packages without a description can't be found
1391 if (D
.end() == true)
1393 DFList
[id
].Df
= D
.FileList();
1396 size_t const PrvPatternOffset
= id
* NumPatterns
;
1397 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1398 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1402 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1404 // Create the text record parser
1405 pkgRecords
Recs(*Cache
);
1406 // Iterate over all the version records and check them
1407 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1409 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1410 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1412 if (NamesOnly
== false)
1414 string
const LongDesc
= P
.LongDesc();
1415 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1417 if (PatternMatch
[PatternOffset
+ I
] == true)
1419 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1420 PatternMatch
[PatternOffset
+ I
] = true;
1424 bool matchedAll
= true;
1425 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1426 if (PatternMatch
[PatternOffset
+ I
] == false)
1432 if (matchedAll
== true)
1434 if (ShowFull
== true)
1438 P
.GetRec(Start
,End
);
1439 fwrite(Start
,End
-Start
,1,stdout
);
1443 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1448 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1449 regfree(&Patterns
[I
]);
1451 return _error
->Error("Write to stdout failed");
1455 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1456 static bool ShowAuto(CommandLine
&)
1458 pkgCacheFile CacheFile
;
1459 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1460 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1461 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1464 std::vector
<string
> packages
;
1465 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1467 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1468 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1469 packages
.push_back(P
.Name());
1471 std::sort(packages
.begin(), packages
.end());
1473 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1476 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1480 // ShowPackage - Dump the package record to the screen /*{{{*/
1481 // ---------------------------------------------------------------------
1483 static bool ShowPackage(CommandLine
&CmdL
)
1485 pkgCacheFile CacheFile
;
1486 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1487 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1488 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1489 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1490 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1491 if (DisplayRecord(CacheFile
, Ver
) == false)
1494 if (verset
.empty() == true)
1496 if (helper
.virtualPkgs
.empty() == true)
1497 return _error
->Error(_("No packages found"));
1499 _error
->Notice(_("No packages found"));
1504 // ShowPkgNames - Show package names /*{{{*/
1505 // ---------------------------------------------------------------------
1506 /* This does a prefix match on the first argument */
1507 static bool ShowPkgNames(CommandLine
&CmdL
)
1509 pkgCacheFile CacheFile
;
1510 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1512 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1513 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1515 if (CmdL
.FileList
[1] != 0)
1517 for (;I
.end() != true; ++I
)
1519 if (All
== false && I
->FirstPackage
== 0)
1521 if (I
.FindPkg("any")->VersionList
== 0)
1523 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1524 cout
<< I
.Name() << endl
;
1531 for (;I
.end() != true; ++I
)
1533 if (All
== false && I
->FirstPackage
== 0)
1535 if (I
.FindPkg("any")->VersionList
== 0)
1537 cout
<< I
.Name() << endl
;
1543 // ShowSrcPackage - Show source package records /*{{{*/
1544 // ---------------------------------------------------------------------
1546 static bool ShowSrcPackage(CommandLine
&CmdL
)
1548 pkgCacheFile CacheFile
;
1549 pkgSourceList
*List
= CacheFile
.GetSourceList();
1550 if (unlikely(List
== NULL
))
1553 // Create the text record parsers
1554 pkgSrcRecords
SrcRecs(*List
);
1555 if (_error
->PendingError() == true)
1559 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1563 pkgSrcRecords::Parser
*Parse
;
1564 unsigned found_this
= 0;
1565 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1566 cout
<< Parse
->AsStr() << endl
;;
1570 if (found_this
== 0) {
1571 _error
->Warning(_("Unable to locate package %s"),*I
);
1576 _error
->Notice(_("No packages found"));
1580 // Policy - Show the results of the preferences file /*{{{*/
1581 // ---------------------------------------------------------------------
1583 static bool Policy(CommandLine
&CmdL
)
1585 pkgCacheFile CacheFile
;
1586 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1587 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1588 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1589 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1592 /* Should the MultiArchKiller be run to see which pseudo packages for an
1593 arch all package are currently installed? Activating it gives a speed
1594 penality for no real gain beside enhanced debugging, so in general no. */
1595 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1596 CacheFile
.GetDepCache();
1598 // Print out all of the package files
1599 if (CmdL
.FileList
[1] == 0)
1601 cout
<< _("Package files:") << endl
;
1602 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1604 // Locate the associated index files so we can derive a description
1606 if (SrcList
->FindIndex(F
,Indx
) == false &&
1607 _system
->FindIndex(F
,Indx
) == false)
1608 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1611 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1613 // Print the reference information for the package
1614 string Str
= F
.RelStr();
1615 if (Str
.empty() == false)
1616 printf(" release %s\n",F
.RelStr().c_str());
1617 if (F
.Site() != 0 && F
.Site()[0] != 0)
1618 printf(" origin %s\n",F
.Site());
1621 // Show any packages have explicit pins
1622 cout
<< _("Pinned packages:") << endl
;
1623 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1624 for (;I
.end() != true; ++I
)
1626 if (Plcy
->GetPriority(I
) == 0)
1629 // Print the package name and the version we are forcing to
1630 cout
<< " " << I
.FullName(true) << " -> ";
1632 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1633 if (V
.end() == true)
1634 cout
<< _("(not found)") << endl
;
1636 cout
<< V
.VerStr() << endl
;
1642 char const * const msgInstalled
= _(" Installed: ");
1643 char const * const msgCandidate
= _(" Candidate: ");
1644 short const InstalledLessCandidate
=
1645 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1646 short const deepInstalled
=
1647 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1648 short const deepCandidate
=
1649 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1651 // Print out detailed information for each package
1652 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1653 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1654 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1656 cout
<< Pkg
.FullName(true) << ":" << endl
;
1658 // Installed version
1659 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1660 if (Pkg
->CurrentVer
== 0)
1661 cout
<< _("(none)") << endl
;
1663 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1665 // Candidate Version
1666 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1667 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1668 if (V
.end() == true)
1669 cout
<< _("(none)") << endl
;
1671 cout
<< V
.VerStr() << endl
;
1674 if (Plcy
->GetPriority(Pkg
) != 0)
1676 cout
<< _(" Package pin: ");
1677 V
= Plcy
->GetMatch(Pkg
);
1678 if (V
.end() == true)
1679 cout
<< _("(not found)") << endl
;
1681 cout
<< V
.VerStr() << endl
;
1684 // Show the priority tables
1685 cout
<< _(" Version table:") << endl
;
1686 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1688 if (Pkg
.CurrentVer() == V
)
1689 cout
<< " *** " << V
.VerStr();
1691 cout
<< " " << V
.VerStr();
1692 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1693 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1695 // Locate the associated index files so we can derive a description
1697 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1698 _system
->FindIndex(VF
.File(),Indx
) == false)
1699 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1700 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1701 Indx
->Describe(true).c_str());
1709 // Madison - Look a bit like katie's madison /*{{{*/
1710 // ---------------------------------------------------------------------
1712 static bool Madison(CommandLine
&CmdL
)
1714 pkgCacheFile CacheFile
;
1715 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1720 // Create the src text record parsers and ignore errors about missing
1721 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1722 pkgSrcRecords
SrcRecs(*SrcList
);
1723 if (_error
->PendingError() == true)
1726 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1727 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1729 _error
->PushToStack();
1730 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1731 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1733 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1735 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1737 // This might be nice, but wouldn't uniquely identify the source -mdz
1738 // if (VF.File().Archive() != 0)
1740 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1741 // << VF.File().Archive() << endl;
1744 // Locate the associated index files so we can derive a description
1745 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1747 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1748 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1749 IF
!= Indexes
->end(); ++IF
)
1751 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1753 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1754 << (*IF
)->Describe(true) << endl
;
1763 pkgSrcRecords::Parser
*SrcParser
;
1764 bool foundSomething
= false;
1765 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1767 foundSomething
= true;
1768 // Maybe support Release info here too eventually
1769 cout
<< setw(10) << SrcParser
->Package() << " | "
1770 << setw(10) << SrcParser
->Version() << " | "
1771 << SrcParser
->Index().Describe(true) << endl
;
1773 if (foundSomething
== true)
1774 _error
->RevertToStack();
1776 _error
->MergeWithStack();
1782 // GenCaches - Call the main cache generator /*{{{*/
1783 // ---------------------------------------------------------------------
1785 static bool GenCaches(CommandLine
&)
1787 OpTextProgress
Progress(*_config
);
1789 pkgCacheFile CacheFile
;
1790 return CacheFile
.BuildCaches(&Progress
, true);
1793 // ShowHelp - Show a help screen /*{{{*/
1794 // ---------------------------------------------------------------------
1796 static bool ShowHelp(CommandLine
&)
1798 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1799 COMMON_ARCH
,__DATE__
,__TIME__
);
1801 if (_config
->FindB("version") == true)
1805 _("Usage: apt-cache [options] command\n"
1806 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1807 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1809 "apt-cache is a low-level tool used to query information\n"
1810 "from APT's binary cache files\n"
1813 " gencaches - Build both the package and source cache\n"
1814 " showpkg - Show some general information for a single package\n"
1815 " showsrc - Show source records\n"
1816 " stats - Show some basic statistics\n"
1817 " dump - Show the entire file in a terse form\n"
1818 " dumpavail - Print an available file to stdout\n"
1819 " unmet - Show unmet dependencies\n"
1820 " search - Search the package list for a regex pattern\n"
1821 " show - Show a readable record for the package\n"
1822 " depends - Show raw dependency information for a package\n"
1823 " rdepends - Show reverse dependency information for a package\n"
1824 " pkgnames - List the names of all packages in the system\n"
1825 " dotty - Generate package graphs for GraphViz\n"
1826 " xvcg - Generate package graphs for xvcg\n"
1827 " policy - Show policy settings\n"
1830 " -h This help text.\n"
1831 " -p=? The package cache.\n"
1832 " -s=? The source cache.\n"
1833 " -q Disable progress indicator.\n"
1834 " -i Show only important deps for the unmet command.\n"
1835 " -c=? Read this configuration file\n"
1836 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1837 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1841 int main(int argc
,const char *argv
[]) /*{{{*/
1843 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1844 {"gencaches",&GenCaches
},
1845 {"showsrc",&ShowSrcPackage
},
1846 {"showpkg",&DumpPackage
},
1849 {"dumpavail",&DumpAvail
},
1852 {"depends",&Depends
},
1853 {"rdepends",&RDepends
},
1856 {"show",&ShowPackage
},
1857 {"pkgnames",&ShowPkgNames
},
1858 {"showauto",&ShowAuto
},
1860 {"madison",&Madison
},
1863 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1865 // Set up gettext support
1866 setlocale(LC_ALL
,"");
1867 textdomain(PACKAGE
);
1869 // Parse the command line and initialize the package library
1870 CommandLine
CmdL(Args
.data(),_config
);
1871 if (pkgInitConfig(*_config
) == false ||
1872 CmdL
.Parse(argc
,argv
) == false ||
1873 pkgInitSystem(*_config
,_system
) == false)
1875 _error
->DumpErrors();
1879 // See if the help should be shown
1880 if (_config
->FindB("help") == true ||
1881 CmdL
.FileSize() == 0)
1887 // Deal with stdout not being a tty
1888 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1889 _config
->Set("quiet","1");
1891 if (_config
->Exists("APT::Cache::Generate") == true)
1892 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1894 // Match the operation
1895 CmdL
.DispatchArg(Cmds
);
1897 // Print any errors or warnings found during parsing
1898 bool const Errors
= _error
->PendingError();
1899 if (_config
->FindI("quiet",0) > 0)
1900 _error
->DumpErrors();
1902 _error
->DumpErrors(GlobalError::DEBUG
);
1903 return Errors
== true ? 100 : 0;