]>
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 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
268 // ---------------------------------------------------------------------
271 static void ShowHashTableStats(std::string Type
,
273 map_ptrloc
*Hashtable
,
276 // hashtable stats for the HashTable
277 long NumBuckets
= Size
;
278 long UsedBuckets
= 0;
279 long UnusedBuckets
= 0;
280 long LongestBucket
= 0;
281 long ShortestBucket
= NumBuckets
;
282 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
284 T
*P
= StartP
+ Hashtable
[i
];
285 if(P
== 0 || P
== StartP
)
290 long ThisBucketSize
= 0;
291 for (; P
!= StartP
; P
= StartP
+ P
->Next
)
293 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
294 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
295 UsedBuckets
+= ThisBucketSize
;
297 cout
<< "Total buckets " << Type
<< ": " << SizeToStr(NumBuckets
) << std::endl
;
298 cout
<< " Unused: " << SizeToStr(UnusedBuckets
) << std::endl
;
299 cout
<< " Used: " << UsedBuckets
<< std::endl
;
300 cout
<< " Average entries: " << UsedBuckets
/(double)NumBuckets
<< std::endl
;
301 cout
<< " Longest: " << LongestBucket
<< std::endl
;
302 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
305 // Stats - Dump some nice statistics /*{{{*/
306 // ---------------------------------------------------------------------
308 static bool Stats(CommandLine
&)
310 pkgCacheFile CacheFile
;
311 pkgCache
*Cache
= CacheFile
.GetPkgCache();
312 if (unlikely(Cache
== NULL
))
315 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
316 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
317 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
318 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
325 pkgCache::PkgIterator I
= Cache
->PkgBegin();
326 for (;I
.end() != true; ++I
)
328 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
334 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
340 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
343 if (I
.ProvidesList()->NextProvides
== 0)
351 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
357 cout
<< _(" Normal packages: ") << Normal
<< endl
;
358 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
359 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
360 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
361 cout
<< _(" Missing: ") << Missing
<< endl
;
363 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
364 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
365 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
366 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
367 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
368 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
370 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
371 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
372 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
373 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
374 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
375 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
378 unsigned long Size
= 0;
379 unsigned long Count
= 0;
380 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
381 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
384 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
386 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
388 unsigned long DepVerSize
= 0;
389 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
391 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
393 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
396 DepVerSize
+= strlen(D
.TargetVer()) + 1;
400 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
402 unsigned long Slack
= 0;
403 for (int I
= 0; I
!= 7; I
++)
404 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
405 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
407 unsigned long Total
= 0;
408 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
409 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
410 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
411 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
412 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
413 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
416 int HashTableSize
= sizeof(Cache
->HeaderP
->PkgHashTable
)/sizeof(map_ptrloc
);
417 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->HeaderP
->PkgHashTable
, HashTableSize
);
418 HashTableSize
= sizeof(Cache
->HeaderP
->GrpHashTable
)/sizeof(map_ptrloc
);
419 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->HeaderP
->GrpHashTable
, HashTableSize
);
424 // Dump - show everything /*{{{*/
425 // ---------------------------------------------------------------------
426 /* This is worthless except fer debugging things */
427 static bool Dump(CommandLine
&)
429 pkgCacheFile CacheFile
;
430 pkgCache
*Cache
= CacheFile
.GetPkgCache();
431 if (unlikely(Cache
== NULL
))
434 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
436 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
438 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
439 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
441 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
442 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
443 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
444 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
445 DeNull(D
.TargetVer()) << std::endl
;
446 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
448 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
449 << " File: " << D
.FileList().File().FileName() << std::endl
450 << " MD5: " << D
.md5() << std::endl
;
455 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
457 std::cout
<< "File: " << F
.FileName() << std::endl
;
458 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
459 std::cout
<< " Size: " << F
->Size
<< std::endl
;
460 std::cout
<< " ID: " << F
->ID
<< std::endl
;
461 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
462 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
463 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
464 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
465 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
466 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
467 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
468 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
469 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
475 // DumpAvail - Print out the available list /*{{{*/
476 // ---------------------------------------------------------------------
477 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
478 make this run really fast, perhaps I went a little overboard.. */
479 static bool DumpAvail(CommandLine
&)
481 pkgCacheFile CacheFile
;
482 pkgCache
*Cache
= CacheFile
.GetPkgCache();
483 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
486 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
487 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
488 memset(VFList
,0,sizeof(*VFList
)*Count
);
490 // Map versions that we want to write out onto the VerList array.
491 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
493 if (P
->VersionList
== 0)
496 /* Find the proper version to use. If the policy says there are no
497 possible selections we return the installed version, if available..
498 This prevents dselect from making it obsolete. */
499 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
502 if (P
->CurrentVer
== 0)
507 pkgCache::VerFileIterator VF
= V
.FileList();
508 for (; VF
.end() == false ; ++VF
)
509 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
512 /* Okay, here we have a bit of a problem.. The policy has selected the
513 currently installed package - however it only exists in the
514 status file.. We need to write out something or dselect will mark
515 the package as obsolete! Thus we emit the status file entry, but
516 below we remove the status line to make it valid for the
517 available file. However! We only do this if their do exist *any*
518 non-source versions of the package - that way the dselect obsolete
519 handling works OK. */
520 if (VF
.end() == true)
522 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
524 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
526 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
533 if (VF
.end() == false)
541 LocalitySort(VFList
,Count
,sizeof(*VFList
));
543 // Iterate over all the package files and write them out.
544 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
545 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
547 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
548 if (File
.IsOk() == false)
550 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
554 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
555 if (_error
->PendingError() == true)
558 /* Write all of the records from this package file, since we
559 already did locality sorting we can now just seek through the
560 file in read order. We apply 1 more optimization here, since often
561 there will be < 1 byte gaps between records (for the \n) we read that
562 into the next buffer and offset a bit.. */
563 unsigned long Pos
= 0;
566 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
569 const pkgCache::VerFile
&VF
= **J
;
571 // Read the record and then write it out again.
572 unsigned long Jitter
= VF
.Offset
- Pos
;
575 if (PkgF
.Seek(VF
.Offset
) == false)
580 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
582 Buffer
[VF
.Size
+ Jitter
] = '\n';
585 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
588 TFRewriteData RW
[] = {{"Status", NULL
, NULL
},{"Config-Version", NULL
, NULL
},{NULL
, NULL
, NULL
}};
589 const char *Zero
= 0;
590 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
591 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
593 _error
->Error("Internal Error, Unable to parse a package record");
600 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
604 Pos
= VF
.Offset
+ VF
.Size
;
608 if (_error
->PendingError() == true)
614 return !_error
->PendingError();
617 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
618 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
620 pkgCacheFile CacheFile
;
621 pkgCache
*Cache
= CacheFile
.GetPkgCache();
622 if (unlikely(Cache
== NULL
))
625 CacheSetHelperVirtuals
helper(false);
626 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionList::CANDIDATE
, helper
);
627 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
628 return _error
->Error(_("No packages found"));
629 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
631 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
632 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
633 bool const Important
= _config
->FindB("APT::Cache::Important", false);
634 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
635 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
636 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
637 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
638 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
639 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
640 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
641 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
642 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
643 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
644 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
646 while (verset
.empty() != true)
648 pkgCache::VerIterator Ver
= *verset
.begin();
649 verset
.erase(verset
.begin());
650 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
651 Shown
[Pkg
->ID
] = true;
653 cout
<< Pkg
.FullName(true) << endl
;
655 if (RevDepends
== true)
656 cout
<< "Reverse Depends:" << endl
;
657 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
658 D
.end() == false; ++D
)
661 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
662 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
663 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
664 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
665 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
666 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
667 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
670 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
672 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
675 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
681 if (ShowDepType
== true)
682 cout
<< D
.DepType() << ": ";
683 if (Trg
->VersionList
== 0)
684 cout
<< "<" << Trg
.FullName(true) << ">";
686 cout
<< Trg
.FullName(true);
687 if (ShowVersion
== true && D
->Version
!= 0)
688 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
691 if (Recurse
== true && Shown
[Trg
->ID
] == false)
693 Shown
[Trg
->ID
] = true;
694 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
699 // Display all solutions
700 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
701 pkgPrioSortList(*Cache
,List
);
702 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
704 pkgCache::VerIterator
V(*Cache
,*I
);
705 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
706 V
->ParentPkg
== D
->Package
)
708 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
710 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
712 Shown
[V
.ParentPkg()->ID
] = true;
713 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
717 if (ShowOnlyFirstOr
== true)
718 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
722 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
723 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
724 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
729 // Depends - Print out a dependency tree /*{{{*/
730 // ---------------------------------------------------------------------
732 static bool Depends(CommandLine
&CmdL
)
734 return ShowDepends(CmdL
, false);
737 // RDepends - Print out a reverse dependency tree /*{{{*/
738 // ---------------------------------------------------------------------
740 static bool RDepends(CommandLine
&CmdL
)
742 return ShowDepends(CmdL
, true);
745 // xvcg - Generate a graph for xvcg /*{{{*/
746 // ---------------------------------------------------------------------
747 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
749 static bool XVcg(CommandLine
&CmdL
)
751 pkgCacheFile CacheFile
;
752 pkgCache
*Cache
= CacheFile
.GetPkgCache();
753 if (unlikely(Cache
== NULL
))
756 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
758 /* Normal packages are boxes
759 Pure Provides are triangles
761 rhomb are missing packages*/
762 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
764 /* Initialize the list of packages to show.
766 2 = To Show no recurse
767 3 = Emitted no recurse
770 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
771 enum TheFlags
{ForceNR
=(1<<0)};
772 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
773 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
774 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
776 // Show everything if no arguments given
777 if (CmdL
.FileList
[1] == 0)
778 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
781 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
783 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
786 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
788 if (Pkg
->VersionList
== 0)
791 if (Pkg
->ProvidesList
== 0)
792 ShapeMap
[Pkg
->ID
] = 0;
794 ShapeMap
[Pkg
->ID
] = 1;
799 if (Pkg
->ProvidesList
== 0)
800 ShapeMap
[Pkg
->ID
] = 2;
802 ShapeMap
[Pkg
->ID
] = 3;
806 // Load the list of packages from the command line into the show list
807 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
808 std::list
<APT::PackageSet::Modifier
> mods
;
809 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
810 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
811 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
812 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
814 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
815 Pkg
!= pkgsets
[0].end(); ++Pkg
)
816 Show
[Pkg
->ID
] = ToShow
;
817 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
818 Pkg
!= pkgsets
[1].end(); ++Pkg
)
820 Show
[Pkg
->ID
] = ToShow
;
821 Flags
[Pkg
->ID
] |= ForceNR
;
825 cout
<< "graph: { title: \"packages\"" << endl
<<
826 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
827 "layout_downfactor: 8" << endl
;
833 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
835 // See we need to show this package
836 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
839 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
842 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
844 // Pure Provides and missing packages have no deps!
845 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
846 Show
[Pkg
->ID
] = Done
;
848 Show
[Pkg
->ID
] = DoneNR
;
851 Show
[Pkg
->ID
] = Done
;
854 // No deps to map out
855 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
858 pkgCache::VerIterator Ver
= Pkg
.VersionList();
859 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
861 // See if anything can meet this dep
862 // Walk along the actual package providing versions
864 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
865 for (pkgCache::VerIterator I
= DPkg
.VersionList();
866 I
.end() == false && Hit
== false; ++I
)
868 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
872 // Follow all provides
873 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
874 I
.end() == false && Hit
== false; ++I
)
876 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
881 // Only graph critical deps
882 if (D
.IsCritical() == true)
884 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
886 // Colour the node for recursion
887 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
889 /* If a conflicts does not meet anything in the database
890 then show the relation but do not recurse */
891 if (Hit
== false && D
.IsNegative() == true)
893 if (Show
[D
.TargetPkg()->ID
] == None
&&
894 Show
[D
.TargetPkg()->ID
] != ToShow
)
895 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
899 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
900 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
902 Show
[D
.TargetPkg()->ID
] = ToShow
;
909 case pkgCache::Dep::Conflicts
:
910 printf("label: \"conflicts\" color: lightgreen }\n");
912 case pkgCache::Dep::DpkgBreaks
:
913 printf("label: \"breaks\" color: lightgreen }\n");
915 case pkgCache::Dep::Obsoletes
:
916 printf("label: \"obsoletes\" color: lightgreen }\n");
919 case pkgCache::Dep::PreDepends
:
920 printf("label: \"predepends\" color: blue }\n");
932 /* Draw the box colours after the fact since we can not tell what colour
933 they should be until everything is finished drawing */
934 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
936 if (Show
[Pkg
->ID
] < DoneNR
)
939 if (Show
[Pkg
->ID
] == DoneNR
)
940 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
941 Shapes
[ShapeMap
[Pkg
->ID
]]);
943 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
944 Shapes
[ShapeMap
[Pkg
->ID
]]);
956 // Dotty - Generate a graph for Dotty /*{{{*/
957 // ---------------------------------------------------------------------
958 /* Dotty is the graphvis program for generating graphs. It is a fairly
959 simple queuing algorithm that just writes dependencies and nodes.
960 http://www.research.att.com/sw/tools/graphviz/ */
961 static bool Dotty(CommandLine
&CmdL
)
963 pkgCacheFile CacheFile
;
964 pkgCache
*Cache
= CacheFile
.GetPkgCache();
965 if (unlikely(Cache
== NULL
))
968 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
970 /* Normal packages are boxes
971 Pure Provides are triangles
973 Hexagons are missing packages*/
974 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
976 /* Initialize the list of packages to show.
978 2 = To Show no recurse
979 3 = Emitted no recurse
982 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
983 enum TheFlags
{ForceNR
=(1<<0)};
984 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
985 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
986 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
988 // Show everything if no arguments given
989 if (CmdL
.FileList
[1] == 0)
990 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
993 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
995 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
998 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1000 if (Pkg
->VersionList
== 0)
1003 if (Pkg
->ProvidesList
== 0)
1004 ShapeMap
[Pkg
->ID
] = 0;
1006 ShapeMap
[Pkg
->ID
] = 1;
1011 if (Pkg
->ProvidesList
== 0)
1012 ShapeMap
[Pkg
->ID
] = 2;
1014 ShapeMap
[Pkg
->ID
] = 3;
1018 // Load the list of packages from the command line into the show list
1019 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1020 std::list
<APT::PackageSet::Modifier
> mods
;
1021 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1022 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1023 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1024 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1026 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1027 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1028 Show
[Pkg
->ID
] = ToShow
;
1029 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1030 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1032 Show
[Pkg
->ID
] = ToShow
;
1033 Flags
[Pkg
->ID
] |= ForceNR
;
1037 printf("digraph packages {\n");
1038 printf("concentrate=true;\n");
1039 printf("size=\"30,40\";\n");
1045 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1047 // See we need to show this package
1048 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1052 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1054 // Pure Provides and missing packages have no deps!
1055 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1056 Show
[Pkg
->ID
] = Done
;
1058 Show
[Pkg
->ID
] = DoneNR
;
1061 Show
[Pkg
->ID
] = Done
;
1064 // No deps to map out
1065 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1068 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1069 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1071 // See if anything can meet this dep
1072 // Walk along the actual package providing versions
1074 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1075 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1076 I
.end() == false && Hit
== false; ++I
)
1078 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1082 // Follow all provides
1083 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1084 I
.end() == false && Hit
== false; ++I
)
1086 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1090 // Only graph critical deps
1091 if (D
.IsCritical() == true)
1093 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1095 // Colour the node for recursion
1096 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1098 /* If a conflicts does not meet anything in the database
1099 then show the relation but do not recurse */
1100 if (Hit
== false && D
.IsNegative() == true)
1102 if (Show
[D
.TargetPkg()->ID
] == None
&&
1103 Show
[D
.TargetPkg()->ID
] != ToShow
)
1104 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1108 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1109 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1111 Show
[D
.TargetPkg()->ID
] = ToShow
;
1118 case pkgCache::Dep::Conflicts
:
1119 case pkgCache::Dep::Obsoletes
:
1120 case pkgCache::Dep::DpkgBreaks
:
1121 printf("[color=springgreen];\n");
1124 case pkgCache::Dep::PreDepends
:
1125 printf("[color=blue];\n");
1137 /* Draw the box colours after the fact since we can not tell what colour
1138 they should be until everything is finished drawing */
1139 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1141 if (Show
[Pkg
->ID
] < DoneNR
)
1144 // Orange box for early recursion stoppage
1145 if (Show
[Pkg
->ID
] == DoneNR
)
1146 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1147 Shapes
[ShapeMap
[Pkg
->ID
]]);
1149 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1150 Shapes
[ShapeMap
[Pkg
->ID
]]);
1160 // DisplayRecord - Displays the complete record for the package /*{{{*/
1161 // ---------------------------------------------------------------------
1162 /* This displays the package record from the proper package index file.
1163 It is not used by DumpAvail for performance reasons. */
1165 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1167 char const * const TagName
= "\nDescription";
1168 size_t const TagLen
= strlen(TagName
);
1169 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1171 if (DescP
[1] == ' ')
1173 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1182 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1184 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1185 if (unlikely(Cache
== NULL
))
1188 // Find an appropriate file
1189 pkgCache::VerFileIterator Vf
= V
.FileList();
1190 for (; Vf
.end() == false; ++Vf
)
1191 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1193 if (Vf
.end() == true)
1196 // Check and load the package list file
1197 pkgCache::PkgFileIterator I
= Vf
.File();
1198 if (I
.IsOk() == false)
1199 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1202 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1205 // Read the record (and ensure that it ends with a newline and NUL)
1206 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1207 Buffer
[Vf
->Size
] = '\n';
1208 Buffer
[Vf
->Size
+1] = '\0';
1209 if (PkgF
.Seek(Vf
->Offset
) == false ||
1210 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1216 // Get a pointer to start of Description field
1217 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1221 DescP
= Buffer
+ Vf
->Size
;
1223 // Write all but Description
1224 size_t const length
= DescP
- Buffer
;
1225 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1231 // Show the right description
1232 pkgRecords
Recs(*Cache
);
1233 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1234 if (Desc
.end() == false)
1236 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1237 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1238 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1240 // Find the first field after the description (if there is any)
1241 DescP
= skipDescriptionFields(DescP
);
1243 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1245 // write the rest of the buffer, but skip mixed in Descriptions* fields
1246 while (DescP
!= NULL
)
1248 const unsigned char * const Start
= DescP
;
1249 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1252 End
= &Buffer
[Vf
->Size
];
1257 ++End
; // get the newline into the output
1258 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1260 size_t const length
= End
- Start
;
1261 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1268 // write a final newline after the last field
1277 pkgCache::DescFile
*Df
;
1281 // Search - Perform a search /*{{{*/
1282 // ---------------------------------------------------------------------
1283 /* This searches the package names and package descriptions for a pattern */
1284 static bool Search(CommandLine
&CmdL
)
1286 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1287 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1288 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1290 pkgCacheFile CacheFile
;
1291 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1292 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1293 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1296 // Make sure there is at least one argument
1297 if (NumPatterns
< 1)
1298 return _error
->Error(_("You must give at least one search pattern"));
1300 // Compile the regex pattern
1301 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1302 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1303 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1305 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1309 regfree(&Patterns
[I
]);
1310 return _error
->Error("Regex compilation error");
1314 if (_error
->PendingError() == true)
1316 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1317 regfree(&Patterns
[I
]);
1321 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1322 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1323 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1325 bool PatternMatch
[descCount
* NumPatterns
];
1326 memset(PatternMatch
,false,sizeof(PatternMatch
));
1328 // Map versions that we want to write out onto the VerList array.
1329 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1331 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1332 size_t unmatched
= 0, matched
= 0;
1333 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1335 if (PatternMatch
[PatternOffset
+ I
] == true)
1337 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1338 PatternMatch
[PatternOffset
+ I
] = true;
1343 // already dealt with this package?
1344 if (matched
== NumPatterns
)
1347 // Doing names only, drop any that don't match..
1348 if (NamesOnly
== true && unmatched
== NumPatterns
)
1351 // Find the proper version to use
1352 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1353 if (P
.end() == true)
1355 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1356 if (V
.end() == false)
1358 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1359 //FIXME: packages without a description can't be found
1360 if (D
.end() == true)
1362 DFList
[G
->ID
].Df
= D
.FileList();
1363 DFList
[G
->ID
].ID
= G
->ID
;
1366 if (unmatched
== NumPatterns
)
1369 // Include all the packages that provide matching names too
1370 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1372 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1373 if (V
.end() == true)
1376 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1377 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1378 //FIXME: packages without a description can't be found
1379 if (D
.end() == true)
1381 DFList
[id
].Df
= D
.FileList();
1384 size_t const PrvPatternOffset
= id
* NumPatterns
;
1385 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1386 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1390 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1392 // Create the text record parser
1393 pkgRecords
Recs(*Cache
);
1394 // Iterate over all the version records and check them
1395 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1397 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1398 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1400 if (NamesOnly
== false)
1402 string
const LongDesc
= P
.LongDesc();
1403 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1405 if (PatternMatch
[PatternOffset
+ I
] == true)
1407 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1408 PatternMatch
[PatternOffset
+ I
] = true;
1412 bool matchedAll
= true;
1413 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1414 if (PatternMatch
[PatternOffset
+ I
] == false)
1420 if (matchedAll
== true)
1422 if (ShowFull
== true)
1426 P
.GetRec(Start
,End
);
1427 fwrite(Start
,End
-Start
,1,stdout
);
1431 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1436 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1437 regfree(&Patterns
[I
]);
1439 return _error
->Error("Write to stdout failed");
1443 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1444 static bool ShowAuto(CommandLine
&)
1446 pkgCacheFile CacheFile
;
1447 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1448 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1449 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1452 std::vector
<string
> packages
;
1453 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1455 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1456 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1457 packages
.push_back(P
.Name());
1459 std::sort(packages
.begin(), packages
.end());
1461 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1464 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1468 // ShowPackage - Dump the package record to the screen /*{{{*/
1469 // ---------------------------------------------------------------------
1471 static bool ShowPackage(CommandLine
&CmdL
)
1473 pkgCacheFile CacheFile
;
1474 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1475 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1476 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1477 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1478 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1479 if (DisplayRecord(CacheFile
, Ver
) == false)
1482 if (verset
.empty() == true)
1484 if (helper
.virtualPkgs
.empty() == true)
1485 return _error
->Error(_("No packages found"));
1487 _error
->Notice(_("No packages found"));
1492 // ShowPkgNames - Show package names /*{{{*/
1493 // ---------------------------------------------------------------------
1494 /* This does a prefix match on the first argument */
1495 static bool ShowPkgNames(CommandLine
&CmdL
)
1497 pkgCacheFile CacheFile
;
1498 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1500 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1501 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1503 if (CmdL
.FileList
[1] != 0)
1505 for (;I
.end() != true; ++I
)
1507 if (All
== false && I
->FirstPackage
== 0)
1509 if (I
.FindPkg("any")->VersionList
== 0)
1511 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1512 cout
<< I
.Name() << endl
;
1519 for (;I
.end() != true; ++I
)
1521 if (All
== false && I
->FirstPackage
== 0)
1523 if (I
.FindPkg("any")->VersionList
== 0)
1525 cout
<< I
.Name() << endl
;
1531 // ShowSrcPackage - Show source package records /*{{{*/
1532 // ---------------------------------------------------------------------
1534 static bool ShowSrcPackage(CommandLine
&CmdL
)
1536 pkgCacheFile CacheFile
;
1537 pkgSourceList
*List
= CacheFile
.GetSourceList();
1538 if (unlikely(List
== NULL
))
1541 // Create the text record parsers
1542 pkgSrcRecords
SrcRecs(*List
);
1543 if (_error
->PendingError() == true)
1547 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1551 pkgSrcRecords::Parser
*Parse
;
1552 unsigned found_this
= 0;
1553 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1554 cout
<< Parse
->AsStr() << endl
;;
1558 if (found_this
== 0) {
1559 _error
->Warning(_("Unable to locate package %s"),*I
);
1564 _error
->Notice(_("No packages found"));
1568 // Policy - Show the results of the preferences file /*{{{*/
1569 // ---------------------------------------------------------------------
1571 static bool Policy(CommandLine
&CmdL
)
1573 pkgCacheFile CacheFile
;
1574 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1575 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1576 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1577 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1580 /* Should the MultiArchKiller be run to see which pseudo packages for an
1581 arch all package are currently installed? Activating it gives a speed
1582 penality for no real gain beside enhanced debugging, so in general no. */
1583 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1584 CacheFile
.GetDepCache();
1586 // Print out all of the package files
1587 if (CmdL
.FileList
[1] == 0)
1589 cout
<< _("Package files:") << endl
;
1590 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1592 // Locate the associated index files so we can derive a description
1594 if (SrcList
->FindIndex(F
,Indx
) == false &&
1595 _system
->FindIndex(F
,Indx
) == false)
1596 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1599 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1601 // Print the reference information for the package
1602 string Str
= F
.RelStr();
1603 if (Str
.empty() == false)
1604 printf(" release %s\n",F
.RelStr().c_str());
1605 if (F
.Site() != 0 && F
.Site()[0] != 0)
1606 printf(" origin %s\n",F
.Site());
1609 // Show any packages have explicit pins
1610 cout
<< _("Pinned packages:") << endl
;
1611 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1612 for (;I
.end() != true; ++I
)
1614 if (Plcy
->GetPriority(I
) == 0)
1617 // Print the package name and the version we are forcing to
1618 cout
<< " " << I
.FullName(true) << " -> ";
1620 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1621 if (V
.end() == true)
1622 cout
<< _("(not found)") << endl
;
1624 cout
<< V
.VerStr() << endl
;
1630 char const * const msgInstalled
= _(" Installed: ");
1631 char const * const msgCandidate
= _(" Candidate: ");
1632 short const InstalledLessCandidate
=
1633 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1634 short const deepInstalled
=
1635 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1636 short const deepCandidate
=
1637 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1639 // Print out detailed information for each package
1640 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1641 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1642 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1644 cout
<< Pkg
.FullName(true) << ":" << endl
;
1646 // Installed version
1647 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1648 if (Pkg
->CurrentVer
== 0)
1649 cout
<< _("(none)") << endl
;
1651 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1653 // Candidate Version
1654 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1655 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1656 if (V
.end() == true)
1657 cout
<< _("(none)") << endl
;
1659 cout
<< V
.VerStr() << endl
;
1662 if (Plcy
->GetPriority(Pkg
) != 0)
1664 cout
<< _(" Package pin: ");
1665 V
= Plcy
->GetMatch(Pkg
);
1666 if (V
.end() == true)
1667 cout
<< _("(not found)") << endl
;
1669 cout
<< V
.VerStr() << endl
;
1672 // Show the priority tables
1673 cout
<< _(" Version table:") << endl
;
1674 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1676 if (Pkg
.CurrentVer() == V
)
1677 cout
<< " *** " << V
.VerStr();
1679 cout
<< " " << V
.VerStr();
1680 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1681 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1683 // Locate the associated index files so we can derive a description
1685 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1686 _system
->FindIndex(VF
.File(),Indx
) == false)
1687 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1688 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1689 Indx
->Describe(true).c_str());
1697 // Madison - Look a bit like katie's madison /*{{{*/
1698 // ---------------------------------------------------------------------
1700 static bool Madison(CommandLine
&CmdL
)
1702 pkgCacheFile CacheFile
;
1703 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1708 // Create the src text record parsers and ignore errors about missing
1709 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1710 pkgSrcRecords
SrcRecs(*SrcList
);
1711 if (_error
->PendingError() == true)
1714 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1715 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1717 _error
->PushToStack();
1718 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1719 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1721 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1723 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1725 // This might be nice, but wouldn't uniquely identify the source -mdz
1726 // if (VF.File().Archive() != 0)
1728 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1729 // << VF.File().Archive() << endl;
1732 // Locate the associated index files so we can derive a description
1733 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1735 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1736 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1737 IF
!= Indexes
->end(); ++IF
)
1739 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1741 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1742 << (*IF
)->Describe(true) << endl
;
1751 pkgSrcRecords::Parser
*SrcParser
;
1752 bool foundSomething
= false;
1753 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1755 foundSomething
= true;
1756 // Maybe support Release info here too eventually
1757 cout
<< setw(10) << SrcParser
->Package() << " | "
1758 << setw(10) << SrcParser
->Version() << " | "
1759 << SrcParser
->Index().Describe(true) << endl
;
1761 if (foundSomething
== true)
1762 _error
->RevertToStack();
1764 _error
->MergeWithStack();
1770 // GenCaches - Call the main cache generator /*{{{*/
1771 // ---------------------------------------------------------------------
1773 static bool GenCaches(CommandLine
&)
1775 OpTextProgress
Progress(*_config
);
1777 pkgCacheFile CacheFile
;
1778 return CacheFile
.BuildCaches(&Progress
, true);
1781 // ShowHelp - Show a help screen /*{{{*/
1782 // ---------------------------------------------------------------------
1784 static bool ShowHelp(CommandLine
&)
1786 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1787 COMMON_ARCH
,__DATE__
,__TIME__
);
1789 if (_config
->FindB("version") == true)
1793 _("Usage: apt-cache [options] command\n"
1794 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1795 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1797 "apt-cache is a low-level tool used to query information\n"
1798 "from APT's binary cache files\n"
1801 " gencaches - Build both the package and source cache\n"
1802 " showpkg - Show some general information for a single package\n"
1803 " showsrc - Show source records\n"
1804 " stats - Show some basic statistics\n"
1805 " dump - Show the entire file in a terse form\n"
1806 " dumpavail - Print an available file to stdout\n"
1807 " unmet - Show unmet dependencies\n"
1808 " search - Search the package list for a regex pattern\n"
1809 " show - Show a readable record for the package\n"
1810 " depends - Show raw dependency information for a package\n"
1811 " rdepends - Show reverse dependency information for a package\n"
1812 " pkgnames - List the names of all packages in the system\n"
1813 " dotty - Generate package graphs for GraphViz\n"
1814 " xvcg - Generate package graphs for xvcg\n"
1815 " policy - Show policy settings\n"
1818 " -h This help text.\n"
1819 " -p=? The package cache.\n"
1820 " -s=? The source cache.\n"
1821 " -q Disable progress indicator.\n"
1822 " -i Show only important deps for the unmet command.\n"
1823 " -c=? Read this configuration file\n"
1824 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1825 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1829 int main(int argc
,const char *argv
[]) /*{{{*/
1831 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1832 {"gencaches",&GenCaches
},
1833 {"showsrc",&ShowSrcPackage
},
1834 {"showpkg",&DumpPackage
},
1837 {"dumpavail",&DumpAvail
},
1840 {"depends",&Depends
},
1841 {"rdepends",&RDepends
},
1844 {"show",&ShowPackage
},
1845 {"pkgnames",&ShowPkgNames
},
1846 {"showauto",&ShowAuto
},
1848 {"madison",&Madison
},
1851 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1853 // Set up gettext support
1854 setlocale(LC_ALL
,"");
1855 textdomain(PACKAGE
);
1857 // Parse the command line and initialize the package library
1858 CommandLine
CmdL(Args
.data(),_config
);
1859 if (pkgInitConfig(*_config
) == false ||
1860 CmdL
.Parse(argc
,argv
) == false ||
1861 pkgInitSystem(*_config
,_system
) == false)
1863 _error
->DumpErrors();
1867 // See if the help should be shown
1868 if (_config
->FindB("help") == true ||
1869 CmdL
.FileSize() == 0)
1875 // Deal with stdout not being a tty
1876 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1877 _config
->Set("quiet","1");
1879 if (_config
->Exists("APT::Cache::Generate") == true)
1880 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1882 // Match the operation
1883 CmdL
.DispatchArg(Cmds
);
1885 // Print any errors or warnings found during parsing
1886 bool const Errors
= _error
->PendingError();
1887 if (_config
->FindI("quiet",0) > 0)
1888 _error
->DumpErrors();
1890 _error
->DumpErrors(GlobalError::DEBUG
);
1891 return Errors
== true ? 100 : 0;