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