]>
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) << " (= " << (Prv
->ProvideVersion
== 0 ? "" : Prv
.ProvideVersion()) << ") ";
259 cout
<< "Reverse Provides: " << endl
;
260 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
261 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << " (= " << (Prv
->ProvideVersion
== 0 ? "" : Prv
.ProvideVersion()) << ")"<< endl
;
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
&CmdL
)
315 pkgCacheFile CacheFile
;
316 pkgCache
*Cache
= CacheFile
.GetPkgCache();
318 if (CmdL
.FileSize() > 1) {
319 _error
->Error(_("apt-cache stats does not take any arguments"));
322 if (unlikely(Cache
== NULL
))
325 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
326 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
327 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
328 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
335 pkgCache::PkgIterator I
= Cache
->PkgBegin();
336 for (;I
.end() != true; ++I
)
338 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
344 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
350 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
353 if (I
.ProvidesList()->NextProvides
== 0)
361 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
367 cout
<< _(" Normal packages: ") << Normal
<< endl
;
368 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
369 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
370 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
371 cout
<< _(" Missing: ") << Missing
<< endl
;
373 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
374 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
375 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
376 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
377 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< "/" << Cache
->Head().DependsDataCount
<< " (" <<
378 SizeToStr((Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) +
379 (Cache
->Head().DependsDataCount
*Cache
->Head().DependencyDataSz
)) << ')' << endl
;
380 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
381 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
382 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
383 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
384 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
385 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
388 std::set
<map_stringitem_t
> stritems
;
389 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
390 stritems
.insert(G
->Name
);
391 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
393 stritems
.insert(P
->Arch
);
394 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
397 stritems
.insert(V
->VerStr
);
399 stritems
.insert(V
->Section
);
400 stritems
.insert(V
->SourcePkgName
);
401 stritems
.insert(V
->SourceVerStr
);
402 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
405 stritems
.insert(D
->Version
);
407 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
409 stritems
.insert(D
->md5sum
);
410 stritems
.insert(D
->language_code
);
413 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
415 if (Prv
->ProvideVersion
!= 0)
416 stritems
.insert(Prv
->ProvideVersion
);
419 for (pkgCache::RlsFileIterator F
= Cache
->RlsFileBegin(); F
!= Cache
->RlsFileEnd(); ++F
)
421 stritems
.insert(F
->FileName
);
422 stritems
.insert(F
->Archive
);
423 stritems
.insert(F
->Codename
);
424 stritems
.insert(F
->Version
);
425 stritems
.insert(F
->Origin
);
426 stritems
.insert(F
->Label
);
427 stritems
.insert(F
->Site
);
429 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
431 stritems
.insert(F
->FileName
);
432 stritems
.insert(F
->Architecture
);
433 stritems
.insert(F
->Component
);
434 stritems
.insert(F
->IndexType
);
437 unsigned long Size
= 0;
438 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
439 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
440 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
443 unsigned long Slack
= 0;
444 for (int I
= 0; I
!= 7; I
++)
445 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
446 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
448 unsigned long Total
= 0;
449 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
450 Total
= Slack
+ Size
+
451 APT_CACHESIZE(GroupCount
, GroupSz
) +
452 APT_CACHESIZE(PackageCount
, PackageSz
) +
453 APT_CACHESIZE(VersionCount
, VersionSz
) +
454 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
455 APT_CACHESIZE(DependsCount
, DependencySz
) +
456 APT_CACHESIZE(DependsDataCount
, DependencyDataSz
) +
457 APT_CACHESIZE(ReleaseFileCount
, ReleaseFileSz
) +
458 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
459 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
460 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
461 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
462 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
463 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
467 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
468 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
473 // Dump - show everything /*{{{*/
474 // ---------------------------------------------------------------------
475 /* This is worthless except fer debugging things */
476 static bool Dump(CommandLine
&)
478 pkgCacheFile CacheFile
;
479 pkgCache
*Cache
= CacheFile
.GetPkgCache();
480 if (unlikely(Cache
== NULL
))
483 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
485 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
487 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
488 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
490 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
491 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
492 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
493 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
494 DeNull(D
.TargetVer()) << std::endl
;
495 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
497 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
498 << " File: " << D
.FileList().File().FileName() << std::endl
499 << " MD5: " << D
.md5() << std::endl
;
504 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
506 std::cout
<< "File: " << F
.FileName() << std::endl
;
507 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
508 std::cout
<< " Size: " << F
->Size
<< std::endl
;
509 std::cout
<< " ID: " << F
->ID
<< std::endl
;
510 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
511 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
512 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
513 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
514 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
515 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
516 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
517 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
518 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
524 // DumpAvail - Print out the available list /*{{{*/
525 // ---------------------------------------------------------------------
526 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
527 make this run really fast, perhaps I went a little overboard.. */
528 static bool DumpAvail(CommandLine
&)
530 pkgCacheFile CacheFile
;
531 pkgCache
*Cache
= CacheFile
.GetPkgCache();
532 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
535 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
536 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
537 memset(VFList
,0,sizeof(*VFList
)*Count
);
539 // Map versions that we want to write out onto the VerList array.
540 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
542 if (P
->VersionList
== 0)
545 /* Find the proper version to use. If the policy says there are no
546 possible selections we return the installed version, if available..
547 This prevents dselect from making it obsolete. */
548 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
551 if (P
->CurrentVer
== 0)
556 pkgCache::VerFileIterator VF
= V
.FileList();
557 for (; VF
.end() == false ; ++VF
)
558 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
561 /* Okay, here we have a bit of a problem.. The policy has selected the
562 currently installed package - however it only exists in the
563 status file.. We need to write out something or dselect will mark
564 the package as obsolete! Thus we emit the status file entry, but
565 below we remove the status line to make it valid for the
566 available file. However! We only do this if their do exist *any*
567 non-source versions of the package - that way the dselect obsolete
568 handling works OK. */
569 if (VF
.end() == true)
571 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
573 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
575 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
582 if (VF
.end() == false)
590 LocalitySort(VFList
,Count
,sizeof(*VFList
));
592 std::vector
<pkgTagSection::Tag
> RW
;
593 RW
.push_back(pkgTagSection::Tag::Remove("Status"));
594 RW
.push_back(pkgTagSection::Tag::Remove("Config-Version"));
596 stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
, false);
598 // Iterate over all the package files and write them out.
599 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
600 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
602 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
603 if (File
.IsOk() == false)
605 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
609 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
610 if (_error
->PendingError() == true)
613 /* Write all of the records from this package file, since we
614 already did locality sorting we can now just seek through the
615 file in read order. We apply 1 more optimization here, since often
616 there will be < 1 byte gaps between records (for the \n) we read that
617 into the next buffer and offset a bit.. */
618 unsigned long Pos
= 0;
621 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
624 const pkgCache::VerFile
&VF
= **J
;
626 // Read the record and then write it out again.
627 unsigned long Jitter
= VF
.Offset
- Pos
;
630 if (PkgF
.Seek(VF
.Offset
) == false)
635 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
637 Buffer
[VF
.Size
+ Jitter
] = '\n';
640 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
643 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
644 Tags
.Write(stdoutfd
, NULL
, RW
) == false ||
645 stdoutfd
.Write("\n", 1) == false)
647 _error
->Error("Internal Error, Unable to parse a package record");
653 if (stdoutfd
.Write(Buffer
+ Jitter
, VF
.Size
+ 1) == false)
657 Pos
= VF
.Offset
+ VF
.Size
;
660 if (_error
->PendingError() == true)
666 return !_error
->PendingError();
669 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
670 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
672 pkgCacheFile CacheFile
;
673 pkgCache
*Cache
= CacheFile
.GetPkgCache();
674 if (unlikely(Cache
== NULL
))
677 CacheSetHelperVirtuals
helper(false);
678 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
679 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
680 return _error
->Error(_("No packages found"));
681 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
683 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
684 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
685 bool const Important
= _config
->FindB("APT::Cache::Important", false);
686 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
687 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
688 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
689 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
690 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
691 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
692 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
693 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
694 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
695 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
696 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
697 bool const ShowImplicit
= _config
->FindB("APT::Cache::ShowImplicit", false);
699 while (verset
.empty() != true)
701 pkgCache::VerIterator Ver
= *verset
.begin();
702 verset
.erase(verset
.begin());
703 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
704 Shown
[Pkg
->ID
] = true;
706 cout
<< Pkg
.FullName(true) << endl
;
708 if (RevDepends
== true)
709 cout
<< "Reverse Depends:" << endl
;
710 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
711 D
.end() == false; ++D
)
714 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
715 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
716 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
717 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
718 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
719 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
720 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
721 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
723 if (ShowImplicit
== false && D
.IsImplicit())
726 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
727 bool const showNoArch
= RevDepends
|| (D
->CompareOp
& pkgCache::Dep::ArchSpecific
) != pkgCache::Dep::ArchSpecific
;
729 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
732 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
738 if (ShowDepType
== true)
739 cout
<< D
.DepType() << ": ";
740 if (Trg
->VersionList
== 0)
741 cout
<< "<" << Trg
.FullName(showNoArch
) << ">";
743 cout
<< Trg
.FullName(showNoArch
);
744 if (ShowVersion
== true && D
->Version
!= 0)
745 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
748 if (Recurse
== true && Shown
[Trg
->ID
] == false)
750 Shown
[Trg
->ID
] = true;
751 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::CacheSetHelper::CANDIDATE
, helper
));
756 // Display all solutions
757 std::unique_ptr
<pkgCache::Version
*[]> List(D
.AllTargets());
758 pkgPrioSortList(*Cache
,List
.get());
759 for (pkgCache::Version
**I
= List
.get(); *I
!= 0; I
++)
761 pkgCache::VerIterator
V(*Cache
,*I
);
762 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
763 V
->ParentPkg
== D
->Package
)
765 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
767 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
769 Shown
[V
.ParentPkg()->ID
] = true;
770 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::CacheSetHelper::CANDIDATE
, helper
));
774 if (ShowOnlyFirstOr
== true)
775 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
779 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
780 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
781 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
786 // Depends - Print out a dependency tree /*{{{*/
787 // ---------------------------------------------------------------------
789 static bool Depends(CommandLine
&CmdL
)
791 return ShowDepends(CmdL
, false);
794 // RDepends - Print out a reverse dependency tree /*{{{*/
795 // ---------------------------------------------------------------------
797 static bool RDepends(CommandLine
&CmdL
)
799 return ShowDepends(CmdL
, true);
802 // xvcg - Generate a graph for xvcg /*{{{*/
803 // ---------------------------------------------------------------------
804 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
806 static bool XVcg(CommandLine
&CmdL
)
808 pkgCacheFile CacheFile
;
809 pkgCache
*Cache
= CacheFile
.GetPkgCache();
810 if (unlikely(Cache
== NULL
))
813 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
815 /* Normal packages are boxes
816 Pure Provides are triangles
818 rhomb are missing packages*/
819 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
821 /* Initialize the list of packages to show.
823 2 = To Show no recurse
824 3 = Emitted no recurse
827 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
828 enum TheFlags
{ForceNR
=(1<<0)};
829 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
830 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
831 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
833 // Show everything if no arguments given
834 if (CmdL
.FileList
[1] == 0)
835 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
838 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
840 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
843 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
845 if (Pkg
->VersionList
== 0)
848 if (Pkg
->ProvidesList
== 0)
849 ShapeMap
[Pkg
->ID
] = 0;
851 ShapeMap
[Pkg
->ID
] = 1;
856 if (Pkg
->ProvidesList
== 0)
857 ShapeMap
[Pkg
->ID
] = 2;
859 ShapeMap
[Pkg
->ID
] = 3;
863 // Load the list of packages from the command line into the show list
864 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
865 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
866 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
867 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
868 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
869 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
871 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
872 Pkg
!= pkgsets
[0].end(); ++Pkg
)
873 Show
[Pkg
->ID
] = ToShow
;
874 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
875 Pkg
!= pkgsets
[1].end(); ++Pkg
)
877 Show
[Pkg
->ID
] = ToShow
;
878 Flags
[Pkg
->ID
] |= ForceNR
;
882 cout
<< "graph: { title: \"packages\"" << endl
<<
883 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
884 "layout_downfactor: 8" << endl
;
890 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
892 // See we need to show this package
893 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
896 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
899 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
901 // Pure Provides and missing packages have no deps!
902 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
903 Show
[Pkg
->ID
] = Done
;
905 Show
[Pkg
->ID
] = DoneNR
;
908 Show
[Pkg
->ID
] = Done
;
911 // No deps to map out
912 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
915 pkgCache::VerIterator Ver
= Pkg
.VersionList();
916 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
918 // See if anything can meet this dep
919 // Walk along the actual package providing versions
921 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
922 for (pkgCache::VerIterator I
= DPkg
.VersionList();
923 I
.end() == false && Hit
== false; ++I
)
925 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
929 // Follow all provides
930 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
931 I
.end() == false && Hit
== false; ++I
)
933 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
938 // Only graph critical deps
939 if (D
.IsCritical() == true)
941 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
943 // Colour the node for recursion
944 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
946 /* If a conflicts does not meet anything in the database
947 then show the relation but do not recurse */
948 if (Hit
== false && D
.IsNegative() == true)
950 if (Show
[D
.TargetPkg()->ID
] == None
&&
951 Show
[D
.TargetPkg()->ID
] != ToShow
)
952 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
956 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
957 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
959 Show
[D
.TargetPkg()->ID
] = ToShow
;
966 case pkgCache::Dep::Conflicts
:
967 printf("label: \"conflicts\" color: lightgreen }\n");
969 case pkgCache::Dep::DpkgBreaks
:
970 printf("label: \"breaks\" color: lightgreen }\n");
972 case pkgCache::Dep::Obsoletes
:
973 printf("label: \"obsoletes\" color: lightgreen }\n");
976 case pkgCache::Dep::PreDepends
:
977 printf("label: \"predepends\" color: blue }\n");
989 /* Draw the box colours after the fact since we can not tell what colour
990 they should be until everything is finished drawing */
991 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
993 if (Show
[Pkg
->ID
] < DoneNR
)
996 if (Show
[Pkg
->ID
] == DoneNR
)
997 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
998 Shapes
[ShapeMap
[Pkg
->ID
]]);
1000 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
1001 Shapes
[ShapeMap
[Pkg
->ID
]]);
1013 // Dotty - Generate a graph for Dotty /*{{{*/
1014 // ---------------------------------------------------------------------
1015 /* Dotty is the graphvis program for generating graphs. It is a fairly
1016 simple queuing algorithm that just writes dependencies and nodes.
1017 http://www.research.att.com/sw/tools/graphviz/ */
1018 static bool Dotty(CommandLine
&CmdL
)
1020 pkgCacheFile CacheFile
;
1021 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1022 if (unlikely(Cache
== NULL
))
1025 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1027 /* Normal packages are boxes
1028 Pure Provides are triangles
1030 Hexagons are missing packages*/
1031 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1033 /* Initialize the list of packages to show.
1035 2 = To Show no recurse
1036 3 = Emitted no recurse
1039 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1040 enum TheFlags
{ForceNR
=(1<<0)};
1041 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1042 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1043 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1045 // Show everything if no arguments given
1046 if (CmdL
.FileList
[1] == 0)
1047 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1050 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1052 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1055 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1057 if (Pkg
->VersionList
== 0)
1060 if (Pkg
->ProvidesList
== 0)
1061 ShapeMap
[Pkg
->ID
] = 0;
1063 ShapeMap
[Pkg
->ID
] = 1;
1068 if (Pkg
->ProvidesList
== 0)
1069 ShapeMap
[Pkg
->ID
] = 2;
1071 ShapeMap
[Pkg
->ID
] = 3;
1075 // Load the list of packages from the command line into the show list
1076 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1077 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
1078 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1079 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1080 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1081 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1083 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1084 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1085 Show
[Pkg
->ID
] = ToShow
;
1086 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1087 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1089 Show
[Pkg
->ID
] = ToShow
;
1090 Flags
[Pkg
->ID
] |= ForceNR
;
1094 printf("digraph packages {\n");
1095 printf("concentrate=true;\n");
1096 printf("size=\"30,40\";\n");
1102 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1104 // See we need to show this package
1105 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1109 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1111 // Pure Provides and missing packages have no deps!
1112 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1113 Show
[Pkg
->ID
] = Done
;
1115 Show
[Pkg
->ID
] = DoneNR
;
1118 Show
[Pkg
->ID
] = Done
;
1121 // No deps to map out
1122 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1125 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1126 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1128 // See if anything can meet this dep
1129 // Walk along the actual package providing versions
1131 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1132 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1133 I
.end() == false && Hit
== false; ++I
)
1135 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1139 // Follow all provides
1140 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1141 I
.end() == false && Hit
== false; ++I
)
1143 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1147 // Only graph critical deps
1148 if (D
.IsCritical() == true)
1150 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1152 // Colour the node for recursion
1153 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1155 /* If a conflicts does not meet anything in the database
1156 then show the relation but do not recurse */
1157 if (Hit
== false && D
.IsNegative() == true)
1159 if (Show
[D
.TargetPkg()->ID
] == None
&&
1160 Show
[D
.TargetPkg()->ID
] != ToShow
)
1161 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1165 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1166 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1168 Show
[D
.TargetPkg()->ID
] = ToShow
;
1175 case pkgCache::Dep::Conflicts
:
1176 case pkgCache::Dep::Obsoletes
:
1177 case pkgCache::Dep::DpkgBreaks
:
1178 printf("[color=springgreen];\n");
1181 case pkgCache::Dep::PreDepends
:
1182 printf("[color=blue];\n");
1194 /* Draw the box colours after the fact since we can not tell what colour
1195 they should be until everything is finished drawing */
1196 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1198 if (Show
[Pkg
->ID
] < DoneNR
)
1201 // Orange box for early recursion stoppage
1202 if (Show
[Pkg
->ID
] == DoneNR
)
1203 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1204 Shapes
[ShapeMap
[Pkg
->ID
]]);
1206 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1207 Shapes
[ShapeMap
[Pkg
->ID
]]);
1217 // DisplayRecord - Displays the complete record for the package /*{{{*/
1218 // ---------------------------------------------------------------------
1219 /* This displays the package record from the proper package index file.
1220 It is not used by DumpAvail for performance reasons. */
1222 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1224 char const * const TagName
= "\nDescription";
1225 size_t const TagLen
= strlen(TagName
);
1226 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1228 if (DescP
[1] == ' ')
1230 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1239 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1241 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1242 if (unlikely(Cache
== NULL
))
1245 // Find an appropriate file
1246 pkgCache::VerFileIterator Vf
= V
.FileList();
1247 for (; Vf
.end() == false; ++Vf
)
1248 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1250 if (Vf
.end() == true)
1253 // Check and load the package list file
1254 pkgCache::PkgFileIterator I
= Vf
.File();
1255 if (I
.IsOk() == false)
1256 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1259 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1262 // Read the record (and ensure that it ends with a newline and NUL)
1263 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1264 Buffer
[Vf
->Size
] = '\n';
1265 Buffer
[Vf
->Size
+1] = '\0';
1266 if (PkgF
.Seek(Vf
->Offset
) == false ||
1267 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1273 // Get a pointer to start of Description field
1274 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1278 DescP
= Buffer
+ Vf
->Size
;
1280 // Write all but Description
1281 size_t const length
= DescP
- Buffer
;
1282 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1288 // Show the right description
1289 pkgRecords
Recs(*Cache
);
1290 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1291 if (Desc
.end() == false)
1293 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1294 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1295 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1297 // Find the first field after the description (if there is any)
1298 DescP
= skipDescriptionFields(DescP
);
1300 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1302 // write the rest of the buffer, but skip mixed in Descriptions* fields
1303 while (DescP
!= NULL
)
1305 const unsigned char * const Start
= DescP
;
1306 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1309 End
= &Buffer
[Vf
->Size
];
1314 ++End
; // get the newline into the output
1315 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1317 size_t const length
= End
- Start
;
1318 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1325 // write a final newline after the last field
1334 pkgCache::DescFile
*Df
;
1338 // Search - Perform a search /*{{{*/
1339 // ---------------------------------------------------------------------
1340 /* This searches the package names and package descriptions for a pattern */
1341 static bool Search(CommandLine
&CmdL
)
1343 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1344 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1345 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1347 pkgCacheFile CacheFile
;
1348 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1349 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1350 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1353 // Make sure there is at least one argument
1354 if (NumPatterns
< 1)
1355 return _error
->Error(_("You must give at least one search pattern"));
1357 // Compile the regex pattern
1358 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1359 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1360 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1362 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1366 regfree(&Patterns
[I
]);
1367 return _error
->Error("Regex compilation error");
1371 if (_error
->PendingError() == true)
1373 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1374 regfree(&Patterns
[I
]);
1378 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1379 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1380 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1382 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1383 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1385 // Map versions that we want to write out onto the VerList array.
1386 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1388 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1389 size_t unmatched
= 0, matched
= 0;
1390 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1392 if (PatternMatch
[PatternOffset
+ I
] == true)
1394 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1395 PatternMatch
[PatternOffset
+ I
] = true;
1400 // already dealt with this package?
1401 if (matched
== NumPatterns
)
1404 // Doing names only, drop any that don't match..
1405 if (NamesOnly
== true && unmatched
== NumPatterns
)
1408 // Find the proper version to use
1409 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1410 if (P
.end() == true)
1412 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1413 if (V
.end() == false)
1415 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1416 //FIXME: packages without a description can't be found
1417 if (D
.end() == true)
1419 DFList
[G
->ID
].Df
= D
.FileList();
1420 DFList
[G
->ID
].ID
= G
->ID
;
1423 if (unmatched
== NumPatterns
)
1426 // Include all the packages that provide matching names too
1427 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1429 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1430 if (V
.end() == true)
1433 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1434 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1435 //FIXME: packages without a description can't be found
1436 if (D
.end() == true)
1438 DFList
[id
].Df
= D
.FileList();
1441 size_t const PrvPatternOffset
= id
* NumPatterns
;
1442 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1443 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1447 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1449 // Create the text record parser
1450 pkgRecords
Recs(*Cache
);
1451 // Iterate over all the version records and check them
1452 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1454 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1455 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1457 if (NamesOnly
== false)
1459 string
const LongDesc
= P
.LongDesc();
1460 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1462 if (PatternMatch
[PatternOffset
+ I
] == true)
1464 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1465 PatternMatch
[PatternOffset
+ I
] = true;
1469 bool matchedAll
= true;
1470 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1471 if (PatternMatch
[PatternOffset
+ I
] == false)
1477 if (matchedAll
== true)
1479 if (ShowFull
== true)
1483 P
.GetRec(Start
,End
);
1484 fwrite(Start
,End
-Start
,1,stdout
);
1488 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1493 delete [] PatternMatch
;
1494 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1495 regfree(&Patterns
[I
]);
1498 return _error
->Error("Write to stdout failed");
1502 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1503 static bool ShowAuto(CommandLine
&)
1505 pkgCacheFile CacheFile
;
1506 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1507 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1508 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1511 std::vector
<string
> packages
;
1512 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1514 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1515 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1516 packages
.push_back(P
.Name());
1518 std::sort(packages
.begin(), packages
.end());
1520 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1523 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1527 // ShowPackage - Dump the package record to the screen /*{{{*/
1528 // ---------------------------------------------------------------------
1530 static bool ShowPackage(CommandLine
&CmdL
)
1532 pkgCacheFile CacheFile
;
1533 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1534 APT::CacheSetHelper::VerSelector
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1535 APT::CacheSetHelper::ALL
: APT::CacheSetHelper::CANDIDATE
;
1536 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1537 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1538 if (DisplayRecord(CacheFile
, Ver
) == false)
1541 if (verset
.empty() == true)
1543 if (helper
.virtualPkgs
.empty() == true)
1544 return _error
->Error(_("No packages found"));
1546 _error
->Notice(_("No packages found"));
1551 // ShowPkgNames - Show package names /*{{{*/
1552 // ---------------------------------------------------------------------
1553 /* This does a prefix match on the first argument */
1554 static bool ShowPkgNames(CommandLine
&CmdL
)
1556 pkgCacheFile CacheFile
;
1557 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1559 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1560 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1562 if (CmdL
.FileList
[1] != 0)
1564 for (;I
.end() != true; ++I
)
1566 if (All
== false && I
->FirstPackage
== 0)
1568 if (I
.FindPkg("any")->VersionList
== 0)
1570 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1571 cout
<< I
.Name() << endl
;
1578 for (;I
.end() != true; ++I
)
1580 if (All
== false && I
->FirstPackage
== 0)
1582 if (I
.FindPkg("any")->VersionList
== 0)
1584 cout
<< I
.Name() << endl
;
1590 // ShowSrcPackage - Show source package records /*{{{*/
1591 // ---------------------------------------------------------------------
1593 static bool ShowSrcPackage(CommandLine
&CmdL
)
1595 pkgCacheFile CacheFile
;
1596 pkgSourceList
*List
= CacheFile
.GetSourceList();
1597 if (unlikely(List
== NULL
))
1600 // Create the text record parsers
1601 pkgSrcRecords
SrcRecs(*List
);
1602 if (_error
->PendingError() == true)
1606 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1610 pkgSrcRecords::Parser
*Parse
;
1611 unsigned found_this
= 0;
1612 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1613 cout
<< Parse
->AsStr() << endl
;;
1617 if (found_this
== 0) {
1618 _error
->Warning(_("Unable to locate package %s"),*I
);
1623 _error
->Notice(_("No packages found"));
1627 // Policy - Show the results of the preferences file /*{{{*/
1628 // ---------------------------------------------------------------------
1630 static bool Policy(CommandLine
&CmdL
)
1632 pkgCacheFile CacheFile
;
1633 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1634 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1635 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1636 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1639 /* Should the MultiArchKiller be run to see which pseudo packages for an
1640 arch all package are currently installed? Activating it gives a speed
1641 penality for no real gain beside enhanced debugging, so in general no. */
1642 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1643 CacheFile
.GetDepCache();
1645 // Print out all of the package files
1646 if (CmdL
.FileList
[1] == 0)
1648 cout
<< _("Package files:") << endl
;
1649 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1651 if (F
.Flagged(pkgCache::Flag::NoPackages
))
1653 // Locate the associated index files so we can derive a description
1655 if (SrcList
->FindIndex(F
,Indx
) == false &&
1656 _system
->FindIndex(F
,Indx
) == false)
1657 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1660 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1662 // Print the reference information for the package
1663 string Str
= F
.RelStr();
1664 if (Str
.empty() == false)
1665 printf(" release %s\n",F
.RelStr().c_str());
1666 if (F
.Site() != 0 && F
.Site()[0] != 0)
1667 printf(" origin %s\n",F
.Site());
1670 // Show any packages have explicit pins
1671 cout
<< _("Pinned packages:") << endl
;
1672 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1673 for (;I
.end() != true; ++I
)
1675 // Old code for debugging
1676 if (_config
->FindI("APT::Policy", 1) < 1) {
1677 if (Plcy
->GetPriority(I
) == 0)
1680 // Print the package name and the version we are forcing to
1681 cout
<< " " << I
.FullName(true) << " -> ";
1683 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1684 if (V
.end() == true)
1685 cout
<< _("(not found)") << endl
;
1687 cout
<< V
.VerStr() << endl
;
1692 for (pkgCache::VerIterator V
= I
.VersionList(); !V
.end(); V
++) {
1693 auto Prio
= Plcy
->GetPriority(V
, false);
1698 // Print the package name and the version we are forcing to
1699 ioprintf(cout
, _("%s -> %s with priority %d\n"), I
.FullName(true).c_str(), V
.VerStr(), Prio
);
1705 char const * const msgInstalled
= _(" Installed: ");
1706 char const * const msgCandidate
= _(" Candidate: ");
1707 short const InstalledLessCandidate
=
1708 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1709 short const deepInstalled
=
1710 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1711 short const deepCandidate
=
1712 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1714 // Print out detailed information for each package
1715 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1716 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1717 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1719 cout
<< Pkg
.FullName(true) << ":" << endl
;
1721 // Installed version
1722 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1723 if (Pkg
->CurrentVer
== 0)
1724 cout
<< _("(none)") << endl
;
1726 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1728 // Candidate Version
1729 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1730 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1731 if (V
.end() == true)
1732 cout
<< _("(none)") << endl
;
1734 cout
<< V
.VerStr() << endl
;
1737 if (_config
->FindI("APT::Policy", 1) < 1 && Plcy
->GetPriority(Pkg
) != 0)
1739 cout
<< _(" Package pin: ");
1740 V
= Plcy
->GetMatch(Pkg
);
1741 if (V
.end() == true)
1742 cout
<< _("(not found)") << endl
;
1744 cout
<< V
.VerStr() << endl
;
1747 // Show the priority tables
1748 cout
<< _(" Version table:") << endl
;
1749 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1751 if (Pkg
.CurrentVer() == V
)
1752 cout
<< " *** " << V
.VerStr();
1754 cout
<< " " << V
.VerStr();
1755 if (_config
->FindI("APT::Policy", 1) < 1)
1756 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1758 cout
<< " " << Plcy
->GetPriority(V
) << endl
;
1759 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1761 // Locate the associated index files so we can derive a description
1763 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1764 _system
->FindIndex(VF
.File(),Indx
) == false)
1765 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1766 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1767 Indx
->Describe(true).c_str());
1775 // Madison - Look a bit like katie's madison /*{{{*/
1776 // ---------------------------------------------------------------------
1778 static bool Madison(CommandLine
&CmdL
)
1780 pkgCacheFile CacheFile
;
1781 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1786 // Create the src text record parsers and ignore errors about missing
1787 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1788 pkgSrcRecords
SrcRecs(*SrcList
);
1789 if (_error
->PendingError() == true)
1792 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1793 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1795 _error
->PushToStack();
1796 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1797 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1799 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1801 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1803 // This might be nice, but wouldn't uniquely identify the source -mdz
1804 // if (VF.File().Archive() != 0)
1806 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1807 // << VF.File().Archive() << endl;
1810 // Locate the associated index files so we can derive a description
1811 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1813 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1814 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1815 IF
!= Indexes
->end(); ++IF
)
1817 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1819 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1820 << (*IF
)->Describe(true) << endl
;
1829 pkgSrcRecords::Parser
*SrcParser
;
1830 bool foundSomething
= false;
1831 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1833 foundSomething
= true;
1834 // Maybe support Release info here too eventually
1835 cout
<< setw(10) << SrcParser
->Package() << " | "
1836 << setw(10) << SrcParser
->Version() << " | "
1837 << SrcParser
->Index().Describe(true) << endl
;
1839 if (foundSomething
== true)
1840 _error
->RevertToStack();
1842 _error
->MergeWithStack();
1848 // GenCaches - Call the main cache generator /*{{{*/
1849 // ---------------------------------------------------------------------
1851 static bool GenCaches(CommandLine
&)
1853 OpTextProgress
Progress(*_config
);
1855 pkgCacheFile CacheFile
;
1856 return CacheFile
.BuildCaches(&Progress
, true);
1859 // ShowHelp - Show a help screen /*{{{*/
1860 // ---------------------------------------------------------------------
1862 static bool ShowHelp(CommandLine
&)
1864 ioprintf(cout
, "%s %s (%s)\n", PACKAGE
, PACKAGE_VERSION
, COMMON_ARCH
);
1866 if (_config
->FindB("version") == true)
1870 _("Usage: apt-cache [options] command\n"
1871 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1872 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1874 "apt-cache is a low-level tool used to query information\n"
1875 "from APT's binary cache files\n"
1878 " gencaches - Build both the package and source cache\n"
1879 " showpkg - Show some general information for a single package\n"
1880 " showsrc - Show source records\n"
1881 " stats - Show some basic statistics\n"
1882 " dump - Show the entire file in a terse form\n"
1883 " dumpavail - Print an available file to stdout\n"
1884 " unmet - Show unmet dependencies\n"
1885 " search - Search the package list for a regex pattern\n"
1886 " show - Show a readable record for the package\n"
1887 " depends - Show raw dependency information for a package\n"
1888 " rdepends - Show reverse dependency information for a package\n"
1889 " pkgnames - List the names of all packages in the system\n"
1890 " dotty - Generate package graphs for GraphViz\n"
1891 " xvcg - Generate package graphs for xvcg\n"
1892 " policy - Show policy settings\n"
1895 " -h This help text.\n"
1896 " -p=? The package cache.\n"
1897 " -s=? The source cache.\n"
1898 " -q Disable progress indicator.\n"
1899 " -i Show only important deps for the unmet command.\n"
1900 " -c=? Read this configuration file\n"
1901 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1902 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1906 int main(int argc
,const char *argv
[]) /*{{{*/
1908 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1909 {"gencaches",&GenCaches
},
1910 {"showsrc",&ShowSrcPackage
},
1911 {"showpkg",&DumpPackage
},
1914 {"dumpavail",&DumpAvail
},
1917 {"depends",&Depends
},
1918 {"rdepends",&RDepends
},
1921 {"show",&ShowPackage
},
1922 {"pkgnames",&ShowPkgNames
},
1923 {"showauto",&ShowAuto
},
1925 {"madison",&Madison
},
1928 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1930 // Set up gettext support
1931 setlocale(LC_ALL
,"");
1932 textdomain(PACKAGE
);
1934 // Parse the command line and initialize the package library
1936 ParseCommandLine(CmdL
, Cmds
, Args
.data(), &_config
, &_system
, argc
, argv
, ShowHelp
);
1940 if (_config
->Exists("APT::Cache::Generate") == true)
1941 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1943 // Match the operation
1944 CmdL
.DispatchArg(Cmds
);
1946 // Print any errors or warnings found during parsing
1947 bool const Errors
= _error
->PendingError();
1948 if (_config
->FindI("quiet",0) > 0)
1949 _error
->DumpErrors();
1951 _error
->DumpErrors(GlobalError::DEBUG
);
1952 return Errors
== true ? 100 : 0;