]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.58 2002/03/26 07:38:58 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>
43 pkgSourceList
*SrcList
= 0;
45 // LocalitySort - Sort a version list by package file locality /*{{{*/
46 // ---------------------------------------------------------------------
48 int LocalityCompare(const void *a
, const void *b
)
50 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
51 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
60 if (A
->File
== B
->File
)
61 return A
->Offset
- B
->Offset
;
62 return A
->File
- B
->File
;
65 void LocalitySort(pkgCache::VerFile
**begin
,
66 unsigned long Count
,size_t Size
)
68 qsort(begin
,Count
,Size
,LocalityCompare
);
71 // UnMet - Show unmet dependencies /*{{{*/
72 // ---------------------------------------------------------------------
74 bool UnMet(CommandLine
&CmdL
)
76 pkgCache
&Cache
= *GCache
;
77 bool Important
= _config
->FindB("APT::Cache::Important",false);
79 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
81 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
84 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
87 pkgCache::DepIterator Start
;
88 pkgCache::DepIterator End
;
91 // Skip conflicts and replaces
92 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
93 End
->Type
!= pkgCache::Dep::Depends
&&
94 End
->Type
!= pkgCache::Dep::Suggests
&&
95 End
->Type
!= pkgCache::Dep::Recommends
)
98 // Important deps only
99 if (Important
== true)
100 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
101 End
->Type
!= pkgCache::Dep::Depends
)
104 // Verify the or group
106 pkgCache::DepIterator RealStart
= Start
;
109 // See if this dep is Ok
110 pkgCache::Version
**VList
= Start
.AllTargets();
131 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
132 P
.Name(),V
.VerStr());
135 // Print out the dep type
136 cout
<< " " << End
.DepType() << ": ";
142 cout
<< Start
.TargetPkg().Name();
143 if (Start
.TargetVer() != 0)
144 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
160 // DumpPackage - Show a dump of a package record /*{{{*/
161 // ---------------------------------------------------------------------
163 bool DumpPackage(CommandLine
&CmdL
)
165 pkgCache
&Cache
= *GCache
;
166 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
168 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
169 if (Pkg
.end() == true)
171 _error
->Warning(_("Unable to locate package %s"),*I
);
175 cout
<< "Package: " << Pkg
.Name() << endl
;
176 cout
<< "Versions: " << endl
;
177 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
179 cout
<< Cur
.VerStr();
180 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
181 cout
<< "(" << Vf
.File().FileName() << ")";
187 cout
<< "Reverse Depends: " << endl
;
188 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
190 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name();
192 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
197 cout
<< "Dependencies: " << endl
;
198 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
200 cout
<< Cur
.VerStr() << " - ";
201 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
202 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
206 cout
<< "Provides: " << endl
;
207 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
209 cout
<< Cur
.VerStr() << " - ";
210 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
211 cout
<< Prv
.ParentPkg().Name() << " ";
214 cout
<< "Reverse Provides: " << endl
;
215 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
216 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr() << endl
;
222 // Stats - Dump some nice statistics /*{{{*/
223 // ---------------------------------------------------------------------
225 bool Stats(CommandLine
&Cmd
)
227 pkgCache
&Cache
= *GCache
;
228 cout
<< _("Total Package Names : ") << Cache
.Head().PackageCount
<< " (" <<
229 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
236 pkgCache::PkgIterator I
= Cache
.PkgBegin();
237 for (;I
.end() != true; I
++)
239 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
245 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
251 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
254 if (I
.ProvidesList()->NextProvides
== 0)
262 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
268 cout
<< _(" Normal Packages: ") << Normal
<< endl
;
269 cout
<< _(" Pure Virtual Packages: ") << Virtual
<< endl
;
270 cout
<< _(" Single Virtual Packages: ") << DVirt
<< endl
;
271 cout
<< _(" Mixed Virtual Packages: ") << NVirt
<< endl
;
272 cout
<< _(" Missing: ") << Missing
<< endl
;
274 cout
<< _("Total Distinct Versions: ") << Cache
.Head().VersionCount
<< " (" <<
275 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
276 cout
<< _("Total Dependencies: ") << Cache
.Head().DependsCount
<< " (" <<
277 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
279 cout
<< _("Total Ver/File relations: ") << Cache
.Head().VerFileCount
<< " (" <<
280 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
281 cout
<< _("Total Provides Mappings: ") << Cache
.Head().ProvidesCount
<< " (" <<
282 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
285 unsigned long Size
= 0;
286 unsigned long Count
= 0;
287 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
288 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
291 Size
+= strlen(Cache
.StrP
+ I
->String
) + 1;
293 cout
<< _("Total Globbed Strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
295 unsigned long DepVerSize
= 0;
296 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
298 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
300 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
303 DepVerSize
+= strlen(D
.TargetVer()) + 1;
307 cout
<< _("Total Dependency Version space: ") << SizeToStr(DepVerSize
) << endl
;
309 unsigned long Slack
= 0;
310 for (int I
= 0; I
!= 7; I
++)
311 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
312 cout
<< _("Total Slack space: ") << SizeToStr(Slack
) << endl
;
314 unsigned long Total
= 0;
315 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
316 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
317 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
318 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
319 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
320 cout
<< _("Total Space Accounted for: ") << SizeToStr(Total
) << endl
;
325 // Dump - show everything /*{{{*/
326 // ---------------------------------------------------------------------
327 /* This is worthless except fer debugging things */
328 bool Dump(CommandLine
&Cmd
)
330 pkgCache
&Cache
= *GCache
;
331 cout
<< "Using Versioning System: " << Cache
.VS
->Label
<< endl
;
333 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
335 cout
<< "Package: " << P
.Name() << endl
;
336 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
338 cout
<< " Version: " << V
.VerStr() << endl
;
339 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
340 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
341 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' <<
342 DeNull(D
.TargetVer()) << endl
;
346 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
348 cout
<< "File: " << F
.FileName() << endl
;
349 cout
<< " Type: " << F
.IndexType() << endl
;
350 cout
<< " Size: " << F
->Size
<< endl
;
351 cout
<< " ID: " << F
->ID
<< endl
;
352 cout
<< " Flags: " << F
->Flags
<< endl
;
353 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
354 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
355 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
356 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
357 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
358 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
359 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
360 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
366 // DumpAvail - Print out the available list /*{{{*/
367 // ---------------------------------------------------------------------
368 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
369 make this run really fast, perhaps I went a little overboard.. */
370 bool DumpAvail(CommandLine
&Cmd
)
372 pkgCache
&Cache
= *GCache
;
374 pkgPolicy
Plcy(&Cache
);
375 if (ReadPinFile(Plcy
) == false)
378 unsigned long Count
= Cache
.HeaderP
->PackageCount
+1;
379 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
380 memset(VFList
,0,sizeof(*VFList
)*Count
);
382 // Map versions that we want to write out onto the VerList array.
383 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
385 if (P
->VersionList
== 0)
388 /* Find the proper version to use. If the policy says there are no
389 possible selections we return the installed version, if available..
390 This prevents dselect from making it obsolete. */
391 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
394 if (P
->CurrentVer
== 0)
399 pkgCache::VerFileIterator VF
= V
.FileList();
400 for (; VF
.end() == false ; VF
++)
401 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
404 /* Okay, here we have a bit of a problem.. The policy has selected the
405 currently installed package - however it only exists in the
406 status file.. We need to write out something or dselect will mark
407 the package as obsolete! Thus we emit the status file entry, but
408 below we remove the status line to make it valid for the
409 available file. However! We only do this if their do exist *any*
410 non-source versions of the package - that way the dselect obsolete
411 handling works OK. */
412 if (VF
.end() == true)
414 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
416 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
418 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
425 if (VF
.end() == false)
433 LocalitySort(VFList
,Count
,sizeof(*VFList
));
435 // Iterate over all the package files and write them out.
436 char *Buffer
= new char[Cache
.HeaderP
->MaxVerFileSize
+10];
437 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
439 pkgCache::PkgFileIterator
File(Cache
,(*J
)->File
+ Cache
.PkgFileP
);
440 if (File
.IsOk() == false)
442 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
446 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
447 if (_error
->PendingError() == true)
450 /* Write all of the records from this package file, since we
451 already did locality sorting we can now just seek through the
452 file in read order. We apply 1 more optimization here, since often
453 there will be < 1 byte gaps between records (for the \n) we read that
454 into the next buffer and offset a bit.. */
455 unsigned long Pos
= 0;
458 if ((*J
)->File
+ Cache
.PkgFileP
!= File
)
461 const pkgCache::VerFile
&VF
= **J
;
463 // Read the record and then write it out again.
464 unsigned long Jitter
= VF
.Offset
- Pos
;
467 if (PkgF
.Seek(VF
.Offset
) == false)
472 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
474 Buffer
[VF
.Size
+ Jitter
] = '\n';
477 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
480 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
481 const char *Zero
= 0;
482 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
483 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
485 _error
->Error("Internal Error, Unable to parse a package record");
492 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
496 Pos
= VF
.Offset
+ VF
.Size
;
500 if (_error
->PendingError() == true)
506 return !_error
->PendingError();
509 // Depends - Print out a dependency tree /*{{{*/
510 // ---------------------------------------------------------------------
512 bool Depends(CommandLine
&CmdL
)
514 pkgCache
&Cache
= *GCache
;
515 SPtrArray
<unsigned> Colours
= new unsigned[Cache
.Head().PackageCount
];
516 memset(Colours
,0,sizeof(*Colours
)*Cache
.Head().PackageCount
);
518 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
520 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
521 if (Pkg
.end() == true)
523 _error
->Warning(_("Unable to locate package %s"),*I
);
526 Colours
[Pkg
->ID
] = 1;
529 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
533 DidSomething
= false;
534 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
536 if (Colours
[Pkg
->ID
] != 1)
538 Colours
[Pkg
->ID
] = 2;
541 pkgCache::VerIterator Ver
= Pkg
.VersionList();
542 if (Ver
.end() == true)
544 cout
<< '<' << Pkg
.Name() << '>' << endl
;
548 cout
<< Pkg
.Name() << endl
;
550 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
552 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
558 pkgCache::PkgIterator Trg
= D
.TargetPkg();
559 if (Trg
->VersionList
== 0)
560 cout
<< D
.DepType() << ": <" << Trg
.Name() << ">" << endl
;
562 cout
<< D
.DepType() << ": " << Trg
.Name() << endl
;
565 Colours
[D
.TargetPkg()->ID
]++;
567 // Display all solutions
568 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
569 pkgPrioSortList(Cache
,List
);
570 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
572 pkgCache::VerIterator
V(Cache
,*I
);
573 if (V
!= Cache
.VerP
+ V
.ParentPkg()->VersionList
||
574 V
->ParentPkg
== D
->Package
)
576 cout
<< " " << V
.ParentPkg().Name() << endl
;
579 Colours
[D
.ParentPkg()->ID
]++;
584 while (DidSomething
== true);
589 // Dotty - Generate a graph for Dotty /*{{{*/
590 // ---------------------------------------------------------------------
591 /* Dotty is the graphvis program for generating graphs. It is a fairly
592 simple queuing algorithm that just writes dependencies and nodes.
593 http://www.research.att.com/sw/tools/graphviz/ */
594 bool Dotty(CommandLine
&CmdL
)
596 pkgCache
&Cache
= *GCache
;
597 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
599 /* Normal packages are boxes
600 Pure Provides are triangles
602 Hexagons are missing packages*/
603 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
605 /* Initialize the list of packages to show.
607 2 = To Show no recurse
608 3 = Emitted no recurse
611 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
612 enum TheFlags
{ForceNR
=(1<<0)};
613 unsigned char *Show
= new unsigned char[Cache
.Head().PackageCount
];
614 unsigned char *Flags
= new unsigned char[Cache
.Head().PackageCount
];
615 unsigned char *ShapeMap
= new unsigned char[Cache
.Head().PackageCount
];
617 // Show everything if no arguments given
618 if (CmdL
.FileList
[1] == 0)
619 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
622 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
624 memset(Flags
,0,sizeof(*Flags
)*Cache
.Head().PackageCount
);
627 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
629 if (Pkg
->VersionList
== 0)
632 if (Pkg
->ProvidesList
== 0)
633 ShapeMap
[Pkg
->ID
] = 0;
635 ShapeMap
[Pkg
->ID
] = 1;
640 if (Pkg
->ProvidesList
== 0)
641 ShapeMap
[Pkg
->ID
] = 2;
643 ShapeMap
[Pkg
->ID
] = 3;
647 // Load the list of packages from the command line into the show list
648 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
650 // Process per-package flags
655 if (P
.end()[-1] == '^')
661 if (P
.end()[-1] == ',')
665 // Locate the package
666 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(P
);
667 if (Pkg
.end() == true)
669 _error
->Warning(_("Unable to locate package %s"),*I
);
672 Show
[Pkg
->ID
] = ToShow
;
675 Flags
[Pkg
->ID
] |= ForceNR
;
679 printf("digraph packages {\n");
680 printf("concentrate=true;\n");
681 printf("size=\"30,40\";\n");
687 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
689 // See we need to show this package
690 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
694 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
696 // Pure Provides and missing packages have no deps!
697 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
698 Show
[Pkg
->ID
] = Done
;
700 Show
[Pkg
->ID
] = DoneNR
;
703 Show
[Pkg
->ID
] = Done
;
706 // No deps to map out
707 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
710 pkgCache::VerIterator Ver
= Pkg
.VersionList();
711 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
713 // See if anything can meet this dep
714 // Walk along the actual package providing versions
716 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
717 for (pkgCache::VerIterator I
= DPkg
.VersionList();
718 I
.end() == false && Hit
== false; I
++)
720 if (Cache
.VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
724 // Follow all provides
725 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
726 I
.end() == false && Hit
== false; I
++)
728 if (Cache
.VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
732 // Only graph critical deps
733 if (D
.IsCritical() == true)
735 printf("\"%s\" -> \"%s\"",Pkg
.Name(),D
.TargetPkg().Name());
737 // Colour the node for recursion
738 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
740 /* If a conflicts does not meet anything in the database
741 then show the relation but do not recurse */
743 (D
->Type
== pkgCache::Dep::Conflicts
||
744 D
->Type
== pkgCache::Dep::Obsoletes
))
746 if (Show
[D
.TargetPkg()->ID
] == None
&&
747 Show
[D
.TargetPkg()->ID
] != ToShow
)
748 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
752 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
753 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
755 Show
[D
.TargetPkg()->ID
] = ToShow
;
762 case pkgCache::Dep::Conflicts
:
763 case pkgCache::Dep::Obsoletes
:
764 printf("[color=springgreen];\n");
767 case pkgCache::Dep::PreDepends
:
768 printf("[color=blue];\n");
780 /* Draw the box colours after the fact since we can not tell what colour
781 they should be until everything is finished drawing */
782 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
784 if (Show
[Pkg
->ID
] < DoneNR
)
787 // Orange box for early recursion stoppage
788 if (Show
[Pkg
->ID
] == DoneNR
)
789 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.Name(),
790 Shapes
[ShapeMap
[Pkg
->ID
]]);
792 printf("\"%s\" [shape=%s];\n",Pkg
.Name(),
793 Shapes
[ShapeMap
[Pkg
->ID
]]);
800 // DoAdd - Perform an adding operation /*{{{*/
801 // ---------------------------------------------------------------------
803 bool DoAdd(CommandLine
&CmdL
)
805 return _error
->Error("Unimplemented");
807 // Make sure there is at least one argument
808 if (CmdL
.FileSize() <= 1)
809 return _error
->Error("You must give at least one file name");
812 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
813 if (_error
->PendingError() == true)
816 DynamicMMap
Map(CacheF
,MMap::Public
);
817 if (_error
->PendingError() == true)
820 OpTextProgress
Progress(*_config
);
821 pkgCacheGenerator
Gen(Map
,Progress
);
822 if (_error
->PendingError() == true)
825 unsigned long Length
= CmdL
.FileSize() - 1;
826 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
828 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
829 Progress
.SubProgress(Length
);
832 FileFd
TagF(*I
,FileFd::ReadOnly
);
833 debListParser
Parser(TagF
);
834 if (_error
->PendingError() == true)
835 return _error
->Error("Problem opening %s",*I
);
837 if (Gen
.SelectFile(*I
,"") == false)
838 return _error
->Error("Problem with SelectFile");
840 if (Gen
.MergeList(Parser
) == false)
841 return _error
->Error("Problem with MergeList");
845 GCache
= &Gen
.GetCache();
852 // DisplayRecord - Displays the complete record for the package /*{{{*/
853 // ---------------------------------------------------------------------
854 /* This displays the package record from the proper package index file.
855 It is not used by DumpAvail for performance reasons. */
856 bool DisplayRecord(pkgCache::VerIterator V
)
858 // Find an appropriate file
859 pkgCache::VerFileIterator Vf
= V
.FileList();
860 for (; Vf
.end() == false; Vf
++)
861 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
863 if (Vf
.end() == true)
866 // Check and load the package list file
867 pkgCache::PkgFileIterator I
= Vf
.File();
868 if (I
.IsOk() == false)
869 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
871 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
872 if (_error
->PendingError() == true)
875 // Read the record and then write it out again.
876 unsigned char *Buffer
= new unsigned char[GCache
->HeaderP
->MaxVerFileSize
+1];
877 Buffer
[V
.FileList()->Size
] = '\n';
878 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
879 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
880 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
+1) != V
.FileList()->Size
+1)
891 // Search - Perform a search /*{{{*/
892 // ---------------------------------------------------------------------
893 /* This searches the package names and pacakge descriptions for a pattern */
896 pkgCache::VerFile
*Vf
;
900 bool Search(CommandLine
&CmdL
)
902 pkgCache
&Cache
= *GCache
;
903 bool ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
904 bool NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
905 unsigned NumPatterns
= CmdL
.FileSize() -1;
907 pkgDepCache::Policy Plcy
;
909 // Make sure there is at least one argument
911 return _error
->Error(_("You must give exactly one pattern"));
913 // Compile the regex pattern
914 regex_t
*Patterns
= new regex_t
[NumPatterns
];
915 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
916 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
918 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
922 regfree(&Patterns
[I
]);
923 return _error
->Error("Regex compilation error");
927 // Create the text record parser
928 pkgRecords
Recs(Cache
);
929 if (_error
->PendingError() == true)
931 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
932 regfree(&Patterns
[I
]);
936 ExVerFile
*VFList
= new ExVerFile
[Cache
.HeaderP
->PackageCount
+1];
937 memset(VFList
,0,sizeof(*VFList
)*Cache
.HeaderP
->PackageCount
+1);
939 // Map versions that we want to write out onto the VerList array.
940 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
942 VFList
[P
->ID
].NameMatch
= NumPatterns
!= 0;
943 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
945 if (regexec(&Patterns
[I
],P
.Name(),0,0,0) == 0)
946 VFList
[P
->ID
].NameMatch
&= true;
948 VFList
[P
->ID
].NameMatch
= false;
951 // Doing names only, drop any that dont match..
952 if (NamesOnly
== true && VFList
[P
->ID
].NameMatch
== false)
955 // Find the proper version to use.
956 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
957 if (V
.end() == false)
958 VFList
[P
->ID
].Vf
= V
.FileList();
961 // Include all the packages that provide matching names too
962 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
964 if (VFList
[P
->ID
].NameMatch
== false)
967 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
969 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Prv
.OwnerPkg());
970 if (V
.end() == false)
972 VFList
[Prv
.OwnerPkg()->ID
].Vf
= V
.FileList();
973 VFList
[Prv
.OwnerPkg()->ID
].NameMatch
= true;
978 LocalitySort(&VFList
->Vf
,Cache
.HeaderP
->PackageCount
,sizeof(*VFList
));
980 // Iterate over all the version records and check them
981 for (ExVerFile
*J
= VFList
; J
->Vf
!= 0; J
++)
983 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::VerFileIterator(Cache
,J
->Vf
));
986 if (J
->NameMatch
== false)
988 string LongDesc
= P
.LongDesc();
989 Match
= NumPatterns
!= 0;
990 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
992 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1001 if (ShowFull
== true)
1005 P
.GetRec(Start
,End
);
1006 fwrite(Start
,End
-Start
,1,stdout
);
1010 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1015 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1016 regfree(&Patterns
[I
]);
1018 return _error
->Error("Write to stdout failed");
1022 // ShowPackage - Dump the package record to the screen /*{{{*/
1023 // ---------------------------------------------------------------------
1025 bool ShowPackage(CommandLine
&CmdL
)
1027 pkgCache
&Cache
= *GCache
;
1028 pkgDepCache::Policy Plcy
;
1030 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1032 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1033 if (Pkg
.end() == true)
1035 _error
->Warning(_("Unable to locate package %s"),*I
);
1039 // Find the proper version to use.
1040 if (_config
->FindB("APT::Cache::AllVersions","true") == true)
1042 pkgCache::VerIterator V
;
1043 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1045 if (DisplayRecord(V
) == false)
1051 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1052 if (V
.end() == true || V
.FileList().end() == true)
1054 if (DisplayRecord(V
) == false)
1061 // ShowPkgNames - Show package names /*{{{*/
1062 // ---------------------------------------------------------------------
1063 /* This does a prefix match on the first argument */
1064 bool ShowPkgNames(CommandLine
&CmdL
)
1066 pkgCache
&Cache
= *GCache
;
1067 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1068 bool All
= _config
->FindB("APT::Cache::AllNames","false");
1070 if (CmdL
.FileList
[1] != 0)
1072 for (;I
.end() != true; I
++)
1074 if (All
== false && I
->VersionList
== 0)
1077 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1078 cout
<< I
.Name() << endl
;
1085 for (;I
.end() != true; I
++)
1087 if (All
== false && I
->VersionList
== 0)
1089 cout
<< I
.Name() << endl
;
1095 // ShowSrcPackage - Show source package records /*{{{*/
1096 // ---------------------------------------------------------------------
1098 bool ShowSrcPackage(CommandLine
&CmdL
)
1101 List
.ReadMainList();
1103 // Create the text record parsers
1104 pkgSrcRecords
SrcRecs(List
);
1105 if (_error
->PendingError() == true)
1108 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1112 pkgSrcRecords::Parser
*Parse
;
1113 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0)
1114 cout
<< Parse
->AsStr() << endl
;;
1119 // Policy - Show the results of the preferences file /*{{{*/
1120 // ---------------------------------------------------------------------
1122 bool Policy(CommandLine
&CmdL
)
1125 return _error
->Error("Generate must be enabled for this function");
1127 pkgCache
&Cache
= *GCache
;
1128 pkgPolicy
Plcy(&Cache
);
1129 if (ReadPinFile(Plcy
) == false)
1132 // Print out all of the package files
1133 if (CmdL
.FileList
[1] == 0)
1135 cout
<< _("Package Files:") << endl
;
1136 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
1138 // Locate the associated index files so we can derive a description
1140 if (SrcList
->FindIndex(F
,Indx
) == false &&
1141 _system
->FindIndex(F
,Indx
) == false)
1142 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1143 printf(_("%4i %s\n"),
1144 Plcy
.GetPriority(F
),Indx
->Describe(true).c_str());
1146 // Print the reference information for the package
1147 string Str
= F
.RelStr();
1148 if (Str
.empty() == false)
1149 printf(" release %s\n",F
.RelStr().c_str());
1150 if (F
.Site() != 0 && F
.Site()[0] != 0)
1151 printf(" origin %s\n",F
.Site());
1154 // Show any packages have explicit pins
1155 cout
<< _("Pinned Packages:") << endl
;
1156 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1157 for (;I
.end() != true; I
++)
1159 if (Plcy
.GetPriority(I
) == 0)
1162 // Print the package name and the version we are forcing to
1163 cout
<< " " << I
.Name() << " -> ";
1165 pkgCache::VerIterator V
= Plcy
.GetMatch(I
);
1166 if (V
.end() == true)
1167 cout
<< _("(not found)") << endl
;
1169 cout
<< V
.VerStr() << endl
;
1175 // Print out detailed information for each package
1176 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1178 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1179 if (Pkg
.end() == true)
1181 _error
->Warning(_("Unable to locate package %s"),*I
);
1185 cout
<< Pkg
.Name() << ":" << endl
;
1187 // Installed version
1188 cout
<< _(" Installed: ");
1189 if (Pkg
->CurrentVer
== 0)
1190 cout
<< _("(none)") << endl
;
1192 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1194 // Candidate Version
1195 cout
<< _(" Candidate: ");
1196 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1197 if (V
.end() == true)
1198 cout
<< _("(none)") << endl
;
1200 cout
<< V
.VerStr() << endl
;
1203 if (Plcy
.GetPriority(Pkg
) != 0)
1205 cout
<< _(" Package Pin: ");
1206 V
= Plcy
.GetMatch(Pkg
);
1207 if (V
.end() == true)
1208 cout
<< _("(not found)") << endl
;
1210 cout
<< V
.VerStr() << endl
;
1213 // Show the priority tables
1214 cout
<< _(" Version Table:") << endl
;
1215 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1217 if (Pkg
.CurrentVer() == V
)
1218 cout
<< " *** " << V
.VerStr();
1220 cout
<< " " << V
.VerStr();
1221 cout
<< " " << Plcy
.GetPriority(Pkg
) << endl
;
1222 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1224 // Locate the associated index files so we can derive a description
1226 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1227 _system
->FindIndex(VF
.File(),Indx
) == false)
1228 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1229 printf(_(" %4i %s\n"),Plcy
.GetPriority(VF
.File()),
1230 Indx
->Describe(true).c_str());
1238 // GenCaches - Call the main cache generator /*{{{*/
1239 // ---------------------------------------------------------------------
1241 bool GenCaches(CommandLine
&Cmd
)
1243 OpTextProgress
Progress(*_config
);
1246 if (List
.ReadMainList() == false)
1248 return pkgMakeStatusCache(List
,Progress
);
1251 // ShowHelp - Show a help screen /*{{{*/
1252 // ---------------------------------------------------------------------
1254 bool ShowHelp(CommandLine
&Cmd
)
1256 ioprintf(cout
,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1257 COMMON_OS
,COMMON_CPU
,__DATE__
,__TIME__
);
1260 _("Usage: apt-cache [options] command\n"
1261 " apt-cache [options] add file1 [file1 ...]\n"
1262 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1263 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1265 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1266 "cache files, and query information from them\n"
1269 " add - Add an package file to the source cache\n"
1270 " gencaches - Build both the package and source cache\n"
1271 " showpkg - Show some general information for a single package\n"
1272 " showsrc - Show source records\n"
1273 " stats - Show some basic statistics\n"
1274 " dump - Show the entire file in a terse form\n"
1275 " dumpavail - Print an available file to stdout\n"
1276 " unmet - Show unmet dependencies\n"
1277 " search - Search the package list for a regex pattern\n"
1278 " show - Show a readable record for the package\n"
1279 " depends - Show raw dependency information for a package\n"
1280 " pkgnames - List the names of all packages\n"
1281 " dotty - Generate package graphs for GraphVis\n"
1282 " policy - Show policy settings\n"
1285 " -h This help text.\n"
1286 " -p=? The package cache.\n"
1287 " -s=? The source cache.\n"
1288 " -q Disable progress indicator.\n"
1289 " -i Show only important deps for the unmet command.\n"
1290 " -c=? Read this configuration file\n"
1291 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1292 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1296 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1297 // ---------------------------------------------------------------------
1299 void CacheInitialize()
1301 _config
->Set("quiet",0);
1302 _config
->Set("help",false);
1306 int main(int argc
,const char *argv
[])
1308 CommandLine::Args Args
[] = {
1309 {'h',"help","help",0},
1310 {'v',"version","version",0},
1311 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1312 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1313 {'q',"quiet","quiet",CommandLine::IntLevel
},
1314 {'i',"important","APT::Cache::Important",0},
1315 {'f',"full","APT::Cache::ShowFull",0},
1316 {'g',"generate","APT::Cache::Generate",0},
1317 {'a',"all-versions","APT::Cache::AllVersions",0},
1318 {0,"names-only","APT::Cache::NamesOnly",0},
1319 {0,"all-names","APT::Cache::AllNames",0},
1320 {0,"recurse","APT::Cache::RecurseDepends",0},
1321 {'c',"config-file",0,CommandLine::ConfigFile
},
1322 {'o',"option",0,CommandLine::ArbItem
},
1324 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1326 {"gencaches",&GenCaches
},
1327 {"showsrc",&ShowSrcPackage
},
1329 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1332 {"dumpavail",&DumpAvail
},
1335 {"depends",&Depends
},
1337 {"show",&ShowPackage
},
1338 {"pkgnames",&ShowPkgNames
},
1344 // Set up gettext support
1345 setlocale(LC_ALL
,"");
1346 textdomain(PACKAGE
);
1348 // Parse the command line and initialize the package library
1349 CommandLine
CmdL(Args
,_config
);
1350 if (pkgInitConfig(*_config
) == false ||
1351 CmdL
.Parse(argc
,argv
) == false ||
1352 pkgInitSystem(*_config
,_system
) == false)
1354 _error
->DumpErrors();
1358 // See if the help should be shown
1359 if (_config
->FindB("help") == true ||
1360 CmdL
.FileSize() == 0)
1366 // Deal with stdout not being a tty
1367 if (ttyname(STDOUT_FILENO
) == 0 && _config
->FindI("quiet",0) < 1)
1368 _config
->Set("quiet","1");
1370 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1373 if (_config
->FindB("APT::Cache::Generate",true) == false)
1375 Map
= new MMap(*new FileFd(_config
->FindFile("Dir::Cache::pkgcache"),
1376 FileFd::ReadOnly
),MMap::Public
|MMap::ReadOnly
);
1380 // Open the cache file
1381 SrcList
= new pkgSourceList
;
1382 SrcList
->ReadMainList();
1384 // Generate it and map it
1386 pkgMakeStatusCache(*SrcList
,Prog
,&Map
,true);
1389 if (_error
->PendingError() == false)
1391 pkgCache
Cache(Map
);
1393 if (_error
->PendingError() == false)
1394 CmdL
.DispatchArg(CmdsB
);
1399 // Print any errors or warnings found during parsing
1400 if (_error
->empty() == false)
1402 bool Errors
= _error
->PendingError();
1403 _error
->DumpErrors();
1404 return Errors
== true?100:0;