]>
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/algorithms.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/indexfile.h>
25 #include <apt-pkg/init.h>
26 #include <apt-pkg/metaindex.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/pkgsystem.h>
29 #include <apt-pkg/policy.h>
30 #include <apt-pkg/progress.h>
31 #include <apt-pkg/sourcelist.h>
32 #include <apt-pkg/sptr.h>
33 #include <apt-pkg/srcrecords.h>
34 #include <apt-pkg/strutl.h>
35 #include <apt-pkg/tagfile.h>
36 #include <apt-pkg/version.h>
37 #include <apt-pkg/cacheiterators.h>
38 #include <apt-pkg/configuration.h>
39 #include <apt-pkg/depcache.h>
40 #include <apt-pkg/macros.h>
41 #include <apt-pkg/mmap.h>
42 #include <apt-pkg/pkgcache.h>
44 #include <apt-private/private-cacheset.h>
45 #include <apt-private/private-cmndline.h>
67 // LocalitySort - Sort a version list by package file locality /*{{{*/
68 // ---------------------------------------------------------------------
70 static int LocalityCompare(const void *a
, const void *b
)
72 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
73 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
82 if (A
->File
== B
->File
)
83 return A
->Offset
- B
->Offset
;
84 return A
->File
- B
->File
;
87 static void LocalitySort(pkgCache::VerFile
**begin
,
88 unsigned long Count
,size_t Size
)
90 qsort(begin
,Count
,Size
,LocalityCompare
);
93 static void LocalitySort(pkgCache::DescFile
**begin
,
94 unsigned long Count
,size_t Size
)
96 qsort(begin
,Count
,Size
,LocalityCompare
);
99 // UnMet - Show unmet dependencies /*{{{*/
100 // ---------------------------------------------------------------------
102 static bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const Important
)
105 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
108 pkgCache::DepIterator Start
;
109 pkgCache::DepIterator End
;
112 // Important deps only
113 if (Important
== true)
114 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
115 End
->Type
!= pkgCache::Dep::Depends
)
118 // Skip conflicts and replaces
119 if (End
.IsNegative() == true)
122 // Verify the or group
124 pkgCache::DepIterator RealStart
= Start
;
127 // See if this dep is Ok
128 pkgCache::Version
**VList
= Start
.AllTargets();
149 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
150 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
153 // Print out the dep type
154 cout
<< " " << End
.DepType() << ": ";
160 cout
<< Start
.TargetPkg().FullName(true);
161 if (Start
.TargetVer() != 0)
162 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
175 static bool UnMet(CommandLine
&CmdL
)
177 bool const Important
= _config
->FindB("APT::Cache::Important",false);
179 pkgCacheFile CacheFile
;
180 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
183 if (CmdL
.FileSize() <= 1)
185 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; ++P
)
186 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
187 if (ShowUnMet(V
, Important
) == false)
192 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
193 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1,
194 APT::VersionList::CANDIDATE
, helper
);
195 for (APT::VersionList::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
196 if (ShowUnMet(V
, Important
) == false)
202 // DumpPackage - Show a dump of a package record /*{{{*/
203 // ---------------------------------------------------------------------
205 static bool DumpPackage(CommandLine
&CmdL
)
207 pkgCacheFile CacheFile
;
208 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
209 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
211 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
213 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
214 cout
<< "Versions: " << endl
;
215 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
217 cout
<< Cur
.VerStr();
218 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
219 cout
<< " (" << Vf
.File().FileName() << ")";
221 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
223 cout
<< " Description Language: " << D
.LanguageCode() << endl
224 << " File: " << D
.FileList().File().FileName() << endl
225 << " MD5: " << D
.md5() << endl
;
232 cout
<< "Reverse Depends: " << endl
;
233 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
235 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
237 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
242 cout
<< "Dependencies: " << endl
;
243 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
245 cout
<< Cur
.VerStr() << " - ";
246 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; ++Dep
)
247 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
251 cout
<< "Provides: " << endl
;
252 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
254 cout
<< Cur
.VerStr() << " - ";
255 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
256 cout
<< Prv
.ParentPkg().FullName(true) << " ";
259 cout
<< "Reverse Provides: " << endl
;
260 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
261 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
267 // Stats - Dump some nice statistics /*{{{*/
268 // ---------------------------------------------------------------------
270 static bool Stats(CommandLine
&)
272 pkgCacheFile CacheFile
;
273 pkgCache
*Cache
= CacheFile
.GetPkgCache();
274 if (unlikely(Cache
== NULL
))
277 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
278 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
279 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
280 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
287 pkgCache::PkgIterator I
= Cache
->PkgBegin();
288 for (;I
.end() != true; ++I
)
290 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
296 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
302 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
305 if (I
.ProvidesList()->NextProvides
== 0)
313 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
319 cout
<< _(" Normal packages: ") << Normal
<< endl
;
320 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
321 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
322 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
323 cout
<< _(" Missing: ") << Missing
<< endl
;
325 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
326 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
327 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
328 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
329 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
330 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
332 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
333 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
334 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
335 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
336 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
337 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
340 unsigned long Size
= 0;
341 unsigned long Count
= 0;
342 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
343 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
346 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
348 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
350 unsigned long DepVerSize
= 0;
351 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
353 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
355 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
358 DepVerSize
+= strlen(D
.TargetVer()) + 1;
362 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
364 unsigned long Slack
= 0;
365 for (int I
= 0; I
!= 7; I
++)
366 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
367 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
369 unsigned long Total
= 0;
370 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
371 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
372 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
373 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
374 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
375 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
380 // Dump - show everything /*{{{*/
381 // ---------------------------------------------------------------------
382 /* This is worthless except fer debugging things */
383 static bool Dump(CommandLine
&)
385 pkgCacheFile CacheFile
;
386 pkgCache
*Cache
= CacheFile
.GetPkgCache();
387 if (unlikely(Cache
== NULL
))
390 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
392 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
394 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
395 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
397 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
398 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
399 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
400 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
401 DeNull(D
.TargetVer()) << std::endl
;
402 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
404 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
405 << " File: " << D
.FileList().File().FileName() << std::endl
406 << " MD5: " << D
.md5() << std::endl
;
411 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
413 std::cout
<< "File: " << F
.FileName() << std::endl
;
414 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
415 std::cout
<< " Size: " << F
->Size
<< std::endl
;
416 std::cout
<< " ID: " << F
->ID
<< std::endl
;
417 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
418 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
419 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
420 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
421 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
422 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
423 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
424 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
425 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
431 // DumpAvail - Print out the available list /*{{{*/
432 // ---------------------------------------------------------------------
433 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
434 make this run really fast, perhaps I went a little overboard.. */
435 static bool DumpAvail(CommandLine
&)
437 pkgCacheFile CacheFile
;
438 pkgCache
*Cache
= CacheFile
.GetPkgCache();
439 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
442 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
443 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
444 memset(VFList
,0,sizeof(*VFList
)*Count
);
446 // Map versions that we want to write out onto the VerList array.
447 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
449 if (P
->VersionList
== 0)
452 /* Find the proper version to use. If the policy says there are no
453 possible selections we return the installed version, if available..
454 This prevents dselect from making it obsolete. */
455 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
458 if (P
->CurrentVer
== 0)
463 pkgCache::VerFileIterator VF
= V
.FileList();
464 for (; VF
.end() == false ; ++VF
)
465 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
468 /* Okay, here we have a bit of a problem.. The policy has selected the
469 currently installed package - however it only exists in the
470 status file.. We need to write out something or dselect will mark
471 the package as obsolete! Thus we emit the status file entry, but
472 below we remove the status line to make it valid for the
473 available file. However! We only do this if their do exist *any*
474 non-source versions of the package - that way the dselect obsolete
475 handling works OK. */
476 if (VF
.end() == true)
478 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
480 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
482 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
489 if (VF
.end() == false)
497 LocalitySort(VFList
,Count
,sizeof(*VFList
));
499 // Iterate over all the package files and write them out.
500 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
501 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
503 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
504 if (File
.IsOk() == false)
506 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
510 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
511 if (_error
->PendingError() == true)
514 /* Write all of the records from this package file, since we
515 already did locality sorting we can now just seek through the
516 file in read order. We apply 1 more optimization here, since often
517 there will be < 1 byte gaps between records (for the \n) we read that
518 into the next buffer and offset a bit.. */
519 unsigned long Pos
= 0;
522 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
525 const pkgCache::VerFile
&VF
= **J
;
527 // Read the record and then write it out again.
528 unsigned long Jitter
= VF
.Offset
- Pos
;
531 if (PkgF
.Seek(VF
.Offset
) == false)
536 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
538 Buffer
[VF
.Size
+ Jitter
] = '\n';
541 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
544 TFRewriteData RW
[] = {{"Status", NULL
, NULL
},{"Config-Version", NULL
, NULL
},{NULL
, NULL
, NULL
}};
545 const char *Zero
= 0;
546 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
547 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
549 _error
->Error("Internal Error, Unable to parse a package record");
556 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
560 Pos
= VF
.Offset
+ VF
.Size
;
564 if (_error
->PendingError() == true)
570 return !_error
->PendingError();
573 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
574 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
576 pkgCacheFile CacheFile
;
577 pkgCache
*Cache
= CacheFile
.GetPkgCache();
578 if (unlikely(Cache
== NULL
))
581 CacheSetHelperVirtuals
helper(false);
582 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionList::CANDIDATE
, helper
);
583 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
584 return _error
->Error(_("No packages found"));
585 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
587 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
588 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
589 bool const Important
= _config
->FindB("APT::Cache::Important", false);
590 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
591 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
592 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
593 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
594 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
595 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
596 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
597 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
598 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
599 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
600 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
602 while (verset
.empty() != true)
604 pkgCache::VerIterator Ver
= *verset
.begin();
605 verset
.erase(verset
.begin());
606 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
607 Shown
[Pkg
->ID
] = true;
609 cout
<< Pkg
.FullName(true) << endl
;
611 if (RevDepends
== true)
612 cout
<< "Reverse Depends:" << endl
;
613 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
614 D
.end() == false; ++D
)
617 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
618 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
619 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
620 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
621 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
622 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
623 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
626 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
628 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
631 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
637 if (ShowDepType
== true)
638 cout
<< D
.DepType() << ": ";
639 if (Trg
->VersionList
== 0)
640 cout
<< "<" << Trg
.FullName(true) << ">";
642 cout
<< Trg
.FullName(true);
643 if (ShowVersion
== true && D
->Version
!= 0)
644 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
647 if (Recurse
== true && Shown
[Trg
->ID
] == false)
649 Shown
[Trg
->ID
] = true;
650 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
655 // Display all solutions
656 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
657 pkgPrioSortList(*Cache
,List
);
658 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
660 pkgCache::VerIterator
V(*Cache
,*I
);
661 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
662 V
->ParentPkg
== D
->Package
)
664 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
666 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
668 Shown
[V
.ParentPkg()->ID
] = true;
669 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
673 if (ShowOnlyFirstOr
== true)
674 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
678 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
679 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
680 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
685 // Depends - Print out a dependency tree /*{{{*/
686 // ---------------------------------------------------------------------
688 static bool Depends(CommandLine
&CmdL
)
690 return ShowDepends(CmdL
, false);
693 // RDepends - Print out a reverse dependency tree /*{{{*/
694 // ---------------------------------------------------------------------
696 static bool RDepends(CommandLine
&CmdL
)
698 return ShowDepends(CmdL
, true);
701 // xvcg - Generate a graph for xvcg /*{{{*/
702 // ---------------------------------------------------------------------
703 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
705 static bool XVcg(CommandLine
&CmdL
)
707 pkgCacheFile CacheFile
;
708 pkgCache
*Cache
= CacheFile
.GetPkgCache();
709 if (unlikely(Cache
== NULL
))
712 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
714 /* Normal packages are boxes
715 Pure Provides are triangles
717 rhomb are missing packages*/
718 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
720 /* Initialize the list of packages to show.
722 2 = To Show no recurse
723 3 = Emitted no recurse
726 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
727 enum TheFlags
{ForceNR
=(1<<0)};
728 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
729 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
730 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
732 // Show everything if no arguments given
733 if (CmdL
.FileList
[1] == 0)
734 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
737 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
739 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
742 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
744 if (Pkg
->VersionList
== 0)
747 if (Pkg
->ProvidesList
== 0)
748 ShapeMap
[Pkg
->ID
] = 0;
750 ShapeMap
[Pkg
->ID
] = 1;
755 if (Pkg
->ProvidesList
== 0)
756 ShapeMap
[Pkg
->ID
] = 2;
758 ShapeMap
[Pkg
->ID
] = 3;
762 // Load the list of packages from the command line into the show list
763 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
764 std::list
<APT::PackageSet::Modifier
> mods
;
765 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
766 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
767 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
768 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
770 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
771 Pkg
!= pkgsets
[0].end(); ++Pkg
)
772 Show
[Pkg
->ID
] = ToShow
;
773 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
774 Pkg
!= pkgsets
[1].end(); ++Pkg
)
776 Show
[Pkg
->ID
] = ToShow
;
777 Flags
[Pkg
->ID
] |= ForceNR
;
781 cout
<< "graph: { title: \"packages\"" << endl
<<
782 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
783 "layout_downfactor: 8" << endl
;
789 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
791 // See we need to show this package
792 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
795 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
798 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
800 // Pure Provides and missing packages have no deps!
801 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
802 Show
[Pkg
->ID
] = Done
;
804 Show
[Pkg
->ID
] = DoneNR
;
807 Show
[Pkg
->ID
] = Done
;
810 // No deps to map out
811 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
814 pkgCache::VerIterator Ver
= Pkg
.VersionList();
815 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
817 // See if anything can meet this dep
818 // Walk along the actual package providing versions
820 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
821 for (pkgCache::VerIterator I
= DPkg
.VersionList();
822 I
.end() == false && Hit
== false; ++I
)
824 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
828 // Follow all provides
829 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
830 I
.end() == false && Hit
== false; ++I
)
832 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
837 // Only graph critical deps
838 if (D
.IsCritical() == true)
840 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
842 // Colour the node for recursion
843 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
845 /* If a conflicts does not meet anything in the database
846 then show the relation but do not recurse */
847 if (Hit
== false && D
.IsNegative() == true)
849 if (Show
[D
.TargetPkg()->ID
] == None
&&
850 Show
[D
.TargetPkg()->ID
] != ToShow
)
851 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
855 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
856 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
858 Show
[D
.TargetPkg()->ID
] = ToShow
;
865 case pkgCache::Dep::Conflicts
:
866 printf("label: \"conflicts\" color: lightgreen }\n");
868 case pkgCache::Dep::DpkgBreaks
:
869 printf("label: \"breaks\" color: lightgreen }\n");
871 case pkgCache::Dep::Obsoletes
:
872 printf("label: \"obsoletes\" color: lightgreen }\n");
875 case pkgCache::Dep::PreDepends
:
876 printf("label: \"predepends\" color: blue }\n");
888 /* Draw the box colours after the fact since we can not tell what colour
889 they should be until everything is finished drawing */
890 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
892 if (Show
[Pkg
->ID
] < DoneNR
)
895 if (Show
[Pkg
->ID
] == DoneNR
)
896 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
897 Shapes
[ShapeMap
[Pkg
->ID
]]);
899 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
900 Shapes
[ShapeMap
[Pkg
->ID
]]);
912 // Dotty - Generate a graph for Dotty /*{{{*/
913 // ---------------------------------------------------------------------
914 /* Dotty is the graphvis program for generating graphs. It is a fairly
915 simple queuing algorithm that just writes dependencies and nodes.
916 http://www.research.att.com/sw/tools/graphviz/ */
917 static bool Dotty(CommandLine
&CmdL
)
919 pkgCacheFile CacheFile
;
920 pkgCache
*Cache
= CacheFile
.GetPkgCache();
921 if (unlikely(Cache
== NULL
))
924 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
926 /* Normal packages are boxes
927 Pure Provides are triangles
929 Hexagons are missing packages*/
930 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
932 /* Initialize the list of packages to show.
934 2 = To Show no recurse
935 3 = Emitted no recurse
938 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
939 enum TheFlags
{ForceNR
=(1<<0)};
940 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
941 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
942 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
944 // Show everything if no arguments given
945 if (CmdL
.FileList
[1] == 0)
946 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
949 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
951 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
954 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
956 if (Pkg
->VersionList
== 0)
959 if (Pkg
->ProvidesList
== 0)
960 ShapeMap
[Pkg
->ID
] = 0;
962 ShapeMap
[Pkg
->ID
] = 1;
967 if (Pkg
->ProvidesList
== 0)
968 ShapeMap
[Pkg
->ID
] = 2;
970 ShapeMap
[Pkg
->ID
] = 3;
974 // Load the list of packages from the command line into the show list
975 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
976 std::list
<APT::PackageSet::Modifier
> mods
;
977 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
978 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
979 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
980 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
982 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
983 Pkg
!= pkgsets
[0].end(); ++Pkg
)
984 Show
[Pkg
->ID
] = ToShow
;
985 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
986 Pkg
!= pkgsets
[1].end(); ++Pkg
)
988 Show
[Pkg
->ID
] = ToShow
;
989 Flags
[Pkg
->ID
] |= ForceNR
;
993 printf("digraph packages {\n");
994 printf("concentrate=true;\n");
995 printf("size=\"30,40\";\n");
1001 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1003 // See we need to show this package
1004 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1008 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1010 // Pure Provides and missing packages have no deps!
1011 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1012 Show
[Pkg
->ID
] = Done
;
1014 Show
[Pkg
->ID
] = DoneNR
;
1017 Show
[Pkg
->ID
] = Done
;
1020 // No deps to map out
1021 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1024 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1025 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1027 // See if anything can meet this dep
1028 // Walk along the actual package providing versions
1030 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1031 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1032 I
.end() == false && Hit
== false; ++I
)
1034 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1038 // Follow all provides
1039 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1040 I
.end() == false && Hit
== false; ++I
)
1042 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1046 // Only graph critical deps
1047 if (D
.IsCritical() == true)
1049 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1051 // Colour the node for recursion
1052 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1054 /* If a conflicts does not meet anything in the database
1055 then show the relation but do not recurse */
1056 if (Hit
== false && D
.IsNegative() == true)
1058 if (Show
[D
.TargetPkg()->ID
] == None
&&
1059 Show
[D
.TargetPkg()->ID
] != ToShow
)
1060 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1064 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1065 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1067 Show
[D
.TargetPkg()->ID
] = ToShow
;
1074 case pkgCache::Dep::Conflicts
:
1075 case pkgCache::Dep::Obsoletes
:
1076 case pkgCache::Dep::DpkgBreaks
:
1077 printf("[color=springgreen];\n");
1080 case pkgCache::Dep::PreDepends
:
1081 printf("[color=blue];\n");
1093 /* Draw the box colours after the fact since we can not tell what colour
1094 they should be until everything is finished drawing */
1095 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1097 if (Show
[Pkg
->ID
] < DoneNR
)
1100 // Orange box for early recursion stoppage
1101 if (Show
[Pkg
->ID
] == DoneNR
)
1102 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1103 Shapes
[ShapeMap
[Pkg
->ID
]]);
1105 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1106 Shapes
[ShapeMap
[Pkg
->ID
]]);
1116 // DisplayRecord - Displays the complete record for the package /*{{{*/
1117 // ---------------------------------------------------------------------
1118 /* This displays the package record from the proper package index file.
1119 It is not used by DumpAvail for performance reasons. */
1121 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1123 char const * const TagName
= "\nDescription";
1124 size_t const TagLen
= strlen(TagName
);
1125 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1127 if (DescP
[1] == ' ')
1129 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1138 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1140 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1141 if (unlikely(Cache
== NULL
))
1144 // Find an appropriate file
1145 pkgCache::VerFileIterator Vf
= V
.FileList();
1146 for (; Vf
.end() == false; ++Vf
)
1147 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1149 if (Vf
.end() == true)
1152 // Check and load the package list file
1153 pkgCache::PkgFileIterator I
= Vf
.File();
1154 if (I
.IsOk() == false)
1155 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1158 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1161 // Read the record (and ensure that it ends with a newline and NUL)
1162 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1163 Buffer
[Vf
->Size
] = '\n';
1164 Buffer
[Vf
->Size
+1] = '\0';
1165 if (PkgF
.Seek(Vf
->Offset
) == false ||
1166 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1172 // Get a pointer to start of Description field
1173 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1177 DescP
= Buffer
+ Vf
->Size
;
1179 // Write all but Description
1180 size_t const length
= DescP
- Buffer
;
1181 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1187 // Show the right description
1188 pkgRecords
Recs(*Cache
);
1189 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1190 if (Desc
.end() == false)
1192 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1193 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1194 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1196 // Find the first field after the description (if there is any)
1197 DescP
= skipDescriptionFields(DescP
);
1199 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1201 // write the rest of the buffer, but skip mixed in Descriptions* fields
1202 while (DescP
!= NULL
)
1204 const unsigned char * const Start
= DescP
;
1205 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1208 End
= &Buffer
[Vf
->Size
];
1213 ++End
; // get the newline into the output
1214 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1216 size_t const length
= End
- Start
;
1217 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1224 // write a final newline after the last field
1233 pkgCache::DescFile
*Df
;
1237 // Search - Perform a search /*{{{*/
1238 // ---------------------------------------------------------------------
1239 /* This searches the package names and package descriptions for a pattern */
1240 static bool Search(CommandLine
&CmdL
)
1242 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1243 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1244 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1246 pkgCacheFile CacheFile
;
1247 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1248 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1249 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1252 // Make sure there is at least one argument
1253 if (NumPatterns
< 1)
1254 return _error
->Error(_("You must give at least one search pattern"));
1256 // Compile the regex pattern
1257 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1258 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1259 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1261 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1265 regfree(&Patterns
[I
]);
1266 return _error
->Error("Regex compilation error");
1270 if (_error
->PendingError() == true)
1272 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1273 regfree(&Patterns
[I
]);
1277 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1278 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1279 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1281 bool PatternMatch
[descCount
* NumPatterns
];
1282 memset(PatternMatch
,false,sizeof(PatternMatch
));
1284 // Map versions that we want to write out onto the VerList array.
1285 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1287 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1288 size_t unmatched
= 0, matched
= 0;
1289 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1291 if (PatternMatch
[PatternOffset
+ I
] == true)
1293 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1294 PatternMatch
[PatternOffset
+ I
] = true;
1299 // already dealt with this package?
1300 if (matched
== NumPatterns
)
1303 // Doing names only, drop any that don't match..
1304 if (NamesOnly
== true && unmatched
== NumPatterns
)
1307 // Find the proper version to use
1308 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1309 if (P
.end() == true)
1311 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1312 if (V
.end() == false)
1314 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1315 //FIXME: packages without a description can't be found
1316 if (D
.end() == true)
1318 DFList
[G
->ID
].Df
= D
.FileList();
1319 DFList
[G
->ID
].ID
= G
->ID
;
1322 if (unmatched
== NumPatterns
)
1325 // Include all the packages that provide matching names too
1326 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1328 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1329 if (V
.end() == true)
1332 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1333 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1334 //FIXME: packages without a description can't be found
1335 if (D
.end() == true)
1337 DFList
[id
].Df
= D
.FileList();
1340 size_t const PrvPatternOffset
= id
* NumPatterns
;
1341 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1342 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1346 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1348 // Create the text record parser
1349 pkgRecords
Recs(*Cache
);
1350 // Iterate over all the version records and check them
1351 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1353 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1354 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1356 if (NamesOnly
== false)
1358 string
const LongDesc
= P
.LongDesc();
1359 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1361 if (PatternMatch
[PatternOffset
+ I
] == true)
1363 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1364 PatternMatch
[PatternOffset
+ I
] = true;
1368 bool matchedAll
= true;
1369 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1370 if (PatternMatch
[PatternOffset
+ I
] == false)
1376 if (matchedAll
== true)
1378 if (ShowFull
== true)
1382 P
.GetRec(Start
,End
);
1383 fwrite(Start
,End
-Start
,1,stdout
);
1387 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1392 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1393 regfree(&Patterns
[I
]);
1395 return _error
->Error("Write to stdout failed");
1399 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1400 static bool ShowAuto(CommandLine
&)
1402 pkgCacheFile CacheFile
;
1403 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1404 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1405 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1408 std::vector
<string
> packages
;
1409 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1411 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1412 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1413 packages
.push_back(P
.Name());
1415 std::sort(packages
.begin(), packages
.end());
1417 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1420 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1424 // ShowPackage - Dump the package record to the screen /*{{{*/
1425 // ---------------------------------------------------------------------
1427 static bool ShowPackage(CommandLine
&CmdL
)
1429 pkgCacheFile CacheFile
;
1430 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1431 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1432 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1433 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1434 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1435 if (DisplayRecord(CacheFile
, Ver
) == false)
1438 if (verset
.empty() == true)
1440 if (helper
.virtualPkgs
.empty() == true)
1441 return _error
->Error(_("No packages found"));
1443 _error
->Notice(_("No packages found"));
1448 // ShowPkgNames - Show package names /*{{{*/
1449 // ---------------------------------------------------------------------
1450 /* This does a prefix match on the first argument */
1451 static bool ShowPkgNames(CommandLine
&CmdL
)
1453 pkgCacheFile CacheFile
;
1454 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1456 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1457 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1459 if (CmdL
.FileList
[1] != 0)
1461 for (;I
.end() != true; ++I
)
1463 if (All
== false && I
->FirstPackage
== 0)
1465 if (I
.FindPkg("any")->VersionList
== 0)
1467 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1468 cout
<< I
.Name() << endl
;
1475 for (;I
.end() != true; ++I
)
1477 if (All
== false && I
->FirstPackage
== 0)
1479 if (I
.FindPkg("any")->VersionList
== 0)
1481 cout
<< I
.Name() << endl
;
1487 // ShowSrcPackage - Show source package records /*{{{*/
1488 // ---------------------------------------------------------------------
1490 static bool ShowSrcPackage(CommandLine
&CmdL
)
1492 pkgCacheFile CacheFile
;
1493 pkgSourceList
*List
= CacheFile
.GetSourceList();
1494 if (unlikely(List
== NULL
))
1497 // Create the text record parsers
1498 pkgSrcRecords
SrcRecs(*List
);
1499 if (_error
->PendingError() == true)
1503 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1507 pkgSrcRecords::Parser
*Parse
;
1508 unsigned found_this
= 0;
1509 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1510 cout
<< Parse
->AsStr() << endl
;;
1514 if (found_this
== 0) {
1515 _error
->Warning(_("Unable to locate package %s"),*I
);
1520 _error
->Notice(_("No packages found"));
1524 // Policy - Show the results of the preferences file /*{{{*/
1525 // ---------------------------------------------------------------------
1527 static bool Policy(CommandLine
&CmdL
)
1529 pkgCacheFile CacheFile
;
1530 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1531 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1532 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1533 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1536 /* Should the MultiArchKiller be run to see which pseudo packages for an
1537 arch all package are currently installed? Activating it gives a speed
1538 penality for no real gain beside enhanced debugging, so in general no. */
1539 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1540 CacheFile
.GetDepCache();
1542 // Print out all of the package files
1543 if (CmdL
.FileList
[1] == 0)
1545 cout
<< _("Package files:") << endl
;
1546 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1548 // Locate the associated index files so we can derive a description
1550 if (SrcList
->FindIndex(F
,Indx
) == false &&
1551 _system
->FindIndex(F
,Indx
) == false)
1552 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1555 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1557 // Print the reference information for the package
1558 string Str
= F
.RelStr();
1559 if (Str
.empty() == false)
1560 printf(" release %s\n",F
.RelStr().c_str());
1561 if (F
.Site() != 0 && F
.Site()[0] != 0)
1562 printf(" origin %s\n",F
.Site());
1565 // Show any packages have explicit pins
1566 cout
<< _("Pinned packages:") << endl
;
1567 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1568 for (;I
.end() != true; ++I
)
1570 if (Plcy
->GetPriority(I
) == 0)
1573 // Print the package name and the version we are forcing to
1574 cout
<< " " << I
.FullName(true) << " -> ";
1576 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1577 if (V
.end() == true)
1578 cout
<< _("(not found)") << endl
;
1580 cout
<< V
.VerStr() << endl
;
1586 char const * const msgInstalled
= _(" Installed: ");
1587 char const * const msgCandidate
= _(" Candidate: ");
1588 short const InstalledLessCandidate
=
1589 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1590 short const deepInstalled
=
1591 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1592 short const deepCandidate
=
1593 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1595 // Print out detailed information for each package
1596 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1597 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1598 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1600 cout
<< Pkg
.FullName(true) << ":" << endl
;
1602 // Installed version
1603 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1604 if (Pkg
->CurrentVer
== 0)
1605 cout
<< _("(none)") << endl
;
1607 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1609 // Candidate Version
1610 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1611 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1612 if (V
.end() == true)
1613 cout
<< _("(none)") << endl
;
1615 cout
<< V
.VerStr() << endl
;
1618 if (Plcy
->GetPriority(Pkg
) != 0)
1620 cout
<< _(" Package pin: ");
1621 V
= Plcy
->GetMatch(Pkg
);
1622 if (V
.end() == true)
1623 cout
<< _("(not found)") << endl
;
1625 cout
<< V
.VerStr() << endl
;
1628 // Show the priority tables
1629 cout
<< _(" Version table:") << endl
;
1630 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1632 if (Pkg
.CurrentVer() == V
)
1633 cout
<< " *** " << V
.VerStr();
1635 cout
<< " " << V
.VerStr();
1636 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1637 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1639 // Locate the associated index files so we can derive a description
1641 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1642 _system
->FindIndex(VF
.File(),Indx
) == false)
1643 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1644 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1645 Indx
->Describe(true).c_str());
1653 // Madison - Look a bit like katie's madison /*{{{*/
1654 // ---------------------------------------------------------------------
1656 static bool Madison(CommandLine
&CmdL
)
1658 pkgCacheFile CacheFile
;
1659 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1664 // Create the src text record parsers and ignore errors about missing
1665 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1666 pkgSrcRecords
SrcRecs(*SrcList
);
1667 if (_error
->PendingError() == true)
1670 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1671 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1673 _error
->PushToStack();
1674 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1675 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1677 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1679 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1681 // This might be nice, but wouldn't uniquely identify the source -mdz
1682 // if (VF.File().Archive() != 0)
1684 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1685 // << VF.File().Archive() << endl;
1688 // Locate the associated index files so we can derive a description
1689 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1691 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1692 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1693 IF
!= Indexes
->end(); ++IF
)
1695 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1697 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1698 << (*IF
)->Describe(true) << endl
;
1707 pkgSrcRecords::Parser
*SrcParser
;
1708 bool foundSomething
= false;
1709 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1711 foundSomething
= true;
1712 // Maybe support Release info here too eventually
1713 cout
<< setw(10) << SrcParser
->Package() << " | "
1714 << setw(10) << SrcParser
->Version() << " | "
1715 << SrcParser
->Index().Describe(true) << endl
;
1717 if (foundSomething
== true)
1718 _error
->RevertToStack();
1720 _error
->MergeWithStack();
1726 // GenCaches - Call the main cache generator /*{{{*/
1727 // ---------------------------------------------------------------------
1729 static bool GenCaches(CommandLine
&)
1731 OpTextProgress
Progress(*_config
);
1733 pkgCacheFile CacheFile
;
1734 return CacheFile
.BuildCaches(&Progress
, true);
1737 // ShowHelp - Show a help screen /*{{{*/
1738 // ---------------------------------------------------------------------
1740 static bool ShowHelp(CommandLine
&)
1742 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1743 COMMON_ARCH
,__DATE__
,__TIME__
);
1745 if (_config
->FindB("version") == true)
1749 _("Usage: apt-cache [options] command\n"
1750 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1751 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1753 "apt-cache is a low-level tool used to query information\n"
1754 "from APT's binary cache files\n"
1757 " gencaches - Build both the package and source cache\n"
1758 " showpkg - Show some general information for a single package\n"
1759 " showsrc - Show source records\n"
1760 " stats - Show some basic statistics\n"
1761 " dump - Show the entire file in a terse form\n"
1762 " dumpavail - Print an available file to stdout\n"
1763 " unmet - Show unmet dependencies\n"
1764 " search - Search the package list for a regex pattern\n"
1765 " show - Show a readable record for the package\n"
1766 " depends - Show raw dependency information for a package\n"
1767 " rdepends - Show reverse dependency information for a package\n"
1768 " pkgnames - List the names of all packages in the system\n"
1769 " dotty - Generate package graphs for GraphViz\n"
1770 " xvcg - Generate package graphs for xvcg\n"
1771 " policy - Show policy settings\n"
1774 " -h This help text.\n"
1775 " -p=? The package cache.\n"
1776 " -s=? The source cache.\n"
1777 " -q Disable progress indicator.\n"
1778 " -i Show only important deps for the unmet command.\n"
1779 " -c=? Read this configuration file\n"
1780 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1781 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1785 int main(int argc
,const char *argv
[]) /*{{{*/
1787 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1788 {"gencaches",&GenCaches
},
1789 {"showsrc",&ShowSrcPackage
},
1790 {"showpkg",&DumpPackage
},
1793 {"dumpavail",&DumpAvail
},
1796 {"depends",&Depends
},
1797 {"rdepends",&RDepends
},
1800 {"show",&ShowPackage
},
1801 {"pkgnames",&ShowPkgNames
},
1802 {"showauto",&ShowAuto
},
1804 {"madison",&Madison
},
1807 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1809 // Set up gettext support
1810 setlocale(LC_ALL
,"");
1811 textdomain(PACKAGE
);
1813 // Parse the command line and initialize the package library
1814 CommandLine
CmdL(Args
.data(),_config
);
1815 if (pkgInitConfig(*_config
) == false ||
1816 CmdL
.Parse(argc
,argv
) == false ||
1817 pkgInitSystem(*_config
,_system
) == false)
1819 _error
->DumpErrors();
1823 // See if the help should be shown
1824 if (_config
->FindB("help") == true ||
1825 CmdL
.FileSize() == 0)
1831 // Deal with stdout not being a tty
1832 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1833 _config
->Set("quiet","1");
1835 if (_config
->Exists("APT::Cache::Generate") == true)
1836 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1838 // Match the operation
1839 CmdL
.DispatchArg(Cmds
);
1841 // Print any errors or warnings found during parsing
1842 bool const Errors
= _error
->PendingError();
1843 if (_config
->FindI("quiet",0) > 0)
1844 _error
->DumpErrors();
1846 _error
->DumpErrors(GlobalError::DEBUG
);
1847 return Errors
== true ? 100 : 0;