]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
557996693456167fbaf109aad217ceddec227790
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/init.h>
21 #include <apt-pkg/progress.h>
22 #include <apt-pkg/sourcelist.h>
23 #include <apt-pkg/cmndline.h>
24 #include <apt-pkg/strutl.h>
25 #include <apt-pkg/pkgrecords.h>
26 #include <apt-pkg/srcrecords.h>
27 #include <apt-pkg/version.h>
28 #include <apt-pkg/policy.h>
29 #include <apt-pkg/tagfile.h>
30 #include <apt-pkg/algorithms.h>
31 #include <apt-pkg/sptr.h>
50 // LocalitySort - Sort a version list by package file locality /*{{{*/
51 // ---------------------------------------------------------------------
53 int LocalityCompare(const void *a
, const void *b
)
55 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
56 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
65 if (A
->File
== B
->File
)
66 return A
->Offset
- B
->Offset
;
67 return A
->File
- B
->File
;
70 void LocalitySort(pkgCache::VerFile
**begin
,
71 unsigned long Count
,size_t Size
)
73 qsort(begin
,Count
,Size
,LocalityCompare
);
76 void LocalitySort(pkgCache::DescFile
**begin
,
77 unsigned long Count
,size_t Size
)
79 qsort(begin
,Count
,Size
,LocalityCompare
);
82 // UnMet - Show unmet dependencies /*{{{*/
83 // ---------------------------------------------------------------------
85 bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const &Important
)
88 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
91 pkgCache::DepIterator Start
;
92 pkgCache::DepIterator End
;
95 // Important deps only
96 if (Important
== true)
97 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
98 End
->Type
!= pkgCache::Dep::Depends
)
101 // Skip conflicts and replaces
102 if (End
->Type
== pkgCache::Dep::DpkgBreaks
||
103 End
->Type
== pkgCache::Dep::Replaces
||
104 End
->Type
== pkgCache::Dep::Conflicts
)
107 // Verify the or group
109 pkgCache::DepIterator RealStart
= Start
;
112 // See if this dep is Ok
113 pkgCache::Version
**VList
= Start
.AllTargets();
134 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
135 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
138 // Print out the dep type
139 cout
<< " " << End
.DepType() << ": ";
145 cout
<< Start
.TargetPkg().FullName(true);
146 if (Start
.TargetVer() != 0)
147 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
160 bool UnMet(CommandLine
&CmdL
)
162 bool const Important
= _config
->FindB("APT::Cache::Important",false);
164 pkgCacheFile CacheFile
;
165 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
168 if (CmdL
.FileSize() <= 1)
170 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; P
++)
171 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
172 if (ShowUnMet(V
, Important
) == false)
177 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
178 for (APT::VersionSet::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
179 if (ShowUnMet(V
, Important
) == false)
185 // DumpPackage - Show a dump of a package record /*{{{*/
186 // ---------------------------------------------------------------------
188 bool DumpPackage(CommandLine
&CmdL
)
190 pkgCacheFile CacheFile
;
191 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
193 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
195 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
196 cout
<< "Versions: " << endl
;
197 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
199 cout
<< Cur
.VerStr();
200 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
201 cout
<< " (" << Vf
.File().FileName() << ")";
203 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; D
++)
205 cout
<< " Description Language: " << D
.LanguageCode() << endl
206 << " File: " << D
.FileList().File().FileName() << endl
207 << " MD5: " << D
.md5() << endl
;
214 cout
<< "Reverse Depends: " << endl
;
215 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
217 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
219 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
224 cout
<< "Dependencies: " << endl
;
225 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
227 cout
<< Cur
.VerStr() << " - ";
228 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
229 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
233 cout
<< "Provides: " << endl
;
234 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
236 cout
<< Cur
.VerStr() << " - ";
237 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
238 cout
<< Prv
.ParentPkg().FullName(true) << " ";
241 cout
<< "Reverse Provides: " << endl
;
242 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
243 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
249 // Stats - Dump some nice statistics /*{{{*/
250 // ---------------------------------------------------------------------
252 bool Stats(CommandLine
&Cmd
)
254 pkgCacheFile CacheFile
;
255 pkgCache
*Cache
= CacheFile
.GetPkgCache();
256 if (unlikely(Cache
== NULL
))
259 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
260 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
261 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
262 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
269 pkgCache::PkgIterator I
= Cache
->PkgBegin();
270 for (;I
.end() != true; I
++)
272 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
278 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
284 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
287 if (I
.ProvidesList()->NextProvides
== 0)
295 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
301 cout
<< _(" Normal packages: ") << Normal
<< endl
;
302 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
303 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
304 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
305 cout
<< _(" Missing: ") << Missing
<< endl
;
307 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
308 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
309 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
310 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
311 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
312 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
314 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
315 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
316 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
317 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
318 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
319 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
322 unsigned long Size
= 0;
323 unsigned long Count
= 0;
324 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
325 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
328 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
330 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
332 unsigned long DepVerSize
= 0;
333 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
335 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
337 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
340 DepVerSize
+= strlen(D
.TargetVer()) + 1;
344 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
346 unsigned long Slack
= 0;
347 for (int I
= 0; I
!= 7; I
++)
348 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
349 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
351 unsigned long Total
= 0;
352 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
353 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
354 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
355 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
356 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
357 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
362 // Dump - show everything /*{{{*/
363 // ---------------------------------------------------------------------
364 /* This is worthless except fer debugging things */
365 bool Dump(CommandLine
&Cmd
)
367 pkgCacheFile CacheFile
;
368 pkgCache
*Cache
= CacheFile
.GetPkgCache();
369 if (unlikely(Cache
== NULL
))
372 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
374 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
376 cout
<< "Package: " << P
.FullName(true) << endl
;
377 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
379 cout
<< " Version: " << V
.VerStr() << endl
;
380 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
381 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
382 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
383 DeNull(D
.TargetVer()) << endl
;
384 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; D
++)
386 cout
<< " Description Language: " << D
.LanguageCode() << endl
387 << " File: " << D
.FileList().File().FileName() << endl
388 << " MD5: " << D
.md5() << endl
;
393 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
395 cout
<< "File: " << F
.FileName() << endl
;
396 cout
<< " Type: " << F
.IndexType() << endl
;
397 cout
<< " Size: " << F
->Size
<< endl
;
398 cout
<< " ID: " << F
->ID
<< endl
;
399 cout
<< " Flags: " << F
->Flags
<< endl
;
400 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
401 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
402 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
403 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
404 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
405 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
406 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
407 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
413 // DumpAvail - Print out the available list /*{{{*/
414 // ---------------------------------------------------------------------
415 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
416 make this run really fast, perhaps I went a little overboard.. */
417 bool DumpAvail(CommandLine
&Cmd
)
419 pkgCacheFile CacheFile
;
420 pkgCache
*Cache
= CacheFile
.GetPkgCache();
421 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
424 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
425 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
426 memset(VFList
,0,sizeof(*VFList
)*Count
);
428 // Map versions that we want to write out onto the VerList array.
429 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
431 if (P
->VersionList
== 0)
434 /* Find the proper version to use. If the policy says there are no
435 possible selections we return the installed version, if available..
436 This prevents dselect from making it obsolete. */
437 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
440 if (P
->CurrentVer
== 0)
445 pkgCache::VerFileIterator VF
= V
.FileList();
446 for (; VF
.end() == false ; VF
++)
447 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
450 /* Okay, here we have a bit of a problem.. The policy has selected the
451 currently installed package - however it only exists in the
452 status file.. We need to write out something or dselect will mark
453 the package as obsolete! Thus we emit the status file entry, but
454 below we remove the status line to make it valid for the
455 available file. However! We only do this if their do exist *any*
456 non-source versions of the package - that way the dselect obsolete
457 handling works OK. */
458 if (VF
.end() == true)
460 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
462 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
464 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
471 if (VF
.end() == false)
479 LocalitySort(VFList
,Count
,sizeof(*VFList
));
481 // Iterate over all the package files and write them out.
482 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
483 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
485 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
486 if (File
.IsOk() == false)
488 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
492 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
493 if (_error
->PendingError() == true)
496 /* Write all of the records from this package file, since we
497 already did locality sorting we can now just seek through the
498 file in read order. We apply 1 more optimization here, since often
499 there will be < 1 byte gaps between records (for the \n) we read that
500 into the next buffer and offset a bit.. */
501 unsigned long Pos
= 0;
504 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
507 const pkgCache::VerFile
&VF
= **J
;
509 // Read the record and then write it out again.
510 unsigned long Jitter
= VF
.Offset
- Pos
;
513 if (PkgF
.Seek(VF
.Offset
) == false)
518 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
520 Buffer
[VF
.Size
+ Jitter
] = '\n';
523 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
526 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
527 const char *Zero
= 0;
528 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
529 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
531 _error
->Error("Internal Error, Unable to parse a package record");
538 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
542 Pos
= VF
.Offset
+ VF
.Size
;
546 if (_error
->PendingError() == true)
552 return !_error
->PendingError();
555 // Depends - Print out a dependency tree /*{{{*/
556 // ---------------------------------------------------------------------
558 bool Depends(CommandLine
&CmdL
)
560 pkgCacheFile CacheFile
;
561 pkgCache
*Cache
= CacheFile
.GetPkgCache();
562 if (unlikely(Cache
== NULL
))
565 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
566 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
568 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
569 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
570 Colours
[Pkg
->ID
] = 1;
572 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
573 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
574 bool const Important
= _config
->FindB("APT::Cache::Important", false);
575 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType",true);
576 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
577 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
578 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
579 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
580 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
581 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
582 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
583 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
587 DidSomething
= false;
588 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
590 if (Colours
[Pkg
->ID
] != 1)
592 Colours
[Pkg
->ID
] = 2;
595 pkgCache::VerIterator Ver
= Pkg
.VersionList();
596 if (Ver
.end() == true)
598 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
602 cout
<< Pkg
.FullName(true) << endl
;
604 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
607 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
608 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
609 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
610 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
611 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
612 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
613 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
614 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
617 pkgCache::PkgIterator Trg
= D
.TargetPkg();
619 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
622 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
628 if (ShowDepType
== true)
629 cout
<< D
.DepType() << ": ";
630 if (Trg
->VersionList
== 0)
631 cout
<< "<" << Trg
.FullName(true) << ">" << endl
;
633 cout
<< Trg
.FullName(true) << endl
;
636 Colours
[D
.TargetPkg()->ID
]++;
640 // Display all solutions
641 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
642 pkgPrioSortList(*Cache
,List
);
643 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
645 pkgCache::VerIterator
V(*Cache
,*I
);
646 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
647 V
->ParentPkg
== D
->Package
)
649 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
652 Colours
[D
.ParentPkg()->ID
]++;
657 while (DidSomething
== true);
662 // RDepends - Print out a reverse dependency tree - mbc /*{{{*/
663 // ---------------------------------------------------------------------
665 bool RDepends(CommandLine
&CmdL
)
667 pkgCacheFile CacheFile
;
668 pkgCache
*Cache
= CacheFile
.GetPkgCache();
669 if (unlikely(Cache
== NULL
))
672 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
673 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
675 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
676 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
677 Colours
[Pkg
->ID
] = 1;
679 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
680 bool const Installed
= _config
->FindB("APT::Cache::Installed",false);
681 bool const Important
= _config
->FindB("APT::Cache::Important", false);
682 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType",false);
683 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
684 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
685 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
686 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
687 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
688 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
689 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
690 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
694 DidSomething
= false;
695 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
697 if (Colours
[Pkg
->ID
] != 1)
699 Colours
[Pkg
->ID
] = 2;
702 pkgCache::VerIterator Ver
= Pkg
.VersionList();
703 if (Ver
.end() == true)
705 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
709 cout
<< Pkg
.FullName(true) << endl
;
711 cout
<< "Reverse Depends:" << endl
;
712 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() == false; D
++)
715 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
716 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
717 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
718 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
719 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
720 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
721 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
722 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
726 pkgCache::PkgIterator Trg
= D
.ParentPkg();
728 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
731 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
736 if (ShowDepType
== true)
737 cout
<< D
.DepType() << ": ";
738 if (Trg
->VersionList
== 0)
739 cout
<< "<" << Trg
.FullName(true) << ">" << endl
;
741 cout
<< Trg
.FullName(true) << endl
;
744 Colours
[D
.ParentPkg()->ID
]++;
748 // Display all solutions
749 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
750 pkgPrioSortList(*Cache
,List
);
751 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
753 pkgCache::VerIterator
V(*Cache
,*I
);
754 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
755 V
->ParentPkg
== D
->Package
)
757 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
760 Colours
[D
.ParentPkg()->ID
]++;
765 while (DidSomething
== true);
770 // xvcg - Generate a graph for xvcg /*{{{*/
771 // ---------------------------------------------------------------------
772 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
774 bool XVcg(CommandLine
&CmdL
)
776 pkgCacheFile CacheFile
;
777 pkgCache
*Cache
= CacheFile
.GetPkgCache();
778 if (unlikely(Cache
== NULL
))
781 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
783 /* Normal packages are boxes
784 Pure Provides are triangles
786 rhomb are missing packages*/
787 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
789 /* Initialize the list of packages to show.
791 2 = To Show no recurse
792 3 = Emitted no recurse
795 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
796 enum TheFlags
{ForceNR
=(1<<0)};
797 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
798 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
799 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
801 // Show everything if no arguments given
802 if (CmdL
.FileList
[1] == 0)
803 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
806 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
808 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
811 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
813 if (Pkg
->VersionList
== 0)
816 if (Pkg
->ProvidesList
== 0)
817 ShapeMap
[Pkg
->ID
] = 0;
819 ShapeMap
[Pkg
->ID
] = 1;
824 if (Pkg
->ProvidesList
== 0)
825 ShapeMap
[Pkg
->ID
] = 2;
827 ShapeMap
[Pkg
->ID
] = 3;
831 // Load the list of packages from the command line into the show list
832 std::list
<APT::PackageSet::Modifier
> mods
;
833 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
834 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
835 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
836 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
838 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
839 Pkg
!= pkgsets
[0].end(); ++Pkg
)
840 Show
[Pkg
->ID
] = ToShow
;
841 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
842 Pkg
!= pkgsets
[1].end(); ++Pkg
)
844 Show
[Pkg
->ID
] = ToShow
;
845 Flags
[Pkg
->ID
] |= ForceNR
;
849 cout
<< "graph: { title: \"packages\"" << endl
<<
850 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
851 "layout_downfactor: 8" << endl
;
857 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
859 // See we need to show this package
860 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
863 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
866 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
868 // Pure Provides and missing packages have no deps!
869 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
870 Show
[Pkg
->ID
] = Done
;
872 Show
[Pkg
->ID
] = DoneNR
;
875 Show
[Pkg
->ID
] = Done
;
878 // No deps to map out
879 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
882 pkgCache::VerIterator Ver
= Pkg
.VersionList();
883 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
885 // See if anything can meet this dep
886 // Walk along the actual package providing versions
888 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
889 for (pkgCache::VerIterator I
= DPkg
.VersionList();
890 I
.end() == false && Hit
== false; I
++)
892 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
896 // Follow all provides
897 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
898 I
.end() == false && Hit
== false; I
++)
900 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
905 // Only graph critical deps
906 if (D
.IsCritical() == true)
908 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
910 // Colour the node for recursion
911 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
913 /* If a conflicts does not meet anything in the database
914 then show the relation but do not recurse */
916 (D
->Type
== pkgCache::Dep::Conflicts
||
917 D
->Type
== pkgCache::Dep::DpkgBreaks
||
918 D
->Type
== pkgCache::Dep::Obsoletes
))
920 if (Show
[D
.TargetPkg()->ID
] == None
&&
921 Show
[D
.TargetPkg()->ID
] != ToShow
)
922 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
926 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
927 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
929 Show
[D
.TargetPkg()->ID
] = ToShow
;
936 case pkgCache::Dep::Conflicts
:
937 printf("label: \"conflicts\" color: lightgreen }\n");
939 case pkgCache::Dep::DpkgBreaks
:
940 printf("label: \"breaks\" color: lightgreen }\n");
942 case pkgCache::Dep::Obsoletes
:
943 printf("label: \"obsoletes\" color: lightgreen }\n");
946 case pkgCache::Dep::PreDepends
:
947 printf("label: \"predepends\" color: blue }\n");
959 /* Draw the box colours after the fact since we can not tell what colour
960 they should be until everything is finished drawing */
961 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
963 if (Show
[Pkg
->ID
] < DoneNR
)
966 if (Show
[Pkg
->ID
] == DoneNR
)
967 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
968 Shapes
[ShapeMap
[Pkg
->ID
]]);
970 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
971 Shapes
[ShapeMap
[Pkg
->ID
]]);
983 // Dotty - Generate a graph for Dotty /*{{{*/
984 // ---------------------------------------------------------------------
985 /* Dotty is the graphvis program for generating graphs. It is a fairly
986 simple queuing algorithm that just writes dependencies and nodes.
987 http://www.research.att.com/sw/tools/graphviz/ */
988 bool Dotty(CommandLine
&CmdL
)
990 pkgCacheFile CacheFile
;
991 pkgCache
*Cache
= CacheFile
.GetPkgCache();
992 if (unlikely(Cache
== NULL
))
995 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
997 /* Normal packages are boxes
998 Pure Provides are triangles
1000 Hexagons are missing packages*/
1001 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
1003 /* Initialize the list of packages to show.
1005 2 = To Show no recurse
1006 3 = Emitted no recurse
1009 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
1010 enum TheFlags
{ForceNR
=(1<<0)};
1011 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
1012 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
1013 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
1015 // Show everything if no arguments given
1016 if (CmdL
.FileList
[1] == 0)
1017 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1020 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1022 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1025 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1027 if (Pkg
->VersionList
== 0)
1030 if (Pkg
->ProvidesList
== 0)
1031 ShapeMap
[Pkg
->ID
] = 0;
1033 ShapeMap
[Pkg
->ID
] = 1;
1038 if (Pkg
->ProvidesList
== 0)
1039 ShapeMap
[Pkg
->ID
] = 2;
1041 ShapeMap
[Pkg
->ID
] = 3;
1045 // Load the list of packages from the command line into the show list
1046 std::list
<APT::PackageSet::Modifier
> mods
;
1047 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1048 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1049 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1050 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
1052 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1053 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1054 Show
[Pkg
->ID
] = ToShow
;
1055 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1056 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1058 Show
[Pkg
->ID
] = ToShow
;
1059 Flags
[Pkg
->ID
] |= ForceNR
;
1063 printf("digraph packages {\n");
1064 printf("concentrate=true;\n");
1065 printf("size=\"30,40\";\n");
1071 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1073 // See we need to show this package
1074 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1078 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1080 // Pure Provides and missing packages have no deps!
1081 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1082 Show
[Pkg
->ID
] = Done
;
1084 Show
[Pkg
->ID
] = DoneNR
;
1087 Show
[Pkg
->ID
] = Done
;
1090 // No deps to map out
1091 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1094 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1095 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
1097 // See if anything can meet this dep
1098 // Walk along the actual package providing versions
1100 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1101 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1102 I
.end() == false && Hit
== false; I
++)
1104 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1108 // Follow all provides
1109 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1110 I
.end() == false && Hit
== false; I
++)
1112 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1116 // Only graph critical deps
1117 if (D
.IsCritical() == true)
1119 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1121 // Colour the node for recursion
1122 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1124 /* If a conflicts does not meet anything in the database
1125 then show the relation but do not recurse */
1127 (D
->Type
== pkgCache::Dep::Conflicts
||
1128 D
->Type
== pkgCache::Dep::Obsoletes
))
1130 if (Show
[D
.TargetPkg()->ID
] == None
&&
1131 Show
[D
.TargetPkg()->ID
] != ToShow
)
1132 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1136 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1137 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1139 Show
[D
.TargetPkg()->ID
] = ToShow
;
1146 case pkgCache::Dep::Conflicts
:
1147 case pkgCache::Dep::Obsoletes
:
1148 printf("[color=springgreen];\n");
1151 case pkgCache::Dep::PreDepends
:
1152 printf("[color=blue];\n");
1164 /* Draw the box colours after the fact since we can not tell what colour
1165 they should be until everything is finished drawing */
1166 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1168 if (Show
[Pkg
->ID
] < DoneNR
)
1171 // Orange box for early recursion stoppage
1172 if (Show
[Pkg
->ID
] == DoneNR
)
1173 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1174 Shapes
[ShapeMap
[Pkg
->ID
]]);
1176 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1177 Shapes
[ShapeMap
[Pkg
->ID
]]);
1184 // DoAdd - Perform an adding operation /*{{{*/
1185 // ---------------------------------------------------------------------
1187 bool DoAdd(CommandLine
&CmdL
)
1189 return _error
->Error("Unimplemented");
1191 // Make sure there is at least one argument
1192 if (CmdL
.FileSize() <= 1)
1193 return _error
->Error("You must give at least one file name");
1196 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
1197 if (_error
->PendingError() == true)
1200 DynamicMMap
Map(CacheF
,MMap::Public
);
1201 if (_error
->PendingError() == true)
1204 OpTextProgress
Progress(*_config
);
1205 pkgCacheGenerator
Gen(Map
,Progress
);
1206 if (_error
->PendingError() == true)
1209 unsigned long Length
= CmdL
.FileSize() - 1;
1210 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1212 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
1213 Progress
.SubProgress(Length
);
1216 FileFd
TagF(*I
,FileFd::ReadOnly
);
1217 debListParser
Parser(TagF
);
1218 if (_error
->PendingError() == true)
1219 return _error
->Error("Problem opening %s",*I
);
1221 if (Gen
.SelectFile(*I
,"") == false)
1222 return _error
->Error("Problem with SelectFile");
1224 if (Gen
.MergeList(Parser
) == false)
1225 return _error
->Error("Problem with MergeList");
1229 GCache
= &Gen
.GetCache();
1236 // DisplayRecord - Displays the complete record for the package /*{{{*/
1237 // ---------------------------------------------------------------------
1238 /* This displays the package record from the proper package index file.
1239 It is not used by DumpAvail for performance reasons. */
1240 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1242 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1243 if (unlikely(Cache
== NULL
))
1246 // Find an appropriate file
1247 pkgCache::VerFileIterator Vf
= V
.FileList();
1248 for (; Vf
.end() == false; Vf
++)
1249 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1251 if (Vf
.end() == true)
1254 // Check and load the package list file
1255 pkgCache::PkgFileIterator I
= Vf
.File();
1256 if (I
.IsOk() == false)
1257 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1260 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnlyGzip
) == false)
1264 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1265 Buffer
[V
.FileList()->Size
] = '\n';
1266 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1267 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1273 // Get a pointer to start of Description field
1274 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1276 // Write all but Description
1277 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1283 // Show the right description
1284 pkgRecords
Recs(*Cache
);
1285 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1286 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1287 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1289 // Find the first field after the description (if there is any)
1290 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1292 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1294 // write the rest of the buffer
1295 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1296 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1305 // write a final newline (after the description)
1315 pkgCache::DescFile
*Df
;
1319 // Search - Perform a search /*{{{*/
1320 // ---------------------------------------------------------------------
1321 /* This searches the package names and package descriptions for a pattern */
1322 bool Search(CommandLine
&CmdL
)
1324 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1325 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1326 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1328 pkgCacheFile CacheFile
;
1329 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1330 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1331 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1334 // Make sure there is at least one argument
1335 if (NumPatterns
< 1)
1336 return _error
->Error(_("You must give at least one search pattern"));
1338 // Compile the regex pattern
1339 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1340 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1341 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1343 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1347 regfree(&Patterns
[I
]);
1348 return _error
->Error("Regex compilation error");
1352 if (_error
->PendingError() == true)
1354 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1355 regfree(&Patterns
[I
]);
1359 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1360 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1362 // Map versions that we want to write out onto the VerList array.
1363 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1365 if (DFList
[G
->ID
].NameMatch
== true)
1368 DFList
[G
->ID
].NameMatch
= true;
1369 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1371 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1373 DFList
[G
->ID
].NameMatch
= false;
1377 // Doing names only, drop any that dont match..
1378 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1381 // Find the proper version to use
1382 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1383 if (P
.end() == true)
1385 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1386 if (V
.end() == false)
1387 DFList
[G
->ID
].Df
= V
.DescriptionList().FileList();
1389 if (DFList
[G
->ID
].NameMatch
== false)
1392 // Include all the packages that provide matching names too
1393 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
1395 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1396 if (V
.end() == true)
1399 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1400 DFList
[id
].Df
= V
.DescriptionList().FileList();
1401 DFList
[id
].NameMatch
= true;
1405 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1407 // Create the text record parser
1408 pkgRecords
Recs(*Cache
);
1409 // Iterate over all the version records and check them
1410 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1412 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1414 if (J
->NameMatch
== false && NamesOnly
== false)
1416 string
const LongDesc
= P
.LongDesc();
1417 J
->NameMatch
= true;
1418 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1420 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1422 J
->NameMatch
= false;
1427 if (J
->NameMatch
== true)
1429 if (ShowFull
== true)
1433 P
.GetRec(Start
,End
);
1434 fwrite(Start
,End
-Start
,1,stdout
);
1438 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1443 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1444 regfree(&Patterns
[I
]);
1446 return _error
->Error("Write to stdout failed");
1451 /* show automatically installed packages (sorted) */
1452 bool ShowAuto(CommandLine
&CmdL
)
1454 pkgCacheFile CacheFile
;
1455 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1456 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1457 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1460 std::vector
<string
> packages
;
1461 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1463 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
1464 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1465 packages
.push_back(P
.Name());
1467 std::sort(packages
.begin(), packages
.end());
1469 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); I
++)
1475 // ShowPackage - Dump the package record to the screen /*{{{*/
1476 // ---------------------------------------------------------------------
1478 bool ShowPackage(CommandLine
&CmdL
)
1480 pkgCacheFile CacheFile
;
1481 APT::VersionSet::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1482 APT::VersionSet::ALL
: APT::VersionSet::CANDIDATE
;
1483 APT::VersionSet
const verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
);
1484 for (APT::VersionSet::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1485 if (DisplayRecord(CacheFile
, Ver
) == false)
1488 if (verset
.empty() == false)
1490 return _error
->Error(_("No packages found"));
1493 // ShowPkgNames - Show package names /*{{{*/
1494 // ---------------------------------------------------------------------
1495 /* This does a prefix match on the first argument */
1496 bool ShowPkgNames(CommandLine
&CmdL
)
1498 pkgCacheFile CacheFile
;
1499 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1501 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1502 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1504 if (CmdL
.FileList
[1] != 0)
1506 for (;I
.end() != true; I
++)
1508 if (All
== false && I
->FirstPackage
== 0)
1510 if (I
.FindPkg("any")->VersionList
== 0)
1512 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1513 cout
<< I
.Name() << endl
;
1520 for (;I
.end() != true; I
++)
1522 if (All
== false && I
->FirstPackage
== 0)
1524 if (I
.FindPkg("any")->VersionList
== 0)
1526 cout
<< I
.Name() << endl
;
1532 // ShowSrcPackage - Show source package records /*{{{*/
1533 // ---------------------------------------------------------------------
1535 bool ShowSrcPackage(CommandLine
&CmdL
)
1537 pkgCacheFile CacheFile
;
1538 pkgSourceList
*List
= CacheFile
.GetSourceList();
1539 if (unlikely(List
== NULL
))
1542 // Create the text record parsers
1543 pkgSrcRecords
SrcRecs(*List
);
1544 if (_error
->PendingError() == true)
1548 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1552 pkgSrcRecords::Parser
*Parse
;
1553 unsigned found_this
= 0;
1554 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1555 cout
<< Parse
->AsStr() << endl
;;
1559 if (found_this
== 0) {
1560 _error
->Warning(_("Unable to locate package %s"),*I
);
1566 return _error
->Error(_("No packages found"));
1569 // Policy - Show the results of the preferences file /*{{{*/
1570 // ---------------------------------------------------------------------
1572 bool Policy(CommandLine
&CmdL
)
1574 pkgCacheFile CacheFile
;
1575 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1576 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1577 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1578 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1581 /* Should the MultiArchKiller be run to see which pseudo packages for an
1582 arch all package are currently installed? Activating it gives a speed
1583 penality for no real gain beside enhanced debugging, so in general no. */
1584 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1585 CacheFile
.GetDepCache();
1587 // Print out all of the package files
1588 if (CmdL
.FileList
[1] == 0)
1590 cout
<< _("Package files:") << endl
;
1591 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
1593 // Locate the associated index files so we can derive a description
1595 if (SrcList
->FindIndex(F
,Indx
) == false &&
1596 _system
->FindIndex(F
,Indx
) == false)
1597 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1600 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1602 // Print the reference information for the package
1603 string Str
= F
.RelStr();
1604 if (Str
.empty() == false)
1605 printf(" release %s\n",F
.RelStr().c_str());
1606 if (F
.Site() != 0 && F
.Site()[0] != 0)
1607 printf(" origin %s\n",F
.Site());
1610 // Show any packages have explicit pins
1611 cout
<< _("Pinned packages:") << endl
;
1612 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1613 for (;I
.end() != true; I
++)
1615 if (Plcy
->GetPriority(I
) == 0)
1618 // Print the package name and the version we are forcing to
1619 cout
<< " " << I
.FullName(true) << " -> ";
1621 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1622 if (V
.end() == true)
1623 cout
<< _("(not found)") << endl
;
1625 cout
<< V
.VerStr() << endl
;
1631 string
const myArch
= _config
->Find("APT::Architecture");
1632 char const * const msgInstalled
= _(" Installed: ");
1633 char const * const msgCandidate
= _(" Candidate: ");
1634 short const InstalledLessCandidate
=
1635 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1636 short const deepInstalled
=
1637 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1638 short const deepCandidate
=
1639 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1641 // Print out detailed information for each package
1642 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1643 for (APT::PackageSet::const_iterator I
= pkgset
.begin(); I
!= pkgset
.end(); ++I
)
1645 pkgCache::PkgIterator Pkg
= I
.Group().FindPkg("any");
1647 for (; Pkg
.end() != true; Pkg
= I
.Group().NextPkg(Pkg
)) {
1648 if (strcmp(Pkg
.Arch(),"all") == 0)
1651 cout
<< Pkg
.FullName(true) << ":" << endl
;
1653 // Installed version
1654 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1655 if (Pkg
->CurrentVer
== 0)
1656 cout
<< _("(none)") << endl
;
1658 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1660 // Candidate Version
1661 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1662 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1663 if (V
.end() == true)
1664 cout
<< _("(none)") << endl
;
1666 cout
<< V
.VerStr() << endl
;
1669 if (Plcy
->GetPriority(Pkg
) != 0)
1671 cout
<< _(" Package pin: ");
1672 V
= Plcy
->GetMatch(Pkg
);
1673 if (V
.end() == true)
1674 cout
<< _("(not found)") << endl
;
1676 cout
<< V
.VerStr() << endl
;
1679 // Show the priority tables
1680 cout
<< _(" Version table:") << endl
;
1681 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1683 if (Pkg
.CurrentVer() == V
)
1684 cout
<< " *** " << V
.VerStr();
1686 cout
<< " " << V
.VerStr();
1687 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1688 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1690 // Locate the associated index files so we can derive a description
1692 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1693 _system
->FindIndex(VF
.File(),Indx
) == false)
1694 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1695 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1696 Indx
->Describe(true).c_str());
1705 // Madison - Look a bit like katie's madison /*{{{*/
1706 // ---------------------------------------------------------------------
1708 bool Madison(CommandLine
&CmdL
)
1710 pkgCacheFile CacheFile
;
1711 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1716 // Create the src text record parsers and ignore errors about missing
1717 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1718 pkgSrcRecords
SrcRecs(*SrcList
);
1719 if (_error
->PendingError() == true)
1722 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1723 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1725 if (Pkg
.end() == false)
1727 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; V
++)
1729 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1731 // This might be nice, but wouldn't uniquely identify the source -mdz
1732 // if (VF.File().Archive() != 0)
1734 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1735 // << VF.File().Archive() << endl;
1738 // Locate the associated index files so we can derive a description
1739 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); S
++)
1741 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1742 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1743 IF
!= Indexes
->end(); IF
++)
1745 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1747 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1748 << (*IF
)->Describe(true) << endl
;
1758 pkgSrcRecords::Parser
*SrcParser
;
1759 while ((SrcParser
= SrcRecs
.Find(Pkg
.Name(),false)) != 0)
1761 // Maybe support Release info here too eventually
1762 cout
<< setw(10) << SrcParser
->Package() << " | "
1763 << setw(10) << SrcParser
->Version() << " | "
1764 << SrcParser
->Index().Describe(true) << endl
;
1771 // GenCaches - Call the main cache generator /*{{{*/
1772 // ---------------------------------------------------------------------
1774 bool GenCaches(CommandLine
&Cmd
)
1776 OpTextProgress
Progress(*_config
);
1778 pkgCacheFile CacheFile
;
1779 return CacheFile
.BuildCaches(&Progress
, true);
1782 // ShowHelp - Show a help screen /*{{{*/
1783 // ---------------------------------------------------------------------
1785 bool ShowHelp(CommandLine
&Cmd
)
1787 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1788 COMMON_ARCH
,__DATE__
,__TIME__
);
1790 if (_config
->FindB("version") == true)
1794 _("Usage: apt-cache [options] command\n"
1795 " apt-cache [options] add file1 [file2 ...]\n"
1796 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1797 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1799 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1800 "cache files, and query information from them\n"
1803 " add - Add a package file to the source cache\n"
1804 " gencaches - Build both the package and source cache\n"
1805 " showpkg - Show some general information for a single package\n"
1806 " showsrc - Show source records\n"
1807 " stats - Show some basic statistics\n"
1808 " dump - Show the entire file in a terse form\n"
1809 " dumpavail - Print an available file to stdout\n"
1810 " unmet - Show unmet dependencies\n"
1811 " search - Search the package list for a regex pattern\n"
1812 " show - Show a readable record for the package\n"
1813 " showauto - Display a list of automatically installed packages\n"
1814 " depends - Show raw dependency information for a package\n"
1815 " rdepends - Show reverse dependency information for a package\n"
1816 " pkgnames - List the names of all packages in the system\n"
1817 " dotty - Generate package graphs for GraphViz\n"
1818 " xvcg - Generate package graphs for xvcg\n"
1819 " policy - Show policy settings\n"
1822 " -h This help text.\n"
1823 " -p=? The package cache.\n"
1824 " -s=? The source cache.\n"
1825 " -q Disable progress indicator.\n"
1826 " -i Show only important deps for the unmet command.\n"
1827 " -c=? Read this configuration file\n"
1828 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1829 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1833 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1834 // ---------------------------------------------------------------------
1836 void CacheInitialize()
1838 _config
->Set("quiet",0);
1839 _config
->Set("help",false);
1842 int main(int argc
,const char *argv
[]) /*{{{*/
1844 CommandLine::Args Args
[] = {
1845 {'h',"help","help",0},
1846 {'v',"version","version",0},
1847 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1848 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1849 {'q',"quiet","quiet",CommandLine::IntLevel
},
1850 {'i',"important","APT::Cache::Important",0},
1851 {'f',"full","APT::Cache::ShowFull",0},
1852 {'g',"generate","APT::Cache::Generate",0},
1853 {'a',"all-versions","APT::Cache::AllVersions",0},
1854 {'n',"names-only","APT::Cache::NamesOnly",0},
1855 {0,"all-names","APT::Cache::AllNames",0},
1856 {0,"recurse","APT::Cache::RecurseDepends",0},
1857 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1858 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1859 {'c',"config-file",0,CommandLine::ConfigFile
},
1860 {'o',"option",0,CommandLine::ArbItem
},
1861 {0,"installed","APT::Cache::Installed",0},
1862 {0,"pre-depends","APT::Cache::ShowPreDepends",0},
1863 {0,"depends","APT::Cache::ShowDepends",0},
1864 {0,"recommends","APT::Cache::ShowRecommends",0},
1865 {0,"suggests","APT::Cache::ShowSuggests",0},
1866 {0,"replaces","APT::Cache::ShowReplaces",0},
1867 {0,"breaks","APT::Cache::ShowBreaks",0},
1868 {0,"conflicts","APT::Cache::ShowConflicts",0},
1869 {0,"enhances","APT::Cache::ShowEnhances",0},
1871 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1873 {"gencaches",&GenCaches
},
1874 {"showsrc",&ShowSrcPackage
},
1876 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1879 {"dumpavail",&DumpAvail
},
1882 {"depends",&Depends
},
1883 {"rdepends",&RDepends
},
1886 {"show",&ShowPackage
},
1887 {"pkgnames",&ShowPkgNames
},
1888 {"showauto",&ShowAuto
},
1890 {"madison",&Madison
},
1895 // Set up gettext support
1896 setlocale(LC_ALL
,"");
1897 textdomain(PACKAGE
);
1899 // Parse the command line and initialize the package library
1900 CommandLine
CmdL(Args
,_config
);
1901 if (pkgInitConfig(*_config
) == false ||
1902 CmdL
.Parse(argc
,argv
) == false ||
1903 pkgInitSystem(*_config
,_system
) == false)
1905 _error
->DumpErrors();
1909 // See if the help should be shown
1910 if (_config
->FindB("help") == true ||
1911 CmdL
.FileSize() == 0)
1917 // Deal with stdout not being a tty
1918 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1919 _config
->Set("quiet","1");
1921 if (_config
->Exists("APT::Cache::Generate") == true)
1922 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1924 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1925 CmdL
.DispatchArg(CmdsB
);
1927 // Print any errors or warnings found during parsing
1928 bool const Errors
= _error
->PendingError();
1929 if (_config
->FindI("quiet",0) > 0)
1930 _error
->DumpErrors();
1932 _error
->DumpErrors(GlobalError::DEBUG
);
1933 return Errors
== true ? 100 : 0;