]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
4 /* ######################################################################
6 apt-cache - Manages the cache files
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools.
11 Returns 100 on failure, 0 on success.
13 ##################################################################### */
15 // Include Files /*{{{*/
18 #include <apt-pkg/algorithms.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/indexfile.h>
25 #include <apt-pkg/init.h>
26 #include <apt-pkg/metaindex.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/pkgsystem.h>
29 #include <apt-pkg/policy.h>
30 #include <apt-pkg/progress.h>
31 #include <apt-pkg/sourcelist.h>
32 #include <apt-pkg/sptr.h>
33 #include <apt-pkg/srcrecords.h>
34 #include <apt-pkg/strutl.h>
35 #include <apt-pkg/tagfile.h>
36 #include <apt-pkg/version.h>
37 #include <apt-pkg/cacheiterators.h>
38 #include <apt-pkg/configuration.h>
39 #include <apt-pkg/depcache.h>
40 #include <apt-pkg/macros.h>
41 #include <apt-pkg/mmap.h>
42 #include <apt-pkg/pkgcache.h>
44 #include <apt-private/private-cacheset.h>
45 #include <apt-private/private-cmndline.h>
67 // LocalitySort - Sort a version list by package file locality /*{{{*/
68 // ---------------------------------------------------------------------
70 static int LocalityCompare(const void *a
, const void *b
)
72 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
73 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
82 if (A
->File
== B
->File
)
83 return A
->Offset
- B
->Offset
;
84 return A
->File
- B
->File
;
87 static void LocalitySort(pkgCache::VerFile
**begin
,
88 unsigned long Count
,size_t Size
)
90 qsort(begin
,Count
,Size
,LocalityCompare
);
93 static void LocalitySort(pkgCache::DescFile
**begin
,
94 unsigned long Count
,size_t Size
)
96 qsort(begin
,Count
,Size
,LocalityCompare
);
99 // UnMet - Show unmet dependencies /*{{{*/
100 // ---------------------------------------------------------------------
102 static bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const Important
)
105 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
108 pkgCache::DepIterator Start
;
109 pkgCache::DepIterator End
;
112 // Important deps only
113 if (Important
== true)
114 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
115 End
->Type
!= pkgCache::Dep::Depends
)
118 // Skip conflicts and replaces
119 if (End
.IsNegative() == true || End
->Type
== pkgCache::Dep::Replaces
)
122 // Verify the or group
124 pkgCache::DepIterator RealStart
= Start
;
127 // See if this dep is Ok
128 pkgCache::Version
**VList
= Start
.AllTargets();
149 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
150 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
153 // Print out the dep type
154 cout
<< " " << End
.DepType() << ": ";
160 cout
<< Start
.TargetPkg().FullName(true);
161 if (Start
.TargetVer() != 0)
162 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
175 static bool UnMet(CommandLine
&CmdL
)
177 bool const Important
= _config
->FindB("APT::Cache::Important",false);
179 pkgCacheFile CacheFile
;
180 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
183 if (CmdL
.FileSize() <= 1)
185 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; ++P
)
186 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
187 if (ShowUnMet(V
, Important
) == false)
192 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
193 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
194 APT::CacheSetHelper::CANDIDATE
, helper
);
195 for (APT::VersionList::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
196 if (ShowUnMet(V
, Important
) == false)
202 // DumpPackage - Show a dump of a package record /*{{{*/
203 // ---------------------------------------------------------------------
205 static bool DumpPackage(CommandLine
&CmdL
)
207 pkgCacheFile CacheFile
;
208 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
209 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
211 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
213 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
214 cout
<< "Versions: " << endl
;
215 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
217 cout
<< Cur
.VerStr();
218 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
219 cout
<< " (" << Vf
.File().FileName() << ")";
221 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
223 cout
<< " Description Language: " << D
.LanguageCode() << endl
224 << " File: " << D
.FileList().File().FileName() << endl
225 << " MD5: " << D
.md5() << endl
;
232 cout
<< "Reverse Depends: " << endl
;
233 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
235 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
237 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
242 cout
<< "Dependencies: " << endl
;
243 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
245 cout
<< Cur
.VerStr() << " - ";
246 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; ++Dep
)
247 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
251 cout
<< "Provides: " << endl
;
252 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
254 cout
<< Cur
.VerStr() << " - ";
255 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
256 cout
<< Prv
.ParentPkg().FullName(true) << " ";
259 cout
<< "Reverse Provides: " << endl
;
260 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
261 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
267 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
268 // ---------------------------------------------------------------------
270 static map_pointer_t
PackageNext(pkgCache::Package
const * const P
) { return P
->NextPackage
; }
271 static map_pointer_t
GroupNext(pkgCache::Group
const * const G
) { return G
->Next
; }
273 static void ShowHashTableStats(std::string Type
,
275 map_pointer_t
*Hashtable
,
277 map_pointer_t(*Next
)(T
const * const))
279 // hashtable stats for the HashTable
280 unsigned long NumBuckets
= Size
;
281 unsigned long UsedBuckets
= 0;
282 unsigned long UnusedBuckets
= 0;
283 unsigned long LongestBucket
= 0;
284 unsigned long ShortestBucket
= NumBuckets
;
285 unsigned long Entries
= 0;
286 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
288 T
*P
= StartP
+ Hashtable
[i
];
289 if(P
== 0 || P
== StartP
)
295 unsigned long ThisBucketSize
= 0;
296 for (; P
!= StartP
; P
= StartP
+ Next(P
))
298 Entries
+= ThisBucketSize
;
299 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
300 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
302 cout
<< "Total buckets in " << Type
<< ": " << NumBuckets
<< std::endl
;
303 cout
<< " Unused: " << UnusedBuckets
<< std::endl
;
304 cout
<< " Used: " << UsedBuckets
<< std::endl
;
305 cout
<< " Average entries: " << Entries
/(double)NumBuckets
<< std::endl
;
306 cout
<< " Longest: " << LongestBucket
<< std::endl
;
307 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
310 // Stats - Dump some nice statistics /*{{{*/
311 // ---------------------------------------------------------------------
313 static bool Stats(CommandLine
&)
315 pkgCacheFile CacheFile
;
316 pkgCache
*Cache
= CacheFile
.GetPkgCache();
317 if (unlikely(Cache
== NULL
))
320 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
321 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
322 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
323 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
330 pkgCache::PkgIterator I
= Cache
->PkgBegin();
331 for (;I
.end() != true; ++I
)
333 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
339 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
345 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
348 if (I
.ProvidesList()->NextProvides
== 0)
356 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
362 cout
<< _(" Normal packages: ") << Normal
<< endl
;
363 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
364 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
365 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
366 cout
<< _(" Missing: ") << Missing
<< endl
;
368 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
369 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
370 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
371 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
372 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
373 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
375 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
376 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
377 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
378 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
379 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
380 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
383 std::set
<map_stringitem_t
> stritems
;
384 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
385 stritems
.insert(G
->Name
);
386 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
388 stritems
.insert(P
->Arch
);
389 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
392 stritems
.insert(V
->VerStr
);
394 stritems
.insert(V
->Section
);
395 #if APT_PKG_ABI >= 413
396 stritems
.insert(V
->SourcePkgName
);
397 stritems
.insert(V
->SourceVerStr
);
399 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
402 stritems
.insert(D
->Version
);
404 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
406 stritems
.insert(D
->md5sum
);
407 stritems
.insert(D
->language_code
);
410 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
412 if (Prv
->ProvideVersion
!= 0)
413 stritems
.insert(Prv
->ProvideVersion
);
416 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
418 stritems
.insert(F
->FileName
);
419 stritems
.insert(F
->Archive
);
420 stritems
.insert(F
->Codename
);
421 stritems
.insert(F
->Component
);
422 stritems
.insert(F
->Version
);
423 stritems
.insert(F
->Origin
);
424 stritems
.insert(F
->Label
);
425 stritems
.insert(F
->Architecture
);
426 stritems
.insert(F
->Site
);
427 stritems
.insert(F
->IndexType
);
429 unsigned long Size
= 0;
430 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
431 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
433 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
436 unsigned long Slack
= 0;
437 for (int I
= 0; I
!= 7; I
++)
438 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
439 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
441 unsigned long Total
= 0;
442 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
443 Total
= Slack
+ Size
+
444 APT_CACHESIZE(GroupCount
, GroupSz
) +
445 APT_CACHESIZE(PackageCount
, PackageSz
) +
446 APT_CACHESIZE(VersionCount
, VersionSz
) +
447 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
448 APT_CACHESIZE(DependsCount
, DependencySz
) +
449 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
450 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
451 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
452 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
453 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
454 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
458 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
459 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
464 // Dump - show everything /*{{{*/
465 // ---------------------------------------------------------------------
466 /* This is worthless except fer debugging things */
467 static bool Dump(CommandLine
&)
469 pkgCacheFile CacheFile
;
470 pkgCache
*Cache
= CacheFile
.GetPkgCache();
471 if (unlikely(Cache
== NULL
))
474 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
476 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
478 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
479 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
481 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
482 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
483 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
484 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
485 DeNull(D
.TargetVer()) << std::endl
;
486 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
488 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
489 << " File: " << D
.FileList().File().FileName() << std::endl
490 << " MD5: " << D
.md5() << std::endl
;
495 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
497 std::cout
<< "File: " << F
.FileName() << std::endl
;
498 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
499 std::cout
<< " Size: " << F
->Size
<< std::endl
;
500 std::cout
<< " ID: " << F
->ID
<< std::endl
;
501 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
502 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
503 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
504 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
505 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
506 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
507 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
508 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
509 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
515 // DumpAvail - Print out the available list /*{{{*/
516 // ---------------------------------------------------------------------
517 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
518 make this run really fast, perhaps I went a little overboard.. */
519 static bool DumpAvail(CommandLine
&)
521 pkgCacheFile CacheFile
;
522 pkgCache
*Cache
= CacheFile
.GetPkgCache();
523 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
526 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
527 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
528 memset(VFList
,0,sizeof(*VFList
)*Count
);
530 // Map versions that we want to write out onto the VerList array.
531 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
533 if (P
->VersionList
== 0)
536 /* Find the proper version to use. If the policy says there are no
537 possible selections we return the installed version, if available..
538 This prevents dselect from making it obsolete. */
539 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
542 if (P
->CurrentVer
== 0)
547 pkgCache::VerFileIterator VF
= V
.FileList();
548 for (; VF
.end() == false ; ++VF
)
549 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
552 /* Okay, here we have a bit of a problem.. The policy has selected the
553 currently installed package - however it only exists in the
554 status file.. We need to write out something or dselect will mark
555 the package as obsolete! Thus we emit the status file entry, but
556 below we remove the status line to make it valid for the
557 available file. However! We only do this if their do exist *any*
558 non-source versions of the package - that way the dselect obsolete
559 handling works OK. */
560 if (VF
.end() == true)
562 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
564 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
566 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
573 if (VF
.end() == false)
581 LocalitySort(VFList
,Count
,sizeof(*VFList
));
583 // Iterate over all the package files and write them out.
584 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
585 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
587 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
588 if (File
.IsOk() == false)
590 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
594 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
595 if (_error
->PendingError() == true)
598 /* Write all of the records from this package file, since we
599 already did locality sorting we can now just seek through the
600 file in read order. We apply 1 more optimization here, since often
601 there will be < 1 byte gaps between records (for the \n) we read that
602 into the next buffer and offset a bit.. */
603 unsigned long Pos
= 0;
606 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
609 const pkgCache::VerFile
&VF
= **J
;
611 // Read the record and then write it out again.
612 unsigned long Jitter
= VF
.Offset
- Pos
;
615 if (PkgF
.Seek(VF
.Offset
) == false)
620 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
622 Buffer
[VF
.Size
+ Jitter
] = '\n';
625 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
628 TFRewriteData RW
[] = {{"Status", NULL
, NULL
},{"Config-Version", NULL
, NULL
},{NULL
, NULL
, NULL
}};
629 const char *Zero
= 0;
630 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
631 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
633 _error
->Error("Internal Error, Unable to parse a package record");
640 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
644 Pos
= VF
.Offset
+ VF
.Size
;
648 if (_error
->PendingError() == true)
654 return !_error
->PendingError();
657 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
658 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
660 pkgCacheFile CacheFile
;
661 pkgCache
*Cache
= CacheFile
.GetPkgCache();
662 if (unlikely(Cache
== NULL
))
665 CacheSetHelperVirtuals
helper(false);
666 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
667 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
668 return _error
->Error(_("No packages found"));
669 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
671 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
672 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
673 bool const Important
= _config
->FindB("APT::Cache::Important", false);
674 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
675 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
676 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
677 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
678 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
679 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
680 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
681 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
682 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
683 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
684 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
686 while (verset
.empty() != true)
688 pkgCache::VerIterator Ver
= *verset
.begin();
689 verset
.erase(verset
.begin());
690 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
691 Shown
[Pkg
->ID
] = true;
693 cout
<< Pkg
.FullName(true) << endl
;
695 if (RevDepends
== true)
696 cout
<< "Reverse Depends:" << endl
;
697 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
698 D
.end() == false; ++D
)
701 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
702 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
703 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
704 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
705 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
706 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
707 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
710 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
712 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
715 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
721 if (ShowDepType
== true)
722 cout
<< D
.DepType() << ": ";
723 if (Trg
->VersionList
== 0)
724 cout
<< "<" << Trg
.FullName(true) << ">";
726 cout
<< Trg
.FullName(true);
727 if (ShowVersion
== true && D
->Version
!= 0)
728 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
731 if (Recurse
== true && Shown
[Trg
->ID
] == false)
733 Shown
[Trg
->ID
] = true;
734 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::CacheSetHelper::CANDIDATE
, helper
));
739 // Display all solutions
740 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
741 pkgPrioSortList(*Cache
,List
);
742 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
744 pkgCache::VerIterator
V(*Cache
,*I
);
745 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
746 V
->ParentPkg
== D
->Package
)
748 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
750 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
752 Shown
[V
.ParentPkg()->ID
] = true;
753 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::CacheSetHelper::CANDIDATE
, helper
));
757 if (ShowOnlyFirstOr
== true)
758 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
762 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
763 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
764 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
769 // Depends - Print out a dependency tree /*{{{*/
770 // ---------------------------------------------------------------------
772 static bool Depends(CommandLine
&CmdL
)
774 return ShowDepends(CmdL
, false);
777 // RDepends - Print out a reverse dependency tree /*{{{*/
778 // ---------------------------------------------------------------------
780 static bool RDepends(CommandLine
&CmdL
)
782 return ShowDepends(CmdL
, true);
785 // xvcg - Generate a graph for xvcg /*{{{*/
786 // ---------------------------------------------------------------------
787 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
789 static bool XVcg(CommandLine
&CmdL
)
791 pkgCacheFile CacheFile
;
792 pkgCache
*Cache
= CacheFile
.GetPkgCache();
793 if (unlikely(Cache
== NULL
))
796 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
798 /* Normal packages are boxes
799 Pure Provides are triangles
801 rhomb are missing packages*/
802 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
804 /* Initialize the list of packages to show.
806 2 = To Show no recurse
807 3 = Emitted no recurse
810 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
811 enum TheFlags
{ForceNR
=(1<<0)};
812 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
813 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
814 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
816 // Show everything if no arguments given
817 if (CmdL
.FileList
[1] == 0)
818 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
821 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
823 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
826 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
828 if (Pkg
->VersionList
== 0)
831 if (Pkg
->ProvidesList
== 0)
832 ShapeMap
[Pkg
->ID
] = 0;
834 ShapeMap
[Pkg
->ID
] = 1;
839 if (Pkg
->ProvidesList
== 0)
840 ShapeMap
[Pkg
->ID
] = 2;
842 ShapeMap
[Pkg
->ID
] = 3;
846 // Load the list of packages from the command line into the show list
847 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
848 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
849 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
850 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
851 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
852 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
854 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
855 Pkg
!= pkgsets
[0].end(); ++Pkg
)
856 Show
[Pkg
->ID
] = ToShow
;
857 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
858 Pkg
!= pkgsets
[1].end(); ++Pkg
)
860 Show
[Pkg
->ID
] = ToShow
;
861 Flags
[Pkg
->ID
] |= ForceNR
;
865 cout
<< "graph: { title: \"packages\"" << endl
<<
866 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
867 "layout_downfactor: 8" << endl
;
873 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
875 // See we need to show this package
876 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
879 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
882 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
884 // Pure Provides and missing packages have no deps!
885 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
886 Show
[Pkg
->ID
] = Done
;
888 Show
[Pkg
->ID
] = DoneNR
;
891 Show
[Pkg
->ID
] = Done
;
894 // No deps to map out
895 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
898 pkgCache::VerIterator Ver
= Pkg
.VersionList();
899 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
901 // See if anything can meet this dep
902 // Walk along the actual package providing versions
904 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
905 for (pkgCache::VerIterator I
= DPkg
.VersionList();
906 I
.end() == false && Hit
== false; ++I
)
908 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
912 // Follow all provides
913 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
914 I
.end() == false && Hit
== false; ++I
)
916 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
921 // Only graph critical deps
922 if (D
.IsCritical() == true)
924 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
926 // Colour the node for recursion
927 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
929 /* If a conflicts does not meet anything in the database
930 then show the relation but do not recurse */
931 if (Hit
== false && D
.IsNegative() == true)
933 if (Show
[D
.TargetPkg()->ID
] == None
&&
934 Show
[D
.TargetPkg()->ID
] != ToShow
)
935 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
939 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
940 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
942 Show
[D
.TargetPkg()->ID
] = ToShow
;
949 case pkgCache::Dep::Conflicts
:
950 printf("label: \"conflicts\" color: lightgreen }\n");
952 case pkgCache::Dep::DpkgBreaks
:
953 printf("label: \"breaks\" color: lightgreen }\n");
955 case pkgCache::Dep::Obsoletes
:
956 printf("label: \"obsoletes\" color: lightgreen }\n");
959 case pkgCache::Dep::PreDepends
:
960 printf("label: \"predepends\" color: blue }\n");
972 /* Draw the box colours after the fact since we can not tell what colour
973 they should be until everything is finished drawing */
974 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
976 if (Show
[Pkg
->ID
] < DoneNR
)
979 if (Show
[Pkg
->ID
] == DoneNR
)
980 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
981 Shapes
[ShapeMap
[Pkg
->ID
]]);
983 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
984 Shapes
[ShapeMap
[Pkg
->ID
]]);
996 // Dotty - Generate a graph for Dotty /*{{{*/
997 // ---------------------------------------------------------------------
998 /* Dotty is the graphvis program for generating graphs. It is a fairly
999 simple queuing algorithm that just writes dependencies and nodes.
1000 http://www.research.att.com/sw/tools/graphviz/ */
1001 static bool Dotty(CommandLine
&CmdL
)
1003 pkgCacheFile CacheFile
;
1004 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1005 if (unlikely(Cache
== NULL
))
1008 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1010 /* Normal packages are boxes
1011 Pure Provides are triangles
1013 Hexagons are missing packages*/
1014 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1016 /* Initialize the list of packages to show.
1018 2 = To Show no recurse
1019 3 = Emitted no recurse
1022 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1023 enum TheFlags
{ForceNR
=(1<<0)};
1024 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1025 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1026 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1028 // Show everything if no arguments given
1029 if (CmdL
.FileList
[1] == 0)
1030 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1033 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1035 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1038 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1040 if (Pkg
->VersionList
== 0)
1043 if (Pkg
->ProvidesList
== 0)
1044 ShapeMap
[Pkg
->ID
] = 0;
1046 ShapeMap
[Pkg
->ID
] = 1;
1051 if (Pkg
->ProvidesList
== 0)
1052 ShapeMap
[Pkg
->ID
] = 2;
1054 ShapeMap
[Pkg
->ID
] = 3;
1058 // Load the list of packages from the command line into the show list
1059 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1060 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
1061 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1062 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1063 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1064 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1066 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1067 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1068 Show
[Pkg
->ID
] = ToShow
;
1069 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1070 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1072 Show
[Pkg
->ID
] = ToShow
;
1073 Flags
[Pkg
->ID
] |= ForceNR
;
1077 printf("digraph packages {\n");
1078 printf("concentrate=true;\n");
1079 printf("size=\"30,40\";\n");
1085 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1087 // See we need to show this package
1088 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1092 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1094 // Pure Provides and missing packages have no deps!
1095 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1096 Show
[Pkg
->ID
] = Done
;
1098 Show
[Pkg
->ID
] = DoneNR
;
1101 Show
[Pkg
->ID
] = Done
;
1104 // No deps to map out
1105 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1108 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1109 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1111 // See if anything can meet this dep
1112 // Walk along the actual package providing versions
1114 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1115 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1116 I
.end() == false && Hit
== false; ++I
)
1118 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1122 // Follow all provides
1123 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1124 I
.end() == false && Hit
== false; ++I
)
1126 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1130 // Only graph critical deps
1131 if (D
.IsCritical() == true)
1133 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1135 // Colour the node for recursion
1136 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1138 /* If a conflicts does not meet anything in the database
1139 then show the relation but do not recurse */
1140 if (Hit
== false && D
.IsNegative() == true)
1142 if (Show
[D
.TargetPkg()->ID
] == None
&&
1143 Show
[D
.TargetPkg()->ID
] != ToShow
)
1144 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1148 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1149 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1151 Show
[D
.TargetPkg()->ID
] = ToShow
;
1158 case pkgCache::Dep::Conflicts
:
1159 case pkgCache::Dep::Obsoletes
:
1160 case pkgCache::Dep::DpkgBreaks
:
1161 printf("[color=springgreen];\n");
1164 case pkgCache::Dep::PreDepends
:
1165 printf("[color=blue];\n");
1177 /* Draw the box colours after the fact since we can not tell what colour
1178 they should be until everything is finished drawing */
1179 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1181 if (Show
[Pkg
->ID
] < DoneNR
)
1184 // Orange box for early recursion stoppage
1185 if (Show
[Pkg
->ID
] == DoneNR
)
1186 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1187 Shapes
[ShapeMap
[Pkg
->ID
]]);
1189 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1190 Shapes
[ShapeMap
[Pkg
->ID
]]);
1200 // DisplayRecord - Displays the complete record for the package /*{{{*/
1201 // ---------------------------------------------------------------------
1202 /* This displays the package record from the proper package index file.
1203 It is not used by DumpAvail for performance reasons. */
1205 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1207 char const * const TagName
= "\nDescription";
1208 size_t const TagLen
= strlen(TagName
);
1209 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1211 if (DescP
[1] == ' ')
1213 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1222 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1224 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1225 if (unlikely(Cache
== NULL
))
1228 // Find an appropriate file
1229 pkgCache::VerFileIterator Vf
= V
.FileList();
1230 for (; Vf
.end() == false; ++Vf
)
1231 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1233 if (Vf
.end() == true)
1236 // Check and load the package list file
1237 pkgCache::PkgFileIterator I
= Vf
.File();
1238 if (I
.IsOk() == false)
1239 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1242 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1245 // Read the record (and ensure that it ends with a newline and NUL)
1246 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1247 Buffer
[Vf
->Size
] = '\n';
1248 Buffer
[Vf
->Size
+1] = '\0';
1249 if (PkgF
.Seek(Vf
->Offset
) == false ||
1250 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1256 // Get a pointer to start of Description field
1257 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1261 DescP
= Buffer
+ Vf
->Size
;
1263 // Write all but Description
1264 size_t const length
= DescP
- Buffer
;
1265 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1271 // Show the right description
1272 pkgRecords
Recs(*Cache
);
1273 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1274 if (Desc
.end() == false)
1276 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1277 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1278 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1280 // Find the first field after the description (if there is any)
1281 DescP
= skipDescriptionFields(DescP
);
1283 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1285 // write the rest of the buffer, but skip mixed in Descriptions* fields
1286 while (DescP
!= NULL
)
1288 const unsigned char * const Start
= DescP
;
1289 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1292 End
= &Buffer
[Vf
->Size
];
1297 ++End
; // get the newline into the output
1298 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1300 size_t const length
= End
- Start
;
1301 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1308 // write a final newline after the last field
1317 pkgCache::DescFile
*Df
;
1321 // Search - Perform a search /*{{{*/
1322 // ---------------------------------------------------------------------
1323 /* This searches the package names and package descriptions for a pattern */
1324 static bool Search(CommandLine
&CmdL
)
1326 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1327 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1328 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1330 pkgCacheFile CacheFile
;
1331 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1332 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1333 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1336 // Make sure there is at least one argument
1337 if (NumPatterns
< 1)
1338 return _error
->Error(_("You must give at least one search pattern"));
1340 // Compile the regex pattern
1341 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1342 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1343 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1345 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1349 regfree(&Patterns
[I
]);
1350 return _error
->Error("Regex compilation error");
1354 if (_error
->PendingError() == true)
1356 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1357 regfree(&Patterns
[I
]);
1361 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1362 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1363 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1365 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1366 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1368 // Map versions that we want to write out onto the VerList array.
1369 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1371 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1372 size_t unmatched
= 0, matched
= 0;
1373 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1375 if (PatternMatch
[PatternOffset
+ I
] == true)
1377 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1378 PatternMatch
[PatternOffset
+ I
] = true;
1383 // already dealt with this package?
1384 if (matched
== NumPatterns
)
1387 // Doing names only, drop any that don't match..
1388 if (NamesOnly
== true && unmatched
== NumPatterns
)
1391 // Find the proper version to use
1392 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1393 if (P
.end() == true)
1395 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1396 if (V
.end() == false)
1398 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1399 //FIXME: packages without a description can't be found
1400 if (D
.end() == true)
1402 DFList
[G
->ID
].Df
= D
.FileList();
1403 DFList
[G
->ID
].ID
= G
->ID
;
1406 if (unmatched
== NumPatterns
)
1409 // Include all the packages that provide matching names too
1410 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1412 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1413 if (V
.end() == true)
1416 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1417 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1418 //FIXME: packages without a description can't be found
1419 if (D
.end() == true)
1421 DFList
[id
].Df
= D
.FileList();
1424 size_t const PrvPatternOffset
= id
* NumPatterns
;
1425 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1426 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1430 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1432 // Create the text record parser
1433 pkgRecords
Recs(*Cache
);
1434 // Iterate over all the version records and check them
1435 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1437 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1438 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1440 if (NamesOnly
== false)
1442 string
const LongDesc
= P
.LongDesc();
1443 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1445 if (PatternMatch
[PatternOffset
+ I
] == true)
1447 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1448 PatternMatch
[PatternOffset
+ I
] = true;
1452 bool matchedAll
= true;
1453 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1454 if (PatternMatch
[PatternOffset
+ I
] == false)
1460 if (matchedAll
== true)
1462 if (ShowFull
== true)
1466 P
.GetRec(Start
,End
);
1467 fwrite(Start
,End
-Start
,1,stdout
);
1471 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1476 delete [] PatternMatch
;
1477 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1478 regfree(&Patterns
[I
]);
1480 return _error
->Error("Write to stdout failed");
1484 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1485 static bool ShowAuto(CommandLine
&)
1487 pkgCacheFile CacheFile
;
1488 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1489 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1490 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1493 std::vector
<string
> packages
;
1494 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1496 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1497 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1498 packages
.push_back(P
.Name());
1500 std::sort(packages
.begin(), packages
.end());
1502 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1505 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1509 // ShowPackage - Dump the package record to the screen /*{{{*/
1510 // ---------------------------------------------------------------------
1512 static bool ShowPackage(CommandLine
&CmdL
)
1514 pkgCacheFile CacheFile
;
1515 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1516 APT::CacheSetHelper::VerSelector
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1517 APT::CacheSetHelper::ALL
: APT::CacheSetHelper::CANDIDATE
;
1518 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1519 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1520 if (DisplayRecord(CacheFile
, Ver
) == false)
1523 if (verset
.empty() == true)
1525 if (helper
.virtualPkgs
.empty() == true)
1526 return _error
->Error(_("No packages found"));
1528 _error
->Notice(_("No packages found"));
1533 // ShowPkgNames - Show package names /*{{{*/
1534 // ---------------------------------------------------------------------
1535 /* This does a prefix match on the first argument */
1536 static bool ShowPkgNames(CommandLine
&CmdL
)
1538 pkgCacheFile CacheFile
;
1539 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1541 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1542 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1544 if (CmdL
.FileList
[1] != 0)
1546 for (;I
.end() != true; ++I
)
1548 if (All
== false && I
->FirstPackage
== 0)
1550 if (I
.FindPkg("any")->VersionList
== 0)
1552 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1553 cout
<< I
.Name() << endl
;
1560 for (;I
.end() != true; ++I
)
1562 if (All
== false && I
->FirstPackage
== 0)
1564 if (I
.FindPkg("any")->VersionList
== 0)
1566 cout
<< I
.Name() << endl
;
1572 // ShowSrcPackage - Show source package records /*{{{*/
1573 // ---------------------------------------------------------------------
1575 static bool ShowSrcPackage(CommandLine
&CmdL
)
1577 pkgCacheFile CacheFile
;
1578 pkgSourceList
*List
= CacheFile
.GetSourceList();
1579 if (unlikely(List
== NULL
))
1582 // Create the text record parsers
1583 pkgSrcRecords
SrcRecs(*List
);
1584 if (_error
->PendingError() == true)
1588 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1592 pkgSrcRecords::Parser
*Parse
;
1593 unsigned found_this
= 0;
1594 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1595 cout
<< Parse
->AsStr() << endl
;;
1599 if (found_this
== 0) {
1600 _error
->Warning(_("Unable to locate package %s"),*I
);
1605 _error
->Notice(_("No packages found"));
1609 // Policy - Show the results of the preferences file /*{{{*/
1610 // ---------------------------------------------------------------------
1612 static bool Policy(CommandLine
&CmdL
)
1614 pkgCacheFile CacheFile
;
1615 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1616 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1617 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1618 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1621 /* Should the MultiArchKiller be run to see which pseudo packages for an
1622 arch all package are currently installed? Activating it gives a speed
1623 penality for no real gain beside enhanced debugging, so in general no. */
1624 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1625 CacheFile
.GetDepCache();
1627 // Print out all of the package files
1628 if (CmdL
.FileList
[1] == 0)
1630 cout
<< _("Package files:") << endl
;
1631 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1633 // Locate the associated index files so we can derive a description
1635 if (SrcList
->FindIndex(F
,Indx
) == false &&
1636 _system
->FindIndex(F
,Indx
) == false)
1637 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1640 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1642 // Print the reference information for the package
1643 string Str
= F
.RelStr();
1644 if (Str
.empty() == false)
1645 printf(" release %s\n",F
.RelStr().c_str());
1646 if (F
.Site() != 0 && F
.Site()[0] != 0)
1647 printf(" origin %s\n",F
.Site());
1650 // Show any packages have explicit pins
1651 cout
<< _("Pinned packages:") << endl
;
1652 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1653 for (;I
.end() != true; ++I
)
1655 if (Plcy
->GetPriority(I
) == 0)
1658 // Print the package name and the version we are forcing to
1659 cout
<< " " << I
.FullName(true) << " -> ";
1661 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1662 if (V
.end() == true)
1663 cout
<< _("(not found)") << endl
;
1665 cout
<< V
.VerStr() << endl
;
1671 char const * const msgInstalled
= _(" Installed: ");
1672 char const * const msgCandidate
= _(" Candidate: ");
1673 short const InstalledLessCandidate
=
1674 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1675 short const deepInstalled
=
1676 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1677 short const deepCandidate
=
1678 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1680 // Print out detailed information for each package
1681 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1682 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1683 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1685 cout
<< Pkg
.FullName(true) << ":" << endl
;
1687 // Installed version
1688 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1689 if (Pkg
->CurrentVer
== 0)
1690 cout
<< _("(none)") << endl
;
1692 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1694 // Candidate Version
1695 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1696 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1697 if (V
.end() == true)
1698 cout
<< _("(none)") << endl
;
1700 cout
<< V
.VerStr() << endl
;
1703 if (Plcy
->GetPriority(Pkg
) != 0)
1705 cout
<< _(" Package pin: ");
1706 V
= Plcy
->GetMatch(Pkg
);
1707 if (V
.end() == true)
1708 cout
<< _("(not found)") << endl
;
1710 cout
<< V
.VerStr() << endl
;
1713 // Show the priority tables
1714 cout
<< _(" Version table:") << endl
;
1715 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1717 if (Pkg
.CurrentVer() == V
)
1718 cout
<< " *** " << V
.VerStr();
1720 cout
<< " " << V
.VerStr();
1721 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1722 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1724 // Locate the associated index files so we can derive a description
1726 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1727 _system
->FindIndex(VF
.File(),Indx
) == false)
1728 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1729 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1730 Indx
->Describe(true).c_str());
1738 // Madison - Look a bit like katie's madison /*{{{*/
1739 // ---------------------------------------------------------------------
1741 static bool Madison(CommandLine
&CmdL
)
1743 pkgCacheFile CacheFile
;
1744 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1749 // Create the src text record parsers and ignore errors about missing
1750 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1751 pkgSrcRecords
SrcRecs(*SrcList
);
1752 if (_error
->PendingError() == true)
1755 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1756 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1758 _error
->PushToStack();
1759 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1760 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1762 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1764 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1766 // This might be nice, but wouldn't uniquely identify the source -mdz
1767 // if (VF.File().Archive() != 0)
1769 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1770 // << VF.File().Archive() << endl;
1773 // Locate the associated index files so we can derive a description
1774 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1776 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1777 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1778 IF
!= Indexes
->end(); ++IF
)
1780 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1782 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1783 << (*IF
)->Describe(true) << endl
;
1792 pkgSrcRecords::Parser
*SrcParser
;
1793 bool foundSomething
= false;
1794 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1796 foundSomething
= true;
1797 // Maybe support Release info here too eventually
1798 cout
<< setw(10) << SrcParser
->Package() << " | "
1799 << setw(10) << SrcParser
->Version() << " | "
1800 << SrcParser
->Index().Describe(true) << endl
;
1802 if (foundSomething
== true)
1803 _error
->RevertToStack();
1805 _error
->MergeWithStack();
1811 // GenCaches - Call the main cache generator /*{{{*/
1812 // ---------------------------------------------------------------------
1814 static bool GenCaches(CommandLine
&)
1816 OpTextProgress
Progress(*_config
);
1818 pkgCacheFile CacheFile
;
1819 return CacheFile
.BuildCaches(&Progress
, true);
1822 // ShowHelp - Show a help screen /*{{{*/
1823 // ---------------------------------------------------------------------
1825 static bool ShowHelp(CommandLine
&)
1827 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1828 COMMON_ARCH
,__DATE__
,__TIME__
);
1830 if (_config
->FindB("version") == true)
1834 _("Usage: apt-cache [options] command\n"
1835 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1836 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1838 "apt-cache is a low-level tool used to query information\n"
1839 "from APT's binary cache files\n"
1842 " gencaches - Build both the package and source cache\n"
1843 " showpkg - Show some general information for a single package\n"
1844 " showsrc - Show source records\n"
1845 " stats - Show some basic statistics\n"
1846 " dump - Show the entire file in a terse form\n"
1847 " dumpavail - Print an available file to stdout\n"
1848 " unmet - Show unmet dependencies\n"
1849 " search - Search the package list for a regex pattern\n"
1850 " show - Show a readable record for the package\n"
1851 " depends - Show raw dependency information for a package\n"
1852 " rdepends - Show reverse dependency information for a package\n"
1853 " pkgnames - List the names of all packages in the system\n"
1854 " dotty - Generate package graphs for GraphViz\n"
1855 " xvcg - Generate package graphs for xvcg\n"
1856 " policy - Show policy settings\n"
1859 " -h This help text.\n"
1860 " -p=? The package cache.\n"
1861 " -s=? The source cache.\n"
1862 " -q Disable progress indicator.\n"
1863 " -i Show only important deps for the unmet command.\n"
1864 " -c=? Read this configuration file\n"
1865 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1866 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1870 int main(int argc
,const char *argv
[]) /*{{{*/
1872 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1873 {"gencaches",&GenCaches
},
1874 {"showsrc",&ShowSrcPackage
},
1875 {"showpkg",&DumpPackage
},
1878 {"dumpavail",&DumpAvail
},
1881 {"depends",&Depends
},
1882 {"rdepends",&RDepends
},
1885 {"show",&ShowPackage
},
1886 {"pkgnames",&ShowPkgNames
},
1887 {"showauto",&ShowAuto
},
1889 {"madison",&Madison
},
1892 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1894 // Set up gettext support
1895 setlocale(LC_ALL
,"");
1896 textdomain(PACKAGE
);
1898 // Parse the command line and initialize the package library
1900 ParseCommandLine(CmdL
, Cmds
, Args
.data(), &_config
, &_system
, argc
, argv
, ShowHelp
);
1904 if (_config
->Exists("APT::Cache::Generate") == true)
1905 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1907 // Match the operation
1908 CmdL
.DispatchArg(Cmds
);
1910 // Print any errors or warnings found during parsing
1911 bool const Errors
= _error
->PendingError();
1912 if (_config
->FindI("quiet",0) > 0)
1913 _error
->DumpErrors();
1915 _error
->DumpErrors(GlobalError::DEBUG
);
1916 return Errors
== true ? 100 : 0;