]>
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 /*{{{*/
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/init.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/cmndline.h>
25 #include <apt-pkg/strutl.h>
26 #include <apt-pkg/fileutl.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/srcrecords.h>
29 #include <apt-pkg/version.h>
30 #include <apt-pkg/policy.h>
31 #include <apt-pkg/tagfile.h>
32 #include <apt-pkg/algorithms.h>
33 #include <apt-pkg/sptr.h>
34 #include <apt-pkg/pkgsystem.h>
35 #include <apt-pkg/indexfile.h>
36 #include <apt-pkg/metaindex.h>
38 #include <apt-private/private-list.h>
39 #include <apt-private/private-cmndline.h>
40 #include <apt-private/private-show.h>
41 #include <apt-private/private-cacheset.h>
58 // LocalitySort - Sort a version list by package file locality /*{{{*/
59 // ---------------------------------------------------------------------
61 int LocalityCompare(const void *a
, const void *b
)
63 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
64 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
73 if (A
->File
== B
->File
)
74 return A
->Offset
- B
->Offset
;
75 return A
->File
- B
->File
;
78 void LocalitySort(pkgCache::VerFile
**begin
,
79 unsigned long Count
,size_t Size
)
81 qsort(begin
,Count
,Size
,LocalityCompare
);
84 void LocalitySort(pkgCache::DescFile
**begin
,
85 unsigned long Count
,size_t Size
)
87 qsort(begin
,Count
,Size
,LocalityCompare
);
90 // UnMet - Show unmet dependencies /*{{{*/
91 // ---------------------------------------------------------------------
93 bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const Important
)
96 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
99 pkgCache::DepIterator Start
;
100 pkgCache::DepIterator End
;
103 // Important deps only
104 if (Important
== true)
105 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
106 End
->Type
!= pkgCache::Dep::Depends
)
109 // Skip conflicts and replaces
110 if (End
.IsNegative() == true)
113 // Verify the or group
115 pkgCache::DepIterator RealStart
= Start
;
118 // See if this dep is Ok
119 pkgCache::Version
**VList
= Start
.AllTargets();
140 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
141 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
144 // Print out the dep type
145 cout
<< " " << End
.DepType() << ": ";
151 cout
<< Start
.TargetPkg().FullName(true);
152 if (Start
.TargetVer() != 0)
153 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
166 bool UnMet(CommandLine
&CmdL
)
168 bool const Important
= _config
->FindB("APT::Cache::Important",false);
170 pkgCacheFile CacheFile
;
171 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
174 if (CmdL
.FileSize() <= 1)
176 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; ++P
)
177 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
178 if (ShowUnMet(V
, Important
) == false)
183 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
184 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
185 APT::VersionList::CANDIDATE
, helper
);
186 for (APT::VersionList::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
187 if (ShowUnMet(V
, Important
) == false)
193 // DumpPackage - Show a dump of a package record /*{{{*/
194 // ---------------------------------------------------------------------
196 bool DumpPackage(CommandLine
&CmdL
)
198 pkgCacheFile CacheFile
;
199 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
200 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
202 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
204 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
205 cout
<< "Versions: " << endl
;
206 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
208 cout
<< Cur
.VerStr();
209 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
210 cout
<< " (" << Vf
.File().FileName() << ")";
212 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
214 cout
<< " Description Language: " << D
.LanguageCode() << endl
215 << " File: " << D
.FileList().File().FileName() << endl
216 << " MD5: " << D
.md5() << endl
;
223 cout
<< "Reverse Depends: " << endl
;
224 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
226 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
228 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
233 cout
<< "Dependencies: " << endl
;
234 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
236 cout
<< Cur
.VerStr() << " - ";
237 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; ++Dep
)
238 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
242 cout
<< "Provides: " << endl
;
243 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
245 cout
<< Cur
.VerStr() << " - ";
246 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
247 cout
<< Prv
.ParentPkg().FullName(true) << " ";
250 cout
<< "Reverse Provides: " << endl
;
251 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
252 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
258 // Stats - Dump some nice statistics /*{{{*/
259 // ---------------------------------------------------------------------
261 bool Stats(CommandLine
&Cmd
)
263 pkgCacheFile CacheFile
;
264 pkgCache
*Cache
= CacheFile
.GetPkgCache();
265 if (unlikely(Cache
== NULL
))
268 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
269 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
270 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
271 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
278 pkgCache::PkgIterator I
= Cache
->PkgBegin();
279 for (;I
.end() != true; ++I
)
281 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
287 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
293 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
296 if (I
.ProvidesList()->NextProvides
== 0)
304 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
310 cout
<< _(" Normal packages: ") << Normal
<< endl
;
311 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
312 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
313 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
314 cout
<< _(" Missing: ") << Missing
<< endl
;
316 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
317 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
318 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
319 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
320 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
321 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
323 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
324 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
325 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
326 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
327 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
328 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
331 unsigned long Size
= 0;
332 unsigned long Count
= 0;
333 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
334 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
337 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
339 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
341 unsigned long DepVerSize
= 0;
342 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
344 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
346 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
349 DepVerSize
+= strlen(D
.TargetVer()) + 1;
353 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
355 unsigned long Slack
= 0;
356 for (int I
= 0; I
!= 7; I
++)
357 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
358 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
360 unsigned long Total
= 0;
361 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
362 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
363 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
364 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
365 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
366 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
371 // Dump - show everything /*{{{*/
372 // ---------------------------------------------------------------------
373 /* This is worthless except fer debugging things */
374 bool Dump(CommandLine
&Cmd
)
376 pkgCacheFile CacheFile
;
377 pkgCache
*Cache
= CacheFile
.GetPkgCache();
378 if (unlikely(Cache
== NULL
))
381 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
383 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
385 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
386 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
388 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
389 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
390 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
391 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
392 DeNull(D
.TargetVer()) << std::endl
;
393 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
395 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
396 << " File: " << D
.FileList().File().FileName() << std::endl
397 << " MD5: " << D
.md5() << std::endl
;
402 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
404 std::cout
<< "File: " << F
.FileName() << std::endl
;
405 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
406 std::cout
<< " Size: " << F
->Size
<< std::endl
;
407 std::cout
<< " ID: " << F
->ID
<< std::endl
;
408 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
409 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
410 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
411 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
412 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
413 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
414 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
415 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
416 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
422 // DumpAvail - Print out the available list /*{{{*/
423 // ---------------------------------------------------------------------
424 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
425 make this run really fast, perhaps I went a little overboard.. */
426 bool DumpAvail(CommandLine
&Cmd
)
428 pkgCacheFile CacheFile
;
429 pkgCache
*Cache
= CacheFile
.GetPkgCache();
430 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
433 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
434 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
435 memset(VFList
,0,sizeof(*VFList
)*Count
);
437 // Map versions that we want to write out onto the VerList array.
438 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
440 if (P
->VersionList
== 0)
443 /* Find the proper version to use. If the policy says there are no
444 possible selections we return the installed version, if available..
445 This prevents dselect from making it obsolete. */
446 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
449 if (P
->CurrentVer
== 0)
454 pkgCache::VerFileIterator VF
= V
.FileList();
455 for (; VF
.end() == false ; ++VF
)
456 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
459 /* Okay, here we have a bit of a problem.. The policy has selected the
460 currently installed package - however it only exists in the
461 status file.. We need to write out something or dselect will mark
462 the package as obsolete! Thus we emit the status file entry, but
463 below we remove the status line to make it valid for the
464 available file. However! We only do this if their do exist *any*
465 non-source versions of the package - that way the dselect obsolete
466 handling works OK. */
467 if (VF
.end() == true)
469 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
471 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
473 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
480 if (VF
.end() == false)
488 LocalitySort(VFList
,Count
,sizeof(*VFList
));
490 // Iterate over all the package files and write them out.
491 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
492 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
494 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
495 if (File
.IsOk() == false)
497 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
501 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
502 if (_error
->PendingError() == true)
505 /* Write all of the records from this package file, since we
506 already did locality sorting we can now just seek through the
507 file in read order. We apply 1 more optimization here, since often
508 there will be < 1 byte gaps between records (for the \n) we read that
509 into the next buffer and offset a bit.. */
510 unsigned long Pos
= 0;
513 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
516 const pkgCache::VerFile
&VF
= **J
;
518 // Read the record and then write it out again.
519 unsigned long Jitter
= VF
.Offset
- Pos
;
522 if (PkgF
.Seek(VF
.Offset
) == false)
527 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
529 Buffer
[VF
.Size
+ Jitter
] = '\n';
532 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
535 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
536 const char *Zero
= 0;
537 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
538 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
540 _error
->Error("Internal Error, Unable to parse a package record");
547 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
551 Pos
= VF
.Offset
+ VF
.Size
;
555 if (_error
->PendingError() == true)
561 return !_error
->PendingError();
564 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
565 bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
567 pkgCacheFile CacheFile
;
568 pkgCache
*Cache
= CacheFile
.GetPkgCache();
569 if (unlikely(Cache
== NULL
))
572 CacheSetHelperVirtuals
helper(false);
573 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionList::CANDIDATE
, helper
);
574 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
575 return _error
->Error(_("No packages found"));
576 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
578 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
579 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
580 bool const Important
= _config
->FindB("APT::Cache::Important", false);
581 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
582 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
583 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
584 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
585 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
586 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
587 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
588 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
589 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
590 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
591 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
593 while (verset
.empty() != true)
595 pkgCache::VerIterator Ver
= *verset
.begin();
596 verset
.erase(verset
.begin());
597 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
598 Shown
[Pkg
->ID
] = true;
600 cout
<< Pkg
.FullName(true) << endl
;
602 if (RevDepends
== true)
603 cout
<< "Reverse Depends:" << endl
;
604 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
605 D
.end() == false; ++D
)
608 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
609 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
610 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
611 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
612 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
613 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
614 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
617 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
619 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
622 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
628 if (ShowDepType
== true)
629 cout
<< D
.DepType() << ": ";
630 if (Trg
->VersionList
== 0)
631 cout
<< "<" << Trg
.FullName(true) << ">";
633 cout
<< Trg
.FullName(true);
634 if (ShowVersion
== true && D
->Version
!= 0)
635 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
638 if (Recurse
== true && Shown
[Trg
->ID
] == false)
640 Shown
[Trg
->ID
] = true;
641 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
646 // Display all solutions
647 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
648 pkgPrioSortList(*Cache
,List
);
649 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
651 pkgCache::VerIterator
V(*Cache
,*I
);
652 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
653 V
->ParentPkg
== D
->Package
)
655 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
657 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
659 Shown
[V
.ParentPkg()->ID
] = true;
660 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
664 if (ShowOnlyFirstOr
== true)
665 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
669 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
670 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
671 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
676 // Depends - Print out a dependency tree /*{{{*/
677 // ---------------------------------------------------------------------
679 bool Depends(CommandLine
&CmdL
)
681 return ShowDepends(CmdL
, false);
684 // RDepends - Print out a reverse dependency tree /*{{{*/
685 // ---------------------------------------------------------------------
687 bool RDepends(CommandLine
&CmdL
)
689 return ShowDepends(CmdL
, true);
692 // xvcg - Generate a graph for xvcg /*{{{*/
693 // ---------------------------------------------------------------------
694 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
696 bool XVcg(CommandLine
&CmdL
)
698 pkgCacheFile CacheFile
;
699 pkgCache
*Cache
= CacheFile
.GetPkgCache();
700 if (unlikely(Cache
== NULL
))
703 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
705 /* Normal packages are boxes
706 Pure Provides are triangles
708 rhomb are missing packages*/
709 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
711 /* Initialize the list of packages to show.
713 2 = To Show no recurse
714 3 = Emitted no recurse
717 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
718 enum TheFlags
{ForceNR
=(1<<0)};
719 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
720 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
721 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
723 // Show everything if no arguments given
724 if (CmdL
.FileList
[1] == 0)
725 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
728 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
730 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
733 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
735 if (Pkg
->VersionList
== 0)
738 if (Pkg
->ProvidesList
== 0)
739 ShapeMap
[Pkg
->ID
] = 0;
741 ShapeMap
[Pkg
->ID
] = 1;
746 if (Pkg
->ProvidesList
== 0)
747 ShapeMap
[Pkg
->ID
] = 2;
749 ShapeMap
[Pkg
->ID
] = 3;
753 // Load the list of packages from the command line into the show list
754 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
755 std::list
<APT::PackageSet::Modifier
> mods
;
756 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
757 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
758 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
759 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
761 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
762 Pkg
!= pkgsets
[0].end(); ++Pkg
)
763 Show
[Pkg
->ID
] = ToShow
;
764 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
765 Pkg
!= pkgsets
[1].end(); ++Pkg
)
767 Show
[Pkg
->ID
] = ToShow
;
768 Flags
[Pkg
->ID
] |= ForceNR
;
772 cout
<< "graph: { title: \"packages\"" << endl
<<
773 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
774 "layout_downfactor: 8" << endl
;
780 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
782 // See we need to show this package
783 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
786 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
789 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
791 // Pure Provides and missing packages have no deps!
792 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
793 Show
[Pkg
->ID
] = Done
;
795 Show
[Pkg
->ID
] = DoneNR
;
798 Show
[Pkg
->ID
] = Done
;
801 // No deps to map out
802 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
805 pkgCache::VerIterator Ver
= Pkg
.VersionList();
806 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
808 // See if anything can meet this dep
809 // Walk along the actual package providing versions
811 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
812 for (pkgCache::VerIterator I
= DPkg
.VersionList();
813 I
.end() == false && Hit
== false; ++I
)
815 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
819 // Follow all provides
820 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
821 I
.end() == false && Hit
== false; ++I
)
823 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
828 // Only graph critical deps
829 if (D
.IsCritical() == true)
831 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
833 // Colour the node for recursion
834 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
836 /* If a conflicts does not meet anything in the database
837 then show the relation but do not recurse */
838 if (Hit
== false && D
.IsNegative() == true)
840 if (Show
[D
.TargetPkg()->ID
] == None
&&
841 Show
[D
.TargetPkg()->ID
] != ToShow
)
842 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
846 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
847 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
849 Show
[D
.TargetPkg()->ID
] = ToShow
;
856 case pkgCache::Dep::Conflicts
:
857 printf("label: \"conflicts\" color: lightgreen }\n");
859 case pkgCache::Dep::DpkgBreaks
:
860 printf("label: \"breaks\" color: lightgreen }\n");
862 case pkgCache::Dep::Obsoletes
:
863 printf("label: \"obsoletes\" color: lightgreen }\n");
866 case pkgCache::Dep::PreDepends
:
867 printf("label: \"predepends\" color: blue }\n");
879 /* Draw the box colours after the fact since we can not tell what colour
880 they should be until everything is finished drawing */
881 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
883 if (Show
[Pkg
->ID
] < DoneNR
)
886 if (Show
[Pkg
->ID
] == DoneNR
)
887 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
888 Shapes
[ShapeMap
[Pkg
->ID
]]);
890 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
891 Shapes
[ShapeMap
[Pkg
->ID
]]);
903 // Dotty - Generate a graph for Dotty /*{{{*/
904 // ---------------------------------------------------------------------
905 /* Dotty is the graphvis program for generating graphs. It is a fairly
906 simple queuing algorithm that just writes dependencies and nodes.
907 http://www.research.att.com/sw/tools/graphviz/ */
908 bool Dotty(CommandLine
&CmdL
)
910 pkgCacheFile CacheFile
;
911 pkgCache
*Cache
= CacheFile
.GetPkgCache();
912 if (unlikely(Cache
== NULL
))
915 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
917 /* Normal packages are boxes
918 Pure Provides are triangles
920 Hexagons are missing packages*/
921 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
923 /* Initialize the list of packages to show.
925 2 = To Show no recurse
926 3 = Emitted no recurse
929 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
930 enum TheFlags
{ForceNR
=(1<<0)};
931 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
932 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
933 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
935 // Show everything if no arguments given
936 if (CmdL
.FileList
[1] == 0)
937 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
940 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
942 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
945 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
947 if (Pkg
->VersionList
== 0)
950 if (Pkg
->ProvidesList
== 0)
951 ShapeMap
[Pkg
->ID
] = 0;
953 ShapeMap
[Pkg
->ID
] = 1;
958 if (Pkg
->ProvidesList
== 0)
959 ShapeMap
[Pkg
->ID
] = 2;
961 ShapeMap
[Pkg
->ID
] = 3;
965 // Load the list of packages from the command line into the show list
966 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
967 std::list
<APT::PackageSet::Modifier
> mods
;
968 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
969 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
970 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
971 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
973 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
974 Pkg
!= pkgsets
[0].end(); ++Pkg
)
975 Show
[Pkg
->ID
] = ToShow
;
976 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
977 Pkg
!= pkgsets
[1].end(); ++Pkg
)
979 Show
[Pkg
->ID
] = ToShow
;
980 Flags
[Pkg
->ID
] |= ForceNR
;
984 printf("digraph packages {\n");
985 printf("concentrate=true;\n");
986 printf("size=\"30,40\";\n");
992 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
994 // See we need to show this package
995 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
999 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1001 // Pure Provides and missing packages have no deps!
1002 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1003 Show
[Pkg
->ID
] = Done
;
1005 Show
[Pkg
->ID
] = DoneNR
;
1008 Show
[Pkg
->ID
] = Done
;
1011 // No deps to map out
1012 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1015 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1016 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1018 // See if anything can meet this dep
1019 // Walk along the actual package providing versions
1021 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1022 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1023 I
.end() == false && Hit
== false; ++I
)
1025 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1029 // Follow all provides
1030 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1031 I
.end() == false && Hit
== false; ++I
)
1033 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1037 // Only graph critical deps
1038 if (D
.IsCritical() == true)
1040 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1042 // Colour the node for recursion
1043 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1045 /* If a conflicts does not meet anything in the database
1046 then show the relation but do not recurse */
1047 if (Hit
== false && D
.IsNegative() == true)
1049 if (Show
[D
.TargetPkg()->ID
] == None
&&
1050 Show
[D
.TargetPkg()->ID
] != ToShow
)
1051 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1055 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1056 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1058 Show
[D
.TargetPkg()->ID
] = ToShow
;
1065 case pkgCache::Dep::Conflicts
:
1066 case pkgCache::Dep::Obsoletes
:
1067 case pkgCache::Dep::DpkgBreaks
:
1068 printf("[color=springgreen];\n");
1071 case pkgCache::Dep::PreDepends
:
1072 printf("[color=blue];\n");
1084 /* Draw the box colours after the fact since we can not tell what colour
1085 they should be until everything is finished drawing */
1086 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1088 if (Show
[Pkg
->ID
] < DoneNR
)
1091 // Orange box for early recursion stoppage
1092 if (Show
[Pkg
->ID
] == DoneNR
)
1093 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1094 Shapes
[ShapeMap
[Pkg
->ID
]]);
1096 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1097 Shapes
[ShapeMap
[Pkg
->ID
]]);
1107 // DisplayRecord - Displays the complete record for the package /*{{{*/
1108 // ---------------------------------------------------------------------
1109 /* This displays the package record from the proper package index file.
1110 It is not used by DumpAvail for performance reasons. */
1112 static unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1114 char const * const TagName
= "\nDescription";
1115 size_t const TagLen
= strlen(TagName
);
1116 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1118 if (DescP
[1] == ' ')
1120 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1129 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1131 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1132 if (unlikely(Cache
== NULL
))
1135 // Find an appropriate file
1136 pkgCache::VerFileIterator Vf
= V
.FileList();
1137 for (; Vf
.end() == false; ++Vf
)
1138 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1140 if (Vf
.end() == true)
1143 // Check and load the package list file
1144 pkgCache::PkgFileIterator I
= Vf
.File();
1145 if (I
.IsOk() == false)
1146 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1149 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1152 // Read the record (and ensure that it ends with a newline and NUL)
1153 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1154 Buffer
[Vf
->Size
] = '\n';
1155 Buffer
[Vf
->Size
+1] = '\0';
1156 if (PkgF
.Seek(Vf
->Offset
) == false ||
1157 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1163 // Get a pointer to start of Description field
1164 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1168 DescP
= Buffer
+ Vf
->Size
;
1170 // Write all but Description
1171 size_t const length
= DescP
- Buffer
;
1172 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1178 // Show the right description
1179 pkgRecords
Recs(*Cache
);
1180 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1181 if (Desc
.end() == false)
1183 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1184 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1185 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1187 // Find the first field after the description (if there is any)
1188 DescP
= skipDescriptionFields(DescP
);
1190 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1192 // write the rest of the buffer, but skip mixed in Descriptions* fields
1193 while (DescP
!= NULL
)
1195 const unsigned char * const Start
= DescP
;
1196 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1199 End
= &Buffer
[Vf
->Size
];
1204 ++End
; // get the newline into the output
1205 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1207 size_t const length
= End
- Start
;
1208 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1215 // write a final newline after the last field
1224 pkgCache::DescFile
*Df
;
1228 // Search - Perform a search /*{{{*/
1229 // ---------------------------------------------------------------------
1230 /* This searches the package names and package descriptions for a pattern */
1231 bool Search(CommandLine
&CmdL
)
1233 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1234 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1235 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1237 pkgCacheFile CacheFile
;
1238 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1239 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1240 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1243 // Make sure there is at least one argument
1244 if (NumPatterns
< 1)
1245 return _error
->Error(_("You must give at least one search pattern"));
1247 // Compile the regex pattern
1248 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1249 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1250 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1252 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1256 regfree(&Patterns
[I
]);
1257 return _error
->Error("Regex compilation error");
1261 if (_error
->PendingError() == true)
1263 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1264 regfree(&Patterns
[I
]);
1268 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1269 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1270 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1272 bool PatternMatch
[descCount
* NumPatterns
];
1273 memset(PatternMatch
,false,sizeof(PatternMatch
));
1275 // Map versions that we want to write out onto the VerList array.
1276 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1278 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1279 size_t unmatched
= 0, matched
= 0;
1280 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1282 if (PatternMatch
[PatternOffset
+ I
] == true)
1284 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1285 PatternMatch
[PatternOffset
+ I
] = true;
1290 // already dealt with this package?
1291 if (matched
== NumPatterns
)
1294 // Doing names only, drop any that don't match..
1295 if (NamesOnly
== true && unmatched
== NumPatterns
)
1298 // Find the proper version to use
1299 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1300 if (P
.end() == true)
1302 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1303 if (V
.end() == false)
1305 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1306 //FIXME: packages without a description can't be found
1307 if (D
.end() == true)
1309 DFList
[G
->ID
].Df
= D
.FileList();
1310 DFList
[G
->ID
].ID
= G
->ID
;
1313 if (unmatched
== NumPatterns
)
1316 // Include all the packages that provide matching names too
1317 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1319 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1320 if (V
.end() == true)
1323 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1324 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1325 //FIXME: packages without a description can't be found
1326 if (D
.end() == true)
1328 DFList
[id
].Df
= D
.FileList();
1331 size_t const PrvPatternOffset
= id
* NumPatterns
;
1332 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1333 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1337 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1339 // Create the text record parser
1340 pkgRecords
Recs(*Cache
);
1341 // Iterate over all the version records and check them
1342 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1344 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1345 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1347 if (NamesOnly
== false)
1349 string
const LongDesc
= P
.LongDesc();
1350 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1352 if (PatternMatch
[PatternOffset
+ I
] == true)
1354 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1355 PatternMatch
[PatternOffset
+ I
] = true;
1359 bool matchedAll
= true;
1360 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1361 if (PatternMatch
[PatternOffset
+ I
] == false)
1367 if (matchedAll
== true)
1369 if (ShowFull
== true)
1373 P
.GetRec(Start
,End
);
1374 fwrite(Start
,End
-Start
,1,stdout
);
1378 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1383 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1384 regfree(&Patterns
[I
]);
1386 return _error
->Error("Write to stdout failed");
1390 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1391 bool ShowAuto(CommandLine
&CmdL
)
1393 pkgCacheFile CacheFile
;
1394 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1395 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1396 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1399 std::vector
<string
> packages
;
1400 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1402 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1403 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1404 packages
.push_back(P
.Name());
1406 std::sort(packages
.begin(), packages
.end());
1408 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1411 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1415 // ShowPackage - Dump the package record to the screen /*{{{*/
1416 // ---------------------------------------------------------------------
1418 bool ShowPackage(CommandLine
&CmdL
)
1420 pkgCacheFile CacheFile
;
1421 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1422 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1423 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1424 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1425 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1426 if (DisplayRecord(CacheFile
, Ver
) == false)
1429 if (verset
.empty() == true)
1431 if (helper
.virtualPkgs
.empty() == true)
1432 return _error
->Error(_("No packages found"));
1434 _error
->Notice(_("No packages found"));
1439 // ShowPkgNames - Show package names /*{{{*/
1440 // ---------------------------------------------------------------------
1441 /* This does a prefix match on the first argument */
1442 bool ShowPkgNames(CommandLine
&CmdL
)
1444 pkgCacheFile CacheFile
;
1445 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1447 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1448 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1450 if (CmdL
.FileList
[1] != 0)
1452 for (;I
.end() != true; ++I
)
1454 if (All
== false && I
->FirstPackage
== 0)
1456 if (I
.FindPkg("any")->VersionList
== 0)
1458 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1459 cout
<< I
.Name() << endl
;
1466 for (;I
.end() != true; ++I
)
1468 if (All
== false && I
->FirstPackage
== 0)
1470 if (I
.FindPkg("any")->VersionList
== 0)
1472 cout
<< I
.Name() << endl
;
1478 // ShowSrcPackage - Show source package records /*{{{*/
1479 // ---------------------------------------------------------------------
1481 bool ShowSrcPackage(CommandLine
&CmdL
)
1483 pkgCacheFile CacheFile
;
1484 pkgSourceList
*List
= CacheFile
.GetSourceList();
1485 if (unlikely(List
== NULL
))
1488 // Create the text record parsers
1489 pkgSrcRecords
SrcRecs(*List
);
1490 if (_error
->PendingError() == true)
1494 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1498 pkgSrcRecords::Parser
*Parse
;
1499 unsigned found_this
= 0;
1500 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1501 cout
<< Parse
->AsStr() << endl
;;
1505 if (found_this
== 0) {
1506 _error
->Warning(_("Unable to locate package %s"),*I
);
1511 _error
->Notice(_("No packages found"));
1515 // Policy - Show the results of the preferences file /*{{{*/
1516 // ---------------------------------------------------------------------
1518 bool Policy(CommandLine
&CmdL
)
1520 pkgCacheFile CacheFile
;
1521 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1522 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1523 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1524 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1527 /* Should the MultiArchKiller be run to see which pseudo packages for an
1528 arch all package are currently installed? Activating it gives a speed
1529 penality for no real gain beside enhanced debugging, so in general no. */
1530 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1531 CacheFile
.GetDepCache();
1533 // Print out all of the package files
1534 if (CmdL
.FileList
[1] == 0)
1536 cout
<< _("Package files:") << endl
;
1537 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1539 // Locate the associated index files so we can derive a description
1541 if (SrcList
->FindIndex(F
,Indx
) == false &&
1542 _system
->FindIndex(F
,Indx
) == false)
1543 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1546 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1548 // Print the reference information for the package
1549 string Str
= F
.RelStr();
1550 if (Str
.empty() == false)
1551 printf(" release %s\n",F
.RelStr().c_str());
1552 if (F
.Site() != 0 && F
.Site()[0] != 0)
1553 printf(" origin %s\n",F
.Site());
1556 // Show any packages have explicit pins
1557 cout
<< _("Pinned packages:") << endl
;
1558 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1559 for (;I
.end() != true; ++I
)
1561 if (Plcy
->GetPriority(I
) == 0)
1564 // Print the package name and the version we are forcing to
1565 cout
<< " " << I
.FullName(true) << " -> ";
1567 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1568 if (V
.end() == true)
1569 cout
<< _("(not found)") << endl
;
1571 cout
<< V
.VerStr() << endl
;
1577 char const * const msgInstalled
= _(" Installed: ");
1578 char const * const msgCandidate
= _(" Candidate: ");
1579 short const InstalledLessCandidate
=
1580 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1581 short const deepInstalled
=
1582 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1583 short const deepCandidate
=
1584 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1586 // Print out detailed information for each package
1587 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1588 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1589 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1591 cout
<< Pkg
.FullName(true) << ":" << endl
;
1593 // Installed version
1594 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1595 if (Pkg
->CurrentVer
== 0)
1596 cout
<< _("(none)") << endl
;
1598 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1600 // Candidate Version
1601 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1602 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1603 if (V
.end() == true)
1604 cout
<< _("(none)") << endl
;
1606 cout
<< V
.VerStr() << endl
;
1609 if (Plcy
->GetPriority(Pkg
) != 0)
1611 cout
<< _(" Package pin: ");
1612 V
= Plcy
->GetMatch(Pkg
);
1613 if (V
.end() == true)
1614 cout
<< _("(not found)") << endl
;
1616 cout
<< V
.VerStr() << endl
;
1619 // Show the priority tables
1620 cout
<< _(" Version table:") << endl
;
1621 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1623 if (Pkg
.CurrentVer() == V
)
1624 cout
<< " *** " << V
.VerStr();
1626 cout
<< " " << V
.VerStr();
1627 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1628 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1630 // Locate the associated index files so we can derive a description
1632 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1633 _system
->FindIndex(VF
.File(),Indx
) == false)
1634 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1635 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1636 Indx
->Describe(true).c_str());
1644 // Madison - Look a bit like katie's madison /*{{{*/
1645 // ---------------------------------------------------------------------
1647 bool Madison(CommandLine
&CmdL
)
1649 pkgCacheFile CacheFile
;
1650 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1655 // Create the src text record parsers and ignore errors about missing
1656 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1657 pkgSrcRecords
SrcRecs(*SrcList
);
1658 if (_error
->PendingError() == true)
1661 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1662 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1664 _error
->PushToStack();
1665 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1666 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1668 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1670 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1672 // This might be nice, but wouldn't uniquely identify the source -mdz
1673 // if (VF.File().Archive() != 0)
1675 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1676 // << VF.File().Archive() << endl;
1679 // Locate the associated index files so we can derive a description
1680 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1682 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1683 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1684 IF
!= Indexes
->end(); ++IF
)
1686 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1688 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1689 << (*IF
)->Describe(true) << endl
;
1698 pkgSrcRecords::Parser
*SrcParser
;
1699 bool foundSomething
= false;
1700 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1702 foundSomething
= true;
1703 // Maybe support Release info here too eventually
1704 cout
<< setw(10) << SrcParser
->Package() << " | "
1705 << setw(10) << SrcParser
->Version() << " | "
1706 << SrcParser
->Index().Describe(true) << endl
;
1708 if (foundSomething
== true)
1709 _error
->RevertToStack();
1711 _error
->MergeWithStack();
1717 // GenCaches - Call the main cache generator /*{{{*/
1718 // ---------------------------------------------------------------------
1720 bool GenCaches(CommandLine
&Cmd
)
1722 OpTextProgress
Progress(*_config
);
1724 pkgCacheFile CacheFile
;
1725 return CacheFile
.BuildCaches(&Progress
, true);
1728 // ShowHelp - Show a help screen /*{{{*/
1729 // ---------------------------------------------------------------------
1731 bool ShowHelp(CommandLine
&Cmd
)
1733 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1734 COMMON_ARCH
,__DATE__
,__TIME__
);
1736 if (_config
->FindB("version") == true)
1740 _("Usage: apt-cache [options] command\n"
1741 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1742 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1744 "apt-cache is a low-level tool used to query information\n"
1745 "from APT's binary cache files\n"
1748 " gencaches - Build both the package and source cache\n"
1749 " showpkg - Show some general information for a single package\n"
1750 " showsrc - Show source records\n"
1751 " stats - Show some basic statistics\n"
1752 " dump - Show the entire file in a terse form\n"
1753 " dumpavail - Print an available file to stdout\n"
1754 " unmet - Show unmet dependencies\n"
1755 " search - Search the package list for a regex pattern\n"
1756 " show - Show a readable record for the package\n"
1757 " depends - Show raw dependency information for a package\n"
1758 " rdepends - Show reverse dependency information for a package\n"
1759 " pkgnames - List the names of all packages in the system\n"
1760 " dotty - Generate package graphs for GraphViz\n"
1761 " xvcg - Generate package graphs for xvcg\n"
1762 " policy - Show policy settings\n"
1765 " -h This help text.\n"
1766 " -p=? The package cache.\n"
1767 " -s=? The source cache.\n"
1768 " -q Disable progress indicator.\n"
1769 " -i Show only important deps for the unmet command.\n"
1770 " -c=? Read this configuration file\n"
1771 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1772 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1776 int main(int argc
,const char *argv
[]) /*{{{*/
1778 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1779 {"gencaches",&GenCaches
},
1780 {"showsrc",&ShowSrcPackage
},
1781 {"showpkg",&DumpPackage
},
1784 {"dumpavail",&DumpAvail
},
1787 {"depends",&Depends
},
1788 {"rdepends",&RDepends
},
1791 {"show",&ShowPackage
},
1792 {"pkgnames",&ShowPkgNames
},
1793 {"showauto",&ShowAuto
},
1795 {"madison",&Madison
},
1798 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1800 // Set up gettext support
1801 setlocale(LC_ALL
,"");
1802 textdomain(PACKAGE
);
1804 // Parse the command line and initialize the package library
1805 CommandLine
CmdL(Args
.data(),_config
);
1806 if (pkgInitConfig(*_config
) == false ||
1807 CmdL
.Parse(argc
,argv
) == false ||
1808 pkgInitSystem(*_config
,_system
) == false)
1810 _error
->DumpErrors();
1814 // See if the help should be shown
1815 if (_config
->FindB("help") == true ||
1816 CmdL
.FileSize() == 0)
1822 // Deal with stdout not being a tty
1823 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1824 _config
->Set("quiet","1");
1826 if (_config
->Exists("APT::Cache::Generate") == true)
1827 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1829 // Match the operation
1830 CmdL
.DispatchArg(Cmds
);
1832 // Print any errors or warnings found during parsing
1833 bool const Errors
= _error
->PendingError();
1834 if (_config
->FindI("quiet",0) > 0)
1835 _error
->DumpErrors();
1837 _error
->DumpErrors(GlobalError::DEBUG
);
1838 return Errors
== true ? 100 : 0;