]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
4 /* ######################################################################
6 apt-cache - Manages the cache files
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools.
11 Returns 100 on failure, 0 on success.
13 ##################################################################### */
15 // Include Files /*{{{*/
16 #include <apt-pkg/error.h>
18 #include <apt-pkg/pkgcachegen.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/init.h>
21 #include <apt-pkg/progress.h>
22 #include <apt-pkg/sourcelist.h>
23 #include <apt-pkg/cmndline.h>
24 #include <apt-pkg/strutl.h>
25 #include <apt-pkg/pkgrecords.h>
26 #include <apt-pkg/srcrecords.h>
27 #include <apt-pkg/version.h>
28 #include <apt-pkg/policy.h>
29 #include <apt-pkg/tagfile.h>
30 #include <apt-pkg/algorithms.h>
31 #include <apt-pkg/sptr.h>
32 #include <apt-pkg/cacheset.h>
49 // LocalitySort - Sort a version list by package file locality /*{{{*/
50 // ---------------------------------------------------------------------
52 int LocalityCompare(const void *a
, const void *b
)
54 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
55 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
64 if (A
->File
== B
->File
)
65 return A
->Offset
- B
->Offset
;
66 return A
->File
- B
->File
;
69 void LocalitySort(pkgCache::VerFile
**begin
,
70 unsigned long Count
,size_t Size
)
72 qsort(begin
,Count
,Size
,LocalityCompare
);
75 void LocalitySort(pkgCache::DescFile
**begin
,
76 unsigned long Count
,size_t Size
)
78 qsort(begin
,Count
,Size
,LocalityCompare
);
81 // UnMet - Show unmet dependencies /*{{{*/
82 // ---------------------------------------------------------------------
84 bool UnMet(CommandLine
&CmdL
)
86 bool const Important
= _config
->FindB("APT::Cache::Important",false);
88 pkgCacheFile CacheFile
;
89 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
92 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; P
++)
94 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
97 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
100 pkgCache::DepIterator Start
;
101 pkgCache::DepIterator End
;
104 // Skip conflicts and replaces
105 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
106 End
->Type
!= pkgCache::Dep::Depends
&&
107 End
->Type
!= pkgCache::Dep::Suggests
&&
108 End
->Type
!= pkgCache::Dep::Recommends
)
111 // Important deps only
112 if (Important
== true)
113 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
114 End
->Type
!= pkgCache::Dep::Depends
)
117 // Verify the or group
119 pkgCache::DepIterator RealStart
= Start
;
122 // See if this dep is Ok
123 pkgCache::Version
**VList
= Start
.AllTargets();
144 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
145 P
.FullName(true).c_str(),V
.VerStr());
148 // Print out the dep type
149 cout
<< " " << End
.DepType() << ": ";
155 cout
<< Start
.TargetPkg().FullName(true);
156 if (Start
.TargetVer() != 0)
157 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
173 // DumpPackage - Show a dump of a package record /*{{{*/
174 // ---------------------------------------------------------------------
176 bool DumpPackage(CommandLine
&CmdL
)
178 pkgCacheFile CacheFile
;
179 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
181 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
183 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
184 cout
<< "Versions: " << endl
;
185 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
187 cout
<< Cur
.VerStr();
188 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
189 cout
<< " (" << Vf
.File().FileName() << ")";
191 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; D
++)
193 cout
<< " Description Language: " << D
.LanguageCode() << endl
194 << " File: " << D
.FileList().File().FileName() << endl
195 << " MD5: " << D
.md5() << endl
;
202 cout
<< "Reverse Depends: " << endl
;
203 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
205 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
207 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
212 cout
<< "Dependencies: " << endl
;
213 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
215 cout
<< Cur
.VerStr() << " - ";
216 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
217 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
221 cout
<< "Provides: " << endl
;
222 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
224 cout
<< Cur
.VerStr() << " - ";
225 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
226 cout
<< Prv
.ParentPkg().FullName(true) << " ";
229 cout
<< "Reverse Provides: " << endl
;
230 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
231 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
237 // Stats - Dump some nice statistics /*{{{*/
238 // ---------------------------------------------------------------------
240 bool Stats(CommandLine
&Cmd
)
242 pkgCacheFile CacheFile
;
243 pkgCache
*Cache
= CacheFile
.GetPkgCache();
244 if (unlikely(Cache
== NULL
))
247 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
248 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
249 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
250 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
257 pkgCache::PkgIterator I
= Cache
->PkgBegin();
258 for (;I
.end() != true; I
++)
260 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
266 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
272 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
275 if (I
.ProvidesList()->NextProvides
== 0)
283 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
289 cout
<< _(" Normal packages: ") << Normal
<< endl
;
290 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
291 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
292 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
293 cout
<< _(" Missing: ") << Missing
<< endl
;
295 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
296 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
297 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
298 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
299 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
300 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
302 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
303 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
304 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
305 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
306 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
307 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
310 unsigned long Size
= 0;
311 unsigned long Count
= 0;
312 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
313 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
316 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
318 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
320 unsigned long DepVerSize
= 0;
321 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
323 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
325 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
328 DepVerSize
+= strlen(D
.TargetVer()) + 1;
332 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
334 unsigned long Slack
= 0;
335 for (int I
= 0; I
!= 7; I
++)
336 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
337 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
339 unsigned long Total
= 0;
340 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
341 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
342 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
343 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
344 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
345 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
350 // Dump - show everything /*{{{*/
351 // ---------------------------------------------------------------------
352 /* This is worthless except fer debugging things */
353 bool Dump(CommandLine
&Cmd
)
355 pkgCacheFile CacheFile
;
356 pkgCache
*Cache
= CacheFile
.GetPkgCache();
357 if (unlikely(Cache
== NULL
))
360 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
362 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
364 cout
<< "Package: " << P
.FullName(true) << endl
;
365 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
367 cout
<< " Version: " << V
.VerStr() << endl
;
368 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
369 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
370 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
371 DeNull(D
.TargetVer()) << endl
;
372 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; D
++)
374 cout
<< " Description Language: " << D
.LanguageCode() << endl
375 << " File: " << D
.FileList().File().FileName() << endl
376 << " MD5: " << D
.md5() << endl
;
381 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
383 cout
<< "File: " << F
.FileName() << endl
;
384 cout
<< " Type: " << F
.IndexType() << endl
;
385 cout
<< " Size: " << F
->Size
<< endl
;
386 cout
<< " ID: " << F
->ID
<< endl
;
387 cout
<< " Flags: " << F
->Flags
<< endl
;
388 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
389 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
390 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
391 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
392 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
393 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
394 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
395 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
401 // DumpAvail - Print out the available list /*{{{*/
402 // ---------------------------------------------------------------------
403 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
404 make this run really fast, perhaps I went a little overboard.. */
405 bool DumpAvail(CommandLine
&Cmd
)
407 pkgCacheFile CacheFile
;
408 pkgCache
*Cache
= CacheFile
.GetPkgCache();
409 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
412 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
413 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
414 memset(VFList
,0,sizeof(*VFList
)*Count
);
416 // Map versions that we want to write out onto the VerList array.
417 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
419 if (P
->VersionList
== 0)
422 /* Find the proper version to use. If the policy says there are no
423 possible selections we return the installed version, if available..
424 This prevents dselect from making it obsolete. */
425 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
428 if (P
->CurrentVer
== 0)
433 pkgCache::VerFileIterator VF
= V
.FileList();
434 for (; VF
.end() == false ; VF
++)
435 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
438 /* Okay, here we have a bit of a problem.. The policy has selected the
439 currently installed package - however it only exists in the
440 status file.. We need to write out something or dselect will mark
441 the package as obsolete! Thus we emit the status file entry, but
442 below we remove the status line to make it valid for the
443 available file. However! We only do this if their do exist *any*
444 non-source versions of the package - that way the dselect obsolete
445 handling works OK. */
446 if (VF
.end() == true)
448 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
450 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
452 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
459 if (VF
.end() == false)
467 LocalitySort(VFList
,Count
,sizeof(*VFList
));
469 // Iterate over all the package files and write them out.
470 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
471 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
473 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
474 if (File
.IsOk() == false)
476 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
480 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
481 if (_error
->PendingError() == true)
484 /* Write all of the records from this package file, since we
485 already did locality sorting we can now just seek through the
486 file in read order. We apply 1 more optimization here, since often
487 there will be < 1 byte gaps between records (for the \n) we read that
488 into the next buffer and offset a bit.. */
489 unsigned long Pos
= 0;
492 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
495 const pkgCache::VerFile
&VF
= **J
;
497 // Read the record and then write it out again.
498 unsigned long Jitter
= VF
.Offset
- Pos
;
501 if (PkgF
.Seek(VF
.Offset
) == false)
506 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
508 Buffer
[VF
.Size
+ Jitter
] = '\n';
511 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
514 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
515 const char *Zero
= 0;
516 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
517 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
519 _error
->Error("Internal Error, Unable to parse a package record");
526 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
530 Pos
= VF
.Offset
+ VF
.Size
;
534 if (_error
->PendingError() == true)
540 return !_error
->PendingError();
543 // Depends - Print out a dependency tree /*{{{*/
544 // ---------------------------------------------------------------------
546 bool Depends(CommandLine
&CmdL
)
548 pkgCacheFile CacheFile
;
549 pkgCache
*Cache
= CacheFile
.GetPkgCache();
550 if (unlikely(Cache
== NULL
))
553 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
554 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
556 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
557 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
558 Colours
[Pkg
->ID
] = 1;
560 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
561 bool Installed
= _config
->FindB("APT::Cache::Installed",false);
562 bool Important
= _config
->FindB("APT::Cache::Important",false);
566 DidSomething
= false;
567 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
569 if (Colours
[Pkg
->ID
] != 1)
571 Colours
[Pkg
->ID
] = 2;
574 pkgCache::VerIterator Ver
= Pkg
.VersionList();
575 if (Ver
.end() == true)
577 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
581 cout
<< Pkg
.FullName(true) << endl
;
583 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
585 // Important deps only
586 if (Important
== true)
587 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
588 D
->Type
!= pkgCache::Dep::Depends
)
591 pkgCache::PkgIterator Trg
= D
.TargetPkg();
593 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
596 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
602 if (Trg
->VersionList
== 0)
603 cout
<< D
.DepType() << ": <" << Trg
.FullName(true) << ">" << endl
;
605 cout
<< D
.DepType() << ": " << Trg
.FullName(true) << endl
;
608 Colours
[D
.TargetPkg()->ID
]++;
612 // Display all solutions
613 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
614 pkgPrioSortList(*Cache
,List
);
615 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
617 pkgCache::VerIterator
V(*Cache
,*I
);
618 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
619 V
->ParentPkg
== D
->Package
)
621 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
624 Colours
[D
.ParentPkg()->ID
]++;
629 while (DidSomething
== true);
634 // RDepends - Print out a reverse dependency tree - mbc /*{{{*/
635 // ---------------------------------------------------------------------
637 bool RDepends(CommandLine
&CmdL
)
639 pkgCacheFile CacheFile
;
640 pkgCache
*Cache
= CacheFile
.GetPkgCache();
641 if (unlikely(Cache
== NULL
))
644 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
645 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
647 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
648 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
649 Colours
[Pkg
->ID
] = 1;
651 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
652 bool Installed
= _config
->FindB("APT::Cache::Installed",false);
656 DidSomething
= false;
657 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
659 if (Colours
[Pkg
->ID
] != 1)
661 Colours
[Pkg
->ID
] = 2;
664 pkgCache::VerIterator Ver
= Pkg
.VersionList();
665 if (Ver
.end() == true)
667 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
671 cout
<< Pkg
.FullName(true) << endl
;
673 cout
<< "Reverse Depends:" << endl
;
674 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() == false; D
++)
677 pkgCache::PkgIterator Trg
= D
.ParentPkg();
679 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
682 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
687 if (Trg
->VersionList
== 0)
688 cout
<< D
.DepType() << ": <" << Trg
.FullName(true) << ">" << endl
;
690 cout
<< Trg
.FullName(true) << endl
;
693 Colours
[D
.ParentPkg()->ID
]++;
697 // Display all solutions
698 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
699 pkgPrioSortList(*Cache
,List
);
700 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
702 pkgCache::VerIterator
V(*Cache
,*I
);
703 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
704 V
->ParentPkg
== D
->Package
)
706 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
709 Colours
[D
.ParentPkg()->ID
]++;
714 while (DidSomething
== true);
719 // xvcg - Generate a graph for xvcg /*{{{*/
720 // ---------------------------------------------------------------------
721 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
723 bool XVcg(CommandLine
&CmdL
)
725 pkgCacheFile CacheFile
;
726 pkgCache
*Cache
= CacheFile
.GetPkgCache();
727 if (unlikely(Cache
== NULL
))
730 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
732 /* Normal packages are boxes
733 Pure Provides are triangles
735 rhomb are missing packages*/
736 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
738 /* Initialize the list of packages to show.
740 2 = To Show no recurse
741 3 = Emitted no recurse
744 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
745 enum TheFlags
{ForceNR
=(1<<0)};
746 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
747 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
748 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
750 // Show everything if no arguments given
751 if (CmdL
.FileList
[1] == 0)
752 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
755 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
757 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
760 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
762 if (Pkg
->VersionList
== 0)
765 if (Pkg
->ProvidesList
== 0)
766 ShapeMap
[Pkg
->ID
] = 0;
768 ShapeMap
[Pkg
->ID
] = 1;
773 if (Pkg
->ProvidesList
== 0)
774 ShapeMap
[Pkg
->ID
] = 2;
776 ShapeMap
[Pkg
->ID
] = 3;
780 // Load the list of packages from the command line into the show list
781 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
783 // Process per-package flags
788 if (P
.end()[-1] == '^')
794 if (P
.end()[-1] == ',')
798 // Locate the package
799 pkgCache::PkgIterator Pkg
= Cache
->FindPkg(P
);
800 if (Pkg
.end() == true)
802 _error
->Warning(_("Unable to locate package %s"),*I
);
805 Show
[Pkg
->ID
] = ToShow
;
808 Flags
[Pkg
->ID
] |= ForceNR
;
812 cout
<< "graph: { title: \"packages\"" << endl
<<
813 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
814 "layout_downfactor: 8" << endl
;
820 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
822 // See we need to show this package
823 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
826 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
829 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
831 // Pure Provides and missing packages have no deps!
832 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
833 Show
[Pkg
->ID
] = Done
;
835 Show
[Pkg
->ID
] = DoneNR
;
838 Show
[Pkg
->ID
] = Done
;
841 // No deps to map out
842 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
845 pkgCache::VerIterator Ver
= Pkg
.VersionList();
846 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
848 // See if anything can meet this dep
849 // Walk along the actual package providing versions
851 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
852 for (pkgCache::VerIterator I
= DPkg
.VersionList();
853 I
.end() == false && Hit
== false; I
++)
855 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
859 // Follow all provides
860 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
861 I
.end() == false && Hit
== false; I
++)
863 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
868 // Only graph critical deps
869 if (D
.IsCritical() == true)
871 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
873 // Colour the node for recursion
874 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
876 /* If a conflicts does not meet anything in the database
877 then show the relation but do not recurse */
879 (D
->Type
== pkgCache::Dep::Conflicts
||
880 D
->Type
== pkgCache::Dep::DpkgBreaks
||
881 D
->Type
== pkgCache::Dep::Obsoletes
))
883 if (Show
[D
.TargetPkg()->ID
] == None
&&
884 Show
[D
.TargetPkg()->ID
] != ToShow
)
885 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
889 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
890 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
892 Show
[D
.TargetPkg()->ID
] = ToShow
;
899 case pkgCache::Dep::Conflicts
:
900 printf("label: \"conflicts\" color: lightgreen }\n");
902 case pkgCache::Dep::DpkgBreaks
:
903 printf("label: \"breaks\" color: lightgreen }\n");
905 case pkgCache::Dep::Obsoletes
:
906 printf("label: \"obsoletes\" color: lightgreen }\n");
909 case pkgCache::Dep::PreDepends
:
910 printf("label: \"predepends\" color: blue }\n");
922 /* Draw the box colours after the fact since we can not tell what colour
923 they should be until everything is finished drawing */
924 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
926 if (Show
[Pkg
->ID
] < DoneNR
)
929 if (Show
[Pkg
->ID
] == DoneNR
)
930 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
931 Shapes
[ShapeMap
[Pkg
->ID
]]);
933 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
934 Shapes
[ShapeMap
[Pkg
->ID
]]);
946 // Dotty - Generate a graph for Dotty /*{{{*/
947 // ---------------------------------------------------------------------
948 /* Dotty is the graphvis program for generating graphs. It is a fairly
949 simple queuing algorithm that just writes dependencies and nodes.
950 http://www.research.att.com/sw/tools/graphviz/ */
951 bool Dotty(CommandLine
&CmdL
)
953 pkgCacheFile CacheFile
;
954 pkgCache
*Cache
= CacheFile
.GetPkgCache();
955 if (unlikely(Cache
== NULL
))
958 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
960 /* Normal packages are boxes
961 Pure Provides are triangles
963 Hexagons are missing packages*/
964 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
966 /* Initialize the list of packages to show.
968 2 = To Show no recurse
969 3 = Emitted no recurse
972 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
973 enum TheFlags
{ForceNR
=(1<<0)};
974 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
975 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
976 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
978 // Show everything if no arguments given
979 if (CmdL
.FileList
[1] == 0)
980 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
983 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
985 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
988 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
990 if (Pkg
->VersionList
== 0)
993 if (Pkg
->ProvidesList
== 0)
994 ShapeMap
[Pkg
->ID
] = 0;
996 ShapeMap
[Pkg
->ID
] = 1;
1001 if (Pkg
->ProvidesList
== 0)
1002 ShapeMap
[Pkg
->ID
] = 2;
1004 ShapeMap
[Pkg
->ID
] = 3;
1008 // Load the list of packages from the command line into the show list
1009 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1011 // Process per-package flags
1016 if (P
.end()[-1] == '^')
1022 if (P
.end()[-1] == ',')
1026 // Locate the package
1027 pkgCache::PkgIterator Pkg
= Cache
->FindPkg(P
);
1028 if (Pkg
.end() == true)
1030 _error
->Warning(_("Unable to locate package %s"),*I
);
1033 Show
[Pkg
->ID
] = ToShow
;
1036 Flags
[Pkg
->ID
] |= ForceNR
;
1040 printf("digraph packages {\n");
1041 printf("concentrate=true;\n");
1042 printf("size=\"30,40\";\n");
1048 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1050 // See we need to show this package
1051 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1055 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1057 // Pure Provides and missing packages have no deps!
1058 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1059 Show
[Pkg
->ID
] = Done
;
1061 Show
[Pkg
->ID
] = DoneNR
;
1064 Show
[Pkg
->ID
] = Done
;
1067 // No deps to map out
1068 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1071 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1072 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
1074 // See if anything can meet this dep
1075 // Walk along the actual package providing versions
1077 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1078 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1079 I
.end() == false && Hit
== false; I
++)
1081 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1085 // Follow all provides
1086 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1087 I
.end() == false && Hit
== false; I
++)
1089 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1093 // Only graph critical deps
1094 if (D
.IsCritical() == true)
1096 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1098 // Colour the node for recursion
1099 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1101 /* If a conflicts does not meet anything in the database
1102 then show the relation but do not recurse */
1104 (D
->Type
== pkgCache::Dep::Conflicts
||
1105 D
->Type
== pkgCache::Dep::Obsoletes
))
1107 if (Show
[D
.TargetPkg()->ID
] == None
&&
1108 Show
[D
.TargetPkg()->ID
] != ToShow
)
1109 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1113 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1114 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1116 Show
[D
.TargetPkg()->ID
] = ToShow
;
1123 case pkgCache::Dep::Conflicts
:
1124 case pkgCache::Dep::Obsoletes
:
1125 printf("[color=springgreen];\n");
1128 case pkgCache::Dep::PreDepends
:
1129 printf("[color=blue];\n");
1141 /* Draw the box colours after the fact since we can not tell what colour
1142 they should be until everything is finished drawing */
1143 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1145 if (Show
[Pkg
->ID
] < DoneNR
)
1148 // Orange box for early recursion stoppage
1149 if (Show
[Pkg
->ID
] == DoneNR
)
1150 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1151 Shapes
[ShapeMap
[Pkg
->ID
]]);
1153 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1154 Shapes
[ShapeMap
[Pkg
->ID
]]);
1161 // DoAdd - Perform an adding operation /*{{{*/
1162 // ---------------------------------------------------------------------
1164 bool DoAdd(CommandLine
&CmdL
)
1166 return _error
->Error("Unimplemented");
1168 // Make sure there is at least one argument
1169 if (CmdL
.FileSize() <= 1)
1170 return _error
->Error("You must give at least one file name");
1173 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
1174 if (_error
->PendingError() == true)
1177 DynamicMMap
Map(CacheF
,MMap::Public
);
1178 if (_error
->PendingError() == true)
1181 OpTextProgress
Progress(*_config
);
1182 pkgCacheGenerator
Gen(Map
,Progress
);
1183 if (_error
->PendingError() == true)
1186 unsigned long Length
= CmdL
.FileSize() - 1;
1187 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1189 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
1190 Progress
.SubProgress(Length
);
1193 FileFd
TagF(*I
,FileFd::ReadOnly
);
1194 debListParser
Parser(TagF
);
1195 if (_error
->PendingError() == true)
1196 return _error
->Error("Problem opening %s",*I
);
1198 if (Gen
.SelectFile(*I
,"") == false)
1199 return _error
->Error("Problem with SelectFile");
1201 if (Gen
.MergeList(Parser
) == false)
1202 return _error
->Error("Problem with MergeList");
1206 GCache
= &Gen
.GetCache();
1213 // DisplayRecord - Displays the complete record for the package /*{{{*/
1214 // ---------------------------------------------------------------------
1215 /* This displays the package record from the proper package index file.
1216 It is not used by DumpAvail for performance reasons. */
1217 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1219 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1220 if (unlikely(Cache
== NULL
))
1223 // Find an appropriate file
1224 pkgCache::VerFileIterator Vf
= V
.FileList();
1225 for (; Vf
.end() == false; Vf
++)
1226 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1228 if (Vf
.end() == true)
1231 // Check and load the package list file
1232 pkgCache::PkgFileIterator I
= Vf
.File();
1233 if (I
.IsOk() == false)
1234 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1236 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
1237 if (_error
->PendingError() == true)
1241 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1242 Buffer
[V
.FileList()->Size
] = '\n';
1243 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1244 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1250 // Get a pointer to start of Description field
1251 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1253 // Write all but Description
1254 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1260 // Show the right description
1261 pkgRecords
Recs(*Cache
);
1262 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1263 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1264 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1266 // Find the first field after the description (if there is any)
1267 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1269 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1271 // write the rest of the buffer
1272 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1273 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1282 // write a final newline (after the description)
1292 pkgCache::DescFile
*Df
;
1296 // Search - Perform a search /*{{{*/
1297 // ---------------------------------------------------------------------
1298 /* This searches the package names and package descriptions for a pattern */
1299 bool Search(CommandLine
&CmdL
)
1301 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1302 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1303 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1305 pkgCacheFile CacheFile
;
1306 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1307 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1308 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1311 // Make sure there is at least one argument
1312 if (NumPatterns
< 1)
1313 return _error
->Error(_("You must give at least one search pattern"));
1315 // Compile the regex pattern
1316 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1317 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1318 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1320 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1324 regfree(&Patterns
[I
]);
1325 return _error
->Error("Regex compilation error");
1329 if (_error
->PendingError() == true)
1331 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1332 regfree(&Patterns
[I
]);
1336 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1337 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1339 // Map versions that we want to write out onto the VerList array.
1340 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1342 if (DFList
[G
->ID
].NameMatch
== true)
1345 DFList
[G
->ID
].NameMatch
= true;
1346 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1348 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1350 DFList
[G
->ID
].NameMatch
= false;
1354 // Doing names only, drop any that dont match..
1355 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1358 // Find the proper version to use
1359 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1360 if (P
.end() == true)
1362 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1363 if (V
.end() == false)
1364 DFList
[G
->ID
].Df
= V
.DescriptionList().FileList();
1366 if (DFList
[G
->ID
].NameMatch
== false)
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 DFList
[id
].Df
= V
.DescriptionList().FileList();
1378 DFList
[id
].NameMatch
= true;
1382 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1384 // Create the text record parser
1385 pkgRecords
Recs(*Cache
);
1386 // Iterate over all the version records and check them
1387 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1389 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1391 if (J
->NameMatch
== false && NamesOnly
== false)
1393 string
const LongDesc
= P
.LongDesc();
1394 J
->NameMatch
= true;
1395 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1397 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1399 J
->NameMatch
= false;
1404 if (J
->NameMatch
== true)
1406 if (ShowFull
== true)
1410 P
.GetRec(Start
,End
);
1411 fwrite(Start
,End
-Start
,1,stdout
);
1415 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1420 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1421 regfree(&Patterns
[I
]);
1423 return _error
->Error("Write to stdout failed");
1428 /* show automatically installed packages (sorted) */
1429 bool ShowAuto(CommandLine
&CmdL
)
1431 pkgCacheFile CacheFile
;
1432 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1433 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1434 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1437 std::vector
<string
> packages
;
1438 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1440 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
1441 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1442 packages
.push_back(P
.Name());
1444 std::sort(packages
.begin(), packages
.end());
1446 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); I
++)
1452 // ShowPackage - Dump the package record to the screen /*{{{*/
1453 // ---------------------------------------------------------------------
1455 bool ShowPackage(CommandLine
&CmdL
)
1457 pkgCacheFile CacheFile
;
1458 APT::VersionSet::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1459 APT::VersionSet::ALL
: APT::VersionSet::CANDIDATE
;
1460 APT::VersionSet
const verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
);
1461 for (APT::VersionSet::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1462 if (DisplayRecord(CacheFile
, Ver
) == false)
1465 if (verset
.empty() == false)
1467 return _error
->Error(_("No packages found"));
1470 // ShowPkgNames - Show package names /*{{{*/
1471 // ---------------------------------------------------------------------
1472 /* This does a prefix match on the first argument */
1473 bool ShowPkgNames(CommandLine
&CmdL
)
1475 pkgCacheFile CacheFile
;
1476 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1478 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1479 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1481 if (CmdL
.FileList
[1] != 0)
1483 for (;I
.end() != true; I
++)
1485 if (All
== false && I
->FirstPackage
== 0)
1487 if (I
.FindPkg("any")->VersionList
== 0)
1489 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1490 cout
<< I
.Name() << endl
;
1497 for (;I
.end() != true; I
++)
1499 if (All
== false && I
->FirstPackage
== 0)
1501 if (I
.FindPkg("any")->VersionList
== 0)
1503 cout
<< I
.Name() << endl
;
1509 // ShowSrcPackage - Show source package records /*{{{*/
1510 // ---------------------------------------------------------------------
1512 bool ShowSrcPackage(CommandLine
&CmdL
)
1514 pkgCacheFile CacheFile
;
1515 pkgSourceList
*List
= CacheFile
.GetSourceList();
1516 if (unlikely(List
== NULL
))
1519 // Create the text record parsers
1520 pkgSrcRecords
SrcRecs(*List
);
1521 if (_error
->PendingError() == true)
1525 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1529 pkgSrcRecords::Parser
*Parse
;
1530 unsigned found_this
= 0;
1531 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1532 cout
<< Parse
->AsStr() << endl
;;
1536 if (found_this
== 0) {
1537 _error
->Warning(_("Unable to locate package %s"),*I
);
1543 return _error
->Error(_("No packages found"));
1546 // Policy - Show the results of the preferences file /*{{{*/
1547 // ---------------------------------------------------------------------
1549 bool Policy(CommandLine
&CmdL
)
1551 pkgCacheFile CacheFile
;
1552 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1553 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1554 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1555 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1558 /* Should the MultiArchKiller be run to see which pseudo packages for an
1559 arch all package are currently installed? Activating it gives a speed
1560 penality for no real gain beside enhanced debugging, so in general no. */
1561 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1562 CacheFile
.GetDepCache();
1564 // Print out all of the package files
1565 if (CmdL
.FileList
[1] == 0)
1567 cout
<< _("Package files:") << endl
;
1568 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
1570 // Locate the associated index files so we can derive a description
1572 if (SrcList
->FindIndex(F
,Indx
) == false &&
1573 _system
->FindIndex(F
,Indx
) == false)
1574 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1577 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1579 // Print the reference information for the package
1580 string Str
= F
.RelStr();
1581 if (Str
.empty() == false)
1582 printf(" release %s\n",F
.RelStr().c_str());
1583 if (F
.Site() != 0 && F
.Site()[0] != 0)
1584 printf(" origin %s\n",F
.Site());
1587 // Show any packages have explicit pins
1588 cout
<< _("Pinned packages:") << endl
;
1589 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1590 for (;I
.end() != true; I
++)
1592 if (Plcy
->GetPriority(I
) == 0)
1595 // Print the package name and the version we are forcing to
1596 cout
<< " " << I
.FullName(true) << " -> ";
1598 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1599 if (V
.end() == true)
1600 cout
<< _("(not found)") << endl
;
1602 cout
<< V
.VerStr() << endl
;
1608 string
const myArch
= _config
->Find("APT::Architecture");
1609 char const * const msgInstalled
= _(" Installed: ");
1610 char const * const msgCandidate
= _(" Candidate: ");
1611 short const InstalledLessCandidate
=
1612 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1613 short const deepInstalled
=
1614 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1615 short const deepCandidate
=
1616 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1618 // Print out detailed information for each package
1619 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1620 for (APT::PackageSet::const_iterator I
= pkgset
.begin(); I
!= pkgset
.end(); ++I
)
1622 pkgCache::PkgIterator Pkg
= I
.Group().FindPkg("any");
1624 for (; Pkg
.end() != true; Pkg
= I
.Group().NextPkg(Pkg
)) {
1625 if (strcmp(Pkg
.Arch(),"all") == 0)
1628 cout
<< Pkg
.FullName(true) << ":" << endl
;
1630 // Installed version
1631 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1632 if (Pkg
->CurrentVer
== 0)
1633 cout
<< _("(none)") << endl
;
1635 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1637 // Candidate Version
1638 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1639 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1640 if (V
.end() == true)
1641 cout
<< _("(none)") << endl
;
1643 cout
<< V
.VerStr() << endl
;
1646 if (Plcy
->GetPriority(Pkg
) != 0)
1648 cout
<< _(" Package pin: ");
1649 V
= Plcy
->GetMatch(Pkg
);
1650 if (V
.end() == true)
1651 cout
<< _("(not found)") << endl
;
1653 cout
<< V
.VerStr() << endl
;
1656 // Show the priority tables
1657 cout
<< _(" Version table:") << endl
;
1658 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1660 if (Pkg
.CurrentVer() == V
)
1661 cout
<< " *** " << V
.VerStr();
1663 cout
<< " " << V
.VerStr();
1664 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1665 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1667 // Locate the associated index files so we can derive a description
1669 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1670 _system
->FindIndex(VF
.File(),Indx
) == false)
1671 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1672 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1673 Indx
->Describe(true).c_str());
1682 // Madison - Look a bit like katie's madison /*{{{*/
1683 // ---------------------------------------------------------------------
1685 bool Madison(CommandLine
&CmdL
)
1687 pkgCacheFile CacheFile
;
1688 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1693 // Create the src text record parsers and ignore errors about missing
1694 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1695 pkgSrcRecords
SrcRecs(*SrcList
);
1696 if (_error
->PendingError() == true)
1699 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1700 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1702 if (Pkg
.end() == false)
1704 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; V
++)
1706 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1708 // This might be nice, but wouldn't uniquely identify the source -mdz
1709 // if (VF.File().Archive() != 0)
1711 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1712 // << VF.File().Archive() << endl;
1715 // Locate the associated index files so we can derive a description
1716 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); S
++)
1718 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1719 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1720 IF
!= Indexes
->end(); IF
++)
1722 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1724 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1725 << (*IF
)->Describe(true) << endl
;
1735 pkgSrcRecords::Parser
*SrcParser
;
1736 while ((SrcParser
= SrcRecs
.Find(Pkg
.Name(),false)) != 0)
1738 // Maybe support Release info here too eventually
1739 cout
<< setw(10) << SrcParser
->Package() << " | "
1740 << setw(10) << SrcParser
->Version() << " | "
1741 << SrcParser
->Index().Describe(true) << endl
;
1748 // GenCaches - Call the main cache generator /*{{{*/
1749 // ---------------------------------------------------------------------
1751 bool GenCaches(CommandLine
&Cmd
)
1753 OpTextProgress
Progress(*_config
);
1755 pkgCacheFile CacheFile
;
1756 return CacheFile
.BuildCaches(&Progress
, true);
1759 // ShowHelp - Show a help screen /*{{{*/
1760 // ---------------------------------------------------------------------
1762 bool ShowHelp(CommandLine
&Cmd
)
1764 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1765 COMMON_ARCH
,__DATE__
,__TIME__
);
1767 if (_config
->FindB("version") == true)
1771 _("Usage: apt-cache [options] command\n"
1772 " apt-cache [options] add file1 [file2 ...]\n"
1773 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1774 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1776 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1777 "cache files, and query information from them\n"
1780 " add - Add a package file to the source cache\n"
1781 " gencaches - Build both the package and source cache\n"
1782 " showpkg - Show some general information for a single package\n"
1783 " showsrc - Show source records\n"
1784 " stats - Show some basic statistics\n"
1785 " dump - Show the entire file in a terse form\n"
1786 " dumpavail - Print an available file to stdout\n"
1787 " unmet - Show unmet dependencies\n"
1788 " search - Search the package list for a regex pattern\n"
1789 " show - Show a readable record for the package\n"
1790 " showauto - Display a list of automatically installed packages\n"
1791 " depends - Show raw dependency information for a package\n"
1792 " rdepends - Show reverse dependency information for a package\n"
1793 " pkgnames - List the names of all packages in the system\n"
1794 " dotty - Generate package graphs for GraphViz\n"
1795 " xvcg - Generate package graphs for xvcg\n"
1796 " policy - Show policy settings\n"
1799 " -h This help text.\n"
1800 " -p=? The package cache.\n"
1801 " -s=? The source cache.\n"
1802 " -q Disable progress indicator.\n"
1803 " -i Show only important deps for the unmet command.\n"
1804 " -c=? Read this configuration file\n"
1805 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1806 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1810 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1811 // ---------------------------------------------------------------------
1813 void CacheInitialize()
1815 _config
->Set("quiet",0);
1816 _config
->Set("help",false);
1819 int main(int argc
,const char *argv
[]) /*{{{*/
1821 CommandLine::Args Args
[] = {
1822 {'h',"help","help",0},
1823 {'v',"version","version",0},
1824 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1825 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1826 {'q',"quiet","quiet",CommandLine::IntLevel
},
1827 {'i',"important","APT::Cache::Important",0},
1828 {'f',"full","APT::Cache::ShowFull",0},
1829 {'g',"generate","APT::Cache::Generate",0},
1830 {'a',"all-versions","APT::Cache::AllVersions",0},
1831 {'n',"names-only","APT::Cache::NamesOnly",0},
1832 {0,"all-names","APT::Cache::AllNames",0},
1833 {0,"recurse","APT::Cache::RecurseDepends",0},
1834 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1835 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1836 {'c',"config-file",0,CommandLine::ConfigFile
},
1837 {'o',"option",0,CommandLine::ArbItem
},
1838 {0,"installed","APT::Cache::Installed",0},
1840 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1842 {"gencaches",&GenCaches
},
1843 {"showsrc",&ShowSrcPackage
},
1845 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1848 {"dumpavail",&DumpAvail
},
1851 {"depends",&Depends
},
1852 {"rdepends",&RDepends
},
1855 {"show",&ShowPackage
},
1856 {"pkgnames",&ShowPkgNames
},
1857 {"showauto",&ShowAuto
},
1859 {"madison",&Madison
},
1864 // Set up gettext support
1865 setlocale(LC_ALL
,"");
1866 textdomain(PACKAGE
);
1868 // Parse the command line and initialize the package library
1869 CommandLine
CmdL(Args
,_config
);
1870 if (pkgInitConfig(*_config
) == false ||
1871 CmdL
.Parse(argc
,argv
) == false ||
1872 pkgInitSystem(*_config
,_system
) == false)
1874 _error
->DumpErrors();
1878 // See if the help should be shown
1879 if (_config
->FindB("help") == true ||
1880 CmdL
.FileSize() == 0)
1886 // Deal with stdout not being a tty
1887 if (isatty(STDOUT_FILENO
) && _config
->FindI("quiet",0) < 1)
1888 _config
->Set("quiet","1");
1890 // if (_config->FindB("APT::Cache::Generate",true) == false)
1891 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1892 CmdL
.DispatchArg(CmdsB
);
1894 // Print any errors or warnings found during parsing
1895 if (_error
->empty() == false)
1897 bool Errors
= _error
->PendingError();
1898 _error
->DumpErrors();
1899 return Errors
== true?100:0;