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