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 ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
601 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
602 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
603 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
604 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
605 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
606 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
607 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
608 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
609 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
611 while (verset
.empty() != true)
613 pkgCache::VerIterator Ver
= *verset
.begin();
614 verset
.erase(verset
.begin());
615 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
616 Shown
[Pkg
->ID
] = true;
618 cout
<< Pkg
.FullName(true) << endl
;
620 if (RevDepends
== true)
621 cout
<< "Reverse Depends:" << endl
;
622 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
623 D
.end() == false; ++D
)
626 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
627 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
628 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
629 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
630 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
631 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
632 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
633 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
636 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
638 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
641 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
647 if (ShowDepType
== true)
648 cout
<< D
.DepType() << ": ";
649 if (Trg
->VersionList
== 0)
650 cout
<< "<" << Trg
.FullName(true) << ">";
652 cout
<< Trg
.FullName(true);
653 if (ShowVersion
== true && D
->Version
!= 0)
654 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
657 if (Recurse
== true && Shown
[Trg
->ID
] == false)
659 Shown
[Trg
->ID
] = true;
660 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
665 // Display all solutions
666 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
667 pkgPrioSortList(*Cache
,List
);
668 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
670 pkgCache::VerIterator
V(*Cache
,*I
);
671 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
672 V
->ParentPkg
== D
->Package
)
674 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
676 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
678 Shown
[V
.ParentPkg()->ID
] = true;
679 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
683 if (ShowOnlyFirstOr
== true)
684 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
688 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
689 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
690 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
695 // Depends - Print out a dependency tree /*{{{*/
696 // ---------------------------------------------------------------------
698 bool Depends(CommandLine
&CmdL
)
700 return ShowDepends(CmdL
, false);
703 // RDepends - Print out a reverse dependency tree /*{{{*/
704 // ---------------------------------------------------------------------
706 bool RDepends(CommandLine
&CmdL
)
708 return ShowDepends(CmdL
, true);
711 // xvcg - Generate a graph for xvcg /*{{{*/
712 // ---------------------------------------------------------------------
713 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
715 bool XVcg(CommandLine
&CmdL
)
717 pkgCacheFile CacheFile
;
718 pkgCache
*Cache
= CacheFile
.GetPkgCache();
719 if (unlikely(Cache
== NULL
))
722 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
724 /* Normal packages are boxes
725 Pure Provides are triangles
727 rhomb are missing packages*/
728 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
730 /* Initialize the list of packages to show.
732 2 = To Show no recurse
733 3 = Emitted no recurse
736 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
737 enum TheFlags
{ForceNR
=(1<<0)};
738 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
739 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
740 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
742 // Show everything if no arguments given
743 if (CmdL
.FileList
[1] == 0)
744 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
747 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
749 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
752 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
754 if (Pkg
->VersionList
== 0)
757 if (Pkg
->ProvidesList
== 0)
758 ShapeMap
[Pkg
->ID
] = 0;
760 ShapeMap
[Pkg
->ID
] = 1;
765 if (Pkg
->ProvidesList
== 0)
766 ShapeMap
[Pkg
->ID
] = 2;
768 ShapeMap
[Pkg
->ID
] = 3;
772 // Load the list of packages from the command line into the show list
773 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
774 std::list
<APT::PackageSet::Modifier
> mods
;
775 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
776 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
777 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
778 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
780 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
781 Pkg
!= pkgsets
[0].end(); ++Pkg
)
782 Show
[Pkg
->ID
] = ToShow
;
783 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
784 Pkg
!= pkgsets
[1].end(); ++Pkg
)
786 Show
[Pkg
->ID
] = ToShow
;
787 Flags
[Pkg
->ID
] |= ForceNR
;
791 cout
<< "graph: { title: \"packages\"" << endl
<<
792 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
793 "layout_downfactor: 8" << endl
;
799 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
801 // See we need to show this package
802 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
805 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
808 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
810 // Pure Provides and missing packages have no deps!
811 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
812 Show
[Pkg
->ID
] = Done
;
814 Show
[Pkg
->ID
] = DoneNR
;
817 Show
[Pkg
->ID
] = Done
;
820 // No deps to map out
821 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
824 pkgCache::VerIterator Ver
= Pkg
.VersionList();
825 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
827 // See if anything can meet this dep
828 // Walk along the actual package providing versions
830 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
831 for (pkgCache::VerIterator I
= DPkg
.VersionList();
832 I
.end() == false && Hit
== false; ++I
)
834 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
838 // Follow all provides
839 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
840 I
.end() == false && Hit
== false; ++I
)
842 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
847 // Only graph critical deps
848 if (D
.IsCritical() == true)
850 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
852 // Colour the node for recursion
853 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
855 /* If a conflicts does not meet anything in the database
856 then show the relation but do not recurse */
857 if (Hit
== false && D
.IsNegative() == true)
859 if (Show
[D
.TargetPkg()->ID
] == None
&&
860 Show
[D
.TargetPkg()->ID
] != ToShow
)
861 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
865 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
866 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
868 Show
[D
.TargetPkg()->ID
] = ToShow
;
875 case pkgCache::Dep::Conflicts
:
876 printf("label: \"conflicts\" color: lightgreen }\n");
878 case pkgCache::Dep::DpkgBreaks
:
879 printf("label: \"breaks\" color: lightgreen }\n");
881 case pkgCache::Dep::Obsoletes
:
882 printf("label: \"obsoletes\" color: lightgreen }\n");
885 case pkgCache::Dep::PreDepends
:
886 printf("label: \"predepends\" color: blue }\n");
898 /* Draw the box colours after the fact since we can not tell what colour
899 they should be until everything is finished drawing */
900 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
902 if (Show
[Pkg
->ID
] < DoneNR
)
905 if (Show
[Pkg
->ID
] == DoneNR
)
906 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
907 Shapes
[ShapeMap
[Pkg
->ID
]]);
909 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
910 Shapes
[ShapeMap
[Pkg
->ID
]]);
922 // Dotty - Generate a graph for Dotty /*{{{*/
923 // ---------------------------------------------------------------------
924 /* Dotty is the graphvis program for generating graphs. It is a fairly
925 simple queuing algorithm that just writes dependencies and nodes.
926 http://www.research.att.com/sw/tools/graphviz/ */
927 bool Dotty(CommandLine
&CmdL
)
929 pkgCacheFile CacheFile
;
930 pkgCache
*Cache
= CacheFile
.GetPkgCache();
931 if (unlikely(Cache
== NULL
))
934 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
936 /* Normal packages are boxes
937 Pure Provides are triangles
939 Hexagons are missing packages*/
940 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
942 /* Initialize the list of packages to show.
944 2 = To Show no recurse
945 3 = Emitted no recurse
948 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
949 enum TheFlags
{ForceNR
=(1<<0)};
950 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
951 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
952 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
954 // Show everything if no arguments given
955 if (CmdL
.FileList
[1] == 0)
956 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
959 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
961 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
964 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
966 if (Pkg
->VersionList
== 0)
969 if (Pkg
->ProvidesList
== 0)
970 ShapeMap
[Pkg
->ID
] = 0;
972 ShapeMap
[Pkg
->ID
] = 1;
977 if (Pkg
->ProvidesList
== 0)
978 ShapeMap
[Pkg
->ID
] = 2;
980 ShapeMap
[Pkg
->ID
] = 3;
984 // Load the list of packages from the command line into the show list
985 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
986 std::list
<APT::PackageSet::Modifier
> mods
;
987 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
988 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
989 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
990 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
992 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
993 Pkg
!= pkgsets
[0].end(); ++Pkg
)
994 Show
[Pkg
->ID
] = ToShow
;
995 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
996 Pkg
!= pkgsets
[1].end(); ++Pkg
)
998 Show
[Pkg
->ID
] = ToShow
;
999 Flags
[Pkg
->ID
] |= ForceNR
;
1003 printf("digraph packages {\n");
1004 printf("concentrate=true;\n");
1005 printf("size=\"30,40\";\n");
1011 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1013 // See we need to show this package
1014 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1018 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1020 // Pure Provides and missing packages have no deps!
1021 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1022 Show
[Pkg
->ID
] = Done
;
1024 Show
[Pkg
->ID
] = DoneNR
;
1027 Show
[Pkg
->ID
] = Done
;
1030 // No deps to map out
1031 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1034 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1035 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1037 // See if anything can meet this dep
1038 // Walk along the actual package providing versions
1040 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1041 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1042 I
.end() == false && Hit
== false; ++I
)
1044 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1048 // Follow all provides
1049 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1050 I
.end() == false && Hit
== false; ++I
)
1052 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1056 // Only graph critical deps
1057 if (D
.IsCritical() == true)
1059 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1061 // Colour the node for recursion
1062 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1064 /* If a conflicts does not meet anything in the database
1065 then show the relation but do not recurse */
1066 if (Hit
== false && D
.IsNegative() == true)
1068 if (Show
[D
.TargetPkg()->ID
] == None
&&
1069 Show
[D
.TargetPkg()->ID
] != ToShow
)
1070 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1074 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1075 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1077 Show
[D
.TargetPkg()->ID
] = ToShow
;
1084 case pkgCache::Dep::Conflicts
:
1085 case pkgCache::Dep::Obsoletes
:
1086 case pkgCache::Dep::DpkgBreaks
:
1087 printf("[color=springgreen];\n");
1090 case pkgCache::Dep::PreDepends
:
1091 printf("[color=blue];\n");
1103 /* Draw the box colours after the fact since we can not tell what colour
1104 they should be until everything is finished drawing */
1105 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1107 if (Show
[Pkg
->ID
] < DoneNR
)
1110 // Orange box for early recursion stoppage
1111 if (Show
[Pkg
->ID
] == DoneNR
)
1112 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1113 Shapes
[ShapeMap
[Pkg
->ID
]]);
1115 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1116 Shapes
[ShapeMap
[Pkg
->ID
]]);
1126 // DisplayRecord - Displays the complete record for the package /*{{{*/
1127 // ---------------------------------------------------------------------
1128 /* This displays the package record from the proper package index file.
1129 It is not used by DumpAvail for performance reasons. */
1131 static unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1133 char const * const TagName
= "\nDescription";
1134 size_t const TagLen
= strlen(TagName
);
1135 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1137 if (DescP
[1] == ' ')
1139 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1148 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1150 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1151 if (unlikely(Cache
== NULL
))
1154 // Find an appropriate file
1155 pkgCache::VerFileIterator Vf
= V
.FileList();
1156 for (; Vf
.end() == false; ++Vf
)
1157 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1159 if (Vf
.end() == true)
1162 // Check and load the package list file
1163 pkgCache::PkgFileIterator I
= Vf
.File();
1164 if (I
.IsOk() == false)
1165 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1168 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1171 // Read the record (and ensure that it ends with a newline and NUL)
1172 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1173 Buffer
[Vf
->Size
] = '\n';
1174 Buffer
[Vf
->Size
+1] = '\0';
1175 if (PkgF
.Seek(Vf
->Offset
) == false ||
1176 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1182 // Get a pointer to start of Description field
1183 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1187 DescP
= Buffer
+ Vf
->Size
;
1189 // Write all but Description
1190 size_t const length
= DescP
- Buffer
;
1191 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1197 // Show the right description
1198 pkgRecords
Recs(*Cache
);
1199 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1200 if (Desc
.end() == false)
1202 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1203 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1204 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1206 // Find the first field after the description (if there is any)
1207 DescP
= skipDescriptionFields(DescP
);
1209 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1211 // write the rest of the buffer, but skip mixed in Descriptions* fields
1212 while (DescP
!= NULL
)
1214 const unsigned char * const Start
= DescP
;
1215 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1218 End
= &Buffer
[Vf
->Size
];
1223 ++End
; // get the newline into the output
1224 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1226 size_t const length
= End
- Start
;
1227 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1234 // write a final newline after the last field
1244 pkgCache::DescFile
*Df
;
1248 // Search - Perform a search /*{{{*/
1249 // ---------------------------------------------------------------------
1250 /* This searches the package names and package descriptions for a pattern */
1251 bool Search(CommandLine
&CmdL
)
1253 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1254 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1255 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1257 pkgCacheFile CacheFile
;
1258 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1259 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1260 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1263 // Make sure there is at least one argument
1264 if (NumPatterns
< 1)
1265 return _error
->Error(_("You must give at least one search pattern"));
1267 // Compile the regex pattern
1268 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1269 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1270 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1272 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1276 regfree(&Patterns
[I
]);
1277 return _error
->Error("Regex compilation error");
1281 if (_error
->PendingError() == true)
1283 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1284 regfree(&Patterns
[I
]);
1288 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1289 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1290 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1292 bool PatternMatch
[descCount
* NumPatterns
];
1293 memset(PatternMatch
,false,sizeof(PatternMatch
));
1295 // Map versions that we want to write out onto the VerList array.
1296 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1298 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1299 size_t unmatched
= 0, matched
= 0;
1300 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1302 if (PatternMatch
[PatternOffset
+ I
] == true)
1304 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1305 PatternMatch
[PatternOffset
+ I
] = true;
1310 // already dealt with this package?
1311 if (matched
== NumPatterns
)
1314 // Doing names only, drop any that don't match..
1315 if (NamesOnly
== true && unmatched
== NumPatterns
)
1318 // Find the proper version to use
1319 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1320 if (P
.end() == true)
1322 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1323 if (V
.end() == false)
1325 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1326 //FIXME: packages without a description can't be found
1327 if (D
.end() == true)
1329 DFList
[G
->ID
].Df
= D
.FileList();
1330 DFList
[G
->ID
].ID
= G
->ID
;
1333 if (unmatched
== NumPatterns
)
1336 // Include all the packages that provide matching names too
1337 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1339 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1340 if (V
.end() == true)
1343 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1344 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1345 //FIXME: packages without a description can't be found
1346 if (D
.end() == true)
1348 DFList
[id
].Df
= D
.FileList();
1351 size_t const PrvPatternOffset
= id
* NumPatterns
;
1352 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1353 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1357 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1359 // Create the text record parser
1360 pkgRecords
Recs(*Cache
);
1361 // Iterate over all the version records and check them
1362 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1364 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1365 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1367 if (NamesOnly
== false)
1369 string
const LongDesc
= P
.LongDesc();
1370 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1372 if (PatternMatch
[PatternOffset
+ I
] == true)
1374 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1375 PatternMatch
[PatternOffset
+ I
] = true;
1379 bool matchedAll
= true;
1380 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1381 if (PatternMatch
[PatternOffset
+ I
] == false)
1387 if (matchedAll
== true)
1389 if (ShowFull
== true)
1393 P
.GetRec(Start
,End
);
1394 fwrite(Start
,End
-Start
,1,stdout
);
1398 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1403 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1404 regfree(&Patterns
[I
]);
1406 return _error
->Error("Write to stdout failed");
1410 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1411 bool ShowAuto(CommandLine
&CmdL
)
1413 pkgCacheFile CacheFile
;
1414 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1415 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1416 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1419 std::vector
<string
> packages
;
1420 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1422 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1423 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1424 packages
.push_back(P
.Name());
1426 std::sort(packages
.begin(), packages
.end());
1428 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1431 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1435 // ShowPackage - Dump the package record to the screen /*{{{*/
1436 // ---------------------------------------------------------------------
1438 bool ShowPackage(CommandLine
&CmdL
)
1440 pkgCacheFile CacheFile
;
1441 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1442 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1443 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1444 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1445 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1446 if (DisplayRecord(CacheFile
, Ver
) == false)
1449 if (verset
.empty() == true)
1451 if (helper
.virtualPkgs
.empty() == true)
1452 return _error
->Error(_("No packages found"));
1454 _error
->Notice(_("No packages found"));
1459 // ShowPkgNames - Show package names /*{{{*/
1460 // ---------------------------------------------------------------------
1461 /* This does a prefix match on the first argument */
1462 bool ShowPkgNames(CommandLine
&CmdL
)
1464 pkgCacheFile CacheFile
;
1465 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1467 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1468 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1470 if (CmdL
.FileList
[1] != 0)
1472 for (;I
.end() != true; ++I
)
1474 if (All
== false && I
->FirstPackage
== 0)
1476 if (I
.FindPkg("any")->VersionList
== 0)
1478 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1479 cout
<< I
.Name() << endl
;
1486 for (;I
.end() != true; ++I
)
1488 if (All
== false && I
->FirstPackage
== 0)
1490 if (I
.FindPkg("any")->VersionList
== 0)
1492 cout
<< I
.Name() << endl
;
1498 // ShowSrcPackage - Show source package records /*{{{*/
1499 // ---------------------------------------------------------------------
1501 bool ShowSrcPackage(CommandLine
&CmdL
)
1503 pkgCacheFile CacheFile
;
1504 pkgSourceList
*List
= CacheFile
.GetSourceList();
1505 if (unlikely(List
== NULL
))
1508 // Create the text record parsers
1509 pkgSrcRecords
SrcRecs(*List
);
1510 if (_error
->PendingError() == true)
1514 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1518 pkgSrcRecords::Parser
*Parse
;
1519 unsigned found_this
= 0;
1520 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1521 cout
<< Parse
->AsStr() << endl
;;
1525 if (found_this
== 0) {
1526 _error
->Warning(_("Unable to locate package %s"),*I
);
1531 _error
->Notice(_("No packages found"));
1535 // Policy - Show the results of the preferences file /*{{{*/
1536 // ---------------------------------------------------------------------
1538 bool Policy(CommandLine
&CmdL
)
1540 pkgCacheFile CacheFile
;
1541 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1542 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1543 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1544 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1547 /* Should the MultiArchKiller be run to see which pseudo packages for an
1548 arch all package are currently installed? Activating it gives a speed
1549 penality for no real gain beside enhanced debugging, so in general no. */
1550 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1551 CacheFile
.GetDepCache();
1553 // Print out all of the package files
1554 if (CmdL
.FileList
[1] == 0)
1556 cout
<< _("Package files:") << endl
;
1557 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1559 // Locate the associated index files so we can derive a description
1561 if (SrcList
->FindIndex(F
,Indx
) == false &&
1562 _system
->FindIndex(F
,Indx
) == false)
1563 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1566 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1568 // Print the reference information for the package
1569 string Str
= F
.RelStr();
1570 if (Str
.empty() == false)
1571 printf(" release %s\n",F
.RelStr().c_str());
1572 if (F
.Site() != 0 && F
.Site()[0] != 0)
1573 printf(" origin %s\n",F
.Site());
1576 // Show any packages have explicit pins
1577 cout
<< _("Pinned packages:") << endl
;
1578 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1579 for (;I
.end() != true; ++I
)
1581 if (Plcy
->GetPriority(I
) == 0)
1584 // Print the package name and the version we are forcing to
1585 cout
<< " " << I
.FullName(true) << " -> ";
1587 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1588 if (V
.end() == true)
1589 cout
<< _("(not found)") << endl
;
1591 cout
<< V
.VerStr() << endl
;
1597 char const * const msgInstalled
= _(" Installed: ");
1598 char const * const msgCandidate
= _(" Candidate: ");
1599 short const InstalledLessCandidate
=
1600 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1601 short const deepInstalled
=
1602 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1603 short const deepCandidate
=
1604 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1606 // Print out detailed information for each package
1607 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1608 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1609 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1611 cout
<< Pkg
.FullName(true) << ":" << endl
;
1613 // Installed version
1614 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1615 if (Pkg
->CurrentVer
== 0)
1616 cout
<< _("(none)") << endl
;
1618 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1620 // Candidate Version
1621 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1622 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1623 if (V
.end() == true)
1624 cout
<< _("(none)") << endl
;
1626 cout
<< V
.VerStr() << endl
;
1629 if (Plcy
->GetPriority(Pkg
) != 0)
1631 cout
<< _(" Package pin: ");
1632 V
= Plcy
->GetMatch(Pkg
);
1633 if (V
.end() == true)
1634 cout
<< _("(not found)") << endl
;
1636 cout
<< V
.VerStr() << endl
;
1639 // Show the priority tables
1640 cout
<< _(" Version table:") << endl
;
1641 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1643 if (Pkg
.CurrentVer() == V
)
1644 cout
<< " *** " << V
.VerStr();
1646 cout
<< " " << V
.VerStr();
1647 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1648 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1650 // Locate the associated index files so we can derive a description
1652 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1653 _system
->FindIndex(VF
.File(),Indx
) == false)
1654 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1655 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1656 Indx
->Describe(true).c_str());
1664 // Madison - Look a bit like katie's madison /*{{{*/
1665 // ---------------------------------------------------------------------
1667 bool Madison(CommandLine
&CmdL
)
1669 pkgCacheFile CacheFile
;
1670 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1675 // Create the src text record parsers and ignore errors about missing
1676 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1677 pkgSrcRecords
SrcRecs(*SrcList
);
1678 if (_error
->PendingError() == true)
1681 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1682 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1684 _error
->PushToStack();
1685 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1686 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1688 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1690 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1692 // This might be nice, but wouldn't uniquely identify the source -mdz
1693 // if (VF.File().Archive() != 0)
1695 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1696 // << VF.File().Archive() << endl;
1699 // Locate the associated index files so we can derive a description
1700 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1702 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1703 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1704 IF
!= Indexes
->end(); ++IF
)
1706 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1708 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1709 << (*IF
)->Describe(true) << endl
;
1718 pkgSrcRecords::Parser
*SrcParser
;
1719 bool foundSomething
= false;
1720 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1722 foundSomething
= true;
1723 // Maybe support Release info here too eventually
1724 cout
<< setw(10) << SrcParser
->Package() << " | "
1725 << setw(10) << SrcParser
->Version() << " | "
1726 << SrcParser
->Index().Describe(true) << endl
;
1728 if (foundSomething
== true)
1729 _error
->RevertToStack();
1731 _error
->MergeWithStack();
1737 // GenCaches - Call the main cache generator /*{{{*/
1738 // ---------------------------------------------------------------------
1740 bool GenCaches(CommandLine
&Cmd
)
1742 OpTextProgress
Progress(*_config
);
1744 pkgCacheFile CacheFile
;
1745 return CacheFile
.BuildCaches(&Progress
, true);
1748 // ShowHelp - Show a help screen /*{{{*/
1749 // ---------------------------------------------------------------------
1751 bool ShowHelp(CommandLine
&Cmd
)
1753 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1754 COMMON_ARCH
,__DATE__
,__TIME__
);
1756 if (_config
->FindB("version") == true)
1760 _("Usage: apt-cache [options] command\n"
1761 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1762 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1764 "apt-cache is a low-level tool used to query information\n"
1765 "from APT's binary cache files\n"
1768 " gencaches - Build both the package and source cache\n"
1769 " showpkg - Show some general information for a single package\n"
1770 " showsrc - Show source records\n"
1771 " stats - Show some basic statistics\n"
1772 " dump - Show the entire file in a terse form\n"
1773 " dumpavail - Print an available file to stdout\n"
1774 " unmet - Show unmet dependencies\n"
1775 " search - Search the package list for a regex pattern\n"
1776 " show - Show a readable record for the package\n"
1777 " depends - Show raw dependency information for a package\n"
1778 " rdepends - Show reverse dependency information for a package\n"
1779 " pkgnames - List the names of all packages in the system\n"
1780 " dotty - Generate package graphs for GraphViz\n"
1781 " xvcg - Generate package graphs for xvcg\n"
1782 " policy - Show policy settings\n"
1785 " -h This help text.\n"
1786 " -p=? The package cache.\n"
1787 " -s=? The source cache.\n"
1788 " -q Disable progress indicator.\n"
1789 " -i Show only important deps for the unmet command.\n"
1790 " -c=? Read this configuration file\n"
1791 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1792 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1796 int main(int argc
,const char *argv
[]) /*{{{*/
1798 CommandLine::Args Args
[] = {
1799 {'h',"help","help",0},
1800 {'v',"version","version",0},
1801 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1802 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1803 {'q',"quiet","quiet",CommandLine::IntLevel
},
1804 {'i',"important","APT::Cache::Important",0},
1805 {'f',"full","APT::Cache::ShowFull",0},
1806 {'g',"generate","APT::Cache::Generate",0},
1807 {'a',"all-versions","APT::Cache::AllVersions",0},
1808 {'n',"names-only","APT::Cache::NamesOnly",0},
1809 {0,"all-names","APT::Cache::AllNames",0},
1810 {0,"recurse","APT::Cache::RecurseDepends",0},
1811 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1812 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1813 {'c',"config-file",0,CommandLine::ConfigFile
},
1814 {'o',"option",0,CommandLine::ArbItem
},
1815 {0,"installed","APT::Cache::Installed",0},
1816 {0,"pre-depends","APT::Cache::ShowPre-Depends",0},
1817 {0,"depends","APT::Cache::ShowDepends",0},
1818 {0,"recommends","APT::Cache::ShowRecommends",0},
1819 {0,"suggests","APT::Cache::ShowSuggests",0},
1820 {0,"replaces","APT::Cache::ShowReplaces",0},
1821 {0,"breaks","APT::Cache::ShowBreaks",0},
1822 {0,"conflicts","APT::Cache::ShowConflicts",0},
1823 {0,"enhances","APT::Cache::ShowEnhances",0},
1825 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1826 {"gencaches",&GenCaches
},
1827 {"showsrc",&ShowSrcPackage
},
1829 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1832 {"dumpavail",&DumpAvail
},
1835 {"depends",&Depends
},
1836 {"rdepends",&RDepends
},
1839 {"show",&ShowPackage
},
1840 {"pkgnames",&ShowPkgNames
},
1841 {"showauto",&ShowAuto
},
1843 {"madison",&Madison
},
1846 // Set up gettext support
1847 setlocale(LC_ALL
,"");
1848 textdomain(PACKAGE
);
1850 // Parse the command line and initialize the package library
1851 CommandLine
CmdL(Args
,_config
);
1852 if (pkgInitConfig(*_config
) == false ||
1853 CmdL
.Parse(argc
,argv
) == false ||
1854 pkgInitSystem(*_config
,_system
) == false)
1856 _error
->DumpErrors();
1860 // See if the help should be shown
1861 if (_config
->FindB("help") == true ||
1862 CmdL
.FileSize() == 0)
1868 // Deal with stdout not being a tty
1869 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1870 _config
->Set("quiet","1");
1872 if (_config
->Exists("APT::Cache::Generate") == true)
1873 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1875 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1876 CmdL
.DispatchArg(CmdsB
);
1878 // Print any errors or warnings found during parsing
1879 bool const Errors
= _error
->PendingError();
1880 if (_config
->FindI("quiet",0) > 0)
1881 _error
->DumpErrors();
1883 _error
->DumpErrors(GlobalError::DEBUG
);
1884 return Errors
== true ? 100 : 0;