]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
26d96c86011340381f85c6afe888e83c33d44a77
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.24 1999/02/08 07:54: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. 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>
34 // UnMet - Show unmet dependencies /*{{{*/
35 // ---------------------------------------------------------------------
37 bool UnMet(CommandLine
&CmdL
)
39 pkgCache
&Cache
= *GCache
;
40 bool Important
= _config
->FindB("APT::Cache::Important",false);
42 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
44 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
47 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
50 pkgCache::DepIterator Start
;
51 pkgCache::DepIterator End
;
54 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
55 End.TargetPkg().Name() << endl;*/
57 // Skip conflicts and replaces
58 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
59 End
->Type
!= pkgCache::Dep::Depends
&&
60 End
->Type
!= pkgCache::Dep::Suggests
&&
61 End
->Type
!= pkgCache::Dep::Recommends
)
64 // Important deps only
65 if (Important
== true)
66 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
67 End
->Type
!= pkgCache::Dep::Depends
)
70 // Verify the or group
72 pkgCache::DepIterator RealStart
= Start
;
75 // See if this dep is Ok
76 pkgCache::Version
**VList
= Start
.AllTargets();
97 cout
<< "Package " << P
.Name() << " version " <<
98 V
.VerStr() << " has an unmet dep:" << endl
;
101 // Print out the dep type
102 cout
<< " " << End
.DepType() << ": ";
108 cout
<< Start
.TargetPkg().Name();
109 if (Start
.TargetVer() != 0)
110 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
126 // DumpPackage - Show a dump of a package record /*{{{*/
127 // ---------------------------------------------------------------------
129 bool DumpPackage(CommandLine
&CmdL
)
131 pkgCache
&Cache
= *GCache
;
132 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
134 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
135 if (Pkg
.end() == true)
137 _error
->Warning("Unable to locate package %s",*I
);
141 cout
<< "Package: " << Pkg
.Name() << endl
;
142 cout
<< "Versions: ";
143 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
145 cout
<< Cur
.VerStr();
146 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
147 cout
<< "(" << Vf
.File().FileName() << ")";
153 cout
<< "Reverse Depends: " << endl
;
154 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
155 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name() << endl
;
157 cout
<< "Dependencies: " << endl
;
158 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
160 cout
<< Cur
.VerStr() << " - ";
161 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
162 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
166 cout
<< "Provides: " << endl
;
167 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
169 cout
<< Cur
.VerStr() << " - ";
170 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
171 cout
<< Prv
.ParentPkg().Name() << " ";
174 cout
<< "Reverse Provides: " << endl
;
175 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
176 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr();
184 // Stats - Dump some nice statistics /*{{{*/
185 // ---------------------------------------------------------------------
187 bool Stats(CommandLine
&Cmd
)
189 pkgCache
&Cache
= *GCache
;
190 cout
<< "Total Package Names : " << Cache
.Head().PackageCount
<< " (" <<
191 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
192 pkgCache::PkgIterator I
= Cache
.PkgBegin();
199 for (;I
.end() != true; I
++)
201 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
207 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
213 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
216 if (I
.ProvidesList()->NextProvides
== 0)
224 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
230 cout
<< " Normal Packages: " << Normal
<< endl
;
231 cout
<< " Pure Virtual Packages: " << Virtual
<< endl
;
232 cout
<< " Single Virtual Packages: " << DVirt
<< endl
;
233 cout
<< " Mixed Virtual Packages: " << NVirt
<< endl
;
234 cout
<< " Missing: " << Missing
<< endl
;
236 cout
<< "Total Distinct Versions: " << Cache
.Head().VersionCount
<< " (" <<
237 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
238 cout
<< "Total Dependencies: " << Cache
.Head().DependsCount
<< " (" <<
239 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
241 cout
<< "Total Ver/File relations: " << Cache
.Head().VerFileCount
<< " (" <<
242 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
243 cout
<< "Total Provides Mappings: " << Cache
.Head().ProvidesCount
<< " (" <<
244 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
247 unsigned long Size
= 0;
248 unsigned long Count
= 0;
249 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
250 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
253 Size
+= strlen(Cache
.StrP
+ I
->String
);
255 cout
<< "Total Globbed Strings: " << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
257 unsigned long Slack
= 0;
258 for (int I
= 0; I
!= 7; I
++)
259 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
260 cout
<< "Total Slack space: " << SizeToStr(Slack
) << endl
;
262 unsigned long Total
= 0;
263 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
264 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
265 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
266 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
267 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
268 cout
<< "Total Space Accounted for: " << SizeToStr(Total
) << endl
;
273 // Check - Check some things about the cache /*{{{*/
274 // ---------------------------------------------------------------------
275 /* Debug aide mostly */
276 bool Check(CommandLine
&Cmd
)
278 pkgCache
&Cache
= *GCache
;
279 pkgCache::PkgIterator Pkg
= Cache
.PkgBegin();
280 for (;Pkg
.end() != true; Pkg
++)
282 if (Pkg
.Section() == 0 && Pkg
->VersionList
!= 0)
283 cout
<< "Bad section " << Pkg
.Name() << endl
;
285 for (pkgCache::VerIterator Cur
= Pkg
.VersionList();
286 Cur
.end() != true; Cur
++)
288 if (Cur
->Priority
< 1 || Cur
->Priority
> 5)
289 cout
<< "Bad prio " << Pkg
.Name() << ',' << Cur
.VerStr() << " == " << (int)Cur
->Priority
<< endl
;
295 // Dump - show everything /*{{{*/
296 // ---------------------------------------------------------------------
298 bool Dump(CommandLine
&Cmd
)
300 pkgCache
&Cache
= *GCache
;
301 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
303 cout
<< "Package: " << P
.Name() << endl
;
304 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
306 cout
<< " Version: " << V
.VerStr() << endl
;
307 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
308 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
309 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
313 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
315 cout
<< "File: " << F
.FileName() << endl
;
316 cout
<< " Size: " << F
->Size
<< endl
;
317 cout
<< " ID: " << F
->ID
<< endl
;
318 cout
<< " Flags: " << F
->Flags
<< endl
;
319 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
320 cout
<< " Archive: " << F
.Archive() << endl
;
321 cout
<< " Component: " << F
.Component() << endl
;
322 cout
<< " Version: " << F
.Version() << endl
;
323 cout
<< " Origin: " << F
.Origin() << endl
;
324 cout
<< " Label: " << F
.Label() << endl
;
325 cout
<< " Architecture: " << F
.Architecture() << endl
;
331 // DumpAvail - Print out the available list /*{{{*/
332 // ---------------------------------------------------------------------
333 /* This is needed to make dpkg --merge happy */
334 bool DumpAvail(CommandLine
&Cmd
)
336 pkgCache
&Cache
= *GCache
;
337 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
339 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
341 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
344 if (I
.IsOk() == false)
347 return _error
->Error("Package file %s is out of sync.",I
.FileName());
350 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
351 if (_error
->PendingError() == true)
357 /* Write all of the records from this package file, we search the entire
358 structure to find them */
359 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
361 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
363 if (V
->FileList
== 0)
365 if (V
.FileList().File() != I
)
368 // Read the record and then write it out again.
369 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
370 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
371 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
383 // DoAdd - Perform an adding operation /*{{{*/
384 // ---------------------------------------------------------------------
386 bool DoAdd(CommandLine
&CmdL
)
388 // Make sure there is at least one argument
389 if (CmdL
.FileSize() <= 1)
390 return _error
->Error("You must give at least one file name");
393 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
394 if (_error
->PendingError() == true)
397 DynamicMMap
Map(CacheF
,MMap::Public
);
398 if (_error
->PendingError() == true)
401 OpTextProgress
Progress(*_config
);
402 pkgCacheGenerator
Gen(Map
,Progress
);
403 if (_error
->PendingError() == true)
406 unsigned long Length
= CmdL
.FileSize() - 1;
407 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
409 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
410 Progress
.SubProgress(Length
);
413 FileFd
TagF(*I
,FileFd::ReadOnly
);
414 debListParser
Parser(TagF
);
415 if (_error
->PendingError() == true)
416 return _error
->Error("Problem opening %s",*I
);
418 if (Gen
.SelectFile(*I
) == false)
419 return _error
->Error("Problem with SelectFile");
421 if (Gen
.MergeList(Parser
) == false)
422 return _error
->Error("Problem with MergeList");
426 GCache
= &Gen
.GetCache();
432 // GenCaches - Call the main cache generator /*{{{*/
433 // ---------------------------------------------------------------------
435 bool GenCaches(CommandLine
&Cmd
)
437 OpTextProgress
Progress(*_config
);
441 return pkgMakeStatusCache(List
,Progress
);
444 // ShowHelp - Show a help screen /*{{{*/
445 // ---------------------------------------------------------------------
447 bool ShowHelp(CommandLine
&Cmd
)
449 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
450 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
451 if (_config
->FindB("version") == true)
454 cout
<< "Usage: apt-cache [options] command" << endl
;
455 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
456 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
458 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
459 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
460 cout
<< "It is not ment for ordinary use only as a debug aide." << endl
;
462 cout
<< "Commands:" << endl
;
463 cout
<< " add - Add an package file to the source cache" << endl
;
464 cout
<< " gencaches - Build both the package and source cache" << endl
;
465 cout
<< " showpkg - Show some general information for a single package" << endl
;
466 cout
<< " stats - Show some basic statistics" << endl
;
467 cout
<< " dump - Show the entire file in a terse form" << endl
;
468 cout
<< " dumpavail - Print an available file to stdout" << endl
;
469 cout
<< " unmet - Show unmet dependencies" << endl
;
470 cout
<< " check - Check the cache a bit" << endl
;
472 cout
<< "Options:" << endl
;
473 cout
<< " -h This help text." << endl
;
474 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
475 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
476 cout
<< " -q Disable progress indicator." << endl
;
477 cout
<< " -i Show only important deps for the unmet command." << endl
;
478 cout
<< " -c=? Read this configuration file" << endl
;
479 cout
<< " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl
;
480 cout
<< "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl
;
484 // CacheInitialize - Initialize things for apt-cache /*{{{*/
485 // ---------------------------------------------------------------------
487 void CacheInitialize()
489 _config
->Set("quiet",0);
490 _config
->Set("help",false);
494 int main(int argc
,const char *argv
[])
496 CommandLine::Args Args
[] = {
497 {'h',"help","help",0},
498 {'v',"version","version",0},
499 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
500 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
501 {'q',"quiet","quiet",CommandLine::IntLevel
},
502 {'i',"important","APT::Cache::Important",0},
503 {'c',"config-file",0,CommandLine::ConfigFile
},
504 {'o',"option",0,CommandLine::ArbItem
},
506 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
508 {"gencaches",&GenCaches
},
510 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
513 {"dumpavail",&DumpAvail
},
520 // Parse the command line and initialize the package library
521 CommandLine
CmdL(Args
,_config
);
522 if (pkgInitialize(*_config
) == false ||
523 CmdL
.Parse(argc
,argv
) == false)
525 _error
->DumpErrors();
529 // See if the help should be shown
530 if (_config
->FindB("help") == true ||
531 CmdL
.FileSize() == 0)
532 return ShowHelp(CmdL
);
534 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
536 // Open the cache file
537 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly
);
538 MMap
Map(CacheF
,MMap::Public
| MMap::ReadOnly
);
539 if (_error
->PendingError() == false)
543 if (_error
->PendingError() == false)
544 CmdL
.DispatchArg(CmdsB
);
548 // Print any errors or warnings found during parsing
549 if (_error
->empty() == false)
551 bool Errors
= _error
->PendingError();
552 _error
->DumpErrors();
553 return Errors
== true?100:0;