]>
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::VersionList::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 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
395 stritems
.insert(D
->Version
);
397 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
399 stritems
.insert(D
->md5sum
);
400 stritems
.insert(D
->language_code
);
403 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
405 if (Prv
->ProvideVersion
!= 0)
406 stritems
.insert(Prv
->ProvideVersion
);
409 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
411 stritems
.insert(F
->FileName
);
412 stritems
.insert(F
->Archive
);
413 stritems
.insert(F
->Codename
);
414 stritems
.insert(F
->Component
);
415 stritems
.insert(F
->Version
);
416 stritems
.insert(F
->Origin
);
417 stritems
.insert(F
->Label
);
418 stritems
.insert(F
->Architecture
);
419 stritems
.insert(F
->Site
);
420 stritems
.insert(F
->IndexType
);
422 unsigned long Size
= 0;
423 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
424 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
426 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
429 unsigned long Slack
= 0;
430 for (int I
= 0; I
!= 7; I
++)
431 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
432 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
434 unsigned long Total
= 0;
435 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
436 Total
= Slack
+ Size
+
437 APT_CACHESIZE(GroupCount
, GroupSz
) +
438 APT_CACHESIZE(PackageCount
, PackageSz
) +
439 APT_CACHESIZE(VersionCount
, VersionSz
) +
440 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
441 APT_CACHESIZE(DependsCount
, DependencySz
) +
442 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
443 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
444 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
445 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
446 (2 * Cache
->Head().HashTableSize
* sizeof(map_id_t
));
447 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
451 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTable(), Cache
->Head().HashTableSize
);
452 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTable(), Cache
->Head().HashTableSize
);
457 // Dump - show everything /*{{{*/
458 // ---------------------------------------------------------------------
459 /* This is worthless except fer debugging things */
460 static bool Dump(CommandLine
&)
462 pkgCacheFile CacheFile
;
463 pkgCache
*Cache
= CacheFile
.GetPkgCache();
464 if (unlikely(Cache
== NULL
))
467 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
469 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
471 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
472 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
474 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
475 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
476 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
477 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
478 DeNull(D
.TargetVer()) << std::endl
;
479 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
481 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
482 << " File: " << D
.FileList().File().FileName() << std::endl
483 << " MD5: " << D
.md5() << std::endl
;
488 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
490 std::cout
<< "File: " << F
.FileName() << std::endl
;
491 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
492 std::cout
<< " Size: " << F
->Size
<< std::endl
;
493 std::cout
<< " ID: " << F
->ID
<< std::endl
;
494 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
495 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
496 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
497 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
498 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
499 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
500 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
501 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
502 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
508 // DumpAvail - Print out the available list /*{{{*/
509 // ---------------------------------------------------------------------
510 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
511 make this run really fast, perhaps I went a little overboard.. */
512 static bool DumpAvail(CommandLine
&)
514 pkgCacheFile CacheFile
;
515 pkgCache
*Cache
= CacheFile
.GetPkgCache();
516 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
519 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
520 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
521 memset(VFList
,0,sizeof(*VFList
)*Count
);
523 // Map versions that we want to write out onto the VerList array.
524 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
526 if (P
->VersionList
== 0)
529 /* Find the proper version to use. If the policy says there are no
530 possible selections we return the installed version, if available..
531 This prevents dselect from making it obsolete. */
532 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
535 if (P
->CurrentVer
== 0)
540 pkgCache::VerFileIterator VF
= V
.FileList();
541 for (; VF
.end() == false ; ++VF
)
542 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
545 /* Okay, here we have a bit of a problem.. The policy has selected the
546 currently installed package - however it only exists in the
547 status file.. We need to write out something or dselect will mark
548 the package as obsolete! Thus we emit the status file entry, but
549 below we remove the status line to make it valid for the
550 available file. However! We only do this if their do exist *any*
551 non-source versions of the package - that way the dselect obsolete
552 handling works OK. */
553 if (VF
.end() == true)
555 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
557 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
559 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
566 if (VF
.end() == false)
574 LocalitySort(VFList
,Count
,sizeof(*VFList
));
576 // Iterate over all the package files and write them out.
577 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
578 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
580 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
581 if (File
.IsOk() == false)
583 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
587 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
588 if (_error
->PendingError() == true)
591 /* Write all of the records from this package file, since we
592 already did locality sorting we can now just seek through the
593 file in read order. We apply 1 more optimization here, since often
594 there will be < 1 byte gaps between records (for the \n) we read that
595 into the next buffer and offset a bit.. */
596 unsigned long Pos
= 0;
599 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
602 const pkgCache::VerFile
&VF
= **J
;
604 // Read the record and then write it out again.
605 unsigned long Jitter
= VF
.Offset
- Pos
;
608 if (PkgF
.Seek(VF
.Offset
) == false)
613 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
615 Buffer
[VF
.Size
+ Jitter
] = '\n';
618 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
621 TFRewriteData RW
[] = {{"Status", NULL
, NULL
},{"Config-Version", NULL
, NULL
},{NULL
, NULL
, NULL
}};
622 const char *Zero
= 0;
623 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
624 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
626 _error
->Error("Internal Error, Unable to parse a package record");
633 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
637 Pos
= VF
.Offset
+ VF
.Size
;
641 if (_error
->PendingError() == true)
647 return !_error
->PendingError();
650 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
651 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
653 pkgCacheFile CacheFile
;
654 pkgCache
*Cache
= CacheFile
.GetPkgCache();
655 if (unlikely(Cache
== NULL
))
658 CacheSetHelperVirtuals
helper(false);
659 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionList::CANDIDATE
, helper
);
660 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
661 return _error
->Error(_("No packages found"));
662 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
664 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
665 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
666 bool const Important
= _config
->FindB("APT::Cache::Important", false);
667 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
668 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
669 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
670 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
671 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
672 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
673 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
674 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
675 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
676 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
677 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
679 while (verset
.empty() != true)
681 pkgCache::VerIterator Ver
= *verset
.begin();
682 verset
.erase(verset
.begin());
683 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
684 Shown
[Pkg
->ID
] = true;
686 cout
<< Pkg
.FullName(true) << endl
;
688 if (RevDepends
== true)
689 cout
<< "Reverse Depends:" << endl
;
690 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
691 D
.end() == false; ++D
)
694 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
695 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
696 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
697 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
698 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
699 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
700 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
703 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
705 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
708 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
714 if (ShowDepType
== true)
715 cout
<< D
.DepType() << ": ";
716 if (Trg
->VersionList
== 0)
717 cout
<< "<" << Trg
.FullName(true) << ">";
719 cout
<< Trg
.FullName(true);
720 if (ShowVersion
== true && D
->Version
!= 0)
721 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
724 if (Recurse
== true && Shown
[Trg
->ID
] == false)
726 Shown
[Trg
->ID
] = true;
727 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
732 // Display all solutions
733 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
734 pkgPrioSortList(*Cache
,List
);
735 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
737 pkgCache::VerIterator
V(*Cache
,*I
);
738 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
739 V
->ParentPkg
== D
->Package
)
741 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
743 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
745 Shown
[V
.ParentPkg()->ID
] = true;
746 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
750 if (ShowOnlyFirstOr
== true)
751 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
755 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
756 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
757 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
762 // Depends - Print out a dependency tree /*{{{*/
763 // ---------------------------------------------------------------------
765 static bool Depends(CommandLine
&CmdL
)
767 return ShowDepends(CmdL
, false);
770 // RDepends - Print out a reverse dependency tree /*{{{*/
771 // ---------------------------------------------------------------------
773 static bool RDepends(CommandLine
&CmdL
)
775 return ShowDepends(CmdL
, true);
778 // xvcg - Generate a graph for xvcg /*{{{*/
779 // ---------------------------------------------------------------------
780 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
782 static bool XVcg(CommandLine
&CmdL
)
784 pkgCacheFile CacheFile
;
785 pkgCache
*Cache
= CacheFile
.GetPkgCache();
786 if (unlikely(Cache
== NULL
))
789 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
791 /* Normal packages are boxes
792 Pure Provides are triangles
794 rhomb are missing packages*/
795 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
797 /* Initialize the list of packages to show.
799 2 = To Show no recurse
800 3 = Emitted no recurse
803 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
804 enum TheFlags
{ForceNR
=(1<<0)};
805 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
806 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
807 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
809 // Show everything if no arguments given
810 if (CmdL
.FileList
[1] == 0)
811 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
814 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
816 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
819 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
821 if (Pkg
->VersionList
== 0)
824 if (Pkg
->ProvidesList
== 0)
825 ShapeMap
[Pkg
->ID
] = 0;
827 ShapeMap
[Pkg
->ID
] = 1;
832 if (Pkg
->ProvidesList
== 0)
833 ShapeMap
[Pkg
->ID
] = 2;
835 ShapeMap
[Pkg
->ID
] = 3;
839 // Load the list of packages from the command line into the show list
840 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
841 std::list
<APT::PackageSet::Modifier
> mods
;
842 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
843 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
844 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
845 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
847 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
848 Pkg
!= pkgsets
[0].end(); ++Pkg
)
849 Show
[Pkg
->ID
] = ToShow
;
850 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
851 Pkg
!= pkgsets
[1].end(); ++Pkg
)
853 Show
[Pkg
->ID
] = ToShow
;
854 Flags
[Pkg
->ID
] |= ForceNR
;
858 cout
<< "graph: { title: \"packages\"" << endl
<<
859 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
860 "layout_downfactor: 8" << endl
;
866 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
868 // See we need to show this package
869 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
872 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
875 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
877 // Pure Provides and missing packages have no deps!
878 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
879 Show
[Pkg
->ID
] = Done
;
881 Show
[Pkg
->ID
] = DoneNR
;
884 Show
[Pkg
->ID
] = Done
;
887 // No deps to map out
888 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
891 pkgCache::VerIterator Ver
= Pkg
.VersionList();
892 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
894 // See if anything can meet this dep
895 // Walk along the actual package providing versions
897 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
898 for (pkgCache::VerIterator I
= DPkg
.VersionList();
899 I
.end() == false && Hit
== false; ++I
)
901 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
905 // Follow all provides
906 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
907 I
.end() == false && Hit
== false; ++I
)
909 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
914 // Only graph critical deps
915 if (D
.IsCritical() == true)
917 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
919 // Colour the node for recursion
920 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
922 /* If a conflicts does not meet anything in the database
923 then show the relation but do not recurse */
924 if (Hit
== false && D
.IsNegative() == true)
926 if (Show
[D
.TargetPkg()->ID
] == None
&&
927 Show
[D
.TargetPkg()->ID
] != ToShow
)
928 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
932 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
933 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
935 Show
[D
.TargetPkg()->ID
] = ToShow
;
942 case pkgCache::Dep::Conflicts
:
943 printf("label: \"conflicts\" color: lightgreen }\n");
945 case pkgCache::Dep::DpkgBreaks
:
946 printf("label: \"breaks\" color: lightgreen }\n");
948 case pkgCache::Dep::Obsoletes
:
949 printf("label: \"obsoletes\" color: lightgreen }\n");
952 case pkgCache::Dep::PreDepends
:
953 printf("label: \"predepends\" color: blue }\n");
965 /* Draw the box colours after the fact since we can not tell what colour
966 they should be until everything is finished drawing */
967 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
969 if (Show
[Pkg
->ID
] < DoneNR
)
972 if (Show
[Pkg
->ID
] == DoneNR
)
973 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
974 Shapes
[ShapeMap
[Pkg
->ID
]]);
976 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
977 Shapes
[ShapeMap
[Pkg
->ID
]]);
989 // Dotty - Generate a graph for Dotty /*{{{*/
990 // ---------------------------------------------------------------------
991 /* Dotty is the graphvis program for generating graphs. It is a fairly
992 simple queuing algorithm that just writes dependencies and nodes.
993 http://www.research.att.com/sw/tools/graphviz/ */
994 static bool Dotty(CommandLine
&CmdL
)
996 pkgCacheFile CacheFile
;
997 pkgCache
*Cache
= CacheFile
.GetPkgCache();
998 if (unlikely(Cache
== NULL
))
1001 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1003 /* Normal packages are boxes
1004 Pure Provides are triangles
1006 Hexagons are missing packages*/
1007 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1009 /* Initialize the list of packages to show.
1011 2 = To Show no recurse
1012 3 = Emitted no recurse
1015 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1016 enum TheFlags
{ForceNR
=(1<<0)};
1017 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1018 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1019 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1021 // Show everything if no arguments given
1022 if (CmdL
.FileList
[1] == 0)
1023 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1026 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1028 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1031 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1033 if (Pkg
->VersionList
== 0)
1036 if (Pkg
->ProvidesList
== 0)
1037 ShapeMap
[Pkg
->ID
] = 0;
1039 ShapeMap
[Pkg
->ID
] = 1;
1044 if (Pkg
->ProvidesList
== 0)
1045 ShapeMap
[Pkg
->ID
] = 2;
1047 ShapeMap
[Pkg
->ID
] = 3;
1051 // Load the list of packages from the command line into the show list
1052 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1053 std::list
<APT::PackageSet::Modifier
> mods
;
1054 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1055 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1056 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1057 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1059 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1060 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1061 Show
[Pkg
->ID
] = ToShow
;
1062 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1063 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1065 Show
[Pkg
->ID
] = ToShow
;
1066 Flags
[Pkg
->ID
] |= ForceNR
;
1070 printf("digraph packages {\n");
1071 printf("concentrate=true;\n");
1072 printf("size=\"30,40\";\n");
1078 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1080 // See we need to show this package
1081 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1085 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1087 // Pure Provides and missing packages have no deps!
1088 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1089 Show
[Pkg
->ID
] = Done
;
1091 Show
[Pkg
->ID
] = DoneNR
;
1094 Show
[Pkg
->ID
] = Done
;
1097 // No deps to map out
1098 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1101 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1102 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1104 // See if anything can meet this dep
1105 // Walk along the actual package providing versions
1107 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1108 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1109 I
.end() == false && Hit
== false; ++I
)
1111 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1115 // Follow all provides
1116 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1117 I
.end() == false && Hit
== false; ++I
)
1119 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1123 // Only graph critical deps
1124 if (D
.IsCritical() == true)
1126 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1128 // Colour the node for recursion
1129 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1131 /* If a conflicts does not meet anything in the database
1132 then show the relation but do not recurse */
1133 if (Hit
== false && D
.IsNegative() == true)
1135 if (Show
[D
.TargetPkg()->ID
] == None
&&
1136 Show
[D
.TargetPkg()->ID
] != ToShow
)
1137 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1141 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1142 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1144 Show
[D
.TargetPkg()->ID
] = ToShow
;
1151 case pkgCache::Dep::Conflicts
:
1152 case pkgCache::Dep::Obsoletes
:
1153 case pkgCache::Dep::DpkgBreaks
:
1154 printf("[color=springgreen];\n");
1157 case pkgCache::Dep::PreDepends
:
1158 printf("[color=blue];\n");
1170 /* Draw the box colours after the fact since we can not tell what colour
1171 they should be until everything is finished drawing */
1172 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1174 if (Show
[Pkg
->ID
] < DoneNR
)
1177 // Orange box for early recursion stoppage
1178 if (Show
[Pkg
->ID
] == DoneNR
)
1179 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1180 Shapes
[ShapeMap
[Pkg
->ID
]]);
1182 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1183 Shapes
[ShapeMap
[Pkg
->ID
]]);
1193 // DisplayRecord - Displays the complete record for the package /*{{{*/
1194 // ---------------------------------------------------------------------
1195 /* This displays the package record from the proper package index file.
1196 It is not used by DumpAvail for performance reasons. */
1198 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1200 char const * const TagName
= "\nDescription";
1201 size_t const TagLen
= strlen(TagName
);
1202 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1204 if (DescP
[1] == ' ')
1206 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1215 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1217 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1218 if (unlikely(Cache
== NULL
))
1221 // Find an appropriate file
1222 pkgCache::VerFileIterator Vf
= V
.FileList();
1223 for (; Vf
.end() == false; ++Vf
)
1224 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1226 if (Vf
.end() == true)
1229 // Check and load the package list file
1230 pkgCache::PkgFileIterator I
= Vf
.File();
1231 if (I
.IsOk() == false)
1232 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1235 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1238 // Read the record (and ensure that it ends with a newline and NUL)
1239 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1240 Buffer
[Vf
->Size
] = '\n';
1241 Buffer
[Vf
->Size
+1] = '\0';
1242 if (PkgF
.Seek(Vf
->Offset
) == false ||
1243 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1249 // Get a pointer to start of Description field
1250 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1254 DescP
= Buffer
+ Vf
->Size
;
1256 // Write all but Description
1257 size_t const length
= DescP
- Buffer
;
1258 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1264 // Show the right description
1265 pkgRecords
Recs(*Cache
);
1266 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1267 if (Desc
.end() == false)
1269 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1270 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1271 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1273 // Find the first field after the description (if there is any)
1274 DescP
= skipDescriptionFields(DescP
);
1276 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1278 // write the rest of the buffer, but skip mixed in Descriptions* fields
1279 while (DescP
!= NULL
)
1281 const unsigned char * const Start
= DescP
;
1282 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1285 End
= &Buffer
[Vf
->Size
];
1290 ++End
; // get the newline into the output
1291 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1293 size_t const length
= End
- Start
;
1294 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1301 // write a final newline after the last field
1310 pkgCache::DescFile
*Df
;
1314 // Search - Perform a search /*{{{*/
1315 // ---------------------------------------------------------------------
1316 /* This searches the package names and package descriptions for a pattern */
1317 static bool Search(CommandLine
&CmdL
)
1319 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1320 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1321 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1323 pkgCacheFile CacheFile
;
1324 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1325 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1326 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1329 // Make sure there is at least one argument
1330 if (NumPatterns
< 1)
1331 return _error
->Error(_("You must give at least one search pattern"));
1333 // Compile the regex pattern
1334 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1335 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1336 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1338 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1342 regfree(&Patterns
[I
]);
1343 return _error
->Error("Regex compilation error");
1347 if (_error
->PendingError() == true)
1349 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1350 regfree(&Patterns
[I
]);
1354 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1355 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1356 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1358 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1359 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1361 // Map versions that we want to write out onto the VerList array.
1362 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1364 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1365 size_t unmatched
= 0, matched
= 0;
1366 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1368 if (PatternMatch
[PatternOffset
+ I
] == true)
1370 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1371 PatternMatch
[PatternOffset
+ I
] = true;
1376 // already dealt with this package?
1377 if (matched
== NumPatterns
)
1380 // Doing names only, drop any that don't match..
1381 if (NamesOnly
== true && unmatched
== NumPatterns
)
1384 // Find the proper version to use
1385 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1386 if (P
.end() == true)
1388 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1389 if (V
.end() == false)
1391 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1392 //FIXME: packages without a description can't be found
1393 if (D
.end() == true)
1395 DFList
[G
->ID
].Df
= D
.FileList();
1396 DFList
[G
->ID
].ID
= G
->ID
;
1399 if (unmatched
== NumPatterns
)
1402 // Include all the packages that provide matching names too
1403 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1405 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1406 if (V
.end() == true)
1409 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1410 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1411 //FIXME: packages without a description can't be found
1412 if (D
.end() == true)
1414 DFList
[id
].Df
= D
.FileList();
1417 size_t const PrvPatternOffset
= id
* NumPatterns
;
1418 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1419 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1423 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1425 // Create the text record parser
1426 pkgRecords
Recs(*Cache
);
1427 // Iterate over all the version records and check them
1428 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1430 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1431 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1433 if (NamesOnly
== false)
1435 string
const LongDesc
= P
.LongDesc();
1436 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1438 if (PatternMatch
[PatternOffset
+ I
] == true)
1440 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1441 PatternMatch
[PatternOffset
+ I
] = true;
1445 bool matchedAll
= true;
1446 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1447 if (PatternMatch
[PatternOffset
+ I
] == false)
1453 if (matchedAll
== true)
1455 if (ShowFull
== true)
1459 P
.GetRec(Start
,End
);
1460 fwrite(Start
,End
-Start
,1,stdout
);
1464 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1469 delete [] PatternMatch
;
1470 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1471 regfree(&Patterns
[I
]);
1473 return _error
->Error("Write to stdout failed");
1477 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1478 static bool ShowAuto(CommandLine
&)
1480 pkgCacheFile CacheFile
;
1481 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1482 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1483 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1486 std::vector
<string
> packages
;
1487 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1489 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1490 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1491 packages
.push_back(P
.Name());
1493 std::sort(packages
.begin(), packages
.end());
1495 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1498 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1502 // ShowPackage - Dump the package record to the screen /*{{{*/
1503 // ---------------------------------------------------------------------
1505 static bool ShowPackage(CommandLine
&CmdL
)
1507 pkgCacheFile CacheFile
;
1508 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1509 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1510 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1511 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1512 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1513 if (DisplayRecord(CacheFile
, Ver
) == false)
1516 if (verset
.empty() == true)
1518 if (helper
.virtualPkgs
.empty() == true)
1519 return _error
->Error(_("No packages found"));
1521 _error
->Notice(_("No packages found"));
1526 // ShowPkgNames - Show package names /*{{{*/
1527 // ---------------------------------------------------------------------
1528 /* This does a prefix match on the first argument */
1529 static bool ShowPkgNames(CommandLine
&CmdL
)
1531 pkgCacheFile CacheFile
;
1532 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1534 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1535 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1537 if (CmdL
.FileList
[1] != 0)
1539 for (;I
.end() != true; ++I
)
1541 if (All
== false && I
->FirstPackage
== 0)
1543 if (I
.FindPkg("any")->VersionList
== 0)
1545 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1546 cout
<< I
.Name() << endl
;
1553 for (;I
.end() != true; ++I
)
1555 if (All
== false && I
->FirstPackage
== 0)
1557 if (I
.FindPkg("any")->VersionList
== 0)
1559 cout
<< I
.Name() << endl
;
1565 // ShowSrcPackage - Show source package records /*{{{*/
1566 // ---------------------------------------------------------------------
1568 static bool ShowSrcPackage(CommandLine
&CmdL
)
1570 pkgCacheFile CacheFile
;
1571 pkgSourceList
*List
= CacheFile
.GetSourceList();
1572 if (unlikely(List
== NULL
))
1575 // Create the text record parsers
1576 pkgSrcRecords
SrcRecs(*List
);
1577 if (_error
->PendingError() == true)
1581 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1585 pkgSrcRecords::Parser
*Parse
;
1586 unsigned found_this
= 0;
1587 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1588 cout
<< Parse
->AsStr() << endl
;;
1592 if (found_this
== 0) {
1593 _error
->Warning(_("Unable to locate package %s"),*I
);
1598 _error
->Notice(_("No packages found"));
1602 // Policy - Show the results of the preferences file /*{{{*/
1603 // ---------------------------------------------------------------------
1605 static bool Policy(CommandLine
&CmdL
)
1607 pkgCacheFile CacheFile
;
1608 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1609 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1610 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1611 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1614 /* Should the MultiArchKiller be run to see which pseudo packages for an
1615 arch all package are currently installed? Activating it gives a speed
1616 penality for no real gain beside enhanced debugging, so in general no. */
1617 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1618 CacheFile
.GetDepCache();
1620 // Print out all of the package files
1621 if (CmdL
.FileList
[1] == 0)
1623 cout
<< _("Package files:") << endl
;
1624 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1626 // Locate the associated index files so we can derive a description
1628 if (SrcList
->FindIndex(F
,Indx
) == false &&
1629 _system
->FindIndex(F
,Indx
) == false)
1630 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1633 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1635 // Print the reference information for the package
1636 string Str
= F
.RelStr();
1637 if (Str
.empty() == false)
1638 printf(" release %s\n",F
.RelStr().c_str());
1639 if (F
.Site() != 0 && F
.Site()[0] != 0)
1640 printf(" origin %s\n",F
.Site());
1643 // Show any packages have explicit pins
1644 cout
<< _("Pinned packages:") << endl
;
1645 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1646 for (;I
.end() != true; ++I
)
1648 if (Plcy
->GetPriority(I
) == 0)
1651 // Print the package name and the version we are forcing to
1652 cout
<< " " << I
.FullName(true) << " -> ";
1654 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1655 if (V
.end() == true)
1656 cout
<< _("(not found)") << endl
;
1658 cout
<< V
.VerStr() << endl
;
1664 char const * const msgInstalled
= _(" Installed: ");
1665 char const * const msgCandidate
= _(" Candidate: ");
1666 short const InstalledLessCandidate
=
1667 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1668 short const deepInstalled
=
1669 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1670 short const deepCandidate
=
1671 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1673 // Print out detailed information for each package
1674 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1675 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1676 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1678 cout
<< Pkg
.FullName(true) << ":" << endl
;
1680 // Installed version
1681 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1682 if (Pkg
->CurrentVer
== 0)
1683 cout
<< _("(none)") << endl
;
1685 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1687 // Candidate Version
1688 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1689 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1690 if (V
.end() == true)
1691 cout
<< _("(none)") << endl
;
1693 cout
<< V
.VerStr() << endl
;
1696 if (Plcy
->GetPriority(Pkg
) != 0)
1698 cout
<< _(" Package pin: ");
1699 V
= Plcy
->GetMatch(Pkg
);
1700 if (V
.end() == true)
1701 cout
<< _("(not found)") << endl
;
1703 cout
<< V
.VerStr() << endl
;
1706 // Show the priority tables
1707 cout
<< _(" Version table:") << endl
;
1708 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1710 if (Pkg
.CurrentVer() == V
)
1711 cout
<< " *** " << V
.VerStr();
1713 cout
<< " " << V
.VerStr();
1714 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1715 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1717 // Locate the associated index files so we can derive a description
1719 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1720 _system
->FindIndex(VF
.File(),Indx
) == false)
1721 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1722 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1723 Indx
->Describe(true).c_str());
1731 // Madison - Look a bit like katie's madison /*{{{*/
1732 // ---------------------------------------------------------------------
1734 static bool Madison(CommandLine
&CmdL
)
1736 pkgCacheFile CacheFile
;
1737 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1742 // Create the src text record parsers and ignore errors about missing
1743 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1744 pkgSrcRecords
SrcRecs(*SrcList
);
1745 if (_error
->PendingError() == true)
1748 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1749 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1751 _error
->PushToStack();
1752 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1753 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1755 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1757 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1759 // This might be nice, but wouldn't uniquely identify the source -mdz
1760 // if (VF.File().Archive() != 0)
1762 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1763 // << VF.File().Archive() << endl;
1766 // Locate the associated index files so we can derive a description
1767 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1769 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1770 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1771 IF
!= Indexes
->end(); ++IF
)
1773 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1775 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1776 << (*IF
)->Describe(true) << endl
;
1785 pkgSrcRecords::Parser
*SrcParser
;
1786 bool foundSomething
= false;
1787 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1789 foundSomething
= true;
1790 // Maybe support Release info here too eventually
1791 cout
<< setw(10) << SrcParser
->Package() << " | "
1792 << setw(10) << SrcParser
->Version() << " | "
1793 << SrcParser
->Index().Describe(true) << endl
;
1795 if (foundSomething
== true)
1796 _error
->RevertToStack();
1798 _error
->MergeWithStack();
1804 // GenCaches - Call the main cache generator /*{{{*/
1805 // ---------------------------------------------------------------------
1807 static bool GenCaches(CommandLine
&)
1809 OpTextProgress
Progress(*_config
);
1811 pkgCacheFile CacheFile
;
1812 return CacheFile
.BuildCaches(&Progress
, true);
1815 // ShowHelp - Show a help screen /*{{{*/
1816 // ---------------------------------------------------------------------
1818 static bool ShowHelp(CommandLine
&)
1820 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1821 COMMON_ARCH
,__DATE__
,__TIME__
);
1823 if (_config
->FindB("version") == true)
1827 _("Usage: apt-cache [options] command\n"
1828 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1829 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1831 "apt-cache is a low-level tool used to query information\n"
1832 "from APT's binary cache files\n"
1835 " gencaches - Build both the package and source cache\n"
1836 " showpkg - Show some general information for a single package\n"
1837 " showsrc - Show source records\n"
1838 " stats - Show some basic statistics\n"
1839 " dump - Show the entire file in a terse form\n"
1840 " dumpavail - Print an available file to stdout\n"
1841 " unmet - Show unmet dependencies\n"
1842 " search - Search the package list for a regex pattern\n"
1843 " show - Show a readable record for the package\n"
1844 " depends - Show raw dependency information for a package\n"
1845 " rdepends - Show reverse dependency information for a package\n"
1846 " pkgnames - List the names of all packages in the system\n"
1847 " dotty - Generate package graphs for GraphViz\n"
1848 " xvcg - Generate package graphs for xvcg\n"
1849 " policy - Show policy settings\n"
1852 " -h This help text.\n"
1853 " -p=? The package cache.\n"
1854 " -s=? The source cache.\n"
1855 " -q Disable progress indicator.\n"
1856 " -i Show only important deps for the unmet command.\n"
1857 " -c=? Read this configuration file\n"
1858 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1859 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1863 int main(int argc
,const char *argv
[]) /*{{{*/
1865 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1866 {"gencaches",&GenCaches
},
1867 {"showsrc",&ShowSrcPackage
},
1868 {"showpkg",&DumpPackage
},
1871 {"dumpavail",&DumpAvail
},
1874 {"depends",&Depends
},
1875 {"rdepends",&RDepends
},
1878 {"show",&ShowPackage
},
1879 {"pkgnames",&ShowPkgNames
},
1880 {"showauto",&ShowAuto
},
1882 {"madison",&Madison
},
1885 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1887 // Set up gettext support
1888 setlocale(LC_ALL
,"");
1889 textdomain(PACKAGE
);
1891 // Parse the command line and initialize the package library
1892 CommandLine
CmdL(Args
.data(),_config
);
1893 if (pkgInitConfig(*_config
) == false ||
1894 CmdL
.Parse(argc
,argv
) == false ||
1895 pkgInitSystem(*_config
,_system
) == false)
1897 _error
->DumpErrors();
1901 // See if the help should be shown
1902 if (_config
->FindB("help") == true ||
1903 CmdL
.FileSize() == 0)
1909 // Deal with stdout not being a tty
1910 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1911 _config
->Set("quiet","1");
1913 if (_config
->Exists("APT::Cache::Generate") == true)
1914 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1916 // Match the operation
1917 CmdL
.DispatchArg(Cmds
);
1919 // Print any errors or warnings found during parsing
1920 bool const Errors
= _error
->PendingError();
1921 if (_config
->FindI("quiet",0) > 0)
1922 _error
->DumpErrors();
1924 _error
->DumpErrors(GlobalError::DEBUG
);
1925 return Errors
== true ? 100 : 0;