]>
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)
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 // ---------------------------------------------------------------------
271 static void ShowHashTableStats(std::string Type
,
273 map_pointer_t
*Hashtable
,
276 // hashtable stats for the HashTable
277 unsigned long NumBuckets
= Size
;
278 unsigned long UsedBuckets
= 0;
279 unsigned long UnusedBuckets
= 0;
280 unsigned long LongestBucket
= 0;
281 unsigned long ShortestBucket
= NumBuckets
;
282 unsigned long Entries
= 0;
283 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
285 T
*P
= StartP
+ Hashtable
[i
];
286 if(P
== 0 || P
== StartP
)
292 unsigned long ThisBucketSize
= 0;
293 for (; P
!= StartP
; P
= StartP
+ P
->Next
)
295 Entries
+= ThisBucketSize
;
296 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
297 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
299 cout
<< "Total buckets in " << Type
<< ": " << NumBuckets
<< std::endl
;
300 cout
<< " Unused: " << UnusedBuckets
<< std::endl
;
301 cout
<< " Used: " << UsedBuckets
<< std::endl
;
302 cout
<< " Average entries: " << Entries
/(double)NumBuckets
<< std::endl
;
303 cout
<< " Longest: " << LongestBucket
<< std::endl
;
304 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
307 // Stats - Dump some nice statistics /*{{{*/
308 // ---------------------------------------------------------------------
310 static bool Stats(CommandLine
&)
312 pkgCacheFile CacheFile
;
313 pkgCache
*Cache
= CacheFile
.GetPkgCache();
314 if (unlikely(Cache
== NULL
))
317 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
318 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
319 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
320 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
327 pkgCache::PkgIterator I
= Cache
->PkgBegin();
328 for (;I
.end() != true; ++I
)
330 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
336 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
342 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
345 if (I
.ProvidesList()->NextProvides
== 0)
353 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
359 cout
<< _(" Normal packages: ") << Normal
<< endl
;
360 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
361 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
362 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
363 cout
<< _(" Missing: ") << Missing
<< endl
;
365 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
366 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
367 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
368 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
369 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
370 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
372 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
373 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
374 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
375 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
376 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
377 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
380 std::set
<map_stringitem_t
> stritems
;
381 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
382 stritems
.insert(G
->Name
);
383 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
385 stritems
.insert(P
->Arch
);
386 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
389 stritems
.insert(V
->VerStr
);
391 stritems
.insert(V
->Section
);
392 stritems
.insert(V
->SourcePkgName
);
393 stritems
.insert(V
->SourceVerStr
);
394 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
397 stritems
.insert(D
->Version
);
399 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
401 stritems
.insert(D
->md5sum
);
402 stritems
.insert(D
->language_code
);
405 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
407 if (Prv
->ProvideVersion
!= 0)
408 stritems
.insert(Prv
->ProvideVersion
);
411 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
413 stritems
.insert(F
->FileName
);
414 stritems
.insert(F
->Archive
);
415 stritems
.insert(F
->Codename
);
416 stritems
.insert(F
->Component
);
417 stritems
.insert(F
->Version
);
418 stritems
.insert(F
->Origin
);
419 stritems
.insert(F
->Label
);
420 stritems
.insert(F
->Architecture
);
421 stritems
.insert(F
->Site
);
422 stritems
.insert(F
->IndexType
);
424 unsigned long Size
= 0;
425 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
426 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
428 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
431 unsigned long Slack
= 0;
432 for (int I
= 0; I
!= 7; I
++)
433 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
434 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
436 unsigned long Total
= 0;
437 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
438 Total
= Slack
+ Size
+
439 APT_CACHESIZE(GroupCount
, GroupSz
) +
440 APT_CACHESIZE(PackageCount
, PackageSz
) +
441 APT_CACHESIZE(VersionCount
, VersionSz
) +
442 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
443 APT_CACHESIZE(DependsCount
, DependencySz
) +
444 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
445 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
446 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
447 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
448 (2 * Cache
->Head().HashTableSize
* sizeof(map_id_t
));
449 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
453 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTable(), Cache
->Head().HashTableSize
);
454 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTable(), Cache
->Head().HashTableSize
);
459 // Dump - show everything /*{{{*/
460 // ---------------------------------------------------------------------
461 /* This is worthless except fer debugging things */
462 static bool Dump(CommandLine
&)
464 pkgCacheFile CacheFile
;
465 pkgCache
*Cache
= CacheFile
.GetPkgCache();
466 if (unlikely(Cache
== NULL
))
469 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
471 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
473 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
474 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
476 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
477 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
478 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
479 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
480 DeNull(D
.TargetVer()) << std::endl
;
481 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
483 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
484 << " File: " << D
.FileList().File().FileName() << std::endl
485 << " MD5: " << D
.md5() << std::endl
;
490 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
492 std::cout
<< "File: " << F
.FileName() << std::endl
;
493 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
494 std::cout
<< " Size: " << F
->Size
<< std::endl
;
495 std::cout
<< " ID: " << F
->ID
<< std::endl
;
496 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
497 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
498 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
499 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
500 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
501 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
502 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
503 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
504 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
510 // DumpAvail - Print out the available list /*{{{*/
511 // ---------------------------------------------------------------------
512 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
513 make this run really fast, perhaps I went a little overboard.. */
514 static bool DumpAvail(CommandLine
&)
516 pkgCacheFile CacheFile
;
517 pkgCache
*Cache
= CacheFile
.GetPkgCache();
518 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
521 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
522 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
523 memset(VFList
,0,sizeof(*VFList
)*Count
);
525 // Map versions that we want to write out onto the VerList array.
526 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
528 if (P
->VersionList
== 0)
531 /* Find the proper version to use. If the policy says there are no
532 possible selections we return the installed version, if available..
533 This prevents dselect from making it obsolete. */
534 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
537 if (P
->CurrentVer
== 0)
542 pkgCache::VerFileIterator VF
= V
.FileList();
543 for (; VF
.end() == false ; ++VF
)
544 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
547 /* Okay, here we have a bit of a problem.. The policy has selected the
548 currently installed package - however it only exists in the
549 status file.. We need to write out something or dselect will mark
550 the package as obsolete! Thus we emit the status file entry, but
551 below we remove the status line to make it valid for the
552 available file. However! We only do this if their do exist *any*
553 non-source versions of the package - that way the dselect obsolete
554 handling works OK. */
555 if (VF
.end() == true)
557 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
559 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
561 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
568 if (VF
.end() == false)
576 LocalitySort(VFList
,Count
,sizeof(*VFList
));
578 // Iterate over all the package files and write them out.
579 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
580 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
582 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
583 if (File
.IsOk() == false)
585 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
589 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
590 if (_error
->PendingError() == true)
593 /* Write all of the records from this package file, since we
594 already did locality sorting we can now just seek through the
595 file in read order. We apply 1 more optimization here, since often
596 there will be < 1 byte gaps between records (for the \n) we read that
597 into the next buffer and offset a bit.. */
598 unsigned long Pos
= 0;
601 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
604 const pkgCache::VerFile
&VF
= **J
;
606 // Read the record and then write it out again.
607 unsigned long Jitter
= VF
.Offset
- Pos
;
610 if (PkgF
.Seek(VF
.Offset
) == false)
615 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
617 Buffer
[VF
.Size
+ Jitter
] = '\n';
620 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
623 TFRewriteData RW
[] = {{"Status", NULL
, NULL
},{"Config-Version", NULL
, NULL
},{NULL
, NULL
, NULL
}};
624 const char *Zero
= 0;
625 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
626 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
628 _error
->Error("Internal Error, Unable to parse a package record");
635 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
639 Pos
= VF
.Offset
+ VF
.Size
;
643 if (_error
->PendingError() == true)
649 return !_error
->PendingError();
652 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
653 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
655 pkgCacheFile CacheFile
;
656 pkgCache
*Cache
= CacheFile
.GetPkgCache();
657 if (unlikely(Cache
== NULL
))
660 CacheSetHelperVirtuals
helper(false);
661 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
662 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
663 return _error
->Error(_("No packages found"));
664 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
666 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
667 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
668 bool const Important
= _config
->FindB("APT::Cache::Important", false);
669 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
670 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
671 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
672 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
673 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
674 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
675 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
676 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
677 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
678 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
679 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
681 while (verset
.empty() != true)
683 pkgCache::VerIterator Ver
= *verset
.begin();
684 verset
.erase(verset
.begin());
685 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
686 Shown
[Pkg
->ID
] = true;
688 cout
<< Pkg
.FullName(true) << endl
;
690 if (RevDepends
== true)
691 cout
<< "Reverse Depends:" << endl
;
692 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
693 D
.end() == false; ++D
)
696 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
697 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
698 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
699 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
700 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
701 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
702 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
705 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
707 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
710 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
716 if (ShowDepType
== true)
717 cout
<< D
.DepType() << ": ";
718 if (Trg
->VersionList
== 0)
719 cout
<< "<" << Trg
.FullName(true) << ">";
721 cout
<< Trg
.FullName(true);
722 if (ShowVersion
== true && D
->Version
!= 0)
723 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
726 if (Recurse
== true && Shown
[Trg
->ID
] == false)
728 Shown
[Trg
->ID
] = true;
729 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::CacheSetHelper::CANDIDATE
, helper
));
734 // Display all solutions
735 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
736 pkgPrioSortList(*Cache
,List
);
737 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
739 pkgCache::VerIterator
V(*Cache
,*I
);
740 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
741 V
->ParentPkg
== D
->Package
)
743 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
745 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
747 Shown
[V
.ParentPkg()->ID
] = true;
748 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::CacheSetHelper::CANDIDATE
, helper
));
752 if (ShowOnlyFirstOr
== true)
753 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
757 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
758 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
759 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
764 // Depends - Print out a dependency tree /*{{{*/
765 // ---------------------------------------------------------------------
767 static bool Depends(CommandLine
&CmdL
)
769 return ShowDepends(CmdL
, false);
772 // RDepends - Print out a reverse dependency tree /*{{{*/
773 // ---------------------------------------------------------------------
775 static bool RDepends(CommandLine
&CmdL
)
777 return ShowDepends(CmdL
, true);
780 // xvcg - Generate a graph for xvcg /*{{{*/
781 // ---------------------------------------------------------------------
782 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
784 static bool XVcg(CommandLine
&CmdL
)
786 pkgCacheFile CacheFile
;
787 pkgCache
*Cache
= CacheFile
.GetPkgCache();
788 if (unlikely(Cache
== NULL
))
791 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
793 /* Normal packages are boxes
794 Pure Provides are triangles
796 rhomb are missing packages*/
797 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
799 /* Initialize the list of packages to show.
801 2 = To Show no recurse
802 3 = Emitted no recurse
805 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
806 enum TheFlags
{ForceNR
=(1<<0)};
807 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
808 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
809 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
811 // Show everything if no arguments given
812 if (CmdL
.FileList
[1] == 0)
813 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
816 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
818 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
821 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
823 if (Pkg
->VersionList
== 0)
826 if (Pkg
->ProvidesList
== 0)
827 ShapeMap
[Pkg
->ID
] = 0;
829 ShapeMap
[Pkg
->ID
] = 1;
834 if (Pkg
->ProvidesList
== 0)
835 ShapeMap
[Pkg
->ID
] = 2;
837 ShapeMap
[Pkg
->ID
] = 3;
841 // Load the list of packages from the command line into the show list
842 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
843 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
844 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
845 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
846 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
847 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
849 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
850 Pkg
!= pkgsets
[0].end(); ++Pkg
)
851 Show
[Pkg
->ID
] = ToShow
;
852 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
853 Pkg
!= pkgsets
[1].end(); ++Pkg
)
855 Show
[Pkg
->ID
] = ToShow
;
856 Flags
[Pkg
->ID
] |= ForceNR
;
860 cout
<< "graph: { title: \"packages\"" << endl
<<
861 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
862 "layout_downfactor: 8" << endl
;
868 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
870 // See we need to show this package
871 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
874 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
877 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
879 // Pure Provides and missing packages have no deps!
880 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
881 Show
[Pkg
->ID
] = Done
;
883 Show
[Pkg
->ID
] = DoneNR
;
886 Show
[Pkg
->ID
] = Done
;
889 // No deps to map out
890 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
893 pkgCache::VerIterator Ver
= Pkg
.VersionList();
894 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
896 // See if anything can meet this dep
897 // Walk along the actual package providing versions
899 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
900 for (pkgCache::VerIterator I
= DPkg
.VersionList();
901 I
.end() == false && Hit
== false; ++I
)
903 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
907 // Follow all provides
908 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
909 I
.end() == false && Hit
== false; ++I
)
911 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
916 // Only graph critical deps
917 if (D
.IsCritical() == true)
919 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
921 // Colour the node for recursion
922 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
924 /* If a conflicts does not meet anything in the database
925 then show the relation but do not recurse */
926 if (Hit
== false && D
.IsNegative() == true)
928 if (Show
[D
.TargetPkg()->ID
] == None
&&
929 Show
[D
.TargetPkg()->ID
] != ToShow
)
930 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
934 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
935 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
937 Show
[D
.TargetPkg()->ID
] = ToShow
;
944 case pkgCache::Dep::Conflicts
:
945 printf("label: \"conflicts\" color: lightgreen }\n");
947 case pkgCache::Dep::DpkgBreaks
:
948 printf("label: \"breaks\" color: lightgreen }\n");
950 case pkgCache::Dep::Obsoletes
:
951 printf("label: \"obsoletes\" color: lightgreen }\n");
954 case pkgCache::Dep::PreDepends
:
955 printf("label: \"predepends\" color: blue }\n");
967 /* Draw the box colours after the fact since we can not tell what colour
968 they should be until everything is finished drawing */
969 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
971 if (Show
[Pkg
->ID
] < DoneNR
)
974 if (Show
[Pkg
->ID
] == DoneNR
)
975 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
976 Shapes
[ShapeMap
[Pkg
->ID
]]);
978 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
979 Shapes
[ShapeMap
[Pkg
->ID
]]);
991 // Dotty - Generate a graph for Dotty /*{{{*/
992 // ---------------------------------------------------------------------
993 /* Dotty is the graphvis program for generating graphs. It is a fairly
994 simple queuing algorithm that just writes dependencies and nodes.
995 http://www.research.att.com/sw/tools/graphviz/ */
996 static bool Dotty(CommandLine
&CmdL
)
998 pkgCacheFile CacheFile
;
999 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1000 if (unlikely(Cache
== NULL
))
1003 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1005 /* Normal packages are boxes
1006 Pure Provides are triangles
1008 Hexagons are missing packages*/
1009 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1011 /* Initialize the list of packages to show.
1013 2 = To Show no recurse
1014 3 = Emitted no recurse
1017 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1018 enum TheFlags
{ForceNR
=(1<<0)};
1019 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1020 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1021 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1023 // Show everything if no arguments given
1024 if (CmdL
.FileList
[1] == 0)
1025 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1028 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1030 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1033 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1035 if (Pkg
->VersionList
== 0)
1038 if (Pkg
->ProvidesList
== 0)
1039 ShapeMap
[Pkg
->ID
] = 0;
1041 ShapeMap
[Pkg
->ID
] = 1;
1046 if (Pkg
->ProvidesList
== 0)
1047 ShapeMap
[Pkg
->ID
] = 2;
1049 ShapeMap
[Pkg
->ID
] = 3;
1053 // Load the list of packages from the command line into the show list
1054 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1055 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
1056 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1057 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1058 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1059 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1061 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1062 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1063 Show
[Pkg
->ID
] = ToShow
;
1064 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1065 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1067 Show
[Pkg
->ID
] = ToShow
;
1068 Flags
[Pkg
->ID
] |= ForceNR
;
1072 printf("digraph packages {\n");
1073 printf("concentrate=true;\n");
1074 printf("size=\"30,40\";\n");
1080 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1082 // See we need to show this package
1083 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1087 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1089 // Pure Provides and missing packages have no deps!
1090 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1091 Show
[Pkg
->ID
] = Done
;
1093 Show
[Pkg
->ID
] = DoneNR
;
1096 Show
[Pkg
->ID
] = Done
;
1099 // No deps to map out
1100 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1103 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1104 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1106 // See if anything can meet this dep
1107 // Walk along the actual package providing versions
1109 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1110 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1111 I
.end() == false && Hit
== false; ++I
)
1113 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1117 // Follow all provides
1118 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1119 I
.end() == false && Hit
== false; ++I
)
1121 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1125 // Only graph critical deps
1126 if (D
.IsCritical() == true)
1128 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1130 // Colour the node for recursion
1131 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1133 /* If a conflicts does not meet anything in the database
1134 then show the relation but do not recurse */
1135 if (Hit
== false && D
.IsNegative() == true)
1137 if (Show
[D
.TargetPkg()->ID
] == None
&&
1138 Show
[D
.TargetPkg()->ID
] != ToShow
)
1139 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1143 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1144 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1146 Show
[D
.TargetPkg()->ID
] = ToShow
;
1153 case pkgCache::Dep::Conflicts
:
1154 case pkgCache::Dep::Obsoletes
:
1155 case pkgCache::Dep::DpkgBreaks
:
1156 printf("[color=springgreen];\n");
1159 case pkgCache::Dep::PreDepends
:
1160 printf("[color=blue];\n");
1172 /* Draw the box colours after the fact since we can not tell what colour
1173 they should be until everything is finished drawing */
1174 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1176 if (Show
[Pkg
->ID
] < DoneNR
)
1179 // Orange box for early recursion stoppage
1180 if (Show
[Pkg
->ID
] == DoneNR
)
1181 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1182 Shapes
[ShapeMap
[Pkg
->ID
]]);
1184 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1185 Shapes
[ShapeMap
[Pkg
->ID
]]);
1195 // DisplayRecord - Displays the complete record for the package /*{{{*/
1196 // ---------------------------------------------------------------------
1197 /* This displays the package record from the proper package index file.
1198 It is not used by DumpAvail for performance reasons. */
1200 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1202 char const * const TagName
= "\nDescription";
1203 size_t const TagLen
= strlen(TagName
);
1204 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1206 if (DescP
[1] == ' ')
1208 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1217 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1219 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1220 if (unlikely(Cache
== NULL
))
1223 // Find an appropriate file
1224 pkgCache::VerFileIterator Vf
= V
.FileList();
1225 for (; Vf
.end() == false; ++Vf
)
1226 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1228 if (Vf
.end() == true)
1231 // Check and load the package list file
1232 pkgCache::PkgFileIterator I
= Vf
.File();
1233 if (I
.IsOk() == false)
1234 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1237 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1240 // Read the record (and ensure that it ends with a newline and NUL)
1241 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1242 Buffer
[Vf
->Size
] = '\n';
1243 Buffer
[Vf
->Size
+1] = '\0';
1244 if (PkgF
.Seek(Vf
->Offset
) == false ||
1245 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1251 // Get a pointer to start of Description field
1252 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1256 DescP
= Buffer
+ Vf
->Size
;
1258 // Write all but Description
1259 size_t const length
= DescP
- Buffer
;
1260 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1266 // Show the right description
1267 pkgRecords
Recs(*Cache
);
1268 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1269 if (Desc
.end() == false)
1271 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1272 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1273 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1275 // Find the first field after the description (if there is any)
1276 DescP
= skipDescriptionFields(DescP
);
1278 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1280 // write the rest of the buffer, but skip mixed in Descriptions* fields
1281 while (DescP
!= NULL
)
1283 const unsigned char * const Start
= DescP
;
1284 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1287 End
= &Buffer
[Vf
->Size
];
1292 ++End
; // get the newline into the output
1293 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1295 size_t const length
= End
- Start
;
1296 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1303 // write a final newline after the last field
1312 pkgCache::DescFile
*Df
;
1316 // Search - Perform a search /*{{{*/
1317 // ---------------------------------------------------------------------
1318 /* This searches the package names and package descriptions for a pattern */
1319 static bool Search(CommandLine
&CmdL
)
1321 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1322 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1323 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1325 pkgCacheFile CacheFile
;
1326 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1327 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1328 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1331 // Make sure there is at least one argument
1332 if (NumPatterns
< 1)
1333 return _error
->Error(_("You must give at least one search pattern"));
1335 // Compile the regex pattern
1336 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1337 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1338 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1340 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1344 regfree(&Patterns
[I
]);
1345 return _error
->Error("Regex compilation error");
1349 if (_error
->PendingError() == true)
1351 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1352 regfree(&Patterns
[I
]);
1356 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1357 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1358 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1360 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1361 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1363 // Map versions that we want to write out onto the VerList array.
1364 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1366 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1367 size_t unmatched
= 0, matched
= 0;
1368 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1370 if (PatternMatch
[PatternOffset
+ I
] == true)
1372 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1373 PatternMatch
[PatternOffset
+ I
] = true;
1378 // already dealt with this package?
1379 if (matched
== NumPatterns
)
1382 // Doing names only, drop any that don't match..
1383 if (NamesOnly
== true && unmatched
== NumPatterns
)
1386 // Find the proper version to use
1387 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1388 if (P
.end() == true)
1390 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1391 if (V
.end() == false)
1393 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1394 //FIXME: packages without a description can't be found
1395 if (D
.end() == true)
1397 DFList
[G
->ID
].Df
= D
.FileList();
1398 DFList
[G
->ID
].ID
= G
->ID
;
1401 if (unmatched
== NumPatterns
)
1404 // Include all the packages that provide matching names too
1405 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1407 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1408 if (V
.end() == true)
1411 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1412 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1413 //FIXME: packages without a description can't be found
1414 if (D
.end() == true)
1416 DFList
[id
].Df
= D
.FileList();
1419 size_t const PrvPatternOffset
= id
* NumPatterns
;
1420 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1421 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1425 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1427 // Create the text record parser
1428 pkgRecords
Recs(*Cache
);
1429 // Iterate over all the version records and check them
1430 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1432 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1433 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1435 if (NamesOnly
== false)
1437 string
const LongDesc
= P
.LongDesc();
1438 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1440 if (PatternMatch
[PatternOffset
+ I
] == true)
1442 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1443 PatternMatch
[PatternOffset
+ I
] = true;
1447 bool matchedAll
= true;
1448 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1449 if (PatternMatch
[PatternOffset
+ I
] == false)
1455 if (matchedAll
== true)
1457 if (ShowFull
== true)
1461 P
.GetRec(Start
,End
);
1462 fwrite(Start
,End
-Start
,1,stdout
);
1466 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1471 delete [] PatternMatch
;
1472 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1473 regfree(&Patterns
[I
]);
1475 return _error
->Error("Write to stdout failed");
1479 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1480 static bool ShowAuto(CommandLine
&)
1482 pkgCacheFile CacheFile
;
1483 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1484 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1485 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1488 std::vector
<string
> packages
;
1489 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1491 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1492 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1493 packages
.push_back(P
.Name());
1495 std::sort(packages
.begin(), packages
.end());
1497 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1500 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1504 // ShowPackage - Dump the package record to the screen /*{{{*/
1505 // ---------------------------------------------------------------------
1507 static bool ShowPackage(CommandLine
&CmdL
)
1509 pkgCacheFile CacheFile
;
1510 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1511 APT::CacheSetHelper::VerSelector
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1512 APT::CacheSetHelper::ALL
: APT::CacheSetHelper::CANDIDATE
;
1513 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1514 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1515 if (DisplayRecord(CacheFile
, Ver
) == false)
1518 if (verset
.empty() == true)
1520 if (helper
.virtualPkgs
.empty() == true)
1521 return _error
->Error(_("No packages found"));
1523 _error
->Notice(_("No packages found"));
1528 // ShowPkgNames - Show package names /*{{{*/
1529 // ---------------------------------------------------------------------
1530 /* This does a prefix match on the first argument */
1531 static bool ShowPkgNames(CommandLine
&CmdL
)
1533 pkgCacheFile CacheFile
;
1534 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1536 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1537 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1539 if (CmdL
.FileList
[1] != 0)
1541 for (;I
.end() != true; ++I
)
1543 if (All
== false && I
->FirstPackage
== 0)
1545 if (I
.FindPkg("any")->VersionList
== 0)
1547 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1548 cout
<< I
.Name() << endl
;
1555 for (;I
.end() != true; ++I
)
1557 if (All
== false && I
->FirstPackage
== 0)
1559 if (I
.FindPkg("any")->VersionList
== 0)
1561 cout
<< I
.Name() << endl
;
1567 // ShowSrcPackage - Show source package records /*{{{*/
1568 // ---------------------------------------------------------------------
1570 static bool ShowSrcPackage(CommandLine
&CmdL
)
1572 pkgCacheFile CacheFile
;
1573 pkgSourceList
*List
= CacheFile
.GetSourceList();
1574 if (unlikely(List
== NULL
))
1577 // Create the text record parsers
1578 pkgSrcRecords
SrcRecs(*List
);
1579 if (_error
->PendingError() == true)
1583 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1587 pkgSrcRecords::Parser
*Parse
;
1588 unsigned found_this
= 0;
1589 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1590 cout
<< Parse
->AsStr() << endl
;;
1594 if (found_this
== 0) {
1595 _error
->Warning(_("Unable to locate package %s"),*I
);
1600 _error
->Notice(_("No packages found"));
1604 // Policy - Show the results of the preferences file /*{{{*/
1605 // ---------------------------------------------------------------------
1607 static bool Policy(CommandLine
&CmdL
)
1609 pkgCacheFile CacheFile
;
1610 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1611 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1612 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1613 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1616 /* Should the MultiArchKiller be run to see which pseudo packages for an
1617 arch all package are currently installed? Activating it gives a speed
1618 penality for no real gain beside enhanced debugging, so in general no. */
1619 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1620 CacheFile
.GetDepCache();
1622 // Print out all of the package files
1623 if (CmdL
.FileList
[1] == 0)
1625 cout
<< _("Package files:") << endl
;
1626 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1628 // Locate the associated index files so we can derive a description
1630 if (SrcList
->FindIndex(F
,Indx
) == false &&
1631 _system
->FindIndex(F
,Indx
) == false)
1632 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1635 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1637 // Print the reference information for the package
1638 string Str
= F
.RelStr();
1639 if (Str
.empty() == false)
1640 printf(" release %s\n",F
.RelStr().c_str());
1641 if (F
.Site() != 0 && F
.Site()[0] != 0)
1642 printf(" origin %s\n",F
.Site());
1645 // Show any packages have explicit pins
1646 cout
<< _("Pinned packages:") << endl
;
1647 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1648 for (;I
.end() != true; ++I
)
1650 if (Plcy
->GetPriority(I
) == 0)
1653 // Print the package name and the version we are forcing to
1654 cout
<< " " << I
.FullName(true) << " -> ";
1656 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1657 if (V
.end() == true)
1658 cout
<< _("(not found)") << endl
;
1660 cout
<< V
.VerStr() << endl
;
1666 char const * const msgInstalled
= _(" Installed: ");
1667 char const * const msgCandidate
= _(" Candidate: ");
1668 short const InstalledLessCandidate
=
1669 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1670 short const deepInstalled
=
1671 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1672 short const deepCandidate
=
1673 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1675 // Print out detailed information for each package
1676 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1677 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1678 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1680 cout
<< Pkg
.FullName(true) << ":" << endl
;
1682 // Installed version
1683 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1684 if (Pkg
->CurrentVer
== 0)
1685 cout
<< _("(none)") << endl
;
1687 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1689 // Candidate Version
1690 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1691 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1692 if (V
.end() == true)
1693 cout
<< _("(none)") << endl
;
1695 cout
<< V
.VerStr() << endl
;
1698 if (Plcy
->GetPriority(Pkg
) != 0)
1700 cout
<< _(" Package pin: ");
1701 V
= Plcy
->GetMatch(Pkg
);
1702 if (V
.end() == true)
1703 cout
<< _("(not found)") << endl
;
1705 cout
<< V
.VerStr() << endl
;
1708 // Show the priority tables
1709 cout
<< _(" Version table:") << endl
;
1710 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1712 if (Pkg
.CurrentVer() == V
)
1713 cout
<< " *** " << V
.VerStr();
1715 cout
<< " " << V
.VerStr();
1716 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1717 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1719 // Locate the associated index files so we can derive a description
1721 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1722 _system
->FindIndex(VF
.File(),Indx
) == false)
1723 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1724 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1725 Indx
->Describe(true).c_str());
1733 // Madison - Look a bit like katie's madison /*{{{*/
1734 // ---------------------------------------------------------------------
1736 static bool Madison(CommandLine
&CmdL
)
1738 pkgCacheFile CacheFile
;
1739 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1744 // Create the src text record parsers and ignore errors about missing
1745 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1746 pkgSrcRecords
SrcRecs(*SrcList
);
1747 if (_error
->PendingError() == true)
1750 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1751 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1753 _error
->PushToStack();
1754 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1755 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1757 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1759 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1761 // This might be nice, but wouldn't uniquely identify the source -mdz
1762 // if (VF.File().Archive() != 0)
1764 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1765 // << VF.File().Archive() << endl;
1768 // Locate the associated index files so we can derive a description
1769 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1771 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1772 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1773 IF
!= Indexes
->end(); ++IF
)
1775 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1777 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1778 << (*IF
)->Describe(true) << endl
;
1787 pkgSrcRecords::Parser
*SrcParser
;
1788 bool foundSomething
= false;
1789 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1791 foundSomething
= true;
1792 // Maybe support Release info here too eventually
1793 cout
<< setw(10) << SrcParser
->Package() << " | "
1794 << setw(10) << SrcParser
->Version() << " | "
1795 << SrcParser
->Index().Describe(true) << endl
;
1797 if (foundSomething
== true)
1798 _error
->RevertToStack();
1800 _error
->MergeWithStack();
1806 // GenCaches - Call the main cache generator /*{{{*/
1807 // ---------------------------------------------------------------------
1809 static bool GenCaches(CommandLine
&)
1811 OpTextProgress
Progress(*_config
);
1813 pkgCacheFile CacheFile
;
1814 return CacheFile
.BuildCaches(&Progress
, true);
1817 // ShowHelp - Show a help screen /*{{{*/
1818 // ---------------------------------------------------------------------
1820 static bool ShowHelp(CommandLine
&)
1822 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1823 COMMON_ARCH
,__DATE__
,__TIME__
);
1825 if (_config
->FindB("version") == true)
1829 _("Usage: apt-cache [options] command\n"
1830 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1831 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1833 "apt-cache is a low-level tool used to query information\n"
1834 "from APT's binary cache files\n"
1837 " gencaches - Build both the package and source cache\n"
1838 " showpkg - Show some general information for a single package\n"
1839 " showsrc - Show source records\n"
1840 " stats - Show some basic statistics\n"
1841 " dump - Show the entire file in a terse form\n"
1842 " dumpavail - Print an available file to stdout\n"
1843 " unmet - Show unmet dependencies\n"
1844 " search - Search the package list for a regex pattern\n"
1845 " show - Show a readable record for the package\n"
1846 " depends - Show raw dependency information for a package\n"
1847 " rdepends - Show reverse dependency information for a package\n"
1848 " pkgnames - List the names of all packages in the system\n"
1849 " dotty - Generate package graphs for GraphViz\n"
1850 " xvcg - Generate package graphs for xvcg\n"
1851 " policy - Show policy settings\n"
1854 " -h This help text.\n"
1855 " -p=? The package cache.\n"
1856 " -s=? The source cache.\n"
1857 " -q Disable progress indicator.\n"
1858 " -i Show only important deps for the unmet command.\n"
1859 " -c=? Read this configuration file\n"
1860 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1861 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1865 int main(int argc
,const char *argv
[]) /*{{{*/
1867 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1868 {"gencaches",&GenCaches
},
1869 {"showsrc",&ShowSrcPackage
},
1870 {"showpkg",&DumpPackage
},
1873 {"dumpavail",&DumpAvail
},
1876 {"depends",&Depends
},
1877 {"rdepends",&RDepends
},
1880 {"show",&ShowPackage
},
1881 {"pkgnames",&ShowPkgNames
},
1882 {"showauto",&ShowAuto
},
1884 {"madison",&Madison
},
1887 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1889 // Set up gettext support
1890 setlocale(LC_ALL
,"");
1891 textdomain(PACKAGE
);
1893 // Parse the command line and initialize the package library
1894 CommandLine
CmdL(Args
.data(),_config
);
1895 if (pkgInitConfig(*_config
) == false ||
1896 CmdL
.Parse(argc
,argv
) == false ||
1897 pkgInitSystem(*_config
,_system
) == false)
1899 _error
->DumpErrors();
1903 // See if the help should be shown
1904 if (_config
->FindB("help") == true ||
1905 CmdL
.FileSize() == 0)
1911 // Deal with stdout not being a tty
1912 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1913 _config
->Set("quiet","1");
1915 if (_config
->Exists("APT::Cache::Generate") == true)
1916 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1918 // Match the operation
1919 CmdL
.DispatchArg(Cmds
);
1921 // Print any errors or warnings found during parsing
1922 bool const Errors
= _error
->PendingError();
1923 if (_config
->FindI("quiet",0) > 0)
1924 _error
->DumpErrors();
1926 _error
->DumpErrors(GlobalError::DEBUG
);
1927 return Errors
== true ? 100 : 0;