]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
3c7084c9ddb44b4ebfddb41b0541f34499a6938e
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.55 2002/01/09 04:59:44 jgg 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>
17 #include <apt-pkg/pkgcachegen.h>
18 #include <apt-pkg/init.h>
19 #include <apt-pkg/progress.h>
20 #include <apt-pkg/sourcelist.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/pkgrecords.h>
24 #include <apt-pkg/srcrecords.h>
25 #include <apt-pkg/version.h>
26 #include <apt-pkg/policy.h>
27 #include <apt-pkg/tagfile.h>
28 #include <apt-pkg/algorithms.h>
29 #include <apt-pkg/sptr.h>
42 pkgSourceList
*SrcList
= 0;
44 // LocalitySort - Sort a version list by package file locality /*{{{*/
45 // ---------------------------------------------------------------------
47 int LocalityCompare(const void *a
, const void *b
)
49 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
50 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
59 if (A
->File
== B
->File
)
60 return A
->Offset
- B
->Offset
;
61 return A
->File
- B
->File
;
64 void LocalitySort(pkgCache::VerFile
**begin
,
65 unsigned long Count
,size_t Size
)
67 qsort(begin
,Count
,Size
,LocalityCompare
);
70 // UnMet - Show unmet dependencies /*{{{*/
71 // ---------------------------------------------------------------------
73 bool UnMet(CommandLine
&CmdL
)
75 pkgCache
&Cache
= *GCache
;
76 bool Important
= _config
->FindB("APT::Cache::Important",false);
78 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
80 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
83 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
86 pkgCache::DepIterator Start
;
87 pkgCache::DepIterator End
;
90 // Skip conflicts and replaces
91 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
92 End
->Type
!= pkgCache::Dep::Depends
&&
93 End
->Type
!= pkgCache::Dep::Suggests
&&
94 End
->Type
!= pkgCache::Dep::Recommends
)
97 // Important deps only
98 if (Important
== true)
99 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
100 End
->Type
!= pkgCache::Dep::Depends
)
103 // Verify the or group
105 pkgCache::DepIterator RealStart
= Start
;
108 // See if this dep is Ok
109 pkgCache::Version
**VList
= Start
.AllTargets();
130 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
131 P
.Name(),V
.VerStr());
134 // Print out the dep type
135 cout
<< " " << End
.DepType() << ": ";
141 cout
<< Start
.TargetPkg().Name();
142 if (Start
.TargetVer() != 0)
143 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
159 // DumpPackage - Show a dump of a package record /*{{{*/
160 // ---------------------------------------------------------------------
162 bool DumpPackage(CommandLine
&CmdL
)
164 pkgCache
&Cache
= *GCache
;
165 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
167 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
168 if (Pkg
.end() == true)
170 _error
->Warning(_("Unable to locate package %s"),*I
);
174 cout
<< "Package: " << Pkg
.Name() << endl
;
175 cout
<< "Versions: " << endl
;
176 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
178 cout
<< Cur
.VerStr();
179 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
180 cout
<< "(" << Vf
.File().FileName() << ")";
186 cout
<< "Reverse Depends: " << endl
;
187 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
189 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name();
191 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
196 cout
<< "Dependencies: " << endl
;
197 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
199 cout
<< Cur
.VerStr() << " - ";
200 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
201 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
205 cout
<< "Provides: " << endl
;
206 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
208 cout
<< Cur
.VerStr() << " - ";
209 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
210 cout
<< Prv
.ParentPkg().Name() << " ";
213 cout
<< "Reverse Provides: " << endl
;
214 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
215 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr() << endl
;
221 // Stats - Dump some nice statistics /*{{{*/
222 // ---------------------------------------------------------------------
224 bool Stats(CommandLine
&Cmd
)
226 pkgCache
&Cache
= *GCache
;
227 cout
<< _("Total Package Names : ") << Cache
.Head().PackageCount
<< " (" <<
228 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
235 pkgCache::PkgIterator I
= Cache
.PkgBegin();
236 for (;I
.end() != true; I
++)
238 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
244 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
250 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
253 if (I
.ProvidesList()->NextProvides
== 0)
261 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
267 cout
<< _(" Normal Packages: ") << Normal
<< endl
;
268 cout
<< _(" Pure Virtual Packages: ") << Virtual
<< endl
;
269 cout
<< _(" Single Virtual Packages: ") << DVirt
<< endl
;
270 cout
<< _(" Mixed Virtual Packages: ") << NVirt
<< endl
;
271 cout
<< _(" Missing: ") << Missing
<< endl
;
273 cout
<< _("Total Distinct Versions: ") << Cache
.Head().VersionCount
<< " (" <<
274 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
275 cout
<< _("Total Dependencies: ") << Cache
.Head().DependsCount
<< " (" <<
276 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
278 cout
<< _("Total Ver/File relations: ") << Cache
.Head().VerFileCount
<< " (" <<
279 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
280 cout
<< _("Total Provides Mappings: ") << Cache
.Head().ProvidesCount
<< " (" <<
281 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
284 unsigned long Size
= 0;
285 unsigned long Count
= 0;
286 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
287 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
290 Size
+= strlen(Cache
.StrP
+ I
->String
) + 1;
292 cout
<< _("Total Globbed Strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
294 unsigned long DepVerSize
= 0;
295 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
297 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
299 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
302 DepVerSize
+= strlen(D
.TargetVer()) + 1;
306 cout
<< _("Total Dependency Version space: ") << SizeToStr(DepVerSize
) << endl
;
308 unsigned long Slack
= 0;
309 for (int I
= 0; I
!= 7; I
++)
310 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
311 cout
<< _("Total Slack space: ") << SizeToStr(Slack
) << endl
;
313 unsigned long Total
= 0;
314 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
315 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
316 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
317 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
318 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
319 cout
<< _("Total Space Accounted for: ") << SizeToStr(Total
) << endl
;
324 // Dump - show everything /*{{{*/
325 // ---------------------------------------------------------------------
326 /* This is worthless except fer debugging things */
327 bool Dump(CommandLine
&Cmd
)
329 pkgCache
&Cache
= *GCache
;
330 cout
<< "Using Versioning System: " << Cache
.VS
->Label
<< endl
;
332 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
334 cout
<< "Package: " << P
.Name() << endl
;
335 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
337 cout
<< " Version: " << V
.VerStr() << endl
;
338 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
339 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
340 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' <<
341 DeNull(D
.TargetVer()) << endl
;
345 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
347 cout
<< "File: " << F
.FileName() << endl
;
348 cout
<< " Type: " << F
.IndexType() << endl
;
349 cout
<< " Size: " << F
->Size
<< endl
;
350 cout
<< " ID: " << F
->ID
<< endl
;
351 cout
<< " Flags: " << F
->Flags
<< endl
;
352 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
353 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
354 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
355 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
356 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
357 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
358 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
359 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
365 // DumpAvail - Print out the available list /*{{{*/
366 // ---------------------------------------------------------------------
367 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
368 make this run really fast, perhaps I went a little overboard.. */
369 bool DumpAvail(CommandLine
&Cmd
)
371 pkgCache
&Cache
= *GCache
;
373 pkgPolicy
Plcy(&Cache
);
374 if (ReadPinFile(Plcy
) == false)
377 unsigned long Count
= Cache
.HeaderP
->PackageCount
+1;
378 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
379 memset(VFList
,0,sizeof(*VFList
)*Count
);
381 // Map versions that we want to write out onto the VerList array.
382 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
384 if (P
->VersionList
== 0)
387 /* Find the proper version to use. If the policy says there are no
388 possible selections we return the installed version, if available..
389 This prevents dselect from making it obsolete. */
390 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
393 if (P
->CurrentVer
== 0)
398 pkgCache::VerFileIterator VF
= V
.FileList();
399 for (; VF
.end() == false ; VF
++)
400 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
403 /* Okay, here we have a bit of a problem.. The policy has selected the
404 currently installed package - however it only exists in the
405 status file.. We need to write out something or dselect will mark
406 the package as obsolete! Thus we emit the status file entry, but
407 below we remove the status line to make it valid for the
408 available file. However! We only do this if their do exist *any*
409 non-source versions of the package - that way the dselect obsolete
410 handling works OK. */
411 if (VF
.end() == true)
413 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
415 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
417 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
424 if (VF
.end() == false)
432 LocalitySort(VFList
,Count
,sizeof(*VFList
));
434 // Iterate over all the package files and write them out.
435 char *Buffer
= new char[Cache
.HeaderP
->MaxVerFileSize
+10];
436 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
438 pkgCache::PkgFileIterator
File(Cache
,(*J
)->File
+ Cache
.PkgFileP
);
439 if (File
.IsOk() == false)
441 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
445 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
446 if (_error
->PendingError() == true)
449 /* Write all of the records from this package file, since we
450 already did locality sorting we can now just seek through the
451 file in read order. We apply 1 more optimization here, since often
452 there will be < 1 byte gaps between records (for the \n) we read that
453 into the next buffer and offset a bit.. */
454 unsigned long Pos
= 0;
457 if ((*J
)->File
+ Cache
.PkgFileP
!= File
)
460 const pkgCache::VerFile
&VF
= **J
;
462 // Read the record and then write it out again.
463 unsigned long Jitter
= VF
.Offset
- Pos
;
466 if (PkgF
.Seek(VF
.Offset
) == false)
471 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
473 Buffer
[VF
.Size
+ Jitter
] = '\n';
476 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
479 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
480 const char *Zero
= 0;
481 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
482 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
484 _error
->Error("Internal Error, Unable to parse a package record");
491 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
495 Pos
= VF
.Offset
+ VF
.Size
;
499 if (_error
->PendingError() == true)
505 return !_error
->PendingError();
508 // Depends - Print out a dependency tree /*{{{*/
509 // ---------------------------------------------------------------------
511 bool Depends(CommandLine
&CmdL
)
513 pkgCache
&Cache
= *GCache
;
514 SPtrArray
<unsigned> Colours
= new unsigned[Cache
.Head().PackageCount
];
515 memset(Colours
,0,sizeof(*Colours
)*Cache
.Head().PackageCount
);
517 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
519 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
520 if (Pkg
.end() == true)
522 _error
->Warning(_("Unable to locate package %s"),*I
);
525 Colours
[Pkg
->ID
] = 1;
528 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
532 DidSomething
= false;
533 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
535 if (Colours
[Pkg
->ID
] != 1)
537 Colours
[Pkg
->ID
] = 2;
540 pkgCache::VerIterator Ver
= Pkg
.VersionList();
541 if (Ver
.end() == true)
543 cout
<< '<' << Pkg
.Name() << '>' << endl
;
547 cout
<< Pkg
.Name() << endl
;
549 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
551 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
557 pkgCache::PkgIterator Trg
= D
.TargetPkg();
558 if (Trg
->VersionList
== 0)
559 cout
<< D
.DepType() << ": <" << Trg
.Name() << ">" << endl
;
561 cout
<< D
.DepType() << ": " << Trg
.Name() << endl
;
564 Colours
[D
.TargetPkg()->ID
]++;
566 // Display all solutions
567 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
568 pkgPrioSortList(Cache
,List
);
569 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
571 pkgCache::VerIterator
V(Cache
,*I
);
572 if (V
!= Cache
.VerP
+ V
.ParentPkg()->VersionList
||
573 V
->ParentPkg
== D
->Package
)
575 cout
<< " " << V
.ParentPkg().Name() << endl
;
578 Colours
[D
.ParentPkg()->ID
]++;
583 while (DidSomething
== true);
588 // Dotty - Generate a graph for Dotty /*{{{*/
589 // ---------------------------------------------------------------------
590 /* Dotty is the graphvis program for generating graphs. It is a fairly
591 simple queuing algorithm that just writes dependencies and nodes.
592 http://www.research.att.com/sw/tools/graphviz/ */
593 bool Dotty(CommandLine
&CmdL
)
595 pkgCache
&Cache
= *GCache
;
596 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
598 /* Normal packages are boxes
599 Pure Provides are triangles
601 Hexagons are missing packages*/
602 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
604 /* Initialize the list of packages to show.
606 2 = To Show no recurse
607 3 = Emitted no recurse
610 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
611 enum TheFlags
{ForceNR
=(1<<0)};
612 unsigned char *Show
= new unsigned char[Cache
.Head().PackageCount
];
613 unsigned char *Flags
= new unsigned char[Cache
.Head().PackageCount
];
614 unsigned char *ShapeMap
= new unsigned char[Cache
.Head().PackageCount
];
616 // Show everything if no arguments given
617 if (CmdL
.FileList
[1] == 0)
618 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
621 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
623 memset(Flags
,0,sizeof(*Flags
)*Cache
.Head().PackageCount
);
626 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
628 if (Pkg
->VersionList
== 0)
631 if (Pkg
->ProvidesList
== 0)
632 ShapeMap
[Pkg
->ID
] = 0;
634 ShapeMap
[Pkg
->ID
] = 1;
639 if (Pkg
->ProvidesList
== 0)
640 ShapeMap
[Pkg
->ID
] = 2;
642 ShapeMap
[Pkg
->ID
] = 3;
646 // Load the list of packages from the command line into the show list
647 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
649 // Process per-package flags
654 if (P
.end()[-1] == '^')
660 if (P
.end()[-1] == ',')
664 // Locate the package
665 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(P
);
666 if (Pkg
.end() == true)
668 _error
->Warning(_("Unable to locate package %s"),*I
);
671 Show
[Pkg
->ID
] = ToShow
;
674 Flags
[Pkg
->ID
] |= ForceNR
;
678 printf("digraph packages {\n");
679 printf("concentrate=true;\n");
680 printf("size=\"30,40\";\n");
686 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
688 // See we need to show this package
689 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
693 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
695 // Pure Provides and missing packages have no deps!
696 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
697 Show
[Pkg
->ID
] = Done
;
699 Show
[Pkg
->ID
] = DoneNR
;
702 Show
[Pkg
->ID
] = Done
;
705 // No deps to map out
706 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
709 pkgCache::VerIterator Ver
= Pkg
.VersionList();
710 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
712 // See if anything can meet this dep
713 // Walk along the actual package providing versions
715 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
716 for (pkgCache::VerIterator I
= DPkg
.VersionList();
717 I
.end() == false && Hit
== false; I
++)
719 if (Cache
.VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
723 // Follow all provides
724 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
725 I
.end() == false && Hit
== false; I
++)
727 if (Cache
.VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
731 // Only graph critical deps
732 if (D
.IsCritical() == true)
734 printf("\"%s\" -> \"%s\"",Pkg
.Name(),D
.TargetPkg().Name());
736 // Colour the node for recursion
737 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
739 /* If a conflicts does not meet anything in the database
740 then show the relation but do not recurse */
742 (D
->Type
== pkgCache::Dep::Conflicts
||
743 D
->Type
== pkgCache::Dep::Obsoletes
))
745 if (Show
[D
.TargetPkg()->ID
] == None
&&
746 Show
[D
.TargetPkg()->ID
] != ToShow
)
747 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
751 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
752 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
754 Show
[D
.TargetPkg()->ID
] = ToShow
;
761 case pkgCache::Dep::Conflicts
:
762 case pkgCache::Dep::Obsoletes
:
763 printf("[color=springgreen];\n");
766 case pkgCache::Dep::PreDepends
:
767 printf("[color=blue];\n");
779 /* Draw the box colours after the fact since we can not tell what colour
780 they should be until everything is finished drawing */
781 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
783 if (Show
[Pkg
->ID
] < DoneNR
)
786 // Orange box for early recursion stoppage
787 if (Show
[Pkg
->ID
] == DoneNR
)
788 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.Name(),
789 Shapes
[ShapeMap
[Pkg
->ID
]]);
791 printf("\"%s\" [shape=%s];\n",Pkg
.Name(),
792 Shapes
[ShapeMap
[Pkg
->ID
]]);
799 // DoAdd - Perform an adding operation /*{{{*/
800 // ---------------------------------------------------------------------
802 bool DoAdd(CommandLine
&CmdL
)
804 return _error
->Error("Unimplemented");
806 // Make sure there is at least one argument
807 if (CmdL
.FileSize() <= 1)
808 return _error
->Error("You must give at least one file name");
811 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
812 if (_error
->PendingError() == true)
815 DynamicMMap
Map(CacheF
,MMap::Public
);
816 if (_error
->PendingError() == true)
819 OpTextProgress
Progress(*_config
);
820 pkgCacheGenerator
Gen(Map
,Progress
);
821 if (_error
->PendingError() == true)
824 unsigned long Length
= CmdL
.FileSize() - 1;
825 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
827 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
828 Progress
.SubProgress(Length
);
831 FileFd
TagF(*I
,FileFd::ReadOnly
);
832 debListParser
Parser(TagF
);
833 if (_error
->PendingError() == true)
834 return _error
->Error("Problem opening %s",*I
);
836 if (Gen
.SelectFile(*I
,"") == false)
837 return _error
->Error("Problem with SelectFile");
839 if (Gen
.MergeList(Parser
) == false)
840 return _error
->Error("Problem with MergeList");
844 GCache
= &Gen
.GetCache();
851 // DisplayRecord - Displays the complete record for the package /*{{{*/
852 // ---------------------------------------------------------------------
853 /* This displays the package record from the proper package index file.
854 It is not used by DumpAvail for performance reasons. */
855 bool DisplayRecord(pkgCache::VerIterator V
)
857 // Find an appropriate file
858 pkgCache::VerFileIterator Vf
= V
.FileList();
859 for (; Vf
.end() == false; Vf
++)
860 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
862 if (Vf
.end() == true)
865 // Check and load the package list file
866 pkgCache::PkgFileIterator I
= Vf
.File();
867 if (I
.IsOk() == false)
868 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
870 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
871 if (_error
->PendingError() == true)
874 // Read the record and then write it out again.
875 unsigned char *Buffer
= new unsigned char[GCache
->HeaderP
->MaxVerFileSize
+1];
876 Buffer
[V
.FileList()->Size
] = '\n';
877 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
878 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
879 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
+1) != V
.FileList()->Size
+1)
890 // Search - Perform a search /*{{{*/
891 // ---------------------------------------------------------------------
892 /* This searches the package names and pacakge descriptions for a pattern */
895 pkgCache::VerFile
*Vf
;
899 bool Search(CommandLine
&CmdL
)
901 pkgCache
&Cache
= *GCache
;
902 bool ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
903 bool NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
904 unsigned NumPatterns
= CmdL
.FileSize() -1;
906 pkgDepCache::Policy Plcy
;
908 // Make sure there is at least one argument
910 return _error
->Error(_("You must give exactly one pattern"));
912 // Compile the regex pattern
913 regex_t
*Patterns
= new regex_t
[NumPatterns
];
914 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
915 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
917 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
921 regfree(&Patterns
[I
]);
922 return _error
->Error("Regex compilation error");
926 // Create the text record parser
927 pkgRecords
Recs(Cache
);
928 if (_error
->PendingError() == true)
930 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
931 regfree(&Patterns
[I
]);
935 ExVerFile
*VFList
= new ExVerFile
[Cache
.HeaderP
->PackageCount
+1];
936 memset(VFList
,0,sizeof(*VFList
)*Cache
.HeaderP
->PackageCount
+1);
938 // Map versions that we want to write out onto the VerList array.
939 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
941 VFList
[P
->ID
].NameMatch
= NumPatterns
!= 0;
942 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
944 if (regexec(&Patterns
[I
],P
.Name(),0,0,0) == 0)
945 VFList
[P
->ID
].NameMatch
&= true;
947 VFList
[P
->ID
].NameMatch
= false;
950 // Doing names only, drop any that dont match..
951 if (NamesOnly
== true && VFList
[P
->ID
].NameMatch
== false)
954 // Find the proper version to use.
955 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
956 if (V
.end() == false)
957 VFList
[P
->ID
].Vf
= V
.FileList();
960 // Include all the packages that provide matching names too
961 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
963 if (VFList
[P
->ID
].NameMatch
== false)
966 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
968 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Prv
.OwnerPkg());
969 if (V
.end() == false)
971 VFList
[Prv
.OwnerPkg()->ID
].Vf
= V
.FileList();
972 VFList
[Prv
.OwnerPkg()->ID
].NameMatch
= true;
977 LocalitySort(&VFList
->Vf
,Cache
.HeaderP
->PackageCount
,sizeof(*VFList
));
979 // Iterate over all the version records and check them
980 for (ExVerFile
*J
= VFList
; J
->Vf
!= 0; J
++)
982 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::VerFileIterator(Cache
,J
->Vf
));
985 if (J
->NameMatch
== false)
987 string LongDesc
= P
.LongDesc();
988 Match
= NumPatterns
!= 0;
989 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
991 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1000 if (ShowFull
== true)
1004 P
.GetRec(Start
,End
);
1005 fwrite(Start
,End
-Start
,1,stdout
);
1009 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1014 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1015 regfree(&Patterns
[I
]);
1017 return _error
->Error("Write to stdout failed");
1021 // ShowPackage - Dump the package record to the screen /*{{{*/
1022 // ---------------------------------------------------------------------
1024 bool ShowPackage(CommandLine
&CmdL
)
1026 pkgCache
&Cache
= *GCache
;
1027 pkgDepCache::Policy Plcy
;
1029 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1031 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1032 if (Pkg
.end() == true)
1034 _error
->Warning(_("Unable to locate package %s"),*I
);
1038 // Find the proper version to use.
1039 if (_config
->FindB("APT::Cache::AllVersions","true") == true)
1041 pkgCache::VerIterator V
;
1042 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1044 if (DisplayRecord(V
) == false)
1050 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1051 if (V
.end() == true || V
.FileList().end() == true)
1053 if (DisplayRecord(V
) == false)
1060 // ShowPkgNames - Show package names /*{{{*/
1061 // ---------------------------------------------------------------------
1062 /* This does a prefix match on the first argument */
1063 bool ShowPkgNames(CommandLine
&CmdL
)
1065 pkgCache
&Cache
= *GCache
;
1066 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1067 bool All
= _config
->FindB("APT::Cache::AllNames","false");
1069 if (CmdL
.FileList
[1] != 0)
1071 for (;I
.end() != true; I
++)
1073 if (All
== false && I
->VersionList
== 0)
1076 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1077 cout
<< I
.Name() << endl
;
1084 for (;I
.end() != true; I
++)
1086 if (All
== false && I
->VersionList
== 0)
1088 cout
<< I
.Name() << endl
;
1094 // ShowSrcPackage - Show source package records /*{{{*/
1095 // ---------------------------------------------------------------------
1097 bool ShowSrcPackage(CommandLine
&CmdL
)
1100 List
.ReadMainList();
1102 // Create the text record parsers
1103 pkgSrcRecords
SrcRecs(List
);
1104 if (_error
->PendingError() == true)
1107 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1111 pkgSrcRecords::Parser
*Parse
;
1112 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0)
1113 cout
<< Parse
->AsStr() << endl
;;
1118 // Policy - Show the results of the preferences file /*{{{*/
1119 // ---------------------------------------------------------------------
1121 bool Policy(CommandLine
&CmdL
)
1124 return _error
->Error("Generate must be enabled for this function");
1126 pkgCache
&Cache
= *GCache
;
1127 pkgPolicy
Plcy(&Cache
);
1128 if (ReadPinFile(Plcy
) == false)
1131 // Print out all of the package files
1132 if (CmdL
.FileList
[1] == 0)
1134 cout
<< _("Package Files:") << endl
;
1135 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
1137 // Locate the associated index files so we can derive a description
1139 if (SrcList
->FindIndex(F
,Indx
) == false &&
1140 _system
->FindIndex(F
,Indx
) == false)
1141 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1142 printf(_("%4i %s\n"),
1143 Plcy
.GetPriority(F
),Indx
->Describe(true).c_str());
1145 // Print the reference information for the package
1146 string Str
= F
.RelStr();
1147 if (Str
.empty() == false)
1148 printf(" release %s\n",F
.RelStr().c_str());
1149 if (F
.Site() != 0 && F
.Site()[0] != 0)
1150 printf(" origin %s\n",F
.Site());
1153 // Show any packages have explicit pins
1154 cout
<< _("Pinned Packages:") << endl
;
1155 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1156 for (;I
.end() != true; I
++)
1158 if (Plcy
.GetPriority(I
) == 0)
1161 // Print the package name and the version we are forcing to
1162 cout
<< " " << I
.Name() << " -> ";
1164 pkgCache::VerIterator V
= Plcy
.GetMatch(I
);
1165 if (V
.end() == true)
1166 cout
<< _("(not found)") << endl
;
1168 cout
<< V
.VerStr() << endl
;
1174 // Print out detailed information for each package
1175 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1177 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1178 if (Pkg
.end() == true)
1180 _error
->Warning(_("Unable to locate package %s"),*I
);
1184 cout
<< Pkg
.Name() << ":" << endl
;
1186 // Installed version
1187 cout
<< _(" Installed: ");
1188 if (Pkg
->CurrentVer
== 0)
1189 cout
<< _("(none)") << endl
;
1191 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1193 // Candidate Version
1194 cout
<< _(" Candidate: ");
1195 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1196 if (V
.end() == true)
1197 cout
<< _("(none)") << endl
;
1199 cout
<< V
.VerStr() << endl
;
1202 if (Plcy
.GetPriority(Pkg
) != 0)
1204 cout
<< _(" Package Pin: ");
1205 V
= Plcy
.GetMatch(Pkg
);
1206 if (V
.end() == true)
1207 cout
<< _("(not found)") << endl
;
1209 cout
<< V
.VerStr() << endl
;
1212 // Show the priority tables
1213 cout
<< _(" Version Table:") << endl
;
1214 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1216 if (Pkg
.CurrentVer() == V
)
1217 cout
<< " *** " << V
.VerStr();
1219 cout
<< " " << V
.VerStr();
1220 cout
<< " " << Plcy
.GetPriority(Pkg
) << endl
;
1221 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1223 // Locate the associated index files so we can derive a description
1225 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1226 _system
->FindIndex(VF
.File(),Indx
) == false)
1227 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1228 printf(_(" %4i %s\n"),Plcy
.GetPriority(VF
.File()),
1229 Indx
->Describe(true).c_str());
1237 // GenCaches - Call the main cache generator /*{{{*/
1238 // ---------------------------------------------------------------------
1240 bool GenCaches(CommandLine
&Cmd
)
1242 OpTextProgress
Progress(*_config
);
1245 if (List
.ReadMainList() == false)
1247 return pkgMakeStatusCache(List
,Progress
);
1250 // ShowHelp - Show a help screen /*{{{*/
1251 // ---------------------------------------------------------------------
1253 bool ShowHelp(CommandLine
&Cmd
)
1255 ioprintf(cout
,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1256 COMMON_OS
,COMMON_CPU
,__DATE__
,__TIME__
);
1259 _("Usage: apt-cache [options] command\n"
1260 " apt-cache [options] add file1 [file1 ...]\n"
1261 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1263 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1264 "cache files, and query information from them\n"
1267 " add - Add an package file to the source cache\n"
1268 " gencaches - Build both the package and source cache\n"
1269 " showpkg - Show some general information for a single package\n"
1270 " stats - Show some basic statistics\n"
1271 " dump - Show the entire file in a terse form\n"
1272 " dumpavail - Print an available file to stdout\n"
1273 " unmet - Show unmet dependencies\n"
1274 " search - Search the package list for a regex pattern\n"
1275 " show - Show a readable record for the package\n"
1276 " depends - Show raw dependency information for a package\n"
1277 " pkgnames - List the names of all packages\n"
1278 " dotty - Generate package graphs for GraphVis\n"
1279 " policy - Show policy settings\n"
1282 " -h This help text.\n"
1283 " -p=? The package cache.\n"
1284 " -s=? The source cache.\n"
1285 " -q Disable progress indicator.\n"
1286 " -i Show only important deps for the unmet command.\n"
1287 " -c=? Read this configuration file\n"
1288 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1289 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1293 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1294 // ---------------------------------------------------------------------
1296 void CacheInitialize()
1298 _config
->Set("quiet",0);
1299 _config
->Set("help",false);
1303 int main(int argc
,const char *argv
[])
1305 CommandLine::Args Args
[] = {
1306 {'h',"help","help",0},
1307 {'v',"version","version",0},
1308 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1309 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1310 {'q',"quiet","quiet",CommandLine::IntLevel
},
1311 {'i',"important","APT::Cache::Important",0},
1312 {'f',"full","APT::Cache::ShowFull",0},
1313 {'g',"generate","APT::Cache::Generate",0},
1314 {'a',"all-versions","APT::Cache::AllVersions",0},
1315 {0,"names-only","APT::Cache::NamesOnly",0},
1316 {0,"all-names","APT::Cache::AllNames",0},
1317 {0,"recurse","APT::Cache::RecurseDepends",0},
1318 {'c',"config-file",0,CommandLine::ConfigFile
},
1319 {'o',"option",0,CommandLine::ArbItem
},
1321 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1323 {"gencaches",&GenCaches
},
1324 {"showsrc",&ShowSrcPackage
},
1326 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1329 {"dumpavail",&DumpAvail
},
1332 {"depends",&Depends
},
1334 {"show",&ShowPackage
},
1335 {"pkgnames",&ShowPkgNames
},
1341 // Set up gettext support
1342 setlocale(LC_ALL
,"");
1343 textdomain(PACKAGE
);
1345 // Parse the command line and initialize the package library
1346 CommandLine
CmdL(Args
,_config
);
1347 if (pkgInitConfig(*_config
) == false ||
1348 CmdL
.Parse(argc
,argv
) == false ||
1349 pkgInitSystem(*_config
,_system
) == false)
1351 _error
->DumpErrors();
1355 // See if the help should be shown
1356 if (_config
->FindB("help") == true ||
1357 CmdL
.FileSize() == 0)
1363 // Deal with stdout not being a tty
1364 if (ttyname(STDOUT_FILENO
) == 0 && _config
->FindI("quiet",0) < 1)
1365 _config
->Set("quiet","1");
1367 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1370 if (_config
->FindB("APT::Cache::Generate",true) == false)
1372 Map
= new MMap(*new FileFd(_config
->FindFile("Dir::Cache::pkgcache"),
1373 FileFd::ReadOnly
),MMap::Public
|MMap::ReadOnly
);
1377 // Open the cache file
1378 SrcList
= new pkgSourceList
;
1379 SrcList
->ReadMainList();
1381 // Generate it and map it
1383 pkgMakeStatusCache(*SrcList
,Prog
,&Map
,true);
1386 if (_error
->PendingError() == false)
1388 pkgCache
Cache(Map
);
1390 if (_error
->PendingError() == false)
1391 CmdL
.DispatchArg(CmdsB
);
1396 // Print any errors or warnings found during parsing
1397 if (_error
->empty() == false)
1399 bool Errors
= _error
->PendingError();
1400 _error
->DumpErrors();
1401 return Errors
== true?100:0;