]>
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_pointer_t
*Hashtable
,
276 // hashtable stats for the HashTable
277 unsigned long NumBuckets
= Size
;
278 unsigned long UsedBuckets
= 0;
279 unsigned long UnusedBuckets
= 0;
280 unsigned long LongestBucket
= 0;
281 unsigned long ShortestBucket
= NumBuckets
;
282 unsigned long Entries
= 0;
283 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
285 T
*P
= StartP
+ Hashtable
[i
];
286 if(P
== 0 || P
== StartP
)
292 unsigned long ThisBucketSize
= 0;
293 for (; P
!= StartP
; P
= StartP
+ P
->Next
)
295 Entries
+= ThisBucketSize
;
296 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
297 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
299 cout
<< "Total buckets in " << Type
<< ": " << NumBuckets
<< std::endl
;
300 cout
<< " Unused: " << UnusedBuckets
<< std::endl
;
301 cout
<< " Used: " << UsedBuckets
<< std::endl
;
302 cout
<< " Average entries: " << Entries
/(double)NumBuckets
<< std::endl
;
303 cout
<< " Longest: " << LongestBucket
<< std::endl
;
304 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
307 // Stats - Dump some nice statistics /*{{{*/
308 // ---------------------------------------------------------------------
310 static bool Stats(CommandLine
&)
312 pkgCacheFile CacheFile
;
313 pkgCache
*Cache
= CacheFile
.GetPkgCache();
314 if (unlikely(Cache
== NULL
))
317 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
318 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
319 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
320 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
327 pkgCache::PkgIterator I
= Cache
->PkgBegin();
328 for (;I
.end() != true; ++I
)
330 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
336 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
342 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
345 if (I
.ProvidesList()->NextProvides
== 0)
353 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
359 cout
<< _(" Normal packages: ") << Normal
<< endl
;
360 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
361 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
362 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
363 cout
<< _(" Missing: ") << Missing
<< endl
;
365 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
366 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
367 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
368 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
369 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
370 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
372 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
373 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
374 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
375 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
376 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
377 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
380 unsigned long Size
= 0;
381 unsigned long Count
= 0;
382 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
383 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
386 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
388 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
390 unsigned long DepVerSize
= 0;
391 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
393 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
395 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
398 DepVerSize
+= strlen(D
.TargetVer()) + 1;
402 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
404 unsigned long Slack
= 0;
405 for (int I
= 0; I
!= 7; I
++)
406 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
407 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
409 unsigned long Total
= 0;
410 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
411 Total
= Slack
+ Size
+
412 APT_CACHESIZE(GroupCount
, GroupSz
) +
413 APT_CACHESIZE(PackageCount
, PackageSz
) +
414 APT_CACHESIZE(VersionCount
, VersionSz
) +
415 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
416 APT_CACHESIZE(DependsCount
, DependencySz
) +
417 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
418 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
419 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
420 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
421 (2 * Cache
->Head().HashTableSize
* sizeof(map_id_t
));
422 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
426 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTable(), Cache
->Head().HashTableSize
);
427 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTable(), Cache
->Head().HashTableSize
);
432 // Dump - show everything /*{{{*/
433 // ---------------------------------------------------------------------
434 /* This is worthless except fer debugging things */
435 static bool Dump(CommandLine
&)
437 pkgCacheFile CacheFile
;
438 pkgCache
*Cache
= CacheFile
.GetPkgCache();
439 if (unlikely(Cache
== NULL
))
442 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
444 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
446 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
447 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
449 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
450 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
451 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
452 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
453 DeNull(D
.TargetVer()) << std::endl
;
454 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
456 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
457 << " File: " << D
.FileList().File().FileName() << std::endl
458 << " MD5: " << D
.md5() << std::endl
;
463 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
465 std::cout
<< "File: " << F
.FileName() << std::endl
;
466 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
467 std::cout
<< " Size: " << F
->Size
<< std::endl
;
468 std::cout
<< " ID: " << F
->ID
<< std::endl
;
469 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
470 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
471 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
472 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
473 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
474 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
475 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
476 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
477 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
483 // DumpAvail - Print out the available list /*{{{*/
484 // ---------------------------------------------------------------------
485 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
486 make this run really fast, perhaps I went a little overboard.. */
487 static bool DumpAvail(CommandLine
&)
489 pkgCacheFile CacheFile
;
490 pkgCache
*Cache
= CacheFile
.GetPkgCache();
491 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
494 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
495 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
496 memset(VFList
,0,sizeof(*VFList
)*Count
);
498 // Map versions that we want to write out onto the VerList array.
499 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
501 if (P
->VersionList
== 0)
504 /* Find the proper version to use. If the policy says there are no
505 possible selections we return the installed version, if available..
506 This prevents dselect from making it obsolete. */
507 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
510 if (P
->CurrentVer
== 0)
515 pkgCache::VerFileIterator VF
= V
.FileList();
516 for (; VF
.end() == false ; ++VF
)
517 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
520 /* Okay, here we have a bit of a problem.. The policy has selected the
521 currently installed package - however it only exists in the
522 status file.. We need to write out something or dselect will mark
523 the package as obsolete! Thus we emit the status file entry, but
524 below we remove the status line to make it valid for the
525 available file. However! We only do this if their do exist *any*
526 non-source versions of the package - that way the dselect obsolete
527 handling works OK. */
528 if (VF
.end() == true)
530 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
532 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
534 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
541 if (VF
.end() == false)
549 LocalitySort(VFList
,Count
,sizeof(*VFList
));
551 // Iterate over all the package files and write them out.
552 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
553 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
555 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
556 if (File
.IsOk() == false)
558 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
562 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
563 if (_error
->PendingError() == true)
566 /* Write all of the records from this package file, since we
567 already did locality sorting we can now just seek through the
568 file in read order. We apply 1 more optimization here, since often
569 there will be < 1 byte gaps between records (for the \n) we read that
570 into the next buffer and offset a bit.. */
571 unsigned long Pos
= 0;
574 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
577 const pkgCache::VerFile
&VF
= **J
;
579 // Read the record and then write it out again.
580 unsigned long Jitter
= VF
.Offset
- Pos
;
583 if (PkgF
.Seek(VF
.Offset
) == false)
588 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
590 Buffer
[VF
.Size
+ Jitter
] = '\n';
593 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
596 TFRewriteData RW
[] = {{"Status", NULL
, NULL
},{"Config-Version", NULL
, NULL
},{NULL
, NULL
, NULL
}};
597 const char *Zero
= 0;
598 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
599 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
601 _error
->Error("Internal Error, Unable to parse a package record");
608 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
612 Pos
= VF
.Offset
+ VF
.Size
;
616 if (_error
->PendingError() == true)
622 return !_error
->PendingError();
625 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
626 static bool ShowDepends(CommandLine
&CmdL
, bool const RevDepends
)
628 pkgCacheFile CacheFile
;
629 pkgCache
*Cache
= CacheFile
.GetPkgCache();
630 if (unlikely(Cache
== NULL
))
633 CacheSetHelperVirtuals
helper(false);
634 APT::VersionList verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, APT::VersionList::CANDIDATE
, helper
);
635 if (verset
.empty() == true && helper
.virtualPkgs
.empty() == true)
636 return _error
->Error(_("No packages found"));
637 std::vector
<bool> Shown(Cache
->Head().PackageCount
);
639 bool const Recurse
= _config
->FindB("APT::Cache::RecurseDepends", false);
640 bool const Installed
= _config
->FindB("APT::Cache::Installed", false);
641 bool const Important
= _config
->FindB("APT::Cache::Important", false);
642 bool const ShowDepType
= _config
->FindB("APT::Cache::ShowDependencyType", RevDepends
== false);
643 bool const ShowVersion
= _config
->FindB("APT::Cache::ShowVersion", false);
644 bool const ShowPreDepends
= _config
->FindB("APT::Cache::ShowPre-Depends", true);
645 bool const ShowDepends
= _config
->FindB("APT::Cache::ShowDepends", true);
646 bool const ShowRecommends
= _config
->FindB("APT::Cache::ShowRecommends", Important
== false);
647 bool const ShowSuggests
= _config
->FindB("APT::Cache::ShowSuggests", Important
== false);
648 bool const ShowReplaces
= _config
->FindB("APT::Cache::ShowReplaces", Important
== false);
649 bool const ShowConflicts
= _config
->FindB("APT::Cache::ShowConflicts", Important
== false);
650 bool const ShowBreaks
= _config
->FindB("APT::Cache::ShowBreaks", Important
== false);
651 bool const ShowEnhances
= _config
->FindB("APT::Cache::ShowEnhances", Important
== false);
652 bool const ShowOnlyFirstOr
= _config
->FindB("APT::Cache::ShowOnlyFirstOr", false);
654 while (verset
.empty() != true)
656 pkgCache::VerIterator Ver
= *verset
.begin();
657 verset
.erase(verset
.begin());
658 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
659 Shown
[Pkg
->ID
] = true;
661 cout
<< Pkg
.FullName(true) << endl
;
663 if (RevDepends
== true)
664 cout
<< "Reverse Depends:" << endl
;
665 for (pkgCache::DepIterator D
= RevDepends
? Pkg
.RevDependsList() : Ver
.DependsList();
666 D
.end() == false; ++D
)
669 case pkgCache::Dep::PreDepends
: if (!ShowPreDepends
) continue; break;
670 case pkgCache::Dep::Depends
: if (!ShowDepends
) continue; break;
671 case pkgCache::Dep::Recommends
: if (!ShowRecommends
) continue; break;
672 case pkgCache::Dep::Suggests
: if (!ShowSuggests
) continue; break;
673 case pkgCache::Dep::Replaces
: if (!ShowReplaces
) continue; break; case pkgCache::Dep::Conflicts
: if (!ShowConflicts
) continue; break;
674 case pkgCache::Dep::DpkgBreaks
: if (!ShowBreaks
) continue; break;
675 case pkgCache::Dep::Enhances
: if (!ShowEnhances
) continue; break;
678 pkgCache::PkgIterator Trg
= RevDepends
? D
.ParentPkg() : D
.TargetPkg();
680 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
683 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
&& ShowOnlyFirstOr
== false)
689 if (ShowDepType
== true)
690 cout
<< D
.DepType() << ": ";
691 if (Trg
->VersionList
== 0)
692 cout
<< "<" << Trg
.FullName(true) << ">";
694 cout
<< Trg
.FullName(true);
695 if (ShowVersion
== true && D
->Version
!= 0)
696 cout
<< " (" << pkgCache::CompTypeDeb(D
->CompareOp
) << ' ' << D
.TargetVer() << ')';
699 if (Recurse
== true && Shown
[Trg
->ID
] == false)
701 Shown
[Trg
->ID
] = true;
702 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, Trg
, APT::VersionSet::CANDIDATE
, helper
));
707 // Display all solutions
708 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
709 pkgPrioSortList(*Cache
,List
);
710 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
712 pkgCache::VerIterator
V(*Cache
,*I
);
713 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
714 V
->ParentPkg
== D
->Package
)
716 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
718 if (Recurse
== true && Shown
[V
.ParentPkg()->ID
] == false)
720 Shown
[V
.ParentPkg()->ID
] = true;
721 verset
.insert(APT::VersionSet::FromPackage(CacheFile
, V
.ParentPkg(), APT::VersionSet::CANDIDATE
, helper
));
725 if (ShowOnlyFirstOr
== true)
726 while ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
) ++D
;
730 for (APT::PackageSet::const_iterator Pkg
= helper
.virtualPkgs
.begin();
731 Pkg
!= helper
.virtualPkgs
.end(); ++Pkg
)
732 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
737 // Depends - Print out a dependency tree /*{{{*/
738 // ---------------------------------------------------------------------
740 static bool Depends(CommandLine
&CmdL
)
742 return ShowDepends(CmdL
, false);
745 // RDepends - Print out a reverse dependency tree /*{{{*/
746 // ---------------------------------------------------------------------
748 static bool RDepends(CommandLine
&CmdL
)
750 return ShowDepends(CmdL
, true);
753 // xvcg - Generate a graph for xvcg /*{{{*/
754 // ---------------------------------------------------------------------
755 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
757 static bool XVcg(CommandLine
&CmdL
)
759 pkgCacheFile CacheFile
;
760 pkgCache
*Cache
= CacheFile
.GetPkgCache();
761 if (unlikely(Cache
== NULL
))
764 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
766 /* Normal packages are boxes
767 Pure Provides are triangles
769 rhomb are missing packages*/
770 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
772 /* Initialize the list of packages to show.
774 2 = To Show no recurse
775 3 = Emitted no recurse
778 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
779 enum TheFlags
{ForceNR
=(1<<0)};
780 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
781 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
782 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
784 // Show everything if no arguments given
785 if (CmdL
.FileList
[1] == 0)
786 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
789 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
791 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
794 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
796 if (Pkg
->VersionList
== 0)
799 if (Pkg
->ProvidesList
== 0)
800 ShapeMap
[Pkg
->ID
] = 0;
802 ShapeMap
[Pkg
->ID
] = 1;
807 if (Pkg
->ProvidesList
== 0)
808 ShapeMap
[Pkg
->ID
] = 2;
810 ShapeMap
[Pkg
->ID
] = 3;
814 // Load the list of packages from the command line into the show list
815 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
816 std::list
<APT::PackageSet::Modifier
> mods
;
817 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
818 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
819 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
820 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
822 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
823 Pkg
!= pkgsets
[0].end(); ++Pkg
)
824 Show
[Pkg
->ID
] = ToShow
;
825 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
826 Pkg
!= pkgsets
[1].end(); ++Pkg
)
828 Show
[Pkg
->ID
] = ToShow
;
829 Flags
[Pkg
->ID
] |= ForceNR
;
833 cout
<< "graph: { title: \"packages\"" << endl
<<
834 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
835 "layout_downfactor: 8" << endl
;
841 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
843 // See we need to show this package
844 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
847 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
850 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
852 // Pure Provides and missing packages have no deps!
853 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
854 Show
[Pkg
->ID
] = Done
;
856 Show
[Pkg
->ID
] = DoneNR
;
859 Show
[Pkg
->ID
] = Done
;
862 // No deps to map out
863 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
866 pkgCache::VerIterator Ver
= Pkg
.VersionList();
867 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
869 // See if anything can meet this dep
870 // Walk along the actual package providing versions
872 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
873 for (pkgCache::VerIterator I
= DPkg
.VersionList();
874 I
.end() == false && Hit
== false; ++I
)
876 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
880 // Follow all provides
881 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
882 I
.end() == false && Hit
== false; ++I
)
884 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
889 // Only graph critical deps
890 if (D
.IsCritical() == true)
892 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
894 // Colour the node for recursion
895 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
897 /* If a conflicts does not meet anything in the database
898 then show the relation but do not recurse */
899 if (Hit
== false && D
.IsNegative() == true)
901 if (Show
[D
.TargetPkg()->ID
] == None
&&
902 Show
[D
.TargetPkg()->ID
] != ToShow
)
903 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
907 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
908 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
910 Show
[D
.TargetPkg()->ID
] = ToShow
;
917 case pkgCache::Dep::Conflicts
:
918 printf("label: \"conflicts\" color: lightgreen }\n");
920 case pkgCache::Dep::DpkgBreaks
:
921 printf("label: \"breaks\" color: lightgreen }\n");
923 case pkgCache::Dep::Obsoletes
:
924 printf("label: \"obsoletes\" color: lightgreen }\n");
927 case pkgCache::Dep::PreDepends
:
928 printf("label: \"predepends\" color: blue }\n");
940 /* Draw the box colours after the fact since we can not tell what colour
941 they should be until everything is finished drawing */
942 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
944 if (Show
[Pkg
->ID
] < DoneNR
)
947 if (Show
[Pkg
->ID
] == DoneNR
)
948 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
949 Shapes
[ShapeMap
[Pkg
->ID
]]);
951 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
952 Shapes
[ShapeMap
[Pkg
->ID
]]);
964 // Dotty - Generate a graph for Dotty /*{{{*/
965 // ---------------------------------------------------------------------
966 /* Dotty is the graphvis program for generating graphs. It is a fairly
967 simple queuing algorithm that just writes dependencies and nodes.
968 http://www.research.att.com/sw/tools/graphviz/ */
969 static bool Dotty(CommandLine
&CmdL
)
971 pkgCacheFile CacheFile
;
972 pkgCache
*Cache
= CacheFile
.GetPkgCache();
973 if (unlikely(Cache
== NULL
))
976 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
978 /* Normal packages are boxes
979 Pure Provides are triangles
981 Hexagons are missing packages*/
982 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
984 /* Initialize the list of packages to show.
986 2 = To Show no recurse
987 3 = Emitted no recurse
990 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
991 enum TheFlags
{ForceNR
=(1<<0)};
992 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
993 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
994 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
996 // Show everything if no arguments given
997 if (CmdL
.FileList
[1] == 0)
998 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1001 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
1003 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
1006 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1008 if (Pkg
->VersionList
== 0)
1011 if (Pkg
->ProvidesList
== 0)
1012 ShapeMap
[Pkg
->ID
] = 0;
1014 ShapeMap
[Pkg
->ID
] = 1;
1019 if (Pkg
->ProvidesList
== 0)
1020 ShapeMap
[Pkg
->ID
] = 2;
1022 ShapeMap
[Pkg
->ID
] = 3;
1026 // Load the list of packages from the command line into the show list
1027 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1028 std::list
<APT::PackageSet::Modifier
> mods
;
1029 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1030 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1031 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1032 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
1034 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1035 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1036 Show
[Pkg
->ID
] = ToShow
;
1037 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1038 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1040 Show
[Pkg
->ID
] = ToShow
;
1041 Flags
[Pkg
->ID
] |= ForceNR
;
1045 printf("digraph packages {\n");
1046 printf("concentrate=true;\n");
1047 printf("size=\"30,40\";\n");
1053 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1055 // See we need to show this package
1056 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1060 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1062 // Pure Provides and missing packages have no deps!
1063 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1064 Show
[Pkg
->ID
] = Done
;
1066 Show
[Pkg
->ID
] = DoneNR
;
1069 Show
[Pkg
->ID
] = Done
;
1072 // No deps to map out
1073 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1076 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1077 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
1079 // See if anything can meet this dep
1080 // Walk along the actual package providing versions
1082 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1083 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1084 I
.end() == false && Hit
== false; ++I
)
1086 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1090 // Follow all provides
1091 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1092 I
.end() == false && Hit
== false; ++I
)
1094 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1098 // Only graph critical deps
1099 if (D
.IsCritical() == true)
1101 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1103 // Colour the node for recursion
1104 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1106 /* If a conflicts does not meet anything in the database
1107 then show the relation but do not recurse */
1108 if (Hit
== false && D
.IsNegative() == true)
1110 if (Show
[D
.TargetPkg()->ID
] == None
&&
1111 Show
[D
.TargetPkg()->ID
] != ToShow
)
1112 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1116 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1117 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1119 Show
[D
.TargetPkg()->ID
] = ToShow
;
1126 case pkgCache::Dep::Conflicts
:
1127 case pkgCache::Dep::Obsoletes
:
1128 case pkgCache::Dep::DpkgBreaks
:
1129 printf("[color=springgreen];\n");
1132 case pkgCache::Dep::PreDepends
:
1133 printf("[color=blue];\n");
1145 /* Draw the box colours after the fact since we can not tell what colour
1146 they should be until everything is finished drawing */
1147 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
1149 if (Show
[Pkg
->ID
] < DoneNR
)
1152 // Orange box for early recursion stoppage
1153 if (Show
[Pkg
->ID
] == DoneNR
)
1154 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1155 Shapes
[ShapeMap
[Pkg
->ID
]]);
1157 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1158 Shapes
[ShapeMap
[Pkg
->ID
]]);
1168 // DisplayRecord - Displays the complete record for the package /*{{{*/
1169 // ---------------------------------------------------------------------
1170 /* This displays the package record from the proper package index file.
1171 It is not used by DumpAvail for performance reasons. */
1173 static APT_PURE
unsigned char const* skipDescriptionFields(unsigned char const * DescP
)
1175 char const * const TagName
= "\nDescription";
1176 size_t const TagLen
= strlen(TagName
);
1177 while ((DescP
= (unsigned char*)strchr((char*)DescP
, '\n')) != NULL
)
1179 if (DescP
[1] == ' ')
1181 else if (strncmp((char*)DescP
, TagName
, TagLen
) == 0)
1190 static bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1192 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1193 if (unlikely(Cache
== NULL
))
1196 // Find an appropriate file
1197 pkgCache::VerFileIterator Vf
= V
.FileList();
1198 for (; Vf
.end() == false; ++Vf
)
1199 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1201 if (Vf
.end() == true)
1204 // Check and load the package list file
1205 pkgCache::PkgFileIterator I
= Vf
.File();
1206 if (I
.IsOk() == false)
1207 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1210 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
, FileFd::Extension
) == false)
1213 // Read the record (and ensure that it ends with a newline and NUL)
1214 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+2];
1215 Buffer
[Vf
->Size
] = '\n';
1216 Buffer
[Vf
->Size
+1] = '\0';
1217 if (PkgF
.Seek(Vf
->Offset
) == false ||
1218 PkgF
.Read(Buffer
,Vf
->Size
) == false)
1224 // Get a pointer to start of Description field
1225 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "\nDescription");
1229 DescP
= Buffer
+ Vf
->Size
;
1231 // Write all but Description
1232 size_t const length
= DescP
- Buffer
;
1233 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Buffer
, length
) == false)
1239 // Show the right description
1240 pkgRecords
Recs(*Cache
);
1241 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1242 if (Desc
.end() == false)
1244 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1245 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1246 cout
<< std::endl
<< "Description-md5: " << Desc
.md5() << std::endl
;
1248 // Find the first field after the description (if there is any)
1249 DescP
= skipDescriptionFields(DescP
);
1251 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1253 // write the rest of the buffer, but skip mixed in Descriptions* fields
1254 while (DescP
!= NULL
)
1256 const unsigned char * const Start
= DescP
;
1257 const unsigned char *End
= (unsigned char*)strstr((char*)DescP
, "\nDescription");
1260 End
= &Buffer
[Vf
->Size
];
1265 ++End
; // get the newline into the output
1266 DescP
= skipDescriptionFields(End
+ strlen("Description"));
1268 size_t const length
= End
- Start
;
1269 if (length
!= 0 && FileFd::Write(STDOUT_FILENO
, Start
, length
) == false)
1276 // write a final newline after the last field
1285 pkgCache::DescFile
*Df
;
1289 // Search - Perform a search /*{{{*/
1290 // ---------------------------------------------------------------------
1291 /* This searches the package names and package descriptions for a pattern */
1292 static bool Search(CommandLine
&CmdL
)
1294 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1295 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1296 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1298 pkgCacheFile CacheFile
;
1299 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1300 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1301 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1304 // Make sure there is at least one argument
1305 if (NumPatterns
< 1)
1306 return _error
->Error(_("You must give at least one search pattern"));
1308 // Compile the regex pattern
1309 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1310 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1311 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1313 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1317 regfree(&Patterns
[I
]);
1318 return _error
->Error("Regex compilation error");
1322 if (_error
->PendingError() == true)
1324 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1325 regfree(&Patterns
[I
]);
1329 size_t const descCount
= Cache
->HeaderP
->GroupCount
+ 1;
1330 ExDescFile
*DFList
= new ExDescFile
[descCount
];
1331 memset(DFList
,0,sizeof(*DFList
) * descCount
);
1333 bool *PatternMatch
= new bool[descCount
* NumPatterns
];
1334 memset(PatternMatch
,false,sizeof(*PatternMatch
) * descCount
* NumPatterns
);
1336 // Map versions that we want to write out onto the VerList array.
1337 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1339 size_t const PatternOffset
= G
->ID
* NumPatterns
;
1340 size_t unmatched
= 0, matched
= 0;
1341 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1343 if (PatternMatch
[PatternOffset
+ I
] == true)
1345 else if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1346 PatternMatch
[PatternOffset
+ I
] = true;
1351 // already dealt with this package?
1352 if (matched
== NumPatterns
)
1355 // Doing names only, drop any that don't match..
1356 if (NamesOnly
== true && unmatched
== NumPatterns
)
1359 // Find the proper version to use
1360 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1361 if (P
.end() == true)
1363 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1364 if (V
.end() == false)
1366 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1367 //FIXME: packages without a description can't be found
1368 if (D
.end() == true)
1370 DFList
[G
->ID
].Df
= D
.FileList();
1371 DFList
[G
->ID
].ID
= G
->ID
;
1374 if (unmatched
== NumPatterns
)
1377 // Include all the packages that provide matching names too
1378 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; ++Prv
)
1380 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1381 if (V
.end() == true)
1384 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1385 pkgCache::DescIterator
const D
= V
.TranslatedDescription();
1386 //FIXME: packages without a description can't be found
1387 if (D
.end() == true)
1389 DFList
[id
].Df
= D
.FileList();
1392 size_t const PrvPatternOffset
= id
* NumPatterns
;
1393 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1394 PatternMatch
[PrvPatternOffset
+ I
] = PatternMatch
[PatternOffset
+ I
];
1398 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1400 // Create the text record parser
1401 pkgRecords
Recs(*Cache
);
1402 // Iterate over all the version records and check them
1403 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; ++J
)
1405 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1406 size_t const PatternOffset
= J
->ID
* NumPatterns
;
1408 if (NamesOnly
== false)
1410 string
const LongDesc
= P
.LongDesc();
1411 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1413 if (PatternMatch
[PatternOffset
+ I
] == true)
1415 else if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1416 PatternMatch
[PatternOffset
+ I
] = true;
1420 bool matchedAll
= true;
1421 for (unsigned I
= 0; I
< NumPatterns
; ++I
)
1422 if (PatternMatch
[PatternOffset
+ I
] == false)
1428 if (matchedAll
== true)
1430 if (ShowFull
== true)
1434 P
.GetRec(Start
,End
);
1435 fwrite(Start
,End
-Start
,1,stdout
);
1439 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1444 delete [] PatternMatch
;
1445 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1446 regfree(&Patterns
[I
]);
1448 return _error
->Error("Write to stdout failed");
1452 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1453 static bool ShowAuto(CommandLine
&)
1455 pkgCacheFile CacheFile
;
1456 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1457 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1458 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1461 std::vector
<string
> packages
;
1462 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1464 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
1465 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1466 packages
.push_back(P
.Name());
1468 std::sort(packages
.begin(), packages
.end());
1470 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
1473 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1477 // ShowPackage - Dump the package record to the screen /*{{{*/
1478 // ---------------------------------------------------------------------
1480 static bool ShowPackage(CommandLine
&CmdL
)
1482 pkgCacheFile CacheFile
;
1483 CacheSetHelperVirtuals
helper(true, GlobalError::NOTICE
);
1484 APT::VersionList::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1485 APT::VersionList::ALL
: APT::VersionList::CANDIDATE
;
1486 APT::VersionList
const verset
= APT::VersionList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
, helper
);
1487 for (APT::VersionList::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1488 if (DisplayRecord(CacheFile
, Ver
) == false)
1491 if (verset
.empty() == true)
1493 if (helper
.virtualPkgs
.empty() == true)
1494 return _error
->Error(_("No packages found"));
1496 _error
->Notice(_("No packages found"));
1501 // ShowPkgNames - Show package names /*{{{*/
1502 // ---------------------------------------------------------------------
1503 /* This does a prefix match on the first argument */
1504 static bool ShowPkgNames(CommandLine
&CmdL
)
1506 pkgCacheFile CacheFile
;
1507 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1509 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1510 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1512 if (CmdL
.FileList
[1] != 0)
1514 for (;I
.end() != true; ++I
)
1516 if (All
== false && I
->FirstPackage
== 0)
1518 if (I
.FindPkg("any")->VersionList
== 0)
1520 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1521 cout
<< I
.Name() << endl
;
1528 for (;I
.end() != true; ++I
)
1530 if (All
== false && I
->FirstPackage
== 0)
1532 if (I
.FindPkg("any")->VersionList
== 0)
1534 cout
<< I
.Name() << endl
;
1540 // ShowSrcPackage - Show source package records /*{{{*/
1541 // ---------------------------------------------------------------------
1543 static bool ShowSrcPackage(CommandLine
&CmdL
)
1545 pkgCacheFile CacheFile
;
1546 pkgSourceList
*List
= CacheFile
.GetSourceList();
1547 if (unlikely(List
== NULL
))
1550 // Create the text record parsers
1551 pkgSrcRecords
SrcRecs(*List
);
1552 if (_error
->PendingError() == true)
1556 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1560 pkgSrcRecords::Parser
*Parse
;
1561 unsigned found_this
= 0;
1562 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1563 cout
<< Parse
->AsStr() << endl
;;
1567 if (found_this
== 0) {
1568 _error
->Warning(_("Unable to locate package %s"),*I
);
1573 _error
->Notice(_("No packages found"));
1577 // Policy - Show the results of the preferences file /*{{{*/
1578 // ---------------------------------------------------------------------
1580 static bool Policy(CommandLine
&CmdL
)
1582 pkgCacheFile CacheFile
;
1583 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1584 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1585 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1586 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1589 /* Should the MultiArchKiller be run to see which pseudo packages for an
1590 arch all package are currently installed? Activating it gives a speed
1591 penality for no real gain beside enhanced debugging, so in general no. */
1592 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1593 CacheFile
.GetDepCache();
1595 // Print out all of the package files
1596 if (CmdL
.FileList
[1] == 0)
1598 cout
<< _("Package files:") << endl
;
1599 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
1601 // Locate the associated index files so we can derive a description
1603 if (SrcList
->FindIndex(F
,Indx
) == false &&
1604 _system
->FindIndex(F
,Indx
) == false)
1605 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1608 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1610 // Print the reference information for the package
1611 string Str
= F
.RelStr();
1612 if (Str
.empty() == false)
1613 printf(" release %s\n",F
.RelStr().c_str());
1614 if (F
.Site() != 0 && F
.Site()[0] != 0)
1615 printf(" origin %s\n",F
.Site());
1618 // Show any packages have explicit pins
1619 cout
<< _("Pinned packages:") << endl
;
1620 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1621 for (;I
.end() != true; ++I
)
1623 if (Plcy
->GetPriority(I
) == 0)
1626 // Print the package name and the version we are forcing to
1627 cout
<< " " << I
.FullName(true) << " -> ";
1629 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1630 if (V
.end() == true)
1631 cout
<< _("(not found)") << endl
;
1633 cout
<< V
.VerStr() << endl
;
1639 char const * const msgInstalled
= _(" Installed: ");
1640 char const * const msgCandidate
= _(" Candidate: ");
1641 short const InstalledLessCandidate
=
1642 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1643 short const deepInstalled
=
1644 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1645 short const deepCandidate
=
1646 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1648 // Print out detailed information for each package
1649 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1650 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
1651 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1653 cout
<< Pkg
.FullName(true) << ":" << endl
;
1655 // Installed version
1656 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1657 if (Pkg
->CurrentVer
== 0)
1658 cout
<< _("(none)") << endl
;
1660 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1662 // Candidate Version
1663 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1664 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1665 if (V
.end() == true)
1666 cout
<< _("(none)") << endl
;
1668 cout
<< V
.VerStr() << endl
;
1671 if (Plcy
->GetPriority(Pkg
) != 0)
1673 cout
<< _(" Package pin: ");
1674 V
= Plcy
->GetMatch(Pkg
);
1675 if (V
.end() == true)
1676 cout
<< _("(not found)") << endl
;
1678 cout
<< V
.VerStr() << endl
;
1681 // Show the priority tables
1682 cout
<< _(" Version table:") << endl
;
1683 for (V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1685 if (Pkg
.CurrentVer() == V
)
1686 cout
<< " *** " << V
.VerStr();
1688 cout
<< " " << V
.VerStr();
1689 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1690 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1692 // Locate the associated index files so we can derive a description
1694 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1695 _system
->FindIndex(VF
.File(),Indx
) == false)
1696 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1697 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1698 Indx
->Describe(true).c_str());
1706 // Madison - Look a bit like katie's madison /*{{{*/
1707 // ---------------------------------------------------------------------
1709 static bool Madison(CommandLine
&CmdL
)
1711 pkgCacheFile CacheFile
;
1712 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1717 // Create the src text record parsers and ignore errors about missing
1718 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1719 pkgSrcRecords
SrcRecs(*SrcList
);
1720 if (_error
->PendingError() == true)
1723 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1724 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1726 _error
->PushToStack();
1727 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1728 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1730 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1732 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1734 // This might be nice, but wouldn't uniquely identify the source -mdz
1735 // if (VF.File().Archive() != 0)
1737 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1738 // << VF.File().Archive() << endl;
1741 // Locate the associated index files so we can derive a description
1742 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1744 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1745 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1746 IF
!= Indexes
->end(); ++IF
)
1748 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1750 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1751 << (*IF
)->Describe(true) << endl
;
1760 pkgSrcRecords::Parser
*SrcParser
;
1761 bool foundSomething
= false;
1762 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1764 foundSomething
= true;
1765 // Maybe support Release info here too eventually
1766 cout
<< setw(10) << SrcParser
->Package() << " | "
1767 << setw(10) << SrcParser
->Version() << " | "
1768 << SrcParser
->Index().Describe(true) << endl
;
1770 if (foundSomething
== true)
1771 _error
->RevertToStack();
1773 _error
->MergeWithStack();
1779 // GenCaches - Call the main cache generator /*{{{*/
1780 // ---------------------------------------------------------------------
1782 static bool GenCaches(CommandLine
&)
1784 OpTextProgress
Progress(*_config
);
1786 pkgCacheFile CacheFile
;
1787 return CacheFile
.BuildCaches(&Progress
, true);
1790 // ShowHelp - Show a help screen /*{{{*/
1791 // ---------------------------------------------------------------------
1793 static bool ShowHelp(CommandLine
&)
1795 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,PACKAGE_VERSION
,
1796 COMMON_ARCH
,__DATE__
,__TIME__
);
1798 if (_config
->FindB("version") == true)
1802 _("Usage: apt-cache [options] command\n"
1803 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1804 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1806 "apt-cache is a low-level tool used to query information\n"
1807 "from APT's binary cache files\n"
1810 " gencaches - Build both the package and source cache\n"
1811 " showpkg - Show some general information for a single package\n"
1812 " showsrc - Show source records\n"
1813 " stats - Show some basic statistics\n"
1814 " dump - Show the entire file in a terse form\n"
1815 " dumpavail - Print an available file to stdout\n"
1816 " unmet - Show unmet dependencies\n"
1817 " search - Search the package list for a regex pattern\n"
1818 " show - Show a readable record for the package\n"
1819 " depends - Show raw dependency information for a package\n"
1820 " rdepends - Show reverse dependency information for a package\n"
1821 " pkgnames - List the names of all packages in the system\n"
1822 " dotty - Generate package graphs for GraphViz\n"
1823 " xvcg - Generate package graphs for xvcg\n"
1824 " policy - Show policy settings\n"
1827 " -h This help text.\n"
1828 " -p=? The package cache.\n"
1829 " -s=? The source cache.\n"
1830 " -q Disable progress indicator.\n"
1831 " -i Show only important deps for the unmet command.\n"
1832 " -c=? Read this configuration file\n"
1833 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1834 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1838 int main(int argc
,const char *argv
[]) /*{{{*/
1840 CommandLine::Dispatch Cmds
[] = {{"help",&ShowHelp
},
1841 {"gencaches",&GenCaches
},
1842 {"showsrc",&ShowSrcPackage
},
1843 {"showpkg",&DumpPackage
},
1846 {"dumpavail",&DumpAvail
},
1849 {"depends",&Depends
},
1850 {"rdepends",&RDepends
},
1853 {"show",&ShowPackage
},
1854 {"pkgnames",&ShowPkgNames
},
1855 {"showauto",&ShowAuto
},
1857 {"madison",&Madison
},
1860 std::vector
<CommandLine::Args
> Args
= getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds
, argc
, argv
));
1862 // Set up gettext support
1863 setlocale(LC_ALL
,"");
1864 textdomain(PACKAGE
);
1866 // Parse the command line and initialize the package library
1867 CommandLine
CmdL(Args
.data(),_config
);
1868 if (pkgInitConfig(*_config
) == false ||
1869 CmdL
.Parse(argc
,argv
) == false ||
1870 pkgInitSystem(*_config
,_system
) == false)
1872 _error
->DumpErrors();
1876 // See if the help should be shown
1877 if (_config
->FindB("help") == true ||
1878 CmdL
.FileSize() == 0)
1884 // Deal with stdout not being a tty
1885 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1886 _config
->Set("quiet","1");
1888 if (_config
->Exists("APT::Cache::Generate") == true)
1889 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1891 // Match the operation
1892 CmdL
.DispatchArg(Cmds
);
1894 // Print any errors or warnings found during parsing
1895 bool const Errors
= _error
->PendingError();
1896 if (_config
->FindI("quiet",0) > 0)
1897 _error
->DumpErrors();
1899 _error
->DumpErrors(GlobalError::DEBUG
);
1900 return Errors
== true ? 100 : 0;