]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
Configuration fixes
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
85f72a56 3// $Id: apt-cache.cc,v 1.18 1998/12/10 05:39:53 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;
85f72a56
AL
454 cout << " -q Disable progress indicator." << endl;
455 cout << " -i Show only important deps for the unmet command." << endl;
e1b74f61
AL
456 cout << " -c=? Read this configuration file" << endl;
457 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
458 cout << "See the apt-cache(8) and apt.conf(8) manual pages for more information." << endl;
459 return 100;
460}
461 /*}}}*/
0a8e3465
AL
462// CacheInitialize - Initialize things for apt-cache /*{{{*/
463// ---------------------------------------------------------------------
464/* */
465void CacheInitialize()
466{
467 _config->Set("quiet",0);
468 _config->Set("help",false);
469}
470 /*}}}*/
1164783d 471
08e8f724 472int main(int argc,const char *argv[])
1164783d 473{
08e8f724
AL
474 CommandLine::Args Args[] = {
475 {'h',"help","help",0},
e1b74f61
AL
476 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
477 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
478 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 479 {'i',"important","APT::Cache::Important",0},
e1b74f61
AL
480 {'c',"config-file",0,CommandLine::ConfigFile},
481 {'o',"option",0,CommandLine::ArbItem},
08e8f724 482 {0,0,0,0}};
0a8e3465
AL
483
484 CacheInitialize();
e1b74f61
AL
485
486 // Parse the command line and initialize the package library
487 CommandLine CmdL(Args,_config);
08e8f724 488 if (pkgInitialize(*_config) == false ||
e1b74f61 489 CmdL.Parse(argc,argv) == false)
08e8f724
AL
490 {
491 _error->DumpErrors();
492 return 100;
1164783d 493 }
8efa2a3b 494
e1b74f61
AL
495 // See if the help should be shown
496 if (_config->FindB("help") == true ||
497 CmdL.FileSize() == 0)
498 return ShowHelp();
499
1164783d
AL
500 while (1)
501 {
3d615484
AL
502 if (strcmp(CmdL.FileList[0],"add") == 0)
503 {
504 ShowHelp();
505 break;
506 }
507
e1b74f61 508 if (strcmp(CmdL.FileList[0],"add") == 0)
1164783d 509 {
e1b74f61 510 DoAdd(CmdL);
1164783d
AL
511 break;
512 }
ad00ae81 513
e1b74f61 514 if (strcmp(CmdL.FileList[0],"gencaches") == 0)
880e9be4
AL
515 {
516 GenCaches();
517 break;
518 }
519
ad00ae81 520 // Open the cache file
303a1703 521 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
ad00ae81
AL
522 if (_error->PendingError() == true)
523 break;
524
525 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
526 if (_error->PendingError() == true)
527 break;
528
529 pkgCache Cache(Map);
530 if (_error->PendingError() == true)
531 break;
1164783d 532
e1b74f61 533 if (strcmp(CmdL.FileList[0],"showpkg") == 0)
1164783d 534 {
e1b74f61 535 DumpPackage(Cache,CmdL);
1164783d
AL
536 break;
537 }
538
e1b74f61 539 if (strcmp(CmdL.FileList[0],"stats") == 0)
1164783d 540 {
ad00ae81 541 Stats(Cache);
1164783d
AL
542 break;
543 }
544
e1b74f61 545 if (strcmp(CmdL.FileList[0],"dump") == 0)
1164783d 546 {
ad00ae81 547 Dump(Cache);
1164783d
AL
548 break;
549 }
550
e1b74f61 551 if (strcmp(CmdL.FileList[0],"dumpavail") == 0)
1164783d 552 {
ad00ae81 553 DumpAvail(Cache);
1164783d
AL
554 break;
555 }
cc718e9a
AL
556
557 if (strcmp(CmdL.FileList[0],"unmet") == 0)
558 {
559 UnMet(Cache);
560 break;
561 }
83d89a9f
AL
562
563 if (strcmp(CmdL.FileList[0],"check") == 0)
564 {
565 Check(Cache);
566 break;
567 }
880e9be4 568
e1b74f61 569 _error->Error("Invalid operation %s", CmdL.FileList[0]);
1164783d
AL
570 break;
571 }
572
573 // Print any errors or warnings found during parsing
574 if (_error->empty() == false)
575 {
0a8e3465 576 bool Errors = _error->PendingError();
1164783d 577 _error->DumpErrors();
0a8e3465 578 return Errors == true?100:0;
1164783d
AL
579 }
580
581 return 0;
582}