]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.28 1999/02/19 08:57:41 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 ment 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>
37 // UnMet - Show unmet dependencies /*{{{*/
38 // ---------------------------------------------------------------------
40 bool UnMet(CommandLine
&CmdL
)
42 pkgCache
&Cache
= *GCache
;
43 bool Important
= _config
->FindB("APT::Cache::Important",false);
45 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
47 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
50 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
53 pkgCache::DepIterator Start
;
54 pkgCache::DepIterator End
;
57 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
58 End.TargetPkg().Name() << endl;*/
60 // Skip conflicts and replaces
61 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
62 End
->Type
!= pkgCache::Dep::Depends
&&
63 End
->Type
!= pkgCache::Dep::Suggests
&&
64 End
->Type
!= pkgCache::Dep::Recommends
)
67 // Important deps only
68 if (Important
== true)
69 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
70 End
->Type
!= pkgCache::Dep::Depends
)
73 // Verify the or group
75 pkgCache::DepIterator RealStart
= Start
;
78 // See if this dep is Ok
79 pkgCache::Version
**VList
= Start
.AllTargets();
100 cout
<< "Package " << P
.Name() << " version " <<
101 V
.VerStr() << " has an unmet dep:" << endl
;
104 // Print out the dep type
105 cout
<< " " << End
.DepType() << ": ";
111 cout
<< Start
.TargetPkg().Name();
112 if (Start
.TargetVer() != 0)
113 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
129 // DumpPackage - Show a dump of a package record /*{{{*/
130 // ---------------------------------------------------------------------
132 bool DumpPackage(CommandLine
&CmdL
)
134 pkgCache
&Cache
= *GCache
;
135 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
137 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
138 if (Pkg
.end() == true)
140 _error
->Warning("Unable to locate package %s",*I
);
144 cout
<< "Package: " << Pkg
.Name() << endl
;
145 cout
<< "Versions: ";
146 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
148 cout
<< Cur
.VerStr();
149 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
150 cout
<< "(" << Vf
.File().FileName() << ")";
156 cout
<< "Reverse Depends: " << endl
;
157 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
158 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name() << endl
;
160 cout
<< "Dependencies: " << endl
;
161 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
163 cout
<< Cur
.VerStr() << " - ";
164 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
165 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
169 cout
<< "Provides: " << endl
;
170 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
172 cout
<< Cur
.VerStr() << " - ";
173 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
174 cout
<< Prv
.ParentPkg().Name() << " ";
177 cout
<< "Reverse Provides: " << endl
;
178 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
179 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr();
187 // Stats - Dump some nice statistics /*{{{*/
188 // ---------------------------------------------------------------------
190 bool Stats(CommandLine
&Cmd
)
192 pkgCache
&Cache
= *GCache
;
193 cout
<< "Total Package Names : " << Cache
.Head().PackageCount
<< " (" <<
194 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
195 pkgCache::PkgIterator I
= Cache
.PkgBegin();
202 for (;I
.end() != true; I
++)
204 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
210 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
216 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
219 if (I
.ProvidesList()->NextProvides
== 0)
227 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
233 cout
<< " Normal Packages: " << Normal
<< endl
;
234 cout
<< " Pure Virtual Packages: " << Virtual
<< endl
;
235 cout
<< " Single Virtual Packages: " << DVirt
<< endl
;
236 cout
<< " Mixed Virtual Packages: " << NVirt
<< endl
;
237 cout
<< " Missing: " << Missing
<< endl
;
239 cout
<< "Total Distinct Versions: " << Cache
.Head().VersionCount
<< " (" <<
240 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
241 cout
<< "Total Dependencies: " << Cache
.Head().DependsCount
<< " (" <<
242 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
244 cout
<< "Total Ver/File relations: " << Cache
.Head().VerFileCount
<< " (" <<
245 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
246 cout
<< "Total Provides Mappings: " << Cache
.Head().ProvidesCount
<< " (" <<
247 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
250 unsigned long Size
= 0;
251 unsigned long Count
= 0;
252 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
253 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
256 Size
+= strlen(Cache
.StrP
+ I
->String
);
258 cout
<< "Total Globbed Strings: " << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
260 unsigned long Slack
= 0;
261 for (int I
= 0; I
!= 7; I
++)
262 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
263 cout
<< "Total Slack space: " << SizeToStr(Slack
) << endl
;
265 unsigned long Total
= 0;
266 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
267 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
268 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
269 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
270 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
271 cout
<< "Total Space Accounted for: " << SizeToStr(Total
) << endl
;
276 // Check - Check some things about the cache /*{{{*/
277 // ---------------------------------------------------------------------
278 /* Debug aide mostly */
279 bool Check(CommandLine
&Cmd
)
281 pkgCache
&Cache
= *GCache
;
282 pkgCache::PkgIterator Pkg
= Cache
.PkgBegin();
283 for (;Pkg
.end() != true; Pkg
++)
285 if (Pkg
.Section() == 0 && Pkg
->VersionList
!= 0)
286 cout
<< "Bad section " << Pkg
.Name() << endl
;
288 for (pkgCache::VerIterator Cur
= Pkg
.VersionList();
289 Cur
.end() != true; Cur
++)
291 if (Cur
->Priority
< 1 || Cur
->Priority
> 5)
292 cout
<< "Bad prio " << Pkg
.Name() << ',' << Cur
.VerStr() << " == " << (int)Cur
->Priority
<< endl
;
298 // Dump - show everything /*{{{*/
299 // ---------------------------------------------------------------------
301 bool Dump(CommandLine
&Cmd
)
303 pkgCache
&Cache
= *GCache
;
304 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
306 cout
<< "Package: " << P
.Name() << endl
;
307 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
309 cout
<< " Version: " << V
.VerStr() << endl
;
310 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
311 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
312 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
316 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
318 cout
<< "File: " << F
.FileName() << endl
;
319 cout
<< " Size: " << F
->Size
<< endl
;
320 cout
<< " ID: " << F
->ID
<< endl
;
321 cout
<< " Flags: " << F
->Flags
<< endl
;
322 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
323 cout
<< " Archive: " << F
.Archive() << endl
;
324 cout
<< " Component: " << F
.Component() << endl
;
325 cout
<< " Version: " << F
.Version() << endl
;
326 cout
<< " Origin: " << F
.Origin() << endl
;
327 cout
<< " Label: " << F
.Label() << endl
;
328 cout
<< " Architecture: " << F
.Architecture() << endl
;
334 // GetCandidateVer - Returns the Candidate install version /*{{{*/
335 // ---------------------------------------------------------------------
336 /* This should really use the DepCache or something.. Copied from there. */
337 static pkgCache::VerIterator
GetCandidateVer(pkgCache::PkgIterator Pkg
)
339 /* Not source/not automatic versions cannot be a candidate version
340 unless they are already installed */
341 for (pkgCache::VerIterator I
= Pkg
.VersionList(); I
.end() == false; I
++)
343 if (Pkg
.CurrentVer() == I
)
345 for (pkgCache::VerFileIterator J
= I
.FileList(); J
.end() == false; J
++)
346 if ((J
.File()->Flags
& pkgCache::Flag::NotSource
) == 0 &&
347 (J
.File()->Flags
& pkgCache::Flag::NotAutomatic
) == 0)
351 return pkgCache::VerIterator(*GCache
,0);
354 // DumpAvail - Print out the available list /*{{{*/
355 // ---------------------------------------------------------------------
356 /* This is needed to make dpkg --merge happy */
357 bool DumpAvail(CommandLine
&Cmd
)
359 pkgCache
&Cache
= *GCache
;
360 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
362 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
364 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
367 if (I
.IsOk() == false)
370 return _error
->Error("Package file %s is out of sync.",I
.FileName());
373 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
374 if (_error
->PendingError() == true)
380 /* Write all of the records from this package file, we search the entire
381 structure to find them */
382 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
384 // Find the proper version to use. We should probably use the DepCache.
385 pkgCache::VerIterator V
= GetCandidateVer(P
);
387 if (V
.end() == true || V
.FileList().File() != I
)
390 // Read the record and then write it out again.
391 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
392 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
393 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
404 // DoAdd - Perform an adding operation /*{{{*/
405 // ---------------------------------------------------------------------
407 bool DoAdd(CommandLine
&CmdL
)
409 // Make sure there is at least one argument
410 if (CmdL
.FileSize() <= 1)
411 return _error
->Error("You must give at least one file name");
414 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
415 if (_error
->PendingError() == true)
418 DynamicMMap
Map(CacheF
,MMap::Public
);
419 if (_error
->PendingError() == true)
422 OpTextProgress
Progress(*_config
);
423 pkgCacheGenerator
Gen(Map
,Progress
);
424 if (_error
->PendingError() == true)
427 unsigned long Length
= CmdL
.FileSize() - 1;
428 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
430 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
431 Progress
.SubProgress(Length
);
434 FileFd
TagF(*I
,FileFd::ReadOnly
);
435 debListParser
Parser(TagF
);
436 if (_error
->PendingError() == true)
437 return _error
->Error("Problem opening %s",*I
);
439 if (Gen
.SelectFile(*I
) == false)
440 return _error
->Error("Problem with SelectFile");
442 if (Gen
.MergeList(Parser
) == false)
443 return _error
->Error("Problem with MergeList");
447 GCache
= &Gen
.GetCache();
453 // DisplayRecord - Displays the complete record for the package /*{{{*/
454 // ---------------------------------------------------------------------
455 /* This displays the package record from the proper package index file.
456 It is not used by DumpAvail for performance reasons. */
457 bool DisplayRecord(pkgCache::VerIterator V
)
459 // Find an appropriate file
460 pkgCache::VerFileIterator Vf
= V
.FileList();
461 for (; Vf
.end() == false; Vf
++)
462 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
464 if (Vf
.end() == true)
467 // Check and load the package list file
468 pkgCache::PkgFileIterator I
= Vf
.File();
469 if (I
.IsOk() == false)
470 return _error
->Error("Package file %s is out of sync.",I
.FileName());
472 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
473 if (_error
->PendingError() == true)
476 // Read the record and then write it out again.
477 unsigned char *Buffer
= new unsigned char[GCache
->HeaderP
->MaxVerFileSize
];
478 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
479 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
480 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
491 // Search - Perform a search /*{{{*/
492 // ---------------------------------------------------------------------
493 /* This searches the package names and pacakge descriptions for a pattern */
494 bool Search(CommandLine
&CmdL
)
496 pkgCache
&Cache
= *GCache
;
497 bool ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
498 bool NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
500 // Make sure there is at least one argument
501 if (CmdL
.FileSize() != 2)
502 return _error
->Error("You must give exactly one pattern");
504 // Compile the regex pattern
506 if (regcomp(&Pattern
,CmdL
.FileList
[1],REG_EXTENDED
| REG_ICASE
|
508 return _error
->Error("Regex compilation error");
510 // Create the text record parser
511 pkgRecords
Recs(Cache
);
512 if (_error
->PendingError() == true)
515 // Search package names
516 pkgCache::PkgIterator I
= Cache
.PkgBegin();
517 for (;I
.end() != true; I
++)
519 // We search against the install version as that makes the most sense..
520 pkgCache::VerIterator V
= GetCandidateVer(I
);
524 pkgRecords::Parser
&P
= Recs
.Lookup(V
.FileList());
526 if (regexec(&Pattern
,I
.Name(),0,0,0) == 0 ||
527 (NamesOnly
== false &&
528 regexec(&Pattern
,P
.LongDesc().c_str(),0,0,0) == 0))
530 if (ShowFull
== true)
533 cout
<< I
.Name() << " - " << P
.ShortDesc() << endl
;
541 // ShowPackage - Dump the package record to the screen /*{{{*/
542 // ---------------------------------------------------------------------
544 bool ShowPackage(CommandLine
&CmdL
)
546 pkgCache
&Cache
= *GCache
;
547 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
549 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
550 if (Pkg
.end() == true)
552 _error
->Warning("Unable to locate package %s",*I
);
556 // Find the proper version to use. We should probably use the DepCache.
557 pkgCache::VerIterator V
= GetCandidateVer(Pkg
);
558 if (V
.end() == true || V
.FileList().end() == true)
560 if (DisplayRecord(V
) == false)
566 // GenCaches - Call the main cache generator /*{{{*/
567 // ---------------------------------------------------------------------
569 bool GenCaches(CommandLine
&Cmd
)
571 OpTextProgress
Progress(*_config
);
575 return pkgMakeStatusCache(List
,Progress
);
578 // ShowHelp - Show a help screen /*{{{*/
579 // ---------------------------------------------------------------------
581 bool ShowHelp(CommandLine
&Cmd
)
583 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
584 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
585 if (_config
->FindB("version") == true)
588 cout
<< "Usage: apt-cache [options] command" << endl
;
589 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
590 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
592 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
593 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
594 cout
<< "It is not ment for ordinary use only as a debug aide." << endl
;
596 cout
<< "Commands:" << endl
;
597 cout
<< " add - Add an package file to the source cache" << endl
;
598 cout
<< " gencaches - Build both the package and source cache" << endl
;
599 cout
<< " showpkg - Show some general information for a single package" << endl
;
600 cout
<< " stats - Show some basic statistics" << endl
;
601 cout
<< " dump - Show the entire file in a terse form" << endl
;
602 cout
<< " dumpavail - Print an available file to stdout" << endl
;
603 cout
<< " unmet - Show unmet dependencies" << endl
;
604 cout
<< " check - Check the cache a bit" << endl
;
605 cout
<< " search - Search the package list for a regex pattern" << endl
;
606 cout
<< " show - Show a readable record for the package" << endl
;
608 cout
<< "Options:" << endl
;
609 cout
<< " -h This help text." << endl
;
610 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
611 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
612 cout
<< " -q Disable progress indicator." << endl
;
613 cout
<< " -i Show only important deps for the unmet command." << endl
;
614 cout
<< " -c=? Read this configuration file" << endl
;
615 cout
<< " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl
;
616 cout
<< "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl
;
620 // CacheInitialize - Initialize things for apt-cache /*{{{*/
621 // ---------------------------------------------------------------------
623 void CacheInitialize()
625 _config
->Set("quiet",0);
626 _config
->Set("help",false);
630 int main(int argc
,const char *argv
[])
632 CommandLine::Args Args
[] = {
633 {'h',"help","help",0},
634 {'v',"version","version",0},
635 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
636 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
637 {'q',"quiet","quiet",CommandLine::IntLevel
},
638 {'i',"important","APT::Cache::Important",0},
639 {'f',"full","APT::Cache::ShowFull",0},
640 {0,"names-only","APT::Cache::NamesOnly",0},
641 {'c',"config-file",0,CommandLine::ConfigFile
},
642 {'o',"option",0,CommandLine::ArbItem
},
644 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
646 {"gencaches",&GenCaches
},
648 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
651 {"dumpavail",&DumpAvail
},
655 {"show",&ShowPackage
},
660 // Parse the command line and initialize the package library
661 CommandLine
CmdL(Args
,_config
);
662 if (pkgInitialize(*_config
) == false ||
663 CmdL
.Parse(argc
,argv
) == false)
665 _error
->DumpErrors();
669 // See if the help should be shown
670 if (_config
->FindB("help") == true ||
671 CmdL
.FileSize() == 0)
672 return ShowHelp(CmdL
);
674 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
676 // Open the cache file
677 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly
);
678 MMap
Map(CacheF
,MMap::Public
| MMap::ReadOnly
);
679 if (_error
->PendingError() == false)
683 if (_error
->PendingError() == false)
684 CmdL
.DispatchArg(CmdsB
);
688 // Print any errors or warnings found during parsing
689 if (_error
->empty() == false)
691 bool Errors
= _error
->PendingError();
692 _error
->DumpErrors();
693 return Errors
== true?100:0;