]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
6c1f972c603b009647a965c6e3f360b539b03e9f
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.26 1999/02/15 04:48:09 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>
35 // UnMet - Show unmet dependencies /*{{{*/
36 // ---------------------------------------------------------------------
38 bool UnMet(CommandLine
&CmdL
)
40 pkgCache
&Cache
= *GCache
;
41 bool Important
= _config
->FindB("APT::Cache::Important",false);
43 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
45 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
48 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
51 pkgCache::DepIterator Start
;
52 pkgCache::DepIterator End
;
55 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
56 End.TargetPkg().Name() << endl;*/
58 // Skip conflicts and replaces
59 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
60 End
->Type
!= pkgCache::Dep::Depends
&&
61 End
->Type
!= pkgCache::Dep::Suggests
&&
62 End
->Type
!= pkgCache::Dep::Recommends
)
65 // Important deps only
66 if (Important
== true)
67 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
68 End
->Type
!= pkgCache::Dep::Depends
)
71 // Verify the or group
73 pkgCache::DepIterator RealStart
= Start
;
76 // See if this dep is Ok
77 pkgCache::Version
**VList
= Start
.AllTargets();
98 cout
<< "Package " << P
.Name() << " version " <<
99 V
.VerStr() << " has an unmet dep:" << endl
;
102 // Print out the dep type
103 cout
<< " " << End
.DepType() << ": ";
109 cout
<< Start
.TargetPkg().Name();
110 if (Start
.TargetVer() != 0)
111 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
127 // DumpPackage - Show a dump of a package record /*{{{*/
128 // ---------------------------------------------------------------------
130 bool DumpPackage(CommandLine
&CmdL
)
132 pkgCache
&Cache
= *GCache
;
133 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
135 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
136 if (Pkg
.end() == true)
138 _error
->Warning("Unable to locate package %s",*I
);
142 cout
<< "Package: " << Pkg
.Name() << endl
;
143 cout
<< "Versions: ";
144 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
146 cout
<< Cur
.VerStr();
147 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
148 cout
<< "(" << Vf
.File().FileName() << ")";
154 cout
<< "Reverse Depends: " << endl
;
155 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
156 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name() << endl
;
158 cout
<< "Dependencies: " << endl
;
159 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
161 cout
<< Cur
.VerStr() << " - ";
162 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
163 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
167 cout
<< "Provides: " << endl
;
168 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
170 cout
<< Cur
.VerStr() << " - ";
171 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
172 cout
<< Prv
.ParentPkg().Name() << " ";
175 cout
<< "Reverse Provides: " << endl
;
176 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
177 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr();
185 // Stats - Dump some nice statistics /*{{{*/
186 // ---------------------------------------------------------------------
188 bool Stats(CommandLine
&Cmd
)
190 pkgCache
&Cache
= *GCache
;
191 cout
<< "Total Package Names : " << Cache
.Head().PackageCount
<< " (" <<
192 SizeToStr(Cache
.Head().PackageCount
*Cache
.Head().PackageSz
) << ')' << endl
;
193 pkgCache::PkgIterator I
= Cache
.PkgBegin();
200 for (;I
.end() != true; I
++)
202 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
208 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
214 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
217 if (I
.ProvidesList()->NextProvides
== 0)
225 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
231 cout
<< " Normal Packages: " << Normal
<< endl
;
232 cout
<< " Pure Virtual Packages: " << Virtual
<< endl
;
233 cout
<< " Single Virtual Packages: " << DVirt
<< endl
;
234 cout
<< " Mixed Virtual Packages: " << NVirt
<< endl
;
235 cout
<< " Missing: " << Missing
<< endl
;
237 cout
<< "Total Distinct Versions: " << Cache
.Head().VersionCount
<< " (" <<
238 SizeToStr(Cache
.Head().VersionCount
*Cache
.Head().VersionSz
) << ')' << endl
;
239 cout
<< "Total Dependencies: " << Cache
.Head().DependsCount
<< " (" <<
240 SizeToStr(Cache
.Head().DependsCount
*Cache
.Head().DependencySz
) << ')' << endl
;
242 cout
<< "Total Ver/File relations: " << Cache
.Head().VerFileCount
<< " (" <<
243 SizeToStr(Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
) << ')' << endl
;
244 cout
<< "Total Provides Mappings: " << Cache
.Head().ProvidesCount
<< " (" <<
245 SizeToStr(Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
) << ')' << endl
;
248 unsigned long Size
= 0;
249 unsigned long Count
= 0;
250 for (pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.Head().StringList
;
251 I
!= Cache
.StringItemP
; I
= Cache
.StringItemP
+ I
->NextItem
)
254 Size
+= strlen(Cache
.StrP
+ I
->String
);
256 cout
<< "Total Globbed Strings: " << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
258 unsigned long Slack
= 0;
259 for (int I
= 0; I
!= 7; I
++)
260 Slack
+= Cache
.Head().Pools
[I
].ItemSize
*Cache
.Head().Pools
[I
].Count
;
261 cout
<< "Total Slack space: " << SizeToStr(Slack
) << endl
;
263 unsigned long Total
= 0;
264 Total
= Slack
+ Size
+ Cache
.Head().DependsCount
*Cache
.Head().DependencySz
+
265 Cache
.Head().VersionCount
*Cache
.Head().VersionSz
+
266 Cache
.Head().PackageCount
*Cache
.Head().PackageSz
+
267 Cache
.Head().VerFileCount
*Cache
.Head().VerFileSz
+
268 Cache
.Head().ProvidesCount
*Cache
.Head().ProvidesSz
;
269 cout
<< "Total Space Accounted for: " << SizeToStr(Total
) << endl
;
274 // Check - Check some things about the cache /*{{{*/
275 // ---------------------------------------------------------------------
276 /* Debug aide mostly */
277 bool Check(CommandLine
&Cmd
)
279 pkgCache
&Cache
= *GCache
;
280 pkgCache::PkgIterator Pkg
= Cache
.PkgBegin();
281 for (;Pkg
.end() != true; Pkg
++)
283 if (Pkg
.Section() == 0 && Pkg
->VersionList
!= 0)
284 cout
<< "Bad section " << Pkg
.Name() << endl
;
286 for (pkgCache::VerIterator Cur
= Pkg
.VersionList();
287 Cur
.end() != true; Cur
++)
289 if (Cur
->Priority
< 1 || Cur
->Priority
> 5)
290 cout
<< "Bad prio " << Pkg
.Name() << ',' << Cur
.VerStr() << " == " << (int)Cur
->Priority
<< endl
;
296 // Dump - show everything /*{{{*/
297 // ---------------------------------------------------------------------
299 bool Dump(CommandLine
&Cmd
)
301 pkgCache
&Cache
= *GCache
;
302 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
304 cout
<< "Package: " << P
.Name() << endl
;
305 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
307 cout
<< " Version: " << V
.VerStr() << endl
;
308 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
309 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
310 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
314 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
316 cout
<< "File: " << F
.FileName() << endl
;
317 cout
<< " Size: " << F
->Size
<< endl
;
318 cout
<< " ID: " << F
->ID
<< endl
;
319 cout
<< " Flags: " << F
->Flags
<< endl
;
320 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
321 cout
<< " Archive: " << F
.Archive() << endl
;
322 cout
<< " Component: " << F
.Component() << endl
;
323 cout
<< " Version: " << F
.Version() << endl
;
324 cout
<< " Origin: " << F
.Origin() << endl
;
325 cout
<< " Label: " << F
.Label() << endl
;
326 cout
<< " Architecture: " << F
.Architecture() << endl
;
332 // GetCandidateVer - Returns the Candidate install version /*{{{*/
333 // ---------------------------------------------------------------------
334 /* This should really use the DepCache or something.. Copied from there. */
335 static pkgCache::VerIterator
GetCandidateVer(pkgCache::PkgIterator Pkg
)
337 /* Not source/not automatic versions cannot be a candidate version
338 unless they are already installed */
339 for (pkgCache::VerIterator I
= Pkg
.VersionList(); I
.end() == false; I
++)
341 if (Pkg
.CurrentVer() == I
)
343 for (pkgCache::VerFileIterator J
= I
.FileList(); J
.end() == false; J
++)
344 if ((J
.File()->Flags
& pkgCache::Flag::NotSource
) == 0 &&
345 (J
.File()->Flags
& pkgCache::Flag::NotAutomatic
) == 0)
349 return pkgCache::VerIterator(*GCache
,0);
352 // DumpAvail - Print out the available list /*{{{*/
353 // ---------------------------------------------------------------------
354 /* This is needed to make dpkg --merge happy */
355 bool DumpAvail(CommandLine
&Cmd
)
357 pkgCache
&Cache
= *GCache
;
358 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
360 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
362 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
365 if (I
.IsOk() == false)
368 return _error
->Error("Package file %s is out of sync.",I
.FileName());
371 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
372 if (_error
->PendingError() == true)
378 /* Write all of the records from this package file, we search the entire
379 structure to find them */
380 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
382 // Find the proper version to use. We should probably use the DepCache.
383 pkgCache::VerIterator V
= GetCandidateVer(P
);
385 if (V
.end() == true || V
.FileList().File() != I
)
388 // Read the record and then write it out again.
389 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
390 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
391 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
402 // DoAdd - Perform an adding operation /*{{{*/
403 // ---------------------------------------------------------------------
405 bool DoAdd(CommandLine
&CmdL
)
407 // Make sure there is at least one argument
408 if (CmdL
.FileSize() <= 1)
409 return _error
->Error("You must give at least one file name");
412 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
413 if (_error
->PendingError() == true)
416 DynamicMMap
Map(CacheF
,MMap::Public
);
417 if (_error
->PendingError() == true)
420 OpTextProgress
Progress(*_config
);
421 pkgCacheGenerator
Gen(Map
,Progress
);
422 if (_error
->PendingError() == true)
425 unsigned long Length
= CmdL
.FileSize() - 1;
426 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
428 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
429 Progress
.SubProgress(Length
);
432 FileFd
TagF(*I
,FileFd::ReadOnly
);
433 debListParser
Parser(TagF
);
434 if (_error
->PendingError() == true)
435 return _error
->Error("Problem opening %s",*I
);
437 if (Gen
.SelectFile(*I
) == false)
438 return _error
->Error("Problem with SelectFile");
440 if (Gen
.MergeList(Parser
) == false)
441 return _error
->Error("Problem with MergeList");
445 GCache
= &Gen
.GetCache();
451 // GenCaches - Call the main cache generator /*{{{*/
452 // ---------------------------------------------------------------------
454 bool GenCaches(CommandLine
&Cmd
)
456 OpTextProgress
Progress(*_config
);
460 return pkgMakeStatusCache(List
,Progress
);
463 // ShowHelp - Show a help screen /*{{{*/
464 // ---------------------------------------------------------------------
466 bool ShowHelp(CommandLine
&Cmd
)
468 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
469 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
470 if (_config
->FindB("version") == true)
473 cout
<< "Usage: apt-cache [options] command" << endl
;
474 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
475 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
477 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
478 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
479 cout
<< "It is not ment for ordinary use only as a debug aide." << endl
;
481 cout
<< "Commands:" << endl
;
482 cout
<< " add - Add an package file to the source cache" << endl
;
483 cout
<< " gencaches - Build both the package and source cache" << endl
;
484 cout
<< " showpkg - Show some general information for a single package" << endl
;
485 cout
<< " stats - Show some basic statistics" << endl
;
486 cout
<< " dump - Show the entire file in a terse form" << endl
;
487 cout
<< " dumpavail - Print an available file to stdout" << endl
;
488 cout
<< " unmet - Show unmet dependencies" << endl
;
489 cout
<< " check - Check the cache a bit" << endl
;
491 cout
<< "Options:" << endl
;
492 cout
<< " -h This help text." << endl
;
493 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
494 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
495 cout
<< " -q Disable progress indicator." << endl
;
496 cout
<< " -i Show only important deps for the unmet command." << endl
;
497 cout
<< " -c=? Read this configuration file" << endl
;
498 cout
<< " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl
;
499 cout
<< "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl
;
503 // CacheInitialize - Initialize things for apt-cache /*{{{*/
504 // ---------------------------------------------------------------------
506 void CacheInitialize()
508 _config
->Set("quiet",0);
509 _config
->Set("help",false);
513 int main(int argc
,const char *argv
[])
515 CommandLine::Args Args
[] = {
516 {'h',"help","help",0},
517 {'v',"version","version",0},
518 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
519 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
520 {'q',"quiet","quiet",CommandLine::IntLevel
},
521 {'i',"important","APT::Cache::Important",0},
522 {'c',"config-file",0,CommandLine::ConfigFile
},
523 {'o',"option",0,CommandLine::ArbItem
},
525 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
527 {"gencaches",&GenCaches
},
529 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
532 {"dumpavail",&DumpAvail
},
539 // Parse the command line and initialize the package library
540 CommandLine
CmdL(Args
,_config
);
541 if (pkgInitialize(*_config
) == false ||
542 CmdL
.Parse(argc
,argv
) == false)
544 _error
->DumpErrors();
548 // See if the help should be shown
549 if (_config
->FindB("help") == true ||
550 CmdL
.FileSize() == 0)
551 return ShowHelp(CmdL
);
553 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
555 // Open the cache file
556 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly
);
557 MMap
Map(CacheF
,MMap::Public
| MMap::ReadOnly
);
558 if (_error
->PendingError() == false)
562 if (_error
->PendingError() == false)
563 CmdL
.DispatchArg(CmdsB
);
567 // Print any errors or warnings found during parsing
568 if (_error
->empty() == false)
570 bool Errors
= _error
->PendingError();
571 _error
->DumpErrors();
572 return Errors
== true?100:0;