]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.60 2003/01/11 07:18: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>
45 pkgSourceList
*SrcList
= 0;
47 // LocalitySort - Sort a version list by package file locality /*{{{*/
48 // ---------------------------------------------------------------------
50 int LocalityCompare(const void *a
, const void *b
)
52 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
53 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
62 if (A
->File
== B
->File
)
63 return A
->Offset
- B
->Offset
;
64 return A
->File
- B
->File
;
67 void LocalitySort(pkgCache::VerFile
**begin
,
68 unsigned long Count
,size_t Size
)
70 qsort(begin
,Count
,Size
,LocalityCompare
);
73 // UnMet - Show unmet dependencies /*{{{*/
74 // ---------------------------------------------------------------------
76 bool UnMet(CommandLine
&CmdL
)
78 pkgCache
&Cache
= *GCache
;
79 bool Important
= _config
->FindB("APT::Cache::Important",false);
81 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
83 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
86 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
89 pkgCache::DepIterator Start
;
90 pkgCache::DepIterator End
;
93 // Skip conflicts and replaces
94 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
95 End
->Type
!= pkgCache::Dep::Depends
&&
96 End
->Type
!= pkgCache::Dep::Suggests
&&
97 End
->Type
!= pkgCache::Dep::Recommends
)
100 // Important deps only
101 if (Important
== true)
102 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
103 End
->Type
!= pkgCache::Dep::Depends
)
106 // Verify the or group
108 pkgCache::DepIterator RealStart
= Start
;
111 // See if this dep is Ok
112 pkgCache::Version
**VList
= Start
.AllTargets();
133 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
134 P
.Name(),V
.VerStr());
137 // Print out the dep type
138 cout
<< " " << End
.DepType() << ": ";
144 cout
<< Start
.TargetPkg().Name();
145 if (Start
.TargetVer() != 0)
146 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
162 // DumpPackage - Show a dump of a package record /*{{{*/
163 // ---------------------------------------------------------------------
165 bool DumpPackage(CommandLine
&CmdL
)
167 pkgCache
&Cache
= *GCache
;
168 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
170 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
171 if (Pkg
.end() == true)
173 _error
->Warning(_("Unable to locate package %s"),*I
);
177 cout
<< "Package: " << Pkg
.Name() << endl
;
178 cout
<< "Versions: " << endl
;
179 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
181 cout
<< Cur
.VerStr();
182 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
183 cout
<< "(" << Vf
.File().FileName() << ")";
189 cout
<< "Reverse Depends: " << endl
;
190 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
192 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name();
194 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
199 cout
<< "Dependencies: " << endl
;
200 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
202 cout
<< Cur
.VerStr() << " - ";
203 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
204 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
208 cout
<< "Provides: " << endl
;
209 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
211 cout
<< Cur
.VerStr() << " - ";
212 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
213 cout
<< Prv
.ParentPkg().Name() << " ";
216 cout
<< "Reverse Provides: " << endl
;
217 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
218 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr() << endl
;
224 // Stats - Dump some nice statistics /*{{{*/
225 // ---------------------------------------------------------------------
227 bool Stats(CommandLine
&Cmd
)
229 pkgCache
&Cache
= *GCache
;
230 cout
<< _("Total Package Names : ") << Cache
.Head().PackageCount
<< " (" <<
231 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
238 pkgCache::PkgIterator I
= Cache
.PkgBegin();
239 for (;I
.end() != true; I
++)
241 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
247 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
253 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
256 if (I
.ProvidesList()->NextProvides
== 0)
264 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
270 cout
<< _(" Normal Packages: ") << Normal
<< endl
;
271 cout
<< _(" Pure Virtual Packages: ") << Virtual
<< endl
;
272 cout
<< _(" Single Virtual Packages: ") << DVirt
<< endl
;
273 cout
<< _(" Mixed Virtual Packages: ") << NVirt
<< endl
;
274 cout
<< _(" Missing: ") << Missing
<< endl
;
276 cout
<< _("Total Distinct Versions: ") << Cache
.Head().VersionCount
<< " (" <<
277 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
278 cout
<< _("Total Dependencies: ") << Cache
.Head().DependsCount
<< " (" <<
279 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
281 cout
<< _("Total Ver/File relations: ") << Cache
.Head().VerFileCount
<< " (" <<
282 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
283 cout
<< _("Total Provides Mappings: ") << Cache
.Head().ProvidesCount
<< " (" <<
284 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
287 unsigned long Size
= 0;
288 unsigned long Count
= 0;
289 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
290 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
293 Size
+= strlen(Cache
.StrP
+ I
->String
) + 1;
295 cout
<< _("Total Globbed Strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
297 unsigned long DepVerSize
= 0;
298 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
300 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
302 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
305 DepVerSize
+= strlen(D
.TargetVer()) + 1;
309 cout
<< _("Total Dependency Version space: ") << SizeToStr(DepVerSize
) << endl
;
311 unsigned long Slack
= 0;
312 for (int I
= 0; I
!= 7; I
++)
313 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
314 cout
<< _("Total Slack space: ") << SizeToStr(Slack
) << endl
;
316 unsigned long Total
= 0;
317 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
318 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
319 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
320 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
321 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
322 cout
<< _("Total Space Accounted for: ") << SizeToStr(Total
) << endl
;
327 // Dump - show everything /*{{{*/
328 // ---------------------------------------------------------------------
329 /* This is worthless except fer debugging things */
330 bool Dump(CommandLine
&Cmd
)
332 pkgCache
&Cache
= *GCache
;
333 cout
<< "Using Versioning System: " << Cache
.VS
->Label
<< endl
;
335 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
337 cout
<< "Package: " << P
.Name() << endl
;
338 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
340 cout
<< " Version: " << V
.VerStr() << endl
;
341 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
342 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
343 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' <<
344 DeNull(D
.TargetVer()) << endl
;
348 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
350 cout
<< "File: " << F
.FileName() << endl
;
351 cout
<< " Type: " << F
.IndexType() << endl
;
352 cout
<< " Size: " << F
->Size
<< endl
;
353 cout
<< " ID: " << F
->ID
<< endl
;
354 cout
<< " Flags: " << F
->Flags
<< endl
;
355 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
356 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
357 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
358 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
359 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
360 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
361 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
362 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
368 // DumpAvail - Print out the available list /*{{{*/
369 // ---------------------------------------------------------------------
370 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
371 make this run really fast, perhaps I went a little overboard.. */
372 bool DumpAvail(CommandLine
&Cmd
)
374 pkgCache
&Cache
= *GCache
;
376 pkgPolicy
Plcy(&Cache
);
377 if (ReadPinFile(Plcy
) == false)
380 unsigned long Count
= Cache
.HeaderP
->PackageCount
+1;
381 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
382 memset(VFList
,0,sizeof(*VFList
)*Count
);
384 // Map versions that we want to write out onto the VerList array.
385 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
387 if (P
->VersionList
== 0)
390 /* Find the proper version to use. If the policy says there are no
391 possible selections we return the installed version, if available..
392 This prevents dselect from making it obsolete. */
393 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
396 if (P
->CurrentVer
== 0)
401 pkgCache::VerFileIterator VF
= V
.FileList();
402 for (; VF
.end() == false ; VF
++)
403 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
406 /* Okay, here we have a bit of a problem.. The policy has selected the
407 currently installed package - however it only exists in the
408 status file.. We need to write out something or dselect will mark
409 the package as obsolete! Thus we emit the status file entry, but
410 below we remove the status line to make it valid for the
411 available file. However! We only do this if their do exist *any*
412 non-source versions of the package - that way the dselect obsolete
413 handling works OK. */
414 if (VF
.end() == true)
416 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
418 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
420 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
427 if (VF
.end() == false)
435 LocalitySort(VFList
,Count
,sizeof(*VFList
));
437 // Iterate over all the package files and write them out.
438 char *Buffer
= new char[Cache
.HeaderP
->MaxVerFileSize
+10];
439 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
441 pkgCache::PkgFileIterator
File(Cache
,(*J
)->File
+ Cache
.PkgFileP
);
442 if (File
.IsOk() == false)
444 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
448 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
449 if (_error
->PendingError() == true)
452 /* Write all of the records from this package file, since we
453 already did locality sorting we can now just seek through the
454 file in read order. We apply 1 more optimization here, since often
455 there will be < 1 byte gaps between records (for the \n) we read that
456 into the next buffer and offset a bit.. */
457 unsigned long Pos
= 0;
460 if ((*J
)->File
+ Cache
.PkgFileP
!= File
)
463 const pkgCache::VerFile
&VF
= **J
;
465 // Read the record and then write it out again.
466 unsigned long Jitter
= VF
.Offset
- Pos
;
469 if (PkgF
.Seek(VF
.Offset
) == false)
474 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
476 Buffer
[VF
.Size
+ Jitter
] = '\n';
479 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
482 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
483 const char *Zero
= 0;
484 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
485 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
487 _error
->Error("Internal Error, Unable to parse a package record");
494 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
498 Pos
= VF
.Offset
+ VF
.Size
;
502 if (_error
->PendingError() == true)
508 return !_error
->PendingError();
511 // Depends - Print out a dependency tree /*{{{*/
512 // ---------------------------------------------------------------------
514 bool Depends(CommandLine
&CmdL
)
516 pkgCache
&Cache
= *GCache
;
517 SPtrArray
<unsigned> Colours
= new unsigned[Cache
.Head().PackageCount
];
518 memset(Colours
,0,sizeof(*Colours
)*Cache
.Head().PackageCount
);
520 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
522 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
523 if (Pkg
.end() == true)
525 _error
->Warning(_("Unable to locate package %s"),*I
);
528 Colours
[Pkg
->ID
] = 1;
531 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
535 DidSomething
= false;
536 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
538 if (Colours
[Pkg
->ID
] != 1)
540 Colours
[Pkg
->ID
] = 2;
543 pkgCache::VerIterator Ver
= Pkg
.VersionList();
544 if (Ver
.end() == true)
546 cout
<< '<' << Pkg
.Name() << '>' << endl
;
550 cout
<< Pkg
.Name() << endl
;
552 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
554 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
560 pkgCache::PkgIterator Trg
= D
.TargetPkg();
561 if (Trg
->VersionList
== 0)
562 cout
<< D
.DepType() << ": <" << Trg
.Name() << ">" << endl
;
564 cout
<< D
.DepType() << ": " << Trg
.Name() << endl
;
567 Colours
[D
.TargetPkg()->ID
]++;
569 // Display all solutions
570 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
571 pkgPrioSortList(Cache
,List
);
572 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
574 pkgCache::VerIterator
V(Cache
,*I
);
575 if (V
!= Cache
.VerP
+ V
.ParentPkg()->VersionList
||
576 V
->ParentPkg
== D
->Package
)
578 cout
<< " " << V
.ParentPkg().Name() << endl
;
581 Colours
[D
.ParentPkg()->ID
]++;
586 while (DidSomething
== true);
591 // Dotty - Generate a graph for Dotty /*{{{*/
592 // ---------------------------------------------------------------------
593 /* Dotty is the graphvis program for generating graphs. It is a fairly
594 simple queuing algorithm that just writes dependencies and nodes.
595 http://www.research.att.com/sw/tools/graphviz/ */
596 bool Dotty(CommandLine
&CmdL
)
598 pkgCache
&Cache
= *GCache
;
599 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
601 /* Normal packages are boxes
602 Pure Provides are triangles
604 Hexagons are missing packages*/
605 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
607 /* Initialize the list of packages to show.
609 2 = To Show no recurse
610 3 = Emitted no recurse
613 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
614 enum TheFlags
{ForceNR
=(1<<0)};
615 unsigned char *Show
= new unsigned char[Cache
.Head().PackageCount
];
616 unsigned char *Flags
= new unsigned char[Cache
.Head().PackageCount
];
617 unsigned char *ShapeMap
= new unsigned char[Cache
.Head().PackageCount
];
619 // Show everything if no arguments given
620 if (CmdL
.FileList
[1] == 0)
621 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
624 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
626 memset(Flags
,0,sizeof(*Flags
)*Cache
.Head().PackageCount
);
629 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
631 if (Pkg
->VersionList
== 0)
634 if (Pkg
->ProvidesList
== 0)
635 ShapeMap
[Pkg
->ID
] = 0;
637 ShapeMap
[Pkg
->ID
] = 1;
642 if (Pkg
->ProvidesList
== 0)
643 ShapeMap
[Pkg
->ID
] = 2;
645 ShapeMap
[Pkg
->ID
] = 3;
649 // Load the list of packages from the command line into the show list
650 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
652 // Process per-package flags
657 if (P
.end()[-1] == '^')
663 if (P
.end()[-1] == ',')
667 // Locate the package
668 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(P
);
669 if (Pkg
.end() == true)
671 _error
->Warning(_("Unable to locate package %s"),*I
);
674 Show
[Pkg
->ID
] = ToShow
;
677 Flags
[Pkg
->ID
] |= ForceNR
;
681 printf("digraph packages {\n");
682 printf("concentrate=true;\n");
683 printf("size=\"30,40\";\n");
689 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
691 // See we need to show this package
692 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
696 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
698 // Pure Provides and missing packages have no deps!
699 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
700 Show
[Pkg
->ID
] = Done
;
702 Show
[Pkg
->ID
] = DoneNR
;
705 Show
[Pkg
->ID
] = Done
;
708 // No deps to map out
709 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
712 pkgCache::VerIterator Ver
= Pkg
.VersionList();
713 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
715 // See if anything can meet this dep
716 // Walk along the actual package providing versions
718 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
719 for (pkgCache::VerIterator I
= DPkg
.VersionList();
720 I
.end() == false && Hit
== false; I
++)
722 if (Cache
.VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
726 // Follow all provides
727 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
728 I
.end() == false && Hit
== false; I
++)
730 if (Cache
.VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
734 // Only graph critical deps
735 if (D
.IsCritical() == true)
737 printf("\"%s\" -> \"%s\"",Pkg
.Name(),D
.TargetPkg().Name());
739 // Colour the node for recursion
740 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
742 /* If a conflicts does not meet anything in the database
743 then show the relation but do not recurse */
745 (D
->Type
== pkgCache::Dep::Conflicts
||
746 D
->Type
== pkgCache::Dep::Obsoletes
))
748 if (Show
[D
.TargetPkg()->ID
] == None
&&
749 Show
[D
.TargetPkg()->ID
] != ToShow
)
750 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
754 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
755 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
757 Show
[D
.TargetPkg()->ID
] = ToShow
;
764 case pkgCache::Dep::Conflicts
:
765 case pkgCache::Dep::Obsoletes
:
766 printf("[color=springgreen];\n");
769 case pkgCache::Dep::PreDepends
:
770 printf("[color=blue];\n");
782 /* Draw the box colours after the fact since we can not tell what colour
783 they should be until everything is finished drawing */
784 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
786 if (Show
[Pkg
->ID
] < DoneNR
)
789 // Orange box for early recursion stoppage
790 if (Show
[Pkg
->ID
] == DoneNR
)
791 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.Name(),
792 Shapes
[ShapeMap
[Pkg
->ID
]]);
794 printf("\"%s\" [shape=%s];\n",Pkg
.Name(),
795 Shapes
[ShapeMap
[Pkg
->ID
]]);
802 // DoAdd - Perform an adding operation /*{{{*/
803 // ---------------------------------------------------------------------
805 bool DoAdd(CommandLine
&CmdL
)
807 return _error
->Error("Unimplemented");
809 // Make sure there is at least one argument
810 if (CmdL
.FileSize() <= 1)
811 return _error
->Error("You must give at least one file name");
814 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
815 if (_error
->PendingError() == true)
818 DynamicMMap
Map(CacheF
,MMap::Public
);
819 if (_error
->PendingError() == true)
822 OpTextProgress
Progress(*_config
);
823 pkgCacheGenerator
Gen(Map
,Progress
);
824 if (_error
->PendingError() == true)
827 unsigned long Length
= CmdL
.FileSize() - 1;
828 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
830 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
831 Progress
.SubProgress(Length
);
834 FileFd
TagF(*I
,FileFd::ReadOnly
);
835 debListParser
Parser(TagF
);
836 if (_error
->PendingError() == true)
837 return _error
->Error("Problem opening %s",*I
);
839 if (Gen
.SelectFile(*I
,"") == false)
840 return _error
->Error("Problem with SelectFile");
842 if (Gen
.MergeList(Parser
) == false)
843 return _error
->Error("Problem with MergeList");
847 GCache
= &Gen
.GetCache();
854 // DisplayRecord - Displays the complete record for the package /*{{{*/
855 // ---------------------------------------------------------------------
856 /* This displays the package record from the proper package index file.
857 It is not used by DumpAvail for performance reasons. */
858 bool DisplayRecord(pkgCache::VerIterator V
)
860 // Find an appropriate file
861 pkgCache::VerFileIterator Vf
= V
.FileList();
862 for (; Vf
.end() == false; Vf
++)
863 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
865 if (Vf
.end() == true)
868 // Check and load the package list file
869 pkgCache::PkgFileIterator I
= Vf
.File();
870 if (I
.IsOk() == false)
871 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
873 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
874 if (_error
->PendingError() == true)
877 // Read the record and then write it out again.
878 unsigned char *Buffer
= new unsigned char[GCache
->HeaderP
->MaxVerFileSize
+1];
879 Buffer
[V
.FileList()->Size
] = '\n';
880 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
881 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
882 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
+1) != V
.FileList()->Size
+1)
893 // Search - Perform a search /*{{{*/
894 // ---------------------------------------------------------------------
895 /* This searches the package names and pacakge descriptions for a pattern */
898 pkgCache::VerFile
*Vf
;
902 bool Search(CommandLine
&CmdL
)
904 pkgCache
&Cache
= *GCache
;
905 bool ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
906 bool NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
907 unsigned NumPatterns
= CmdL
.FileSize() -1;
909 pkgDepCache::Policy Plcy
;
911 // Make sure there is at least one argument
913 return _error
->Error(_("You must give exactly one pattern"));
915 // Compile the regex pattern
916 regex_t
*Patterns
= new regex_t
[NumPatterns
];
917 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
918 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
920 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
924 regfree(&Patterns
[I
]);
925 return _error
->Error("Regex compilation error");
929 // Create the text record parser
930 pkgRecords
Recs(Cache
);
931 if (_error
->PendingError() == true)
933 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
934 regfree(&Patterns
[I
]);
938 ExVerFile
*VFList
= new ExVerFile
[Cache
.HeaderP
->PackageCount
+1];
939 memset(VFList
,0,sizeof(*VFList
)*Cache
.HeaderP
->PackageCount
+1);
941 // Map versions that we want to write out onto the VerList array.
942 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
944 VFList
[P
->ID
].NameMatch
= NumPatterns
!= 0;
945 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
947 if (regexec(&Patterns
[I
],P
.Name(),0,0,0) == 0)
948 VFList
[P
->ID
].NameMatch
&= true;
950 VFList
[P
->ID
].NameMatch
= false;
953 // Doing names only, drop any that dont match..
954 if (NamesOnly
== true && VFList
[P
->ID
].NameMatch
== false)
957 // Find the proper version to use.
958 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
959 if (V
.end() == false)
960 VFList
[P
->ID
].Vf
= V
.FileList();
963 // Include all the packages that provide matching names too
964 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
966 if (VFList
[P
->ID
].NameMatch
== false)
969 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
971 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Prv
.OwnerPkg());
972 if (V
.end() == false)
974 VFList
[Prv
.OwnerPkg()->ID
].Vf
= V
.FileList();
975 VFList
[Prv
.OwnerPkg()->ID
].NameMatch
= true;
980 LocalitySort(&VFList
->Vf
,Cache
.HeaderP
->PackageCount
,sizeof(*VFList
));
982 // Iterate over all the version records and check them
983 for (ExVerFile
*J
= VFList
; J
->Vf
!= 0; J
++)
985 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::VerFileIterator(Cache
,J
->Vf
));
988 if (J
->NameMatch
== false)
990 string LongDesc
= P
.LongDesc();
991 Match
= NumPatterns
!= 0;
992 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
994 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1003 if (ShowFull
== true)
1007 P
.GetRec(Start
,End
);
1008 fwrite(Start
,End
-Start
,1,stdout
);
1012 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1017 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1018 regfree(&Patterns
[I
]);
1020 return _error
->Error("Write to stdout failed");
1024 // ShowPackage - Dump the package record to the screen /*{{{*/
1025 // ---------------------------------------------------------------------
1027 bool ShowPackage(CommandLine
&CmdL
)
1029 pkgCache
&Cache
= *GCache
;
1030 pkgDepCache::Policy Plcy
;
1032 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1034 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1035 if (Pkg
.end() == true)
1037 _error
->Warning(_("Unable to locate package %s"),*I
);
1041 // Find the proper version to use.
1042 if (_config
->FindB("APT::Cache::AllVersions","true") == true)
1044 pkgCache::VerIterator V
;
1045 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1047 if (DisplayRecord(V
) == false)
1053 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1054 if (V
.end() == true || V
.FileList().end() == true)
1056 if (DisplayRecord(V
) == false)
1063 // ShowPkgNames - Show package names /*{{{*/
1064 // ---------------------------------------------------------------------
1065 /* This does a prefix match on the first argument */
1066 bool ShowPkgNames(CommandLine
&CmdL
)
1068 pkgCache
&Cache
= *GCache
;
1069 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1070 bool All
= _config
->FindB("APT::Cache::AllNames","false");
1072 if (CmdL
.FileList
[1] != 0)
1074 for (;I
.end() != true; I
++)
1076 if (All
== false && I
->VersionList
== 0)
1079 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1080 cout
<< I
.Name() << endl
;
1087 for (;I
.end() != true; I
++)
1089 if (All
== false && I
->VersionList
== 0)
1091 cout
<< I
.Name() << endl
;
1097 // ShowSrcPackage - Show source package records /*{{{*/
1098 // ---------------------------------------------------------------------
1100 bool ShowSrcPackage(CommandLine
&CmdL
)
1103 List
.ReadMainList();
1105 // Create the text record parsers
1106 pkgSrcRecords
SrcRecs(List
);
1107 if (_error
->PendingError() == true)
1110 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1114 pkgSrcRecords::Parser
*Parse
;
1115 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0)
1116 cout
<< Parse
->AsStr() << endl
;;
1121 // Policy - Show the results of the preferences file /*{{{*/
1122 // ---------------------------------------------------------------------
1124 bool Policy(CommandLine
&CmdL
)
1127 return _error
->Error("Generate must be enabled for this function");
1129 pkgCache
&Cache
= *GCache
;
1130 pkgPolicy
Plcy(&Cache
);
1131 if (ReadPinFile(Plcy
) == false)
1134 // Print out all of the package files
1135 if (CmdL
.FileList
[1] == 0)
1137 cout
<< _("Package Files:") << endl
;
1138 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
1140 // Locate the associated index files so we can derive a description
1142 if (SrcList
->FindIndex(F
,Indx
) == false &&
1143 _system
->FindIndex(F
,Indx
) == false)
1144 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1145 printf(_("%4i %s\n"),
1146 Plcy
.GetPriority(F
),Indx
->Describe(true).c_str());
1148 // Print the reference information for the package
1149 string Str
= F
.RelStr();
1150 if (Str
.empty() == false)
1151 printf(" release %s\n",F
.RelStr().c_str());
1152 if (F
.Site() != 0 && F
.Site()[0] != 0)
1153 printf(" origin %s\n",F
.Site());
1156 // Show any packages have explicit pins
1157 cout
<< _("Pinned Packages:") << endl
;
1158 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1159 for (;I
.end() != true; I
++)
1161 if (Plcy
.GetPriority(I
) == 0)
1164 // Print the package name and the version we are forcing to
1165 cout
<< " " << I
.Name() << " -> ";
1167 pkgCache::VerIterator V
= Plcy
.GetMatch(I
);
1168 if (V
.end() == true)
1169 cout
<< _("(not found)") << endl
;
1171 cout
<< V
.VerStr() << endl
;
1177 // Print out detailed information for each package
1178 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1180 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1181 if (Pkg
.end() == true)
1183 _error
->Warning(_("Unable to locate package %s"),*I
);
1187 cout
<< Pkg
.Name() << ":" << endl
;
1189 // Installed version
1190 cout
<< _(" Installed: ");
1191 if (Pkg
->CurrentVer
== 0)
1192 cout
<< _("(none)") << endl
;
1194 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1196 // Candidate Version
1197 cout
<< _(" Candidate: ");
1198 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1199 if (V
.end() == true)
1200 cout
<< _("(none)") << endl
;
1202 cout
<< V
.VerStr() << endl
;
1205 if (Plcy
.GetPriority(Pkg
) != 0)
1207 cout
<< _(" Package Pin: ");
1208 V
= Plcy
.GetMatch(Pkg
);
1209 if (V
.end() == true)
1210 cout
<< _("(not found)") << endl
;
1212 cout
<< V
.VerStr() << endl
;
1215 // Show the priority tables
1216 cout
<< _(" Version Table:") << endl
;
1217 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1219 if (Pkg
.CurrentVer() == V
)
1220 cout
<< " *** " << V
.VerStr();
1222 cout
<< " " << V
.VerStr();
1223 cout
<< " " << Plcy
.GetPriority(Pkg
) << endl
;
1224 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1226 // Locate the associated index files so we can derive a description
1228 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1229 _system
->FindIndex(VF
.File(),Indx
) == false)
1230 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1231 printf(_(" %4i %s\n"),Plcy
.GetPriority(VF
.File()),
1232 Indx
->Describe(true).c_str());
1240 // GenCaches - Call the main cache generator /*{{{*/
1241 // ---------------------------------------------------------------------
1243 bool GenCaches(CommandLine
&Cmd
)
1245 OpTextProgress
Progress(*_config
);
1248 if (List
.ReadMainList() == false)
1250 return pkgMakeStatusCache(List
,Progress
);
1253 // ShowHelp - Show a help screen /*{{{*/
1254 // ---------------------------------------------------------------------
1256 bool ShowHelp(CommandLine
&Cmd
)
1258 ioprintf(cout
,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1259 COMMON_OS
,COMMON_CPU
,__DATE__
,__TIME__
);
1262 _("Usage: apt-cache [options] command\n"
1263 " apt-cache [options] add file1 [file1 ...]\n"
1264 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1265 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1267 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1268 "cache files, and query information from them\n"
1271 " add - Add an package file to the source cache\n"
1272 " gencaches - Build both the package and source cache\n"
1273 " showpkg - Show some general information for a single package\n"
1274 " showsrc - Show source records\n"
1275 " stats - Show some basic statistics\n"
1276 " dump - Show the entire file in a terse form\n"
1277 " dumpavail - Print an available file to stdout\n"
1278 " unmet - Show unmet dependencies\n"
1279 " search - Search the package list for a regex pattern\n"
1280 " show - Show a readable record for the package\n"
1281 " depends - Show raw dependency information for a package\n"
1282 " pkgnames - List the names of all packages\n"
1283 " dotty - Generate package graphs for GraphVis\n"
1284 " policy - Show policy settings\n"
1287 " -h This help text.\n"
1288 " -p=? The package cache.\n"
1289 " -s=? The source cache.\n"
1290 " -q Disable progress indicator.\n"
1291 " -i Show only important deps for the unmet command.\n"
1292 " -c=? Read this configuration file\n"
1293 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1294 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1298 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1299 // ---------------------------------------------------------------------
1301 void CacheInitialize()
1303 _config
->Set("quiet",0);
1304 _config
->Set("help",false);
1308 int main(int argc
,const char *argv
[])
1310 CommandLine::Args Args
[] = {
1311 {'h',"help","help",0},
1312 {'v',"version","version",0},
1313 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1314 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1315 {'q',"quiet","quiet",CommandLine::IntLevel
},
1316 {'i',"important","APT::Cache::Important",0},
1317 {'f',"full","APT::Cache::ShowFull",0},
1318 {'g',"generate","APT::Cache::Generate",0},
1319 {'a',"all-versions","APT::Cache::AllVersions",0},
1320 {0,"names-only","APT::Cache::NamesOnly",0},
1321 {'n',"all-names","APT::Cache::AllNames",0},
1322 {0,"recurse","APT::Cache::RecurseDepends",0},
1323 {'c',"config-file",0,CommandLine::ConfigFile
},
1324 {'o',"option",0,CommandLine::ArbItem
},
1326 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1328 {"gencaches",&GenCaches
},
1329 {"showsrc",&ShowSrcPackage
},
1331 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1334 {"dumpavail",&DumpAvail
},
1337 {"depends",&Depends
},
1339 {"show",&ShowPackage
},
1340 {"pkgnames",&ShowPkgNames
},
1346 // Set up gettext support
1347 setlocale(LC_ALL
,"");
1348 textdomain(PACKAGE
);
1350 // Parse the command line and initialize the package library
1351 CommandLine
CmdL(Args
,_config
);
1352 if (pkgInitConfig(*_config
) == false ||
1353 CmdL
.Parse(argc
,argv
) == false ||
1354 pkgInitSystem(*_config
,_system
) == false)
1356 _error
->DumpErrors();
1360 // See if the help should be shown
1361 if (_config
->FindB("help") == true ||
1362 CmdL
.FileSize() == 0)
1368 // Deal with stdout not being a tty
1369 if (ttyname(STDOUT_FILENO
) == 0 && _config
->FindI("quiet",0) < 1)
1370 _config
->Set("quiet","1");
1372 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1375 if (_config
->FindB("APT::Cache::Generate",true) == false)
1377 Map
= new MMap(*new FileFd(_config
->FindFile("Dir::Cache::pkgcache"),
1378 FileFd::ReadOnly
),MMap::Public
|MMap::ReadOnly
);
1382 // Open the cache file
1383 SrcList
= new pkgSourceList
;
1384 SrcList
->ReadMainList();
1386 // Generate it and map it
1388 pkgMakeStatusCache(*SrcList
,Prog
,&Map
,true);
1391 if (_error
->PendingError() == false)
1393 pkgCache
Cache(Map
);
1395 if (_error
->PendingError() == false)
1396 CmdL
.DispatchArg(CmdsB
);
1401 // Print any errors or warnings found during parsing
1402 if (_error
->empty() == false)
1404 bool Errors
= _error
->PendingError();
1405 _error
->DumpErrors();
1406 return Errors
== true?100:0;