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/error.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/init.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/cmndline.h>
25 #include <apt-pkg/strutl.h>
26 #include <apt-pkg/fileutl.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/srcrecords.h>
29 #include <apt-pkg/version.h>
30 #include <apt-pkg/policy.h>
31 #include <apt-pkg/tagfile.h>
32 #include <apt-pkg/algorithms.h>
33 #include <apt-pkg/sptr.h>
34 #include <apt-pkg/pkgsystem.h>
35 #include <apt-pkg/indexfile.h>
36 #include <apt-pkg/metaindex.h>
53 // CacheSetHelper saving virtual packages /*{{{*/
54 class CacheSetHelperVirtuals
: public APT::CacheSetHelper
{
56 APT::PackageSet virtualPkgs
;
58 virtual pkgCache::VerIterator
canNotFindCandidateVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
59 virtualPkgs
.insert(Pkg
);
60 return CacheSetHelper::canNotFindCandidateVer(Cache
, Pkg
);
63 virtual pkgCache::VerIterator
canNotFindNewestVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
64 virtualPkgs
.insert(Pkg
);
65 return CacheSetHelper::canNotFindNewestVer(Cache
, Pkg
);
68 virtual void canNotFindAllVer(APT::VersionContainerInterface
* vci
, pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
69 virtualPkgs
.insert(Pkg
);
70 CacheSetHelper::canNotFindAllVer(vci
, Cache
, Pkg
);
73 CacheSetHelperVirtuals(bool const ShowErrors
= true, GlobalError::MsgType
const &ErrorType
= GlobalError::NOTICE
) : CacheSetHelper(ShowErrors
, ErrorType
) {}
76 // LocalitySort - Sort a version list by package file locality /*{{{*/
77 // ---------------------------------------------------------------------
79 int LocalityCompare(const void *a
, const void *b
)
81 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
82 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
91 if (A
->File
== B
->File
)
92 return A
->Offset
- B
->Offset
;
93 return A
->File
- B
->File
;
96 void LocalitySort(pkgCache::VerFile
**begin
,
97 unsigned long Count
,size_t Size
)
99 qsort(begin
,Count
,Size
,LocalityCompare
);
102 void LocalitySort(pkgCache::DescFile
**begin
,
103 unsigned long Count
,size_t Size
)
105 qsort(begin
,Count
,Size
,LocalityCompare
);
108 // UnMet - Show unmet dependencies /*{{{*/
109 // ---------------------------------------------------------------------
111 bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const Important
)
114 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
117 pkgCache::DepIterator Start
;
118 pkgCache::DepIterator End
;
121 // Important deps only
122 if (Important
== true)
123 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
124 End
->Type
!= pkgCache::Dep::Depends
)
127 // Skip conflicts and replaces
128 if (End
.IsNegative() == true)
131 // Verify the or group
133 pkgCache::DepIterator RealStart
= Start
;
136 // See if this dep is Ok
137 pkgCache::Version
**VList
= Start
.AllTargets();
158 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
159 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
162 // Print out the dep type
163 cout
<< " " << End
.DepType() << ": ";
169 cout
<< Start
.TargetPkg().FullName(true);
170 if (Start
.TargetVer() != 0)
171 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
184 bool UnMet(CommandLine
&CmdL
)
186 bool const Important
= _config
->FindB("APT::Cache::Important",false);
188 pkgCacheFile CacheFile
;
189 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
192 if (CmdL
.FileSize() <= 1)
194 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; ++P
)
195 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
196 if (ShowUnMet(V
, Important
) == false)
201 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
202 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
203 APT::VersionList::CANDIDATE
, helper
);
204 for (APT::VersionList::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
205 if (ShowUnMet(V
, Important
) == false)
211 // DumpPackage - Show a dump of a package record /*{{{*/
212 // ---------------------------------------------------------------------
214 bool DumpPackage(CommandLine
&CmdL
)
216 pkgCacheFile CacheFile
;
217 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
218 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
220 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
222 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
223 cout
<< "Versions: " << endl
;
224 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
226 cout
<< Cur
.VerStr();
227 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
228 cout
<< " (" << Vf
.File().FileName() << ")";
230 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
232 cout
<< " Description Language: " << D
.LanguageCode() << endl
233 << " File: " << D
.FileList().File().FileName() << endl
234 << " MD5: " << D
.md5() << endl
;
241 cout
<< "Reverse Depends: " << endl
;
242 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
244 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
246 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
251 cout
<< "Dependencies: " << endl
;
252 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
254 cout
<< Cur
.VerStr() << " - ";
255 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; ++Dep
)
256 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
260 cout
<< "Provides: " << endl
;
261 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
263 cout
<< Cur
.VerStr() << " - ";
264 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
265 cout
<< Prv
.ParentPkg().FullName(true) << " ";
268 cout
<< "Reverse Provides: " << endl
;
269 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
270 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
276 // Stats - Dump some nice statistics /*{{{*/
277 // ---------------------------------------------------------------------
279 bool Stats(CommandLine
&Cmd
)
281 pkgCacheFile CacheFile
;
282 pkgCache
*Cache
= CacheFile
.GetPkgCache();
283 if (unlikely(Cache
== NULL
))
286 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
287 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
288 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
289 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
296 pkgCache::PkgIterator I
= Cache
->PkgBegin();
297 for (;I
.end() != true; ++I
)
299 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
305 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
311 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
314 if (I
.ProvidesList()->NextProvides
== 0)
322 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
328 cout
<< _(" Normal packages: ") << Normal
<< endl
;
329 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
330 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
331 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
332 cout
<< _(" Missing: ") << Missing
<< endl
;
334 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
335 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
336 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
337 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
338 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
339 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
341 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
342 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
343 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
344 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
345 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
346 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
349 unsigned long Size
= 0;
350 unsigned long Count
= 0;
351 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
352 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
355 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
357 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
359 unsigned long DepVerSize
= 0;
360 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
362 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
364 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
367 DepVerSize
+= strlen(D
.TargetVer()) + 1;
371 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
373 unsigned long Slack
= 0;
374 for (int I
= 0; I
!= 7; I
++)
375 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
376 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
378 unsigned long Total
= 0;
379 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
380 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
381 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
382 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
383 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
384 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
389 // Dump - show everything /*{{{*/
390 // ---------------------------------------------------------------------
391 /* This is worthless except fer debugging things */
392 bool Dump(CommandLine
&Cmd
)
394 pkgCacheFile CacheFile
;
395 pkgCache
*Cache
= CacheFile
.GetPkgCache();
396 if (unlikely(Cache
== NULL
))
399 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
401 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
403 cout
<< "Package: " << P
.FullName(true) << endl
;
404 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
406 cout
<< " Version: " << V
.VerStr() << endl
;
407 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
408 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
409 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
410 DeNull(D
.TargetVer()) << endl
;
411 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
413 cout
<< " Description Language: " << D
.LanguageCode() << endl
414 << " File: " << D
.FileList().File().FileName() << endl
415 << " MD5: " << D
.md5() << endl
;
420 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
422 cout
<< "File: " << F
.FileName() << endl
;
423 cout
<< " Type: " << F
.IndexType() << endl
;
424 cout
<< " Size: " << F
->Size
<< endl
;
425 cout
<< " ID: " << F
->ID
<< endl
;
426 cout
<< " Flags: " << F
->Flags
<< endl
;
427 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
428 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
429 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
430 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
431 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
432 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
433 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
434 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
440 // DumpAvail - Print out the available list /*{{{*/
441 // ---------------------------------------------------------------------
442 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
443 make this run really fast, perhaps I went a little overboard.. */
444 bool DumpAvail(CommandLine
&Cmd
)
446 pkgCacheFile CacheFile
;
447 pkgCache
*Cache
= CacheFile
.GetPkgCache();
448 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
451 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
452 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
453 memset(VFList
,0,sizeof(*VFList
)*Count
);
455 // Map versions that we want to write out onto the VerList array.
456 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
458 if (P
->VersionList
== 0)
461 /* Find the proper version to use. If the policy says there are no
462 possible selections we return the installed version, if available..
463 This prevents dselect from making it obsolete. */
464 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
467 if (P
->CurrentVer
== 0)
472 pkgCache::VerFileIterator VF
= V
.FileList();
473 for (; VF
.end() == false ; ++VF
)
474 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
477 /* Okay, here we have a bit of a problem.. The policy has selected the
478 currently installed package - however it only exists in the
479 status file.. We need to write out something or dselect will mark
480 the package as obsolete! Thus we emit the status file entry, but
481 below we remove the status line to make it valid for the
482 available file. However! We only do this if their do exist *any*
483 non-source versions of the package - that way the dselect obsolete
484 handling works OK. */
485 if (VF
.end() == true)
487 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
489 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
491 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
498 if (VF
.end() == false)
506 LocalitySort(VFList
,Count
,sizeof(*VFList
));
508 // Iterate over all the package files and write them out.
509 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
510 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
512 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
513 if (File
.IsOk() == false)
515 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
519 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
520 if (_error
->PendingError() == true)
523 /* Write all of the records from this package file, since we
524 already did locality sorting we can now just seek through the
525 file in read order. We apply 1 more optimization here, since often
526 there will be < 1 byte gaps between records (for the \n) we read that
527 into the next buffer and offset a bit.. */
528 unsigned long Pos
= 0;
531 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
534 const pkgCache::VerFile
&VF
= **J
;
536 // Read the record and then write it out again.
537 unsigned long Jitter
= VF
.Offset
- Pos
;
540 if (PkgF
.Seek(VF
.Offset
) == false)
545 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
547 Buffer
[VF
.Size
+ Jitter
] = '\n';
550 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
553 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
554 const char *Zero
= 0;
555 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
556 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
558 _error
->Error("Internal Error, Unable to parse a package record");
565 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
569 Pos
= VF
.Offset
+ VF
.Size
;
573 if (_error
->PendingError() == true)
579 return !_error
->PendingError();
582 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
583 bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
585 pkgCacheFile CacheFile
;
586 pkgCache
*Cache
= CacheFile
.GetPkgCache();
587 if (unlikely(Cache
== NULL
))
590 CacheSetHelperVirtuals
helper(false);
591 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionList::CANDIDATE
, helper
);
592 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
593 return _error
->Error(_("No packages found"));
594 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
596 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
597 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
598 bool const Important
= _config
->FindB("APT::Cache::Important", false);
599 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
600 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
601 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
602 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
603 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
604 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
605 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
606 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
607 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
608 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
610 while (verset
.empty() != true)
612 pkgCache::VerIterator Ver
= *verset
.begin();
613 verset
.erase(verset
.begin());
614 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
615 Shown
[Pkg
->ID
] = true;
617 cout
<< Pkg
.FullName(true) << endl
;
619 if (RevDepends
== true)
620 cout
<< "Reverse Depends:" << endl
;
621 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
622 D
.end() == false; ++D
)
625 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
626 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
627 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
628 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
629 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
630 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
631 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
632 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
635 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
637 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
640 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
646 if (ShowDepType
== true)
647 cout
<< D
.DepType() << ": ";
648 if (Trg
->VersionList
== 0)
649 cout
<< "<" << Trg
.FullName(true) << ">" << endl
;
651 cout
<< Trg
.FullName(true) << endl
;
653 if (Recurse
== true && Shown
[Trg
->ID
] == false)
655 Shown
[Trg
->ID
] = true;
656 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
661 // Display all solutions
662 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
663 pkgPrioSortList(*Cache
,List
);
664 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
666 pkgCache::VerIterator
V(*Cache
,*I
);
667 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
668 V
->ParentPkg
== D
->Package
)
670 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
672 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
674 Shown
[V
.ParentPkg()->ID
] = true;
675 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
679 if (ShowOnlyFirstOr
== true)
680 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
684 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
685 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
686 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
691 // Depends - Print out a dependency tree /*{{{*/
692 // ---------------------------------------------------------------------
694 bool Depends(CommandLine
&CmdL
)
696 return ShowDepends(CmdL
, false);
699 // RDepends - Print out a reverse dependency tree /*{{{*/
700 // ---------------------------------------------------------------------
702 bool RDepends(CommandLine
&CmdL
)
704 return ShowDepends(CmdL
, true);
707 // xvcg - Generate a graph for xvcg /*{{{*/
708 // ---------------------------------------------------------------------
709 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
711 bool XVcg(CommandLine
&CmdL
)
713 pkgCacheFile CacheFile
;
714 pkgCache
*Cache
= CacheFile
.GetPkgCache();
715 if (unlikely(Cache
== NULL
))
718 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
720 /* Normal packages are boxes
721 Pure Provides are triangles
723 rhomb are missing packages*/
724 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
726 /* Initialize the list of packages to show.
728 2 = To Show no recurse
729 3 = Emitted no recurse
732 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
733 enum TheFlags
{ForceNR
=(1<<0)};
734 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
735 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
736 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
738 // Show everything if no arguments given
739 if (CmdL
.FileList
[1] == 0)
740 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
743 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
745 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
748 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
750 if (Pkg
->VersionList
== 0)
753 if (Pkg
->ProvidesList
== 0)
754 ShapeMap
[Pkg
->ID
] = 0;
756 ShapeMap
[Pkg
->ID
] = 1;
761 if (Pkg
->ProvidesList
== 0)
762 ShapeMap
[Pkg
->ID
] = 2;
764 ShapeMap
[Pkg
->ID
] = 3;
768 // Load the list of packages from the command line into the show list
769 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
770 std::list
<APT::PackageSet::Modifier
> mods
;
771 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
772 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
773 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
774 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
776 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
777 Pkg
!= pkgsets
[0].end(); ++Pkg
)
778 Show
[Pkg
->ID
] = ToShow
;
779 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
780 Pkg
!= pkgsets
[1].end(); ++Pkg
)
782 Show
[Pkg
->ID
] = ToShow
;
783 Flags
[Pkg
->ID
] |= ForceNR
;
787 cout
<< "graph: { title: \"packages\"" << endl
<<
788 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
789 "layout_downfactor: 8" << endl
;
795 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
797 // See we need to show this package
798 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
801 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
804 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
806 // Pure Provides and missing packages have no deps!
807 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
808 Show
[Pkg
->ID
] = Done
;
810 Show
[Pkg
->ID
] = DoneNR
;
813 Show
[Pkg
->ID
] = Done
;
816 // No deps to map out
817 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
820 pkgCache::VerIterator Ver
= Pkg
.VersionList();
821 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
823 // See if anything can meet this dep
824 // Walk along the actual package providing versions
826 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
827 for (pkgCache::VerIterator I
= DPkg
.VersionList();
828 I
.end() == false && Hit
== false; ++I
)
830 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
834 // Follow all provides
835 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
836 I
.end() == false && Hit
== false; ++I
)
838 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
843 // Only graph critical deps
844 if (D
.IsCritical() == true)
846 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
848 // Colour the node for recursion
849 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
851 /* If a conflicts does not meet anything in the database
852 then show the relation but do not recurse */
853 if (Hit
== false && D
.IsNegative() == true)
855 if (Show
[D
.TargetPkg()->ID
] == None
&&
856 Show
[D
.TargetPkg()->ID
] != ToShow
)
857 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
861 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
862 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
864 Show
[D
.TargetPkg()->ID
] = ToShow
;
871 case pkgCache::Dep::Conflicts
:
872 printf("label: \"conflicts\" color: lightgreen }\n");
874 case pkgCache::Dep::DpkgBreaks
:
875 printf("label: \"breaks\" color: lightgreen }\n");
877 case pkgCache::Dep::Obsoletes
:
878 printf("label: \"obsoletes\" color: lightgreen }\n");
881 case pkgCache::Dep::PreDepends
:
882 printf("label: \"predepends\" color: blue }\n");
894 /* Draw the box colours after the fact since we can not tell what colour
895 they should be until everything is finished drawing */
896 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
898 if (Show
[Pkg
->ID
] < DoneNR
)
901 if (Show
[Pkg
->ID
] == DoneNR
)
902 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
903 Shapes
[ShapeMap
[Pkg
->ID
]]);
905 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
906 Shapes
[ShapeMap
[Pkg
->ID
]]);
918 // Dotty - Generate a graph for Dotty /*{{{*/
919 // ---------------------------------------------------------------------
920 /* Dotty is the graphvis program for generating graphs. It is a fairly
921 simple queuing algorithm that just writes dependencies and nodes.
922 http://www.research.att.com/sw/tools/graphviz/ */
923 bool Dotty(CommandLine
&CmdL
)
925 pkgCacheFile CacheFile
;
926 pkgCache
*Cache
= CacheFile
.GetPkgCache();
927 if (unlikely(Cache
== NULL
))
930 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
932 /* Normal packages are boxes
933 Pure Provides are triangles
935 Hexagons are missing packages*/
936 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
938 /* Initialize the list of packages to show.
940 2 = To Show no recurse
941 3 = Emitted no recurse
944 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
945 enum TheFlags
{ForceNR
=(1<<0)};
946 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
947 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
948 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
950 // Show everything if no arguments given
951 if (CmdL
.FileList
[1] == 0)
952 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
955 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
957 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
960 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
962 if (Pkg
->VersionList
== 0)
965 if (Pkg
->ProvidesList
== 0)
966 ShapeMap
[Pkg
->ID
] = 0;
968 ShapeMap
[Pkg
->ID
] = 1;
973 if (Pkg
->ProvidesList
== 0)
974 ShapeMap
[Pkg
->ID
] = 2;
976 ShapeMap
[Pkg
->ID
] = 3;
980 // Load the list of packages from the command line into the show list
981 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
982 std::list
<APT::PackageSet::Modifier
> mods
;
983 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
984 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
985 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
986 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
988 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
989 Pkg
!= pkgsets
[0].end(); ++Pkg
)
990 Show
[Pkg
->ID
] = ToShow
;
991 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
992 Pkg
!= pkgsets
[1].end(); ++Pkg
)
994 Show
[Pkg
->ID
] = ToShow
;
995 Flags
[Pkg
->ID
] |= ForceNR
;
999 printf("digraph packages {\n");
1000 printf("concentrate=true;\n");
1001 printf("size=\"30,40\";\n");
1007 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1009 // See we need to show this package
1010 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1014 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1016 // Pure Provides and missing packages have no deps!
1017 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1018 Show
[Pkg
->ID
] = Done
;
1020 Show
[Pkg
->ID
] = DoneNR
;
1023 Show
[Pkg
->ID
] = Done
;
1026 // No deps to map out
1027 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1030 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1031 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1033 // See if anything can meet this dep
1034 // Walk along the actual package providing versions
1036 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1037 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1038 I
.end() == false && Hit
== false; ++I
)
1040 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1044 // Follow all provides
1045 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1046 I
.end() == false && Hit
== false; ++I
)
1048 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1052 // Only graph critical deps
1053 if (D
.IsCritical() == true)
1055 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1057 // Colour the node for recursion
1058 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1060 /* If a conflicts does not meet anything in the database
1061 then show the relation but do not recurse */
1062 if (Hit
== false && D
.IsNegative() == true)
1064 if (Show
[D
.TargetPkg()->ID
] == None
&&
1065 Show
[D
.TargetPkg()->ID
] != ToShow
)
1066 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1070 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1071 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1073 Show
[D
.TargetPkg()->ID
] = ToShow
;
1080 case pkgCache::Dep::Conflicts
:
1081 case pkgCache::Dep::Obsoletes
:
1082 case pkgCache::Dep::DpkgBreaks
:
1083 printf("[color=springgreen];\n");
1086 case pkgCache::Dep::PreDepends
:
1087 printf("[color=blue];\n");
1099 /* Draw the box colours after the fact since we can not tell what colour
1100 they should be until everything is finished drawing */
1101 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1103 if (Show
[Pkg
->ID
] < DoneNR
)
1106 // Orange box for early recursion stoppage
1107 if (Show
[Pkg
->ID
] == DoneNR
)
1108 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1109 Shapes
[ShapeMap
[Pkg
->ID
]]);
1111 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1112 Shapes
[ShapeMap
[Pkg
->ID
]]);
1122 // DisplayRecord - Displays the complete record for the package /*{{{*/
1123 // ---------------------------------------------------------------------
1124 /* This displays the package record from the proper package index file.
1125 It is not used by DumpAvail for performance reasons. */
1126 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1128 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1129 if (unlikely(Cache
== NULL
))
1132 // Find an appropriate file
1133 pkgCache::VerFileIterator Vf
= V
.FileList();
1134 for (; Vf
.end() == false; ++Vf
)
1135 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1137 if (Vf
.end() == true)
1140 // Check and load the package list file
1141 pkgCache::PkgFileIterator I
= Vf
.File();
1142 if (I
.IsOk() == false)
1143 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1146 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1150 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1151 Buffer
[V
.FileList()->Size
] = '\n';
1152 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1153 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1159 // Get a pointer to start of Description field
1160 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1162 // Write all but Description
1163 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1169 // Show the right description
1170 pkgRecords
Recs(*Cache
);
1171 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1172 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1173 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1175 // Find the first field after the description (if there is any)
1176 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1178 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1180 // write the rest of the buffer
1181 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1182 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1191 // write a final newline (after the description)
1201 pkgCache::DescFile
*Df
;
1205 // Search - Perform a search /*{{{*/
1206 // ---------------------------------------------------------------------
1207 /* This searches the package names and package descriptions for a pattern */
1208 bool Search(CommandLine
&CmdL
)
1210 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1211 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1212 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1214 pkgCacheFile CacheFile
;
1215 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1216 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1217 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1220 // Make sure there is at least one argument
1221 if (NumPatterns
< 1)
1222 return _error
->Error(_("You must give at least one search pattern"));
1224 // Compile the regex pattern
1225 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1226 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1227 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1229 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1233 regfree(&Patterns
[I
]);
1234 return _error
->Error("Regex compilation error");
1238 if (_error
->PendingError() == true)
1240 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1241 regfree(&Patterns
[I
]);
1245 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1246 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1248 // Map versions that we want to write out onto the VerList array.
1249 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1251 if (DFList
[G
->ID
].NameMatch
== true)
1254 DFList
[G
->ID
].NameMatch
= true;
1255 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1257 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1259 DFList
[G
->ID
].NameMatch
= false;
1263 // Doing names only, drop any that dont match..
1264 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1267 // Find the proper version to use
1268 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1269 if (P
.end() == true)
1271 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1272 if (V
.end() == false)
1273 DFList
[G
->ID
].Df
= V
.TranslatedDescription().FileList();
1275 if (DFList
[G
->ID
].NameMatch
== false)
1278 // Include all the packages that provide matching names too
1279 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1281 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1282 if (V
.end() == true)
1285 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1286 DFList
[id
].Df
= V
.TranslatedDescription().FileList();
1287 DFList
[id
].NameMatch
= true;
1291 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1293 // Create the text record parser
1294 pkgRecords
Recs(*Cache
);
1295 // Iterate over all the version records and check them
1296 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1298 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1300 if (J
->NameMatch
== false && NamesOnly
== false)
1302 string
const LongDesc
= P
.LongDesc();
1303 J
->NameMatch
= true;
1304 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1306 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1308 J
->NameMatch
= false;
1313 if (J
->NameMatch
== true)
1315 if (ShowFull
== true)
1319 P
.GetRec(Start
,End
);
1320 fwrite(Start
,End
-Start
,1,stdout
);
1324 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1329 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1330 regfree(&Patterns
[I
]);
1332 return _error
->Error("Write to stdout failed");
1336 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1337 bool ShowAuto(CommandLine
&CmdL
)
1339 pkgCacheFile CacheFile
;
1340 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1341 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1342 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1345 std::vector
<string
> packages
;
1346 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1348 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1349 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1350 packages
.push_back(P
.Name());
1352 std::sort(packages
.begin(), packages
.end());
1354 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1357 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1361 // ShowPackage - Dump the package record to the screen /*{{{*/
1362 // ---------------------------------------------------------------------
1364 bool ShowPackage(CommandLine
&CmdL
)
1366 pkgCacheFile CacheFile
;
1367 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1368 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1369 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1370 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1371 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1372 if (DisplayRecord(CacheFile
, Ver
) == false)
1375 if (verset
.empty() == true)
1377 if (helper
.virtualPkgs
.empty() == true)
1378 return _error
->Error(_("No packages found"));
1380 _error
->Notice(_("No packages found"));
1385 // ShowPkgNames - Show package names /*{{{*/
1386 // ---------------------------------------------------------------------
1387 /* This does a prefix match on the first argument */
1388 bool ShowPkgNames(CommandLine
&CmdL
)
1390 pkgCacheFile CacheFile
;
1391 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1393 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1394 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1396 if (CmdL
.FileList
[1] != 0)
1398 for (;I
.end() != true; ++I
)
1400 if (All
== false && I
->FirstPackage
== 0)
1402 if (I
.FindPkg("any")->VersionList
== 0)
1404 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1405 cout
<< I
.Name() << endl
;
1412 for (;I
.end() != true; ++I
)
1414 if (All
== false && I
->FirstPackage
== 0)
1416 if (I
.FindPkg("any")->VersionList
== 0)
1418 cout
<< I
.Name() << endl
;
1424 // ShowSrcPackage - Show source package records /*{{{*/
1425 // ---------------------------------------------------------------------
1427 bool ShowSrcPackage(CommandLine
&CmdL
)
1429 pkgCacheFile CacheFile
;
1430 pkgSourceList
*List
= CacheFile
.GetSourceList();
1431 if (unlikely(List
== NULL
))
1434 // Create the text record parsers
1435 pkgSrcRecords
SrcRecs(*List
);
1436 if (_error
->PendingError() == true)
1440 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1444 pkgSrcRecords::Parser
*Parse
;
1445 unsigned found_this
= 0;
1446 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1447 cout
<< Parse
->AsStr() << endl
;;
1451 if (found_this
== 0) {
1452 _error
->Warning(_("Unable to locate package %s"),*I
);
1457 _error
->Notice(_("No packages found"));
1461 // Policy - Show the results of the preferences file /*{{{*/
1462 // ---------------------------------------------------------------------
1464 bool Policy(CommandLine
&CmdL
)
1466 pkgCacheFile CacheFile
;
1467 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1468 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1469 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1470 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1473 /* Should the MultiArchKiller be run to see which pseudo packages for an
1474 arch all package are currently installed? Activating it gives a speed
1475 penality for no real gain beside enhanced debugging, so in general no. */
1476 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1477 CacheFile
.GetDepCache();
1479 // Print out all of the package files
1480 if (CmdL
.FileList
[1] == 0)
1482 cout
<< _("Package files:") << endl
;
1483 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1485 // Locate the associated index files so we can derive a description
1487 if (SrcList
->FindIndex(F
,Indx
) == false &&
1488 _system
->FindIndex(F
,Indx
) == false)
1489 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1492 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1494 // Print the reference information for the package
1495 string Str
= F
.RelStr();
1496 if (Str
.empty() == false)
1497 printf(" release %s\n",F
.RelStr().c_str());
1498 if (F
.Site() != 0 && F
.Site()[0] != 0)
1499 printf(" origin %s\n",F
.Site());
1502 // Show any packages have explicit pins
1503 cout
<< _("Pinned packages:") << endl
;
1504 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1505 for (;I
.end() != true; ++I
)
1507 if (Plcy
->GetPriority(I
) == 0)
1510 // Print the package name and the version we are forcing to
1511 cout
<< " " << I
.FullName(true) << " -> ";
1513 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1514 if (V
.end() == true)
1515 cout
<< _("(not found)") << endl
;
1517 cout
<< V
.VerStr() << endl
;
1523 char const * const msgInstalled
= _(" Installed: ");
1524 char const * const msgCandidate
= _(" Candidate: ");
1525 short const InstalledLessCandidate
=
1526 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1527 short const deepInstalled
=
1528 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1529 short const deepCandidate
=
1530 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1532 // Print out detailed information for each package
1533 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1534 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1535 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1537 cout
<< Pkg
.FullName(true) << ":" << endl
;
1539 // Installed version
1540 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1541 if (Pkg
->CurrentVer
== 0)
1542 cout
<< _("(none)") << endl
;
1544 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1546 // Candidate Version
1547 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1548 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1549 if (V
.end() == true)
1550 cout
<< _("(none)") << endl
;
1552 cout
<< V
.VerStr() << endl
;
1555 if (Plcy
->GetPriority(Pkg
) != 0)
1557 cout
<< _(" Package pin: ");
1558 V
= Plcy
->GetMatch(Pkg
);
1559 if (V
.end() == true)
1560 cout
<< _("(not found)") << endl
;
1562 cout
<< V
.VerStr() << endl
;
1565 // Show the priority tables
1566 cout
<< _(" Version table:") << endl
;
1567 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1569 if (Pkg
.CurrentVer() == V
)
1570 cout
<< " *** " << V
.VerStr();
1572 cout
<< " " << V
.VerStr();
1573 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1574 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1576 // Locate the associated index files so we can derive a description
1578 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1579 _system
->FindIndex(VF
.File(),Indx
) == false)
1580 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1581 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1582 Indx
->Describe(true).c_str());
1590 // Madison - Look a bit like katie's madison /*{{{*/
1591 // ---------------------------------------------------------------------
1593 bool Madison(CommandLine
&CmdL
)
1595 pkgCacheFile CacheFile
;
1596 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1601 // Create the src text record parsers and ignore errors about missing
1602 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1603 pkgSrcRecords
SrcRecs(*SrcList
);
1604 if (_error
->PendingError() == true)
1607 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1608 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1610 _error
->PushToStack();
1611 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1612 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1614 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1616 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1618 // This might be nice, but wouldn't uniquely identify the source -mdz
1619 // if (VF.File().Archive() != 0)
1621 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1622 // << VF.File().Archive() << endl;
1625 // Locate the associated index files so we can derive a description
1626 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1628 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1629 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1630 IF
!= Indexes
->end(); ++IF
)
1632 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1634 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1635 << (*IF
)->Describe(true) << endl
;
1644 pkgSrcRecords::Parser
*SrcParser
;
1645 bool foundSomething
= false;
1646 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1648 foundSomething
= true;
1649 // Maybe support Release info here too eventually
1650 cout
<< setw(10) << SrcParser
->Package() << " | "
1651 << setw(10) << SrcParser
->Version() << " | "
1652 << SrcParser
->Index().Describe(true) << endl
;
1654 if (foundSomething
== true)
1655 _error
->RevertToStack();
1657 _error
->MergeWithStack();
1663 // GenCaches - Call the main cache generator /*{{{*/
1664 // ---------------------------------------------------------------------
1666 bool GenCaches(CommandLine
&Cmd
)
1668 OpTextProgress
Progress(*_config
);
1670 pkgCacheFile CacheFile
;
1671 return CacheFile
.BuildCaches(&Progress
, true);
1674 // ShowHelp - Show a help screen /*{{{*/
1675 // ---------------------------------------------------------------------
1677 bool ShowHelp(CommandLine
&Cmd
)
1679 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1680 COMMON_ARCH
,__DATE__
,__TIME__
);
1682 if (_config
->FindB("version") == true)
1686 _("Usage: apt-cache [options] command\n"
1687 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1688 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1690 "apt-cache is a low-level tool used to query information\n"
1691 "from APT's binary cache files\n"
1694 " gencaches - Build both the package and source cache\n"
1695 " showpkg - Show some general information for a single package\n"
1696 " showsrc - Show source records\n"
1697 " stats - Show some basic statistics\n"
1698 " dump - Show the entire file in a terse form\n"
1699 " dumpavail - Print an available file to stdout\n"
1700 " unmet - Show unmet dependencies\n"
1701 " search - Search the package list for a regex pattern\n"
1702 " show - Show a readable record for the package\n"
1703 " depends - Show raw dependency information for a package\n"
1704 " rdepends - Show reverse dependency information for a package\n"
1705 " pkgnames - List the names of all packages in the system\n"
1706 " dotty - Generate package graphs for GraphViz\n"
1707 " xvcg - Generate package graphs for xvcg\n"
1708 " policy - Show policy settings\n"
1711 " -h This help text.\n"
1712 " -p=? The package cache.\n"
1713 " -s=? The source cache.\n"
1714 " -q Disable progress indicator.\n"
1715 " -i Show only important deps for the unmet command.\n"
1716 " -c=? Read this configuration file\n"
1717 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1718 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1722 int main(int argc
,const char *argv
[]) /*{{{*/
1724 CommandLine::Args Args
[] = {
1725 {'h',"help","help",0},
1726 {'v',"version","version",0},
1727 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1728 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1729 {'q',"quiet","quiet",CommandLine::IntLevel
},
1730 {'i',"important","APT::Cache::Important",0},
1731 {'f',"full","APT::Cache::ShowFull",0},
1732 {'g',"generate","APT::Cache::Generate",0},
1733 {'a',"all-versions","APT::Cache::AllVersions",0},
1734 {'n',"names-only","APT::Cache::NamesOnly",0},
1735 {0,"all-names","APT::Cache::AllNames",0},
1736 {0,"recurse","APT::Cache::RecurseDepends",0},
1737 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1738 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1739 {'c',"config-file",0,CommandLine::ConfigFile
},
1740 {'o',"option",0,CommandLine::ArbItem
},
1741 {0,"installed","APT::Cache::Installed",0},
1742 {0,"pre-depends","APT::Cache::ShowPre-Depends",0},
1743 {0,"depends","APT::Cache::ShowDepends",0},
1744 {0,"recommends","APT::Cache::ShowRecommends",0},
1745 {0,"suggests","APT::Cache::ShowSuggests",0},
1746 {0,"replaces","APT::Cache::ShowReplaces",0},
1747 {0,"breaks","APT::Cache::ShowBreaks",0},
1748 {0,"conflicts","APT::Cache::ShowConflicts",0},
1749 {0,"enhances","APT::Cache::ShowEnhances",0},
1751 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1752 {"gencaches",&GenCaches
},
1753 {"showsrc",&ShowSrcPackage
},
1755 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1758 {"dumpavail",&DumpAvail
},
1761 {"depends",&Depends
},
1762 {"rdepends",&RDepends
},
1765 {"show",&ShowPackage
},
1766 {"pkgnames",&ShowPkgNames
},
1767 {"showauto",&ShowAuto
},
1769 {"madison",&Madison
},
1772 // Set up gettext support
1773 setlocale(LC_ALL
,"");
1774 textdomain(PACKAGE
);
1776 // Parse the command line and initialize the package library
1777 CommandLine
CmdL(Args
,_config
);
1778 if (pkgInitConfig(*_config
) == false ||
1779 CmdL
.Parse(argc
,argv
) == false ||
1780 pkgInitSystem(*_config
,_system
) == false)
1782 _error
->DumpErrors();
1786 // See if the help should be shown
1787 if (_config
->FindB("help") == true ||
1788 CmdL
.FileSize() == 0)
1794 // Deal with stdout not being a tty
1795 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1796 _config
->Set("quiet","1");
1798 if (_config
->Exists("APT::Cache::Generate") == true)
1799 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1801 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1802 CmdL
.DispatchArg(CmdsB
);
1804 // Print any errors or warnings found during parsing
1805 bool const Errors
= _error
->PendingError();
1806 if (_config
->FindI("quiet",0) > 0)
1807 _error
->DumpErrors();
1809 _error
->DumpErrors(GlobalError::DEBUG
);
1810 return Errors
== true ? 100 : 0;