]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
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 // CacheSetHelper saving virtual packages /*{{{*/
50 class CacheSetHelperVirtuals
: public APT::CacheSetHelper
{
52 APT::PackageSet virtualPkgs
;
54 virtual pkgCache::VerIterator
canNotFindCandidateVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
55 virtualPkgs
.insert(Pkg
);
56 return CacheSetHelper::canNotFindCandidateVer(Cache
, Pkg
);
59 virtual pkgCache::VerIterator
canNotFindNewestVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
60 virtualPkgs
.insert(Pkg
);
61 return CacheSetHelper::canNotFindNewestVer(Cache
, Pkg
);
64 virtual APT::VersionSet
canNotFindAllVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) {
65 virtualPkgs
.insert(Pkg
);
66 return CacheSetHelper::canNotFindAllVer(Cache
, Pkg
);
69 CacheSetHelperVirtuals(bool const &ShowErrors
= true, GlobalError::MsgType
const &ErrorType
= GlobalError::NOTICE
) : CacheSetHelper(ShowErrors
, ErrorType
) {}
72 // LocalitySort - Sort a version list by package file locality /*{{{*/
73 // ---------------------------------------------------------------------
75 int LocalityCompare(const void *a
, const void *b
)
77 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
78 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
87 if (A
->File
== B
->File
)
88 return A
->Offset
- B
->Offset
;
89 return A
->File
- B
->File
;
92 void LocalitySort(pkgCache::VerFile
**begin
,
93 unsigned long Count
,size_t Size
)
95 qsort(begin
,Count
,Size
,LocalityCompare
);
98 void LocalitySort(pkgCache::DescFile
**begin
,
99 unsigned long Count
,size_t Size
)
101 qsort(begin
,Count
,Size
,LocalityCompare
);
104 // UnMet - Show unmet dependencies /*{{{*/
105 // ---------------------------------------------------------------------
107 bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const &Important
)
110 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
113 pkgCache::DepIterator Start
;
114 pkgCache::DepIterator End
;
117 // Important deps only
118 if (Important
== true)
119 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
120 End
->Type
!= pkgCache::Dep::Depends
)
123 // Skip conflicts and replaces
124 if (End
->Type
== pkgCache::Dep::DpkgBreaks
||
125 End
->Type
== pkgCache::Dep::Replaces
||
126 End
->Type
== pkgCache::Dep::Conflicts
)
129 // Verify the or group
131 pkgCache::DepIterator RealStart
= Start
;
134 // See if this dep is Ok
135 pkgCache::Version
**VList
= Start
.AllTargets();
156 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
157 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
160 // Print out the dep type
161 cout
<< " " << End
.DepType() << ": ";
167 cout
<< Start
.TargetPkg().FullName(true);
168 if (Start
.TargetVer() != 0)
169 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
182 bool UnMet(CommandLine
&CmdL
)
184 bool const Important
= _config
->FindB("APT::Cache::Important",false);
186 pkgCacheFile CacheFile
;
187 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
190 if (CmdL
.FileSize() <= 1)
192 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; P
++)
193 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
194 if (ShowUnMet(V
, Important
) == false)
199 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
200 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
201 APT::VersionSet::CANDIDATE
, helper
);
202 for (APT::VersionSet::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
203 if (ShowUnMet(V
, Important
) == false)
209 // DumpPackage - Show a dump of a package record /*{{{*/
210 // ---------------------------------------------------------------------
212 bool DumpPackage(CommandLine
&CmdL
)
214 pkgCacheFile CacheFile
;
215 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
216 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
218 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
220 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
221 cout
<< "Versions: " << endl
;
222 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
224 cout
<< Cur
.VerStr();
225 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
226 cout
<< " (" << Vf
.File().FileName() << ")";
228 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; D
++)
230 cout
<< " Description Language: " << D
.LanguageCode() << endl
231 << " File: " << D
.FileList().File().FileName() << endl
232 << " MD5: " << D
.md5() << endl
;
239 cout
<< "Reverse Depends: " << endl
;
240 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
242 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
244 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
249 cout
<< "Dependencies: " << endl
;
250 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
252 cout
<< Cur
.VerStr() << " - ";
253 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
254 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
258 cout
<< "Provides: " << endl
;
259 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
261 cout
<< Cur
.VerStr() << " - ";
262 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
263 cout
<< Prv
.ParentPkg().FullName(true) << " ";
266 cout
<< "Reverse Provides: " << endl
;
267 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
268 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
274 // Stats - Dump some nice statistics /*{{{*/
275 // ---------------------------------------------------------------------
277 bool Stats(CommandLine
&Cmd
)
279 pkgCacheFile CacheFile
;
280 pkgCache
*Cache
= CacheFile
.GetPkgCache();
281 if (unlikely(Cache
== NULL
))
284 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
285 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
286 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
287 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
294 pkgCache::PkgIterator I
= Cache
->PkgBegin();
295 for (;I
.end() != true; I
++)
297 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
303 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
309 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
312 if (I
.ProvidesList()->NextProvides
== 0)
320 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
326 cout
<< _(" Normal packages: ") << Normal
<< endl
;
327 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
328 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
329 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
330 cout
<< _(" Missing: ") << Missing
<< endl
;
332 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
333 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
334 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
335 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
336 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
337 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
339 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
340 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
341 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
342 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
343 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
344 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
347 unsigned long Size
= 0;
348 unsigned long Count
= 0;
349 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
350 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
353 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
355 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
357 unsigned long DepVerSize
= 0;
358 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
360 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
362 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
365 DepVerSize
+= strlen(D
.TargetVer()) + 1;
369 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
371 unsigned long Slack
= 0;
372 for (int I
= 0; I
!= 7; I
++)
373 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
374 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
376 unsigned long Total
= 0;
377 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
378 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
379 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
380 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
381 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
382 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
387 // Dump - show everything /*{{{*/
388 // ---------------------------------------------------------------------
389 /* This is worthless except fer debugging things */
390 bool Dump(CommandLine
&Cmd
)
392 pkgCacheFile CacheFile
;
393 pkgCache
*Cache
= CacheFile
.GetPkgCache();
394 if (unlikely(Cache
== NULL
))
397 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
399 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
401 cout
<< "Package: " << P
.FullName(true) << endl
;
402 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
404 cout
<< " Version: " << V
.VerStr() << endl
;
405 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
406 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
407 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
408 DeNull(D
.TargetVer()) << endl
;
409 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; D
++)
411 cout
<< " Description Language: " << D
.LanguageCode() << endl
412 << " File: " << D
.FileList().File().FileName() << endl
413 << " MD5: " << D
.md5() << endl
;
418 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
420 cout
<< "File: " << F
.FileName() << endl
;
421 cout
<< " Type: " << F
.IndexType() << endl
;
422 cout
<< " Size: " << F
->Size
<< endl
;
423 cout
<< " ID: " << F
->ID
<< endl
;
424 cout
<< " Flags: " << F
->Flags
<< endl
;
425 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
426 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
427 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
428 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
429 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
430 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
431 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
432 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
438 // DumpAvail - Print out the available list /*{{{*/
439 // ---------------------------------------------------------------------
440 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
441 make this run really fast, perhaps I went a little overboard.. */
442 bool DumpAvail(CommandLine
&Cmd
)
444 pkgCacheFile CacheFile
;
445 pkgCache
*Cache
= CacheFile
.GetPkgCache();
446 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
449 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
450 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
451 memset(VFList
,0,sizeof(*VFList
)*Count
);
453 // Map versions that we want to write out onto the VerList array.
454 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
456 if (P
->VersionList
== 0)
459 /* Find the proper version to use. If the policy says there are no
460 possible selections we return the installed version, if available..
461 This prevents dselect from making it obsolete. */
462 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
465 if (P
->CurrentVer
== 0)
470 pkgCache::VerFileIterator VF
= V
.FileList();
471 for (; VF
.end() == false ; VF
++)
472 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
475 /* Okay, here we have a bit of a problem.. The policy has selected the
476 currently installed package - however it only exists in the
477 status file.. We need to write out something or dselect will mark
478 the package as obsolete! Thus we emit the status file entry, but
479 below we remove the status line to make it valid for the
480 available file. However! We only do this if their do exist *any*
481 non-source versions of the package - that way the dselect obsolete
482 handling works OK. */
483 if (VF
.end() == true)
485 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
487 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
489 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
496 if (VF
.end() == false)
504 LocalitySort(VFList
,Count
,sizeof(*VFList
));
506 // Iterate over all the package files and write them out.
507 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
508 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
510 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
511 if (File
.IsOk() == false)
513 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
517 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
518 if (_error
->PendingError() == true)
521 /* Write all of the records from this package file, since we
522 already did locality sorting we can now just seek through the
523 file in read order. We apply 1 more optimization here, since often
524 there will be < 1 byte gaps between records (for the \n) we read that
525 into the next buffer and offset a bit.. */
526 unsigned long Pos
= 0;
529 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
532 const pkgCache::VerFile
&VF
= **J
;
534 // Read the record and then write it out again.
535 unsigned long Jitter
= VF
.Offset
- Pos
;
538 if (PkgF
.Seek(VF
.Offset
) == false)
543 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
545 Buffer
[VF
.Size
+ Jitter
] = '\n';
548 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
551 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
552 const char *Zero
= 0;
553 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
554 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
556 _error
->Error("Internal Error, Unable to parse a package record");
563 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
567 Pos
= VF
.Offset
+ VF
.Size
;
571 if (_error
->PendingError() == true)
577 return !_error
->PendingError();
580 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
581 bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
583 pkgCacheFile CacheFile
;
584 pkgCache
*Cache
= CacheFile
.GetPkgCache();
585 if (unlikely(Cache
== NULL
))
588 CacheSetHelperVirtuals
helper(false);
589 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionSet::CANDIDATE
, helper
);
590 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
591 return _error
->Error(_("No packages found"));
592 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
594 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
595 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
596 bool const Important
= _config
->FindB("APT::Cache::Important", false);
597 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
598 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
599 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
600 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
601 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
602 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
603 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
604 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
605 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
606 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
608 while (verset
.empty() != true)
610 pkgCache::VerIterator Ver
= *verset
.begin();
611 verset
.erase(verset
.begin());
612 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
613 Shown
[Pkg
->ID
] = true;
615 cout
<< Pkg
.FullName(true) << endl
;
617 if (RevDepends
== true)
618 cout
<< "Reverse Depends:" << endl
;
619 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
620 D
.end() == false; D
++)
623 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
624 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
625 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
626 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
627 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break;
628 case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
629 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
630 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
633 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
635 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
638 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
644 if (ShowDepType
== true)
645 cout
<< D
.DepType() << ": ";
646 if (Trg
->VersionList
== 0)
647 cout
<< "<" << Trg
.FullName(true) << ">" << endl
;
649 cout
<< Trg
.FullName(true) << endl
;
651 if (Recurse
== true && Shown
[Trg
->ID
] == false)
653 Shown
[Trg
->ID
] = true;
654 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
659 // Display all solutions
660 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
661 pkgPrioSortList(*Cache
,List
);
662 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
664 pkgCache::VerIterator
V(*Cache
,*I
);
665 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
666 V
->ParentPkg
== D
->Package
)
668 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
670 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
672 Shown
[V
.ParentPkg()->ID
] = true;
673 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
677 if (ShowOnlyFirstOr
== true)
678 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
682 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
683 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
684 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
689 // Depends - Print out a dependency tree /*{{{*/
690 // ---------------------------------------------------------------------
692 bool Depends(CommandLine
&CmdL
)
694 return ShowDepends(CmdL
, false);
697 // RDepends - Print out a reverse dependency tree /*{{{*/
698 // ---------------------------------------------------------------------
700 bool RDepends(CommandLine
&CmdL
)
702 return ShowDepends(CmdL
, true);
705 // xvcg - Generate a graph for xvcg /*{{{*/
706 // ---------------------------------------------------------------------
707 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
709 bool XVcg(CommandLine
&CmdL
)
711 pkgCacheFile CacheFile
;
712 pkgCache
*Cache
= CacheFile
.GetPkgCache();
713 if (unlikely(Cache
== NULL
))
716 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
718 /* Normal packages are boxes
719 Pure Provides are triangles
721 rhomb are missing packages*/
722 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
724 /* Initialize the list of packages to show.
726 2 = To Show no recurse
727 3 = Emitted no recurse
730 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
731 enum TheFlags
{ForceNR
=(1<<0)};
732 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
733 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
734 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
736 // Show everything if no arguments given
737 if (CmdL
.FileList
[1] == 0)
738 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
741 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
743 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
746 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
748 if (Pkg
->VersionList
== 0)
751 if (Pkg
->ProvidesList
== 0)
752 ShapeMap
[Pkg
->ID
] = 0;
754 ShapeMap
[Pkg
->ID
] = 1;
759 if (Pkg
->ProvidesList
== 0)
760 ShapeMap
[Pkg
->ID
] = 2;
762 ShapeMap
[Pkg
->ID
] = 3;
766 // Load the list of packages from the command line into the show list
767 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
768 std::list
<APT::PackageSet::Modifier
> mods
;
769 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
770 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
771 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
772 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
774 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
775 Pkg
!= pkgsets
[0].end(); ++Pkg
)
776 Show
[Pkg
->ID
] = ToShow
;
777 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
778 Pkg
!= pkgsets
[1].end(); ++Pkg
)
780 Show
[Pkg
->ID
] = ToShow
;
781 Flags
[Pkg
->ID
] |= ForceNR
;
785 cout
<< "graph: { title: \"packages\"" << endl
<<
786 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
787 "layout_downfactor: 8" << endl
;
793 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
795 // See we need to show this package
796 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
799 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
802 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
804 // Pure Provides and missing packages have no deps!
805 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
806 Show
[Pkg
->ID
] = Done
;
808 Show
[Pkg
->ID
] = DoneNR
;
811 Show
[Pkg
->ID
] = Done
;
814 // No deps to map out
815 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
818 pkgCache::VerIterator Ver
= Pkg
.VersionList();
819 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
821 // See if anything can meet this dep
822 // Walk along the actual package providing versions
824 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
825 for (pkgCache::VerIterator I
= DPkg
.VersionList();
826 I
.end() == false && Hit
== false; I
++)
828 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
832 // Follow all provides
833 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
834 I
.end() == false && Hit
== false; I
++)
836 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
841 // Only graph critical deps
842 if (D
.IsCritical() == true)
844 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
846 // Colour the node for recursion
847 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
849 /* If a conflicts does not meet anything in the database
850 then show the relation but do not recurse */
852 (D
->Type
== pkgCache::Dep::Conflicts
||
853 D
->Type
== pkgCache::Dep::DpkgBreaks
||
854 D
->Type
== pkgCache::Dep::Obsoletes
))
856 if (Show
[D
.TargetPkg()->ID
] == None
&&
857 Show
[D
.TargetPkg()->ID
] != ToShow
)
858 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
862 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
863 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
865 Show
[D
.TargetPkg()->ID
] = ToShow
;
872 case pkgCache::Dep::Conflicts
:
873 printf("label: \"conflicts\" color: lightgreen }\n");
875 case pkgCache::Dep::DpkgBreaks
:
876 printf("label: \"breaks\" color: lightgreen }\n");
878 case pkgCache::Dep::Obsoletes
:
879 printf("label: \"obsoletes\" color: lightgreen }\n");
882 case pkgCache::Dep::PreDepends
:
883 printf("label: \"predepends\" color: blue }\n");
895 /* Draw the box colours after the fact since we can not tell what colour
896 they should be until everything is finished drawing */
897 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
899 if (Show
[Pkg
->ID
] < DoneNR
)
902 if (Show
[Pkg
->ID
] == DoneNR
)
903 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
904 Shapes
[ShapeMap
[Pkg
->ID
]]);
906 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
907 Shapes
[ShapeMap
[Pkg
->ID
]]);
919 // Dotty - Generate a graph for Dotty /*{{{*/
920 // ---------------------------------------------------------------------
921 /* Dotty is the graphvis program for generating graphs. It is a fairly
922 simple queuing algorithm that just writes dependencies and nodes.
923 http://www.research.att.com/sw/tools/graphviz/ */
924 bool Dotty(CommandLine
&CmdL
)
926 pkgCacheFile CacheFile
;
927 pkgCache
*Cache
= CacheFile
.GetPkgCache();
928 if (unlikely(Cache
== NULL
))
931 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
933 /* Normal packages are boxes
934 Pure Provides are triangles
936 Hexagons are missing packages*/
937 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
939 /* Initialize the list of packages to show.
941 2 = To Show no recurse
942 3 = Emitted no recurse
945 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
946 enum TheFlags
{ForceNR
=(1<<0)};
947 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
948 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
949 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
951 // Show everything if no arguments given
952 if (CmdL
.FileList
[1] == 0)
953 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
956 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
958 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
961 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
963 if (Pkg
->VersionList
== 0)
966 if (Pkg
->ProvidesList
== 0)
967 ShapeMap
[Pkg
->ID
] = 0;
969 ShapeMap
[Pkg
->ID
] = 1;
974 if (Pkg
->ProvidesList
== 0)
975 ShapeMap
[Pkg
->ID
] = 2;
977 ShapeMap
[Pkg
->ID
] = 3;
981 // Load the list of packages from the command line into the show list
982 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
983 std::list
<APT::PackageSet::Modifier
> mods
;
984 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
985 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
986 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
987 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
989 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
990 Pkg
!= pkgsets
[0].end(); ++Pkg
)
991 Show
[Pkg
->ID
] = ToShow
;
992 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
993 Pkg
!= pkgsets
[1].end(); ++Pkg
)
995 Show
[Pkg
->ID
] = ToShow
;
996 Flags
[Pkg
->ID
] |= ForceNR
;
1000 printf("digraph packages {\n");
1001 printf("concentrate=true;\n");
1002 printf("size=\"30,40\";\n");
1008 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1010 // See we need to show this package
1011 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1015 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1017 // Pure Provides and missing packages have no deps!
1018 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1019 Show
[Pkg
->ID
] = Done
;
1021 Show
[Pkg
->ID
] = DoneNR
;
1024 Show
[Pkg
->ID
] = Done
;
1027 // No deps to map out
1028 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1031 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1032 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
1034 // See if anything can meet this dep
1035 // Walk along the actual package providing versions
1037 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1038 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1039 I
.end() == false && Hit
== false; I
++)
1041 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1045 // Follow all provides
1046 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1047 I
.end() == false && Hit
== false; I
++)
1049 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1053 // Only graph critical deps
1054 if (D
.IsCritical() == true)
1056 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1058 // Colour the node for recursion
1059 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1061 /* If a conflicts does not meet anything in the database
1062 then show the relation but do not recurse */
1064 (D
->Type
== pkgCache::Dep::Conflicts
||
1065 D
->Type
== pkgCache::Dep::Obsoletes
))
1067 if (Show
[D
.TargetPkg()->ID
] == None
&&
1068 Show
[D
.TargetPkg()->ID
] != ToShow
)
1069 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1073 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1074 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1076 Show
[D
.TargetPkg()->ID
] = ToShow
;
1083 case pkgCache::Dep::Conflicts
:
1084 case pkgCache::Dep::Obsoletes
:
1085 printf("[color=springgreen];\n");
1088 case pkgCache::Dep::PreDepends
:
1089 printf("[color=blue];\n");
1101 /* Draw the box colours after the fact since we can not tell what colour
1102 they should be until everything is finished drawing */
1103 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1105 if (Show
[Pkg
->ID
] < DoneNR
)
1108 // Orange box for early recursion stoppage
1109 if (Show
[Pkg
->ID
] == DoneNR
)
1110 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1111 Shapes
[ShapeMap
[Pkg
->ID
]]);
1113 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1114 Shapes
[ShapeMap
[Pkg
->ID
]]);
1121 // DoAdd - Perform an adding operation /*{{{*/
1122 // ---------------------------------------------------------------------
1124 bool DoAdd(CommandLine
&CmdL
)
1126 return _error
->Error("Unimplemented");
1128 // Make sure there is at least one argument
1129 if (CmdL
.FileSize() <= 1)
1130 return _error
->Error("You must give at least one file name");
1133 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
1134 if (_error
->PendingError() == true)
1137 DynamicMMap
Map(CacheF
,MMap::Public
);
1138 if (_error
->PendingError() == true)
1141 OpTextProgress
Progress(*_config
);
1142 pkgCacheGenerator
Gen(Map
,Progress
);
1143 if (_error
->PendingError() == true)
1146 unsigned long Length
= CmdL
.FileSize() - 1;
1147 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1149 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
1150 Progress
.SubProgress(Length
);
1153 FileFd
TagF(*I
,FileFd::ReadOnly
);
1154 debListParser
Parser(TagF
);
1155 if (_error
->PendingError() == true)
1156 return _error
->Error("Problem opening %s",*I
);
1158 if (Gen
.SelectFile(*I
,"") == false)
1159 return _error
->Error("Problem with SelectFile");
1161 if (Gen
.MergeList(Parser
) == false)
1162 return _error
->Error("Problem with MergeList");
1166 GCache
= &Gen
.GetCache();
1173 // DisplayRecord - Displays the complete record for the package /*{{{*/
1174 // ---------------------------------------------------------------------
1175 /* This displays the package record from the proper package index file.
1176 It is not used by DumpAvail for performance reasons. */
1177 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1179 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1180 if (unlikely(Cache
== NULL
))
1183 // Find an appropriate file
1184 pkgCache::VerFileIterator Vf
= V
.FileList();
1185 for (; Vf
.end() == false; Vf
++)
1186 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1188 if (Vf
.end() == true)
1191 // Check and load the package list file
1192 pkgCache::PkgFileIterator I
= Vf
.File();
1193 if (I
.IsOk() == false)
1194 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1197 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnlyGzip
) == false)
1201 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1202 Buffer
[V
.FileList()->Size
] = '\n';
1203 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1204 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1210 // Get a pointer to start of Description field
1211 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1213 // Write all but Description
1214 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1220 // Show the right description
1221 pkgRecords
Recs(*Cache
);
1222 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1223 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1224 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1226 // Find the first field after the description (if there is any)
1227 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1229 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1231 // write the rest of the buffer
1232 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1233 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1242 // write a final newline (after the description)
1252 pkgCache::DescFile
*Df
;
1256 // Search - Perform a search /*{{{*/
1257 // ---------------------------------------------------------------------
1258 /* This searches the package names and package descriptions for a pattern */
1259 bool Search(CommandLine
&CmdL
)
1261 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1262 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1263 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1265 pkgCacheFile CacheFile
;
1266 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1267 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1268 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1271 // Make sure there is at least one argument
1272 if (NumPatterns
< 1)
1273 return _error
->Error(_("You must give at least one search pattern"));
1275 // Compile the regex pattern
1276 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1277 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1278 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1280 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1284 regfree(&Patterns
[I
]);
1285 return _error
->Error("Regex compilation error");
1289 if (_error
->PendingError() == true)
1291 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1292 regfree(&Patterns
[I
]);
1296 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1297 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1299 // Map versions that we want to write out onto the VerList array.
1300 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1302 if (DFList
[G
->ID
].NameMatch
== true)
1305 DFList
[G
->ID
].NameMatch
= true;
1306 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1308 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1310 DFList
[G
->ID
].NameMatch
= false;
1314 // Doing names only, drop any that dont match..
1315 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1318 // Find the proper version to use
1319 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1320 if (P
.end() == true)
1322 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1323 if (V
.end() == false)
1324 DFList
[G
->ID
].Df
= V
.TranslatedDescription().FileList();
1326 if (DFList
[G
->ID
].NameMatch
== false)
1329 // Include all the packages that provide matching names too
1330 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
1332 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1333 if (V
.end() == true)
1336 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1337 DFList
[id
].Df
= V
.TranslatedDescription().FileList();
1338 DFList
[id
].NameMatch
= true;
1342 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1344 // Create the text record parser
1345 pkgRecords
Recs(*Cache
);
1346 // Iterate over all the version records and check them
1347 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1349 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1351 if (J
->NameMatch
== false && NamesOnly
== false)
1353 string
const LongDesc
= P
.LongDesc();
1354 J
->NameMatch
= true;
1355 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1357 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1359 J
->NameMatch
= false;
1364 if (J
->NameMatch
== true)
1366 if (ShowFull
== true)
1370 P
.GetRec(Start
,End
);
1371 fwrite(Start
,End
-Start
,1,stdout
);
1375 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1380 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1381 regfree(&Patterns
[I
]);
1383 return _error
->Error("Write to stdout failed");
1388 /* show automatically installed packages (sorted) */
1389 bool ShowAuto(CommandLine
&CmdL
)
1391 pkgCacheFile CacheFile
;
1392 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1393 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1394 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1397 std::vector
<string
> packages
;
1398 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1400 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
1401 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1402 packages
.push_back(P
.Name());
1404 std::sort(packages
.begin(), packages
.end());
1406 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); I
++)
1412 // ShowPackage - Dump the package record to the screen /*{{{*/
1413 // ---------------------------------------------------------------------
1415 bool ShowPackage(CommandLine
&CmdL
)
1417 pkgCacheFile CacheFile
;
1418 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1419 APT::VersionSet::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1420 APT::VersionSet::ALL
: APT::VersionSet::CANDIDATE
;
1421 APT::VersionSet
const verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1422 for (APT::VersionSet::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1423 if (DisplayRecord(CacheFile
, Ver
) == false)
1426 if (verset
.empty() == true)
1428 if (helper
.virtualPkgs
.empty() == true)
1429 return _error
->Error(_("No packages found"));
1431 _error
->Notice(_("No packages found"));
1436 // ShowPkgNames - Show package names /*{{{*/
1437 // ---------------------------------------------------------------------
1438 /* This does a prefix match on the first argument */
1439 bool ShowPkgNames(CommandLine
&CmdL
)
1441 pkgCacheFile CacheFile
;
1442 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1444 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1445 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1447 if (CmdL
.FileList
[1] != 0)
1449 for (;I
.end() != true; I
++)
1451 if (All
== false && I
->FirstPackage
== 0)
1453 if (I
.FindPkg("any")->VersionList
== 0)
1455 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1456 cout
<< I
.Name() << endl
;
1463 for (;I
.end() != true; I
++)
1465 if (All
== false && I
->FirstPackage
== 0)
1467 if (I
.FindPkg("any")->VersionList
== 0)
1469 cout
<< I
.Name() << endl
;
1475 // ShowSrcPackage - Show source package records /*{{{*/
1476 // ---------------------------------------------------------------------
1478 bool ShowSrcPackage(CommandLine
&CmdL
)
1480 pkgCacheFile CacheFile
;
1481 pkgSourceList
*List
= CacheFile
.GetSourceList();
1482 if (unlikely(List
== NULL
))
1485 // Create the text record parsers
1486 pkgSrcRecords
SrcRecs(*List
);
1487 if (_error
->PendingError() == true)
1491 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1495 pkgSrcRecords::Parser
*Parse
;
1496 unsigned found_this
= 0;
1497 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1498 cout
<< Parse
->AsStr() << endl
;;
1502 if (found_this
== 0) {
1503 _error
->Warning(_("Unable to locate package %s"),*I
);
1508 _error
->Notice(_("No packages found"));
1512 // Policy - Show the results of the preferences file /*{{{*/
1513 // ---------------------------------------------------------------------
1515 bool Policy(CommandLine
&CmdL
)
1517 pkgCacheFile CacheFile
;
1518 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1519 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1520 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1521 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1524 /* Should the MultiArchKiller be run to see which pseudo packages for an
1525 arch all package are currently installed? Activating it gives a speed
1526 penality for no real gain beside enhanced debugging, so in general no. */
1527 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1528 CacheFile
.GetDepCache();
1530 // Print out all of the package files
1531 if (CmdL
.FileList
[1] == 0)
1533 cout
<< _("Package files:") << endl
;
1534 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
1536 // Locate the associated index files so we can derive a description
1538 if (SrcList
->FindIndex(F
,Indx
) == false &&
1539 _system
->FindIndex(F
,Indx
) == false)
1540 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1543 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1545 // Print the reference information for the package
1546 string Str
= F
.RelStr();
1547 if (Str
.empty() == false)
1548 printf(" release %s\n",F
.RelStr().c_str());
1549 if (F
.Site() != 0 && F
.Site()[0] != 0)
1550 printf(" origin %s\n",F
.Site());
1553 // Show any packages have explicit pins
1554 cout
<< _("Pinned packages:") << endl
;
1555 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1556 for (;I
.end() != true; I
++)
1558 if (Plcy
->GetPriority(I
) == 0)
1561 // Print the package name and the version we are forcing to
1562 cout
<< " " << I
.FullName(true) << " -> ";
1564 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1565 if (V
.end() == true)
1566 cout
<< _("(not found)") << endl
;
1568 cout
<< V
.VerStr() << endl
;
1574 string
const myArch
= _config
->Find("APT::Architecture");
1575 char const * const msgInstalled
= _(" Installed: ");
1576 char const * const msgCandidate
= _(" Candidate: ");
1577 short const InstalledLessCandidate
=
1578 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1579 short const deepInstalled
=
1580 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1581 short const deepCandidate
=
1582 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1584 // Print out detailed information for each package
1585 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1586 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1587 for (APT::PackageSet::const_iterator I
= pkgset
.begin(); I
!= pkgset
.end(); ++I
)
1589 pkgCache::PkgIterator Pkg
= I
.Group().FindPkg("any");
1591 for (; Pkg
.end() != true; Pkg
= I
.Group().NextPkg(Pkg
)) {
1592 if (strcmp(Pkg
.Arch(),"all") == 0)
1595 cout
<< Pkg
.FullName(true) << ":" << endl
;
1597 // Installed version
1598 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1599 if (Pkg
->CurrentVer
== 0)
1600 cout
<< _("(none)") << endl
;
1602 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1604 // Candidate Version
1605 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1606 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1607 if (V
.end() == true)
1608 cout
<< _("(none)") << endl
;
1610 cout
<< V
.VerStr() << endl
;
1613 if (Plcy
->GetPriority(Pkg
) != 0)
1615 cout
<< _(" Package pin: ");
1616 V
= Plcy
->GetMatch(Pkg
);
1617 if (V
.end() == true)
1618 cout
<< _("(not found)") << endl
;
1620 cout
<< V
.VerStr() << endl
;
1623 // Show the priority tables
1624 cout
<< _(" Version table:") << endl
;
1625 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1627 if (Pkg
.CurrentVer() == V
)
1628 cout
<< " *** " << V
.VerStr();
1630 cout
<< " " << V
.VerStr();
1631 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1632 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1634 // Locate the associated index files so we can derive a description
1636 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1637 _system
->FindIndex(VF
.File(),Indx
) == false)
1638 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1639 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1640 Indx
->Describe(true).c_str());
1649 // Madison - Look a bit like katie's madison /*{{{*/
1650 // ---------------------------------------------------------------------
1652 bool Madison(CommandLine
&CmdL
)
1654 pkgCacheFile CacheFile
;
1655 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1660 // Create the src text record parsers and ignore errors about missing
1661 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1662 pkgSrcRecords
SrcRecs(*SrcList
);
1663 if (_error
->PendingError() == true)
1666 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1667 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1669 _error
->PushToStack();
1670 APT::PackageSet pkgset
= APT::PackageSet::FromString(CacheFile
, *I
, helper
);
1671 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1673 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; V
++)
1675 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1677 // This might be nice, but wouldn't uniquely identify the source -mdz
1678 // if (VF.File().Archive() != 0)
1680 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1681 // << VF.File().Archive() << endl;
1684 // Locate the associated index files so we can derive a description
1685 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); S
++)
1687 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1688 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1689 IF
!= Indexes
->end(); IF
++)
1691 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1693 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1694 << (*IF
)->Describe(true) << endl
;
1703 pkgSrcRecords::Parser
*SrcParser
;
1704 bool foundSomething
= false;
1705 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1707 foundSomething
= true;
1708 // Maybe support Release info here too eventually
1709 cout
<< setw(10) << SrcParser
->Package() << " | "
1710 << setw(10) << SrcParser
->Version() << " | "
1711 << SrcParser
->Index().Describe(true) << endl
;
1713 if (foundSomething
== true)
1714 _error
->RevertToStack();
1716 _error
->MergeWithStack();
1722 // GenCaches - Call the main cache generator /*{{{*/
1723 // ---------------------------------------------------------------------
1725 bool GenCaches(CommandLine
&Cmd
)
1727 OpTextProgress
Progress(*_config
);
1729 pkgCacheFile CacheFile
;
1730 return CacheFile
.BuildCaches(&Progress
, true);
1733 // ShowHelp - Show a help screen /*{{{*/
1734 // ---------------------------------------------------------------------
1736 bool ShowHelp(CommandLine
&Cmd
)
1738 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1739 COMMON_ARCH
,__DATE__
,__TIME__
);
1741 if (_config
->FindB("version") == true)
1745 _("Usage: apt-cache [options] command\n"
1746 " apt-cache [options] add file1 [file2 ...]\n"
1747 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1748 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1750 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1751 "cache files, and query information from them\n"
1754 " add - Add a package file to the source cache\n"
1755 " gencaches - Build both the package and source cache\n"
1756 " showpkg - Show some general information for a single package\n"
1757 " showsrc - Show source records\n"
1758 " stats - Show some basic statistics\n"
1759 " dump - Show the entire file in a terse form\n"
1760 " dumpavail - Print an available file to stdout\n"
1761 " unmet - Show unmet dependencies\n"
1762 " search - Search the package list for a regex pattern\n"
1763 " show - Show a readable record for the package\n"
1764 " showauto - Display a list of automatically installed packages\n"
1765 " depends - Show raw dependency information for a package\n"
1766 " rdepends - Show reverse dependency information for a package\n"
1767 " pkgnames - List the names of all packages in the system\n"
1768 " dotty - Generate package graphs for GraphViz\n"
1769 " xvcg - Generate package graphs for xvcg\n"
1770 " policy - Show policy settings\n"
1773 " -h This help text.\n"
1774 " -p=? The package cache.\n"
1775 " -s=? The source cache.\n"
1776 " -q Disable progress indicator.\n"
1777 " -i Show only important deps for the unmet command.\n"
1778 " -c=? Read this configuration file\n"
1779 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1780 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1784 int main(int argc
,const char *argv
[]) /*{{{*/
1786 CommandLine::Args Args
[] = {
1787 {'h',"help","help",0},
1788 {'v',"version","version",0},
1789 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1790 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1791 {'q',"quiet","quiet",CommandLine::IntLevel
},
1792 {'i',"important","APT::Cache::Important",0},
1793 {'f',"full","APT::Cache::ShowFull",0},
1794 {'g',"generate","APT::Cache::Generate",0},
1795 {'a',"all-versions","APT::Cache::AllVersions",0},
1796 {'n',"names-only","APT::Cache::NamesOnly",0},
1797 {0,"all-names","APT::Cache::AllNames",0},
1798 {0,"recurse","APT::Cache::RecurseDepends",0},
1799 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1800 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1801 {'c',"config-file",0,CommandLine::ConfigFile
},
1802 {'o',"option",0,CommandLine::ArbItem
},
1803 {0,"installed","APT::Cache::Installed",0},
1804 {0,"pre-depends","APT::Cache::ShowPreDepends",0},
1805 {0,"depends","APT::Cache::ShowDepends",0},
1806 {0,"recommends","APT::Cache::ShowRecommends",0},
1807 {0,"suggests","APT::Cache::ShowSuggests",0},
1808 {0,"replaces","APT::Cache::ShowReplaces",0},
1809 {0,"breaks","APT::Cache::ShowBreaks",0},
1810 {0,"conflicts","APT::Cache::ShowConflicts",0},
1811 {0,"enhances","APT::Cache::ShowEnhances",0},
1813 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1815 {"gencaches",&GenCaches
},
1816 {"showsrc",&ShowSrcPackage
},
1818 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1821 {"dumpavail",&DumpAvail
},
1824 {"depends",&Depends
},
1825 {"rdepends",&RDepends
},
1828 {"show",&ShowPackage
},
1829 {"pkgnames",&ShowPkgNames
},
1830 {"showauto",&ShowAuto
},
1832 {"madison",&Madison
},
1835 // Set up gettext support
1836 setlocale(LC_ALL
,"");
1837 textdomain(PACKAGE
);
1839 // Parse the command line and initialize the package library
1840 CommandLine
CmdL(Args
,_config
);
1841 if (pkgInitConfig(*_config
) == false ||
1842 CmdL
.Parse(argc
,argv
) == false ||
1843 pkgInitSystem(*_config
,_system
) == false)
1845 _error
->DumpErrors();
1849 // See if the help should be shown
1850 if (_config
->FindB("help") == true ||
1851 CmdL
.FileSize() == 0)
1857 // Deal with stdout not being a tty
1858 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1859 _config
->Set("quiet","1");
1861 if (_config
->Exists("APT::Cache::Generate") == true)
1862 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1864 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1865 CmdL
.DispatchArg(CmdsB
);
1867 // Print any errors or warnings found during parsing
1868 bool const Errors
= _error
->PendingError();
1869 if (_config
->FindI("quiet",0) > 0)
1870 _error
->DumpErrors();
1872 _error
->DumpErrors(GlobalError::DEBUG
);
1873 return Errors
== true ? 100 : 0;