]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
Spelling fix
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
f826cfaa 3// $Id: apt-cache.cc,v 1.16 1998/12/07 00:34:22 jgg Exp $
1164783d
AL
4/* ######################################################################
5
e1b74f61 6 apt-cache - Manages the cache files
1164783d 7
e1b74f61
AL
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.
1164783d
AL
12
13 Returns 100 on failure, 0 on success.
14
15 ##################################################################### */
16 /*}}}*/
17// Include Files /*{{{*/
18#include <apt-pkg/error.h>
19#include <apt-pkg/pkgcachegen.h>
20#include <apt-pkg/deblistparser.h>
8efa2a3b 21#include <apt-pkg/init.h>
404ec98e 22#include <apt-pkg/progress.h>
880e9be4 23#include <apt-pkg/sourcelist.h>
08e8f724 24#include <apt-pkg/cmndline.h>
f826cfaa 25#include <strutl.h>
1164783d
AL
26
27#include <iostream.h>
e1b74f61 28#include <config.h>
1164783d
AL
29 /*}}}*/
30
cc718e9a
AL
31// UnMet - Show unmet dependencies /*{{{*/
32// ---------------------------------------------------------------------
33/* */
34bool UnMet(pkgCache &Cache)
35{
76fbce56 36 bool Important = _config->FindB("APT::Cache::Important",false);
018f1533 37
cc718e9a
AL
38 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
39 {
40 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
41 {
42 bool Header = false;
018f1533 43 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
44 {
45 // Collect or groups
46 pkgCache::DepIterator Start;
47 pkgCache::DepIterator End;
48 D.GlobOr(Start,End);
49
018f1533
AL
50/* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
51 End.TargetPkg().Name() << endl;*/
52
53 // Skip conflicts and replaces
cc718e9a
AL
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)
58 continue;
59
018f1533
AL
60 // Important deps only
61 if (Important == true)
62 if (End->Type != pkgCache::Dep::PreDepends &&
63 End->Type != pkgCache::Dep::Depends)
64 continue;
65
cc718e9a
AL
66 // Verify the or group
67 bool OK = false;
68 pkgCache::DepIterator RealStart = Start;
69 do
70 {
71 // See if this dep is Ok
72 pkgCache::Version **VList = Start.AllTargets();
73 if (*VList != 0)
74 {
75 OK = true;
76 delete [] VList;
77 break;
78 }
79 delete [] VList;
80
81 if (Start == End)
82 break;
83 Start++;
84 }
85 while (1);
86
87 // The group is OK
88 if (OK == true)
89 continue;
90
91 // Oops, it failed..
92 if (Header == false)
93 cout << "Package " << P.Name() << " version " <<
94 V.VerStr() << " has an unmet dep:" << endl;
95 Header = true;
96
97 // Print out the dep type
98 cout << " " << End.DepType() << ": ";
99
100 // Show the group
101 Start = RealStart;
102 do
103 {
104 cout << Start.TargetPkg().Name();
105 if (Start.TargetVer() != 0)
106 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
107 ")";
108 if (Start == End)
109 break;
110 cout << " | ";
111 Start++;
112 }
113 while (1);
114
115 cout << endl;
116 }
117 }
118 }
119 return true;
120}
121 /*}}}*/
1164783d
AL
122// DumpPackage - Show a dump of a package record /*{{{*/
123// ---------------------------------------------------------------------
124/* */
e1b74f61 125bool DumpPackage(pkgCache &Cache,CommandLine &CmdL)
ad00ae81 126{
e1b74f61 127 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1164783d 128 {
e1b74f61 129 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1164783d
AL
130 if (Pkg.end() == true)
131 {
e1b74f61 132 _error->Warning("Unable to locate package %s",*I);
1164783d
AL
133 continue;
134 }
135
136 cout << "Package: " << Pkg.Name() << endl;
137 cout << "Versions: ";
138 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
03e39e59
AL
139 {
140 cout << Cur.VerStr();
141 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
142 cout << "(" << Vf.File().FileName() << ")";
143 cout << ',';
144 }
145
1164783d
AL
146 cout << endl;
147
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;
151
152 cout << "Dependencies: " << endl;
153 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
154 {
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() << ") ";
158 cout << endl;
159 }
160
161 cout << "Provides: " << endl;
162 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
163 {
164 cout << Cur.VerStr() << " - ";
165 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
166 cout << Prv.ParentPkg().Name() << " ";
167 cout << endl;
8efa2a3b
AL
168 }
169 cout << "Reverse Provides: " << endl;
170 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
171 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr();
172 cout << endl;
03e39e59 173
1164783d
AL
174 }
175
176 return true;
177}
178 /*}}}*/
179// Stats - Dump some nice statistics /*{{{*/
180// ---------------------------------------------------------------------
181/* */
ad00ae81 182bool Stats(pkgCache &Cache)
1164783d 183{
f826cfaa
AL
184 cout << "Total Package Names : " << Cache.Head().PackageCount << " (" <<
185 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
1164783d
AL
186 pkgCache::PkgIterator I = Cache.PkgBegin();
187
188 int Normal = 0;
189 int Virtual = 0;
190 int NVirt = 0;
191 int DVirt = 0;
192 int Missing = 0;
193 for (;I.end() != true; I++)
194 {
195 if (I->VersionList != 0 && I->ProvidesList == 0)
196 {
197 Normal++;
198 continue;
199 }
200
201 if (I->VersionList != 0 && I->ProvidesList != 0)
202 {
203 NVirt++;
204 continue;
205 }
206
207 if (I->VersionList == 0 && I->ProvidesList != 0)
208 {
209 // Only 1 provides
210 if (I.ProvidesList()->NextProvides == 0)
211 {
212 DVirt++;
213 }
214 else
215 Virtual++;
216 continue;
217 }
218 if (I->VersionList == 0 && I->ProvidesList == 0)
219 {
220 Missing++;
221 continue;
222 }
223 }
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;
229
f826cfaa
AL
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;
234
235 cout << "Total Ver/File relations: " << Cache.Head().PackageCount << " (" <<
236 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
237
238 // String list stats
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)
243 {
244 Count++;
245 Size += strlen(Cache.StrP + I->String);
246 }
247 cout << "Total Globbed Strings: " << Count << " (" << SizeToStr(Size) << ')' << endl;
248
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;
253
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;
259
1164783d
AL
260 return true;
261}
262 /*}}}*/
83d89a9f
AL
263// Check - Check some things about the cache /*{{{*/
264// ---------------------------------------------------------------------
265/* Debug aide mostly */
266bool Check(pkgCache &Cache)
267{
268 pkgCache::PkgIterator Pkg = Cache.PkgBegin();
269 for (;Pkg.end() != true; Pkg++)
270 {
271 if (Pkg.Section() == 0 && Pkg->VersionList != 0)
272 cout << "Bad section " << Pkg.Name() << endl;
273
274 for (pkgCache::VerIterator Cur = Pkg.VersionList();
275 Cur.end() != true; Cur++)
276 {
277 if (Cur->Priority < 1 || Cur->Priority > 5)
278 cout << "Bad prio " << Pkg.Name() << ',' << Cur.VerStr() << " == " << (int)Cur->Priority << endl;
279 }
280 }
281 return true;
282}
283 /*}}}*/
1164783d
AL
284// Dump - show everything /*{{{*/
285// ---------------------------------------------------------------------
286/* */
ad00ae81 287bool Dump(pkgCache &Cache)
1164783d 288{
1164783d
AL
289 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
290 {
291 cout << "Package: " << P.Name() << endl;
292 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
293 {
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;
298 }
299 }
300
301 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
302 {
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;
308 }
309
310 return true;
311}
312 /*}}}*/
313// DumpAvail - Print out the available list /*{{{*/
314// ---------------------------------------------------------------------
315/* This is needed to make dpkg --merge happy */
ad00ae81 316bool DumpAvail(pkgCache &Cache)
1164783d 317{
ad00ae81 318 unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
1164783d 319
ad00ae81 320 for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
1164783d 321 {
ad00ae81 322 if ((I->Flags & pkgCache::Flag::NotSource) != 0)
1164783d
AL
323 continue;
324
ad00ae81
AL
325 if (I.IsOk() == false)
326 {
327 delete [] Buffer;
328 return _error->Error("Package file %s is out of sync.",I.FileName());
329 }
1164783d 330
8e06abb2 331 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
ad00ae81 332 if (_error->PendingError() == true)
1164783d 333 {
ad00ae81
AL
334 delete [] Buffer;
335 return false;
336 }
337
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++)
341 {
342 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
1164783d 343 {
ad00ae81
AL
344 if (V->FileList == 0)
345 continue;
346 if (V.FileList().File() != I)
347 continue;
348
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)
353 {
354 delete [] Buffer;
355 return false;
356 }
1164783d 357 }
1164783d 358 }
ad00ae81
AL
359 }
360
361 return true;
362}
363 /*}}}*/
364// DoAdd - Perform an adding operation /*{{{*/
365// ---------------------------------------------------------------------
366/* */
e1b74f61 367bool DoAdd(CommandLine &CmdL)
ad00ae81 368{
e1b74f61
AL
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");
ad00ae81
AL
372
373 // Open the cache
018f1533 374 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
ad00ae81
AL
375 if (_error->PendingError() == true)
376 return false;
377
378 DynamicMMap Map(CacheF,MMap::Public);
379 if (_error->PendingError() == true)
380 return false;
404ec98e 381
0a8e3465 382 OpTextProgress Progress(*_config);
404ec98e 383 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
384 if (_error->PendingError() == true)
385 return false;
386
e1b74f61
AL
387 unsigned long Length = CmdL.FileSize() - 1;
388 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 389 {
e1b74f61 390 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
018f1533
AL
391 Progress.SubProgress(Length);
392
ad00ae81 393 // Do the merge
e1b74f61 394 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
395 debListParser Parser(TagF);
396 if (_error->PendingError() == true)
e1b74f61 397 return _error->Error("Problem opening %s",*I);
ad00ae81 398
e1b74f61 399 if (Gen.SelectFile(*I) == false)
ad00ae81
AL
400 return _error->Error("Problem with SelectFile");
401
402 if (Gen.MergeList(Parser) == false)
403 return _error->Error("Problem with MergeList");
1164783d 404 }
404ec98e
AL
405
406 Progress.Done();
ad00ae81
AL
407 Stats(Gen.GetCache());
408
1164783d
AL
409 return true;
410}
411 /*}}}*/
880e9be4
AL
412// GenCaches - Call the main cache generator /*{{{*/
413// ---------------------------------------------------------------------
414/* */
415bool GenCaches()
416{
0a8e3465
AL
417 OpTextProgress Progress(*_config);
418
880e9be4
AL
419 pkgSourceList List;
420 List.ReadMainList();
0a8e3465 421 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
422}
423 /*}}}*/
e1b74f61
AL
424// ShowHelp - Show a help screen /*{{{*/
425// ---------------------------------------------------------------------
426/* */
427int ShowHelp()
428{
429 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
430 " compiled on " << __DATE__ << " " << __TIME__ << endl;
431
432 cout << "Usage: apt-cache [options] command" << endl;
433 cout << " apt-cache [options] add file1 [file1 ...]" << endl;
0a8e3465 434 cout << " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl;
e1b74f61
AL
435 cout << endl;
436 cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl;
303a1703 437 cout << "cache files stored in " << _config->FindFile("Dir::Cache") << endl;
e1b74f61
AL
438 cout << "It is not ment for ordinary use only as a debug aide." << endl;
439 cout << 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;
cc718e9a 447 cout << " unmet - Show unmet dependencies" << endl;
83d89a9f 448 cout << " check - Check the cache a bit" << endl;
e1b74f61
AL
449 cout << endl;
450 cout << "Options:" << endl;
451 cout << " -h This help text." << endl;
303a1703
AL
452 cout << " -p=? The package cache. [" << _config->FindFile("Dir::Cache::pkgcache") << ']' << endl;
453 cout << " -s=? The source cache. [" << _config->FindFile("Dir::Cache::srcpkgcache") << ']' << endl;
e1b74f61
AL
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;
458 return 100;
459}
460 /*}}}*/
0a8e3465
AL
461// CacheInitialize - Initialize things for apt-cache /*{{{*/
462// ---------------------------------------------------------------------
463/* */
464void CacheInitialize()
465{
466 _config->Set("quiet",0);
467 _config->Set("help",false);
468}
469 /*}}}*/
1164783d 470
08e8f724 471int main(int argc,const char *argv[])
1164783d 472{
08e8f724
AL
473 CommandLine::Args Args[] = {
474 {'h',"help","help",0},
e1b74f61
AL
475 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
476 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
477 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 478 {'i',"important","APT::Cache::Important",0},
e1b74f61
AL
479 {'c',"config-file",0,CommandLine::ConfigFile},
480 {'o',"option",0,CommandLine::ArbItem},
08e8f724 481 {0,0,0,0}};
0a8e3465
AL
482
483 CacheInitialize();
e1b74f61
AL
484
485 // Parse the command line and initialize the package library
486 CommandLine CmdL(Args,_config);
08e8f724 487 if (pkgInitialize(*_config) == false ||
e1b74f61 488 CmdL.Parse(argc,argv) == false)
08e8f724
AL
489 {
490 _error->DumpErrors();
491 return 100;
1164783d 492 }
8efa2a3b 493
e1b74f61
AL
494 // See if the help should be shown
495 if (_config->FindB("help") == true ||
496 CmdL.FileSize() == 0)
497 return ShowHelp();
498
1164783d
AL
499 while (1)
500 {
e1b74f61 501 if (strcmp(CmdL.FileList[0],"add") == 0)
1164783d 502 {
e1b74f61 503 DoAdd(CmdL);
1164783d
AL
504 break;
505 }
ad00ae81 506
e1b74f61 507 if (strcmp(CmdL.FileList[0],"gencaches") == 0)
880e9be4
AL
508 {
509 GenCaches();
510 break;
511 }
512
ad00ae81 513 // Open the cache file
303a1703 514 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
ad00ae81
AL
515 if (_error->PendingError() == true)
516 break;
517
518 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
519 if (_error->PendingError() == true)
520 break;
521
522 pkgCache Cache(Map);
523 if (_error->PendingError() == true)
524 break;
1164783d 525
e1b74f61 526 if (strcmp(CmdL.FileList[0],"showpkg") == 0)
1164783d 527 {
e1b74f61 528 DumpPackage(Cache,CmdL);
1164783d
AL
529 break;
530 }
531
e1b74f61 532 if (strcmp(CmdL.FileList[0],"stats") == 0)
1164783d 533 {
ad00ae81 534 Stats(Cache);
1164783d
AL
535 break;
536 }
537
e1b74f61 538 if (strcmp(CmdL.FileList[0],"dump") == 0)
1164783d 539 {
ad00ae81 540 Dump(Cache);
1164783d
AL
541 break;
542 }
543
e1b74f61 544 if (strcmp(CmdL.FileList[0],"dumpavail") == 0)
1164783d 545 {
ad00ae81 546 DumpAvail(Cache);
1164783d
AL
547 break;
548 }
cc718e9a
AL
549
550 if (strcmp(CmdL.FileList[0],"unmet") == 0)
551 {
552 UnMet(Cache);
553 break;
554 }
83d89a9f
AL
555
556 if (strcmp(CmdL.FileList[0],"check") == 0)
557 {
558 Check(Cache);
559 break;
560 }
880e9be4 561
e1b74f61 562 _error->Error("Invalid operation %s", CmdL.FileList[0]);
1164783d
AL
563 break;
564 }
565
566 // Print any errors or warnings found during parsing
567 if (_error->empty() == false)
568 {
0a8e3465 569 bool Errors = _error->PendingError();
1164783d 570 _error->DumpErrors();
0a8e3465 571 return Errors == true?100:0;
1164783d
AL
572 }
573
574 return 0;
575}