5bb9db7ccf0f7fa7fb7a4f8133c4c77af0ed059b
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.39 1999/10/18 03:44:39 jgg Exp $
4 /* ######################################################################
5
6 apt-cache - Manages the cache files
7
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 meant as a debug aide.
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>
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>
26 #include <apt-pkg/pkgrecords.h>
27 #include <apt-pkg/srcrecords.h>
28 #include <config.h>
29
30 #include <iostream.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <regex.h>
34 /*}}}*/
35
36 pkgCache *GCache = 0;
37
38 // UnMet - Show unmet dependencies /*{{{*/
39 // ---------------------------------------------------------------------
40 /* */
41 bool UnMet(CommandLine &CmdL)
42 {
43 pkgCache &Cache = *GCache;
44 bool Important = _config->FindB("APT::Cache::Important",false);
45
46 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
47 {
48 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
49 {
50 bool Header = false;
51 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
52 {
53 // Collect or groups
54 pkgCache::DepIterator Start;
55 pkgCache::DepIterator End;
56 D.GlobOr(Start,End);
57
58 /* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
59 End.TargetPkg().Name() << endl;*/
60
61 // Skip conflicts and replaces
62 if (End->Type != pkgCache::Dep::PreDepends &&
63 End->Type != pkgCache::Dep::Depends &&
64 End->Type != pkgCache::Dep::Suggests &&
65 End->Type != pkgCache::Dep::Recommends)
66 continue;
67
68 // Important deps only
69 if (Important == true)
70 if (End->Type != pkgCache::Dep::PreDepends &&
71 End->Type != pkgCache::Dep::Depends)
72 continue;
73
74 // Verify the or group
75 bool OK = false;
76 pkgCache::DepIterator RealStart = Start;
77 do
78 {
79 // See if this dep is Ok
80 pkgCache::Version **VList = Start.AllTargets();
81 if (*VList != 0)
82 {
83 OK = true;
84 delete [] VList;
85 break;
86 }
87 delete [] VList;
88
89 if (Start == End)
90 break;
91 Start++;
92 }
93 while (1);
94
95 // The group is OK
96 if (OK == true)
97 continue;
98
99 // Oops, it failed..
100 if (Header == false)
101 cout << "Package " << P.Name() << " version " <<
102 V.VerStr() << " has an unmet dep:" << endl;
103 Header = true;
104
105 // Print out the dep type
106 cout << " " << End.DepType() << ": ";
107
108 // Show the group
109 Start = RealStart;
110 do
111 {
112 cout << Start.TargetPkg().Name();
113 if (Start.TargetVer() != 0)
114 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
115 ")";
116 if (Start == End)
117 break;
118 cout << " | ";
119 Start++;
120 }
121 while (1);
122
123 cout << endl;
124 }
125 }
126 }
127 return true;
128 }
129 /*}}}*/
130 // DumpPackage - Show a dump of a package record /*{{{*/
131 // ---------------------------------------------------------------------
132 /* */
133 bool DumpPackage(CommandLine &CmdL)
134 {
135 pkgCache &Cache = *GCache;
136 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
137 {
138 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
139 if (Pkg.end() == true)
140 {
141 _error->Warning("Unable to locate package %s",*I);
142 continue;
143 }
144
145 cout << "Package: " << Pkg.Name() << endl;
146 cout << "Versions: ";
147 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
148 {
149 cout << Cur.VerStr();
150 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
151 cout << "(" << Vf.File().FileName() << ")";
152 cout << ',';
153 }
154
155 cout << endl;
156
157 cout << "Reverse Depends: " << endl;
158 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
159 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
160
161 cout << "Dependencies: " << endl;
162 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
163 {
164 cout << Cur.VerStr() << " - ";
165 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
166 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
167 cout << endl;
168 }
169
170 cout << "Provides: " << endl;
171 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
172 {
173 cout << Cur.VerStr() << " - ";
174 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
175 cout << Prv.ParentPkg().Name() << " ";
176 cout << endl;
177 }
178 cout << "Reverse Provides: " << endl;
179 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
180 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;
181 }
182
183 return true;
184 }
185 /*}}}*/
186 // Stats - Dump some nice statistics /*{{{*/
187 // ---------------------------------------------------------------------
188 /* */
189 bool Stats(CommandLine &Cmd)
190 {
191 pkgCache &Cache = *GCache;
192 cout << "Total Package Names : " << Cache.Head().PackageCount << " (" <<
193 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
194 pkgCache::PkgIterator I = Cache.PkgBegin();
195
196 int Normal = 0;
197 int Virtual = 0;
198 int NVirt = 0;
199 int DVirt = 0;
200 int Missing = 0;
201 for (;I.end() != true; I++)
202 {
203 if (I->VersionList != 0 && I->ProvidesList == 0)
204 {
205 Normal++;
206 continue;
207 }
208
209 if (I->VersionList != 0 && I->ProvidesList != 0)
210 {
211 NVirt++;
212 continue;
213 }
214
215 if (I->VersionList == 0 && I->ProvidesList != 0)
216 {
217 // Only 1 provides
218 if (I.ProvidesList()->NextProvides == 0)
219 {
220 DVirt++;
221 }
222 else
223 Virtual++;
224 continue;
225 }
226 if (I->VersionList == 0 && I->ProvidesList == 0)
227 {
228 Missing++;
229 continue;
230 }
231 }
232 cout << " Normal Packages: " << Normal << endl;
233 cout << " Pure Virtual Packages: " << Virtual << endl;
234 cout << " Single Virtual Packages: " << DVirt << endl;
235 cout << " Mixed Virtual Packages: " << NVirt << endl;
236 cout << " Missing: " << Missing << endl;
237
238 cout << "Total Distinct Versions: " << Cache.Head().VersionCount << " (" <<
239 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
240 cout << "Total Dependencies: " << Cache.Head().DependsCount << " (" <<
241 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
242
243 cout << "Total Ver/File relations: " << Cache.Head().VerFileCount << " (" <<
244 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
245 cout << "Total Provides Mappings: " << Cache.Head().ProvidesCount << " (" <<
246 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
247
248 // String list stats
249 unsigned long Size = 0;
250 unsigned long Count = 0;
251 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
252 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
253 {
254 Count++;
255 Size += strlen(Cache.StrP + I->String);
256 }
257 cout << "Total Globbed Strings: " << Count << " (" << SizeToStr(Size) << ')' << endl;
258
259 unsigned long Slack = 0;
260 for (int I = 0; I != 7; I++)
261 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
262 cout << "Total Slack space: " << SizeToStr(Slack) << endl;
263
264 unsigned long Total = 0;
265 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
266 Cache.Head().VersionCount*Cache.Head().VersionSz +
267 Cache.Head().PackageCount*Cache.Head().PackageSz +
268 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
269 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
270 cout << "Total Space Accounted for: " << SizeToStr(Total) << endl;
271
272 return true;
273 }
274 /*}}}*/
275 // Check - Check some things about the cache /*{{{*/
276 // ---------------------------------------------------------------------
277 /* Debug aide mostly */
278 bool Check(CommandLine &Cmd)
279 {
280 pkgCache &Cache = *GCache;
281 pkgCache::PkgIterator Pkg = Cache.PkgBegin();
282 for (;Pkg.end() != true; Pkg++)
283 {
284 if (Pkg.Section() == 0 && Pkg->VersionList != 0)
285 cout << "Bad section " << Pkg.Name() << endl;
286
287 for (pkgCache::VerIterator Cur = Pkg.VersionList();
288 Cur.end() != true; Cur++)
289 {
290 if (Cur->Priority < 1 || Cur->Priority > 5)
291 cout << "Bad prio " << Pkg.Name() << ',' << Cur.VerStr() << " == " << (int)Cur->Priority << endl;
292 }
293 }
294 return true;
295 }
296 /*}}}*/
297 // Dump - show everything /*{{{*/
298 // ---------------------------------------------------------------------
299 /* */
300 bool Dump(CommandLine &Cmd)
301 {
302 pkgCache &Cache = *GCache;
303 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
304 {
305 cout << "Package: " << P.Name() << endl;
306 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
307 {
308 cout << " Version: " << V.VerStr() << endl;
309 cout << " File: " << V.FileList().File().FileName() << endl;
310 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
311 cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
312 }
313 }
314
315 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
316 {
317 cout << "File: " << F.FileName() << endl;
318 cout << " Size: " << F->Size << endl;
319 cout << " ID: " << F->ID << endl;
320 cout << " Flags: " << F->Flags << endl;
321 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
322 cout << " Archive: " << F.Archive() << endl;
323 cout << " Component: " << F.Component() << endl;
324 cout << " Version: " << F.Version() << endl;
325 cout << " Origin: " << F.Origin() << endl;
326 cout << " Label: " << F.Label() << endl;
327 cout << " Architecture: " << F.Architecture() << endl;
328 }
329
330 return true;
331 }
332 /*}}}*/
333 // DumpAvail - Print out the available list /*{{{*/
334 // ---------------------------------------------------------------------
335 /* This is needed to make dpkg --merge happy */
336 bool DumpAvail(CommandLine &Cmd)
337 {
338 pkgCache &Cache = *GCache;
339 unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
340
341 for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
342 {
343 if ((I->Flags & pkgCache::Flag::NotSource) != 0)
344 continue;
345
346 if (I.IsOk() == false)
347 {
348 delete [] Buffer;
349 return _error->Error("Package file %s is out of sync.",I.FileName());
350 }
351
352 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
353 if (_error->PendingError() == true)
354 {
355 delete [] Buffer;
356 return false;
357 }
358
359 /* Write all of the records from this package file, we search the entire
360 structure to find them */
361 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
362 {
363 // Find the proper version to use. We should probably use the DepCache.
364 pkgCache::VerIterator V = Cache.GetCandidateVer(P,false);
365
366 if (V.end() == true || V.FileList().File() != I)
367 continue;
368
369 // Read the record and then write it out again.
370 if (PkgF.Seek(V.FileList()->Offset) == false ||
371 PkgF.Read(Buffer,V.FileList()->Size) == false ||
372 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
373 {
374 delete [] Buffer;
375 return false;
376 }
377 }
378 }
379
380 return true;
381 }
382 /*}}}*/
383 // Depends - Print out a dependency tree /*{{{*/
384 // ---------------------------------------------------------------------
385 /* */
386 bool Depends(CommandLine &CmdL)
387 {
388 pkgCache &Cache = *GCache;
389
390 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
391 {
392 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
393 if (Pkg.end() == true)
394 {
395 _error->Warning("Unable to locate package %s",*I);
396 continue;
397 }
398
399 pkgCache::VerIterator Ver = Pkg.VersionList();
400 if (Ver.end() == true)
401 {
402 cout << '<' << Pkg.Name() << '>' << endl;
403 continue;
404 }
405
406 cout << Pkg.Name() << endl;
407
408 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
409 {
410 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
411 cout << " |";
412 else
413 cout << " ";
414
415 // Show the package
416 pkgCache::PkgIterator Trg = D.TargetPkg();
417 if (Trg->VersionList == 0)
418 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
419 else
420 cout << D.DepType() << ": " << Trg.Name() << endl;
421
422 // Display all solutions
423 pkgCache::Version **List = D.AllTargets();
424 for (pkgCache::Version **I = List; *I != 0; I++)
425 {
426 pkgCache::VerIterator V(Cache,*I);
427 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
428 V->ParentPkg == D->Package)
429 continue;
430 cout << " " << V.ParentPkg().Name() << endl;
431 }
432 delete [] List;
433 }
434 }
435
436 return true;
437 }
438 /*}}}*/
439 // DoAdd - Perform an adding operation /*{{{*/
440 // ---------------------------------------------------------------------
441 /* */
442 bool DoAdd(CommandLine &CmdL)
443 {
444 // Make sure there is at least one argument
445 if (CmdL.FileSize() <= 1)
446 return _error->Error("You must give at least one file name");
447
448 // Open the cache
449 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
450 if (_error->PendingError() == true)
451 return false;
452
453 DynamicMMap Map(CacheF,MMap::Public);
454 if (_error->PendingError() == true)
455 return false;
456
457 OpTextProgress Progress(*_config);
458 pkgCacheGenerator Gen(Map,Progress);
459 if (_error->PendingError() == true)
460 return false;
461
462 unsigned long Length = CmdL.FileSize() - 1;
463 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
464 {
465 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
466 Progress.SubProgress(Length);
467
468 // Do the merge
469 FileFd TagF(*I,FileFd::ReadOnly);
470 debListParser Parser(TagF);
471 if (_error->PendingError() == true)
472 return _error->Error("Problem opening %s",*I);
473
474 if (Gen.SelectFile(*I) == false)
475 return _error->Error("Problem with SelectFile");
476
477 if (Gen.MergeList(Parser) == false)
478 return _error->Error("Problem with MergeList");
479 }
480
481 Progress.Done();
482 GCache = &Gen.GetCache();
483 Stats(CmdL);
484
485 return true;
486 }
487 /*}}}*/
488 // DisplayRecord - Displays the complete record for the package /*{{{*/
489 // ---------------------------------------------------------------------
490 /* This displays the package record from the proper package index file.
491 It is not used by DumpAvail for performance reasons. */
492 bool DisplayRecord(pkgCache::VerIterator V)
493 {
494 // Find an appropriate file
495 pkgCache::VerFileIterator Vf = V.FileList();
496 for (; Vf.end() == false; Vf++)
497 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
498 break;
499 if (Vf.end() == true)
500 Vf = V.FileList();
501
502 // Check and load the package list file
503 pkgCache::PkgFileIterator I = Vf.File();
504 if (I.IsOk() == false)
505 return _error->Error("Package file %s is out of sync.",I.FileName());
506
507 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
508 if (_error->PendingError() == true)
509 return false;
510
511 // Read the record and then write it out again.
512 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize];
513 if (PkgF.Seek(V.FileList()->Offset) == false ||
514 PkgF.Read(Buffer,V.FileList()->Size) == false ||
515 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
516 {
517 delete [] Buffer;
518 return false;
519 }
520
521 delete [] Buffer;
522
523 return true;
524 }
525 /*}}}*/
526 // Search - Perform a search /*{{{*/
527 // ---------------------------------------------------------------------
528 /* This searches the package names and pacakge descriptions for a pattern */
529 bool Search(CommandLine &CmdL)
530 {
531 pkgCache &Cache = *GCache;
532 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
533 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
534
535 // Make sure there is at least one argument
536 if (CmdL.FileSize() != 2)
537 return _error->Error("You must give exactly one pattern");
538
539 // Compile the regex pattern
540 regex_t Pattern;
541 if (regcomp(&Pattern,CmdL.FileList[1],REG_EXTENDED | REG_ICASE |
542 REG_NOSUB) != 0)
543 return _error->Error("Regex compilation error");
544
545 // Create the text record parser
546 pkgRecords Recs(Cache);
547 if (_error->PendingError() == true)
548 return false;
549
550 // Search package names
551 pkgCache::PkgIterator I = Cache.PkgBegin();
552 for (;I.end() != true; I++)
553 {
554 // We search against the install version as that makes the most sense..
555 pkgCache::VerIterator V = Cache.GetCandidateVer(I);
556 if (V.end() == true)
557 continue;
558
559 pkgRecords::Parser &P = Recs.Lookup(V.FileList());
560
561 if (regexec(&Pattern,I.Name(),0,0,0) == 0 ||
562 (NamesOnly == false &&
563 regexec(&Pattern,P.LongDesc().c_str(),0,0,0) == 0))
564 {
565 if (ShowFull == true)
566 DisplayRecord(V);
567 else
568 cout << I.Name() << " - " << P.ShortDesc() << endl;
569 }
570 }
571
572 regfree(&Pattern);
573 return true;
574 }
575 /*}}}*/
576 // ShowPackage - Dump the package record to the screen /*{{{*/
577 // ---------------------------------------------------------------------
578 /* */
579 bool ShowPackage(CommandLine &CmdL)
580 {
581 pkgCache &Cache = *GCache;
582 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
583 {
584 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
585 if (Pkg.end() == true)
586 {
587 _error->Warning("Unable to locate package %s",*I);
588 continue;
589 }
590
591 // Find the proper version to use. We should probably use the DepCache.
592 pkgCache::VerIterator V = Cache.GetCandidateVer(Pkg);
593 if (V.end() == true || V.FileList().end() == true)
594 continue;
595 if (DisplayRecord(V) == false)
596 return false;
597 }
598 return true;
599 }
600 /*}}}*/
601 // ShowSrcPackage - Show source package records /*{{{*/
602 // ---------------------------------------------------------------------
603 /* */
604 bool ShowSrcPackage(CommandLine &CmdL)
605 {
606 pkgSourceList List;
607 List.ReadMainList();
608
609 // Create the text record parsers
610 pkgSrcRecords SrcRecs(List);
611 if (_error->PendingError() == true)
612 return false;
613
614 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
615 {
616 pkgSrcRecords::Parser *Parse;
617 while ((Parse = SrcRecs.Find(*I,false)) != 0)
618 cout << Parse->AsStr();
619 }
620 return true;
621 }
622 /*}}}*/
623 // GenCaches - Call the main cache generator /*{{{*/
624 // ---------------------------------------------------------------------
625 /* */
626 bool GenCaches(CommandLine &Cmd)
627 {
628 OpTextProgress Progress(*_config);
629
630 pkgSourceList List;
631 List.ReadMainList();
632 return pkgMakeStatusCache(List,Progress);
633 }
634 /*}}}*/
635 // ShowHelp - Show a help screen /*{{{*/
636 // ---------------------------------------------------------------------
637 /* */
638 bool ShowHelp(CommandLine &Cmd)
639 {
640 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
641 " compiled on " << __DATE__ << " " << __TIME__ << endl;
642 if (_config->FindB("version") == true)
643 return 100;
644
645 cout << "Usage: apt-cache [options] command" << endl;
646 cout << " apt-cache [options] add file1 [file1 ...]" << endl;
647 cout << " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl;
648 cout << endl;
649 cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl;
650 cout << "cache files stored in " << _config->FindFile("Dir::Cache") << endl;
651 cout << "It is not meant for ordinary use only as a debug aide." << endl;
652 cout << endl;
653 cout << "Commands:" << endl;
654 cout << " add - Add an package file to the source cache" << endl;
655 cout << " gencaches - Build both the package and source cache" << endl;
656 cout << " showpkg - Show some general information for a single package" << endl;
657 cout << " stats - Show some basic statistics" << endl;
658 cout << " dump - Show the entire file in a terse form" << endl;
659 cout << " dumpavail - Print an available file to stdout" << endl;
660 cout << " unmet - Show unmet dependencies" << endl;
661 cout << " check - Check the cache a bit" << endl;
662 cout << " search - Search the package list for a regex pattern" << endl;
663 cout << " show - Show a readable record for the package" << endl;
664 cout << " depends - Show raw dependency information for a package" << endl;
665 cout << endl;
666 cout << "Options:" << endl;
667 cout << " -h This help text." << endl;
668 cout << " -p=? The package cache. [" << _config->FindFile("Dir::Cache::pkgcache") << ']' << endl;
669 cout << " -s=? The source cache. [" << _config->FindFile("Dir::Cache::srcpkgcache") << ']' << endl;
670 cout << " -q Disable progress indicator." << endl;
671 cout << " -i Show only important deps for the unmet command." << endl;
672 cout << " -c=? Read this configuration file" << endl;
673 cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
674 cout << "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl;
675 return 100;
676 }
677 /*}}}*/
678 // CacheInitialize - Initialize things for apt-cache /*{{{*/
679 // ---------------------------------------------------------------------
680 /* */
681 void CacheInitialize()
682 {
683 _config->Set("quiet",0);
684 _config->Set("help",false);
685 }
686 /*}}}*/
687
688 int main(int argc,const char *argv[])
689 {
690 CommandLine::Args Args[] = {
691 {'h',"help","help",0},
692 {'v',"version","version",0},
693 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
694 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
695 {'q',"quiet","quiet",CommandLine::IntLevel},
696 {'i',"important","APT::Cache::Important",0},
697 {'f',"full","APT::Cache::ShowFull",0},
698 {'g',"no-generate","APT::Cache::NoGenerate",0},
699 {0,"names-only","APT::Cache::NamesOnly",0},
700 {'c',"config-file",0,CommandLine::ConfigFile},
701 {'o',"option",0,CommandLine::ArbItem},
702 {0,0,0,0}};
703 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
704 {"add",&DoAdd},
705 {"gencaches",&GenCaches},
706 {"showsrc",&ShowSrcPackage},
707 {0,0}};
708 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
709 {"stats",&Stats},
710 {"dump",&Dump},
711 {"dumpavail",&DumpAvail},
712 {"unmet",&UnMet},
713 {"check",&Check},
714 {"search",&Search},
715 {"depends",&Depends},
716 {"show",&ShowPackage},
717 {0,0}};
718
719 CacheInitialize();
720
721 // Parse the command line and initialize the package library
722 CommandLine CmdL(Args,_config);
723 if (pkgInitialize(*_config) == false ||
724 CmdL.Parse(argc,argv) == false)
725 {
726 _error->DumpErrors();
727 return 100;
728 }
729
730 // See if the help should be shown
731 if (_config->FindB("help") == true ||
732 CmdL.FileSize() == 0)
733 return ShowHelp(CmdL);
734
735 // Deal with stdout not being a tty
736 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
737 _config->Set("quiet","1");
738
739 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
740 {
741 MMap *Map;
742 if (_config->FindB("APT::Cache::NoGenerate",false) == true)
743 {
744 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
745 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
746 }
747 else
748 {
749 // Open the cache file
750 pkgSourceList List;
751 List.ReadMainList();
752
753 // Generate it and map it
754 OpProgress Prog;
755 Map = pkgMakeStatusCacheMem(List,Prog);
756 }
757
758 if (_error->PendingError() == false)
759 {
760 pkgCache Cache(*Map);
761 GCache = &Cache;
762 if (_error->PendingError() == false)
763 CmdL.DispatchArg(CmdsB);
764 }
765 delete Map;
766 }
767
768 // Print any errors or warnings found during parsing
769 if (_error->empty() == false)
770 {
771 bool Errors = _error->PendingError();
772 _error->DumpErrors();
773 return Errors == true?100:0;
774 }
775
776 return 0;
777 }