]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.52 2001/07/02 00:10:32 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 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Cache
.HeaderP
->PackageCount
];
378 memset(VFList
,0,sizeof(*VFList
)*Cache
.HeaderP
->PackageCount
);
380 // Map versions that we want to write out onto the VerList array.
381 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
383 if (P
->VersionList
== 0)
386 /* Find the proper version to use. If the policy says there are no
387 possible selections we return the installed version, if available..
388 This prevents dselect from making it obsolete. */
389 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
392 if (P
->CurrentVer
== 0)
397 pkgCache::VerFileIterator VF
= V
.FileList();
398 for (; VF
.end() == false ; VF
++)
399 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
402 /* Okay, here we have a bit of a problem.. The policy has selected the
403 currently installed package - however it only exists in the
404 status file.. We need to write out something or dselect will mark
405 the package as obsolete! Thus we emit the status file entry, but
406 below we remove the status line to make it valid for the
407 available file. However! We only do this if their do exist *any*
408 non-source versions of the package - that way the dselect obsolete
409 handling works OK. */
410 if (VF
.end() == true)
412 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
414 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
416 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
423 if (VF
.end() == false)
431 LocalitySort(VFList
,Cache
.HeaderP
->PackageCount
,sizeof(*VFList
));
433 // Iterate over all the package files and write them out.
434 char *Buffer
= new char[Cache
.HeaderP
->MaxVerFileSize
+10];
435 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
437 pkgCache::PkgFileIterator
File(Cache
,(*J
)->File
+ Cache
.PkgFileP
);
438 if (File
.IsOk() == false)
440 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
444 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
445 if (_error
->PendingError() == true)
448 /* Write all of the records from this package file, since we
449 already did locality sorting we can now just seek through the
450 file in read order. We apply 1 more optimization here, since often
451 there will be < 1 byte gaps between records (for the \n) we read that
452 into the next buffer and offset a bit.. */
453 unsigned long Pos
= 0;
456 if ((*J
)->File
+ Cache
.PkgFileP
!= File
)
459 const pkgCache::VerFile
&VF
= **J
;
461 // Read the record and then write it out again.
462 unsigned long Jitter
= VF
.Offset
- Pos
;
465 if (PkgF
.Seek(VF
.Offset
) == false)
470 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
472 Buffer
[VF
.Size
+ Jitter
] = '\n';
475 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
478 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
479 const char *Zero
= 0;
480 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
481 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
483 _error
->Error("Internal Error, Unable to parse a package record");
490 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
494 Pos
= VF
.Offset
+ VF
.Size
;
498 if (_error
->PendingError() == true)
504 return !_error
->PendingError();
507 // Depends - Print out a dependency tree /*{{{*/
508 // ---------------------------------------------------------------------
510 bool Depends(CommandLine
&CmdL
)
512 pkgCache
&Cache
= *GCache
;
513 SPtrArray
<unsigned> Colours
= new unsigned[Cache
.Head().PackageCount
];
514 memset(Colours
,0,sizeof(*Colours
)*Cache
.Head().PackageCount
);
516 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
518 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
519 if (Pkg
.end() == true)
521 _error
->Warning(_("Unable to locate package %s"),*I
);
524 Colours
[Pkg
->ID
] = 1;
527 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
531 DidSomething
= false;
532 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
534 if (Colours
[Pkg
->ID
] != 1)
536 Colours
[Pkg
->ID
] = 2;
539 pkgCache::VerIterator Ver
= Pkg
.VersionList();
540 if (Ver
.end() == true)
542 cout
<< '<' << Pkg
.Name() << '>' << endl
;
546 cout
<< Pkg
.Name() << endl
;
548 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
550 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
556 pkgCache::PkgIterator Trg
= D
.TargetPkg();
557 if (Trg
->VersionList
== 0)
558 cout
<< D
.DepType() << ": <" << Trg
.Name() << ">" << endl
;
560 cout
<< D
.DepType() << ": " << Trg
.Name() << endl
;
563 Colours
[D
.TargetPkg()->ID
]++;
565 // Display all solutions
566 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
567 pkgPrioSortList(Cache
,List
);
568 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
570 pkgCache::VerIterator
V(Cache
,*I
);
571 if (V
!= Cache
.VerP
+ V
.ParentPkg()->VersionList
||
572 V
->ParentPkg
== D
->Package
)
574 cout
<< " " << V
.ParentPkg().Name() << endl
;
577 Colours
[D
.ParentPkg()->ID
]++;
582 while (DidSomething
== true);
587 // Dotty - Generate a graph for Dotty /*{{{*/
588 // ---------------------------------------------------------------------
589 /* Dotty is the graphvis program for generating graphs. It is a fairly
590 simple queuing algorithm that just writes dependencies and nodes.
591 http://www.research.att.com/sw/tools/graphviz/ */
592 bool Dotty(CommandLine
&CmdL
)
594 pkgCache
&Cache
= *GCache
;
595 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
597 /* Normal packages are boxes
598 Pure Provides are triangles
600 Hexagons are missing packages*/
601 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
603 /* Initialize the list of packages to show.
605 2 = To Show no recurse
606 3 = Emitted no recurse
609 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
610 enum TheFlags
{ForceNR
=(1<<0)};
611 unsigned char *Show
= new unsigned char[Cache
.Head().PackageCount
];
612 unsigned char *Flags
= new unsigned char[Cache
.Head().PackageCount
];
613 unsigned char *ShapeMap
= new unsigned char[Cache
.Head().PackageCount
];
615 // Show everything if no arguments given
616 if (CmdL
.FileList
[1] == 0)
617 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
620 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
622 memset(Flags
,0,sizeof(*Flags
)*Cache
.Head().PackageCount
);
625 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
627 if (Pkg
->VersionList
== 0)
630 if (Pkg
->ProvidesList
== 0)
631 ShapeMap
[Pkg
->ID
] = 0;
633 ShapeMap
[Pkg
->ID
] = 1;
638 if (Pkg
->ProvidesList
== 0)
639 ShapeMap
[Pkg
->ID
] = 2;
641 ShapeMap
[Pkg
->ID
] = 3;
645 // Load the list of packages from the command line into the show list
646 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
648 // Process per-package flags
653 if (P
.end()[-1] == '^')
659 if (P
.end()[-1] == ',')
663 // Locate the package
664 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(P
);
665 if (Pkg
.end() == true)
667 _error
->Warning(_("Unable to locate package %s"),*I
);
670 Show
[Pkg
->ID
] = ToShow
;
673 Flags
[Pkg
->ID
] |= ForceNR
;
677 printf("digraph packages {\n");
678 printf("concentrate=true;\n");
679 printf("size=\"30,40\";\n");
685 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
687 // See we need to show this package
688 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
692 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
694 // Pure Provides and missing packages have no deps!
695 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
696 Show
[Pkg
->ID
] = Done
;
698 Show
[Pkg
->ID
] = DoneNR
;
701 Show
[Pkg
->ID
] = Done
;
704 // No deps to map out
705 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
708 pkgCache::VerIterator Ver
= Pkg
.VersionList();
709 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
711 // See if anything can meet this dep
712 // Walk along the actual package providing versions
714 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
715 for (pkgCache::VerIterator I
= DPkg
.VersionList();
716 I
.end() == false && Hit
== false; I
++)
718 if (Cache
.VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
722 // Follow all provides
723 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
724 I
.end() == false && Hit
== false; I
++)
726 if (Cache
.VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
730 // Only graph critical deps
731 if (D
.IsCritical() == true)
733 printf("\"%s\" -> \"%s\"",Pkg
.Name(),D
.TargetPkg().Name());
735 // Colour the node for recursion
736 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
738 /* If a conflicts does not meet anything in the database
739 then show the relation but do not recurse */
741 (D
->Type
== pkgCache::Dep::Conflicts
||
742 D
->Type
== pkgCache::Dep::Obsoletes
))
744 if (Show
[D
.TargetPkg()->ID
] == None
&&
745 Show
[D
.TargetPkg()->ID
] != ToShow
)
746 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
750 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
751 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
753 Show
[D
.TargetPkg()->ID
] = ToShow
;
760 case pkgCache::Dep::Conflicts
:
761 case pkgCache::Dep::Obsoletes
:
762 printf("[color=springgreen];\n");
765 case pkgCache::Dep::PreDepends
:
766 printf("[color=blue];\n");
778 /* Draw the box colours after the fact since we can not tell what colour
779 they should be until everything is finished drawing */
780 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
782 if (Show
[Pkg
->ID
] < DoneNR
)
785 // Orange box for early recursion stoppage
786 if (Show
[Pkg
->ID
] == DoneNR
)
787 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.Name(),
788 Shapes
[ShapeMap
[Pkg
->ID
]]);
790 printf("\"%s\" [shape=%s];\n",Pkg
.Name(),
791 Shapes
[ShapeMap
[Pkg
->ID
]]);
798 // DoAdd - Perform an adding operation /*{{{*/
799 // ---------------------------------------------------------------------
801 bool DoAdd(CommandLine
&CmdL
)
803 return _error
->Error("Unimplemented");
805 // Make sure there is at least one argument
806 if (CmdL
.FileSize() <= 1)
807 return _error
->Error("You must give at least one file name");
810 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
811 if (_error
->PendingError() == true)
814 DynamicMMap
Map(CacheF
,MMap::Public
);
815 if (_error
->PendingError() == true)
818 OpTextProgress
Progress(*_config
);
819 pkgCacheGenerator
Gen(Map
,Progress
);
820 if (_error
->PendingError() == true)
823 unsigned long Length
= CmdL
.FileSize() - 1;
824 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
826 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
827 Progress
.SubProgress(Length
);
830 FileFd
TagF(*I
,FileFd::ReadOnly
);
831 debListParser
Parser(TagF
);
832 if (_error
->PendingError() == true)
833 return _error
->Error("Problem opening %s",*I
);
835 if (Gen
.SelectFile(*I
,"") == false)
836 return _error
->Error("Problem with SelectFile");
838 if (Gen
.MergeList(Parser
) == false)
839 return _error
->Error("Problem with MergeList");
843 GCache
= &Gen
.GetCache();
850 // DisplayRecord - Displays the complete record for the package /*{{{*/
851 // ---------------------------------------------------------------------
852 /* This displays the package record from the proper package index file.
853 It is not used by DumpAvail for performance reasons. */
854 bool DisplayRecord(pkgCache::VerIterator V
)
856 // Find an appropriate file
857 pkgCache::VerFileIterator Vf
= V
.FileList();
858 for (; Vf
.end() == false; Vf
++)
859 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
861 if (Vf
.end() == true)
864 // Check and load the package list file
865 pkgCache::PkgFileIterator I
= Vf
.File();
866 if (I
.IsOk() == false)
867 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
869 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
870 if (_error
->PendingError() == true)
873 // Read the record and then write it out again.
874 unsigned char *Buffer
= new unsigned char[GCache
->HeaderP
->MaxVerFileSize
+1];
875 Buffer
[V
.FileList()->Size
] = '\n';
876 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
877 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
878 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
+1) != V
.FileList()->Size
+1)
889 // Search - Perform a search /*{{{*/
890 // ---------------------------------------------------------------------
891 /* This searches the package names and pacakge descriptions for a pattern */
894 pkgCache::VerFile
*Vf
;
898 bool Search(CommandLine
&CmdL
)
900 pkgCache
&Cache
= *GCache
;
901 bool ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
902 bool NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
903 unsigned NumPatterns
= CmdL
.FileSize() -1;
905 pkgDepCache::Policy Plcy
;
907 // Make sure there is at least one argument
909 return _error
->Error(_("You must give exactly one pattern"));
911 // Compile the regex pattern
912 regex_t
*Patterns
= new regex_t
[NumPatterns
];
913 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
914 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
916 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
920 regfree(&Patterns
[I
]);
921 return _error
->Error("Regex compilation error");
925 // Create the text record parser
926 pkgRecords
Recs(Cache
);
927 if (_error
->PendingError() == true)
929 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
930 regfree(&Patterns
[I
]);
934 ExVerFile
*VFList
= new ExVerFile
[Cache
.HeaderP
->PackageCount
+1];
935 memset(VFList
,0,sizeof(*VFList
)*Cache
.HeaderP
->PackageCount
+1);
937 // Map versions that we want to write out onto the VerList array.
938 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
940 VFList
[P
->ID
].NameMatch
= NumPatterns
!= 0;
941 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
943 if (regexec(&Patterns
[I
],P
.Name(),0,0,0) == 0)
944 VFList
[P
->ID
].NameMatch
&= true;
946 VFList
[P
->ID
].NameMatch
= false;
949 // Doing names only, drop any that dont match..
950 if (NamesOnly
== true && VFList
[P
->ID
].NameMatch
== false)
953 // Find the proper version to use.
954 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
955 if (V
.end() == false)
956 VFList
[P
->ID
].Vf
= V
.FileList();
959 // Include all the packages that provide matching names too
960 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
962 if (VFList
[P
->ID
].NameMatch
== false)
965 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
967 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Prv
.OwnerPkg());
968 if (V
.end() == false)
970 VFList
[Prv
.OwnerPkg()->ID
].Vf
= V
.FileList();
971 VFList
[Prv
.OwnerPkg()->ID
].NameMatch
= true;
976 LocalitySort(&VFList
->Vf
,Cache
.HeaderP
->PackageCount
,sizeof(*VFList
));
978 // Iterate over all the version records and check them
979 for (ExVerFile
*J
= VFList
; J
->Vf
!= 0; J
++)
981 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::VerFileIterator(Cache
,J
->Vf
));
984 if (J
->NameMatch
== false)
986 string LongDesc
= P
.LongDesc();
987 Match
= NumPatterns
!= 0;
988 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
990 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
999 if (ShowFull
== true)
1003 P
.GetRec(Start
,End
);
1004 fwrite(Start
,End
-Start
,1,stdout
);
1008 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1013 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1014 regfree(&Patterns
[I
]);
1016 return _error
->Error("Write to stdout failed");
1020 // ShowPackage - Dump the package record to the screen /*{{{*/
1021 // ---------------------------------------------------------------------
1023 bool ShowPackage(CommandLine
&CmdL
)
1025 pkgCache
&Cache
= *GCache
;
1026 pkgDepCache::Policy Plcy
;
1028 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1030 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1031 if (Pkg
.end() == true)
1033 _error
->Warning(_("Unable to locate package %s"),*I
);
1037 // Find the proper version to use.
1038 if (_config
->FindB("APT::Cache::AllVersions","true") == true)
1040 pkgCache::VerIterator V
;
1041 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1043 if (DisplayRecord(V
) == false)
1049 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1050 if (V
.end() == true || V
.FileList().end() == true)
1052 if (DisplayRecord(V
) == false)
1059 // ShowPkgNames - Show package names /*{{{*/
1060 // ---------------------------------------------------------------------
1061 /* This does a prefix match on the first argument */
1062 bool ShowPkgNames(CommandLine
&CmdL
)
1064 pkgCache
&Cache
= *GCache
;
1065 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1066 bool All
= _config
->FindB("APT::Cache::AllNames","false");
1068 if (CmdL
.FileList
[1] != 0)
1070 for (;I
.end() != true; I
++)
1072 if (All
== false && I
->VersionList
== 0)
1075 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1076 cout
<< I
.Name() << endl
;
1083 for (;I
.end() != true; I
++)
1085 if (All
== false && I
->VersionList
== 0)
1087 cout
<< I
.Name() << endl
;
1093 // ShowSrcPackage - Show source package records /*{{{*/
1094 // ---------------------------------------------------------------------
1096 bool ShowSrcPackage(CommandLine
&CmdL
)
1099 List
.ReadMainList();
1101 // Create the text record parsers
1102 pkgSrcRecords
SrcRecs(List
);
1103 if (_error
->PendingError() == true)
1106 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1110 pkgSrcRecords::Parser
*Parse
;
1111 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0)
1112 cout
<< Parse
->AsStr() << endl
;;
1117 // Policy - Show the results of the preferences file /*{{{*/
1118 // ---------------------------------------------------------------------
1120 bool Policy(CommandLine
&CmdL
)
1123 return _error
->Error("Generate must be enabled for this function");
1125 pkgCache
&Cache
= *GCache
;
1126 pkgPolicy
Plcy(&Cache
);
1127 if (ReadPinFile(Plcy
) == false)
1130 // Print out all of the package files
1131 if (CmdL
.FileList
[1] == 0)
1133 cout
<< _("Package Files:") << endl
;
1134 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
1136 // Locate the associated index files so we can derive a description
1138 if (SrcList
->FindIndex(F
,Indx
) == false &&
1139 _system
->FindIndex(F
,Indx
) == false)
1140 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1141 printf(_("%4i %s\n"),
1142 Plcy
.GetPriority(F
),Indx
->Describe(true).c_str());
1144 // Print the reference information for the package
1145 string Str
= F
.RelStr();
1146 if (Str
.empty() == false)
1147 printf(" release %s\n",F
.RelStr().c_str());
1148 if (F
.Site() != 0 && F
.Site()[0] != 0)
1149 printf(" origin %s\n",F
.Site());
1152 // Show any packages have explicit pins
1153 cout
<< _("Pinned Packages:") << endl
;
1154 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1155 for (;I
.end() != true; I
++)
1157 if (Plcy
.GetPriority(I
) == 0)
1160 // Print the package name and the version we are forcing to
1161 cout
<< " " << I
.Name() << " -> ";
1163 pkgCache::VerIterator V
= Plcy
.GetMatch(I
);
1164 if (V
.end() == true)
1165 cout
<< _("(not found)") << endl
;
1167 cout
<< V
.VerStr() << endl
;
1173 // Print out detailed information for each package
1174 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1176 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1177 if (Pkg
.end() == true)
1179 _error
->Warning(_("Unable to locate package %s"),*I
);
1183 cout
<< Pkg
.Name() << ":" << endl
;
1185 // Installed version
1186 cout
<< _(" Installed: ");
1187 if (Pkg
->CurrentVer
== 0)
1188 cout
<< _("(none)") << endl
;
1190 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1192 // Candidate Version
1193 cout
<< _(" Candidate: ");
1194 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1195 if (V
.end() == true)
1196 cout
<< _("(none)") << endl
;
1198 cout
<< V
.VerStr() << endl
;
1201 if (Plcy
.GetPriority(Pkg
) != 0)
1203 cout
<< _(" Package Pin: ");
1204 V
= Plcy
.GetMatch(Pkg
);
1205 if (V
.end() == true)
1206 cout
<< _("(not found)") << endl
;
1208 cout
<< V
.VerStr() << endl
;
1211 // Show the priority tables
1212 cout
<< _(" Version Table:") << endl
;
1213 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1215 if (Pkg
.CurrentVer() == V
)
1216 cout
<< " *** " << V
.VerStr();
1218 cout
<< " " << V
.VerStr();
1219 cout
<< " " << Plcy
.GetPriority(Pkg
) << endl
;
1220 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1222 // Locate the associated index files so we can derive a description
1224 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1225 _system
->FindIndex(VF
.File(),Indx
) == false)
1226 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1227 printf(_(" %4i %s\n"),Plcy
.GetPriority(VF
.File()),
1228 Indx
->Describe(true).c_str());
1236 // GenCaches - Call the main cache generator /*{{{*/
1237 // ---------------------------------------------------------------------
1239 bool GenCaches(CommandLine
&Cmd
)
1241 OpTextProgress
Progress(*_config
);
1244 if (List
.ReadMainList() == false)
1246 return pkgMakeStatusCache(List
,Progress
);
1249 // ShowHelp - Show a help screen /*{{{*/
1250 // ---------------------------------------------------------------------
1252 bool ShowHelp(CommandLine
&Cmd
)
1254 ioprintf(cout
,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1255 COMMON_OS
,COMMON_CPU
,__DATE__
,__TIME__
);
1258 _("Usage: apt-cache [options] command\n"
1259 " apt-cache [options] add file1 [file1 ...]\n"
1260 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1262 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1263 "cache files, and query information from them\n"
1266 " add - Add an package file to the source cache\n"
1267 " gencaches - Build both the package and source cache\n"
1268 " showpkg - Show some general information for a single package\n"
1269 " stats - Show some basic statistics\n"
1270 " dump - Show the entire file in a terse form\n"
1271 " dumpavail - Print an available file to stdout\n"
1272 " unmet - Show unmet dependencies\n"
1273 " search - Search the package list for a regex pattern\n"
1274 " show - Show a readable record for the package\n"
1275 " depends - Show raw dependency information for a package\n"
1276 " pkgnames - List the names of all packages\n"
1277 " dotty - Generate package graphs for GraphVis\n"
1278 " policy - Show policy settings\n"
1281 " -h This help text.\n"
1282 " -p=? The package cache.\n"
1283 " -s=? The source cache.\n"
1284 " -q Disable progress indicator.\n"
1285 " -i Show only important deps for the unmet command.\n"
1286 " -c=? Read this configuration file\n"
1287 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1288 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1292 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1293 // ---------------------------------------------------------------------
1295 void CacheInitialize()
1297 _config
->Set("quiet",0);
1298 _config
->Set("help",false);
1302 int main(int argc
,const char *argv
[])
1304 CommandLine::Args Args
[] = {
1305 {'h',"help","help",0},
1306 {'v',"version","version",0},
1307 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1308 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1309 {'q',"quiet","quiet",CommandLine::IntLevel
},
1310 {'i',"important","APT::Cache::Important",0},
1311 {'f',"full","APT::Cache::ShowFull",0},
1312 {'g',"generate","APT::Cache::Generate",0},
1313 {'a',"all-versions","APT::Cache::AllVersions",0},
1314 {0,"names-only","APT::Cache::NamesOnly",0},
1315 {0,"all-names","APT::Cache::AllNames",0},
1316 {0,"recurse","APT::Cache::RecurseDepends",0},
1317 {'c',"config-file",0,CommandLine::ConfigFile
},
1318 {'o',"option",0,CommandLine::ArbItem
},
1320 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1322 {"gencaches",&GenCaches
},
1323 {"showsrc",&ShowSrcPackage
},
1325 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1328 {"dumpavail",&DumpAvail
},
1331 {"depends",&Depends
},
1333 {"show",&ShowPackage
},
1334 {"pkgnames",&ShowPkgNames
},
1340 // Parse the command line and initialize the package library
1341 CommandLine
CmdL(Args
,_config
);
1342 if (pkgInitConfig(*_config
) == false ||
1343 CmdL
.Parse(argc
,argv
) == false ||
1344 pkgInitSystem(*_config
,_system
) == false)
1346 _error
->DumpErrors();
1350 // See if the help should be shown
1351 if (_config
->FindB("help") == true ||
1352 CmdL
.FileSize() == 0)
1358 // Deal with stdout not being a tty
1359 if (ttyname(STDOUT_FILENO
) == 0 && _config
->FindI("quiet",0) < 1)
1360 _config
->Set("quiet","1");
1362 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1365 if (_config
->FindB("APT::Cache::Generate",true) == false)
1367 Map
= new MMap(*new FileFd(_config
->FindFile("Dir::Cache::pkgcache"),
1368 FileFd::ReadOnly
),MMap::Public
|MMap::ReadOnly
);
1372 // Open the cache file
1373 SrcList
= new pkgSourceList
;
1374 SrcList
->ReadMainList();
1376 // Generate it and map it
1378 pkgMakeStatusCache(*SrcList
,Prog
,&Map
,true);
1381 if (_error
->PendingError() == false)
1383 pkgCache
Cache(Map
);
1385 if (_error
->PendingError() == false)
1386 CmdL
.DispatchArg(CmdsB
);
1391 // Print any errors or warnings found during parsing
1392 if (_error
->empty() == false)
1394 bool Errors
= _error
->PendingError();
1395 _error
->DumpErrors();
1396 return Errors
== true?100:0;