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::CacheSetHelper
helper(true, GlobalError::NOTICE
);
177 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
178 APT::VersionSet::CANDIDATE
, helper
);
179 for (APT::VersionSet::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
180 if (ShowUnMet(V
, Important
) == false)
186 // DumpPackage - Show a dump of a package record /*{{{*/
187 // ---------------------------------------------------------------------
189 bool DumpPackage(CommandLine
&CmdL
)
191 pkgCacheFile CacheFile
;
192 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
193 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
195 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
197 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
198 cout
<< "Versions: " << endl
;
199 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
201 cout
<< Cur
.VerStr();
202 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
203 cout
<< " (" << Vf
.File().FileName() << ")";
205 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; D
++)
207 cout
<< " Description Language: " << D
.LanguageCode() << endl
208 << " File: " << D
.FileList().File().FileName() << endl
209 << " MD5: " << D
.md5() << endl
;
216 cout
<< "Reverse Depends: " << endl
;
217 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
219 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
221 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
226 cout
<< "Dependencies: " << endl
;
227 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
229 cout
<< Cur
.VerStr() << " - ";
230 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
231 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
235 cout
<< "Provides: " << endl
;
236 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
238 cout
<< Cur
.VerStr() << " - ";
239 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
240 cout
<< Prv
.ParentPkg().FullName(true) << " ";
243 cout
<< "Reverse Provides: " << endl
;
244 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
245 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
251 // Stats - Dump some nice statistics /*{{{*/
252 // ---------------------------------------------------------------------
254 bool Stats(CommandLine
&Cmd
)
256 pkgCacheFile CacheFile
;
257 pkgCache
*Cache
= CacheFile
.GetPkgCache();
258 if (unlikely(Cache
== NULL
))
261 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
262 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
263 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
264 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
271 pkgCache::PkgIterator I
= Cache
->PkgBegin();
272 for (;I
.end() != true; I
++)
274 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
280 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
286 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
289 if (I
.ProvidesList()->NextProvides
== 0)
297 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
303 cout
<< _(" Normal packages: ") << Normal
<< endl
;
304 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
305 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
306 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
307 cout
<< _(" Missing: ") << Missing
<< endl
;
309 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
310 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
311 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
312 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
313 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
314 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
316 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
317 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
318 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
319 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
320 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
321 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
324 unsigned long Size
= 0;
325 unsigned long Count
= 0;
326 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
327 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
330 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
332 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
334 unsigned long DepVerSize
= 0;
335 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
337 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
339 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
342 DepVerSize
+= strlen(D
.TargetVer()) + 1;
346 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
348 unsigned long Slack
= 0;
349 for (int I
= 0; I
!= 7; I
++)
350 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
351 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
353 unsigned long Total
= 0;
354 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
355 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
356 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
357 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
358 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
359 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
364 // Dump - show everything /*{{{*/
365 // ---------------------------------------------------------------------
366 /* This is worthless except fer debugging things */
367 bool Dump(CommandLine
&Cmd
)
369 pkgCacheFile CacheFile
;
370 pkgCache
*Cache
= CacheFile
.GetPkgCache();
371 if (unlikely(Cache
== NULL
))
374 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
376 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
378 cout
<< "Package: " << P
.FullName(true) << endl
;
379 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
381 cout
<< " Version: " << V
.VerStr() << endl
;
382 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
383 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
384 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
385 DeNull(D
.TargetVer()) << endl
;
386 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; D
++)
388 cout
<< " Description Language: " << D
.LanguageCode() << endl
389 << " File: " << D
.FileList().File().FileName() << endl
390 << " MD5: " << D
.md5() << endl
;
395 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
397 cout
<< "File: " << F
.FileName() << endl
;
398 cout
<< " Type: " << F
.IndexType() << endl
;
399 cout
<< " Size: " << F
->Size
<< endl
;
400 cout
<< " ID: " << F
->ID
<< endl
;
401 cout
<< " Flags: " << F
->Flags
<< endl
;
402 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
403 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
404 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
405 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
406 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
407 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
408 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
409 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
415 // DumpAvail - Print out the available list /*{{{*/
416 // ---------------------------------------------------------------------
417 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
418 make this run really fast, perhaps I went a little overboard.. */
419 bool DumpAvail(CommandLine
&Cmd
)
421 pkgCacheFile CacheFile
;
422 pkgCache
*Cache
= CacheFile
.GetPkgCache();
423 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
426 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
427 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
428 memset(VFList
,0,sizeof(*VFList
)*Count
);
430 // Map versions that we want to write out onto the VerList array.
431 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
433 if (P
->VersionList
== 0)
436 /* Find the proper version to use. If the policy says there are no
437 possible selections we return the installed version, if available..
438 This prevents dselect from making it obsolete. */
439 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
442 if (P
->CurrentVer
== 0)
447 pkgCache::VerFileIterator VF
= V
.FileList();
448 for (; VF
.end() == false ; VF
++)
449 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
452 /* Okay, here we have a bit of a problem.. The policy has selected the
453 currently installed package - however it only exists in the
454 status file.. We need to write out something or dselect will mark
455 the package as obsolete! Thus we emit the status file entry, but
456 below we remove the status line to make it valid for the
457 available file. However! We only do this if their do exist *any*
458 non-source versions of the package - that way the dselect obsolete
459 handling works OK. */
460 if (VF
.end() == true)
462 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
464 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
466 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
473 if (VF
.end() == false)
481 LocalitySort(VFList
,Count
,sizeof(*VFList
));
483 // Iterate over all the package files and write them out.
484 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
485 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
487 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
488 if (File
.IsOk() == false)
490 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
494 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
495 if (_error
->PendingError() == true)
498 /* Write all of the records from this package file, since we
499 already did locality sorting we can now just seek through the
500 file in read order. We apply 1 more optimization here, since often
501 there will be < 1 byte gaps between records (for the \n) we read that
502 into the next buffer and offset a bit.. */
503 unsigned long Pos
= 0;
506 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
509 const pkgCache::VerFile
&VF
= **J
;
511 // Read the record and then write it out again.
512 unsigned long Jitter
= VF
.Offset
- Pos
;
515 if (PkgF
.Seek(VF
.Offset
) == false)
520 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
522 Buffer
[VF
.Size
+ Jitter
] = '\n';
525 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
528 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
529 const char *Zero
= 0;
530 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
531 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
533 _error
->Error("Internal Error, Unable to parse a package record");
540 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
544 Pos
= VF
.Offset
+ VF
.Size
;
548 if (_error
->PendingError() == true)
554 return !_error
->PendingError();
557 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
558 class CacheSetHelperDepends
: public APT::CacheSetHelper
{
560 APT::PackageSet virtualPkgs
;
562 virtual pkgCache::VerIterator
canNotFindCandidateVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
563 virtualPkgs
.insert(Pkg
);
564 return pkgCache::VerIterator(Cache
, 0);
567 virtual pkgCache::VerIterator
canNotFindNewestVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
568 virtualPkgs
.insert(Pkg
);
569 return pkgCache::VerIterator(Cache
, 0);
572 CacheSetHelperDepends() : CacheSetHelper(false, GlobalError::NOTICE
) {}
574 bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
576 pkgCacheFile CacheFile
;
577 pkgCache
*Cache
= CacheFile
.GetPkgCache();
578 if (unlikely(Cache
== NULL
))
581 CacheSetHelperDepends helper
;
582 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionSet::CANDIDATE
, helper
);
583 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
585 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
587 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
588 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
589 bool const Important
= _config
->FindB("APT::Cache::Important", false);
590 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
591 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
592 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
593 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
594 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
595 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
596 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
597 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
598 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
599 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
601 while (verset
.empty() != true)
603 pkgCache::VerIterator Ver
= *verset
.begin();
604 verset
.erase(verset
.begin());
605 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
606 Shown
[Pkg
->ID
] = true;
608 cout
<< Pkg
.FullName(true) << endl
;
610 if (RevDepends
== true)
611 cout
<< "Reverse Depends:" << endl
;
612 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
613 D
.end() == false; D
++)
616 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
617 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
618 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
619 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
620 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
621 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
622 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
623 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
626 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
628 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
631 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
637 if (ShowDepType
== true)
638 cout
<< D
.DepType() << ": ";
639 if (Trg
->VersionList
== 0)
640 cout
<< "<" << Trg
.FullName(true) << ">" << endl
;
642 cout
<< Trg
.FullName(true) << endl
;
644 if (Recurse
== true && Shown
[Trg
->ID
] == false)
646 Shown
[Trg
->ID
] = true;
647 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
652 // Display all solutions
653 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
654 pkgPrioSortList(*Cache
,List
);
655 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
657 pkgCache::VerIterator
V(*Cache
,*I
);
658 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
659 V
->ParentPkg
== D
->Package
)
661 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
663 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
665 Shown
[V
.ParentPkg()->ID
] = true;
666 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
670 if (ShowOnlyFirstOr
== true)
671 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
675 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
676 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
677 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
682 // Depends - Print out a dependency tree /*{{{*/
683 // ---------------------------------------------------------------------
685 bool Depends(CommandLine
&CmdL
)
687 return ShowDepends(CmdL
, false);
690 // RDepends - Print out a reverse dependency tree /*{{{*/
691 // ---------------------------------------------------------------------
693 bool RDepends(CommandLine
&CmdL
)
695 return ShowDepends(CmdL
, true);
698 // xvcg - Generate a graph for xvcg /*{{{*/
699 // ---------------------------------------------------------------------
700 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
702 bool XVcg(CommandLine
&CmdL
)
704 pkgCacheFile CacheFile
;
705 pkgCache
*Cache
= CacheFile
.GetPkgCache();
706 if (unlikely(Cache
== NULL
))
709 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
711 /* Normal packages are boxes
712 Pure Provides are triangles
714 rhomb are missing packages*/
715 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
717 /* Initialize the list of packages to show.
719 2 = To Show no recurse
720 3 = Emitted no recurse
723 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
724 enum TheFlags
{ForceNR
=(1<<0)};
725 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
726 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
727 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
729 // Show everything if no arguments given
730 if (CmdL
.FileList
[1] == 0)
731 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
734 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
736 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
739 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
741 if (Pkg
->VersionList
== 0)
744 if (Pkg
->ProvidesList
== 0)
745 ShapeMap
[Pkg
->ID
] = 0;
747 ShapeMap
[Pkg
->ID
] = 1;
752 if (Pkg
->ProvidesList
== 0)
753 ShapeMap
[Pkg
->ID
] = 2;
755 ShapeMap
[Pkg
->ID
] = 3;
759 // Load the list of packages from the command line into the show list
760 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
761 std::list
<APT::PackageSet::Modifier
> mods
;
762 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
763 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
764 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
765 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
767 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
768 Pkg
!= pkgsets
[0].end(); ++Pkg
)
769 Show
[Pkg
->ID
] = ToShow
;
770 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
771 Pkg
!= pkgsets
[1].end(); ++Pkg
)
773 Show
[Pkg
->ID
] = ToShow
;
774 Flags
[Pkg
->ID
] |= ForceNR
;
778 cout
<< "graph: { title: \"packages\"" << endl
<<
779 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
780 "layout_downfactor: 8" << endl
;
786 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
788 // See we need to show this package
789 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
792 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
795 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
797 // Pure Provides and missing packages have no deps!
798 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
799 Show
[Pkg
->ID
] = Done
;
801 Show
[Pkg
->ID
] = DoneNR
;
804 Show
[Pkg
->ID
] = Done
;
807 // No deps to map out
808 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
811 pkgCache::VerIterator Ver
= Pkg
.VersionList();
812 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
814 // See if anything can meet this dep
815 // Walk along the actual package providing versions
817 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
818 for (pkgCache::VerIterator I
= DPkg
.VersionList();
819 I
.end() == false && Hit
== false; I
++)
821 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
825 // Follow all provides
826 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
827 I
.end() == false && Hit
== false; I
++)
829 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
834 // Only graph critical deps
835 if (D
.IsCritical() == true)
837 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
839 // Colour the node for recursion
840 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
842 /* If a conflicts does not meet anything in the database
843 then show the relation but do not recurse */
845 (D
->Type
== pkgCache::Dep::Conflicts
||
846 D
->Type
== pkgCache::Dep::DpkgBreaks
||
847 D
->Type
== pkgCache::Dep::Obsoletes
))
849 if (Show
[D
.TargetPkg()->ID
] == None
&&
850 Show
[D
.TargetPkg()->ID
] != ToShow
)
851 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
855 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
856 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
858 Show
[D
.TargetPkg()->ID
] = ToShow
;
865 case pkgCache::Dep::Conflicts
:
866 printf("label: \"conflicts\" color: lightgreen }\n");
868 case pkgCache::Dep::DpkgBreaks
:
869 printf("label: \"breaks\" color: lightgreen }\n");
871 case pkgCache::Dep::Obsoletes
:
872 printf("label: \"obsoletes\" color: lightgreen }\n");
875 case pkgCache::Dep::PreDepends
:
876 printf("label: \"predepends\" color: blue }\n");
888 /* Draw the box colours after the fact since we can not tell what colour
889 they should be until everything is finished drawing */
890 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
892 if (Show
[Pkg
->ID
] < DoneNR
)
895 if (Show
[Pkg
->ID
] == DoneNR
)
896 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
897 Shapes
[ShapeMap
[Pkg
->ID
]]);
899 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
900 Shapes
[ShapeMap
[Pkg
->ID
]]);
912 // Dotty - Generate a graph for Dotty /*{{{*/
913 // ---------------------------------------------------------------------
914 /* Dotty is the graphvis program for generating graphs. It is a fairly
915 simple queuing algorithm that just writes dependencies and nodes.
916 http://www.research.att.com/sw/tools/graphviz/ */
917 bool Dotty(CommandLine
&CmdL
)
919 pkgCacheFile CacheFile
;
920 pkgCache
*Cache
= CacheFile
.GetPkgCache();
921 if (unlikely(Cache
== NULL
))
924 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
926 /* Normal packages are boxes
927 Pure Provides are triangles
929 Hexagons are missing packages*/
930 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
932 /* Initialize the list of packages to show.
934 2 = To Show no recurse
935 3 = Emitted no recurse
938 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
939 enum TheFlags
{ForceNR
=(1<<0)};
940 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
941 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
942 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
944 // Show everything if no arguments given
945 if (CmdL
.FileList
[1] == 0)
946 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
949 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
951 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
954 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
956 if (Pkg
->VersionList
== 0)
959 if (Pkg
->ProvidesList
== 0)
960 ShapeMap
[Pkg
->ID
] = 0;
962 ShapeMap
[Pkg
->ID
] = 1;
967 if (Pkg
->ProvidesList
== 0)
968 ShapeMap
[Pkg
->ID
] = 2;
970 ShapeMap
[Pkg
->ID
] = 3;
974 // Load the list of packages from the command line into the show list
975 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
976 std::list
<APT::PackageSet::Modifier
> mods
;
977 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
978 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
979 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
980 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
982 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
983 Pkg
!= pkgsets
[0].end(); ++Pkg
)
984 Show
[Pkg
->ID
] = ToShow
;
985 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
986 Pkg
!= pkgsets
[1].end(); ++Pkg
)
988 Show
[Pkg
->ID
] = ToShow
;
989 Flags
[Pkg
->ID
] |= ForceNR
;
993 printf("digraph packages {\n");
994 printf("concentrate=true;\n");
995 printf("size=\"30,40\";\n");
1001 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1003 // See we need to show this package
1004 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1008 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1010 // Pure Provides and missing packages have no deps!
1011 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1012 Show
[Pkg
->ID
] = Done
;
1014 Show
[Pkg
->ID
] = DoneNR
;
1017 Show
[Pkg
->ID
] = Done
;
1020 // No deps to map out
1021 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1024 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1025 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
1027 // See if anything can meet this dep
1028 // Walk along the actual package providing versions
1030 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1031 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1032 I
.end() == false && Hit
== false; I
++)
1034 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1038 // Follow all provides
1039 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1040 I
.end() == false && Hit
== false; I
++)
1042 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1046 // Only graph critical deps
1047 if (D
.IsCritical() == true)
1049 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1051 // Colour the node for recursion
1052 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1054 /* If a conflicts does not meet anything in the database
1055 then show the relation but do not recurse */
1057 (D
->Type
== pkgCache::Dep::Conflicts
||
1058 D
->Type
== pkgCache::Dep::Obsoletes
))
1060 if (Show
[D
.TargetPkg()->ID
] == None
&&
1061 Show
[D
.TargetPkg()->ID
] != ToShow
)
1062 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1066 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1067 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1069 Show
[D
.TargetPkg()->ID
] = ToShow
;
1076 case pkgCache::Dep::Conflicts
:
1077 case pkgCache::Dep::Obsoletes
:
1078 printf("[color=springgreen];\n");
1081 case pkgCache::Dep::PreDepends
:
1082 printf("[color=blue];\n");
1094 /* Draw the box colours after the fact since we can not tell what colour
1095 they should be until everything is finished drawing */
1096 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1098 if (Show
[Pkg
->ID
] < DoneNR
)
1101 // Orange box for early recursion stoppage
1102 if (Show
[Pkg
->ID
] == DoneNR
)
1103 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1104 Shapes
[ShapeMap
[Pkg
->ID
]]);
1106 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1107 Shapes
[ShapeMap
[Pkg
->ID
]]);
1114 // DoAdd - Perform an adding operation /*{{{*/
1115 // ---------------------------------------------------------------------
1117 bool DoAdd(CommandLine
&CmdL
)
1119 return _error
->Error("Unimplemented");
1121 // Make sure there is at least one argument
1122 if (CmdL
.FileSize() <= 1)
1123 return _error
->Error("You must give at least one file name");
1126 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
1127 if (_error
->PendingError() == true)
1130 DynamicMMap
Map(CacheF
,MMap::Public
);
1131 if (_error
->PendingError() == true)
1134 OpTextProgress
Progress(*_config
);
1135 pkgCacheGenerator
Gen(Map
,Progress
);
1136 if (_error
->PendingError() == true)
1139 unsigned long Length
= CmdL
.FileSize() - 1;
1140 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1142 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
1143 Progress
.SubProgress(Length
);
1146 FileFd
TagF(*I
,FileFd::ReadOnly
);
1147 debListParser
Parser(TagF
);
1148 if (_error
->PendingError() == true)
1149 return _error
->Error("Problem opening %s",*I
);
1151 if (Gen
.SelectFile(*I
,"") == false)
1152 return _error
->Error("Problem with SelectFile");
1154 if (Gen
.MergeList(Parser
) == false)
1155 return _error
->Error("Problem with MergeList");
1159 GCache
= &Gen
.GetCache();
1166 // DisplayRecord - Displays the complete record for the package /*{{{*/
1167 // ---------------------------------------------------------------------
1168 /* This displays the package record from the proper package index file.
1169 It is not used by DumpAvail for performance reasons. */
1170 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1172 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1173 if (unlikely(Cache
== NULL
))
1176 // Find an appropriate file
1177 pkgCache::VerFileIterator Vf
= V
.FileList();
1178 for (; Vf
.end() == false; Vf
++)
1179 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1181 if (Vf
.end() == true)
1184 // Check and load the package list file
1185 pkgCache::PkgFileIterator I
= Vf
.File();
1186 if (I
.IsOk() == false)
1187 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1190 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnlyGzip
) == false)
1194 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1195 Buffer
[V
.FileList()->Size
] = '\n';
1196 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1197 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1203 // Get a pointer to start of Description field
1204 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1206 // Write all but Description
1207 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1213 // Show the right description
1214 pkgRecords
Recs(*Cache
);
1215 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1216 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1217 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1219 // Find the first field after the description (if there is any)
1220 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1222 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1224 // write the rest of the buffer
1225 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1226 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1235 // write a final newline (after the description)
1245 pkgCache::DescFile
*Df
;
1249 // Search - Perform a search /*{{{*/
1250 // ---------------------------------------------------------------------
1251 /* This searches the package names and package descriptions for a pattern */
1252 bool Search(CommandLine
&CmdL
)
1254 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1255 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1256 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1258 pkgCacheFile CacheFile
;
1259 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1260 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1261 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1264 // Make sure there is at least one argument
1265 if (NumPatterns
< 1)
1266 return _error
->Error(_("You must give at least one search pattern"));
1268 // Compile the regex pattern
1269 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1270 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1271 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1273 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1277 regfree(&Patterns
[I
]);
1278 return _error
->Error("Regex compilation error");
1282 if (_error
->PendingError() == true)
1284 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1285 regfree(&Patterns
[I
]);
1289 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1290 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1292 // Map versions that we want to write out onto the VerList array.
1293 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1295 if (DFList
[G
->ID
].NameMatch
== true)
1298 DFList
[G
->ID
].NameMatch
= true;
1299 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1301 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1303 DFList
[G
->ID
].NameMatch
= false;
1307 // Doing names only, drop any that dont match..
1308 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1311 // Find the proper version to use
1312 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1313 if (P
.end() == true)
1315 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1316 if (V
.end() == false)
1317 DFList
[G
->ID
].Df
= V
.DescriptionList().FileList();
1319 if (DFList
[G
->ID
].NameMatch
== false)
1322 // Include all the packages that provide matching names too
1323 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
1325 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1326 if (V
.end() == true)
1329 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1330 DFList
[id
].Df
= V
.DescriptionList().FileList();
1331 DFList
[id
].NameMatch
= true;
1335 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1337 // Create the text record parser
1338 pkgRecords
Recs(*Cache
);
1339 // Iterate over all the version records and check them
1340 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1342 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1344 if (J
->NameMatch
== false && NamesOnly
== false)
1346 string
const LongDesc
= P
.LongDesc();
1347 J
->NameMatch
= true;
1348 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1350 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1352 J
->NameMatch
= false;
1357 if (J
->NameMatch
== true)
1359 if (ShowFull
== true)
1363 P
.GetRec(Start
,End
);
1364 fwrite(Start
,End
-Start
,1,stdout
);
1368 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1373 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1374 regfree(&Patterns
[I
]);
1376 return _error
->Error("Write to stdout failed");
1381 /* show automatically installed packages (sorted) */
1382 bool ShowAuto(CommandLine
&CmdL
)
1384 pkgCacheFile CacheFile
;
1385 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1386 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1387 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1390 std::vector
<string
> packages
;
1391 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1393 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
1394 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1395 packages
.push_back(P
.Name());
1397 std::sort(packages
.begin(), packages
.end());
1399 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); I
++)
1405 // ShowPackage - Dump the package record to the screen /*{{{*/
1406 // ---------------------------------------------------------------------
1408 bool ShowPackage(CommandLine
&CmdL
)
1410 pkgCacheFile CacheFile
;
1411 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1412 APT::VersionSet::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1413 APT::VersionSet::ALL
: APT::VersionSet::CANDIDATE
;
1414 APT::VersionSet
const verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1415 for (APT::VersionSet::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1416 if (DisplayRecord(CacheFile
, Ver
) == false)
1419 if (verset
.empty() == false)
1421 return _error
->Error(_("No packages found"));
1424 // ShowPkgNames - Show package names /*{{{*/
1425 // ---------------------------------------------------------------------
1426 /* This does a prefix match on the first argument */
1427 bool ShowPkgNames(CommandLine
&CmdL
)
1429 pkgCacheFile CacheFile
;
1430 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1432 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1433 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1435 if (CmdL
.FileList
[1] != 0)
1437 for (;I
.end() != true; I
++)
1439 if (All
== false && I
->FirstPackage
== 0)
1441 if (I
.FindPkg("any")->VersionList
== 0)
1443 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1444 cout
<< I
.Name() << endl
;
1451 for (;I
.end() != true; I
++)
1453 if (All
== false && I
->FirstPackage
== 0)
1455 if (I
.FindPkg("any")->VersionList
== 0)
1457 cout
<< I
.Name() << endl
;
1463 // ShowSrcPackage - Show source package records /*{{{*/
1464 // ---------------------------------------------------------------------
1466 bool ShowSrcPackage(CommandLine
&CmdL
)
1468 pkgCacheFile CacheFile
;
1469 pkgSourceList
*List
= CacheFile
.GetSourceList();
1470 if (unlikely(List
== NULL
))
1473 // Create the text record parsers
1474 pkgSrcRecords
SrcRecs(*List
);
1475 if (_error
->PendingError() == true)
1479 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1483 pkgSrcRecords::Parser
*Parse
;
1484 unsigned found_this
= 0;
1485 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1486 cout
<< Parse
->AsStr() << endl
;;
1490 if (found_this
== 0) {
1491 _error
->Warning(_("Unable to locate package %s"),*I
);
1497 return _error
->Error(_("No packages found"));
1500 // Policy - Show the results of the preferences file /*{{{*/
1501 // ---------------------------------------------------------------------
1503 bool Policy(CommandLine
&CmdL
)
1505 pkgCacheFile CacheFile
;
1506 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1507 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1508 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1509 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1512 /* Should the MultiArchKiller be run to see which pseudo packages for an
1513 arch all package are currently installed? Activating it gives a speed
1514 penality for no real gain beside enhanced debugging, so in general no. */
1515 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1516 CacheFile
.GetDepCache();
1518 // Print out all of the package files
1519 if (CmdL
.FileList
[1] == 0)
1521 cout
<< _("Package files:") << endl
;
1522 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
1524 // Locate the associated index files so we can derive a description
1526 if (SrcList
->FindIndex(F
,Indx
) == false &&
1527 _system
->FindIndex(F
,Indx
) == false)
1528 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1531 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1533 // Print the reference information for the package
1534 string Str
= F
.RelStr();
1535 if (Str
.empty() == false)
1536 printf(" release %s\n",F
.RelStr().c_str());
1537 if (F
.Site() != 0 && F
.Site()[0] != 0)
1538 printf(" origin %s\n",F
.Site());
1541 // Show any packages have explicit pins
1542 cout
<< _("Pinned packages:") << endl
;
1543 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1544 for (;I
.end() != true; I
++)
1546 if (Plcy
->GetPriority(I
) == 0)
1549 // Print the package name and the version we are forcing to
1550 cout
<< " " << I
.FullName(true) << " -> ";
1552 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1553 if (V
.end() == true)
1554 cout
<< _("(not found)") << endl
;
1556 cout
<< V
.VerStr() << endl
;
1562 string
const myArch
= _config
->Find("APT::Architecture");
1563 char const * const msgInstalled
= _(" Installed: ");
1564 char const * const msgCandidate
= _(" Candidate: ");
1565 short const InstalledLessCandidate
=
1566 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1567 short const deepInstalled
=
1568 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1569 short const deepCandidate
=
1570 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1572 // Print out detailed information for each package
1573 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1574 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1575 for (APT::PackageSet::const_iterator I
= pkgset
.begin(); I
!= pkgset
.end(); ++I
)
1577 pkgCache::PkgIterator Pkg
= I
.Group().FindPkg("any");
1579 for (; Pkg
.end() != true; Pkg
= I
.Group().NextPkg(Pkg
)) {
1580 if (strcmp(Pkg
.Arch(),"all") == 0)
1583 cout
<< Pkg
.FullName(true) << ":" << endl
;
1585 // Installed version
1586 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1587 if (Pkg
->CurrentVer
== 0)
1588 cout
<< _("(none)") << endl
;
1590 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1592 // Candidate Version
1593 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1594 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1595 if (V
.end() == true)
1596 cout
<< _("(none)") << endl
;
1598 cout
<< V
.VerStr() << endl
;
1601 if (Plcy
->GetPriority(Pkg
) != 0)
1603 cout
<< _(" Package pin: ");
1604 V
= Plcy
->GetMatch(Pkg
);
1605 if (V
.end() == true)
1606 cout
<< _("(not found)") << endl
;
1608 cout
<< V
.VerStr() << endl
;
1611 // Show the priority tables
1612 cout
<< _(" Version table:") << endl
;
1613 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1615 if (Pkg
.CurrentVer() == V
)
1616 cout
<< " *** " << V
.VerStr();
1618 cout
<< " " << V
.VerStr();
1619 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1620 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1622 // Locate the associated index files so we can derive a description
1624 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1625 _system
->FindIndex(VF
.File(),Indx
) == false)
1626 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1627 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1628 Indx
->Describe(true).c_str());
1637 // Madison - Look a bit like katie's madison /*{{{*/
1638 // ---------------------------------------------------------------------
1640 bool Madison(CommandLine
&CmdL
)
1642 pkgCacheFile CacheFile
;
1643 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1648 // Create the src text record parsers and ignore errors about missing
1649 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1650 pkgSrcRecords
SrcRecs(*SrcList
);
1651 if (_error
->PendingError() == true)
1654 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1655 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1656 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1658 if (Pkg
.end() == false)
1660 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; V
++)
1662 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1664 // This might be nice, but wouldn't uniquely identify the source -mdz
1665 // if (VF.File().Archive() != 0)
1667 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1668 // << VF.File().Archive() << endl;
1671 // Locate the associated index files so we can derive a description
1672 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); S
++)
1674 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1675 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1676 IF
!= Indexes
->end(); IF
++)
1678 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1680 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1681 << (*IF
)->Describe(true) << endl
;
1691 pkgSrcRecords::Parser
*SrcParser
;
1692 while ((SrcParser
= SrcRecs
.Find(Pkg
.Name(),false)) != 0)
1694 // Maybe support Release info here too eventually
1695 cout
<< setw(10) << SrcParser
->Package() << " | "
1696 << setw(10) << SrcParser
->Version() << " | "
1697 << SrcParser
->Index().Describe(true) << endl
;
1704 // GenCaches - Call the main cache generator /*{{{*/
1705 // ---------------------------------------------------------------------
1707 bool GenCaches(CommandLine
&Cmd
)
1709 OpTextProgress
Progress(*_config
);
1711 pkgCacheFile CacheFile
;
1712 return CacheFile
.BuildCaches(&Progress
, true);
1715 // ShowHelp - Show a help screen /*{{{*/
1716 // ---------------------------------------------------------------------
1718 bool ShowHelp(CommandLine
&Cmd
)
1720 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1721 COMMON_ARCH
,__DATE__
,__TIME__
);
1723 if (_config
->FindB("version") == true)
1727 _("Usage: apt-cache [options] command\n"
1728 " apt-cache [options] add file1 [file2 ...]\n"
1729 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1730 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1732 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1733 "cache files, and query information from them\n"
1736 " add - Add a package file to the source cache\n"
1737 " gencaches - Build both the package and source cache\n"
1738 " showpkg - Show some general information for a single package\n"
1739 " showsrc - Show source records\n"
1740 " stats - Show some basic statistics\n"
1741 " dump - Show the entire file in a terse form\n"
1742 " dumpavail - Print an available file to stdout\n"
1743 " unmet - Show unmet dependencies\n"
1744 " search - Search the package list for a regex pattern\n"
1745 " show - Show a readable record for the package\n"
1746 " showauto - Display a list of automatically installed packages\n"
1747 " depends - Show raw dependency information for a package\n"
1748 " rdepends - Show reverse dependency information for a package\n"
1749 " pkgnames - List the names of all packages in the system\n"
1750 " dotty - Generate package graphs for GraphViz\n"
1751 " xvcg - Generate package graphs for xvcg\n"
1752 " policy - Show policy settings\n"
1755 " -h This help text.\n"
1756 " -p=? The package cache.\n"
1757 " -s=? The source cache.\n"
1758 " -q Disable progress indicator.\n"
1759 " -i Show only important deps for the unmet command.\n"
1760 " -c=? Read this configuration file\n"
1761 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1762 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1766 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1767 // ---------------------------------------------------------------------
1769 void CacheInitialize()
1771 _config
->Set("quiet",0);
1772 _config
->Set("help",false);
1775 int main(int argc
,const char *argv
[]) /*{{{*/
1777 CommandLine::Args Args
[] = {
1778 {'h',"help","help",0},
1779 {'v',"version","version",0},
1780 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1781 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1782 {'q',"quiet","quiet",CommandLine::IntLevel
},
1783 {'i',"important","APT::Cache::Important",0},
1784 {'f',"full","APT::Cache::ShowFull",0},
1785 {'g',"generate","APT::Cache::Generate",0},
1786 {'a',"all-versions","APT::Cache::AllVersions",0},
1787 {'n',"names-only","APT::Cache::NamesOnly",0},
1788 {0,"all-names","APT::Cache::AllNames",0},
1789 {0,"recurse","APT::Cache::RecurseDepends",0},
1790 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1791 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1792 {'c',"config-file",0,CommandLine::ConfigFile
},
1793 {'o',"option",0,CommandLine::ArbItem
},
1794 {0,"installed","APT::Cache::Installed",0},
1795 {0,"pre-depends","APT::Cache::ShowPreDepends",0},
1796 {0,"depends","APT::Cache::ShowDepends",0},
1797 {0,"recommends","APT::Cache::ShowRecommends",0},
1798 {0,"suggests","APT::Cache::ShowSuggests",0},
1799 {0,"replaces","APT::Cache::ShowReplaces",0},
1800 {0,"breaks","APT::Cache::ShowBreaks",0},
1801 {0,"conflicts","APT::Cache::ShowConflicts",0},
1802 {0,"enhances","APT::Cache::ShowEnhances",0},
1804 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1806 {"gencaches",&GenCaches
},
1807 {"showsrc",&ShowSrcPackage
},
1809 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1812 {"dumpavail",&DumpAvail
},
1815 {"depends",&Depends
},
1816 {"rdepends",&RDepends
},
1819 {"show",&ShowPackage
},
1820 {"pkgnames",&ShowPkgNames
},
1821 {"showauto",&ShowAuto
},
1823 {"madison",&Madison
},
1828 // Set up gettext support
1829 setlocale(LC_ALL
,"");
1830 textdomain(PACKAGE
);
1832 // Parse the command line and initialize the package library
1833 CommandLine
CmdL(Args
,_config
);
1834 if (pkgInitConfig(*_config
) == false ||
1835 CmdL
.Parse(argc
,argv
) == false ||
1836 pkgInitSystem(*_config
,_system
) == false)
1838 _error
->DumpErrors();
1842 // See if the help should be shown
1843 if (_config
->FindB("help") == true ||
1844 CmdL
.FileSize() == 0)
1850 // Deal with stdout not being a tty
1851 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1852 _config
->Set("quiet","1");
1854 if (_config
->Exists("APT::Cache::Generate") == true)
1855 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1857 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1858 CmdL
.DispatchArg(CmdsB
);
1860 // Print any errors or warnings found during parsing
1861 bool const Errors
= _error
->PendingError();
1862 if (_config
->FindI("quiet",0) > 0)
1863 _error
->DumpErrors();
1865 _error
->DumpErrors(GlobalError::DEBUG
);
1866 return Errors
== true ? 100 : 0;