]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
82cb45acdc4ee05776a4a2d2f732401d2ecc4a72
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>
46 #include <apt-private/private-show.h>
68 // LocalitySort - Sort a version list by package file locality /*{{{*/
69 // ---------------------------------------------------------------------
71 static int LocalityCompare(const void *a
, const void *b
)
73 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
74 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
83 if (A
->File
== B
->File
)
84 return A
->Offset
- B
->Offset
;
85 return A
->File
- B
->File
;
88 static void LocalitySort(pkgCache::VerFile
**begin
,
89 unsigned long Count
,size_t Size
)
91 qsort(begin
,Count
,Size
,LocalityCompare
);
94 static void LocalitySort(pkgCache::DescFile
**begin
,
95 unsigned long Count
,size_t Size
)
97 qsort(begin
,Count
,Size
,LocalityCompare
);
100 // UnMet - Show unmet dependencies /*{{{*/
101 // ---------------------------------------------------------------------
103 static bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const Important
)
106 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
109 pkgCache::DepIterator Start
;
110 pkgCache::DepIterator End
;
113 // Important deps only
114 if (Important
== true)
115 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
116 End
->Type
!= pkgCache::Dep::Depends
)
119 // Skip conflicts and replaces
120 if (End
.IsNegative() == true || End
->Type
== pkgCache::Dep::Replaces
)
123 // Verify the or group
125 pkgCache::DepIterator RealStart
= Start
;
128 // See if this dep is Ok
129 pkgCache::Version
**VList
= Start
.AllTargets();
150 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
151 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
154 // Print out the dep type
155 cout
<< " " << End
.DepType() << ": ";
161 cout
<< Start
.TargetPkg().FullName(true);
162 if (Start
.TargetVer() != 0)
163 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
176 static bool UnMet(CommandLine
&CmdL
)
178 bool const Important
= _config
->FindB("APT::Cache::Important",false);
180 pkgCacheFile CacheFile
;
181 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
184 if (CmdL
.FileSize() <= 1)
186 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; ++P
)
187 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
188 if (ShowUnMet(V
, Important
) == false)
193 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
194 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
195 APT::CacheSetHelper::CANDIDATE
, helper
);
196 for (APT::VersionList::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
197 if (ShowUnMet(V
, Important
) == false)
203 // DumpPackage - Show a dump of a package record /*{{{*/
204 // ---------------------------------------------------------------------
206 static bool DumpPackage(CommandLine
&CmdL
)
208 pkgCacheFile CacheFile
;
209 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
210 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
212 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
214 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
215 cout
<< "Versions: " << endl
;
216 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
218 cout
<< Cur
.VerStr();
219 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
220 cout
<< " (" << Vf
.File().FileName() << ")";
222 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
224 cout
<< " Description Language: " << D
.LanguageCode() << endl
225 << " File: " << D
.FileList().File().FileName() << endl
226 << " MD5: " << D
.md5() << endl
;
233 cout
<< "Reverse Depends: " << endl
;
234 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
236 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
238 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
243 cout
<< "Dependencies: " << endl
;
244 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
246 cout
<< Cur
.VerStr() << " - ";
247 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; ++Dep
)
248 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
252 cout
<< "Provides: " << endl
;
253 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
255 cout
<< Cur
.VerStr() << " - ";
256 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
257 cout
<< Prv
.ParentPkg().FullName(true) << " (= " << (Prv
->ProvideVersion
== 0 ? "" : Prv
.ProvideVersion()) << ") ";
260 cout
<< "Reverse Provides: " << endl
;
261 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
262 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << " (= " << (Prv
->ProvideVersion
== 0 ? "" : Prv
.ProvideVersion()) << ")"<< endl
;
268 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
269 // ---------------------------------------------------------------------
271 static map_pointer_t
PackageNext(pkgCache::Package
const * const P
) { return P
->NextPackage
; }
272 static map_pointer_t
GroupNext(pkgCache::Group
const * const G
) { return G
->Next
; }
274 static void ShowHashTableStats(std::string Type
,
276 map_pointer_t
*Hashtable
,
278 map_pointer_t(*Next
)(T
const * const))
280 // hashtable stats for the HashTable
281 unsigned long NumBuckets
= Size
;
282 unsigned long UsedBuckets
= 0;
283 unsigned long UnusedBuckets
= 0;
284 unsigned long LongestBucket
= 0;
285 unsigned long ShortestBucket
= NumBuckets
;
286 unsigned long Entries
= 0;
287 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
289 T
*P
= StartP
+ Hashtable
[i
];
290 if(P
== 0 || P
== StartP
)
296 unsigned long ThisBucketSize
= 0;
297 for (; P
!= StartP
; P
= StartP
+ Next(P
))
299 Entries
+= ThisBucketSize
;
300 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
301 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
303 cout
<< "Total buckets in " << Type
<< ": " << NumBuckets
<< std::endl
;
304 cout
<< " Unused: " << UnusedBuckets
<< std::endl
;
305 cout
<< " Used: " << UsedBuckets
<< std::endl
;
306 cout
<< " Average entries: " << Entries
/(double)NumBuckets
<< std::endl
;
307 cout
<< " Longest: " << LongestBucket
<< std::endl
;
308 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
311 // Stats - Dump some nice statistics /*{{{*/
312 // ---------------------------------------------------------------------
314 static bool Stats(CommandLine
&CmdL
)
316 if (CmdL
.FileSize() > 1) {
317 _error
->Error(_("apt-cache stats does not take any arguments"));
321 pkgCacheFile CacheFile
;
322 pkgCache
*Cache
= CacheFile
.GetPkgCache();
324 if (unlikely(Cache
== NULL
))
327 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
328 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
329 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
330 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
337 pkgCache::PkgIterator I
= Cache
->PkgBegin();
338 for (;I
.end() != true; ++I
)
340 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
346 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
352 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
355 if (I
.ProvidesList()->NextProvides
== 0)
363 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
369 cout
<< _(" Normal packages: ") << Normal
<< endl
;
370 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
371 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
372 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
373 cout
<< _(" Missing: ") << Missing
<< endl
;
375 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
376 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
377 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
378 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
379 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< "/" << Cache
->Head().DependsDataCount
<< " (" <<
380 SizeToStr((Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) +
381 (Cache
->Head().DependsDataCount
*Cache
->Head().DependencyDataSz
)) << ')' << endl
;
382 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
383 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
384 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
385 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
386 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
387 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
390 std::set
<map_stringitem_t
> stritems
;
391 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
392 stritems
.insert(G
->Name
);
393 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
395 stritems
.insert(P
->Arch
);
396 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
399 stritems
.insert(V
->VerStr
);
401 stritems
.insert(V
->Section
);
402 stritems
.insert(V
->SourcePkgName
);
403 stritems
.insert(V
->SourceVerStr
);
404 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
407 stritems
.insert(D
->Version
);
409 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
411 stritems
.insert(D
->md5sum
);
412 stritems
.insert(D
->language_code
);
415 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
417 if (Prv
->ProvideVersion
!= 0)
418 stritems
.insert(Prv
->ProvideVersion
);
421 for (pkgCache::RlsFileIterator F
= Cache
->RlsFileBegin(); F
!= Cache
->RlsFileEnd(); ++F
)
423 stritems
.insert(F
->FileName
);
424 stritems
.insert(F
->Archive
);
425 stritems
.insert(F
->Codename
);
426 stritems
.insert(F
->Version
);
427 stritems
.insert(F
->Origin
);
428 stritems
.insert(F
->Label
);
429 stritems
.insert(F
->Site
);
431 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
433 stritems
.insert(F
->FileName
);
434 stritems
.insert(F
->Architecture
);
435 stritems
.insert(F
->Component
);
436 stritems
.insert(F
->IndexType
);
439 unsigned long Size
= 0;
440 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
441 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
442 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
445 unsigned long Slack
= 0;
446 for (int I
= 0; I
!= 7; I
++)
447 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
448 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
450 unsigned long Total
= 0;
451 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
452 Total
= Slack
+ Size
+
453 APT_CACHESIZE(GroupCount
, GroupSz
) +
454 APT_CACHESIZE(PackageCount
, PackageSz
) +
455 APT_CACHESIZE(VersionCount
, VersionSz
) +
456 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
457 APT_CACHESIZE(DependsCount
, DependencySz
) +
458 APT_CACHESIZE(DependsDataCount
, DependencyDataSz
) +
459 APT_CACHESIZE(ReleaseFileCount
, ReleaseFileSz
) +
460 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
461 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
462 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
463 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
464 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
465 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
469 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
470 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
475 // Dump - show everything /*{{{*/
476 // ---------------------------------------------------------------------
477 /* This is worthless except fer debugging things */
478 static bool Dump(CommandLine
&)
480 pkgCacheFile CacheFile
;
481 pkgCache
*Cache
= CacheFile
.GetPkgCache();
482 if (unlikely(Cache
== NULL
))
485 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
487 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
489 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
490 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
492 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
493 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
494 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
495 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
496 DeNull(D
.TargetVer()) << std::endl
;
497 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
499 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
500 << " File: " << D
.FileList().File().FileName() << std::endl
501 << " MD5: " << D
.md5() << std::endl
;
506 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
508 std::cout
<< "File: " << F
.FileName() << std::endl
;
509 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
510 std::cout
<< " Size: " << F
->Size
<< std::endl
;
511 std::cout
<< " ID: " << F
->ID
<< std::endl
;
512 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
513 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
514 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
515 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
516 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
517 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
518 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
519 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
520 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
526 // DumpAvail - Print out the available list /*{{{*/
527 // ---------------------------------------------------------------------
528 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
529 make this run really fast, perhaps I went a little overboard.. */
530 static bool DumpAvail(CommandLine
&)
532 pkgCacheFile CacheFile
;
533 pkgCache
*Cache
= CacheFile
.GetPkgCache();
534 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
537 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
538 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
539 memset(VFList
,0,sizeof(*VFList
)*Count
);
541 // Map versions that we want to write out onto the VerList array.
542 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
544 if (P
->VersionList
== 0)
547 /* Find the proper version to use. If the policy says there are no
548 possible selections we return the installed version, if available..
549 This prevents dselect from making it obsolete. */
550 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
553 if (P
->CurrentVer
== 0)
558 pkgCache::VerFileIterator VF
= V
.FileList();
559 for (; VF
.end() == false ; ++VF
)
560 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
563 /* Okay, here we have a bit of a problem.. The policy has selected the
564 currently installed package - however it only exists in the
565 status file.. We need to write out something or dselect will mark
566 the package as obsolete! Thus we emit the status file entry, but
567 below we remove the status line to make it valid for the
568 available file. However! We only do this if their do exist *any*
569 non-source versions of the package - that way the dselect obsolete
570 handling works OK. */
571 if (VF
.end() == true)
573 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
575 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
577 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
584 if (VF
.end() == false)
592 LocalitySort(VFList
,Count
,sizeof(*VFList
));
594 std::vector
<pkgTagSection::Tag
> RW
;
595 RW
.push_back(pkgTagSection::Tag::Remove("Status"));
596 RW
.push_back(pkgTagSection::Tag::Remove("Config-Version"));
598 stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
, false);
600 // Iterate over all the package files and write them out.
601 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
602 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
604 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
605 if (File
.IsOk() == false)
607 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
611 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
612 if (_error
->PendingError() == true)
615 /* Write all of the records from this package file, since we
616 already did locality sorting we can now just seek through the
617 file in read order. We apply 1 more optimization here, since often
618 there will be < 1 byte gaps between records (for the \n) we read that
619 into the next buffer and offset a bit.. */
620 unsigned long Pos
= 0;
623 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
626 const pkgCache::VerFile
&VF
= **J
;
628 // Read the record and then write it out again.
629 unsigned long Jitter
= VF
.Offset
- Pos
;
632 if (PkgF
.Seek(VF
.Offset
) == false)
637 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
639 Buffer
[VF
.Size
+ Jitter
] = '\n';
642 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
645 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
646 Tags
.Write(stdoutfd
, NULL
, RW
) == false ||
647 stdoutfd
.Write("\n", 1) == false)
649 _error
->Error("Internal Error, Unable to parse a package record");
655 if (stdoutfd
.Write(Buffer
+ Jitter
, VF
.Size
+ 1) == false)
659 Pos
= VF
.Offset
+ VF
.Size
;
662 if (_error
->PendingError() == true)
668 return !_error
->PendingError();
671 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
672 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
674 pkgCacheFile CacheFile
;
675 pkgCache
*Cache
= CacheFile
.GetPkgCache();
676 if (unlikely(Cache
== NULL
))
679 CacheSetHelperVirtuals
helper(false);
680 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
681 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
682 return _error
->Error(_("No packages found"));
683 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
685 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
686 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
687 bool const Important
= _config
->FindB("APT::Cache::Important", false);
688 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
689 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
690 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
691 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
692 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
693 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
694 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
695 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
696 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
697 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
698 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
699 bool const ShowImplicit
= _config
->FindB("APT::Cache::ShowImplicit", false);
701 while (verset
.empty() != true)
703 pkgCache::VerIterator Ver
= *verset
.begin();
704 verset
.erase(verset
.begin());
705 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
706 Shown
[Pkg
->ID
] = true;
708 cout
<< Pkg
.FullName(true) << endl
;
710 if (RevDepends
== true)
711 cout
<< "Reverse Depends:" << endl
;
712 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
713 D
.end() == false; ++D
)
716 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
717 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
718 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
719 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
720 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
721 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
722 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
723 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
725 if (ShowImplicit
== false && D
.IsImplicit())
728 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
730 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
733 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
739 if (ShowDepType
== true)
740 cout
<< D
.DepType() << ": ";
741 if (Trg
->VersionList
== 0)
742 cout
<< "<" << Trg
.FullName(true) << ">";
744 cout
<< Trg
.FullName(true);
745 if (ShowVersion
== true && D
->Version
!= 0)
746 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
749 if (Recurse
== true && Shown
[Trg
->ID
] == false)
751 Shown
[Trg
->ID
] = true;
752 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::CacheSetHelper::CANDIDATE
, helper
));
757 // Display all solutions
758 std::unique_ptr
<pkgCache::Version
*[]> List(D
.AllTargets());
759 pkgPrioSortList(*Cache
,List
.get());
760 for (pkgCache::Version
**I
= List
.get(); *I
!= 0; I
++)
762 pkgCache::VerIterator
V(*Cache
,*I
);
763 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
764 V
->ParentPkg
== D
->Package
)
766 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
768 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
770 Shown
[V
.ParentPkg()->ID
] = true;
771 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::CacheSetHelper::CANDIDATE
, helper
));
775 if (ShowOnlyFirstOr
== true)
776 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
780 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
781 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
782 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
787 // Depends - Print out a dependency tree /*{{{*/
788 // ---------------------------------------------------------------------
790 static bool Depends(CommandLine
&CmdL
)
792 return ShowDepends(CmdL
, false);
795 // RDepends - Print out a reverse dependency tree /*{{{*/
796 // ---------------------------------------------------------------------
798 static bool RDepends(CommandLine
&CmdL
)
800 return ShowDepends(CmdL
, true);
803 // xvcg - Generate a graph for xvcg /*{{{*/
804 // ---------------------------------------------------------------------
805 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
807 static bool XVcg(CommandLine
&CmdL
)
809 pkgCacheFile CacheFile
;
810 pkgCache
*Cache
= CacheFile
.GetPkgCache();
811 if (unlikely(Cache
== NULL
))
814 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
816 /* Normal packages are boxes
817 Pure Provides are triangles
819 rhomb are missing packages*/
820 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
822 /* Initialize the list of packages to show.
824 2 = To Show no recurse
825 3 = Emitted no recurse
828 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
829 enum TheFlags
{ForceNR
=(1<<0)};
830 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
831 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
832 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
834 // Show everything if no arguments given
835 if (CmdL
.FileList
[1] == 0)
836 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
839 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
841 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
844 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
846 if (Pkg
->VersionList
== 0)
849 if (Pkg
->ProvidesList
== 0)
850 ShapeMap
[Pkg
->ID
] = 0;
852 ShapeMap
[Pkg
->ID
] = 1;
857 if (Pkg
->ProvidesList
== 0)
858 ShapeMap
[Pkg
->ID
] = 2;
860 ShapeMap
[Pkg
->ID
] = 3;
864 // Load the list of packages from the command line into the show list
865 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
866 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
867 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
868 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
869 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
870 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
872 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
873 Pkg
!= pkgsets
[0].end(); ++Pkg
)
874 Show
[Pkg
->ID
] = ToShow
;
875 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
876 Pkg
!= pkgsets
[1].end(); ++Pkg
)
878 Show
[Pkg
->ID
] = ToShow
;
879 Flags
[Pkg
->ID
] |= ForceNR
;
883 cout
<< "graph: { title: \"packages\"" << endl
<<
884 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
885 "layout_downfactor: 8" << endl
;
891 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
893 // See we need to show this package
894 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
897 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
900 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
902 // Pure Provides and missing packages have no deps!
903 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
904 Show
[Pkg
->ID
] = Done
;
906 Show
[Pkg
->ID
] = DoneNR
;
909 Show
[Pkg
->ID
] = Done
;
912 // No deps to map out
913 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
916 pkgCache::VerIterator Ver
= Pkg
.VersionList();
917 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
919 // See if anything can meet this dep
920 // Walk along the actual package providing versions
922 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
923 for (pkgCache::VerIterator I
= DPkg
.VersionList();
924 I
.end() == false && Hit
== false; ++I
)
926 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
930 // Follow all provides
931 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
932 I
.end() == false && Hit
== false; ++I
)
934 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
939 // Only graph critical deps
940 if (D
.IsCritical() == true)
942 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
944 // Colour the node for recursion
945 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
947 /* If a conflicts does not meet anything in the database
948 then show the relation but do not recurse */
949 if (Hit
== false && D
.IsNegative() == true)
951 if (Show
[D
.TargetPkg()->ID
] == None
&&
952 Show
[D
.TargetPkg()->ID
] != ToShow
)
953 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
957 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
958 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
960 Show
[D
.TargetPkg()->ID
] = ToShow
;
967 case pkgCache::Dep::Conflicts
:
968 printf("label: \"conflicts\" color: lightgreen }\n");
970 case pkgCache::Dep::DpkgBreaks
:
971 printf("label: \"breaks\" color: lightgreen }\n");
973 case pkgCache::Dep::Obsoletes
:
974 printf("label: \"obsoletes\" color: lightgreen }\n");
977 case pkgCache::Dep::PreDepends
:
978 printf("label: \"predepends\" color: blue }\n");
990 /* Draw the box colours after the fact since we can not tell what colour
991 they should be until everything is finished drawing */
992 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
994 if (Show
[Pkg
->ID
] < DoneNR
)
997 if (Show
[Pkg
->ID
] == DoneNR
)
998 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
999 Shapes
[ShapeMap
[Pkg
->ID
]]);
1001 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
1002 Shapes
[ShapeMap
[Pkg
->ID
]]);
1014 // Dotty - Generate a graph for Dotty /*{{{*/
1015 // ---------------------------------------------------------------------
1016 /* Dotty is the graphvis program for generating graphs. It is a fairly
1017 simple queuing algorithm that just writes dependencies and nodes.
1018 http://www.research.att.com/sw/tools/graphviz/ */
1019 static bool Dotty(CommandLine
&CmdL
)
1021 pkgCacheFile CacheFile
;
1022 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1023 if (unlikely(Cache
== NULL
))
1026 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1028 /* Normal packages are boxes
1029 Pure Provides are triangles
1031 Hexagons are missing packages*/
1032 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1034 /* Initialize the list of packages to show.
1036 2 = To Show no recurse
1037 3 = Emitted no recurse
1040 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1041 enum TheFlags
{ForceNR
=(1<<0)};
1042 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1043 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1044 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1046 // Show everything if no arguments given
1047 if (CmdL
.FileList
[1] == 0)
1048 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1051 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1053 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1056 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1058 if (Pkg
->VersionList
== 0)
1061 if (Pkg
->ProvidesList
== 0)
1062 ShapeMap
[Pkg
->ID
] = 0;
1064 ShapeMap
[Pkg
->ID
] = 1;
1069 if (Pkg
->ProvidesList
== 0)
1070 ShapeMap
[Pkg
->ID
] = 2;
1072 ShapeMap
[Pkg
->ID
] = 3;
1076 // Load the list of packages from the command line into the show list
1077 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1078 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
1079 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1080 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1081 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1082 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1084 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1085 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1086 Show
[Pkg
->ID
] = ToShow
;
1087 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1088 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1090 Show
[Pkg
->ID
] = ToShow
;
1091 Flags
[Pkg
->ID
] |= ForceNR
;
1095 printf("digraph packages {\n");
1096 printf("concentrate=true;\n");
1097 printf("size=\"30,40\";\n");
1103 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1105 // See we need to show this package
1106 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1110 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1112 // Pure Provides and missing packages have no deps!
1113 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1114 Show
[Pkg
->ID
] = Done
;
1116 Show
[Pkg
->ID
] = DoneNR
;
1119 Show
[Pkg
->ID
] = Done
;
1122 // No deps to map out
1123 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1126 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1127 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1129 // See if anything can meet this dep
1130 // Walk along the actual package providing versions
1132 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1133 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1134 I
.end() == false && Hit
== false; ++I
)
1136 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1140 // Follow all provides
1141 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1142 I
.end() == false && Hit
== false; ++I
)
1144 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1148 // Only graph critical deps
1149 if (D
.IsCritical() == true)
1151 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1153 // Colour the node for recursion
1154 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1156 /* If a conflicts does not meet anything in the database
1157 then show the relation but do not recurse */
1158 if (Hit
== false && D
.IsNegative() == true)
1160 if (Show
[D
.TargetPkg()->ID
] == None
&&
1161 Show
[D
.TargetPkg()->ID
] != ToShow
)
1162 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1166 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1167 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1169 Show
[D
.TargetPkg()->ID
] = ToShow
;
1176 case pkgCache::Dep::Conflicts
:
1177 case pkgCache::Dep::Obsoletes
:
1178 case pkgCache::Dep::DpkgBreaks
:
1179 printf("[color=springgreen];\n");
1182 case pkgCache::Dep::PreDepends
:
1183 printf("[color=blue];\n");
1195 /* Draw the box colours after the fact since we can not tell what colour
1196 they should be until everything is finished drawing */
1197 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1199 if (Show
[Pkg
->ID
] < DoneNR
)
1202 // Orange box for early recursion stoppage
1203 if (Show
[Pkg
->ID
] == DoneNR
)
1204 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1205 Shapes
[ShapeMap
[Pkg
->ID
]]);
1207 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1208 Shapes
[ShapeMap
[Pkg
->ID
]]);
1220 pkgCache::DescFile
*Df
;
1221 pkgCache::VerIterator V
;
1225 // Search - Perform a search /*{{{*/
1226 // ---------------------------------------------------------------------
1227 /* This searches the package names and package descriptions for a pattern */
1228 static bool Search(CommandLine
&CmdL
)
1230 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1231 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1232 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1234 pkgCacheFile CacheFile
;
1235 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1236 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1237 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1240 // Make sure there is at least one argument
1241 if (NumPatterns
< 1)
1242 return _error
->Error(_("You must give at least one search pattern"));
1244 // Compile the regex pattern
1245 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1246 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1247 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1249 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1253 regfree(&Patterns
[I
]);
1254 return _error
->Error("Regex compilation error");
1258 if (_error
->PendingError() == true)
1260 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1261 regfree(&Patterns
[I
]);
1265 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1266 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1267 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1269 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1270 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1272 // Map versions that we want to write out onto the VerList array.
1273 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1275 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1276 size_t unmatched
= 0, matched
= 0;
1277 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1279 if (PatternMatch
[PatternOffset
+ I
] == true)
1281 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1282 PatternMatch
[PatternOffset
+ I
] = true;
1287 // already dealt with this package?
1288 if (matched
== NumPatterns
)
1291 // Doing names only, drop any that don't match..
1292 if (NamesOnly
== true && unmatched
== NumPatterns
)
1295 // Find the proper version to use
1296 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1297 if (P
.end() == true)
1299 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1300 if (V
.end() == false)
1302 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1303 //FIXME: packages without a description can't be found
1304 if (D
.end() == true)
1306 DFList
[G
->ID
].Df
= D
.FileList();
1307 DFList
[G
->ID
].V
= V
;
1308 DFList
[G
->ID
].ID
= G
->ID
;
1311 if (unmatched
== NumPatterns
)
1314 // Include all the packages that provide matching names too
1315 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1317 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1318 if (V
.end() == true)
1321 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1322 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1323 //FIXME: packages without a description can't be found
1324 if (D
.end() == true)
1326 DFList
[id
].Df
= D
.FileList();
1330 size_t const PrvPatternOffset
= id
* NumPatterns
;
1331 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1332 PatternMatch
[PrvPatternOffset
+ I
] |= PatternMatch
[PatternOffset
+ I
];
1336 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1338 // Create the text record parser
1339 pkgRecords
Recs(*Cache
);
1340 // Iterate over all the version records and check them
1341 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1343 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1344 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1346 if (NamesOnly
== false)
1348 string
const LongDesc
= P
.LongDesc();
1349 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1351 if (PatternMatch
[PatternOffset
+ I
] == true)
1353 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1354 PatternMatch
[PatternOffset
+ I
] = true;
1358 bool matchedAll
= true;
1359 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1360 if (PatternMatch
[PatternOffset
+ I
] == false)
1366 if (matchedAll
== true)
1368 if (ShowFull
== true)
1369 DisplayRecordV1(CacheFile
, J
->V
, std::cout
);
1371 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1376 delete [] PatternMatch
;
1377 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1378 regfree(&Patterns
[I
]);
1381 return _error
->Error("Write to stdout failed");
1385 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1386 static bool ShowAuto(CommandLine
&)
1388 pkgCacheFile CacheFile
;
1389 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1390 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1391 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1394 std::vector
<string
> packages
;
1395 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1397 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1398 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1399 packages
.push_back(P
.Name());
1401 std::sort(packages
.begin(), packages
.end());
1403 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1406 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1410 // ShowPkgNames - Show package names /*{{{*/
1411 // ---------------------------------------------------------------------
1412 /* This does a prefix match on the first argument */
1413 static bool ShowPkgNames(CommandLine
&CmdL
)
1415 pkgCacheFile CacheFile
;
1416 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1418 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1419 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1421 if (CmdL
.FileList
[1] != 0)
1423 for (;I
.end() != true; ++I
)
1425 if (All
== false && I
->FirstPackage
== 0)
1427 if (I
.FindPkg("any")->VersionList
== 0)
1429 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1430 cout
<< I
.Name() << endl
;
1437 for (;I
.end() != true; ++I
)
1439 if (All
== false && I
->FirstPackage
== 0)
1441 if (I
.FindPkg("any")->VersionList
== 0)
1443 cout
<< I
.Name() << endl
;
1449 // ShowSrcPackage - Show source package records /*{{{*/
1450 // ---------------------------------------------------------------------
1452 static bool ShowSrcPackage(CommandLine
&CmdL
)
1454 pkgCacheFile CacheFile
;
1455 pkgSourceList
*List
= CacheFile
.GetSourceList();
1456 if (unlikely(List
== NULL
))
1459 // Create the text record parsers
1460 pkgSrcRecords
SrcRecs(*List
);
1461 if (_error
->PendingError() == true)
1465 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1469 pkgSrcRecords::Parser
*Parse
;
1470 unsigned found_this
= 0;
1471 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1472 // SrcRecs.Find() will find both binary and source names
1473 if (_config
->FindB("APT::Cache::Only-Source", false) == true)
1474 if (Parse
->Package() != *I
)
1476 cout
<< Parse
->AsStr() << endl
;;
1480 if (found_this
== 0) {
1481 _error
->Warning(_("Unable to locate package %s"),*I
);
1486 _error
->Notice(_("No packages found"));
1490 // Policy - Show the results of the preferences file /*{{{*/
1491 // ---------------------------------------------------------------------
1493 static bool Policy(CommandLine
&CmdL
)
1495 pkgCacheFile CacheFile
;
1496 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1497 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1498 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1499 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1502 /* Should the MultiArchKiller be run to see which pseudo packages for an
1503 arch all package are currently installed? Activating it gives a speed
1504 penality for no real gain beside enhanced debugging, so in general no. */
1505 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1506 CacheFile
.GetDepCache();
1508 // Print out all of the package files
1509 if (CmdL
.FileList
[1] == 0)
1511 cout
<< _("Package files:") << endl
;
1512 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1514 if (F
.Flagged(pkgCache::Flag::NoPackages
))
1516 // Locate the associated index files so we can derive a description
1518 if (SrcList
->FindIndex(F
,Indx
) == false &&
1519 _system
->FindIndex(F
,Indx
) == false)
1520 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1523 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1525 // Print the reference information for the package
1526 string Str
= F
.RelStr();
1527 if (Str
.empty() == false)
1528 printf(" release %s\n",F
.RelStr().c_str());
1529 if (F
.Site() != 0 && F
.Site()[0] != 0)
1530 printf(" origin %s\n",F
.Site());
1533 // Show any packages have explicit pins
1534 cout
<< _("Pinned packages:") << endl
;
1535 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1536 for (;I
.end() != true; ++I
)
1538 // Old code for debugging
1539 if (_config
->FindI("APT::Policy", 1) < 1) {
1540 if (Plcy
->GetPriority(I
) == 0)
1543 // Print the package name and the version we are forcing to
1544 cout
<< " " << I
.FullName(true) << " -> ";
1546 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1547 if (V
.end() == true)
1548 cout
<< _("(not found)") << endl
;
1550 cout
<< V
.VerStr() << endl
;
1555 for (pkgCache::VerIterator V
= I
.VersionList(); !V
.end(); V
++) {
1556 auto Prio
= Plcy
->GetPriority(V
, false);
1561 // Print the package name and the version we are forcing to
1562 ioprintf(cout
, _("%s -> %s with priority %d\n"), I
.FullName(true).c_str(), V
.VerStr(), Prio
);
1568 char const * const msgInstalled
= _(" Installed: ");
1569 char const * const msgCandidate
= _(" Candidate: ");
1570 short const InstalledLessCandidate
=
1571 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1572 short const deepInstalled
=
1573 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1574 short const deepCandidate
=
1575 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1577 // Print out detailed information for each package
1578 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1579 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1580 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1582 cout
<< Pkg
.FullName(true) << ":" << endl
;
1584 // Installed version
1585 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1586 if (Pkg
->CurrentVer
== 0)
1587 cout
<< _("(none)") << endl
;
1589 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1591 // Candidate Version
1592 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1593 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1594 if (V
.end() == true)
1595 cout
<< _("(none)") << endl
;
1597 cout
<< V
.VerStr() << endl
;
1600 if (_config
->FindI("APT::Policy", 1) < 1 && Plcy
->GetPriority(Pkg
) != 0)
1602 cout
<< _(" Package pin: ");
1603 V
= Plcy
->GetMatch(Pkg
);
1604 if (V
.end() == true)
1605 cout
<< _("(not found)") << endl
;
1607 cout
<< V
.VerStr() << endl
;
1610 // Show the priority tables
1611 cout
<< _(" Version table:") << endl
;
1612 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1614 if (Pkg
.CurrentVer() == V
)
1615 cout
<< " *** " << V
.VerStr();
1617 cout
<< " " << V
.VerStr();
1618 if (_config
->FindI("APT::Policy", 1) < 1)
1619 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1621 cout
<< " " << Plcy
->GetPriority(V
) << endl
;
1622 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1624 // Locate the associated index files so we can derive a description
1626 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1627 _system
->FindIndex(VF
.File(),Indx
) == false)
1628 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1629 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1630 Indx
->Describe(true).c_str());
1638 // Madison - Look a bit like katie's madison /*{{{*/
1639 // ---------------------------------------------------------------------
1641 static bool Madison(CommandLine
&CmdL
)
1643 pkgCacheFile CacheFile
;
1644 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1649 // Create the src text record parsers and ignore errors about missing
1650 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1651 pkgSrcRecords
SrcRecs(*SrcList
);
1652 if (_error
->PendingError() == true)
1655 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1656 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1658 _error
->PushToStack();
1659 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1660 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1662 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1664 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1666 // This might be nice, but wouldn't uniquely identify the source -mdz
1667 // if (VF.File().Archive() != 0)
1669 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1670 // << VF.File().Archive() << endl;
1673 // Locate the associated index files so we can derive a description
1674 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1676 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1677 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1678 IF
!= Indexes
->end(); ++IF
)
1680 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1682 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1683 << (*IF
)->Describe(true) << endl
;
1692 pkgSrcRecords::Parser
*SrcParser
;
1693 bool foundSomething
= false;
1694 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1696 foundSomething
= true;
1697 // Maybe support Release info here too eventually
1698 cout
<< setw(10) << SrcParser
->Package() << " | "
1699 << setw(10) << SrcParser
->Version() << " | "
1700 << SrcParser
->Index().Describe(true) << endl
;
1702 if (foundSomething
== true)
1703 _error
->RevertToStack();
1705 _error
->MergeWithStack();
1711 // GenCaches - Call the main cache generator /*{{{*/
1712 // ---------------------------------------------------------------------
1714 static bool GenCaches(CommandLine
&)
1716 OpTextProgress
Progress(*_config
);
1718 pkgCacheFile CacheFile
;
1719 return CacheFile
.BuildCaches(&Progress
, true);
1722 // ShowHelp - Show a help screen /*{{{*/
1723 // ---------------------------------------------------------------------
1725 static bool ShowHelp(CommandLine
&)
1727 ioprintf(cout
, "%s %s (%s)\n", PACKAGE
, PACKAGE_VERSION
, COMMON_ARCH
);
1729 if (_config
->FindB("version") == true)
1733 _("Usage: apt-cache [options] command\n"
1734 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1735 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1737 "apt-cache is a low-level tool used to query information\n"
1738 "from APT's binary cache files\n"
1741 " gencaches - Build both the package and source cache\n"
1742 " showpkg - Show some general information for a single package\n"
1743 " showsrc - Show source records\n"
1744 " stats - Show some basic statistics\n"
1745 " dump - Show the entire file in a terse form\n"
1746 " dumpavail - Print an available file to stdout\n"
1747 " unmet - Show unmet dependencies\n"
1748 " search - Search the package list for a regex pattern\n"
1749 " show - Show a readable record for the package\n"
1750 " depends - Show raw dependency information for a package\n"
1751 " rdepends - Show reverse dependency information for a package\n"
1752 " pkgnames - List the names of all packages in the system\n"
1753 " dotty - Generate package graphs for GraphViz\n"
1754 " xvcg - Generate package graphs for xvcg\n"
1755 " policy - Show policy settings\n"
1758 " -h This help text.\n"
1759 " -p=? The package cache.\n"
1760 " -s=? The source cache.\n"
1761 " -q Disable progress indicator.\n"
1762 " -i Show only important deps for the unmet command.\n"
1763 " -c=? Read this configuration file\n"
1764 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1765 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1769 int main(int argc
,const char *argv
[]) /*{{{*/
1771 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1772 {"gencaches",&GenCaches
},
1773 {"showsrc",&ShowSrcPackage
},
1774 {"showpkg",&DumpPackage
},
1777 {"dumpavail",&DumpAvail
},
1780 {"depends",&Depends
},
1781 {"rdepends",&RDepends
},
1784 {"show",&ShowPackage
},
1785 {"pkgnames",&ShowPkgNames
},
1786 {"showauto",&ShowAuto
},
1788 {"madison",&Madison
},
1791 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1793 // Set up gettext support
1794 setlocale(LC_ALL
,"");
1795 textdomain(PACKAGE
);
1797 // Parse the command line and initialize the package library
1799 ParseCommandLine(CmdL
, Cmds
, Args
.data(), &_config
, &_system
, argc
, argv
, ShowHelp
);
1803 if (_config
->Exists("APT::Cache::Generate") == true)
1804 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1806 // Match the operation
1807 CmdL
.DispatchArg(Cmds
);
1809 // Print any errors or warnings found during parsing
1810 bool const Errors
= _error
->PendingError();
1811 if (_config
->FindI("quiet",0) > 0)
1812 _error
->DumpErrors();
1814 _error
->DumpErrors(GlobalError::DEBUG
);
1815 return Errors
== true ? 100 : 0;