]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
2fc721f693b58970b9c0d6d7f5b548af75905669
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
4 /* ######################################################################
6 apt-cache - Manages the cache files
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools.
11 Returns 100 on failure, 0 on success.
13 ##################################################################### */
15 // Include Files /*{{{*/
18 #include <apt-pkg/algorithms.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/indexfile.h>
25 #include <apt-pkg/init.h>
26 #include <apt-pkg/metaindex.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/pkgsystem.h>
29 #include <apt-pkg/policy.h>
30 #include <apt-pkg/progress.h>
31 #include <apt-pkg/sourcelist.h>
32 #include <apt-pkg/sptr.h>
33 #include <apt-pkg/srcrecords.h>
34 #include <apt-pkg/strutl.h>
35 #include <apt-pkg/tagfile.h>
36 #include <apt-pkg/version.h>
37 #include <apt-pkg/cacheiterators.h>
38 #include <apt-pkg/configuration.h>
39 #include <apt-pkg/depcache.h>
40 #include <apt-pkg/macros.h>
41 #include <apt-pkg/mmap.h>
42 #include <apt-pkg/pkgcache.h>
44 #include <apt-private/private-cacheset.h>
45 #include <apt-private/private-cmndline.h>
67 // LocalitySort - Sort a version list by package file locality /*{{{*/
68 // ---------------------------------------------------------------------
70 static int LocalityCompare(const void *a
, const void *b
)
72 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
73 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
82 if (A
->File
== B
->File
)
83 return A
->Offset
- B
->Offset
;
84 return A
->File
- B
->File
;
87 static void LocalitySort(pkgCache::VerFile
**begin
,
88 unsigned long Count
,size_t Size
)
90 qsort(begin
,Count
,Size
,LocalityCompare
);
93 static void LocalitySort(pkgCache::DescFile
**begin
,
94 unsigned long Count
,size_t Size
)
96 qsort(begin
,Count
,Size
,LocalityCompare
);
99 // UnMet - Show unmet dependencies /*{{{*/
100 // ---------------------------------------------------------------------
102 static bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const Important
)
105 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
108 pkgCache::DepIterator Start
;
109 pkgCache::DepIterator End
;
112 // Important deps only
113 if (Important
== true)
114 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
115 End
->Type
!= pkgCache::Dep::Depends
)
118 // Skip conflicts and replaces
119 if (End
.IsNegative() == true || End
->Type
== pkgCache::Dep::Replaces
)
122 // Verify the or group
124 pkgCache::DepIterator RealStart
= Start
;
127 // See if this dep is Ok
128 pkgCache::Version
**VList
= Start
.AllTargets();
149 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
150 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
153 // Print out the dep type
154 cout
<< " " << End
.DepType() << ": ";
160 cout
<< Start
.TargetPkg().FullName(true);
161 if (Start
.TargetVer() != 0)
162 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
175 static bool UnMet(CommandLine
&CmdL
)
177 bool const Important
= _config
->FindB("APT::Cache::Important",false);
179 pkgCacheFile CacheFile
;
180 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
183 if (CmdL
.FileSize() <= 1)
185 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; ++P
)
186 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
187 if (ShowUnMet(V
, Important
) == false)
192 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
193 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
194 APT::CacheSetHelper::CANDIDATE
, helper
);
195 for (APT::VersionList::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
196 if (ShowUnMet(V
, Important
) == false)
202 // DumpPackage - Show a dump of a package record /*{{{*/
203 // ---------------------------------------------------------------------
205 static bool DumpPackage(CommandLine
&CmdL
)
207 pkgCacheFile CacheFile
;
208 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
209 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
211 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
213 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
214 cout
<< "Versions: " << endl
;
215 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
217 cout
<< Cur
.VerStr();
218 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
219 cout
<< " (" << Vf
.File().FileName() << ")";
221 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
223 cout
<< " Description Language: " << D
.LanguageCode() << endl
224 << " File: " << D
.FileList().File().FileName() << endl
225 << " MD5: " << D
.md5() << endl
;
232 cout
<< "Reverse Depends: " << endl
;
233 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
235 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
237 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
242 cout
<< "Dependencies: " << endl
;
243 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
245 cout
<< Cur
.VerStr() << " - ";
246 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; ++Dep
)
247 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
251 cout
<< "Provides: " << endl
;
252 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
254 cout
<< Cur
.VerStr() << " - ";
255 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
256 cout
<< Prv
.ParentPkg().FullName(true) << " ";
259 cout
<< "Reverse Provides: " << endl
;
260 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
261 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
267 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
268 // ---------------------------------------------------------------------
270 static map_pointer_t
PackageNext(pkgCache::Package
const * const P
) { return P
->NextPackage
; }
271 static map_pointer_t
GroupNext(pkgCache::Group
const * const G
) { return G
->Next
; }
273 static void ShowHashTableStats(std::string Type
,
275 map_pointer_t
*Hashtable
,
277 map_pointer_t(*Next
)(T
const * const))
279 // hashtable stats for the HashTable
280 unsigned long NumBuckets
= Size
;
281 unsigned long UsedBuckets
= 0;
282 unsigned long UnusedBuckets
= 0;
283 unsigned long LongestBucket
= 0;
284 unsigned long ShortestBucket
= NumBuckets
;
285 unsigned long Entries
= 0;
286 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
288 T
*P
= StartP
+ Hashtable
[i
];
289 if(P
== 0 || P
== StartP
)
295 unsigned long ThisBucketSize
= 0;
296 for (; P
!= StartP
; P
= StartP
+ Next(P
))
298 Entries
+= ThisBucketSize
;
299 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
300 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
302 cout
<< "Total buckets in " << Type
<< ": " << NumBuckets
<< std::endl
;
303 cout
<< " Unused: " << UnusedBuckets
<< std::endl
;
304 cout
<< " Used: " << UsedBuckets
<< std::endl
;
305 cout
<< " Average entries: " << Entries
/(double)NumBuckets
<< std::endl
;
306 cout
<< " Longest: " << LongestBucket
<< std::endl
;
307 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
310 // Stats - Dump some nice statistics /*{{{*/
311 // ---------------------------------------------------------------------
313 static bool Stats(CommandLine
&)
315 pkgCacheFile CacheFile
;
316 pkgCache
*Cache
= CacheFile
.GetPkgCache();
317 if (unlikely(Cache
== NULL
))
320 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
321 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
322 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
323 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
330 pkgCache::PkgIterator I
= Cache
->PkgBegin();
331 for (;I
.end() != true; ++I
)
333 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
339 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
345 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
348 if (I
.ProvidesList()->NextProvides
== 0)
356 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
362 cout
<< _(" Normal packages: ") << Normal
<< endl
;
363 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
364 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
365 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
366 cout
<< _(" Missing: ") << Missing
<< endl
;
368 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
369 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
370 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
371 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
372 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< "/" << Cache
->Head().DependsDataCount
<< " (" <<
373 SizeToStr((Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) +
374 (Cache
->Head().DependsDataCount
*Cache
->Head().DependencyDataSz
)) << ')' << endl
;
375 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
376 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
377 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
378 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
379 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
380 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
383 std::set
<map_stringitem_t
> stritems
;
384 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
385 stritems
.insert(G
->Name
);
386 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
388 stritems
.insert(P
->Arch
);
389 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
392 stritems
.insert(V
->VerStr
);
394 stritems
.insert(V
->Section
);
395 stritems
.insert(V
->SourcePkgName
);
396 stritems
.insert(V
->SourceVerStr
);
397 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
400 stritems
.insert(D
->Version
);
402 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
404 stritems
.insert(D
->md5sum
);
405 stritems
.insert(D
->language_code
);
408 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
410 if (Prv
->ProvideVersion
!= 0)
411 stritems
.insert(Prv
->ProvideVersion
);
414 for (pkgCache::RlsFileIterator F
= Cache
->RlsFileBegin(); F
!= Cache
->RlsFileEnd(); ++F
)
416 stritems
.insert(F
->FileName
);
417 stritems
.insert(F
->Archive
);
418 stritems
.insert(F
->Codename
);
419 stritems
.insert(F
->Version
);
420 stritems
.insert(F
->Origin
);
421 stritems
.insert(F
->Label
);
422 stritems
.insert(F
->Site
);
424 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
426 stritems
.insert(F
->FileName
);
427 stritems
.insert(F
->Architecture
);
428 stritems
.insert(F
->Component
);
429 stritems
.insert(F
->IndexType
);
432 unsigned long Size
= 0;
433 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
434 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
435 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
438 unsigned long Slack
= 0;
439 for (int I
= 0; I
!= 7; I
++)
440 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
441 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
443 unsigned long Total
= 0;
444 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
445 Total
= Slack
+ Size
+
446 APT_CACHESIZE(GroupCount
, GroupSz
) +
447 APT_CACHESIZE(PackageCount
, PackageSz
) +
448 APT_CACHESIZE(VersionCount
, VersionSz
) +
449 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
450 APT_CACHESIZE(DependsCount
, DependencySz
) +
451 APT_CACHESIZE(DependsDataCount
, DependencyDataSz
) +
452 APT_CACHESIZE(ReleaseFileCount
, ReleaseFileSz
) +
453 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
454 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
455 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
456 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
457 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
458 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
462 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
463 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
468 // Dump - show everything /*{{{*/
469 // ---------------------------------------------------------------------
470 /* This is worthless except fer debugging things */
471 static bool Dump(CommandLine
&)
473 pkgCacheFile CacheFile
;
474 pkgCache
*Cache
= CacheFile
.GetPkgCache();
475 if (unlikely(Cache
== NULL
))
478 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
480 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
482 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
483 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
485 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
486 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
487 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
488 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
489 DeNull(D
.TargetVer()) << std::endl
;
490 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
492 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
493 << " File: " << D
.FileList().File().FileName() << std::endl
494 << " MD5: " << D
.md5() << std::endl
;
499 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
501 std::cout
<< "File: " << F
.FileName() << std::endl
;
502 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
503 std::cout
<< " Size: " << F
->Size
<< std::endl
;
504 std::cout
<< " ID: " << F
->ID
<< std::endl
;
505 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
506 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
507 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
508 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
509 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
510 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
511 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
512 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
513 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
519 // DumpAvail - Print out the available list /*{{{*/
520 // ---------------------------------------------------------------------
521 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
522 make this run really fast, perhaps I went a little overboard.. */
523 static bool DumpAvail(CommandLine
&)
525 pkgCacheFile CacheFile
;
526 pkgCache
*Cache
= CacheFile
.GetPkgCache();
527 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
530 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
531 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
532 memset(VFList
,0,sizeof(*VFList
)*Count
);
534 // Map versions that we want to write out onto the VerList array.
535 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
537 if (P
->VersionList
== 0)
540 /* Find the proper version to use. If the policy says there are no
541 possible selections we return the installed version, if available..
542 This prevents dselect from making it obsolete. */
543 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
546 if (P
->CurrentVer
== 0)
551 pkgCache::VerFileIterator VF
= V
.FileList();
552 for (; VF
.end() == false ; ++VF
)
553 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
556 /* Okay, here we have a bit of a problem.. The policy has selected the
557 currently installed package - however it only exists in the
558 status file.. We need to write out something or dselect will mark
559 the package as obsolete! Thus we emit the status file entry, but
560 below we remove the status line to make it valid for the
561 available file. However! We only do this if their do exist *any*
562 non-source versions of the package - that way the dselect obsolete
563 handling works OK. */
564 if (VF
.end() == true)
566 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
568 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
570 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
577 if (VF
.end() == false)
585 LocalitySort(VFList
,Count
,sizeof(*VFList
));
587 std::vector
<pkgTagSection::Tag
> RW
;
588 RW
.push_back(pkgTagSection::Tag::Remove("Status"));
589 RW
.push_back(pkgTagSection::Tag::Remove("Config-Version"));
591 stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
, false);
593 // Iterate over all the package files and write them out.
594 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
595 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
597 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
598 if (File
.IsOk() == false)
600 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
604 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
605 if (_error
->PendingError() == true)
608 /* Write all of the records from this package file, since we
609 already did locality sorting we can now just seek through the
610 file in read order. We apply 1 more optimization here, since often
611 there will be < 1 byte gaps between records (for the \n) we read that
612 into the next buffer and offset a bit.. */
613 unsigned long Pos
= 0;
616 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
619 const pkgCache::VerFile
&VF
= **J
;
621 // Read the record and then write it out again.
622 unsigned long Jitter
= VF
.Offset
- Pos
;
625 if (PkgF
.Seek(VF
.Offset
) == false)
630 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
632 Buffer
[VF
.Size
+ Jitter
] = '\n';
635 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
638 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
639 Tags
.Write(stdoutfd
, NULL
, RW
) == false ||
640 stdoutfd
.Write("\n", 1) == false)
642 _error
->Error("Internal Error, Unable to parse a package record");
648 if (stdoutfd
.Write(Buffer
+ Jitter
, VF
.Size
+ 1) == false)
652 Pos
= VF
.Offset
+ VF
.Size
;
655 if (_error
->PendingError() == true)
661 return !_error
->PendingError();
664 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
665 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
667 pkgCacheFile CacheFile
;
668 pkgCache
*Cache
= CacheFile
.GetPkgCache();
669 if (unlikely(Cache
== NULL
))
672 CacheSetHelperVirtuals
helper(false);
673 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
674 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
675 return _error
->Error(_("No packages found"));
676 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
678 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
679 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
680 bool const Important
= _config
->FindB("APT::Cache::Important", false);
681 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
682 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
683 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
684 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
685 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
686 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
687 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
688 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
689 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
690 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
691 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
693 while (verset
.empty() != true)
695 pkgCache::VerIterator Ver
= *verset
.begin();
696 verset
.erase(verset
.begin());
697 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
698 Shown
[Pkg
->ID
] = true;
700 cout
<< Pkg
.FullName(true) << endl
;
702 if (RevDepends
== true)
703 cout
<< "Reverse Depends:" << endl
;
704 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
705 D
.end() == false; ++D
)
708 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
709 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
710 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
711 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
712 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
713 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
714 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
717 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
719 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
722 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
728 if (ShowDepType
== true)
729 cout
<< D
.DepType() << ": ";
730 if (Trg
->VersionList
== 0)
731 cout
<< "<" << Trg
.FullName(true) << ">";
733 cout
<< Trg
.FullName(true);
734 if (ShowVersion
== true && D
->Version
!= 0)
735 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
738 if (Recurse
== true && Shown
[Trg
->ID
] == false)
740 Shown
[Trg
->ID
] = true;
741 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::CacheSetHelper::CANDIDATE
, helper
));
746 // Display all solutions
747 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
748 pkgPrioSortList(*Cache
,List
);
749 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
751 pkgCache::VerIterator
V(*Cache
,*I
);
752 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
753 V
->ParentPkg
== D
->Package
)
755 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
757 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
759 Shown
[V
.ParentPkg()->ID
] = true;
760 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::CacheSetHelper::CANDIDATE
, helper
));
764 if (ShowOnlyFirstOr
== true)
765 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
769 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
770 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
771 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
776 // Depends - Print out a dependency tree /*{{{*/
777 // ---------------------------------------------------------------------
779 static bool Depends(CommandLine
&CmdL
)
781 return ShowDepends(CmdL
, false);
784 // RDepends - Print out a reverse dependency tree /*{{{*/
785 // ---------------------------------------------------------------------
787 static bool RDepends(CommandLine
&CmdL
)
789 return ShowDepends(CmdL
, true);
792 // xvcg - Generate a graph for xvcg /*{{{*/
793 // ---------------------------------------------------------------------
794 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
796 static bool XVcg(CommandLine
&CmdL
)
798 pkgCacheFile CacheFile
;
799 pkgCache
*Cache
= CacheFile
.GetPkgCache();
800 if (unlikely(Cache
== NULL
))
803 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
805 /* Normal packages are boxes
806 Pure Provides are triangles
808 rhomb are missing packages*/
809 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
811 /* Initialize the list of packages to show.
813 2 = To Show no recurse
814 3 = Emitted no recurse
817 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
818 enum TheFlags
{ForceNR
=(1<<0)};
819 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
820 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
821 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
823 // Show everything if no arguments given
824 if (CmdL
.FileList
[1] == 0)
825 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
828 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
830 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
833 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
835 if (Pkg
->VersionList
== 0)
838 if (Pkg
->ProvidesList
== 0)
839 ShapeMap
[Pkg
->ID
] = 0;
841 ShapeMap
[Pkg
->ID
] = 1;
846 if (Pkg
->ProvidesList
== 0)
847 ShapeMap
[Pkg
->ID
] = 2;
849 ShapeMap
[Pkg
->ID
] = 3;
853 // Load the list of packages from the command line into the show list
854 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
855 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
856 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
857 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
858 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
859 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
861 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
862 Pkg
!= pkgsets
[0].end(); ++Pkg
)
863 Show
[Pkg
->ID
] = ToShow
;
864 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
865 Pkg
!= pkgsets
[1].end(); ++Pkg
)
867 Show
[Pkg
->ID
] = ToShow
;
868 Flags
[Pkg
->ID
] |= ForceNR
;
872 cout
<< "graph: { title: \"packages\"" << endl
<<
873 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
874 "layout_downfactor: 8" << endl
;
880 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
882 // See we need to show this package
883 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
886 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
889 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
891 // Pure Provides and missing packages have no deps!
892 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
893 Show
[Pkg
->ID
] = Done
;
895 Show
[Pkg
->ID
] = DoneNR
;
898 Show
[Pkg
->ID
] = Done
;
901 // No deps to map out
902 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
905 pkgCache::VerIterator Ver
= Pkg
.VersionList();
906 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
908 // See if anything can meet this dep
909 // Walk along the actual package providing versions
911 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
912 for (pkgCache::VerIterator I
= DPkg
.VersionList();
913 I
.end() == false && Hit
== false; ++I
)
915 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
919 // Follow all provides
920 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
921 I
.end() == false && Hit
== false; ++I
)
923 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
928 // Only graph critical deps
929 if (D
.IsCritical() == true)
931 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
933 // Colour the node for recursion
934 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
936 /* If a conflicts does not meet anything in the database
937 then show the relation but do not recurse */
938 if (Hit
== false && D
.IsNegative() == true)
940 if (Show
[D
.TargetPkg()->ID
] == None
&&
941 Show
[D
.TargetPkg()->ID
] != ToShow
)
942 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
946 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
947 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
949 Show
[D
.TargetPkg()->ID
] = ToShow
;
956 case pkgCache::Dep::Conflicts
:
957 printf("label: \"conflicts\" color: lightgreen }\n");
959 case pkgCache::Dep::DpkgBreaks
:
960 printf("label: \"breaks\" color: lightgreen }\n");
962 case pkgCache::Dep::Obsoletes
:
963 printf("label: \"obsoletes\" color: lightgreen }\n");
966 case pkgCache::Dep::PreDepends
:
967 printf("label: \"predepends\" color: blue }\n");
979 /* Draw the box colours after the fact since we can not tell what colour
980 they should be until everything is finished drawing */
981 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
983 if (Show
[Pkg
->ID
] < DoneNR
)
986 if (Show
[Pkg
->ID
] == DoneNR
)
987 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
988 Shapes
[ShapeMap
[Pkg
->ID
]]);
990 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
991 Shapes
[ShapeMap
[Pkg
->ID
]]);
1003 // Dotty - Generate a graph for Dotty /*{{{*/
1004 // ---------------------------------------------------------------------
1005 /* Dotty is the graphvis program for generating graphs. It is a fairly
1006 simple queuing algorithm that just writes dependencies and nodes.
1007 http://www.research.att.com/sw/tools/graphviz/ */
1008 static bool Dotty(CommandLine
&CmdL
)
1010 pkgCacheFile CacheFile
;
1011 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1012 if (unlikely(Cache
== NULL
))
1015 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
1017 /* Normal packages are boxes
1018 Pure Provides are triangles
1020 Hexagons are missing packages*/
1021 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1023 /* Initialize the list of packages to show.
1025 2 = To Show no recurse
1026 3 = Emitted no recurse
1029 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1030 enum TheFlags
{ForceNR
=(1<<0)};
1031 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1032 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1033 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1035 // Show everything if no arguments given
1036 if (CmdL
.FileList
[1] == 0)
1037 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1040 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1042 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1045 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1047 if (Pkg
->VersionList
== 0)
1050 if (Pkg
->ProvidesList
== 0)
1051 ShapeMap
[Pkg
->ID
] = 0;
1053 ShapeMap
[Pkg
->ID
] = 1;
1058 if (Pkg
->ProvidesList
== 0)
1059 ShapeMap
[Pkg
->ID
] = 2;
1061 ShapeMap
[Pkg
->ID
] = 3;
1065 // Load the list of packages from the command line into the show list
1066 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1067 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
1068 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1069 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1070 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1071 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1073 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1074 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1075 Show
[Pkg
->ID
] = ToShow
;
1076 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1077 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1079 Show
[Pkg
->ID
] = ToShow
;
1080 Flags
[Pkg
->ID
] |= ForceNR
;
1084 printf("digraph packages {\n");
1085 printf("concentrate=true;\n");
1086 printf("size=\"30,40\";\n");
1092 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1094 // See we need to show this package
1095 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1099 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1101 // Pure Provides and missing packages have no deps!
1102 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1103 Show
[Pkg
->ID
] = Done
;
1105 Show
[Pkg
->ID
] = DoneNR
;
1108 Show
[Pkg
->ID
] = Done
;
1111 // No deps to map out
1112 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1115 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1116 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1118 // See if anything can meet this dep
1119 // Walk along the actual package providing versions
1121 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1122 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1123 I
.end() == false && Hit
== false; ++I
)
1125 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1129 // Follow all provides
1130 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1131 I
.end() == false && Hit
== false; ++I
)
1133 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1137 // Only graph critical deps
1138 if (D
.IsCritical() == true)
1140 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1142 // Colour the node for recursion
1143 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1145 /* If a conflicts does not meet anything in the database
1146 then show the relation but do not recurse */
1147 if (Hit
== false && D
.IsNegative() == true)
1149 if (Show
[D
.TargetPkg()->ID
] == None
&&
1150 Show
[D
.TargetPkg()->ID
] != ToShow
)
1151 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1155 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1156 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1158 Show
[D
.TargetPkg()->ID
] = ToShow
;
1165 case pkgCache::Dep::Conflicts
:
1166 case pkgCache::Dep::Obsoletes
:
1167 case pkgCache::Dep::DpkgBreaks
:
1168 printf("[color=springgreen];\n");
1171 case pkgCache::Dep::PreDepends
:
1172 printf("[color=blue];\n");
1184 /* Draw the box colours after the fact since we can not tell what colour
1185 they should be until everything is finished drawing */
1186 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1188 if (Show
[Pkg
->ID
] < DoneNR
)
1191 // Orange box for early recursion stoppage
1192 if (Show
[Pkg
->ID
] == DoneNR
)
1193 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1194 Shapes
[ShapeMap
[Pkg
->ID
]]);
1196 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1197 Shapes
[ShapeMap
[Pkg
->ID
]]);
1207 // DisplayRecord - Displays the complete record for the package /*{{{*/
1208 // ---------------------------------------------------------------------
1209 /* This displays the package record from the proper package index file.
1210 It is not used by DumpAvail for performance reasons. */
1212 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1214 char const * const TagName
= "\nDescription";
1215 size_t const TagLen
= strlen(TagName
);
1216 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1218 if (DescP
[1] == ' ')
1220 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1229 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1231 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1232 if (unlikely(Cache
== NULL
))
1235 // Find an appropriate file
1236 pkgCache::VerFileIterator Vf
= V
.FileList();
1237 for (; Vf
.end() == false; ++Vf
)
1238 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1240 if (Vf
.end() == true)
1243 // Check and load the package list file
1244 pkgCache::PkgFileIterator I
= Vf
.File();
1245 if (I
.IsOk() == false)
1246 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1249 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1252 // Read the record (and ensure that it ends with a newline and NUL)
1253 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1254 Buffer
[Vf
->Size
] = '\n';
1255 Buffer
[Vf
->Size
+1] = '\0';
1256 if (PkgF
.Seek(Vf
->Offset
) == false ||
1257 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1263 // Get a pointer to start of Description field
1264 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1268 DescP
= Buffer
+ Vf
->Size
;
1270 // Write all but Description
1271 size_t const length
= DescP
- Buffer
;
1272 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1278 // Show the right description
1279 pkgRecords
Recs(*Cache
);
1280 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1281 if (Desc
.end() == false)
1283 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1284 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1285 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1287 // Find the first field after the description (if there is any)
1288 DescP
= skipDescriptionFields(DescP
);
1290 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1292 // write the rest of the buffer, but skip mixed in Descriptions* fields
1293 while (DescP
!= NULL
)
1295 const unsigned char * const Start
= DescP
;
1296 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1299 End
= &Buffer
[Vf
->Size
];
1304 ++End
; // get the newline into the output
1305 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1307 size_t const length
= End
- Start
;
1308 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1315 // write a final newline after the last field
1324 pkgCache::DescFile
*Df
;
1328 // Search - Perform a search /*{{{*/
1329 // ---------------------------------------------------------------------
1330 /* This searches the package names and package descriptions for a pattern */
1331 static bool Search(CommandLine
&CmdL
)
1333 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1334 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1335 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1337 pkgCacheFile CacheFile
;
1338 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1339 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1340 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1343 // Make sure there is at least one argument
1344 if (NumPatterns
< 1)
1345 return _error
->Error(_("You must give at least one search pattern"));
1347 // Compile the regex pattern
1348 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1349 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1350 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1352 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1356 regfree(&Patterns
[I
]);
1357 return _error
->Error("Regex compilation error");
1361 if (_error
->PendingError() == true)
1363 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1364 regfree(&Patterns
[I
]);
1368 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1369 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1370 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1372 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1373 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1375 // Map versions that we want to write out onto the VerList array.
1376 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1378 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1379 size_t unmatched
= 0, matched
= 0;
1380 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1382 if (PatternMatch
[PatternOffset
+ I
] == true)
1384 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1385 PatternMatch
[PatternOffset
+ I
] = true;
1390 // already dealt with this package?
1391 if (matched
== NumPatterns
)
1394 // Doing names only, drop any that don't match..
1395 if (NamesOnly
== true && unmatched
== NumPatterns
)
1398 // Find the proper version to use
1399 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1400 if (P
.end() == true)
1402 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1403 if (V
.end() == false)
1405 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1406 //FIXME: packages without a description can't be found
1407 if (D
.end() == true)
1409 DFList
[G
->ID
].Df
= D
.FileList();
1410 DFList
[G
->ID
].ID
= G
->ID
;
1413 if (unmatched
== NumPatterns
)
1416 // Include all the packages that provide matching names too
1417 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1419 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1420 if (V
.end() == true)
1423 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1424 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1425 //FIXME: packages without a description can't be found
1426 if (D
.end() == true)
1428 DFList
[id
].Df
= D
.FileList();
1431 size_t const PrvPatternOffset
= id
* NumPatterns
;
1432 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1433 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1437 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1439 // Create the text record parser
1440 pkgRecords
Recs(*Cache
);
1441 // Iterate over all the version records and check them
1442 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1444 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1445 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1447 if (NamesOnly
== false)
1449 string
const LongDesc
= P
.LongDesc();
1450 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1452 if (PatternMatch
[PatternOffset
+ I
] == true)
1454 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1455 PatternMatch
[PatternOffset
+ I
] = true;
1459 bool matchedAll
= true;
1460 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1461 if (PatternMatch
[PatternOffset
+ I
] == false)
1467 if (matchedAll
== true)
1469 if (ShowFull
== true)
1473 P
.GetRec(Start
,End
);
1474 fwrite(Start
,End
-Start
,1,stdout
);
1478 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1483 delete [] PatternMatch
;
1484 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1485 regfree(&Patterns
[I
]);
1488 return _error
->Error("Write to stdout failed");
1492 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1493 static bool ShowAuto(CommandLine
&)
1495 pkgCacheFile CacheFile
;
1496 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1497 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1498 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1501 std::vector
<string
> packages
;
1502 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1504 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1505 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1506 packages
.push_back(P
.Name());
1508 std::sort(packages
.begin(), packages
.end());
1510 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1513 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1517 // ShowPackage - Dump the package record to the screen /*{{{*/
1518 // ---------------------------------------------------------------------
1520 static bool ShowPackage(CommandLine
&CmdL
)
1522 pkgCacheFile CacheFile
;
1523 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1524 APT::CacheSetHelper::VerSelector
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1525 APT::CacheSetHelper::ALL
: APT::CacheSetHelper::CANDIDATE
;
1526 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1527 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1528 if (DisplayRecord(CacheFile
, Ver
) == false)
1531 if (verset
.empty() == true)
1533 if (helper
.virtualPkgs
.empty() == true)
1534 return _error
->Error(_("No packages found"));
1536 _error
->Notice(_("No packages found"));
1541 // ShowPkgNames - Show package names /*{{{*/
1542 // ---------------------------------------------------------------------
1543 /* This does a prefix match on the first argument */
1544 static bool ShowPkgNames(CommandLine
&CmdL
)
1546 pkgCacheFile CacheFile
;
1547 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1549 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1550 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1552 if (CmdL
.FileList
[1] != 0)
1554 for (;I
.end() != true; ++I
)
1556 if (All
== false && I
->FirstPackage
== 0)
1558 if (I
.FindPkg("any")->VersionList
== 0)
1560 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1561 cout
<< I
.Name() << endl
;
1568 for (;I
.end() != true; ++I
)
1570 if (All
== false && I
->FirstPackage
== 0)
1572 if (I
.FindPkg("any")->VersionList
== 0)
1574 cout
<< I
.Name() << endl
;
1580 // ShowSrcPackage - Show source package records /*{{{*/
1581 // ---------------------------------------------------------------------
1583 static bool ShowSrcPackage(CommandLine
&CmdL
)
1585 pkgCacheFile CacheFile
;
1586 pkgSourceList
*List
= CacheFile
.GetSourceList();
1587 if (unlikely(List
== NULL
))
1590 // Create the text record parsers
1591 pkgSrcRecords
SrcRecs(*List
);
1592 if (_error
->PendingError() == true)
1596 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1600 pkgSrcRecords::Parser
*Parse
;
1601 unsigned found_this
= 0;
1602 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1603 cout
<< Parse
->AsStr() << endl
;;
1607 if (found_this
== 0) {
1608 _error
->Warning(_("Unable to locate package %s"),*I
);
1613 _error
->Notice(_("No packages found"));
1617 // Policy - Show the results of the preferences file /*{{{*/
1618 // ---------------------------------------------------------------------
1620 static bool Policy(CommandLine
&CmdL
)
1622 pkgCacheFile CacheFile
;
1623 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1624 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1625 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1626 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1629 /* Should the MultiArchKiller be run to see which pseudo packages for an
1630 arch all package are currently installed? Activating it gives a speed
1631 penality for no real gain beside enhanced debugging, so in general no. */
1632 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1633 CacheFile
.GetDepCache();
1635 // Print out all of the package files
1636 if (CmdL
.FileList
[1] == 0)
1638 cout
<< _("Package files:") << endl
;
1639 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1641 if (F
.Flagged(pkgCache::Flag::NoPackages
))
1643 // Locate the associated index files so we can derive a description
1645 if (SrcList
->FindIndex(F
,Indx
) == false &&
1646 _system
->FindIndex(F
,Indx
) == false)
1647 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1650 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1652 // Print the reference information for the package
1653 string Str
= F
.RelStr();
1654 if (Str
.empty() == false)
1655 printf(" release %s\n",F
.RelStr().c_str());
1656 if (F
.Site() != 0 && F
.Site()[0] != 0)
1657 printf(" origin %s\n",F
.Site());
1660 // Show any packages have explicit pins
1661 cout
<< _("Pinned packages:") << endl
;
1662 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1663 for (;I
.end() != true; ++I
)
1665 if (Plcy
->GetPriority(I
) == 0)
1668 // Print the package name and the version we are forcing to
1669 cout
<< " " << I
.FullName(true) << " -> ";
1671 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1672 if (V
.end() == true)
1673 cout
<< _("(not found)") << endl
;
1675 cout
<< V
.VerStr() << endl
;
1681 char const * const msgInstalled
= _(" Installed: ");
1682 char const * const msgCandidate
= _(" Candidate: ");
1683 short const InstalledLessCandidate
=
1684 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1685 short const deepInstalled
=
1686 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1687 short const deepCandidate
=
1688 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1690 // Print out detailed information for each package
1691 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1692 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1693 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1695 cout
<< Pkg
.FullName(true) << ":" << endl
;
1697 // Installed version
1698 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1699 if (Pkg
->CurrentVer
== 0)
1700 cout
<< _("(none)") << endl
;
1702 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1704 // Candidate Version
1705 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1706 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1707 if (V
.end() == true)
1708 cout
<< _("(none)") << endl
;
1710 cout
<< V
.VerStr() << endl
;
1713 if (Plcy
->GetPriority(Pkg
) != 0)
1715 cout
<< _(" Package pin: ");
1716 V
= Plcy
->GetMatch(Pkg
);
1717 if (V
.end() == true)
1718 cout
<< _("(not found)") << endl
;
1720 cout
<< V
.VerStr() << endl
;
1723 // Show the priority tables
1724 cout
<< _(" Version table:") << endl
;
1725 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1727 if (Pkg
.CurrentVer() == V
)
1728 cout
<< " *** " << V
.VerStr();
1730 cout
<< " " << V
.VerStr();
1731 cout
<< " " << Plcy
->GetPriority(V
) << endl
;
1732 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1734 // Locate the associated index files so we can derive a description
1736 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1737 _system
->FindIndex(VF
.File(),Indx
) == false)
1738 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1739 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1740 Indx
->Describe(true).c_str());
1748 // Madison - Look a bit like katie's madison /*{{{*/
1749 // ---------------------------------------------------------------------
1751 static bool Madison(CommandLine
&CmdL
)
1753 pkgCacheFile CacheFile
;
1754 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1759 // Create the src text record parsers and ignore errors about missing
1760 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1761 pkgSrcRecords
SrcRecs(*SrcList
);
1762 if (_error
->PendingError() == true)
1765 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1766 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1768 _error
->PushToStack();
1769 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1770 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1772 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1774 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1776 // This might be nice, but wouldn't uniquely identify the source -mdz
1777 // if (VF.File().Archive() != 0)
1779 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1780 // << VF.File().Archive() << endl;
1783 // Locate the associated index files so we can derive a description
1784 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1786 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1787 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1788 IF
!= Indexes
->end(); ++IF
)
1790 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1792 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1793 << (*IF
)->Describe(true) << endl
;
1802 pkgSrcRecords::Parser
*SrcParser
;
1803 bool foundSomething
= false;
1804 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1806 foundSomething
= true;
1807 // Maybe support Release info here too eventually
1808 cout
<< setw(10) << SrcParser
->Package() << " | "
1809 << setw(10) << SrcParser
->Version() << " | "
1810 << SrcParser
->Index().Describe(true) << endl
;
1812 if (foundSomething
== true)
1813 _error
->RevertToStack();
1815 _error
->MergeWithStack();
1821 // GenCaches - Call the main cache generator /*{{{*/
1822 // ---------------------------------------------------------------------
1824 static bool GenCaches(CommandLine
&)
1826 OpTextProgress
Progress(*_config
);
1828 pkgCacheFile CacheFile
;
1829 return CacheFile
.BuildCaches(&Progress
, true);
1832 // ShowHelp - Show a help screen /*{{{*/
1833 // ---------------------------------------------------------------------
1835 static bool ShowHelp(CommandLine
&)
1837 ioprintf(cout
, "%s %s (%s)\n", PACKAGE
, PACKAGE_VERSION
, COMMON_ARCH
);
1839 if (_config
->FindB("version") == true)
1843 _("Usage: apt-cache [options] command\n"
1844 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1845 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1847 "apt-cache is a low-level tool used to query information\n"
1848 "from APT's binary cache files\n"
1851 " gencaches - Build both the package and source cache\n"
1852 " showpkg - Show some general information for a single package\n"
1853 " showsrc - Show source records\n"
1854 " stats - Show some basic statistics\n"
1855 " dump - Show the entire file in a terse form\n"
1856 " dumpavail - Print an available file to stdout\n"
1857 " unmet - Show unmet dependencies\n"
1858 " search - Search the package list for a regex pattern\n"
1859 " show - Show a readable record for the package\n"
1860 " depends - Show raw dependency information for a package\n"
1861 " rdepends - Show reverse dependency information for a package\n"
1862 " pkgnames - List the names of all packages in the system\n"
1863 " dotty - Generate package graphs for GraphViz\n"
1864 " xvcg - Generate package graphs for xvcg\n"
1865 " policy - Show policy settings\n"
1868 " -h This help text.\n"
1869 " -p=? The package cache.\n"
1870 " -s=? The source cache.\n"
1871 " -q Disable progress indicator.\n"
1872 " -i Show only important deps for the unmet command.\n"
1873 " -c=? Read this configuration file\n"
1874 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1875 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1879 int main(int argc
,const char *argv
[]) /*{{{*/
1881 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1882 {"gencaches",&GenCaches
},
1883 {"showsrc",&ShowSrcPackage
},
1884 {"showpkg",&DumpPackage
},
1887 {"dumpavail",&DumpAvail
},
1890 {"depends",&Depends
},
1891 {"rdepends",&RDepends
},
1894 {"show",&ShowPackage
},
1895 {"pkgnames",&ShowPkgNames
},
1896 {"showauto",&ShowAuto
},
1898 {"madison",&Madison
},
1901 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1903 // Set up gettext support
1904 setlocale(LC_ALL
,"");
1905 textdomain(PACKAGE
);
1907 // Parse the command line and initialize the package library
1909 ParseCommandLine(CmdL
, Cmds
, Args
.data(), &_config
, &_system
, argc
, argv
, ShowHelp
);
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;