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 /*{{{*/
16 #include <apt-pkg/error.h>
18 #include <apt-pkg/pkgcachegen.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/pkgrecords.h>
27 #include <apt-pkg/srcrecords.h>
28 #include <apt-pkg/version.h>
29 #include <apt-pkg/policy.h>
30 #include <apt-pkg/tagfile.h>
31 #include <apt-pkg/algorithms.h>
32 #include <apt-pkg/sptr.h>
49 // LocalitySort - Sort a version list by package file locality /*{{{*/
50 // ---------------------------------------------------------------------
52 int LocalityCompare(const void *a
, const void *b
)
54 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
55 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
64 if (A
->File
== B
->File
)
65 return A
->Offset
- B
->Offset
;
66 return A
->File
- B
->File
;
69 void LocalitySort(pkgCache::VerFile
**begin
,
70 unsigned long Count
,size_t Size
)
72 qsort(begin
,Count
,Size
,LocalityCompare
);
75 void LocalitySort(pkgCache::DescFile
**begin
,
76 unsigned long Count
,size_t Size
)
78 qsort(begin
,Count
,Size
,LocalityCompare
);
81 // UnMet - Show unmet dependencies /*{{{*/
82 // ---------------------------------------------------------------------
84 bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const &Important
)
87 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
90 pkgCache::DepIterator Start
;
91 pkgCache::DepIterator End
;
94 // Important deps only
95 if (Important
== true)
96 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
97 End
->Type
!= pkgCache::Dep::Depends
)
100 // Skip conflicts and replaces
101 if (End
->Type
== pkgCache::Dep::DpkgBreaks
||
102 End
->Type
== pkgCache::Dep::Replaces
||
103 End
->Type
== pkgCache::Dep::Conflicts
)
106 // Verify the or group
108 pkgCache::DepIterator RealStart
= Start
;
111 // See if this dep is Ok
112 pkgCache::Version
**VList
= Start
.AllTargets();
133 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
134 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
137 // Print out the dep type
138 cout
<< " " << End
.DepType() << ": ";
144 cout
<< Start
.TargetPkg().FullName(true);
145 if (Start
.TargetVer() != 0)
146 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
159 bool UnMet(CommandLine
&CmdL
)
161 bool const Important
= _config
->FindB("APT::Cache::Important",false);
163 pkgCacheFile CacheFile
;
164 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
167 if (CmdL
.FileSize() <= 1)
169 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; P
++)
170 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
171 if (ShowUnMet(V
, Important
) == false)
176 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
177 for (APT::VersionSet::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
178 if (ShowUnMet(V
, Important
) == false)
184 // DumpPackage - Show a dump of a package record /*{{{*/
185 // ---------------------------------------------------------------------
187 bool DumpPackage(CommandLine
&CmdL
)
189 pkgCacheFile CacheFile
;
190 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
192 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
194 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
195 cout
<< "Versions: " << endl
;
196 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
198 cout
<< Cur
.VerStr();
199 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
200 cout
<< " (" << Vf
.File().FileName() << ")";
202 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; D
++)
204 cout
<< " Description Language: " << D
.LanguageCode() << endl
205 << " File: " << D
.FileList().File().FileName() << endl
206 << " MD5: " << D
.md5() << endl
;
213 cout
<< "Reverse Depends: " << endl
;
214 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
216 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
218 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
223 cout
<< "Dependencies: " << endl
;
224 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
226 cout
<< Cur
.VerStr() << " - ";
227 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
228 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
232 cout
<< "Provides: " << endl
;
233 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
235 cout
<< Cur
.VerStr() << " - ";
236 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
237 cout
<< Prv
.ParentPkg().FullName(true) << " ";
240 cout
<< "Reverse Provides: " << endl
;
241 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
242 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
248 // Stats - Dump some nice statistics /*{{{*/
249 // ---------------------------------------------------------------------
251 bool Stats(CommandLine
&Cmd
)
253 pkgCacheFile CacheFile
;
254 pkgCache
*Cache
= CacheFile
.GetPkgCache();
255 if (unlikely(Cache
== NULL
))
258 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
259 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
260 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
261 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
268 pkgCache::PkgIterator I
= Cache
->PkgBegin();
269 for (;I
.end() != true; I
++)
271 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
277 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
283 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
286 if (I
.ProvidesList()->NextProvides
== 0)
294 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
300 cout
<< _(" Normal packages: ") << Normal
<< endl
;
301 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
302 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
303 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
304 cout
<< _(" Missing: ") << Missing
<< endl
;
306 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
307 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
308 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
309 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
310 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
311 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
313 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
314 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
315 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
316 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
317 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
318 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
321 unsigned long Size
= 0;
322 unsigned long Count
= 0;
323 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
324 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
327 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
329 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
331 unsigned long DepVerSize
= 0;
332 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
334 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
336 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
339 DepVerSize
+= strlen(D
.TargetVer()) + 1;
343 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
345 unsigned long Slack
= 0;
346 for (int I
= 0; I
!= 7; I
++)
347 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
348 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
350 unsigned long Total
= 0;
351 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
352 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
353 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
354 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
355 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
356 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
361 // Dump - show everything /*{{{*/
362 // ---------------------------------------------------------------------
363 /* This is worthless except fer debugging things */
364 bool Dump(CommandLine
&Cmd
)
366 pkgCacheFile CacheFile
;
367 pkgCache
*Cache
= CacheFile
.GetPkgCache();
368 if (unlikely(Cache
== NULL
))
371 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
373 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
375 cout
<< "Package: " << P
.FullName(true) << endl
;
376 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
378 cout
<< " Version: " << V
.VerStr() << endl
;
379 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
380 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
381 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
382 DeNull(D
.TargetVer()) << endl
;
383 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; D
++)
385 cout
<< " Description Language: " << D
.LanguageCode() << endl
386 << " File: " << D
.FileList().File().FileName() << endl
387 << " MD5: " << D
.md5() << endl
;
392 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
394 cout
<< "File: " << F
.FileName() << endl
;
395 cout
<< " Type: " << F
.IndexType() << endl
;
396 cout
<< " Size: " << F
->Size
<< endl
;
397 cout
<< " ID: " << F
->ID
<< endl
;
398 cout
<< " Flags: " << F
->Flags
<< endl
;
399 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
400 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
401 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
402 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
403 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
404 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
405 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
406 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
412 // DumpAvail - Print out the available list /*{{{*/
413 // ---------------------------------------------------------------------
414 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
415 make this run really fast, perhaps I went a little overboard.. */
416 bool DumpAvail(CommandLine
&Cmd
)
418 pkgCacheFile CacheFile
;
419 pkgCache
*Cache
= CacheFile
.GetPkgCache();
420 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
423 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
424 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
425 memset(VFList
,0,sizeof(*VFList
)*Count
);
427 // Map versions that we want to write out onto the VerList array.
428 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
430 if (P
->VersionList
== 0)
433 /* Find the proper version to use. If the policy says there are no
434 possible selections we return the installed version, if available..
435 This prevents dselect from making it obsolete. */
436 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
439 if (P
->CurrentVer
== 0)
444 pkgCache::VerFileIterator VF
= V
.FileList();
445 for (; VF
.end() == false ; VF
++)
446 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
449 /* Okay, here we have a bit of a problem.. The policy has selected the
450 currently installed package - however it only exists in the
451 status file.. We need to write out something or dselect will mark
452 the package as obsolete! Thus we emit the status file entry, but
453 below we remove the status line to make it valid for the
454 available file. However! We only do this if their do exist *any*
455 non-source versions of the package - that way the dselect obsolete
456 handling works OK. */
457 if (VF
.end() == true)
459 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
461 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
463 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
470 if (VF
.end() == false)
478 LocalitySort(VFList
,Count
,sizeof(*VFList
));
480 // Iterate over all the package files and write them out.
481 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
482 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
484 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
485 if (File
.IsOk() == false)
487 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
491 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
492 if (_error
->PendingError() == true)
495 /* Write all of the records from this package file, since we
496 already did locality sorting we can now just seek through the
497 file in read order. We apply 1 more optimization here, since often
498 there will be < 1 byte gaps between records (for the \n) we read that
499 into the next buffer and offset a bit.. */
500 unsigned long Pos
= 0;
503 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
506 const pkgCache::VerFile
&VF
= **J
;
508 // Read the record and then write it out again.
509 unsigned long Jitter
= VF
.Offset
- Pos
;
512 if (PkgF
.Seek(VF
.Offset
) == false)
517 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
519 Buffer
[VF
.Size
+ Jitter
] = '\n';
522 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
525 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
526 const char *Zero
= 0;
527 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
528 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
530 _error
->Error("Internal Error, Unable to parse a package record");
537 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
541 Pos
= VF
.Offset
+ VF
.Size
;
545 if (_error
->PendingError() == true)
551 return !_error
->PendingError();
554 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
555 class CacheSetHelperDepends
: public APT::CacheSetHelper
{
557 APT::PackageSet virtualPkgs
;
559 virtual pkgCache::VerIterator
canNotFindCandidateVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
560 virtualPkgs
.insert(Pkg
);
561 return pkgCache::VerIterator(Cache
, 0);
564 virtual pkgCache::VerIterator
canNotFindNewestVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
565 virtualPkgs
.insert(Pkg
);
566 return pkgCache::VerIterator(Cache
, 0);
569 CacheSetHelperDepends() : CacheSetHelper(false) {}
571 bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
573 pkgCacheFile CacheFile
;
574 pkgCache
*Cache
= CacheFile
.GetPkgCache();
575 if (unlikely(Cache
== NULL
))
578 CacheSetHelperDepends helper
;
579 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionSet::CANDIDATE
, helper
);
580 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
582 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
584 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
585 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
586 bool const Important
= _config
->FindB("APT::Cache::Important", false);
587 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
588 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
589 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
590 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
591 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
592 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
593 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
594 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
595 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
596 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
598 while (verset
.empty() != true)
600 pkgCache::VerIterator Ver
= *verset
.begin();
601 verset
.erase(verset
.begin());
602 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
603 Shown
[Pkg
->ID
] = true;
605 cout
<< Pkg
.FullName(true) << endl
;
607 if (RevDepends
== true)
608 cout
<< "Reverse Depends:" << endl
;
609 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
610 D
.end() == false; D
++)
613 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
614 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
615 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
616 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
617 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
618 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
619 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
620 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
623 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
625 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
628 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
634 if (ShowDepType
== true)
635 cout
<< D
.DepType() << ": ";
636 if (Trg
->VersionList
== 0)
637 cout
<< "<" << Trg
.FullName(true) << ">" << endl
;
639 cout
<< Trg
.FullName(true) << endl
;
641 if (Recurse
== true && Shown
[Trg
->ID
] == false)
643 Shown
[Trg
->ID
] = true;
644 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
649 // Display all solutions
650 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
651 pkgPrioSortList(*Cache
,List
);
652 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
654 pkgCache::VerIterator
V(*Cache
,*I
);
655 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
656 V
->ParentPkg
== D
->Package
)
658 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
660 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
662 Shown
[V
.ParentPkg()->ID
] = true;
663 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
667 if (ShowOnlyFirstOr
== true)
668 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
672 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
673 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
674 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
679 // Depends - Print out a dependency tree /*{{{*/
680 // ---------------------------------------------------------------------
682 bool Depends(CommandLine
&CmdL
)
684 return ShowDepends(CmdL
, false);
687 // RDepends - Print out a reverse dependency tree /*{{{*/
688 // ---------------------------------------------------------------------
690 bool RDepends(CommandLine
&CmdL
)
692 return ShowDepends(CmdL
, true);
695 // xvcg - Generate a graph for xvcg /*{{{*/
696 // ---------------------------------------------------------------------
697 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
699 bool XVcg(CommandLine
&CmdL
)
701 pkgCacheFile CacheFile
;
702 pkgCache
*Cache
= CacheFile
.GetPkgCache();
703 if (unlikely(Cache
== NULL
))
706 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
708 /* Normal packages are boxes
709 Pure Provides are triangles
711 rhomb are missing packages*/
712 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
714 /* Initialize the list of packages to show.
716 2 = To Show no recurse
717 3 = Emitted no recurse
720 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
721 enum TheFlags
{ForceNR
=(1<<0)};
722 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
723 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
724 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
726 // Show everything if no arguments given
727 if (CmdL
.FileList
[1] == 0)
728 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
731 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
733 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
736 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
738 if (Pkg
->VersionList
== 0)
741 if (Pkg
->ProvidesList
== 0)
742 ShapeMap
[Pkg
->ID
] = 0;
744 ShapeMap
[Pkg
->ID
] = 1;
749 if (Pkg
->ProvidesList
== 0)
750 ShapeMap
[Pkg
->ID
] = 2;
752 ShapeMap
[Pkg
->ID
] = 3;
756 // Load the list of packages from the command line into the show list
757 std::list
<APT::PackageSet::Modifier
> mods
;
758 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
759 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
760 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
761 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
763 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
764 Pkg
!= pkgsets
[0].end(); ++Pkg
)
765 Show
[Pkg
->ID
] = ToShow
;
766 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
767 Pkg
!= pkgsets
[1].end(); ++Pkg
)
769 Show
[Pkg
->ID
] = ToShow
;
770 Flags
[Pkg
->ID
] |= ForceNR
;
774 cout
<< "graph: { title: \"packages\"" << endl
<<
775 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
776 "layout_downfactor: 8" << endl
;
782 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
784 // See we need to show this package
785 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
788 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
791 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
793 // Pure Provides and missing packages have no deps!
794 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
795 Show
[Pkg
->ID
] = Done
;
797 Show
[Pkg
->ID
] = DoneNR
;
800 Show
[Pkg
->ID
] = Done
;
803 // No deps to map out
804 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
807 pkgCache::VerIterator Ver
= Pkg
.VersionList();
808 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
810 // See if anything can meet this dep
811 // Walk along the actual package providing versions
813 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
814 for (pkgCache::VerIterator I
= DPkg
.VersionList();
815 I
.end() == false && Hit
== false; I
++)
817 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
821 // Follow all provides
822 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
823 I
.end() == false && Hit
== false; I
++)
825 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
830 // Only graph critical deps
831 if (D
.IsCritical() == true)
833 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
835 // Colour the node for recursion
836 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
838 /* If a conflicts does not meet anything in the database
839 then show the relation but do not recurse */
841 (D
->Type
== pkgCache::Dep::Conflicts
||
842 D
->Type
== pkgCache::Dep::DpkgBreaks
||
843 D
->Type
== pkgCache::Dep::Obsoletes
))
845 if (Show
[D
.TargetPkg()->ID
] == None
&&
846 Show
[D
.TargetPkg()->ID
] != ToShow
)
847 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
851 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
852 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
854 Show
[D
.TargetPkg()->ID
] = ToShow
;
861 case pkgCache::Dep::Conflicts
:
862 printf("label: \"conflicts\" color: lightgreen }\n");
864 case pkgCache::Dep::DpkgBreaks
:
865 printf("label: \"breaks\" color: lightgreen }\n");
867 case pkgCache::Dep::Obsoletes
:
868 printf("label: \"obsoletes\" color: lightgreen }\n");
871 case pkgCache::Dep::PreDepends
:
872 printf("label: \"predepends\" color: blue }\n");
884 /* Draw the box colours after the fact since we can not tell what colour
885 they should be until everything is finished drawing */
886 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
888 if (Show
[Pkg
->ID
] < DoneNR
)
891 if (Show
[Pkg
->ID
] == DoneNR
)
892 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
893 Shapes
[ShapeMap
[Pkg
->ID
]]);
895 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
896 Shapes
[ShapeMap
[Pkg
->ID
]]);
908 // Dotty - Generate a graph for Dotty /*{{{*/
909 // ---------------------------------------------------------------------
910 /* Dotty is the graphvis program for generating graphs. It is a fairly
911 simple queuing algorithm that just writes dependencies and nodes.
912 http://www.research.att.com/sw/tools/graphviz/ */
913 bool Dotty(CommandLine
&CmdL
)
915 pkgCacheFile CacheFile
;
916 pkgCache
*Cache
= CacheFile
.GetPkgCache();
917 if (unlikely(Cache
== NULL
))
920 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
922 /* Normal packages are boxes
923 Pure Provides are triangles
925 Hexagons are missing packages*/
926 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
928 /* Initialize the list of packages to show.
930 2 = To Show no recurse
931 3 = Emitted no recurse
934 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
935 enum TheFlags
{ForceNR
=(1<<0)};
936 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
937 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
938 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
940 // Show everything if no arguments given
941 if (CmdL
.FileList
[1] == 0)
942 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
945 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
947 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
950 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
952 if (Pkg
->VersionList
== 0)
955 if (Pkg
->ProvidesList
== 0)
956 ShapeMap
[Pkg
->ID
] = 0;
958 ShapeMap
[Pkg
->ID
] = 1;
963 if (Pkg
->ProvidesList
== 0)
964 ShapeMap
[Pkg
->ID
] = 2;
966 ShapeMap
[Pkg
->ID
] = 3;
970 // Load the list of packages from the command line into the show list
971 std::list
<APT::PackageSet::Modifier
> mods
;
972 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
973 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
974 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
975 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
977 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
978 Pkg
!= pkgsets
[0].end(); ++Pkg
)
979 Show
[Pkg
->ID
] = ToShow
;
980 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
981 Pkg
!= pkgsets
[1].end(); ++Pkg
)
983 Show
[Pkg
->ID
] = ToShow
;
984 Flags
[Pkg
->ID
] |= ForceNR
;
988 printf("digraph packages {\n");
989 printf("concentrate=true;\n");
990 printf("size=\"30,40\";\n");
996 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
998 // See we need to show this package
999 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1003 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1005 // Pure Provides and missing packages have no deps!
1006 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1007 Show
[Pkg
->ID
] = Done
;
1009 Show
[Pkg
->ID
] = DoneNR
;
1012 Show
[Pkg
->ID
] = Done
;
1015 // No deps to map out
1016 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1019 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1020 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
1022 // See if anything can meet this dep
1023 // Walk along the actual package providing versions
1025 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1026 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1027 I
.end() == false && Hit
== false; I
++)
1029 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1033 // Follow all provides
1034 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1035 I
.end() == false && Hit
== false; I
++)
1037 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1041 // Only graph critical deps
1042 if (D
.IsCritical() == true)
1044 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1046 // Colour the node for recursion
1047 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1049 /* If a conflicts does not meet anything in the database
1050 then show the relation but do not recurse */
1052 (D
->Type
== pkgCache::Dep::Conflicts
||
1053 D
->Type
== pkgCache::Dep::Obsoletes
))
1055 if (Show
[D
.TargetPkg()->ID
] == None
&&
1056 Show
[D
.TargetPkg()->ID
] != ToShow
)
1057 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1061 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1062 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1064 Show
[D
.TargetPkg()->ID
] = ToShow
;
1071 case pkgCache::Dep::Conflicts
:
1072 case pkgCache::Dep::Obsoletes
:
1073 printf("[color=springgreen];\n");
1076 case pkgCache::Dep::PreDepends
:
1077 printf("[color=blue];\n");
1089 /* Draw the box colours after the fact since we can not tell what colour
1090 they should be until everything is finished drawing */
1091 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1093 if (Show
[Pkg
->ID
] < DoneNR
)
1096 // Orange box for early recursion stoppage
1097 if (Show
[Pkg
->ID
] == DoneNR
)
1098 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1099 Shapes
[ShapeMap
[Pkg
->ID
]]);
1101 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1102 Shapes
[ShapeMap
[Pkg
->ID
]]);
1109 // DoAdd - Perform an adding operation /*{{{*/
1110 // ---------------------------------------------------------------------
1112 bool DoAdd(CommandLine
&CmdL
)
1114 return _error
->Error("Unimplemented");
1116 // Make sure there is at least one argument
1117 if (CmdL
.FileSize() <= 1)
1118 return _error
->Error("You must give at least one file name");
1121 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
1122 if (_error
->PendingError() == true)
1125 DynamicMMap
Map(CacheF
,MMap::Public
);
1126 if (_error
->PendingError() == true)
1129 OpTextProgress
Progress(*_config
);
1130 pkgCacheGenerator
Gen(Map
,Progress
);
1131 if (_error
->PendingError() == true)
1134 unsigned long Length
= CmdL
.FileSize() - 1;
1135 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1137 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
1138 Progress
.SubProgress(Length
);
1141 FileFd
TagF(*I
,FileFd::ReadOnly
);
1142 debListParser
Parser(TagF
);
1143 if (_error
->PendingError() == true)
1144 return _error
->Error("Problem opening %s",*I
);
1146 if (Gen
.SelectFile(*I
,"") == false)
1147 return _error
->Error("Problem with SelectFile");
1149 if (Gen
.MergeList(Parser
) == false)
1150 return _error
->Error("Problem with MergeList");
1154 GCache
= &Gen
.GetCache();
1161 // DisplayRecord - Displays the complete record for the package /*{{{*/
1162 // ---------------------------------------------------------------------
1163 /* This displays the package record from the proper package index file.
1164 It is not used by DumpAvail for performance reasons. */
1165 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1167 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1168 if (unlikely(Cache
== NULL
))
1171 // Find an appropriate file
1172 pkgCache::VerFileIterator Vf
= V
.FileList();
1173 for (; Vf
.end() == false; Vf
++)
1174 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1176 if (Vf
.end() == true)
1179 // Check and load the package list file
1180 pkgCache::PkgFileIterator I
= Vf
.File();
1181 if (I
.IsOk() == false)
1182 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1185 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnlyGzip
) == false)
1189 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1190 Buffer
[V
.FileList()->Size
] = '\n';
1191 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1192 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1198 // Get a pointer to start of Description field
1199 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1201 // Write all but Description
1202 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1208 // Show the right description
1209 pkgRecords
Recs(*Cache
);
1210 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1211 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1212 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1214 // Find the first field after the description (if there is any)
1215 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1217 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1219 // write the rest of the buffer
1220 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1221 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1230 // write a final newline (after the description)
1240 pkgCache::DescFile
*Df
;
1244 // Search - Perform a search /*{{{*/
1245 // ---------------------------------------------------------------------
1246 /* This searches the package names and package descriptions for a pattern */
1247 bool Search(CommandLine
&CmdL
)
1249 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1250 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1251 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1253 pkgCacheFile CacheFile
;
1254 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1255 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1256 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1259 // Make sure there is at least one argument
1260 if (NumPatterns
< 1)
1261 return _error
->Error(_("You must give at least one search pattern"));
1263 // Compile the regex pattern
1264 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1265 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1266 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1268 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1272 regfree(&Patterns
[I
]);
1273 return _error
->Error("Regex compilation error");
1277 if (_error
->PendingError() == true)
1279 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1280 regfree(&Patterns
[I
]);
1284 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1285 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1287 // Map versions that we want to write out onto the VerList array.
1288 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1290 if (DFList
[G
->ID
].NameMatch
== true)
1293 DFList
[G
->ID
].NameMatch
= true;
1294 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1296 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1298 DFList
[G
->ID
].NameMatch
= false;
1302 // Doing names only, drop any that dont match..
1303 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1306 // Find the proper version to use
1307 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1308 if (P
.end() == true)
1310 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1311 if (V
.end() == false)
1312 DFList
[G
->ID
].Df
= V
.DescriptionList().FileList();
1314 if (DFList
[G
->ID
].NameMatch
== false)
1317 // Include all the packages that provide matching names too
1318 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
1320 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1321 if (V
.end() == true)
1324 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1325 DFList
[id
].Df
= V
.DescriptionList().FileList();
1326 DFList
[id
].NameMatch
= true;
1330 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1332 // Create the text record parser
1333 pkgRecords
Recs(*Cache
);
1334 // Iterate over all the version records and check them
1335 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1337 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1339 if (J
->NameMatch
== false && NamesOnly
== false)
1341 string
const LongDesc
= P
.LongDesc();
1342 J
->NameMatch
= true;
1343 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1345 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1347 J
->NameMatch
= false;
1352 if (J
->NameMatch
== true)
1354 if (ShowFull
== true)
1358 P
.GetRec(Start
,End
);
1359 fwrite(Start
,End
-Start
,1,stdout
);
1363 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1368 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1369 regfree(&Patterns
[I
]);
1371 return _error
->Error("Write to stdout failed");
1376 /* show automatically installed packages (sorted) */
1377 bool ShowAuto(CommandLine
&CmdL
)
1379 pkgCacheFile CacheFile
;
1380 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1381 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1382 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1385 std::vector
<string
> packages
;
1386 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1388 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
1389 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1390 packages
.push_back(P
.Name());
1392 std::sort(packages
.begin(), packages
.end());
1394 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); I
++)
1400 // ShowPackage - Dump the package record to the screen /*{{{*/
1401 // ---------------------------------------------------------------------
1403 bool ShowPackage(CommandLine
&CmdL
)
1405 pkgCacheFile CacheFile
;
1406 APT::VersionSet::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1407 APT::VersionSet::ALL
: APT::VersionSet::CANDIDATE
;
1408 APT::VersionSet
const verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
);
1409 for (APT::VersionSet::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1410 if (DisplayRecord(CacheFile
, Ver
) == false)
1413 if (verset
.empty() == false)
1415 return _error
->Error(_("No packages found"));
1418 // ShowPkgNames - Show package names /*{{{*/
1419 // ---------------------------------------------------------------------
1420 /* This does a prefix match on the first argument */
1421 bool ShowPkgNames(CommandLine
&CmdL
)
1423 pkgCacheFile CacheFile
;
1424 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1426 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1427 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1429 if (CmdL
.FileList
[1] != 0)
1431 for (;I
.end() != true; I
++)
1433 if (All
== false && I
->FirstPackage
== 0)
1435 if (I
.FindPkg("any")->VersionList
== 0)
1437 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1438 cout
<< I
.Name() << endl
;
1445 for (;I
.end() != true; I
++)
1447 if (All
== false && I
->FirstPackage
== 0)
1449 if (I
.FindPkg("any")->VersionList
== 0)
1451 cout
<< I
.Name() << endl
;
1457 // ShowSrcPackage - Show source package records /*{{{*/
1458 // ---------------------------------------------------------------------
1460 bool ShowSrcPackage(CommandLine
&CmdL
)
1462 pkgCacheFile CacheFile
;
1463 pkgSourceList
*List
= CacheFile
.GetSourceList();
1464 if (unlikely(List
== NULL
))
1467 // Create the text record parsers
1468 pkgSrcRecords
SrcRecs(*List
);
1469 if (_error
->PendingError() == true)
1473 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1477 pkgSrcRecords::Parser
*Parse
;
1478 unsigned found_this
= 0;
1479 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1480 cout
<< Parse
->AsStr() << endl
;;
1484 if (found_this
== 0) {
1485 _error
->Warning(_("Unable to locate package %s"),*I
);
1491 return _error
->Error(_("No packages found"));
1494 // Policy - Show the results of the preferences file /*{{{*/
1495 // ---------------------------------------------------------------------
1497 bool Policy(CommandLine
&CmdL
)
1499 pkgCacheFile CacheFile
;
1500 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1501 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1502 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1503 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1506 /* Should the MultiArchKiller be run to see which pseudo packages for an
1507 arch all package are currently installed? Activating it gives a speed
1508 penality for no real gain beside enhanced debugging, so in general no. */
1509 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1510 CacheFile
.GetDepCache();
1512 // Print out all of the package files
1513 if (CmdL
.FileList
[1] == 0)
1515 cout
<< _("Package files:") << endl
;
1516 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
1518 // Locate the associated index files so we can derive a description
1520 if (SrcList
->FindIndex(F
,Indx
) == false &&
1521 _system
->FindIndex(F
,Indx
) == false)
1522 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1525 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1527 // Print the reference information for the package
1528 string Str
= F
.RelStr();
1529 if (Str
.empty() == false)
1530 printf(" release %s\n",F
.RelStr().c_str());
1531 if (F
.Site() != 0 && F
.Site()[0] != 0)
1532 printf(" origin %s\n",F
.Site());
1535 // Show any packages have explicit pins
1536 cout
<< _("Pinned packages:") << endl
;
1537 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1538 for (;I
.end() != true; I
++)
1540 if (Plcy
->GetPriority(I
) == 0)
1543 // Print the package name and the version we are forcing to
1544 cout
<< " " << I
.FullName(true) << " -> ";
1546 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1547 if (V
.end() == true)
1548 cout
<< _("(not found)") << endl
;
1550 cout
<< V
.VerStr() << endl
;
1556 string
const myArch
= _config
->Find("APT::Architecture");
1557 char const * const msgInstalled
= _(" Installed: ");
1558 char const * const msgCandidate
= _(" Candidate: ");
1559 short const InstalledLessCandidate
=
1560 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1561 short const deepInstalled
=
1562 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1563 short const deepCandidate
=
1564 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1566 // Print out detailed information for each package
1567 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1568 for (APT::PackageSet::const_iterator I
= pkgset
.begin(); I
!= pkgset
.end(); ++I
)
1570 pkgCache::PkgIterator Pkg
= I
.Group().FindPkg("any");
1572 for (; Pkg
.end() != true; Pkg
= I
.Group().NextPkg(Pkg
)) {
1573 if (strcmp(Pkg
.Arch(),"all") == 0)
1576 cout
<< Pkg
.FullName(true) << ":" << endl
;
1578 // Installed version
1579 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1580 if (Pkg
->CurrentVer
== 0)
1581 cout
<< _("(none)") << endl
;
1583 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1585 // Candidate Version
1586 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1587 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1588 if (V
.end() == true)
1589 cout
<< _("(none)") << endl
;
1591 cout
<< V
.VerStr() << endl
;
1594 if (Plcy
->GetPriority(Pkg
) != 0)
1596 cout
<< _(" Package pin: ");
1597 V
= Plcy
->GetMatch(Pkg
);
1598 if (V
.end() == true)
1599 cout
<< _("(not found)") << endl
;
1601 cout
<< V
.VerStr() << endl
;
1604 // Show the priority tables
1605 cout
<< _(" Version table:") << endl
;
1606 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1608 if (Pkg
.CurrentVer() == V
)
1609 cout
<< " *** " << V
.VerStr();
1611 cout
<< " " << V
.VerStr();
1612 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1613 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1615 // Locate the associated index files so we can derive a description
1617 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1618 _system
->FindIndex(VF
.File(),Indx
) == false)
1619 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1620 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1621 Indx
->Describe(true).c_str());
1630 // Madison - Look a bit like katie's madison /*{{{*/
1631 // ---------------------------------------------------------------------
1633 bool Madison(CommandLine
&CmdL
)
1635 pkgCacheFile CacheFile
;
1636 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1641 // Create the src text record parsers and ignore errors about missing
1642 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1643 pkgSrcRecords
SrcRecs(*SrcList
);
1644 if (_error
->PendingError() == true)
1647 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1648 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1650 if (Pkg
.end() == false)
1652 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; V
++)
1654 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1656 // This might be nice, but wouldn't uniquely identify the source -mdz
1657 // if (VF.File().Archive() != 0)
1659 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1660 // << VF.File().Archive() << endl;
1663 // Locate the associated index files so we can derive a description
1664 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); S
++)
1666 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1667 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1668 IF
!= Indexes
->end(); IF
++)
1670 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1672 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1673 << (*IF
)->Describe(true) << endl
;
1683 pkgSrcRecords::Parser
*SrcParser
;
1684 while ((SrcParser
= SrcRecs
.Find(Pkg
.Name(),false)) != 0)
1686 // Maybe support Release info here too eventually
1687 cout
<< setw(10) << SrcParser
->Package() << " | "
1688 << setw(10) << SrcParser
->Version() << " | "
1689 << SrcParser
->Index().Describe(true) << endl
;
1696 // GenCaches - Call the main cache generator /*{{{*/
1697 // ---------------------------------------------------------------------
1699 bool GenCaches(CommandLine
&Cmd
)
1701 OpTextProgress
Progress(*_config
);
1703 pkgCacheFile CacheFile
;
1704 return CacheFile
.BuildCaches(&Progress
, true);
1707 // ShowHelp - Show a help screen /*{{{*/
1708 // ---------------------------------------------------------------------
1710 bool ShowHelp(CommandLine
&Cmd
)
1712 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1713 COMMON_ARCH
,__DATE__
,__TIME__
);
1715 if (_config
->FindB("version") == true)
1719 _("Usage: apt-cache [options] command\n"
1720 " apt-cache [options] add file1 [file2 ...]\n"
1721 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1722 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1724 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1725 "cache files, and query information from them\n"
1728 " add - Add a package file to the source cache\n"
1729 " gencaches - Build both the package and source cache\n"
1730 " showpkg - Show some general information for a single package\n"
1731 " showsrc - Show source records\n"
1732 " stats - Show some basic statistics\n"
1733 " dump - Show the entire file in a terse form\n"
1734 " dumpavail - Print an available file to stdout\n"
1735 " unmet - Show unmet dependencies\n"
1736 " search - Search the package list for a regex pattern\n"
1737 " show - Show a readable record for the package\n"
1738 " showauto - Display a list of automatically installed packages\n"
1739 " depends - Show raw dependency information for a package\n"
1740 " rdepends - Show reverse dependency information for a package\n"
1741 " pkgnames - List the names of all packages in the system\n"
1742 " dotty - Generate package graphs for GraphViz\n"
1743 " xvcg - Generate package graphs for xvcg\n"
1744 " policy - Show policy settings\n"
1747 " -h This help text.\n"
1748 " -p=? The package cache.\n"
1749 " -s=? The source cache.\n"
1750 " -q Disable progress indicator.\n"
1751 " -i Show only important deps for the unmet command.\n"
1752 " -c=? Read this configuration file\n"
1753 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1754 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1758 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1759 // ---------------------------------------------------------------------
1761 void CacheInitialize()
1763 _config
->Set("quiet",0);
1764 _config
->Set("help",false);
1767 int main(int argc
,const char *argv
[]) /*{{{*/
1769 CommandLine::Args Args
[] = {
1770 {'h',"help","help",0},
1771 {'v',"version","version",0},
1772 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1773 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1774 {'q',"quiet","quiet",CommandLine::IntLevel
},
1775 {'i',"important","APT::Cache::Important",0},
1776 {'f',"full","APT::Cache::ShowFull",0},
1777 {'g',"generate","APT::Cache::Generate",0},
1778 {'a',"all-versions","APT::Cache::AllVersions",0},
1779 {'n',"names-only","APT::Cache::NamesOnly",0},
1780 {0,"all-names","APT::Cache::AllNames",0},
1781 {0,"recurse","APT::Cache::RecurseDepends",0},
1782 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1783 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1784 {'c',"config-file",0,CommandLine::ConfigFile
},
1785 {'o',"option",0,CommandLine::ArbItem
},
1786 {0,"installed","APT::Cache::Installed",0},
1787 {0,"pre-depends","APT::Cache::ShowPreDepends",0},
1788 {0,"depends","APT::Cache::ShowDepends",0},
1789 {0,"recommends","APT::Cache::ShowRecommends",0},
1790 {0,"suggests","APT::Cache::ShowSuggests",0},
1791 {0,"replaces","APT::Cache::ShowReplaces",0},
1792 {0,"breaks","APT::Cache::ShowBreaks",0},
1793 {0,"conflicts","APT::Cache::ShowConflicts",0},
1794 {0,"enhances","APT::Cache::ShowEnhances",0},
1796 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1798 {"gencaches",&GenCaches
},
1799 {"showsrc",&ShowSrcPackage
},
1801 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1804 {"dumpavail",&DumpAvail
},
1807 {"depends",&Depends
},
1808 {"rdepends",&RDepends
},
1811 {"show",&ShowPackage
},
1812 {"pkgnames",&ShowPkgNames
},
1813 {"showauto",&ShowAuto
},
1815 {"madison",&Madison
},
1820 // Set up gettext support
1821 setlocale(LC_ALL
,"");
1822 textdomain(PACKAGE
);
1824 // Parse the command line and initialize the package library
1825 CommandLine
CmdL(Args
,_config
);
1826 if (pkgInitConfig(*_config
) == false ||
1827 CmdL
.Parse(argc
,argv
) == false ||
1828 pkgInitSystem(*_config
,_system
) == false)
1830 _error
->DumpErrors();
1834 // See if the help should be shown
1835 if (_config
->FindB("help") == true ||
1836 CmdL
.FileSize() == 0)
1842 // Deal with stdout not being a tty
1843 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1844 _config
->Set("quiet","1");
1846 if (_config
->Exists("APT::Cache::Generate") == true)
1847 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1849 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1850 CmdL
.DispatchArg(CmdsB
);
1852 // Print any errors or warnings found during parsing
1853 bool const Errors
= _error
->PendingError();
1854 if (_config
->FindI("quiet",0) > 0)
1855 _error
->DumpErrors();
1857 _error
->DumpErrors(GlobalError::DEBUG
);
1858 return Errors
== true ? 100 : 0;