]>
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
&)
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
<< "/" << Cache
->Head().DependsDataCount
<< " (" <<
373 SizeToStr((Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) +
374 (Cache
->Head().DependsDataCount
*Cache
->Head().DependencyDataSz
)) << ')' << endl
;
375 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
376 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
377 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
378 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
379 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
380 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
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 stritems
.insert(V
->SourcePkgName
);
396 stritems
.insert(V
->SourceVerStr
);
397 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
400 stritems
.insert(D
->Version
);
402 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
404 stritems
.insert(D
->md5sum
);
405 stritems
.insert(D
->language_code
);
408 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
410 if (Prv
->ProvideVersion
!= 0)
411 stritems
.insert(Prv
->ProvideVersion
);
414 for (pkgCache::RlsFileIterator F
= Cache
->RlsFileBegin(); F
!= Cache
->RlsFileEnd(); ++F
)
416 stritems
.insert(F
->FileName
);
417 stritems
.insert(F
->Archive
);
418 stritems
.insert(F
->Codename
);
419 stritems
.insert(F
->Version
);
420 stritems
.insert(F
->Origin
);
421 stritems
.insert(F
->Label
);
422 stritems
.insert(F
->Site
);
424 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
426 stritems
.insert(F
->FileName
);
427 stritems
.insert(F
->Architecture
);
428 stritems
.insert(F
->Component
);
429 stritems
.insert(F
->IndexType
);
432 unsigned long Size
= 0;
433 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
434 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
435 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
438 unsigned long Slack
= 0;
439 for (int I
= 0; I
!= 7; I
++)
440 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
441 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
443 unsigned long Total
= 0;
444 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
445 Total
= Slack
+ Size
+
446 APT_CACHESIZE(GroupCount
, GroupSz
) +
447 APT_CACHESIZE(PackageCount
, PackageSz
) +
448 APT_CACHESIZE(VersionCount
, VersionSz
) +
449 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
450 APT_CACHESIZE(DependsCount
, DependencySz
) +
451 APT_CACHESIZE(DependsDataCount
, DependencyDataSz
) +
452 APT_CACHESIZE(ReleaseFileCount
, ReleaseFileSz
) +
453 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
454 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
455 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
456 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
457 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
458 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
462 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
463 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
468 // Dump - show everything /*{{{*/
469 // ---------------------------------------------------------------------
470 /* This is worthless except fer debugging things */
471 static bool Dump(CommandLine
&)
473 pkgCacheFile CacheFile
;
474 pkgCache
*Cache
= CacheFile
.GetPkgCache();
475 if (unlikely(Cache
== NULL
))
478 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
480 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
482 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
483 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
485 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
486 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
487 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
488 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
489 DeNull(D
.TargetVer()) << std::endl
;
490 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
492 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
493 << " File: " << D
.FileList().File().FileName() << std::endl
494 << " MD5: " << D
.md5() << std::endl
;
499 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
501 std::cout
<< "File: " << F
.FileName() << std::endl
;
502 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
503 std::cout
<< " Size: " << F
->Size
<< std::endl
;
504 std::cout
<< " ID: " << F
->ID
<< std::endl
;
505 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
506 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
507 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
508 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
509 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
510 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
511 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
512 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
513 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
519 // DumpAvail - Print out the available list /*{{{*/
520 // ---------------------------------------------------------------------
521 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
522 make this run really fast, perhaps I went a little overboard.. */
523 static bool DumpAvail(CommandLine
&)
525 pkgCacheFile CacheFile
;
526 pkgCache
*Cache
= CacheFile
.GetPkgCache();
527 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
530 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
531 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
532 memset(VFList
,0,sizeof(*VFList
)*Count
);
534 // Map versions that we want to write out onto the VerList array.
535 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
537 if (P
->VersionList
== 0)
540 /* Find the proper version to use. If the policy says there are no
541 possible selections we return the installed version, if available..
542 This prevents dselect from making it obsolete. */
543 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
546 if (P
->CurrentVer
== 0)
551 pkgCache::VerFileIterator VF
= V
.FileList();
552 for (; VF
.end() == false ; ++VF
)
553 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
556 /* Okay, here we have a bit of a problem.. The policy has selected the
557 currently installed package - however it only exists in the
558 status file.. We need to write out something or dselect will mark
559 the package as obsolete! Thus we emit the status file entry, but
560 below we remove the status line to make it valid for the
561 available file. However! We only do this if their do exist *any*
562 non-source versions of the package - that way the dselect obsolete
563 handling works OK. */
564 if (VF
.end() == true)
566 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
568 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
570 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
577 if (VF
.end() == false)
585 LocalitySort(VFList
,Count
,sizeof(*VFList
));
587 std::vector
<pkgTagSection::Tag
> RW
;
588 RW
.push_back(pkgTagSection::Tag::Remove("Status"));
589 RW
.push_back(pkgTagSection::Tag::Remove("Config-Version"));
591 stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
, false);
593 // Iterate over all the package files and write them out.
594 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
595 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
597 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
598 if (File
.IsOk() == false)
600 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
604 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
605 if (_error
->PendingError() == true)
608 /* Write all of the records from this package file, since we
609 already did locality sorting we can now just seek through the
610 file in read order. We apply 1 more optimization here, since often
611 there will be < 1 byte gaps between records (for the \n) we read that
612 into the next buffer and offset a bit.. */
613 unsigned long Pos
= 0;
616 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
619 const pkgCache::VerFile
&VF
= **J
;
621 // Read the record and then write it out again.
622 unsigned long Jitter
= VF
.Offset
- Pos
;
625 if (PkgF
.Seek(VF
.Offset
) == false)
630 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
632 Buffer
[VF
.Size
+ Jitter
] = '\n';
635 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
638 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
639 Tags
.Write(stdoutfd
, NULL
, RW
) == false ||
640 stdoutfd
.Write("\n", 1) == false)
642 _error
->Error("Internal Error, Unable to parse a package record");
648 if (stdoutfd
.Write(Buffer
+ Jitter
, VF
.Size
+ 1) == false)
652 Pos
= VF
.Offset
+ VF
.Size
;
655 if (_error
->PendingError() == true)
661 return !_error
->PendingError();
664 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
665 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
667 pkgCacheFile CacheFile
;
668 pkgCache
*Cache
= CacheFile
.GetPkgCache();
669 if (unlikely(Cache
== NULL
))
672 CacheSetHelperVirtuals
helper(false);
673 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
674 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
675 return _error
->Error(_("No packages found"));
676 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
678 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
679 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
680 bool const Important
= _config
->FindB("APT::Cache::Important", false);
681 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
682 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
683 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
684 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
685 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
686 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
687 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
688 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
689 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
690 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
691 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
692 bool const ShowImplicit
= _config
->FindB("APT::Cache::ShowImplicit", false);
694 while (verset
.empty() != true)
696 pkgCache::VerIterator Ver
= *verset
.begin();
697 verset
.erase(verset
.begin());
698 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
699 Shown
[Pkg
->ID
] = true;
701 cout
<< Pkg
.FullName(true) << endl
;
703 if (RevDepends
== true)
704 cout
<< "Reverse Depends:" << endl
;
705 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
706 D
.end() == false; ++D
)
709 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
710 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
711 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
712 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
713 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
714 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
715 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
716 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
718 if (ShowImplicit
== false && D
.IsImplicit())
721 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
722 bool const showNoArch
= RevDepends
|| (D
->CompareOp
& pkgCache::Dep::ArchSpecific
) != pkgCache::Dep::ArchSpecific
;
724 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
727 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
733 if (ShowDepType
== true)
734 cout
<< D
.DepType() << ": ";
735 if (Trg
->VersionList
== 0)
736 cout
<< "<" << Trg
.FullName(showNoArch
) << ">";
738 cout
<< Trg
.FullName(showNoArch
);
739 if (ShowVersion
== true && D
->Version
!= 0)
740 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
743 if (Recurse
== true && Shown
[Trg
->ID
] == false)
745 Shown
[Trg
->ID
] = true;
746 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::CacheSetHelper::CANDIDATE
, helper
));
751 // Display all solutions
752 std::unique_ptr
<pkgCache::Version
*[]> List(D
.AllTargets());
753 pkgPrioSortList(*Cache
,List
.get());
754 for (pkgCache::Version
**I
= List
.get(); *I
!= 0; I
++)
756 pkgCache::VerIterator
V(*Cache
,*I
);
757 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
758 V
->ParentPkg
== D
->Package
)
760 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
762 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
764 Shown
[V
.ParentPkg()->ID
] = true;
765 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::CacheSetHelper::CANDIDATE
, helper
));
769 if (ShowOnlyFirstOr
== true)
770 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
774 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
775 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
776 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
781 // Depends - Print out a dependency tree /*{{{*/
782 // ---------------------------------------------------------------------
784 static bool Depends(CommandLine
&CmdL
)
786 return ShowDepends(CmdL
, false);
789 // RDepends - Print out a reverse dependency tree /*{{{*/
790 // ---------------------------------------------------------------------
792 static bool RDepends(CommandLine
&CmdL
)
794 return ShowDepends(CmdL
, true);
797 // xvcg - Generate a graph for xvcg /*{{{*/
798 // ---------------------------------------------------------------------
799 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
801 static bool XVcg(CommandLine
&CmdL
)
803 pkgCacheFile CacheFile
;
804 pkgCache
*Cache
= CacheFile
.GetPkgCache();
805 if (unlikely(Cache
== NULL
))
808 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
810 /* Normal packages are boxes
811 Pure Provides are triangles
813 rhomb are missing packages*/
814 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
816 /* Initialize the list of packages to show.
818 2 = To Show no recurse
819 3 = Emitted no recurse
822 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
823 enum TheFlags
{ForceNR
=(1<<0)};
824 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
825 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
826 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
828 // Show everything if no arguments given
829 if (CmdL
.FileList
[1] == 0)
830 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
833 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
835 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
838 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
840 if (Pkg
->VersionList
== 0)
843 if (Pkg
->ProvidesList
== 0)
844 ShapeMap
[Pkg
->ID
] = 0;
846 ShapeMap
[Pkg
->ID
] = 1;
851 if (Pkg
->ProvidesList
== 0)
852 ShapeMap
[Pkg
->ID
] = 2;
854 ShapeMap
[Pkg
->ID
] = 3;
858 // Load the list of packages from the command line into the show list
859 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
860 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
861 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
862 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
863 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
864 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
866 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
867 Pkg
!= pkgsets
[0].end(); ++Pkg
)
868 Show
[Pkg
->ID
] = ToShow
;
869 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
870 Pkg
!= pkgsets
[1].end(); ++Pkg
)
872 Show
[Pkg
->ID
] = ToShow
;
873 Flags
[Pkg
->ID
] |= ForceNR
;
877 cout
<< "graph: { title: \"packages\"" << endl
<<
878 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
879 "layout_downfactor: 8" << endl
;
885 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
887 // See we need to show this package
888 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
891 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
894 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
896 // Pure Provides and missing packages have no deps!
897 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
898 Show
[Pkg
->ID
] = Done
;
900 Show
[Pkg
->ID
] = DoneNR
;
903 Show
[Pkg
->ID
] = Done
;
906 // No deps to map out
907 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
910 pkgCache::VerIterator Ver
= Pkg
.VersionList();
911 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
913 // See if anything can meet this dep
914 // Walk along the actual package providing versions
916 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
917 for (pkgCache::VerIterator I
= DPkg
.VersionList();
918 I
.end() == false && Hit
== false; ++I
)
920 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
924 // Follow all provides
925 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
926 I
.end() == false && Hit
== false; ++I
)
928 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
933 // Only graph critical deps
934 if (D
.IsCritical() == true)
936 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
938 // Colour the node for recursion
939 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
941 /* If a conflicts does not meet anything in the database
942 then show the relation but do not recurse */
943 if (Hit
== false && D
.IsNegative() == true)
945 if (Show
[D
.TargetPkg()->ID
] == None
&&
946 Show
[D
.TargetPkg()->ID
] != ToShow
)
947 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
951 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
952 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
954 Show
[D
.TargetPkg()->ID
] = ToShow
;
961 case pkgCache::Dep::Conflicts
:
962 printf("label: \"conflicts\" color: lightgreen }\n");
964 case pkgCache::Dep::DpkgBreaks
:
965 printf("label: \"breaks\" color: lightgreen }\n");
967 case pkgCache::Dep::Obsoletes
:
968 printf("label: \"obsoletes\" color: lightgreen }\n");
971 case pkgCache::Dep::PreDepends
:
972 printf("label: \"predepends\" color: blue }\n");
984 /* Draw the box colours after the fact since we can not tell what colour
985 they should be until everything is finished drawing */
986 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
988 if (Show
[Pkg
->ID
] < DoneNR
)
991 if (Show
[Pkg
->ID
] == DoneNR
)
992 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
993 Shapes
[ShapeMap
[Pkg
->ID
]]);
995 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
996 Shapes
[ShapeMap
[Pkg
->ID
]]);
1008 // Dotty - Generate a graph for Dotty /*{{{*/
1009 // ---------------------------------------------------------------------
1010 /* Dotty is the graphvis program for generating graphs. It is a fairly
1011 simple queuing algorithm that just writes dependencies and nodes.
1012 http://www.research.att.com/sw/tools/graphviz/ */
1013 static bool Dotty(CommandLine
&CmdL
)
1015 pkgCacheFile CacheFile
;
1016 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1017 if (unlikely(Cache
== NULL
))
1020 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1022 /* Normal packages are boxes
1023 Pure Provides are triangles
1025 Hexagons are missing packages*/
1026 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1028 /* Initialize the list of packages to show.
1030 2 = To Show no recurse
1031 3 = Emitted no recurse
1034 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1035 enum TheFlags
{ForceNR
=(1<<0)};
1036 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1037 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1038 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1040 // Show everything if no arguments given
1041 if (CmdL
.FileList
[1] == 0)
1042 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1045 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1047 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1050 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1052 if (Pkg
->VersionList
== 0)
1055 if (Pkg
->ProvidesList
== 0)
1056 ShapeMap
[Pkg
->ID
] = 0;
1058 ShapeMap
[Pkg
->ID
] = 1;
1063 if (Pkg
->ProvidesList
== 0)
1064 ShapeMap
[Pkg
->ID
] = 2;
1066 ShapeMap
[Pkg
->ID
] = 3;
1070 // Load the list of packages from the command line into the show list
1071 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1072 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
1073 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1074 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1075 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1076 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1078 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1079 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1080 Show
[Pkg
->ID
] = ToShow
;
1081 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1082 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1084 Show
[Pkg
->ID
] = ToShow
;
1085 Flags
[Pkg
->ID
] |= ForceNR
;
1089 printf("digraph packages {\n");
1090 printf("concentrate=true;\n");
1091 printf("size=\"30,40\";\n");
1097 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1099 // See we need to show this package
1100 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1104 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1106 // Pure Provides and missing packages have no deps!
1107 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1108 Show
[Pkg
->ID
] = Done
;
1110 Show
[Pkg
->ID
] = DoneNR
;
1113 Show
[Pkg
->ID
] = Done
;
1116 // No deps to map out
1117 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1120 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1121 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1123 // See if anything can meet this dep
1124 // Walk along the actual package providing versions
1126 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1127 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1128 I
.end() == false && Hit
== false; ++I
)
1130 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1134 // Follow all provides
1135 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1136 I
.end() == false && Hit
== false; ++I
)
1138 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1142 // Only graph critical deps
1143 if (D
.IsCritical() == true)
1145 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1147 // Colour the node for recursion
1148 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1150 /* If a conflicts does not meet anything in the database
1151 then show the relation but do not recurse */
1152 if (Hit
== false && D
.IsNegative() == true)
1154 if (Show
[D
.TargetPkg()->ID
] == None
&&
1155 Show
[D
.TargetPkg()->ID
] != ToShow
)
1156 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1160 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1161 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1163 Show
[D
.TargetPkg()->ID
] = ToShow
;
1170 case pkgCache::Dep::Conflicts
:
1171 case pkgCache::Dep::Obsoletes
:
1172 case pkgCache::Dep::DpkgBreaks
:
1173 printf("[color=springgreen];\n");
1176 case pkgCache::Dep::PreDepends
:
1177 printf("[color=blue];\n");
1189 /* Draw the box colours after the fact since we can not tell what colour
1190 they should be until everything is finished drawing */
1191 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1193 if (Show
[Pkg
->ID
] < DoneNR
)
1196 // Orange box for early recursion stoppage
1197 if (Show
[Pkg
->ID
] == DoneNR
)
1198 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1199 Shapes
[ShapeMap
[Pkg
->ID
]]);
1201 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1202 Shapes
[ShapeMap
[Pkg
->ID
]]);
1212 // DisplayRecord - Displays the complete record for the package /*{{{*/
1213 // ---------------------------------------------------------------------
1214 /* This displays the package record from the proper package index file.
1215 It is not used by DumpAvail for performance reasons. */
1217 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1219 char const * const TagName
= "\nDescription";
1220 size_t const TagLen
= strlen(TagName
);
1221 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1223 if (DescP
[1] == ' ')
1225 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1234 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1236 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1237 if (unlikely(Cache
== NULL
))
1240 // Find an appropriate file
1241 pkgCache::VerFileIterator Vf
= V
.FileList();
1242 for (; Vf
.end() == false; ++Vf
)
1243 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1245 if (Vf
.end() == true)
1248 // Check and load the package list file
1249 pkgCache::PkgFileIterator I
= Vf
.File();
1250 if (I
.IsOk() == false)
1251 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1254 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1257 // Read the record (and ensure that it ends with a newline and NUL)
1258 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1259 Buffer
[Vf
->Size
] = '\n';
1260 Buffer
[Vf
->Size
+1] = '\0';
1261 if (PkgF
.Seek(Vf
->Offset
) == false ||
1262 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1268 // Get a pointer to start of Description field
1269 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1273 DescP
= Buffer
+ Vf
->Size
;
1275 // Write all but Description
1276 size_t const length
= DescP
- Buffer
;
1277 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1283 // Show the right description
1284 pkgRecords
Recs(*Cache
);
1285 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1286 if (Desc
.end() == false)
1288 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1289 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1290 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1292 // Find the first field after the description (if there is any)
1293 DescP
= skipDescriptionFields(DescP
);
1295 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1297 // write the rest of the buffer, but skip mixed in Descriptions* fields
1298 while (DescP
!= NULL
)
1300 const unsigned char * const Start
= DescP
;
1301 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1304 End
= &Buffer
[Vf
->Size
];
1309 ++End
; // get the newline into the output
1310 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1312 size_t const length
= End
- Start
;
1313 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1320 // write a final newline after the last field
1329 pkgCache::DescFile
*Df
;
1333 // Search - Perform a search /*{{{*/
1334 // ---------------------------------------------------------------------
1335 /* This searches the package names and package descriptions for a pattern */
1336 static bool Search(CommandLine
&CmdL
)
1338 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1339 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1340 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1342 pkgCacheFile CacheFile
;
1343 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1344 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1345 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1348 // Make sure there is at least one argument
1349 if (NumPatterns
< 1)
1350 return _error
->Error(_("You must give at least one search pattern"));
1352 // Compile the regex pattern
1353 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1354 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1355 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1357 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1361 regfree(&Patterns
[I
]);
1362 return _error
->Error("Regex compilation error");
1366 if (_error
->PendingError() == true)
1368 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1369 regfree(&Patterns
[I
]);
1373 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1374 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1375 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1377 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1378 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1380 // Map versions that we want to write out onto the VerList array.
1381 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1383 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1384 size_t unmatched
= 0, matched
= 0;
1385 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1387 if (PatternMatch
[PatternOffset
+ I
] == true)
1389 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1390 PatternMatch
[PatternOffset
+ I
] = true;
1395 // already dealt with this package?
1396 if (matched
== NumPatterns
)
1399 // Doing names only, drop any that don't match..
1400 if (NamesOnly
== true && unmatched
== NumPatterns
)
1403 // Find the proper version to use
1404 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1405 if (P
.end() == true)
1407 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1408 if (V
.end() == false)
1410 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1411 //FIXME: packages without a description can't be found
1412 if (D
.end() == true)
1414 DFList
[G
->ID
].Df
= D
.FileList();
1415 DFList
[G
->ID
].ID
= G
->ID
;
1418 if (unmatched
== NumPatterns
)
1421 // Include all the packages that provide matching names too
1422 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1424 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1425 if (V
.end() == true)
1428 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1429 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1430 //FIXME: packages without a description can't be found
1431 if (D
.end() == true)
1433 DFList
[id
].Df
= D
.FileList();
1436 size_t const PrvPatternOffset
= id
* NumPatterns
;
1437 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1438 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1442 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1444 // Create the text record parser
1445 pkgRecords
Recs(*Cache
);
1446 // Iterate over all the version records and check them
1447 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1449 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1450 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1452 if (NamesOnly
== false)
1454 string
const LongDesc
= P
.LongDesc();
1455 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1457 if (PatternMatch
[PatternOffset
+ I
] == true)
1459 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1460 PatternMatch
[PatternOffset
+ I
] = true;
1464 bool matchedAll
= true;
1465 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1466 if (PatternMatch
[PatternOffset
+ I
] == false)
1472 if (matchedAll
== true)
1474 if (ShowFull
== true)
1478 P
.GetRec(Start
,End
);
1479 fwrite(Start
,End
-Start
,1,stdout
);
1483 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1488 delete [] PatternMatch
;
1489 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1490 regfree(&Patterns
[I
]);
1493 return _error
->Error("Write to stdout failed");
1497 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1498 static bool ShowAuto(CommandLine
&)
1500 pkgCacheFile CacheFile
;
1501 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1502 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1503 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1506 std::vector
<string
> packages
;
1507 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1509 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1510 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1511 packages
.push_back(P
.Name());
1513 std::sort(packages
.begin(), packages
.end());
1515 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1518 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1522 // ShowPackage - Dump the package record to the screen /*{{{*/
1523 // ---------------------------------------------------------------------
1525 static bool ShowPackage(CommandLine
&CmdL
)
1527 pkgCacheFile CacheFile
;
1528 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1529 APT::CacheSetHelper::VerSelector
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1530 APT::CacheSetHelper::ALL
: APT::CacheSetHelper::CANDIDATE
;
1531 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1532 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1533 if (DisplayRecord(CacheFile
, Ver
) == false)
1536 if (verset
.empty() == true)
1538 if (helper
.virtualPkgs
.empty() == true)
1539 return _error
->Error(_("No packages found"));
1541 _error
->Notice(_("No packages found"));
1546 // ShowPkgNames - Show package names /*{{{*/
1547 // ---------------------------------------------------------------------
1548 /* This does a prefix match on the first argument */
1549 static bool ShowPkgNames(CommandLine
&CmdL
)
1551 pkgCacheFile CacheFile
;
1552 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1554 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1555 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1557 if (CmdL
.FileList
[1] != 0)
1559 for (;I
.end() != true; ++I
)
1561 if (All
== false && I
->FirstPackage
== 0)
1563 if (I
.FindPkg("any")->VersionList
== 0)
1565 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1566 cout
<< I
.Name() << endl
;
1573 for (;I
.end() != true; ++I
)
1575 if (All
== false && I
->FirstPackage
== 0)
1577 if (I
.FindPkg("any")->VersionList
== 0)
1579 cout
<< I
.Name() << endl
;
1585 // ShowSrcPackage - Show source package records /*{{{*/
1586 // ---------------------------------------------------------------------
1588 static bool ShowSrcPackage(CommandLine
&CmdL
)
1590 pkgCacheFile CacheFile
;
1591 pkgSourceList
*List
= CacheFile
.GetSourceList();
1592 if (unlikely(List
== NULL
))
1595 // Create the text record parsers
1596 pkgSrcRecords
SrcRecs(*List
);
1597 if (_error
->PendingError() == true)
1601 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1605 pkgSrcRecords::Parser
*Parse
;
1606 unsigned found_this
= 0;
1607 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1608 cout
<< Parse
->AsStr() << endl
;;
1612 if (found_this
== 0) {
1613 _error
->Warning(_("Unable to locate package %s"),*I
);
1618 _error
->Notice(_("No packages found"));
1622 // Policy - Show the results of the preferences file /*{{{*/
1623 // ---------------------------------------------------------------------
1625 static bool Policy(CommandLine
&CmdL
)
1627 pkgCacheFile CacheFile
;
1628 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1629 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1630 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1631 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1634 /* Should the MultiArchKiller be run to see which pseudo packages for an
1635 arch all package are currently installed? Activating it gives a speed
1636 penality for no real gain beside enhanced debugging, so in general no. */
1637 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1638 CacheFile
.GetDepCache();
1640 // Print out all of the package files
1641 if (CmdL
.FileList
[1] == 0)
1643 cout
<< _("Package files:") << endl
;
1644 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1646 if (F
.Flagged(pkgCache::Flag::NoPackages
))
1648 // Locate the associated index files so we can derive a description
1650 if (SrcList
->FindIndex(F
,Indx
) == false &&
1651 _system
->FindIndex(F
,Indx
) == false)
1652 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1655 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1657 // Print the reference information for the package
1658 string Str
= F
.RelStr();
1659 if (Str
.empty() == false)
1660 printf(" release %s\n",F
.RelStr().c_str());
1661 if (F
.Site() != 0 && F
.Site()[0] != 0)
1662 printf(" origin %s\n",F
.Site());
1665 // Show any packages have explicit pins
1666 cout
<< _("Pinned packages:") << endl
;
1667 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1668 for (;I
.end() != true; ++I
)
1670 // Old code for debugging
1671 if (_config
->FindI("APT::Policy", 1) < 1) {
1672 if (Plcy
->GetPriority(I
) == 0)
1675 // Print the package name and the version we are forcing to
1676 cout
<< " " << I
.FullName(true) << " -> ";
1678 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1679 if (V
.end() == true)
1680 cout
<< _("(not found)") << endl
;
1682 cout
<< V
.VerStr() << endl
;
1687 for (pkgCache::VerIterator V
= I
.VersionList(); !V
.end(); V
++) {
1688 auto Prio
= Plcy
->GetPriority(V
, false);
1693 // Print the package name and the version we are forcing to
1694 ioprintf(cout
, _("%s -> %s with priority %d\n"), I
.FullName(true).c_str(), V
.VerStr(), Prio
);
1700 char const * const msgInstalled
= _(" Installed: ");
1701 char const * const msgCandidate
= _(" Candidate: ");
1702 short const InstalledLessCandidate
=
1703 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1704 short const deepInstalled
=
1705 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1706 short const deepCandidate
=
1707 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1709 // Print out detailed information for each package
1710 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1711 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1712 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1714 cout
<< Pkg
.FullName(true) << ":" << endl
;
1716 // Installed version
1717 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1718 if (Pkg
->CurrentVer
== 0)
1719 cout
<< _("(none)") << endl
;
1721 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1723 // Candidate Version
1724 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1725 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1726 if (V
.end() == true)
1727 cout
<< _("(none)") << endl
;
1729 cout
<< V
.VerStr() << endl
;
1732 if (_config
->FindI("APT::Policy", 1) < 1 && Plcy
->GetPriority(Pkg
) != 0)
1734 cout
<< _(" Package pin: ");
1735 V
= Plcy
->GetMatch(Pkg
);
1736 if (V
.end() == true)
1737 cout
<< _("(not found)") << endl
;
1739 cout
<< V
.VerStr() << endl
;
1742 // Show the priority tables
1743 cout
<< _(" Version table:") << endl
;
1744 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1746 if (Pkg
.CurrentVer() == V
)
1747 cout
<< " *** " << V
.VerStr();
1749 cout
<< " " << V
.VerStr();
1750 if (_config
->FindI("APT::Policy", 1) < 1)
1751 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1753 cout
<< " " << Plcy
->GetPriority(V
) << endl
;
1754 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1756 // Locate the associated index files so we can derive a description
1758 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1759 _system
->FindIndex(VF
.File(),Indx
) == false)
1760 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1761 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1762 Indx
->Describe(true).c_str());
1770 // Madison - Look a bit like katie's madison /*{{{*/
1771 // ---------------------------------------------------------------------
1773 static bool Madison(CommandLine
&CmdL
)
1775 pkgCacheFile CacheFile
;
1776 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1781 // Create the src text record parsers and ignore errors about missing
1782 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1783 pkgSrcRecords
SrcRecs(*SrcList
);
1784 if (_error
->PendingError() == true)
1787 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1788 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1790 _error
->PushToStack();
1791 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1792 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1794 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1796 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1798 // This might be nice, but wouldn't uniquely identify the source -mdz
1799 // if (VF.File().Archive() != 0)
1801 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1802 // << VF.File().Archive() << endl;
1805 // Locate the associated index files so we can derive a description
1806 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1808 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1809 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1810 IF
!= Indexes
->end(); ++IF
)
1812 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1814 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1815 << (*IF
)->Describe(true) << endl
;
1824 pkgSrcRecords::Parser
*SrcParser
;
1825 bool foundSomething
= false;
1826 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1828 foundSomething
= true;
1829 // Maybe support Release info here too eventually
1830 cout
<< setw(10) << SrcParser
->Package() << " | "
1831 << setw(10) << SrcParser
->Version() << " | "
1832 << SrcParser
->Index().Describe(true) << endl
;
1834 if (foundSomething
== true)
1835 _error
->RevertToStack();
1837 _error
->MergeWithStack();
1843 // GenCaches - Call the main cache generator /*{{{*/
1844 // ---------------------------------------------------------------------
1846 static bool GenCaches(CommandLine
&)
1848 OpTextProgress
Progress(*_config
);
1850 pkgCacheFile CacheFile
;
1851 return CacheFile
.BuildCaches(&Progress
, true);
1854 // ShowHelp - Show a help screen /*{{{*/
1855 // ---------------------------------------------------------------------
1857 static bool ShowHelp(CommandLine
&)
1859 ioprintf(cout
, "%s %s (%s)\n", PACKAGE
, PACKAGE_VERSION
, COMMON_ARCH
);
1861 if (_config
->FindB("version") == true)
1865 _("Usage: apt-cache [options] command\n"
1866 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1867 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1869 "apt-cache is a low-level tool used to query information\n"
1870 "from APT's binary cache files\n"
1873 " gencaches - Build both the package and source cache\n"
1874 " showpkg - Show some general information for a single package\n"
1875 " showsrc - Show source records\n"
1876 " stats - Show some basic statistics\n"
1877 " dump - Show the entire file in a terse form\n"
1878 " dumpavail - Print an available file to stdout\n"
1879 " unmet - Show unmet dependencies\n"
1880 " search - Search the package list for a regex pattern\n"
1881 " show - Show a readable record for the package\n"
1882 " depends - Show raw dependency information for a package\n"
1883 " rdepends - Show reverse dependency information for a package\n"
1884 " pkgnames - List the names of all packages in the system\n"
1885 " dotty - Generate package graphs for GraphViz\n"
1886 " xvcg - Generate package graphs for xvcg\n"
1887 " policy - Show policy settings\n"
1890 " -h This help text.\n"
1891 " -p=? The package cache.\n"
1892 " -s=? The source cache.\n"
1893 " -q Disable progress indicator.\n"
1894 " -i Show only important deps for the unmet command.\n"
1895 " -c=? Read this configuration file\n"
1896 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1897 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1901 int main(int argc
,const char *argv
[]) /*{{{*/
1903 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1904 {"gencaches",&GenCaches
},
1905 {"showsrc",&ShowSrcPackage
},
1906 {"showpkg",&DumpPackage
},
1909 {"dumpavail",&DumpAvail
},
1912 {"depends",&Depends
},
1913 {"rdepends",&RDepends
},
1916 {"show",&ShowPackage
},
1917 {"pkgnames",&ShowPkgNames
},
1918 {"showauto",&ShowAuto
},
1920 {"madison",&Madison
},
1923 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1925 // Set up gettext support
1926 setlocale(LC_ALL
,"");
1927 textdomain(PACKAGE
);
1929 // Parse the command line and initialize the package library
1931 ParseCommandLine(CmdL
, Cmds
, Args
.data(), &_config
, &_system
, argc
, argv
, ShowHelp
);
1935 if (_config
->Exists("APT::Cache::Generate") == true)
1936 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1938 // Match the operation
1939 CmdL
.DispatchArg(Cmds
);
1941 // Print any errors or warnings found during parsing
1942 bool const Errors
= _error
->PendingError();
1943 if (_config
->FindI("quiet",0) > 0)
1944 _error
->DumpErrors();
1946 _error
->DumpErrors(GlobalError::DEBUG
);
1947 return Errors
== true ? 100 : 0;