]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.23 1999/01/30 02:12:53 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>
33 // UnMet - Show unmet dependencies /*{{{*/
34 // ---------------------------------------------------------------------
36 bool UnMet(CommandLine
&CmdL
)
38 pkgCache
&Cache
= *GCache
;
39 bool Important
= _config
->FindB("APT::Cache::Important",false);
41 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
43 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
46 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
49 pkgCache::DepIterator Start
;
50 pkgCache::DepIterator End
;
53 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
54 End.TargetPkg().Name() << endl;*/
56 // Skip conflicts and replaces
57 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
58 End
->Type
!= pkgCache::Dep::Depends
&&
59 End
->Type
!= pkgCache::Dep::Suggests
&&
60 End
->Type
!= pkgCache::Dep::Recommends
)
63 // Important deps only
64 if (Important
== true)
65 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
66 End
->Type
!= pkgCache::Dep::Depends
)
69 // Verify the or group
71 pkgCache::DepIterator RealStart
= Start
;
74 // See if this dep is Ok
75 pkgCache::Version
**VList
= Start
.AllTargets();
96 cout
<< "Package " << P
.Name() << " version " <<
97 V
.VerStr() << " has an unmet dep:" << endl
;
100 // Print out the dep type
101 cout
<< " " << End
.DepType() << ": ";
107 cout
<< Start
.TargetPkg().Name();
108 if (Start
.TargetVer() != 0)
109 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
125 // DumpPackage - Show a dump of a package record /*{{{*/
126 // ---------------------------------------------------------------------
128 bool DumpPackage(CommandLine
&CmdL
)
130 pkgCache
&Cache
= *GCache
;
131 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
133 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
134 if (Pkg
.end() == true)
136 _error
->Warning("Unable to locate package %s",*I
);
140 cout
<< "Package: " << Pkg
.Name() << endl
;
141 cout
<< "Versions: ";
142 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
144 cout
<< Cur
.VerStr();
145 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
146 cout
<< "(" << Vf
.File().FileName() << ")";
152 cout
<< "Reverse Depends: " << endl
;
153 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
154 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name() << endl
;
156 cout
<< "Dependencies: " << endl
;
157 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
159 cout
<< Cur
.VerStr() << " - ";
160 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
161 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
165 cout
<< "Provides: " << endl
;
166 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
168 cout
<< Cur
.VerStr() << " - ";
169 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
170 cout
<< Prv
.ParentPkg().Name() << " ";
173 cout
<< "Reverse Provides: " << endl
;
174 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
175 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr();
183 // Stats - Dump some nice statistics /*{{{*/
184 // ---------------------------------------------------------------------
186 bool Stats(CommandLine
&Cmd
)
188 pkgCache
&Cache
= *GCache
;
189 cout
<< "Total Package Names : " << Cache
.Head().PackageCount
<< " (" <<
190 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
191 pkgCache::PkgIterator I
= Cache
.PkgBegin();
198 for (;I
.end() != true; I
++)
200 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
206 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
212 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
215 if (I
.ProvidesList()->NextProvides
== 0)
223 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
229 cout
<< " Normal Packages: " << Normal
<< endl
;
230 cout
<< " Pure Virtual Packages: " << Virtual
<< endl
;
231 cout
<< " Single Virtual Packages: " << DVirt
<< endl
;
232 cout
<< " Mixed Virtual Packages: " << NVirt
<< endl
;
233 cout
<< " Missing: " << Missing
<< endl
;
235 cout
<< "Total Distinct Versions: " << Cache
.Head().VersionCount
<< " (" <<
236 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
237 cout
<< "Total Dependencies: " << Cache
.Head().DependsCount
<< " (" <<
238 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
240 cout
<< "Total Ver/File relations: " << Cache
.Head().VerFileCount
<< " (" <<
241 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
242 cout
<< "Total Provides Mappings: " << Cache
.Head().ProvidesCount
<< " (" <<
243 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
246 unsigned long Size
= 0;
247 unsigned long Count
= 0;
248 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
249 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
252 Size
+= strlen(Cache
.StrP
+ I
->String
);
254 cout
<< "Total Globbed Strings: " << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
256 unsigned long Slack
= 0;
257 for (int I
= 0; I
!= 7; I
++)
258 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
259 cout
<< "Total Slack space: " << SizeToStr(Slack
) << endl
;
261 unsigned long Total
= 0;
262 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
263 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
264 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
265 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
266 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
267 cout
<< "Total Space Accounted for: " << SizeToStr(Total
) << endl
;
272 // Check - Check some things about the cache /*{{{*/
273 // ---------------------------------------------------------------------
274 /* Debug aide mostly */
275 bool Check(CommandLine
&Cmd
)
277 pkgCache
&Cache
= *GCache
;
278 pkgCache::PkgIterator Pkg
= Cache
.PkgBegin();
279 for (;Pkg
.end() != true; Pkg
++)
281 if (Pkg
.Section() == 0 && Pkg
->VersionList
!= 0)
282 cout
<< "Bad section " << Pkg
.Name() << endl
;
284 for (pkgCache::VerIterator Cur
= Pkg
.VersionList();
285 Cur
.end() != true; Cur
++)
287 if (Cur
->Priority
< 1 || Cur
->Priority
> 5)
288 cout
<< "Bad prio " << Pkg
.Name() << ',' << Cur
.VerStr() << " == " << (int)Cur
->Priority
<< endl
;
294 // Dump - show everything /*{{{*/
295 // ---------------------------------------------------------------------
297 bool Dump(CommandLine
&Cmd
)
299 pkgCache
&Cache
= *GCache
;
300 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
302 cout
<< "Package: " << P
.Name() << endl
;
303 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
305 cout
<< " Version: " << V
.VerStr() << endl
;
306 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
307 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
308 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
312 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
314 cout
<< "File: " << F
.FileName() << endl
;
315 cout
<< " Size: " << F
->Size
<< endl
;
316 cout
<< " ID: " << F
->ID
<< endl
;
317 cout
<< " Flags: " << F
->Flags
<< endl
;
318 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
319 cout
<< " Archive: " << F
.Archive() << endl
;
320 cout
<< " Component: " << F
.Component() << endl
;
321 cout
<< " Version: " << F
.Version() << endl
;
322 cout
<< " Origin: " << F
.Origin() << endl
;
323 cout
<< " Label: " << F
.Label() << endl
;
324 cout
<< " Architecture: " << F
.Architecture() << endl
;
330 // DumpAvail - Print out the available list /*{{{*/
331 // ---------------------------------------------------------------------
332 /* This is needed to make dpkg --merge happy */
333 bool DumpAvail(CommandLine
&Cmd
)
335 pkgCache
&Cache
= *GCache
;
336 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
338 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
340 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
343 if (I
.IsOk() == false)
346 return _error
->Error("Package file %s is out of sync.",I
.FileName());
349 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
350 if (_error
->PendingError() == true)
356 /* Write all of the records from this package file, we search the entire
357 structure to find them */
358 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
360 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
362 if (V
->FileList
== 0)
364 if (V
.FileList().File() != I
)
367 // Read the record and then write it out again.
368 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
369 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
370 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
382 // DoAdd - Perform an adding operation /*{{{*/
383 // ---------------------------------------------------------------------
385 bool DoAdd(CommandLine
&CmdL
)
387 // Make sure there is at least one argument
388 if (CmdL
.FileSize() <= 1)
389 return _error
->Error("You must give at least one file name");
392 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
393 if (_error
->PendingError() == true)
396 DynamicMMap
Map(CacheF
,MMap::Public
);
397 if (_error
->PendingError() == true)
400 OpTextProgress
Progress(*_config
);
401 pkgCacheGenerator
Gen(Map
,Progress
);
402 if (_error
->PendingError() == true)
405 unsigned long Length
= CmdL
.FileSize() - 1;
406 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
408 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
409 Progress
.SubProgress(Length
);
412 FileFd
TagF(*I
,FileFd::ReadOnly
);
413 debListParser
Parser(TagF
);
414 if (_error
->PendingError() == true)
415 return _error
->Error("Problem opening %s",*I
);
417 if (Gen
.SelectFile(*I
) == false)
418 return _error
->Error("Problem with SelectFile");
420 if (Gen
.MergeList(Parser
) == false)
421 return _error
->Error("Problem with MergeList");
425 GCache
= &Gen
.GetCache();
431 // GenCaches - Call the main cache generator /*{{{*/
432 // ---------------------------------------------------------------------
434 bool GenCaches(CommandLine
&Cmd
)
436 OpTextProgress
Progress(*_config
);
440 return pkgMakeStatusCache(List
,Progress
);
443 // ShowHelp - Show a help screen /*{{{*/
444 // ---------------------------------------------------------------------
446 bool ShowHelp(CommandLine
&Cmd
)
448 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
449 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
450 if (_config
->FindB("version") == true)
453 cout
<< "Usage: apt-cache [options] command" << endl
;
454 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
455 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
457 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
458 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
459 cout
<< "It is not ment for ordinary use only as a debug aide." << endl
;
461 cout
<< "Commands:" << endl
;
462 cout
<< " add - Add an package file to the source cache" << endl
;
463 cout
<< " gencaches - Build both the package and source cache" << endl
;
464 cout
<< " showpkg - Show some general information for a single package" << endl
;
465 cout
<< " stats - Show some basic statistics" << endl
;
466 cout
<< " dump - Show the entire file in a terse form" << endl
;
467 cout
<< " dumpavail - Print an available file to stdout" << endl
;
468 cout
<< " unmet - Show unmet dependencies" << endl
;
469 cout
<< " check - Check the cache a bit" << endl
;
471 cout
<< "Options:" << endl
;
472 cout
<< " -h This help text." << endl
;
473 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
474 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
475 cout
<< " -q Disable progress indicator." << endl
;
476 cout
<< " -i Show only important deps for the unmet command." << endl
;
477 cout
<< " -c=? Read this configuration file" << endl
;
478 cout
<< " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl
;
479 cout
<< "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl
;
483 // CacheInitialize - Initialize things for apt-cache /*{{{*/
484 // ---------------------------------------------------------------------
486 void CacheInitialize()
488 _config
->Set("quiet",0);
489 _config
->Set("help",false);
493 int main(int argc
,const char *argv
[])
495 CommandLine::Args Args
[] = {
496 {'h',"help","help",0},
497 {'v',"version","version",0},
498 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
499 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
500 {'q',"quiet","quiet",CommandLine::IntLevel
},
501 {'i',"important","APT::Cache::Important",0},
502 {'c',"config-file",0,CommandLine::ConfigFile
},
503 {'o',"option",0,CommandLine::ArbItem
},
505 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
507 {"gencaches",&GenCaches
},
509 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
512 {"dumpavail",&DumpAvail
},
519 // Parse the command line and initialize the package library
520 CommandLine
CmdL(Args
,_config
);
521 if (pkgInitialize(*_config
) == false ||
522 CmdL
.Parse(argc
,argv
) == false)
524 _error
->DumpErrors();
528 // See if the help should be shown
529 if (_config
->FindB("help") == true ||
530 CmdL
.FileSize() == 0)
531 return ShowHelp(CmdL
);
533 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
535 // Open the cache file
536 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly
);
537 MMap
Map(CacheF
,MMap::Public
| MMap::ReadOnly
);
538 if (_error
->PendingError() == false)
542 if (_error
->PendingError() == false)
543 CmdL
.DispatchArg(CmdsB
);
547 // Print any errors or warnings found during parsing
548 if (_error
->empty() == false)
550 bool Errors
= _error
->PendingError();
551 _error
->DumpErrors();
552 return Errors
== true?100:0;