]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.45 2001/02/22 06:26:27 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 // LocalitySort - Sort a version list by package file locality /*{{{*/
44 // ---------------------------------------------------------------------
46 int LocalityCompare(const void *a
, const void *b
)
48 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
49 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
58 if (A
->File
== B
->File
)
59 return A
->Offset
- B
->Offset
;
60 return A
->File
- B
->File
;
63 void LocalitySort(pkgCache::VerFile
**begin
,
64 unsigned long Count
,size_t Size
)
66 qsort(begin
,Count
,Size
,LocalityCompare
);
69 // UnMet - Show unmet dependencies /*{{{*/
70 // ---------------------------------------------------------------------
72 bool UnMet(CommandLine
&CmdL
)
74 pkgCache
&Cache
= *GCache
;
75 bool Important
= _config
->FindB("APT::Cache::Important",false);
77 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
79 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
82 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
85 pkgCache::DepIterator Start
;
86 pkgCache::DepIterator End
;
89 // Skip conflicts and replaces
90 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
91 End
->Type
!= pkgCache::Dep::Depends
&&
92 End
->Type
!= pkgCache::Dep::Suggests
&&
93 End
->Type
!= pkgCache::Dep::Recommends
)
96 // Important deps only
97 if (Important
== true)
98 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
99 End
->Type
!= pkgCache::Dep::Depends
)
102 // Verify the or group
104 pkgCache::DepIterator RealStart
= Start
;
107 // See if this dep is Ok
108 pkgCache::Version
**VList
= Start
.AllTargets();
129 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
130 P
.Name(),V
.VerStr());
133 // Print out the dep type
134 cout
<< " " << End
.DepType() << ": ";
140 cout
<< Start
.TargetPkg().Name();
141 if (Start
.TargetVer() != 0)
142 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
158 // DumpPackage - Show a dump of a package record /*{{{*/
159 // ---------------------------------------------------------------------
161 bool DumpPackage(CommandLine
&CmdL
)
163 pkgCache
&Cache
= *GCache
;
164 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
166 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
167 if (Pkg
.end() == true)
169 _error
->Warning(_("Unable to locate package %s"),*I
);
173 cout
<< "Package: " << Pkg
.Name() << endl
;
174 cout
<< "Versions: " << endl
;
175 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
177 cout
<< Cur
.VerStr();
178 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
179 cout
<< "(" << Vf
.File().FileName() << ")";
185 cout
<< "Reverse Depends: " << endl
;
186 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
188 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name();
190 cout
<< ' ' << D
.TargetVer() << endl
;
195 cout
<< "Dependencies: " << endl
;
196 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
198 cout
<< Cur
.VerStr() << " - ";
199 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
200 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
204 cout
<< "Provides: " << endl
;
205 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
207 cout
<< Cur
.VerStr() << " - ";
208 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
209 cout
<< Prv
.ParentPkg().Name() << " ";
212 cout
<< "Reverse Provides: " << endl
;
213 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
214 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr() << endl
;
220 // Stats - Dump some nice statistics /*{{{*/
221 // ---------------------------------------------------------------------
223 bool Stats(CommandLine
&Cmd
)
225 pkgCache
&Cache
= *GCache
;
226 cout
<< _("Total Package Names : ") << Cache
.Head().PackageCount
<< " (" <<
227 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
234 pkgCache::PkgIterator I
= Cache
.PkgBegin();
235 for (;I
.end() != true; I
++)
237 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
243 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
249 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
252 if (I
.ProvidesList()->NextProvides
== 0)
260 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
266 cout
<< _(" Normal Packages: ") << Normal
<< endl
;
267 cout
<< _(" Pure Virtual Packages: ") << Virtual
<< endl
;
268 cout
<< _(" Single Virtual Packages: ") << DVirt
<< endl
;
269 cout
<< _(" Mixed Virtual Packages: ") << NVirt
<< endl
;
270 cout
<< _(" Missing: ") << Missing
<< endl
;
272 cout
<< _("Total Distinct Versions: ") << Cache
.Head().VersionCount
<< " (" <<
273 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
274 cout
<< _("Total Dependencies: ") << Cache
.Head().DependsCount
<< " (" <<
275 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
277 cout
<< _("Total Ver/File relations: ") << Cache
.Head().VerFileCount
<< " (" <<
278 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
279 cout
<< _("Total Provides Mappings: ") << Cache
.Head().ProvidesCount
<< " (" <<
280 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
283 unsigned long Size
= 0;
284 unsigned long Count
= 0;
285 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
286 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
289 Size
+= strlen(Cache
.StrP
+ I
->String
) + 1;
291 cout
<< _("Total Globbed Strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
293 unsigned long DepVerSize
= 0;
294 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
296 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
298 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
301 DepVerSize
+= strlen(D
.TargetVer()) + 1;
305 cout
<< _("Total Dependency Version space: ") << SizeToStr(DepVerSize
) << endl
;
307 unsigned long Slack
= 0;
308 for (int I
= 0; I
!= 7; I
++)
309 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
310 cout
<< _("Total Slack space: ") << SizeToStr(Slack
) << endl
;
312 unsigned long Total
= 0;
313 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
314 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
315 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
316 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
317 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
318 cout
<< _("Total Space Accounted for: ") << SizeToStr(Total
) << endl
;
323 // Dump - show everything /*{{{*/
324 // ---------------------------------------------------------------------
325 /* This is worthless except fer debugging things */
326 bool Dump(CommandLine
&Cmd
)
328 pkgCache
&Cache
= *GCache
;
329 cout
<< "Using Versioning System: " << Cache
.VS
->Label
<< endl
;
331 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
333 cout
<< "Package: " << P
.Name() << endl
;
334 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
336 cout
<< " Version: " << V
.VerStr() << endl
;
337 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
338 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
339 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
343 for (pkgCache::PkgFileIterator F
= Cache
.FileBegin(); F
.end() == false; F
++)
345 cout
<< "File: " << F
.FileName() << endl
;
346 cout
<< " Type: " << F
.IndexType() << endl
;
347 cout
<< " Size: " << F
->Size
<< endl
;
348 cout
<< " ID: " << F
->ID
<< endl
;
349 cout
<< " Flags: " << F
->Flags
<< endl
;
350 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
351 cout
<< " Archive: " << F
.Archive() << endl
;
352 cout
<< " Component: " << F
.Component() << endl
;
353 cout
<< " Version: " << F
.Version() << endl
;
354 cout
<< " Origin: " << F
.Origin() << endl
;
355 cout
<< " Site: " << F
.Site() << endl
;
356 cout
<< " Label: " << F
.Label() << endl
;
357 cout
<< " Architecture: " << F
.Architecture() << endl
;
363 // DumpAvail - Print out the available list /*{{{*/
364 // ---------------------------------------------------------------------
365 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
366 make this run really fast, perhaps I went a little overboard.. */
367 bool DumpAvail(CommandLine
&Cmd
)
369 pkgCache
&Cache
= *GCache
;
371 pkgPolicy
Plcy(&Cache
);
372 if (ReadPinFile(Plcy
) == false)
375 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Cache
.HeaderP
->PackageCount
];
376 memset(VFList
,0,sizeof(*VFList
)*Cache
.HeaderP
->PackageCount
);
378 // Map versions that we want to write out onto the VerList array.
379 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
381 if (P
->VersionList
== 0)
384 /* Find the proper version to use. If the policy says there are no
385 possible selections we return the installed version, if available..
386 This prevents dselect from making it obsolete. */
387 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
390 if (P
->CurrentVer
== 0)
395 pkgCache::VerFileIterator VF
= V
.FileList();
396 for (; VF
.end() == false ; VF
++)
397 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
400 /* Okay, here we have a bit of a problem.. The policy has selected the
401 currently installed package - however it only exists in the
402 status file.. We need to write out something or dselect will mark
403 the package as obsolete! Thus we emit the status file entry, but
404 below we remove the status line to make it valid for the
405 available file. However! We only do this if their do exist *any*
406 non-source versions of the package - that way the dselect obsolete
407 handling works OK. */
408 if (VF
.end() == true)
410 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
412 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
414 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
421 if (VF
.end() == false)
429 LocalitySort(VFList
,Cache
.HeaderP
->PackageCount
,sizeof(*VFList
));
431 // Iterate over all the package files and write them out.
432 char *Buffer
= new char[Cache
.HeaderP
->MaxVerFileSize
+10];
433 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
435 pkgCache::PkgFileIterator
File(Cache
,(*J
)->File
+ Cache
.PkgFileP
);
436 if (File
.IsOk() == false)
438 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
442 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
443 if (_error
->PendingError() == true)
446 /* Write all of the records from this package file, since we
447 already did locality sorting we can now just seek through the
448 file in read order. We apply 1 more optimization here, since often
449 there will be < 1 byte gaps between records (for the \n) we read that
450 into the next buffer and offset a bit.. */
451 unsigned long Pos
= 0;
454 if ((*J
)->File
+ Cache
.PkgFileP
!= File
)
457 const pkgCache::VerFile
&VF
= **J
;
459 // Read the record and then write it out again.
460 unsigned long Jitter
= VF
.Offset
- Pos
;
463 if (PkgF
.Seek(VF
.Offset
) == false)
468 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
470 Buffer
[VF
.Size
+ Jitter
] = '\n';
473 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
476 TFRewriteData RW
[] = {{"Status",0},{}};
477 const char *Zero
= 0;
478 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
479 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
481 _error
->Error("Internal Error, Unable to parse a package record");
488 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
492 Pos
= VF
.Offset
+ VF
.Size
;
496 if (_error
->PendingError() == true)
502 return !_error
->PendingError();
505 // Depends - Print out a dependency tree /*{{{*/
506 // ---------------------------------------------------------------------
508 bool Depends(CommandLine
&CmdL
)
510 pkgCache
&Cache
= *GCache
;
511 SPtrArray
<unsigned> Colours
= new unsigned[Cache
.Head().PackageCount
];
512 memset(Colours
,0,sizeof(*Colours
)*Cache
.Head().PackageCount
);
514 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
516 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
517 if (Pkg
.end() == true)
519 _error
->Warning(_("Unable to locate package %s"),*I
);
522 Colours
[Pkg
->ID
] = 1;
525 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
529 DidSomething
= false;
530 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
532 if (Colours
[Pkg
->ID
] != 1)
534 Colours
[Pkg
->ID
] = 2;
537 pkgCache::VerIterator Ver
= Pkg
.VersionList();
538 if (Ver
.end() == true)
540 cout
<< '<' << Pkg
.Name() << '>' << endl
;
544 cout
<< Pkg
.Name() << endl
;
546 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
548 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
554 pkgCache::PkgIterator Trg
= D
.TargetPkg();
555 if (Trg
->VersionList
== 0)
556 cout
<< D
.DepType() << ": <" << Trg
.Name() << ">" << endl
;
558 cout
<< D
.DepType() << ": " << Trg
.Name() << endl
;
561 Colours
[D
.TargetPkg()->ID
]++;
563 // Display all solutions
564 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
565 pkgPrioSortList(Cache
,List
);
566 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
568 pkgCache::VerIterator
V(Cache
,*I
);
569 if (V
!= Cache
.VerP
+ V
.ParentPkg()->VersionList
||
570 V
->ParentPkg
== D
->Package
)
572 cout
<< " " << V
.ParentPkg().Name() << endl
;
575 Colours
[D
.ParentPkg()->ID
]++;
580 while (DidSomething
== true);
585 // Dotty - Generate a graph for Dotty /*{{{*/
586 // ---------------------------------------------------------------------
587 /* Dotty is the graphvis program for generating graphs. It is a fairly
588 simple queuing algorithm that just writes dependencies and nodes.
589 http://www.research.att.com/sw/tools/graphviz/ */
590 bool Dotty(CommandLine
&CmdL
)
592 pkgCache
&Cache
= *GCache
;
593 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
595 /* Normal packages are boxes
596 Pure Provides are triangles
598 Hexagons are missing packages*/
599 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
601 /* Initialize the list of packages to show.
603 2 = To Show no recurse
604 3 = Emitted no recurse
607 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
608 enum TheFlags
{ForceNR
=(1<<0)};
609 unsigned char *Show
= new unsigned char[Cache
.Head().PackageCount
];
610 unsigned char *Flags
= new unsigned char[Cache
.Head().PackageCount
];
611 unsigned char *ShapeMap
= new unsigned char[Cache
.Head().PackageCount
];
613 // Show everything if no arguments given
614 if (CmdL
.FileList
[1] == 0)
615 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
618 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
620 memset(Flags
,0,sizeof(*Flags
)*Cache
.Head().PackageCount
);
623 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
625 if (Pkg
->VersionList
== 0)
628 if (Pkg
->ProvidesList
== 0)
629 ShapeMap
[Pkg
->ID
] = 0;
631 ShapeMap
[Pkg
->ID
] = 1;
636 if (Pkg
->ProvidesList
== 0)
637 ShapeMap
[Pkg
->ID
] = 2;
639 ShapeMap
[Pkg
->ID
] = 3;
643 // Load the list of packages from the command line into the show list
644 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
646 // Process per-package flags
651 if (P
.end()[-1] == '^')
657 if (P
.end()[-1] == ',')
661 // Locate the package
662 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(P
);
663 if (Pkg
.end() == true)
665 _error
->Warning(_("Unable to locate package %s"),*I
);
668 Show
[Pkg
->ID
] = ToShow
;
671 Flags
[Pkg
->ID
] |= ForceNR
;
675 printf("digraph packages {\n");
676 printf("concentrate=true;\n");
677 printf("size=\"30,40\";\n");
683 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
685 // See we need to show this package
686 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
690 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
692 // Pure Provides and missing packages have no deps!
693 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
694 Show
[Pkg
->ID
] = Done
;
696 Show
[Pkg
->ID
] = DoneNR
;
699 Show
[Pkg
->ID
] = Done
;
702 // No deps to map out
703 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
706 pkgCache::VerIterator Ver
= Pkg
.VersionList();
707 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
709 // See if anything can meet this dep
710 // Walk along the actual package providing versions
712 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
713 for (pkgCache::VerIterator I
= DPkg
.VersionList();
714 I
.end() == false && Hit
== false; I
++)
716 if (Cache
.VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
720 // Follow all provides
721 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
722 I
.end() == false && Hit
== false; I
++)
724 if (Cache
.VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
728 // Only graph critical deps
729 if (D
.IsCritical() == true)
731 printf("\"%s\" -> \"%s\"",Pkg
.Name(),D
.TargetPkg().Name());
733 // Colour the node for recursion
734 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
736 /* If a conflicts does not meet anything in the database
737 then show the relation but do not recurse */
739 (D
->Type
== pkgCache::Dep::Conflicts
||
740 D
->Type
== pkgCache::Dep::Obsoletes
))
742 if (Show
[D
.TargetPkg()->ID
] == None
&&
743 Show
[D
.TargetPkg()->ID
] != ToShow
)
744 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
748 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
749 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
751 Show
[D
.TargetPkg()->ID
] = ToShow
;
758 case pkgCache::Dep::Conflicts
:
759 case pkgCache::Dep::Obsoletes
:
760 printf("[color=springgreen];\n");
763 case pkgCache::Dep::PreDepends
:
764 printf("[color=blue];\n");
776 /* Draw the box colours after the fact since we can not tell what colour
777 they should be until everything is finished drawing */
778 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
780 if (Show
[Pkg
->ID
] < DoneNR
)
783 // Orange box for early recursion stoppage
784 if (Show
[Pkg
->ID
] == DoneNR
)
785 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.Name(),
786 Shapes
[ShapeMap
[Pkg
->ID
]]);
788 printf("\"%s\" [shape=%s];\n",Pkg
.Name(),
789 Shapes
[ShapeMap
[Pkg
->ID
]]);
796 // DoAdd - Perform an adding operation /*{{{*/
797 // ---------------------------------------------------------------------
799 bool DoAdd(CommandLine
&CmdL
)
801 return _error
->Error("Unimplemented");
803 // Make sure there is at least one argument
804 if (CmdL
.FileSize() <= 1)
805 return _error
->Error("You must give at least one file name");
808 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
809 if (_error
->PendingError() == true)
812 DynamicMMap
Map(CacheF
,MMap::Public
);
813 if (_error
->PendingError() == true)
816 OpTextProgress
Progress(*_config
);
817 pkgCacheGenerator
Gen(Map
,Progress
);
818 if (_error
->PendingError() == true)
821 unsigned long Length
= CmdL
.FileSize() - 1;
822 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
824 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
825 Progress
.SubProgress(Length
);
828 FileFd
TagF(*I
,FileFd::ReadOnly
);
829 debListParser
Parser(TagF
);
830 if (_error
->PendingError() == true)
831 return _error
->Error("Problem opening %s",*I
);
833 if (Gen
.SelectFile(*I
,"") == false)
834 return _error
->Error("Problem with SelectFile");
836 if (Gen
.MergeList(Parser
) == false)
837 return _error
->Error("Problem with MergeList");
841 GCache
= &Gen
.GetCache();
848 // DisplayRecord - Displays the complete record for the package /*{{{*/
849 // ---------------------------------------------------------------------
850 /* This displays the package record from the proper package index file.
851 It is not used by DumpAvail for performance reasons. */
852 bool DisplayRecord(pkgCache::VerIterator V
)
854 // Find an appropriate file
855 pkgCache::VerFileIterator Vf
= V
.FileList();
856 for (; Vf
.end() == false; Vf
++)
857 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
859 if (Vf
.end() == true)
862 // Check and load the package list file
863 pkgCache::PkgFileIterator I
= Vf
.File();
864 if (I
.IsOk() == false)
865 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
867 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
868 if (_error
->PendingError() == true)
871 // Read the record and then write it out again.
872 unsigned char *Buffer
= new unsigned char[GCache
->HeaderP
->MaxVerFileSize
+1];
873 Buffer
[V
.FileList()->Size
] = '\n';
874 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
875 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
876 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
+1) != V
.FileList()->Size
+1)
887 // Search - Perform a search /*{{{*/
888 // ---------------------------------------------------------------------
889 /* This searches the package names and pacakge descriptions for a pattern */
892 pkgCache::VerFile
*Vf
;
896 bool Search(CommandLine
&CmdL
)
898 pkgCache
&Cache
= *GCache
;
899 bool ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
900 bool NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
901 unsigned NumPatterns
= CmdL
.FileSize() -1;
903 pkgDepCache::Policy Plcy
;
905 // Make sure there is at least one argument
907 return _error
->Error(_("You must give exactly one pattern"));
909 // Compile the regex pattern
910 regex_t
*Patterns
= new regex_t
[NumPatterns
];
911 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
912 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
914 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
918 regfree(&Patterns
[I
]);
919 return _error
->Error("Regex compilation error");
923 // Create the text record parser
924 pkgRecords
Recs(Cache
);
925 if (_error
->PendingError() == true)
927 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
928 regfree(&Patterns
[I
]);
932 ExVerFile
*VFList
= new ExVerFile
[Cache
.HeaderP
->PackageCount
+1];
933 memset(VFList
,0,sizeof(*VFList
)*Cache
.HeaderP
->PackageCount
+1);
935 // Map versions that we want to write out onto the VerList array.
936 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
938 VFList
[P
->ID
].NameMatch
= NumPatterns
!= 0;
939 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
941 if (regexec(&Patterns
[I
],P
.Name(),0,0,0) == 0)
942 VFList
[P
->ID
].NameMatch
&= true;
944 VFList
[P
->ID
].NameMatch
= false;
947 // Doing names only, drop any that dont match..
948 if (NamesOnly
== true && VFList
[P
->ID
].NameMatch
== false)
951 // Find the proper version to use.
952 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(P
);
955 VFList
[P
->ID
].Vf
= V
.FileList();
958 LocalitySort(&VFList
->Vf
,Cache
.HeaderP
->PackageCount
,sizeof(*VFList
));
960 // Iterate over all the version records and check them
961 for (ExVerFile
*J
= VFList
; J
->Vf
!= 0; J
++)
963 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::VerFileIterator(Cache
,J
->Vf
));
966 if (J
->NameMatch
== false)
968 string LongDesc
= P
.LongDesc();
969 Match
= NumPatterns
!= 0;
970 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
972 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
981 if (ShowFull
== true)
986 fwrite(Start
,End
-Start
,1,stdout
);
990 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
995 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
996 regfree(&Patterns
[I
]);
998 return _error
->Error("Write to stdout failed");
1002 // ShowPackage - Dump the package record to the screen /*{{{*/
1003 // ---------------------------------------------------------------------
1005 bool ShowPackage(CommandLine
&CmdL
)
1007 pkgCache
&Cache
= *GCache
;
1008 pkgDepCache::Policy Plcy
;
1010 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1012 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
1013 if (Pkg
.end() == true)
1015 _error
->Warning(_("Unable to locate package %s"),*I
);
1019 // Find the proper version to use.
1020 if (_config
->FindB("APT::Cache::AllVersions","true") == true)
1022 pkgCache::VerIterator V
;
1023 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1025 if (DisplayRecord(V
) == false)
1031 pkgCache::VerIterator V
= Plcy
.GetCandidateVer(Pkg
);
1032 if (V
.end() == true || V
.FileList().end() == true)
1034 if (DisplayRecord(V
) == false)
1041 // ShowPkgNames - Show package names /*{{{*/
1042 // ---------------------------------------------------------------------
1043 /* This does a prefix match on the first argument */
1044 bool ShowPkgNames(CommandLine
&CmdL
)
1046 pkgCache
&Cache
= *GCache
;
1047 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1048 bool All
= _config
->FindB("APT::Cache::AllNames","false");
1050 if (CmdL
.FileList
[1] != 0)
1052 for (;I
.end() != true; I
++)
1054 if (All
== false && I
->VersionList
== 0)
1057 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1058 cout
<< I
.Name() << endl
;
1065 for (;I
.end() != true; I
++)
1067 if (All
== false && I
->VersionList
== 0)
1069 cout
<< I
.Name() << endl
;
1075 // ShowSrcPackage - Show source package records /*{{{*/
1076 // ---------------------------------------------------------------------
1078 bool ShowSrcPackage(CommandLine
&CmdL
)
1081 List
.ReadMainList();
1083 // Create the text record parsers
1084 pkgSrcRecords
SrcRecs(List
);
1085 if (_error
->PendingError() == true)
1088 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1092 pkgSrcRecords::Parser
*Parse
;
1093 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0)
1094 cout
<< Parse
->AsStr() << endl
;;
1099 // GenCaches - Call the main cache generator /*{{{*/
1100 // ---------------------------------------------------------------------
1102 bool GenCaches(CommandLine
&Cmd
)
1104 OpTextProgress
Progress(*_config
);
1107 if (List
.ReadMainList() == false)
1109 return pkgMakeStatusCache(List
,Progress
);
1112 // ShowHelp - Show a help screen /*{{{*/
1113 // ---------------------------------------------------------------------
1115 bool ShowHelp(CommandLine
&Cmd
)
1117 ioprintf(cout
,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1118 COMMON_OS
,COMMON_CPU
,__DATE__
,__TIME__
);
1121 _("Usage: apt-cache [options] command\n"
1122 " apt-cache [options] add file1 [file1 ...]\n"
1123 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1125 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1126 "cache files, and query information from them\n"
1129 " add - Add an package file to the source cache\n"
1130 " gencaches - Build both the package and source cache\n"
1131 " showpkg - Show some general information for a single package\n"
1132 " stats - Show some basic statistics\n"
1133 " dump - Show the entire file in a terse form\n"
1134 " dumpavail - Print an available file to stdout\n"
1135 " unmet - Show unmet dependencies\n"
1136 " check - Check the cache a bit\n"
1137 " search - Search the package list for a regex pattern\n"
1138 " show - Show a readable record for the package\n"
1139 " depends - Show raw dependency information for a package\n"
1140 " pkgnames - List the names of all packages\n"
1141 " dotty - Generate package graphs for GraphVis\n"
1144 " -h This help text.\n"
1145 " -p=? The package cache.\n"
1146 " -s=? The source cache.\n"
1147 " -q Disable progress indicator.\n"
1148 " -i Show only important deps for the unmet command.\n"
1149 " -c=? Read this configuration file\n"
1150 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1151 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1155 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1156 // ---------------------------------------------------------------------
1158 void CacheInitialize()
1160 _config
->Set("quiet",0);
1161 _config
->Set("help",false);
1165 int main(int argc
,const char *argv
[])
1167 CommandLine::Args Args
[] = {
1168 {'h',"help","help",0},
1169 {'v',"version","version",0},
1170 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1171 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1172 {'q',"quiet","quiet",CommandLine::IntLevel
},
1173 {'i',"important","APT::Cache::Important",0},
1174 {'f',"full","APT::Cache::ShowFull",0},
1175 {'g',"generate","APT::Cache::Generate",0},
1176 {'a',"all-versions","APT::Cache::AllVersions",0},
1177 {0,"names-only","APT::Cache::NamesOnly",0},
1178 {0,"all-names","APT::Cache::AllNames",0},
1179 {0,"recurse","APT::Cache::RecurseDepends",0},
1180 {'c',"config-file",0,CommandLine::ConfigFile
},
1181 {'o',"option",0,CommandLine::ArbItem
},
1183 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1185 {"gencaches",&GenCaches
},
1186 {"showsrc",&ShowSrcPackage
},
1188 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1191 {"dumpavail",&DumpAvail
},
1194 {"depends",&Depends
},
1196 {"show",&ShowPackage
},
1197 {"pkgnames",&ShowPkgNames
},
1202 // Parse the command line and initialize the package library
1203 CommandLine
CmdL(Args
,_config
);
1204 if (pkgInitConfig(*_config
) == false ||
1205 CmdL
.Parse(argc
,argv
) == false ||
1206 pkgInitSystem(*_config
,_system
) == false)
1208 _error
->DumpErrors();
1212 // See if the help should be shown
1213 if (_config
->FindB("help") == true ||
1214 CmdL
.FileSize() == 0)
1220 // Deal with stdout not being a tty
1221 if (ttyname(STDOUT_FILENO
) == 0 && _config
->FindI("quiet",0) < 1)
1222 _config
->Set("quiet","1");
1224 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1227 if (_config
->FindB("APT::Cache::Generate",true) == false)
1229 Map
= new MMap(*new FileFd(_config
->FindFile("Dir::Cache::pkgcache"),
1230 FileFd::ReadOnly
),MMap::Public
|MMap::ReadOnly
);
1234 // Open the cache file
1236 List
.ReadMainList();
1238 // Generate it and map it
1240 pkgMakeStatusCache(List
,Prog
,&Map
,true);
1243 if (_error
->PendingError() == false)
1245 pkgCache
Cache(Map
);
1247 if (_error
->PendingError() == false)
1248 CmdL
.DispatchArg(CmdsB
);
1253 // Print any errors or warnings found during parsing
1254 if (_error
->empty() == false)
1256 bool Errors
= _error
->PendingError();
1257 _error
->DumpErrors();
1258 return Errors
== true?100:0;