]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.16 1998/12/07 00:34:22 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>
31 // UnMet - Show unmet dependencies /*{{{*/
32 // ---------------------------------------------------------------------
34 bool UnMet(pkgCache
&Cache
)
36 bool Important
= _config
->FindB("APT::Cache::Important",false);
38 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
40 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
43 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
46 pkgCache::DepIterator Start
;
47 pkgCache::DepIterator End
;
50 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
51 End.TargetPkg().Name() << endl;*/
53 // Skip conflicts and replaces
54 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
55 End
->Type
!= pkgCache::Dep::Depends
&&
56 End
->Type
!= pkgCache::Dep::Suggests
&&
57 End
->Type
!= pkgCache::Dep::Recommends
)
60 // Important deps only
61 if (Important
== true)
62 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
63 End
->Type
!= pkgCache::Dep::Depends
)
66 // Verify the or group
68 pkgCache::DepIterator RealStart
= Start
;
71 // See if this dep is Ok
72 pkgCache::Version
**VList
= Start
.AllTargets();
93 cout
<< "Package " << P
.Name() << " version " <<
94 V
.VerStr() << " has an unmet dep:" << endl
;
97 // Print out the dep type
98 cout
<< " " << End
.DepType() << ": ";
104 cout
<< Start
.TargetPkg().Name();
105 if (Start
.TargetVer() != 0)
106 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
122 // DumpPackage - Show a dump of a package record /*{{{*/
123 // ---------------------------------------------------------------------
125 bool DumpPackage(pkgCache
&Cache
,CommandLine
&CmdL
)
127 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
129 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
130 if (Pkg
.end() == true)
132 _error
->Warning("Unable to locate package %s",*I
);
136 cout
<< "Package: " << Pkg
.Name() << endl
;
137 cout
<< "Versions: ";
138 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
140 cout
<< Cur
.VerStr();
141 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
142 cout
<< "(" << Vf
.File().FileName() << ")";
148 cout
<< "Reverse Depends: " << endl
;
149 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
150 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name() << endl
;
152 cout
<< "Dependencies: " << endl
;
153 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
155 cout
<< Cur
.VerStr() << " - ";
156 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
157 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
161 cout
<< "Provides: " << endl
;
162 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
164 cout
<< Cur
.VerStr() << " - ";
165 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
166 cout
<< Prv
.ParentPkg().Name() << " ";
169 cout
<< "Reverse Provides: " << endl
;
170 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
171 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr();
179 // Stats - Dump some nice statistics /*{{{*/
180 // ---------------------------------------------------------------------
182 bool Stats(pkgCache
&Cache
)
184 cout
<< "Total Package Names : " << Cache
.Head().PackageCount
<< " (" <<
185 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
186 pkgCache::PkgIterator I
= Cache
.PkgBegin();
193 for (;I
.end() != true; I
++)
195 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
201 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
207 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
210 if (I
.ProvidesList()->NextProvides
== 0)
218 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
224 cout
<< " Normal Packages: " << Normal
<< endl
;
225 cout
<< " Pure Virtual Packages: " << Virtual
<< endl
;
226 cout
<< " Single Virtual Packages: " << DVirt
<< endl
;
227 cout
<< " Mixed Virtual Packages: " << NVirt
<< endl
;
228 cout
<< " Missing: " << Missing
<< endl
;
230 cout
<< "Total Distinct Versions: " << Cache
.Head().VersionCount
<< " (" <<
231 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
232 cout
<< "Total Dependencies: " << Cache
.Head().DependsCount
<< " (" <<
233 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
235 cout
<< "Total Ver/File relations: " << Cache
.Head().PackageCount
<< " (" <<
236 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
239 unsigned long Size
= 0;
240 unsigned long Count
= 0;
241 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
242 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
245 Size
+= strlen(Cache
.StrP
+ I
->String
);
247 cout
<< "Total Globbed Strings: " << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
249 unsigned long Slack
= 0;
250 for (int I
= 0; I
!= 7; I
++)
251 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
252 cout
<< "Total Slack space: " << SizeToStr(Slack
) << endl
;
254 unsigned long Total
= 0;
255 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
256 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
257 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
;
258 cout
<< "Total Space Accounted for: " << SizeToStr(Total
) << endl
;
263 // Check - Check some things about the cache /*{{{*/
264 // ---------------------------------------------------------------------
265 /* Debug aide mostly */
266 bool Check(pkgCache
&Cache
)
268 pkgCache::PkgIterator Pkg
= Cache
.PkgBegin();
269 for (;Pkg
.end() != true; Pkg
++)
271 if (Pkg
.Section() == 0 && Pkg
->VersionList
!= 0)
272 cout
<< "Bad section " << Pkg
.Name() << endl
;
274 for (pkgCache::VerIterator Cur
= Pkg
.VersionList();
275 Cur
.end() != true; Cur
++)
277 if (Cur
->Priority
< 1 || Cur
->Priority
> 5)
278 cout
<< "Bad prio " << Pkg
.Name() << ',' << Cur
.VerStr() << " == " << (int)Cur
->Priority
<< endl
;
284 // Dump - show everything /*{{{*/
285 // ---------------------------------------------------------------------
287 bool Dump(pkgCache
&Cache
)
289 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
291 cout
<< "Package: " << P
.Name() << endl
;
292 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
294 cout
<< " Version: " << V
.VerStr() << endl
;
295 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
296 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
297 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
301 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
303 cout
<< "File: " << F
.FileName() << endl
;
304 cout
<< " Size: " << F
->Size
<< endl
;
305 cout
<< " ID: " << F
->ID
<< endl
;
306 cout
<< " Flags: " << F
->Flags
<< endl
;
307 cout
<< " Time: " << ctime(&F
->mtime
) << endl
;
313 // DumpAvail - Print out the available list /*{{{*/
314 // ---------------------------------------------------------------------
315 /* This is needed to make dpkg --merge happy */
316 bool DumpAvail(pkgCache
&Cache
)
318 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
320 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
322 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
325 if (I
.IsOk() == false)
328 return _error
->Error("Package file %s is out of sync.",I
.FileName());
331 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
332 if (_error
->PendingError() == true)
338 /* Write all of the records from this package file, we search the entire
339 structure to find them */
340 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
342 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
344 if (V
->FileList
== 0)
346 if (V
.FileList().File() != I
)
349 // Read the record and then write it out again.
350 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
351 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
352 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
364 // DoAdd - Perform an adding operation /*{{{*/
365 // ---------------------------------------------------------------------
367 bool DoAdd(CommandLine
&CmdL
)
369 // Make sure there is at least one argument
370 if (CmdL
.FileSize() <= 1)
371 return _error
->Error("You must give at least one file name");
374 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
375 if (_error
->PendingError() == true)
378 DynamicMMap
Map(CacheF
,MMap::Public
);
379 if (_error
->PendingError() == true)
382 OpTextProgress
Progress(*_config
);
383 pkgCacheGenerator
Gen(Map
,Progress
);
384 if (_error
->PendingError() == true)
387 unsigned long Length
= CmdL
.FileSize() - 1;
388 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
390 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
391 Progress
.SubProgress(Length
);
394 FileFd
TagF(*I
,FileFd::ReadOnly
);
395 debListParser
Parser(TagF
);
396 if (_error
->PendingError() == true)
397 return _error
->Error("Problem opening %s",*I
);
399 if (Gen
.SelectFile(*I
) == false)
400 return _error
->Error("Problem with SelectFile");
402 if (Gen
.MergeList(Parser
) == false)
403 return _error
->Error("Problem with MergeList");
407 Stats(Gen
.GetCache());
412 // GenCaches - Call the main cache generator /*{{{*/
413 // ---------------------------------------------------------------------
417 OpTextProgress
Progress(*_config
);
421 return pkgMakeStatusCache(List
,Progress
);
424 // ShowHelp - Show a help screen /*{{{*/
425 // ---------------------------------------------------------------------
429 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
430 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
432 cout
<< "Usage: apt-cache [options] command" << endl
;
433 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
434 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
436 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
437 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
438 cout
<< "It is not ment for ordinary use only as a debug aide." << endl
;
440 cout
<< "Commands:" << endl
;
441 cout
<< " add - Add an package file to the source cache" << endl
;
442 cout
<< " gencaches - Build both the package and source cache" << endl
;
443 cout
<< " showpkg - Show some general information for a single package" << endl
;
444 cout
<< " stats - Show some basic statistics" << endl
;
445 cout
<< " dump - Show the entire file in a terse form" << endl
;
446 cout
<< " dumpavail - Print an available file to stdout" << endl
;
447 cout
<< " unmet - Show unmet dependencies" << endl
;
448 cout
<< " check - Check the cache a bit" << endl
;
450 cout
<< "Options:" << endl
;
451 cout
<< " -h This help text." << endl
;
452 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
453 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
454 cout
<< " -q Disable progress indicator. " << endl
;
455 cout
<< " -c=? Read this configuration file" << endl
;
456 cout
<< " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl
;
457 cout
<< "See the apt-cache(8) and apt.conf(8) manual pages for more information." << endl
;
461 // CacheInitialize - Initialize things for apt-cache /*{{{*/
462 // ---------------------------------------------------------------------
464 void CacheInitialize()
466 _config
->Set("quiet",0);
467 _config
->Set("help",false);
471 int main(int argc
,const char *argv
[])
473 CommandLine::Args Args
[] = {
474 {'h',"help","help",0},
475 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
476 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
477 {'q',"quiet","quiet",CommandLine::IntLevel
},
478 {'i',"important","APT::Cache::Important",0},
479 {'c',"config-file",0,CommandLine::ConfigFile
},
480 {'o',"option",0,CommandLine::ArbItem
},
485 // Parse the command line and initialize the package library
486 CommandLine
CmdL(Args
,_config
);
487 if (pkgInitialize(*_config
) == false ||
488 CmdL
.Parse(argc
,argv
) == false)
490 _error
->DumpErrors();
494 // See if the help should be shown
495 if (_config
->FindB("help") == true ||
496 CmdL
.FileSize() == 0)
501 if (strcmp(CmdL
.FileList
[0],"add") == 0)
507 if (strcmp(CmdL
.FileList
[0],"gencaches") == 0)
513 // Open the cache file
514 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly
);
515 if (_error
->PendingError() == true)
518 MMap
Map(CacheF
,MMap::Public
| MMap::ReadOnly
);
519 if (_error
->PendingError() == true)
523 if (_error
->PendingError() == true)
526 if (strcmp(CmdL
.FileList
[0],"showpkg") == 0)
528 DumpPackage(Cache
,CmdL
);
532 if (strcmp(CmdL
.FileList
[0],"stats") == 0)
538 if (strcmp(CmdL
.FileList
[0],"dump") == 0)
544 if (strcmp(CmdL
.FileList
[0],"dumpavail") == 0)
550 if (strcmp(CmdL
.FileList
[0],"unmet") == 0)
556 if (strcmp(CmdL
.FileList
[0],"check") == 0)
562 _error
->Error("Invalid operation %s", CmdL
.FileList
[0]);
566 // Print any errors or warnings found during parsing
567 if (_error
->empty() == false)
569 bool Errors
= _error
->PendingError();
570 _error
->DumpErrors();
571 return Errors
== true?100:0;