]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
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 || End
->Type
== pkgCache::Dep::Replaces
)
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::CacheSetHelper::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 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
268 // ---------------------------------------------------------------------
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
; }
273 static void ShowHashTableStats(std::string Type
,
275 map_pointer_t
*Hashtable
,
277 map_pointer_t(*Next
)(T
const * const))
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
)
288 T
*P
= StartP
+ Hashtable
[i
];
289 if(P
== 0 || P
== StartP
)
295 unsigned long ThisBucketSize
= 0;
296 for (; P
!= StartP
; P
= StartP
+ Next(P
))
298 Entries
+= ThisBucketSize
;
299 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
300 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
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
;
310 // Stats - Dump some nice statistics /*{{{*/
311 // ---------------------------------------------------------------------
313 static bool Stats(CommandLine
&)
315 pkgCacheFile CacheFile
;
316 pkgCache
*Cache
= CacheFile
.GetPkgCache();
317 if (unlikely(Cache
== NULL
))
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
;
330 pkgCache::PkgIterator I
= Cache
->PkgBegin();
331 for (;I
.end() != true; ++I
)
333 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
339 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
345 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
348 if (I
.ProvidesList()->NextProvides
== 0)
356 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
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
;
368 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
369 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
370 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
371 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
372 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
373 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
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
;
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
)
388 stritems
.insert(P
->Arch
);
389 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
392 stritems
.insert(V
->VerStr
);
394 stritems
.insert(V
->Section
);
395 #if APT_PKG_ABI >= 413
396 stritems
.insert(V
->SourcePkgName
);
397 stritems
.insert(V
->SourceVerStr
);
399 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
402 stritems
.insert(D
->Version
);
404 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
406 stritems
.insert(D
->md5sum
);
407 stritems
.insert(D
->language_code
);
410 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
412 if (Prv
->ProvideVersion
!= 0)
413 stritems
.insert(Prv
->ProvideVersion
);
416 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
418 stritems
.insert(F
->FileName
);
419 stritems
.insert(F
->Archive
);
420 stritems
.insert(F
->Codename
);
421 stritems
.insert(F
->Component
);
422 stritems
.insert(F
->Version
);
423 stritems
.insert(F
->Origin
);
424 stritems
.insert(F
->Label
);
425 stritems
.insert(F
->Architecture
);
426 stritems
.insert(F
->Site
);
427 stritems
.insert(F
->IndexType
);
429 unsigned long Size
= 0;
430 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
431 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
433 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
436 unsigned long Slack
= 0;
437 for (int I
= 0; I
!= 7; I
++)
438 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
439 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
441 unsigned long Total
= 0;
442 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
443 Total
= Slack
+ Size
+
444 APT_CACHESIZE(GroupCount
, GroupSz
) +
445 APT_CACHESIZE(PackageCount
, PackageSz
) +
446 APT_CACHESIZE(VersionCount
, VersionSz
) +
447 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
448 APT_CACHESIZE(DependsCount
, DependencySz
) +
449 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
450 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
451 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
452 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
453 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
454 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
458 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
459 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
464 // Dump - show everything /*{{{*/
465 // ---------------------------------------------------------------------
466 /* This is worthless except fer debugging things */
467 static bool Dump(CommandLine
&)
469 pkgCacheFile CacheFile
;
470 pkgCache
*Cache
= CacheFile
.GetPkgCache();
471 if (unlikely(Cache
== NULL
))
474 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
476 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
478 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
479 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
481 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
482 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
483 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
484 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
485 DeNull(D
.TargetVer()) << std::endl
;
486 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
488 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
489 << " File: " << D
.FileList().File().FileName() << std::endl
490 << " MD5: " << D
.md5() << std::endl
;
495 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
497 std::cout
<< "File: " << F
.FileName() << std::endl
;
498 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
499 std::cout
<< " Size: " << F
->Size
<< std::endl
;
500 std::cout
<< " ID: " << F
->ID
<< std::endl
;
501 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
502 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
503 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
504 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
505 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
506 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
507 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
508 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
509 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
515 // DumpAvail - Print out the available list /*{{{*/
516 // ---------------------------------------------------------------------
517 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
518 make this run really fast, perhaps I went a little overboard.. */
519 static bool DumpAvail(CommandLine
&)
521 pkgCacheFile CacheFile
;
522 pkgCache
*Cache
= CacheFile
.GetPkgCache();
523 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
526 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
527 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
528 memset(VFList
,0,sizeof(*VFList
)*Count
);
530 // Map versions that we want to write out onto the VerList array.
531 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
533 if (P
->VersionList
== 0)
536 /* Find the proper version to use. If the policy says there are no
537 possible selections we return the installed version, if available..
538 This prevents dselect from making it obsolete. */
539 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
542 if (P
->CurrentVer
== 0)
547 pkgCache::VerFileIterator VF
= V
.FileList();
548 for (; VF
.end() == false ; ++VF
)
549 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
552 /* Okay, here we have a bit of a problem.. The policy has selected the
553 currently installed package - however it only exists in the
554 status file.. We need to write out something or dselect will mark
555 the package as obsolete! Thus we emit the status file entry, but
556 below we remove the status line to make it valid for the
557 available file. However! We only do this if their do exist *any*
558 non-source versions of the package - that way the dselect obsolete
559 handling works OK. */
560 if (VF
.end() == true)
562 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
564 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
566 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
573 if (VF
.end() == false)
581 LocalitySort(VFList
,Count
,sizeof(*VFList
));
583 std::vector
<pkgTagSection::Tag
> RW
;
584 RW
.push_back(pkgTagSection::Tag::Remove("Status"));
585 RW
.push_back(pkgTagSection::Tag::Remove("Config-Version"));
587 stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
, false);
589 // Iterate over all the package files and write them out.
590 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
591 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
593 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
594 if (File
.IsOk() == false)
596 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
600 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
601 if (_error
->PendingError() == true)
604 /* Write all of the records from this package file, since we
605 already did locality sorting we can now just seek through the
606 file in read order. We apply 1 more optimization here, since often
607 there will be < 1 byte gaps between records (for the \n) we read that
608 into the next buffer and offset a bit.. */
609 unsigned long Pos
= 0;
612 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
615 const pkgCache::VerFile
&VF
= **J
;
617 // Read the record and then write it out again.
618 unsigned long Jitter
= VF
.Offset
- Pos
;
621 if (PkgF
.Seek(VF
.Offset
) == false)
626 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
628 Buffer
[VF
.Size
+ Jitter
] = '\n';
631 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
634 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
635 Tags
.Write(stdoutfd
, NULL
, RW
) == false ||
636 stdoutfd
.Write("\n", 1) == false)
638 _error
->Error("Internal Error, Unable to parse a package record");
644 if (stdoutfd
.Write(Buffer
+ Jitter
, VF
.Size
+ 1) == false)
648 Pos
= VF
.Offset
+ VF
.Size
;
651 if (_error
->PendingError() == true)
657 return !_error
->PendingError();
660 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
661 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
663 pkgCacheFile CacheFile
;
664 pkgCache
*Cache
= CacheFile
.GetPkgCache();
665 if (unlikely(Cache
== NULL
))
668 CacheSetHelperVirtuals
helper(false);
669 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
670 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
671 return _error
->Error(_("No packages found"));
672 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
674 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
675 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
676 bool const Important
= _config
->FindB("APT::Cache::Important", false);
677 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
678 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
679 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
680 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
681 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
682 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
683 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
684 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
685 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
686 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
687 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
689 while (verset
.empty() != true)
691 pkgCache::VerIterator Ver
= *verset
.begin();
692 verset
.erase(verset
.begin());
693 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
694 Shown
[Pkg
->ID
] = true;
696 cout
<< Pkg
.FullName(true) << endl
;
698 if (RevDepends
== true)
699 cout
<< "Reverse Depends:" << endl
;
700 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
701 D
.end() == false; ++D
)
704 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
705 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
706 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
707 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
708 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
709 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
710 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
713 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
715 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
718 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
724 if (ShowDepType
== true)
725 cout
<< D
.DepType() << ": ";
726 if (Trg
->VersionList
== 0)
727 cout
<< "<" << Trg
.FullName(true) << ">";
729 cout
<< Trg
.FullName(true);
730 if (ShowVersion
== true && D
->Version
!= 0)
731 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
734 if (Recurse
== true && Shown
[Trg
->ID
] == false)
736 Shown
[Trg
->ID
] = true;
737 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::CacheSetHelper::CANDIDATE
, helper
));
742 // Display all solutions
743 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
744 pkgPrioSortList(*Cache
,List
);
745 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
747 pkgCache::VerIterator
V(*Cache
,*I
);
748 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
749 V
->ParentPkg
== D
->Package
)
751 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
753 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
755 Shown
[V
.ParentPkg()->ID
] = true;
756 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::CacheSetHelper::CANDIDATE
, helper
));
760 if (ShowOnlyFirstOr
== true)
761 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
765 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
766 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
767 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
772 // Depends - Print out a dependency tree /*{{{*/
773 // ---------------------------------------------------------------------
775 static bool Depends(CommandLine
&CmdL
)
777 return ShowDepends(CmdL
, false);
780 // RDepends - Print out a reverse dependency tree /*{{{*/
781 // ---------------------------------------------------------------------
783 static bool RDepends(CommandLine
&CmdL
)
785 return ShowDepends(CmdL
, true);
788 // xvcg - Generate a graph for xvcg /*{{{*/
789 // ---------------------------------------------------------------------
790 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
792 static bool XVcg(CommandLine
&CmdL
)
794 pkgCacheFile CacheFile
;
795 pkgCache
*Cache
= CacheFile
.GetPkgCache();
796 if (unlikely(Cache
== NULL
))
799 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
801 /* Normal packages are boxes
802 Pure Provides are triangles
804 rhomb are missing packages*/
805 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
807 /* Initialize the list of packages to show.
809 2 = To Show no recurse
810 3 = Emitted no recurse
813 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
814 enum TheFlags
{ForceNR
=(1<<0)};
815 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
816 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
817 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
819 // Show everything if no arguments given
820 if (CmdL
.FileList
[1] == 0)
821 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
824 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
826 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
829 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
831 if (Pkg
->VersionList
== 0)
834 if (Pkg
->ProvidesList
== 0)
835 ShapeMap
[Pkg
->ID
] = 0;
837 ShapeMap
[Pkg
->ID
] = 1;
842 if (Pkg
->ProvidesList
== 0)
843 ShapeMap
[Pkg
->ID
] = 2;
845 ShapeMap
[Pkg
->ID
] = 3;
849 // Load the list of packages from the command line into the show list
850 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
851 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
852 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
853 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
854 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
855 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
857 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
858 Pkg
!= pkgsets
[0].end(); ++Pkg
)
859 Show
[Pkg
->ID
] = ToShow
;
860 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
861 Pkg
!= pkgsets
[1].end(); ++Pkg
)
863 Show
[Pkg
->ID
] = ToShow
;
864 Flags
[Pkg
->ID
] |= ForceNR
;
868 cout
<< "graph: { title: \"packages\"" << endl
<<
869 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
870 "layout_downfactor: 8" << endl
;
876 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
878 // See we need to show this package
879 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
882 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
885 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
887 // Pure Provides and missing packages have no deps!
888 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
889 Show
[Pkg
->ID
] = Done
;
891 Show
[Pkg
->ID
] = DoneNR
;
894 Show
[Pkg
->ID
] = Done
;
897 // No deps to map out
898 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
901 pkgCache::VerIterator Ver
= Pkg
.VersionList();
902 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
904 // See if anything can meet this dep
905 // Walk along the actual package providing versions
907 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
908 for (pkgCache::VerIterator I
= DPkg
.VersionList();
909 I
.end() == false && Hit
== false; ++I
)
911 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
915 // Follow all provides
916 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
917 I
.end() == false && Hit
== false; ++I
)
919 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
924 // Only graph critical deps
925 if (D
.IsCritical() == true)
927 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
929 // Colour the node for recursion
930 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
932 /* If a conflicts does not meet anything in the database
933 then show the relation but do not recurse */
934 if (Hit
== false && D
.IsNegative() == true)
936 if (Show
[D
.TargetPkg()->ID
] == None
&&
937 Show
[D
.TargetPkg()->ID
] != ToShow
)
938 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
942 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
943 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
945 Show
[D
.TargetPkg()->ID
] = ToShow
;
952 case pkgCache::Dep::Conflicts
:
953 printf("label: \"conflicts\" color: lightgreen }\n");
955 case pkgCache::Dep::DpkgBreaks
:
956 printf("label: \"breaks\" color: lightgreen }\n");
958 case pkgCache::Dep::Obsoletes
:
959 printf("label: \"obsoletes\" color: lightgreen }\n");
962 case pkgCache::Dep::PreDepends
:
963 printf("label: \"predepends\" color: blue }\n");
975 /* Draw the box colours after the fact since we can not tell what colour
976 they should be until everything is finished drawing */
977 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
979 if (Show
[Pkg
->ID
] < DoneNR
)
982 if (Show
[Pkg
->ID
] == DoneNR
)
983 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
984 Shapes
[ShapeMap
[Pkg
->ID
]]);
986 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
987 Shapes
[ShapeMap
[Pkg
->ID
]]);
999 // Dotty - Generate a graph for Dotty /*{{{*/
1000 // ---------------------------------------------------------------------
1001 /* Dotty is the graphvis program for generating graphs. It is a fairly
1002 simple queuing algorithm that just writes dependencies and nodes.
1003 http://www.research.att.com/sw/tools/graphviz/ */
1004 static bool Dotty(CommandLine
&CmdL
)
1006 pkgCacheFile CacheFile
;
1007 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1008 if (unlikely(Cache
== NULL
))
1011 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1013 /* Normal packages are boxes
1014 Pure Provides are triangles
1016 Hexagons are missing packages*/
1017 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1019 /* Initialize the list of packages to show.
1021 2 = To Show no recurse
1022 3 = Emitted no recurse
1025 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1026 enum TheFlags
{ForceNR
=(1<<0)};
1027 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1028 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1029 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1031 // Show everything if no arguments given
1032 if (CmdL
.FileList
[1] == 0)
1033 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1036 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1038 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1041 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1043 if (Pkg
->VersionList
== 0)
1046 if (Pkg
->ProvidesList
== 0)
1047 ShapeMap
[Pkg
->ID
] = 0;
1049 ShapeMap
[Pkg
->ID
] = 1;
1054 if (Pkg
->ProvidesList
== 0)
1055 ShapeMap
[Pkg
->ID
] = 2;
1057 ShapeMap
[Pkg
->ID
] = 3;
1061 // Load the list of packages from the command line into the show list
1062 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1063 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
1064 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1065 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1066 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1067 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1069 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1070 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1071 Show
[Pkg
->ID
] = ToShow
;
1072 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1073 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1075 Show
[Pkg
->ID
] = ToShow
;
1076 Flags
[Pkg
->ID
] |= ForceNR
;
1080 printf("digraph packages {\n");
1081 printf("concentrate=true;\n");
1082 printf("size=\"30,40\";\n");
1088 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1090 // See we need to show this package
1091 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1095 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1097 // Pure Provides and missing packages have no deps!
1098 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1099 Show
[Pkg
->ID
] = Done
;
1101 Show
[Pkg
->ID
] = DoneNR
;
1104 Show
[Pkg
->ID
] = Done
;
1107 // No deps to map out
1108 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1111 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1112 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1114 // See if anything can meet this dep
1115 // Walk along the actual package providing versions
1117 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1118 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1119 I
.end() == false && Hit
== false; ++I
)
1121 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1125 // Follow all provides
1126 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1127 I
.end() == false && Hit
== false; ++I
)
1129 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1133 // Only graph critical deps
1134 if (D
.IsCritical() == true)
1136 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1138 // Colour the node for recursion
1139 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1141 /* If a conflicts does not meet anything in the database
1142 then show the relation but do not recurse */
1143 if (Hit
== false && D
.IsNegative() == true)
1145 if (Show
[D
.TargetPkg()->ID
] == None
&&
1146 Show
[D
.TargetPkg()->ID
] != ToShow
)
1147 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1151 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1152 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1154 Show
[D
.TargetPkg()->ID
] = ToShow
;
1161 case pkgCache::Dep::Conflicts
:
1162 case pkgCache::Dep::Obsoletes
:
1163 case pkgCache::Dep::DpkgBreaks
:
1164 printf("[color=springgreen];\n");
1167 case pkgCache::Dep::PreDepends
:
1168 printf("[color=blue];\n");
1180 /* Draw the box colours after the fact since we can not tell what colour
1181 they should be until everything is finished drawing */
1182 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1184 if (Show
[Pkg
->ID
] < DoneNR
)
1187 // Orange box for early recursion stoppage
1188 if (Show
[Pkg
->ID
] == DoneNR
)
1189 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1190 Shapes
[ShapeMap
[Pkg
->ID
]]);
1192 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1193 Shapes
[ShapeMap
[Pkg
->ID
]]);
1203 // DisplayRecord - Displays the complete record for the package /*{{{*/
1204 // ---------------------------------------------------------------------
1205 /* This displays the package record from the proper package index file.
1206 It is not used by DumpAvail for performance reasons. */
1208 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1210 char const * const TagName
= "\nDescription";
1211 size_t const TagLen
= strlen(TagName
);
1212 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1214 if (DescP
[1] == ' ')
1216 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1225 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1227 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1228 if (unlikely(Cache
== NULL
))
1231 // Find an appropriate file
1232 pkgCache::VerFileIterator Vf
= V
.FileList();
1233 for (; Vf
.end() == false; ++Vf
)
1234 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1236 if (Vf
.end() == true)
1239 // Check and load the package list file
1240 pkgCache::PkgFileIterator I
= Vf
.File();
1241 if (I
.IsOk() == false)
1242 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1245 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1248 // Read the record (and ensure that it ends with a newline and NUL)
1249 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1250 Buffer
[Vf
->Size
] = '\n';
1251 Buffer
[Vf
->Size
+1] = '\0';
1252 if (PkgF
.Seek(Vf
->Offset
) == false ||
1253 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1259 // Get a pointer to start of Description field
1260 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1264 DescP
= Buffer
+ Vf
->Size
;
1266 // Write all but Description
1267 size_t const length
= DescP
- Buffer
;
1268 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1274 // Show the right description
1275 pkgRecords
Recs(*Cache
);
1276 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1277 if (Desc
.end() == false)
1279 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1280 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1281 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1283 // Find the first field after the description (if there is any)
1284 DescP
= skipDescriptionFields(DescP
);
1286 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1288 // write the rest of the buffer, but skip mixed in Descriptions* fields
1289 while (DescP
!= NULL
)
1291 const unsigned char * const Start
= DescP
;
1292 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1295 End
= &Buffer
[Vf
->Size
];
1300 ++End
; // get the newline into the output
1301 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1303 size_t const length
= End
- Start
;
1304 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1311 // write a final newline after the last field
1320 pkgCache::DescFile
*Df
;
1324 // Search - Perform a search /*{{{*/
1325 // ---------------------------------------------------------------------
1326 /* This searches the package names and package descriptions for a pattern */
1327 static bool Search(CommandLine
&CmdL
)
1329 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1330 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1331 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1333 pkgCacheFile CacheFile
;
1334 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1335 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1336 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1339 // Make sure there is at least one argument
1340 if (NumPatterns
< 1)
1341 return _error
->Error(_("You must give at least one search pattern"));
1343 // Compile the regex pattern
1344 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1345 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1346 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1348 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1352 regfree(&Patterns
[I
]);
1353 return _error
->Error("Regex compilation error");
1357 if (_error
->PendingError() == true)
1359 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1360 regfree(&Patterns
[I
]);
1364 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1365 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1366 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1368 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1369 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1371 // Map versions that we want to write out onto the VerList array.
1372 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1374 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1375 size_t unmatched
= 0, matched
= 0;
1376 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1378 if (PatternMatch
[PatternOffset
+ I
] == true)
1380 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1381 PatternMatch
[PatternOffset
+ I
] = true;
1386 // already dealt with this package?
1387 if (matched
== NumPatterns
)
1390 // Doing names only, drop any that don't match..
1391 if (NamesOnly
== true && unmatched
== NumPatterns
)
1394 // Find the proper version to use
1395 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1396 if (P
.end() == true)
1398 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1399 if (V
.end() == false)
1401 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1402 //FIXME: packages without a description can't be found
1403 if (D
.end() == true)
1405 DFList
[G
->ID
].Df
= D
.FileList();
1406 DFList
[G
->ID
].ID
= G
->ID
;
1409 if (unmatched
== NumPatterns
)
1412 // Include all the packages that provide matching names too
1413 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1415 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1416 if (V
.end() == true)
1419 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1420 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1421 //FIXME: packages without a description can't be found
1422 if (D
.end() == true)
1424 DFList
[id
].Df
= D
.FileList();
1427 size_t const PrvPatternOffset
= id
* NumPatterns
;
1428 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1429 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1433 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1435 // Create the text record parser
1436 pkgRecords
Recs(*Cache
);
1437 // Iterate over all the version records and check them
1438 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1440 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1441 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1443 if (NamesOnly
== false)
1445 string
const LongDesc
= P
.LongDesc();
1446 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1448 if (PatternMatch
[PatternOffset
+ I
] == true)
1450 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1451 PatternMatch
[PatternOffset
+ I
] = true;
1455 bool matchedAll
= true;
1456 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1457 if (PatternMatch
[PatternOffset
+ I
] == false)
1463 if (matchedAll
== true)
1465 if (ShowFull
== true)
1469 P
.GetRec(Start
,End
);
1470 fwrite(Start
,End
-Start
,1,stdout
);
1474 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1479 delete [] PatternMatch
;
1480 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1481 regfree(&Patterns
[I
]);
1483 return _error
->Error("Write to stdout failed");
1487 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1488 static bool ShowAuto(CommandLine
&)
1490 pkgCacheFile CacheFile
;
1491 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1492 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1493 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1496 std::vector
<string
> packages
;
1497 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1499 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1500 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1501 packages
.push_back(P
.Name());
1503 std::sort(packages
.begin(), packages
.end());
1505 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1508 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1512 // ShowPackage - Dump the package record to the screen /*{{{*/
1513 // ---------------------------------------------------------------------
1515 static bool ShowPackage(CommandLine
&CmdL
)
1517 pkgCacheFile CacheFile
;
1518 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1519 APT::CacheSetHelper::VerSelector
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1520 APT::CacheSetHelper::ALL
: APT::CacheSetHelper::CANDIDATE
;
1521 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1522 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1523 if (DisplayRecord(CacheFile
, Ver
) == false)
1526 if (verset
.empty() == true)
1528 if (helper
.virtualPkgs
.empty() == true)
1529 return _error
->Error(_("No packages found"));
1531 _error
->Notice(_("No packages found"));
1536 // ShowPkgNames - Show package names /*{{{*/
1537 // ---------------------------------------------------------------------
1538 /* This does a prefix match on the first argument */
1539 static bool ShowPkgNames(CommandLine
&CmdL
)
1541 pkgCacheFile CacheFile
;
1542 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1544 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1545 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1547 if (CmdL
.FileList
[1] != 0)
1549 for (;I
.end() != true; ++I
)
1551 if (All
== false && I
->FirstPackage
== 0)
1553 if (I
.FindPkg("any")->VersionList
== 0)
1555 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1556 cout
<< I
.Name() << endl
;
1563 for (;I
.end() != true; ++I
)
1565 if (All
== false && I
->FirstPackage
== 0)
1567 if (I
.FindPkg("any")->VersionList
== 0)
1569 cout
<< I
.Name() << endl
;
1575 // ShowSrcPackage - Show source package records /*{{{*/
1576 // ---------------------------------------------------------------------
1578 static bool ShowSrcPackage(CommandLine
&CmdL
)
1580 pkgCacheFile CacheFile
;
1581 pkgSourceList
*List
= CacheFile
.GetSourceList();
1582 if (unlikely(List
== NULL
))
1585 // Create the text record parsers
1586 pkgSrcRecords
SrcRecs(*List
);
1587 if (_error
->PendingError() == true)
1591 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1595 pkgSrcRecords::Parser
*Parse
;
1596 unsigned found_this
= 0;
1597 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1598 cout
<< Parse
->AsStr() << endl
;;
1602 if (found_this
== 0) {
1603 _error
->Warning(_("Unable to locate package %s"),*I
);
1608 _error
->Notice(_("No packages found"));
1612 // Policy - Show the results of the preferences file /*{{{*/
1613 // ---------------------------------------------------------------------
1615 static bool Policy(CommandLine
&CmdL
)
1617 pkgCacheFile CacheFile
;
1618 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1619 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1620 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1621 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1624 /* Should the MultiArchKiller be run to see which pseudo packages for an
1625 arch all package are currently installed? Activating it gives a speed
1626 penality for no real gain beside enhanced debugging, so in general no. */
1627 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1628 CacheFile
.GetDepCache();
1630 // Print out all of the package files
1631 if (CmdL
.FileList
[1] == 0)
1633 cout
<< _("Package files:") << endl
;
1634 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1636 // Locate the associated index files so we can derive a description
1638 if (SrcList
->FindIndex(F
,Indx
) == false &&
1639 _system
->FindIndex(F
,Indx
) == false)
1640 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1643 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1645 // Print the reference information for the package
1646 string Str
= F
.RelStr();
1647 if (Str
.empty() == false)
1648 printf(" release %s\n",F
.RelStr().c_str());
1649 if (F
.Site() != 0 && F
.Site()[0] != 0)
1650 printf(" origin %s\n",F
.Site());
1653 // Show any packages have explicit pins
1654 cout
<< _("Pinned packages:") << endl
;
1655 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1656 for (;I
.end() != true; ++I
)
1658 if (Plcy
->GetPriority(I
) == 0)
1661 // Print the package name and the version we are forcing to
1662 cout
<< " " << I
.FullName(true) << " -> ";
1664 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1665 if (V
.end() == true)
1666 cout
<< _("(not found)") << endl
;
1668 cout
<< V
.VerStr() << endl
;
1674 char const * const msgInstalled
= _(" Installed: ");
1675 char const * const msgCandidate
= _(" Candidate: ");
1676 short const InstalledLessCandidate
=
1677 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1678 short const deepInstalled
=
1679 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1680 short const deepCandidate
=
1681 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1683 // Print out detailed information for each package
1684 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1685 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1686 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1688 cout
<< Pkg
.FullName(true) << ":" << endl
;
1690 // Installed version
1691 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1692 if (Pkg
->CurrentVer
== 0)
1693 cout
<< _("(none)") << endl
;
1695 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1697 // Candidate Version
1698 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1699 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1700 if (V
.end() == true)
1701 cout
<< _("(none)") << endl
;
1703 cout
<< V
.VerStr() << endl
;
1706 if (Plcy
->GetPriority(Pkg
) != 0)
1708 cout
<< _(" Package pin: ");
1709 V
= Plcy
->GetMatch(Pkg
);
1710 if (V
.end() == true)
1711 cout
<< _("(not found)") << endl
;
1713 cout
<< V
.VerStr() << endl
;
1716 // Show the priority tables
1717 cout
<< _(" Version table:") << endl
;
1718 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1720 if (Pkg
.CurrentVer() == V
)
1721 cout
<< " *** " << V
.VerStr();
1723 cout
<< " " << V
.VerStr();
1724 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1725 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1727 // Locate the associated index files so we can derive a description
1729 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1730 _system
->FindIndex(VF
.File(),Indx
) == false)
1731 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1732 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1733 Indx
->Describe(true).c_str());
1741 // Madison - Look a bit like katie's madison /*{{{*/
1742 // ---------------------------------------------------------------------
1744 static bool Madison(CommandLine
&CmdL
)
1746 pkgCacheFile CacheFile
;
1747 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1752 // Create the src text record parsers and ignore errors about missing
1753 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1754 pkgSrcRecords
SrcRecs(*SrcList
);
1755 if (_error
->PendingError() == true)
1758 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1759 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1761 _error
->PushToStack();
1762 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1763 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1765 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1767 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1769 // This might be nice, but wouldn't uniquely identify the source -mdz
1770 // if (VF.File().Archive() != 0)
1772 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1773 // << VF.File().Archive() << endl;
1776 // Locate the associated index files so we can derive a description
1777 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1779 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1780 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1781 IF
!= Indexes
->end(); ++IF
)
1783 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1785 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1786 << (*IF
)->Describe(true) << endl
;
1795 pkgSrcRecords::Parser
*SrcParser
;
1796 bool foundSomething
= false;
1797 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1799 foundSomething
= true;
1800 // Maybe support Release info here too eventually
1801 cout
<< setw(10) << SrcParser
->Package() << " | "
1802 << setw(10) << SrcParser
->Version() << " | "
1803 << SrcParser
->Index().Describe(true) << endl
;
1805 if (foundSomething
== true)
1806 _error
->RevertToStack();
1808 _error
->MergeWithStack();
1814 // GenCaches - Call the main cache generator /*{{{*/
1815 // ---------------------------------------------------------------------
1817 static bool GenCaches(CommandLine
&)
1819 OpTextProgress
Progress(*_config
);
1821 pkgCacheFile CacheFile
;
1822 return CacheFile
.BuildCaches(&Progress
, true);
1825 // ShowHelp - Show a help screen /*{{{*/
1826 // ---------------------------------------------------------------------
1828 static bool ShowHelp(CommandLine
&)
1830 ioprintf(cout
, "%s %s (%s)\n", PACKAGE
, PACKAGE_VERSION
, COMMON_ARCH
);
1832 if (_config
->FindB("version") == true)
1836 _("Usage: apt-cache [options] command\n"
1837 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1838 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1840 "apt-cache is a low-level tool used to query information\n"
1841 "from APT's binary cache files\n"
1844 " gencaches - Build both the package and source cache\n"
1845 " showpkg - Show some general information for a single package\n"
1846 " showsrc - Show source records\n"
1847 " stats - Show some basic statistics\n"
1848 " dump - Show the entire file in a terse form\n"
1849 " dumpavail - Print an available file to stdout\n"
1850 " unmet - Show unmet dependencies\n"
1851 " search - Search the package list for a regex pattern\n"
1852 " show - Show a readable record for the package\n"
1853 " depends - Show raw dependency information for a package\n"
1854 " rdepends - Show reverse dependency information for a package\n"
1855 " pkgnames - List the names of all packages in the system\n"
1856 " dotty - Generate package graphs for GraphViz\n"
1857 " xvcg - Generate package graphs for xvcg\n"
1858 " policy - Show policy settings\n"
1861 " -h This help text.\n"
1862 " -p=? The package cache.\n"
1863 " -s=? The source cache.\n"
1864 " -q Disable progress indicator.\n"
1865 " -i Show only important deps for the unmet command.\n"
1866 " -c=? Read this configuration file\n"
1867 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1868 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1872 int main(int argc
,const char *argv
[]) /*{{{*/
1874 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1875 {"gencaches",&GenCaches
},
1876 {"showsrc",&ShowSrcPackage
},
1877 {"showpkg",&DumpPackage
},
1880 {"dumpavail",&DumpAvail
},
1883 {"depends",&Depends
},
1884 {"rdepends",&RDepends
},
1887 {"show",&ShowPackage
},
1888 {"pkgnames",&ShowPkgNames
},
1889 {"showauto",&ShowAuto
},
1891 {"madison",&Madison
},
1894 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1896 // Set up gettext support
1897 setlocale(LC_ALL
,"");
1898 textdomain(PACKAGE
);
1900 // Parse the command line and initialize the package library
1902 ParseCommandLine(CmdL
, Cmds
, Args
.data(), &_config
, &_system
, argc
, argv
, ShowHelp
);
1906 if (_config
->Exists("APT::Cache::Generate") == true)
1907 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1909 // Match the operation
1910 CmdL
.DispatchArg(Cmds
);
1912 // Print any errors or warnings found during parsing
1913 bool const Errors
= _error
->PendingError();
1914 if (_config
->FindI("quiet",0) > 0)
1915 _error
->DumpErrors();
1917 _error
->DumpErrors(GlobalError::DEBUG
);
1918 return Errors
== true ? 100 : 0;