]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.43 2000/05/12 04:00:59 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. The
10 only really usefull function right now is dumpavail which is used
11 by the dselect method. Everything else is meant as a debug aide.
13 Returns 100 on failure, 0 on success.
15 ##################################################################### */
17 // Include Files /*{{{*/
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/pkgcachegen.h>
20 #include <apt-pkg/deblistparser.h>
21 #include <apt-pkg/init.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/cmndline.h>
25 #include <apt-pkg/strutl.h>
26 #include <apt-pkg/pkgrecords.h>
27 #include <apt-pkg/srcrecords.h>
28 #include <apt-pkg/version.h>
40 // UnMet - Show unmet dependencies /*{{{*/
41 // ---------------------------------------------------------------------
43 bool UnMet(CommandLine
&CmdL
)
45 pkgCache
&Cache
= *GCache
;
46 bool Important
= _config
->FindB("APT::Cache::Important",false);
48 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
50 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
53 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
56 pkgCache::DepIterator Start
;
57 pkgCache::DepIterator End
;
60 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
61 End.TargetPkg().Name() << endl;*/
63 // Skip conflicts and replaces
64 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
65 End
->Type
!= pkgCache::Dep::Depends
&&
66 End
->Type
!= pkgCache::Dep::Suggests
&&
67 End
->Type
!= pkgCache::Dep::Recommends
)
70 // Important deps only
71 if (Important
== true)
72 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
73 End
->Type
!= pkgCache::Dep::Depends
)
76 // Verify the or group
78 pkgCache::DepIterator RealStart
= Start
;
81 // See if this dep is Ok
82 pkgCache::Version
**VList
= Start
.AllTargets();
103 cout
<< "Package " << P
.Name() << " version " <<
104 V
.VerStr() << " has an unmet dep:" << endl
;
107 // Print out the dep type
108 cout
<< " " << End
.DepType() << ": ";
114 cout
<< Start
.TargetPkg().Name();
115 if (Start
.TargetVer() != 0)
116 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
132 // DumpPackage - Show a dump of a package record /*{{{*/
133 // ---------------------------------------------------------------------
135 bool DumpPackage(CommandLine
&CmdL
)
137 pkgCache
&Cache
= *GCache
;
138 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
140 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
141 if (Pkg
.end() == true)
143 _error
->Warning("Unable to locate package %s",*I
);
147 cout
<< "Package: " << Pkg
.Name() << endl
;
148 cout
<< "Versions: ";
149 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
151 cout
<< Cur
.VerStr();
152 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
153 cout
<< "(" << Vf
.File().FileName() << ")";
159 cout
<< "Reverse Depends: " << endl
;
160 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
161 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name() << endl
;
163 cout
<< "Dependencies: " << endl
;
164 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
166 cout
<< Cur
.VerStr() << " - ";
167 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
168 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
172 cout
<< "Provides: " << endl
;
173 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
175 cout
<< Cur
.VerStr() << " - ";
176 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
177 cout
<< Prv
.ParentPkg().Name() << " ";
180 cout
<< "Reverse Provides: " << endl
;
181 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
182 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr() << endl
;
188 // Stats - Dump some nice statistics /*{{{*/
189 // ---------------------------------------------------------------------
191 bool Stats(CommandLine
&Cmd
)
193 pkgCache
&Cache
= *GCache
;
194 cout
<< "Total Package Names : " << Cache
.Head().PackageCount
<< " (" <<
195 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
196 pkgCache::PkgIterator I
= Cache
.PkgBegin();
203 for (;I
.end() != true; I
++)
205 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
211 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
217 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
220 if (I
.ProvidesList()->NextProvides
== 0)
228 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
234 cout
<< " Normal Packages: " << Normal
<< endl
;
235 cout
<< " Pure Virtual Packages: " << Virtual
<< endl
;
236 cout
<< " Single Virtual Packages: " << DVirt
<< endl
;
237 cout
<< " Mixed Virtual Packages: " << NVirt
<< endl
;
238 cout
<< " Missing: " << Missing
<< endl
;
240 cout
<< "Total Distinct Versions: " << Cache
.Head().VersionCount
<< " (" <<
241 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
242 cout
<< "Total Dependencies: " << Cache
.Head().DependsCount
<< " (" <<
243 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
245 cout
<< "Total Ver/File relations: " << Cache
.Head().VerFileCount
<< " (" <<
246 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
247 cout
<< "Total Provides Mappings: " << Cache
.Head().ProvidesCount
<< " (" <<
248 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
251 unsigned long Size
= 0;
252 unsigned long Count
= 0;
253 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
254 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
257 Size
+= strlen(Cache
.StrP
+ I
->String
);
259 cout
<< "Total Globbed Strings: " << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
261 unsigned long Slack
= 0;
262 for (int I
= 0; I
!= 7; I
++)
263 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
264 cout
<< "Total Slack space: " << SizeToStr(Slack
) << endl
;
266 unsigned long Total
= 0;
267 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
268 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
269 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
270 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
271 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
272 cout
<< "Total Space Accounted for: " << SizeToStr(Total
) << endl
;
277 // Check - Check some things about the cache /*{{{*/
278 // ---------------------------------------------------------------------
279 /* Debug aide mostly */
280 bool Check(CommandLine
&Cmd
)
282 pkgCache
&Cache
= *GCache
;
283 pkgCache::PkgIterator Pkg
= Cache
.PkgBegin();
284 for (;Pkg
.end() != true; Pkg
++)
286 if (Pkg
.Section() == 0 && Pkg
->VersionList
!= 0)
287 cout
<< "Bad section " << Pkg
.Name() << endl
;
289 for (pkgCache::VerIterator Cur
= Pkg
.VersionList();
290 Cur
.end() != true; Cur
++)
292 if (Cur
->Priority
< 1 || Cur
->Priority
> 5)
293 cout
<< "Bad prio " << Pkg
.Name() << ',' << Cur
.VerStr() << " == " << (int)Cur
->Priority
<< endl
;
299 // Dump - show everything /*{{{*/
300 // ---------------------------------------------------------------------
302 bool Dump(CommandLine
&Cmd
)
304 pkgCache
&Cache
= *GCache
;
305 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
307 cout
<< "Package: " << P
.Name() << endl
;
308 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
310 cout
<< " Version: " << V
.VerStr() << endl
;
311 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
312 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
313 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
317 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
319 cout
<< "File: " << F
.FileName() << endl
;
320 cout
<< " Size: " << F
->Size
<< endl
;
321 cout
<< " ID: " << F
->ID
<< endl
;
322 cout
<< " Flags: " << F
->Flags
<< endl
;
323 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
324 cout
<< " Archive: " << F
.Archive() << endl
;
325 cout
<< " Component: " << F
.Component() << endl
;
326 cout
<< " Version: " << F
.Version() << endl
;
327 cout
<< " Origin: " << F
.Origin() << endl
;
328 cout
<< " Label: " << F
.Label() << endl
;
329 cout
<< " Architecture: " << F
.Architecture() << endl
;
335 // DumpAvail - Print out the available list /*{{{*/
336 // ---------------------------------------------------------------------
337 /* This is needed to make dpkg --merge happy */
338 bool DumpAvail(CommandLine
&Cmd
)
340 pkgCache
&Cache
= *GCache
;
341 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
343 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
345 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
348 if (I
.IsOk() == false)
351 return _error
->Error("Package file %s is out of sync.",I
.FileName());
354 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
355 if (_error
->PendingError() == true)
361 /* Write all of the records from this package file, we search the entire
362 structure to find them */
363 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
365 // Find the proper version to use. We should probably use the DepCache.
366 pkgCache::VerIterator V
= Cache
.GetCandidateVer(P
,false);
368 if (V
.end() == true || V
.FileList().File() != I
)
371 // Read the record and then write it out again.
372 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
373 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
374 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
385 // Depends - Print out a dependency tree /*{{{*/
386 // ---------------------------------------------------------------------
388 bool Depends(CommandLine
&CmdL
)
390 pkgCache
&Cache
= *GCache
;
392 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
394 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
395 if (Pkg
.end() == true)
397 _error
->Warning("Unable to locate package %s",*I
);
401 pkgCache::VerIterator Ver
= Pkg
.VersionList();
402 if (Ver
.end() == true)
404 cout
<< '<' << Pkg
.Name() << '>' << endl
;
408 cout
<< Pkg
.Name() << endl
;
410 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
412 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
418 pkgCache::PkgIterator Trg
= D
.TargetPkg();
419 if (Trg
->VersionList
== 0)
420 cout
<< D
.DepType() << ": <" << Trg
.Name() << ">" << endl
;
422 cout
<< D
.DepType() << ": " << Trg
.Name() << endl
;
424 // Display all solutions
425 pkgCache::Version
**List
= D
.AllTargets();
426 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
428 pkgCache::VerIterator
V(Cache
,*I
);
429 if (V
!= Cache
.VerP
+ V
.ParentPkg()->VersionList
||
430 V
->ParentPkg
== D
->Package
)
432 cout
<< " " << V
.ParentPkg().Name() << endl
;
441 // Dotty - Generate a graph for Dotty /*{{{*/
442 // ---------------------------------------------------------------------
443 /* Dotty is the graphvis program for generating graphs. It is a fairly
444 simple queuing algorithm that just writes dependencies and nodes.
445 http://www.research.att.com/sw/tools/graphviz/ */
446 bool Dotty(CommandLine
&CmdL
)
448 pkgCache
&Cache
= *GCache
;
449 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
451 /* Normal packages are boxes
452 Pure Provides are triangles
454 Hexagons are missing packages*/
455 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
457 /* Initialize the list of packages to show.
459 2 = To Show no recurse
460 3 = Emitted no recurse
463 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
464 enum TheFlags
{ForceNR
=(1<<0)};
465 unsigned char *Show
= new unsigned char[Cache
.Head().PackageCount
];
466 unsigned char *Flags
= new unsigned char[Cache
.Head().PackageCount
];
467 unsigned char *ShapeMap
= new unsigned char[Cache
.Head().PackageCount
];
469 // Show everything if no arguments given
470 if (CmdL
.FileList
[1] == 0)
471 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
474 for (unsigned long I
= 0; I
!= Cache
.Head().PackageCount
; I
++)
476 memset(Flags
,0,sizeof(*Flags
)*Cache
.Head().PackageCount
);
479 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
481 if (Pkg
->VersionList
== 0)
484 if (Pkg
->ProvidesList
== 0)
485 ShapeMap
[Pkg
->ID
] = 0;
487 ShapeMap
[Pkg
->ID
] = 1;
492 if (Pkg
->ProvidesList
== 0)
493 ShapeMap
[Pkg
->ID
] = 2;
495 ShapeMap
[Pkg
->ID
] = 3;
499 // Load the list of packages from the command line into the show list
500 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
502 // Process per-package flags
507 if (P
.end()[-1] == '^')
513 if (P
.end()[-1] == ',')
517 // Locate the package
518 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(P
);
519 if (Pkg
.end() == true)
521 _error
->Warning("Unable to locate package %s",*I
);
524 Show
[Pkg
->ID
] = ToShow
;
527 Flags
[Pkg
->ID
] |= ForceNR
;
531 printf("digraph packages {\n");
532 printf("concentrate=true;\n");
533 printf("size=\"30,40\";\n");
539 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
541 // See we need to show this package
542 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
546 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
548 // Pure Provides and missing packages have no deps!
549 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
550 Show
[Pkg
->ID
] = Done
;
552 Show
[Pkg
->ID
] = DoneNR
;
555 Show
[Pkg
->ID
] = Done
;
558 // No deps to map out
559 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
562 pkgCache::VerIterator Ver
= Pkg
.VersionList();
563 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
565 // See if anything can meet this dep
566 // Walk along the actual package providing versions
568 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
569 for (pkgCache::VerIterator I
= DPkg
.VersionList();
570 I
.end() == false && Hit
== false; I
++)
572 if (pkgCheckDep(D
.TargetVer(),I
.VerStr(),D
->CompareOp
) == true)
576 // Follow all provides
577 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
578 I
.end() == false && Hit
== false; I
++)
580 if (pkgCheckDep(D
.TargetVer(),I
.ProvideVersion(),D
->CompareOp
) == false)
584 // Only graph critical deps
585 if (D
.IsCritical() == true)
587 printf("\"%s\" -> \"%s\"",Pkg
.Name(),D
.TargetPkg().Name());
589 // Colour the node for recursion
590 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
592 /* If a conflicts does not meet anything in the database
593 then show the relation but do not recurse */
594 if (Hit
== false && D
->Type
== pkgCache::Dep::Conflicts
)
596 if (Show
[D
.TargetPkg()->ID
] == None
&&
597 Show
[D
.TargetPkg()->ID
] != ToShow
)
598 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
602 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
603 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
605 Show
[D
.TargetPkg()->ID
] = ToShow
;
612 case pkgCache::Dep::Conflicts
:
613 printf("[color=springgreen];\n");
616 case pkgCache::Dep::PreDepends
:
617 printf("[color=blue];\n");
629 /* Draw the box colours after the fact since we can not tell what colour
630 they should be until everything is finished drawing */
631 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; Pkg
++)
633 if (Show
[Pkg
->ID
] < DoneNR
)
636 // Orange box for early recursion stoppage
637 if (Show
[Pkg
->ID
] == DoneNR
)
638 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.Name(),
639 Shapes
[ShapeMap
[Pkg
->ID
]]);
641 printf("\"%s\" [shape=%s];\n",Pkg
.Name(),
642 Shapes
[ShapeMap
[Pkg
->ID
]]);
649 // DoAdd - Perform an adding operation /*{{{*/
650 // ---------------------------------------------------------------------
652 bool DoAdd(CommandLine
&CmdL
)
654 // Make sure there is at least one argument
655 if (CmdL
.FileSize() <= 1)
656 return _error
->Error("You must give at least one file name");
659 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
660 if (_error
->PendingError() == true)
663 DynamicMMap
Map(CacheF
,MMap::Public
);
664 if (_error
->PendingError() == true)
667 OpTextProgress
Progress(*_config
);
668 pkgCacheGenerator
Gen(Map
,Progress
);
669 if (_error
->PendingError() == true)
672 unsigned long Length
= CmdL
.FileSize() - 1;
673 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
675 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
676 Progress
.SubProgress(Length
);
679 FileFd
TagF(*I
,FileFd::ReadOnly
);
680 debListParser
Parser(TagF
);
681 if (_error
->PendingError() == true)
682 return _error
->Error("Problem opening %s",*I
);
684 if (Gen
.SelectFile(*I
) == false)
685 return _error
->Error("Problem with SelectFile");
687 if (Gen
.MergeList(Parser
) == false)
688 return _error
->Error("Problem with MergeList");
692 GCache
= &Gen
.GetCache();
698 // DisplayRecord - Displays the complete record for the package /*{{{*/
699 // ---------------------------------------------------------------------
700 /* This displays the package record from the proper package index file.
701 It is not used by DumpAvail for performance reasons. */
702 bool DisplayRecord(pkgCache::VerIterator V
)
704 // Find an appropriate file
705 pkgCache::VerFileIterator Vf
= V
.FileList();
706 for (; Vf
.end() == false; Vf
++)
707 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
709 if (Vf
.end() == true)
712 // Check and load the package list file
713 pkgCache::PkgFileIterator I
= Vf
.File();
714 if (I
.IsOk() == false)
715 return _error
->Error("Package file %s is out of sync.",I
.FileName());
717 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
718 if (_error
->PendingError() == true)
721 // Read the record and then write it out again.
722 unsigned char *Buffer
= new unsigned char[GCache
->HeaderP
->MaxVerFileSize
];
723 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
724 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
725 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
736 // Search - Perform a search /*{{{*/
737 // ---------------------------------------------------------------------
738 /* This searches the package names and pacakge descriptions for a pattern */
739 bool Search(CommandLine
&CmdL
)
741 pkgCache
&Cache
= *GCache
;
742 bool ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
743 bool NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
745 // Make sure there is at least one argument
746 if (CmdL
.FileSize() != 2)
747 return _error
->Error("You must give exactly one pattern");
749 // Compile the regex pattern
751 if (regcomp(&Pattern
,CmdL
.FileList
[1],REG_EXTENDED
| REG_ICASE
|
753 return _error
->Error("Regex compilation error");
755 // Create the text record parser
756 pkgRecords
Recs(Cache
);
757 if (_error
->PendingError() == true)
760 // Search package names
761 pkgCache::PkgIterator I
= Cache
.PkgBegin();
762 for (;I
.end() != true; I
++)
764 // We search against the install version as that makes the most sense..
765 pkgCache::VerIterator V
= Cache
.GetCandidateVer(I
);
769 pkgRecords::Parser
&P
= Recs
.Lookup(V
.FileList());
771 if (regexec(&Pattern
,I
.Name(),0,0,0) == 0 ||
772 (NamesOnly
== false &&
773 regexec(&Pattern
,P
.LongDesc().c_str(),0,0,0) == 0))
775 if (ShowFull
== true)
778 cout
<< I
.Name() << " - " << P
.ShortDesc() << endl
;
786 // ShowPackage - Dump the package record to the screen /*{{{*/
787 // ---------------------------------------------------------------------
789 bool ShowPackage(CommandLine
&CmdL
)
791 pkgCache
&Cache
= *GCache
;
792 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
794 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
795 if (Pkg
.end() == true)
797 _error
->Warning("Unable to locate package %s",*I
);
801 // Find the proper version to use. We should probably use the DepCache.
802 if (_config
->FindB("APT::Cache::AllVersions","true") == true)
804 pkgCache::VerIterator V
;
805 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
807 if (DisplayRecord(V
) == false)
813 pkgCache::VerIterator V
= Cache
.GetCandidateVer(Pkg
);
814 if (V
.end() == true || V
.FileList().end() == true)
816 if (DisplayRecord(V
) == false)
823 // ShowPkgNames - Show package names /*{{{*/
824 // ---------------------------------------------------------------------
825 /* This does a prefix match on the first argument */
826 bool ShowPkgNames(CommandLine
&CmdL
)
828 pkgCache
&Cache
= *GCache
;
829 pkgCache::PkgIterator I
= Cache
.PkgBegin();
830 bool All
= _config
->FindB("APT::Cache::AllNames","false");
832 if (CmdL
.FileList
[1] != 0)
834 for (;I
.end() != true; I
++)
836 if (All
== false && I
->VersionList
== 0)
839 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
840 cout
<< I
.Name() << endl
;
847 for (;I
.end() != true; I
++)
849 if (All
== false && I
->VersionList
== 0)
851 cout
<< I
.Name() << endl
;
857 // ShowSrcPackage - Show source package records /*{{{*/
858 // ---------------------------------------------------------------------
860 bool ShowSrcPackage(CommandLine
&CmdL
)
865 // Create the text record parsers
866 pkgSrcRecords
SrcRecs(List
);
867 if (_error
->PendingError() == true)
870 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
874 pkgSrcRecords::Parser
*Parse
;
875 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0)
876 cout
<< Parse
->AsStr();
881 // GenCaches - Call the main cache generator /*{{{*/
882 // ---------------------------------------------------------------------
884 bool GenCaches(CommandLine
&Cmd
)
886 OpTextProgress
Progress(*_config
);
890 return pkgMakeStatusCache(List
,Progress
);
893 // ShowHelp - Show a help screen /*{{{*/
894 // ---------------------------------------------------------------------
896 bool ShowHelp(CommandLine
&Cmd
)
898 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
899 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
900 if (_config
->FindB("version") == true)
903 cout
<< "Usage: apt-cache [options] command" << endl
;
904 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
905 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
907 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
908 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
909 cout
<< "It is not meant for ordinary use only as a debug aide." << endl
;
911 cout
<< "Commands:" << endl
;
912 cout
<< " add - Add an package file to the source cache" << endl
;
913 cout
<< " gencaches - Build both the package and source cache" << endl
;
914 cout
<< " showpkg - Show some general information for a single package" << endl
;
915 cout
<< " stats - Show some basic statistics" << endl
;
916 cout
<< " dump - Show the entire file in a terse form" << endl
;
917 cout
<< " dumpavail - Print an available file to stdout" << endl
;
918 cout
<< " unmet - Show unmet dependencies" << endl
;
919 cout
<< " check - Check the cache a bit" << endl
;
920 cout
<< " search - Search the package list for a regex pattern" << endl
;
921 cout
<< " show - Show a readable record for the package" << endl
;
922 cout
<< " depends - Show raw dependency information for a package" << endl
;
923 cout
<< " pkgnames - List the names of all packages" << endl
;
924 cout
<< " dotty - Generate package graphs for GraphVis" << endl
;
926 cout
<< "Options:" << endl
;
927 cout
<< " -h This help text." << endl
;
928 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
929 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
930 cout
<< " -q Disable progress indicator." << endl
;
931 cout
<< " -i Show only important deps for the unmet command." << endl
;
932 cout
<< " -c=? Read this configuration file" << endl
;
933 cout
<< " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl
;
934 cout
<< "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl
;
938 // CacheInitialize - Initialize things for apt-cache /*{{{*/
939 // ---------------------------------------------------------------------
941 void CacheInitialize()
943 _config
->Set("quiet",0);
944 _config
->Set("help",false);
948 int main(int argc
,const char *argv
[])
950 CommandLine::Args Args
[] = {
951 {'h',"help","help",0},
952 {'v',"version","version",0},
953 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
954 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
955 {'q',"quiet","quiet",CommandLine::IntLevel
},
956 {'i',"important","APT::Cache::Important",0},
957 {'f',"full","APT::Cache::ShowFull",0},
958 {'g',"no-generate","APT::Cache::NoGenerate",0},
959 {'a',"all-versions","APT::Cache::AllVersions",0},
960 {0,"names-only","APT::Cache::NamesOnly",0},
961 {0,"all-names","APT::Cache::AllNames",0},
962 {'c',"config-file",0,CommandLine::ConfigFile
},
963 {'o',"option",0,CommandLine::ArbItem
},
965 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
967 {"gencaches",&GenCaches
},
968 {"showsrc",&ShowSrcPackage
},
970 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
973 {"dumpavail",&DumpAvail
},
977 {"depends",&Depends
},
979 {"show",&ShowPackage
},
980 {"pkgnames",&ShowPkgNames
},
985 // Parse the command line and initialize the package library
986 CommandLine
CmdL(Args
,_config
);
987 if (pkgInitialize(*_config
) == false ||
988 CmdL
.Parse(argc
,argv
) == false)
990 _error
->DumpErrors();
994 // See if the help should be shown
995 if (_config
->FindB("help") == true ||
996 CmdL
.FileSize() == 0)
997 return ShowHelp(CmdL
);
999 // Deal with stdout not being a tty
1000 if (ttyname(STDOUT_FILENO
) == 0 && _config
->FindI("quiet",0) < 1)
1001 _config
->Set("quiet","1");
1003 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1006 if (_config
->FindB("APT::Cache::NoGenerate",false) == true)
1008 Map
= new MMap(*new FileFd(_config
->FindFile("Dir::Cache::pkgcache"),
1009 FileFd::ReadOnly
),MMap::Public
|MMap::ReadOnly
);
1013 // Open the cache file
1015 List
.ReadMainList();
1017 // Generate it and map it
1019 Map
= pkgMakeStatusCacheMem(List
,Prog
);
1022 if (_error
->PendingError() == false)
1024 pkgCache
Cache(*Map
);
1026 if (_error
->PendingError() == false)
1027 CmdL
.DispatchArg(CmdsB
);
1032 // Print any errors or warnings found during parsing
1033 if (_error
->empty() == false)
1035 bool Errors
= _error
->PendingError();
1036 _error
->DumpErrors();
1037 return Errors
== true?100:0;