]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
G++ 3.2 fixes
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.60 2003/01/11 07:18:44 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.
10
11 Returns 100 on failure, 0 on success.
12
13 ##################################################################### */
14 /*}}}*/
15 // Include Files /*{{{*/
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/pkgcachegen.h>
18 #include <apt-pkg/init.h>
19 #include <apt-pkg/progress.h>
20 #include <apt-pkg/sourcelist.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/pkgrecords.h>
24 #include <apt-pkg/srcrecords.h>
25 #include <apt-pkg/version.h>
26 #include <apt-pkg/policy.h>
27 #include <apt-pkg/tagfile.h>
28 #include <apt-pkg/algorithms.h>
29 #include <apt-pkg/sptr.h>
30
31 #include <config.h>
32 #include <apti18n.h>
33
34 #include <locale.h>
35 #include <iostream>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <regex.h>
39 #include <stdio.h>
40 /*}}}*/
41
42 using namespace std;
43
44 pkgCache *GCache = 0;
45 pkgSourceList *SrcList = 0;
46
47 // LocalitySort - Sort a version list by package file locality /*{{{*/
48 // ---------------------------------------------------------------------
49 /* */
50 int LocalityCompare(const void *a, const void *b)
51 {
52 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
53 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
54
55 if (A == 0 && B == 0)
56 return 0;
57 if (A == 0)
58 return 1;
59 if (B == 0)
60 return -1;
61
62 if (A->File == B->File)
63 return A->Offset - B->Offset;
64 return A->File - B->File;
65 }
66
67 void LocalitySort(pkgCache::VerFile **begin,
68 unsigned long Count,size_t Size)
69 {
70 qsort(begin,Count,Size,LocalityCompare);
71 }
72 /*}}}*/
73 // UnMet - Show unmet dependencies /*{{{*/
74 // ---------------------------------------------------------------------
75 /* */
76 bool UnMet(CommandLine &CmdL)
77 {
78 pkgCache &Cache = *GCache;
79 bool Important = _config->FindB("APT::Cache::Important",false);
80
81 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
82 {
83 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
84 {
85 bool Header = false;
86 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
87 {
88 // Collect or groups
89 pkgCache::DepIterator Start;
90 pkgCache::DepIterator End;
91 D.GlobOr(Start,End);
92
93 // Skip conflicts and replaces
94 if (End->Type != pkgCache::Dep::PreDepends &&
95 End->Type != pkgCache::Dep::Depends &&
96 End->Type != pkgCache::Dep::Suggests &&
97 End->Type != pkgCache::Dep::Recommends)
98 continue;
99
100 // Important deps only
101 if (Important == true)
102 if (End->Type != pkgCache::Dep::PreDepends &&
103 End->Type != pkgCache::Dep::Depends)
104 continue;
105
106 // Verify the or group
107 bool OK = false;
108 pkgCache::DepIterator RealStart = Start;
109 do
110 {
111 // See if this dep is Ok
112 pkgCache::Version **VList = Start.AllTargets();
113 if (*VList != 0)
114 {
115 OK = true;
116 delete [] VList;
117 break;
118 }
119 delete [] VList;
120
121 if (Start == End)
122 break;
123 Start++;
124 }
125 while (1);
126
127 // The group is OK
128 if (OK == true)
129 continue;
130
131 // Oops, it failed..
132 if (Header == false)
133 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
134 P.Name(),V.VerStr());
135 Header = true;
136
137 // Print out the dep type
138 cout << " " << End.DepType() << ": ";
139
140 // Show the group
141 Start = RealStart;
142 do
143 {
144 cout << Start.TargetPkg().Name();
145 if (Start.TargetVer() != 0)
146 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
147 ")";
148 if (Start == End)
149 break;
150 cout << " | ";
151 Start++;
152 }
153 while (1);
154
155 cout << endl;
156 }
157 }
158 }
159 return true;
160 }
161 /*}}}*/
162 // DumpPackage - Show a dump of a package record /*{{{*/
163 // ---------------------------------------------------------------------
164 /* */
165 bool DumpPackage(CommandLine &CmdL)
166 {
167 pkgCache &Cache = *GCache;
168 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
169 {
170 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
171 if (Pkg.end() == true)
172 {
173 _error->Warning(_("Unable to locate package %s"),*I);
174 continue;
175 }
176
177 cout << "Package: " << Pkg.Name() << endl;
178 cout << "Versions: " << endl;
179 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
180 {
181 cout << Cur.VerStr();
182 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
183 cout << "(" << Vf.File().FileName() << ")";
184 cout << endl;
185 }
186
187 cout << endl;
188
189 cout << "Reverse Depends: " << endl;
190 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
191 {
192 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
193 if (D->Version != 0)
194 cout << ' ' << DeNull(D.TargetVer()) << endl;
195 else
196 cout << endl;
197 }
198
199 cout << "Dependencies: " << endl;
200 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
201 {
202 cout << Cur.VerStr() << " - ";
203 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
204 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
205 cout << endl;
206 }
207
208 cout << "Provides: " << endl;
209 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
210 {
211 cout << Cur.VerStr() << " - ";
212 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
213 cout << Prv.ParentPkg().Name() << " ";
214 cout << endl;
215 }
216 cout << "Reverse Provides: " << endl;
217 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
218 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;
219 }
220
221 return true;
222 }
223 /*}}}*/
224 // Stats - Dump some nice statistics /*{{{*/
225 // ---------------------------------------------------------------------
226 /* */
227 bool Stats(CommandLine &Cmd)
228 {
229 pkgCache &Cache = *GCache;
230 cout << _("Total Package Names : ") << Cache.Head().PackageCount << " (" <<
231 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
232
233 int Normal = 0;
234 int Virtual = 0;
235 int NVirt = 0;
236 int DVirt = 0;
237 int Missing = 0;
238 pkgCache::PkgIterator I = Cache.PkgBegin();
239 for (;I.end() != true; I++)
240 {
241 if (I->VersionList != 0 && I->ProvidesList == 0)
242 {
243 Normal++;
244 continue;
245 }
246
247 if (I->VersionList != 0 && I->ProvidesList != 0)
248 {
249 NVirt++;
250 continue;
251 }
252
253 if (I->VersionList == 0 && I->ProvidesList != 0)
254 {
255 // Only 1 provides
256 if (I.ProvidesList()->NextProvides == 0)
257 {
258 DVirt++;
259 }
260 else
261 Virtual++;
262 continue;
263 }
264 if (I->VersionList == 0 && I->ProvidesList == 0)
265 {
266 Missing++;
267 continue;
268 }
269 }
270 cout << _(" Normal Packages: ") << Normal << endl;
271 cout << _(" Pure Virtual Packages: ") << Virtual << endl;
272 cout << _(" Single Virtual Packages: ") << DVirt << endl;
273 cout << _(" Mixed Virtual Packages: ") << NVirt << endl;
274 cout << _(" Missing: ") << Missing << endl;
275
276 cout << _("Total Distinct Versions: ") << Cache.Head().VersionCount << " (" <<
277 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
278 cout << _("Total Dependencies: ") << Cache.Head().DependsCount << " (" <<
279 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
280
281 cout << _("Total Ver/File relations: ") << Cache.Head().VerFileCount << " (" <<
282 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
283 cout << _("Total Provides Mappings: ") << Cache.Head().ProvidesCount << " (" <<
284 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
285
286 // String list stats
287 unsigned long Size = 0;
288 unsigned long Count = 0;
289 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
290 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
291 {
292 Count++;
293 Size += strlen(Cache.StrP + I->String) + 1;
294 }
295 cout << _("Total Globbed Strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
296
297 unsigned long DepVerSize = 0;
298 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
299 {
300 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
301 {
302 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
303 {
304 if (D->Version != 0)
305 DepVerSize += strlen(D.TargetVer()) + 1;
306 }
307 }
308 }
309 cout << _("Total Dependency Version space: ") << SizeToStr(DepVerSize) << endl;
310
311 unsigned long Slack = 0;
312 for (int I = 0; I != 7; I++)
313 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
314 cout << _("Total Slack space: ") << SizeToStr(Slack) << endl;
315
316 unsigned long Total = 0;
317 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
318 Cache.Head().VersionCount*Cache.Head().VersionSz +
319 Cache.Head().PackageCount*Cache.Head().PackageSz +
320 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
321 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
322 cout << _("Total Space Accounted for: ") << SizeToStr(Total) << endl;
323
324 return true;
325 }
326 /*}}}*/
327 // Dump - show everything /*{{{*/
328 // ---------------------------------------------------------------------
329 /* This is worthless except fer debugging things */
330 bool Dump(CommandLine &Cmd)
331 {
332 pkgCache &Cache = *GCache;
333 cout << "Using Versioning System: " << Cache.VS->Label << endl;
334
335 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
336 {
337 cout << "Package: " << P.Name() << endl;
338 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
339 {
340 cout << " Version: " << V.VerStr() << endl;
341 cout << " File: " << V.FileList().File().FileName() << endl;
342 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
343 cout << " Depends: " << D.TargetPkg().Name() << ' ' <<
344 DeNull(D.TargetVer()) << endl;
345 }
346 }
347
348 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
349 {
350 cout << "File: " << F.FileName() << endl;
351 cout << " Type: " << F.IndexType() << endl;
352 cout << " Size: " << F->Size << endl;
353 cout << " ID: " << F->ID << endl;
354 cout << " Flags: " << F->Flags << endl;
355 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
356 cout << " Archive: " << DeNull(F.Archive()) << endl;
357 cout << " Component: " << DeNull(F.Component()) << endl;
358 cout << " Version: " << DeNull(F.Version()) << endl;
359 cout << " Origin: " << DeNull(F.Origin()) << endl;
360 cout << " Site: " << DeNull(F.Site()) << endl;
361 cout << " Label: " << DeNull(F.Label()) << endl;
362 cout << " Architecture: " << DeNull(F.Architecture()) << endl;
363 }
364
365 return true;
366 }
367 /*}}}*/
368 // DumpAvail - Print out the available list /*{{{*/
369 // ---------------------------------------------------------------------
370 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
371 make this run really fast, perhaps I went a little overboard.. */
372 bool DumpAvail(CommandLine &Cmd)
373 {
374 pkgCache &Cache = *GCache;
375
376 pkgPolicy Plcy(&Cache);
377 if (ReadPinFile(Plcy) == false)
378 return false;
379
380 unsigned long Count = Cache.HeaderP->PackageCount+1;
381 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
382 memset(VFList,0,sizeof(*VFList)*Count);
383
384 // Map versions that we want to write out onto the VerList array.
385 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
386 {
387 if (P->VersionList == 0)
388 continue;
389
390 /* Find the proper version to use. If the policy says there are no
391 possible selections we return the installed version, if available..
392 This prevents dselect from making it obsolete. */
393 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
394 if (V.end() == true)
395 {
396 if (P->CurrentVer == 0)
397 continue;
398 V = P.CurrentVer();
399 }
400
401 pkgCache::VerFileIterator VF = V.FileList();
402 for (; VF.end() == false ; VF++)
403 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
404 break;
405
406 /* Okay, here we have a bit of a problem.. The policy has selected the
407 currently installed package - however it only exists in the
408 status file.. We need to write out something or dselect will mark
409 the package as obsolete! Thus we emit the status file entry, but
410 below we remove the status line to make it valid for the
411 available file. However! We only do this if their do exist *any*
412 non-source versions of the package - that way the dselect obsolete
413 handling works OK. */
414 if (VF.end() == true)
415 {
416 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
417 {
418 for (VF = Cur.FileList(); VF.end() == false; VF++)
419 {
420 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
421 {
422 VF = V.FileList();
423 break;
424 }
425 }
426
427 if (VF.end() == false)
428 break;
429 }
430 }
431
432 VFList[P->ID] = VF;
433 }
434
435 LocalitySort(VFList,Count,sizeof(*VFList));
436
437 // Iterate over all the package files and write them out.
438 char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
439 for (pkgCache::VerFile **J = VFList; *J != 0;)
440 {
441 pkgCache::PkgFileIterator File(Cache,(*J)->File + Cache.PkgFileP);
442 if (File.IsOk() == false)
443 {
444 _error->Error(_("Package file %s is out of sync."),File.FileName());
445 break;
446 }
447
448 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
449 if (_error->PendingError() == true)
450 break;
451
452 /* Write all of the records from this package file, since we
453 already did locality sorting we can now just seek through the
454 file in read order. We apply 1 more optimization here, since often
455 there will be < 1 byte gaps between records (for the \n) we read that
456 into the next buffer and offset a bit.. */
457 unsigned long Pos = 0;
458 for (; *J != 0; J++)
459 {
460 if ((*J)->File + Cache.PkgFileP != File)
461 break;
462
463 const pkgCache::VerFile &VF = **J;
464
465 // Read the record and then write it out again.
466 unsigned long Jitter = VF.Offset - Pos;
467 if (Jitter > 8)
468 {
469 if (PkgF.Seek(VF.Offset) == false)
470 break;
471 Jitter = 0;
472 }
473
474 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
475 break;
476 Buffer[VF.Size + Jitter] = '\n';
477
478 // See above..
479 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
480 {
481 pkgTagSection Tags;
482 TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
483 const char *Zero = 0;
484 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
485 TFRewrite(stdout,Tags,&Zero,RW) == false)
486 {
487 _error->Error("Internal Error, Unable to parse a package record");
488 break;
489 }
490 fputc('\n',stdout);
491 }
492 else
493 {
494 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
495 break;
496 }
497
498 Pos = VF.Offset + VF.Size;
499 }
500
501 fflush(stdout);
502 if (_error->PendingError() == true)
503 break;
504 }
505
506 delete [] Buffer;
507 delete [] VFList;
508 return !_error->PendingError();
509 }
510 /*}}}*/
511 // Depends - Print out a dependency tree /*{{{*/
512 // ---------------------------------------------------------------------
513 /* */
514 bool Depends(CommandLine &CmdL)
515 {
516 pkgCache &Cache = *GCache;
517 SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
518 memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
519
520 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
521 {
522 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
523 if (Pkg.end() == true)
524 {
525 _error->Warning(_("Unable to locate package %s"),*I);
526 continue;
527 }
528 Colours[Pkg->ID] = 1;
529 }
530
531 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
532 bool DidSomething;
533 do
534 {
535 DidSomething = false;
536 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
537 {
538 if (Colours[Pkg->ID] != 1)
539 continue;
540 Colours[Pkg->ID] = 2;
541 DidSomething = true;
542
543 pkgCache::VerIterator Ver = Pkg.VersionList();
544 if (Ver.end() == true)
545 {
546 cout << '<' << Pkg.Name() << '>' << endl;
547 continue;
548 }
549
550 cout << Pkg.Name() << endl;
551
552 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
553 {
554 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
555 cout << " |";
556 else
557 cout << " ";
558
559 // Show the package
560 pkgCache::PkgIterator Trg = D.TargetPkg();
561 if (Trg->VersionList == 0)
562 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
563 else
564 cout << D.DepType() << ": " << Trg.Name() << endl;
565
566 if (Recurse == true)
567 Colours[D.TargetPkg()->ID]++;
568
569 // Display all solutions
570 SPtrArray<pkgCache::Version *> List = D.AllTargets();
571 pkgPrioSortList(Cache,List);
572 for (pkgCache::Version **I = List; *I != 0; I++)
573 {
574 pkgCache::VerIterator V(Cache,*I);
575 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
576 V->ParentPkg == D->Package)
577 continue;
578 cout << " " << V.ParentPkg().Name() << endl;
579
580 if (Recurse == true)
581 Colours[D.ParentPkg()->ID]++;
582 }
583 }
584 }
585 }
586 while (DidSomething == true);
587
588 return true;
589 }
590 /*}}}*/
591 // Dotty - Generate a graph for Dotty /*{{{*/
592 // ---------------------------------------------------------------------
593 /* Dotty is the graphvis program for generating graphs. It is a fairly
594 simple queuing algorithm that just writes dependencies and nodes.
595 http://www.research.att.com/sw/tools/graphviz/ */
596 bool Dotty(CommandLine &CmdL)
597 {
598 pkgCache &Cache = *GCache;
599 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
600
601 /* Normal packages are boxes
602 Pure Provides are triangles
603 Mixed are diamonds
604 Hexagons are missing packages*/
605 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
606
607 /* Initialize the list of packages to show.
608 1 = To Show
609 2 = To Show no recurse
610 3 = Emitted no recurse
611 4 = Emitted
612 0 = None */
613 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
614 enum TheFlags {ForceNR=(1<<0)};
615 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
616 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
617 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
618
619 // Show everything if no arguments given
620 if (CmdL.FileList[1] == 0)
621 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
622 Show[I] = ToShow;
623 else
624 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
625 Show[I] = None;
626 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
627
628 // Map the shapes
629 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
630 {
631 if (Pkg->VersionList == 0)
632 {
633 // Missing
634 if (Pkg->ProvidesList == 0)
635 ShapeMap[Pkg->ID] = 0;
636 else
637 ShapeMap[Pkg->ID] = 1;
638 }
639 else
640 {
641 // Normal
642 if (Pkg->ProvidesList == 0)
643 ShapeMap[Pkg->ID] = 2;
644 else
645 ShapeMap[Pkg->ID] = 3;
646 }
647 }
648
649 // Load the list of packages from the command line into the show list
650 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
651 {
652 // Process per-package flags
653 string P = *I;
654 bool Force = false;
655 if (P.length() > 3)
656 {
657 if (P.end()[-1] == '^')
658 {
659 Force = true;
660 P.erase(P.end()-1);
661 }
662
663 if (P.end()[-1] == ',')
664 P.erase(P.end()-1);
665 }
666
667 // Locate the package
668 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
669 if (Pkg.end() == true)
670 {
671 _error->Warning(_("Unable to locate package %s"),*I);
672 continue;
673 }
674 Show[Pkg->ID] = ToShow;
675
676 if (Force == true)
677 Flags[Pkg->ID] |= ForceNR;
678 }
679
680 // Little header
681 printf("digraph packages {\n");
682 printf("concentrate=true;\n");
683 printf("size=\"30,40\";\n");
684
685 bool Act = true;
686 while (Act == true)
687 {
688 Act = false;
689 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
690 {
691 // See we need to show this package
692 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
693 continue;
694
695 // Colour as done
696 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
697 {
698 // Pure Provides and missing packages have no deps!
699 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
700 Show[Pkg->ID] = Done;
701 else
702 Show[Pkg->ID] = DoneNR;
703 }
704 else
705 Show[Pkg->ID] = Done;
706 Act = true;
707
708 // No deps to map out
709 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
710 continue;
711
712 pkgCache::VerIterator Ver = Pkg.VersionList();
713 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
714 {
715 // See if anything can meet this dep
716 // Walk along the actual package providing versions
717 bool Hit = false;
718 pkgCache::PkgIterator DPkg = D.TargetPkg();
719 for (pkgCache::VerIterator I = DPkg.VersionList();
720 I.end() == false && Hit == false; I++)
721 {
722 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
723 Hit = true;
724 }
725
726 // Follow all provides
727 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
728 I.end() == false && Hit == false; I++)
729 {
730 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
731 Hit = true;
732 }
733
734 // Only graph critical deps
735 if (D.IsCritical() == true)
736 {
737 printf("\"%s\" -> \"%s\"",Pkg.Name(),D.TargetPkg().Name());
738
739 // Colour the node for recursion
740 if (Show[D.TargetPkg()->ID] <= DoneNR)
741 {
742 /* If a conflicts does not meet anything in the database
743 then show the relation but do not recurse */
744 if (Hit == false &&
745 (D->Type == pkgCache::Dep::Conflicts ||
746 D->Type == pkgCache::Dep::Obsoletes))
747 {
748 if (Show[D.TargetPkg()->ID] == None &&
749 Show[D.TargetPkg()->ID] != ToShow)
750 Show[D.TargetPkg()->ID] = ToShowNR;
751 }
752 else
753 {
754 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
755 Show[D.TargetPkg()->ID] = ToShowNR;
756 else
757 Show[D.TargetPkg()->ID] = ToShow;
758 }
759 }
760
761 // Edge colour
762 switch(D->Type)
763 {
764 case pkgCache::Dep::Conflicts:
765 case pkgCache::Dep::Obsoletes:
766 printf("[color=springgreen];\n");
767 break;
768
769 case pkgCache::Dep::PreDepends:
770 printf("[color=blue];\n");
771 break;
772
773 default:
774 printf(";\n");
775 break;
776 }
777 }
778 }
779 }
780 }
781
782 /* Draw the box colours after the fact since we can not tell what colour
783 they should be until everything is finished drawing */
784 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
785 {
786 if (Show[Pkg->ID] < DoneNR)
787 continue;
788
789 // Orange box for early recursion stoppage
790 if (Show[Pkg->ID] == DoneNR)
791 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.Name(),
792 Shapes[ShapeMap[Pkg->ID]]);
793 else
794 printf("\"%s\" [shape=%s];\n",Pkg.Name(),
795 Shapes[ShapeMap[Pkg->ID]]);
796 }
797
798 printf("}\n");
799 return true;
800 }
801 /*}}}*/
802 // DoAdd - Perform an adding operation /*{{{*/
803 // ---------------------------------------------------------------------
804 /* */
805 bool DoAdd(CommandLine &CmdL)
806 {
807 return _error->Error("Unimplemented");
808 #if 0
809 // Make sure there is at least one argument
810 if (CmdL.FileSize() <= 1)
811 return _error->Error("You must give at least one file name");
812
813 // Open the cache
814 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
815 if (_error->PendingError() == true)
816 return false;
817
818 DynamicMMap Map(CacheF,MMap::Public);
819 if (_error->PendingError() == true)
820 return false;
821
822 OpTextProgress Progress(*_config);
823 pkgCacheGenerator Gen(Map,Progress);
824 if (_error->PendingError() == true)
825 return false;
826
827 unsigned long Length = CmdL.FileSize() - 1;
828 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
829 {
830 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
831 Progress.SubProgress(Length);
832
833 // Do the merge
834 FileFd TagF(*I,FileFd::ReadOnly);
835 debListParser Parser(TagF);
836 if (_error->PendingError() == true)
837 return _error->Error("Problem opening %s",*I);
838
839 if (Gen.SelectFile(*I,"") == false)
840 return _error->Error("Problem with SelectFile");
841
842 if (Gen.MergeList(Parser) == false)
843 return _error->Error("Problem with MergeList");
844 }
845
846 Progress.Done();
847 GCache = &Gen.GetCache();
848 Stats(CmdL);
849
850 return true;
851 #endif
852 }
853 /*}}}*/
854 // DisplayRecord - Displays the complete record for the package /*{{{*/
855 // ---------------------------------------------------------------------
856 /* This displays the package record from the proper package index file.
857 It is not used by DumpAvail for performance reasons. */
858 bool DisplayRecord(pkgCache::VerIterator V)
859 {
860 // Find an appropriate file
861 pkgCache::VerFileIterator Vf = V.FileList();
862 for (; Vf.end() == false; Vf++)
863 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
864 break;
865 if (Vf.end() == true)
866 Vf = V.FileList();
867
868 // Check and load the package list file
869 pkgCache::PkgFileIterator I = Vf.File();
870 if (I.IsOk() == false)
871 return _error->Error(_("Package file %s is out of sync."),I.FileName());
872
873 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
874 if (_error->PendingError() == true)
875 return false;
876
877 // Read the record and then write it out again.
878 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
879 Buffer[V.FileList()->Size] = '\n';
880 if (PkgF.Seek(V.FileList()->Offset) == false ||
881 PkgF.Read(Buffer,V.FileList()->Size) == false ||
882 write(STDOUT_FILENO,Buffer,V.FileList()->Size+1) != V.FileList()->Size+1)
883 {
884 delete [] Buffer;
885 return false;
886 }
887
888 delete [] Buffer;
889
890 return true;
891 }
892 /*}}}*/
893 // Search - Perform a search /*{{{*/
894 // ---------------------------------------------------------------------
895 /* This searches the package names and pacakge descriptions for a pattern */
896 struct ExVerFile
897 {
898 pkgCache::VerFile *Vf;
899 bool NameMatch;
900 };
901
902 bool Search(CommandLine &CmdL)
903 {
904 pkgCache &Cache = *GCache;
905 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
906 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
907 unsigned NumPatterns = CmdL.FileSize() -1;
908
909 pkgDepCache::Policy Plcy;
910
911 // Make sure there is at least one argument
912 if (NumPatterns < 1)
913 return _error->Error(_("You must give exactly one pattern"));
914
915 // Compile the regex pattern
916 regex_t *Patterns = new regex_t[NumPatterns];
917 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
918 for (unsigned I = 0; I != NumPatterns; I++)
919 {
920 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
921 REG_NOSUB) != 0)
922 {
923 for (; I != 0; I--)
924 regfree(&Patterns[I]);
925 return _error->Error("Regex compilation error");
926 }
927 }
928
929 // Create the text record parser
930 pkgRecords Recs(Cache);
931 if (_error->PendingError() == true)
932 {
933 for (unsigned I = 0; I != NumPatterns; I++)
934 regfree(&Patterns[I]);
935 return false;
936 }
937
938 ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
939 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
940
941 // Map versions that we want to write out onto the VerList array.
942 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
943 {
944 VFList[P->ID].NameMatch = NumPatterns != 0;
945 for (unsigned I = 0; I != NumPatterns; I++)
946 {
947 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
948 VFList[P->ID].NameMatch &= true;
949 else
950 VFList[P->ID].NameMatch = false;
951 }
952
953 // Doing names only, drop any that dont match..
954 if (NamesOnly == true && VFList[P->ID].NameMatch == false)
955 continue;
956
957 // Find the proper version to use.
958 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
959 if (V.end() == false)
960 VFList[P->ID].Vf = V.FileList();
961 }
962
963 // Include all the packages that provide matching names too
964 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
965 {
966 if (VFList[P->ID].NameMatch == false)
967 continue;
968
969 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
970 {
971 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
972 if (V.end() == false)
973 {
974 VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
975 VFList[Prv.OwnerPkg()->ID].NameMatch = true;
976 }
977 }
978 }
979
980 LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
981
982 // Iterate over all the version records and check them
983 for (ExVerFile *J = VFList; J->Vf != 0; J++)
984 {
985 pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
986
987 bool Match = true;
988 if (J->NameMatch == false)
989 {
990 string LongDesc = P.LongDesc();
991 Match = NumPatterns != 0;
992 for (unsigned I = 0; I != NumPatterns; I++)
993 {
994 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
995 Match &= true;
996 else
997 Match = false;
998 }
999 }
1000
1001 if (Match == true)
1002 {
1003 if (ShowFull == true)
1004 {
1005 const char *Start;
1006 const char *End;
1007 P.GetRec(Start,End);
1008 fwrite(Start,End-Start,1,stdout);
1009 putc('\n',stdout);
1010 }
1011 else
1012 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1013 }
1014 }
1015
1016 delete [] VFList;
1017 for (unsigned I = 0; I != NumPatterns; I++)
1018 regfree(&Patterns[I]);
1019 if (ferror(stdout))
1020 return _error->Error("Write to stdout failed");
1021 return true;
1022 }
1023 /*}}}*/
1024 // ShowPackage - Dump the package record to the screen /*{{{*/
1025 // ---------------------------------------------------------------------
1026 /* */
1027 bool ShowPackage(CommandLine &CmdL)
1028 {
1029 pkgCache &Cache = *GCache;
1030 pkgDepCache::Policy Plcy;
1031
1032 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1033 {
1034 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1035 if (Pkg.end() == true)
1036 {
1037 _error->Warning(_("Unable to locate package %s"),*I);
1038 continue;
1039 }
1040
1041 // Find the proper version to use.
1042 if (_config->FindB("APT::Cache::AllVersions","true") == true)
1043 {
1044 pkgCache::VerIterator V;
1045 for (V = Pkg.VersionList(); V.end() == false; V++)
1046 {
1047 if (DisplayRecord(V) == false)
1048 return false;
1049 }
1050 }
1051 else
1052 {
1053 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1054 if (V.end() == true || V.FileList().end() == true)
1055 continue;
1056 if (DisplayRecord(V) == false)
1057 return false;
1058 }
1059 }
1060 return true;
1061 }
1062 /*}}}*/
1063 // ShowPkgNames - Show package names /*{{{*/
1064 // ---------------------------------------------------------------------
1065 /* This does a prefix match on the first argument */
1066 bool ShowPkgNames(CommandLine &CmdL)
1067 {
1068 pkgCache &Cache = *GCache;
1069 pkgCache::PkgIterator I = Cache.PkgBegin();
1070 bool All = _config->FindB("APT::Cache::AllNames","false");
1071
1072 if (CmdL.FileList[1] != 0)
1073 {
1074 for (;I.end() != true; I++)
1075 {
1076 if (All == false && I->VersionList == 0)
1077 continue;
1078
1079 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1080 cout << I.Name() << endl;
1081 }
1082
1083 return true;
1084 }
1085
1086 // Show all pkgs
1087 for (;I.end() != true; I++)
1088 {
1089 if (All == false && I->VersionList == 0)
1090 continue;
1091 cout << I.Name() << endl;
1092 }
1093
1094 return true;
1095 }
1096 /*}}}*/
1097 // ShowSrcPackage - Show source package records /*{{{*/
1098 // ---------------------------------------------------------------------
1099 /* */
1100 bool ShowSrcPackage(CommandLine &CmdL)
1101 {
1102 pkgSourceList List;
1103 List.ReadMainList();
1104
1105 // Create the text record parsers
1106 pkgSrcRecords SrcRecs(List);
1107 if (_error->PendingError() == true)
1108 return false;
1109
1110 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1111 {
1112 SrcRecs.Restart();
1113
1114 pkgSrcRecords::Parser *Parse;
1115 while ((Parse = SrcRecs.Find(*I,false)) != 0)
1116 cout << Parse->AsStr() << endl;;
1117 }
1118 return true;
1119 }
1120 /*}}}*/
1121 // Policy - Show the results of the preferences file /*{{{*/
1122 // ---------------------------------------------------------------------
1123 /* */
1124 bool Policy(CommandLine &CmdL)
1125 {
1126 if (SrcList == 0)
1127 return _error->Error("Generate must be enabled for this function");
1128
1129 pkgCache &Cache = *GCache;
1130 pkgPolicy Plcy(&Cache);
1131 if (ReadPinFile(Plcy) == false)
1132 return false;
1133
1134 // Print out all of the package files
1135 if (CmdL.FileList[1] == 0)
1136 {
1137 cout << _("Package Files:") << endl;
1138 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1139 {
1140 // Locate the associated index files so we can derive a description
1141 pkgIndexFile *Indx;
1142 if (SrcList->FindIndex(F,Indx) == false &&
1143 _system->FindIndex(F,Indx) == false)
1144 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1145 printf(_("%4i %s\n"),
1146 Plcy.GetPriority(F),Indx->Describe(true).c_str());
1147
1148 // Print the reference information for the package
1149 string Str = F.RelStr();
1150 if (Str.empty() == false)
1151 printf(" release %s\n",F.RelStr().c_str());
1152 if (F.Site() != 0 && F.Site()[0] != 0)
1153 printf(" origin %s\n",F.Site());
1154 }
1155
1156 // Show any packages have explicit pins
1157 cout << _("Pinned Packages:") << endl;
1158 pkgCache::PkgIterator I = Cache.PkgBegin();
1159 for (;I.end() != true; I++)
1160 {
1161 if (Plcy.GetPriority(I) == 0)
1162 continue;
1163
1164 // Print the package name and the version we are forcing to
1165 cout << " " << I.Name() << " -> ";
1166
1167 pkgCache::VerIterator V = Plcy.GetMatch(I);
1168 if (V.end() == true)
1169 cout << _("(not found)") << endl;
1170 else
1171 cout << V.VerStr() << endl;
1172 }
1173
1174 return true;
1175 }
1176
1177 // Print out detailed information for each package
1178 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1179 {
1180 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1181 if (Pkg.end() == true)
1182 {
1183 _error->Warning(_("Unable to locate package %s"),*I);
1184 continue;
1185 }
1186
1187 cout << Pkg.Name() << ":" << endl;
1188
1189 // Installed version
1190 cout << _(" Installed: ");
1191 if (Pkg->CurrentVer == 0)
1192 cout << _("(none)") << endl;
1193 else
1194 cout << Pkg.CurrentVer().VerStr() << endl;
1195
1196 // Candidate Version
1197 cout << _(" Candidate: ");
1198 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1199 if (V.end() == true)
1200 cout << _("(none)") << endl;
1201 else
1202 cout << V.VerStr() << endl;
1203
1204 // Pinned version
1205 if (Plcy.GetPriority(Pkg) != 0)
1206 {
1207 cout << _(" Package Pin: ");
1208 V = Plcy.GetMatch(Pkg);
1209 if (V.end() == true)
1210 cout << _("(not found)") << endl;
1211 else
1212 cout << V.VerStr() << endl;
1213 }
1214
1215 // Show the priority tables
1216 cout << _(" Version Table:") << endl;
1217 for (V = Pkg.VersionList(); V.end() == false; V++)
1218 {
1219 if (Pkg.CurrentVer() == V)
1220 cout << " *** " << V.VerStr();
1221 else
1222 cout << " " << V.VerStr();
1223 cout << " " << Plcy.GetPriority(Pkg) << endl;
1224 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1225 {
1226 // Locate the associated index files so we can derive a description
1227 pkgIndexFile *Indx;
1228 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1229 _system->FindIndex(VF.File(),Indx) == false)
1230 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1231 printf(_(" %4i %s\n"),Plcy.GetPriority(VF.File()),
1232 Indx->Describe(true).c_str());
1233 }
1234 }
1235 }
1236
1237 return true;
1238 }
1239 /*}}}*/
1240 // GenCaches - Call the main cache generator /*{{{*/
1241 // ---------------------------------------------------------------------
1242 /* */
1243 bool GenCaches(CommandLine &Cmd)
1244 {
1245 OpTextProgress Progress(*_config);
1246
1247 pkgSourceList List;
1248 if (List.ReadMainList() == false)
1249 return false;
1250 return pkgMakeStatusCache(List,Progress);
1251 }
1252 /*}}}*/
1253 // ShowHelp - Show a help screen /*{{{*/
1254 // ---------------------------------------------------------------------
1255 /* */
1256 bool ShowHelp(CommandLine &Cmd)
1257 {
1258 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1259 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
1260
1261 cout <<
1262 _("Usage: apt-cache [options] command\n"
1263 " apt-cache [options] add file1 [file1 ...]\n"
1264 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1265 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1266 "\n"
1267 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1268 "cache files, and query information from them\n"
1269 "\n"
1270 "Commands:\n"
1271 " add - Add an package file to the source cache\n"
1272 " gencaches - Build both the package and source cache\n"
1273 " showpkg - Show some general information for a single package\n"
1274 " showsrc - Show source records\n"
1275 " stats - Show some basic statistics\n"
1276 " dump - Show the entire file in a terse form\n"
1277 " dumpavail - Print an available file to stdout\n"
1278 " unmet - Show unmet dependencies\n"
1279 " search - Search the package list for a regex pattern\n"
1280 " show - Show a readable record for the package\n"
1281 " depends - Show raw dependency information for a package\n"
1282 " pkgnames - List the names of all packages\n"
1283 " dotty - Generate package graphs for GraphVis\n"
1284 " policy - Show policy settings\n"
1285 "\n"
1286 "Options:\n"
1287 " -h This help text.\n"
1288 " -p=? The package cache.\n"
1289 " -s=? The source cache.\n"
1290 " -q Disable progress indicator.\n"
1291 " -i Show only important deps for the unmet command.\n"
1292 " -c=? Read this configuration file\n"
1293 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1294 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1295 return true;
1296 }
1297 /*}}}*/
1298 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1299 // ---------------------------------------------------------------------
1300 /* */
1301 void CacheInitialize()
1302 {
1303 _config->Set("quiet",0);
1304 _config->Set("help",false);
1305 }
1306 /*}}}*/
1307
1308 int main(int argc,const char *argv[])
1309 {
1310 CommandLine::Args Args[] = {
1311 {'h',"help","help",0},
1312 {'v',"version","version",0},
1313 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1314 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1315 {'q',"quiet","quiet",CommandLine::IntLevel},
1316 {'i',"important","APT::Cache::Important",0},
1317 {'f',"full","APT::Cache::ShowFull",0},
1318 {'g',"generate","APT::Cache::Generate",0},
1319 {'a',"all-versions","APT::Cache::AllVersions",0},
1320 {0,"names-only","APT::Cache::NamesOnly",0},
1321 {'n',"all-names","APT::Cache::AllNames",0},
1322 {0,"recurse","APT::Cache::RecurseDepends",0},
1323 {'c',"config-file",0,CommandLine::ConfigFile},
1324 {'o',"option",0,CommandLine::ArbItem},
1325 {0,0,0,0}};
1326 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1327 {"add",&DoAdd},
1328 {"gencaches",&GenCaches},
1329 {"showsrc",&ShowSrcPackage},
1330 {0,0}};
1331 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1332 {"stats",&Stats},
1333 {"dump",&Dump},
1334 {"dumpavail",&DumpAvail},
1335 {"unmet",&UnMet},
1336 {"search",&Search},
1337 {"depends",&Depends},
1338 {"dotty",&Dotty},
1339 {"show",&ShowPackage},
1340 {"pkgnames",&ShowPkgNames},
1341 {"policy",&Policy},
1342 {0,0}};
1343
1344 CacheInitialize();
1345
1346 // Set up gettext support
1347 setlocale(LC_ALL,"");
1348 textdomain(PACKAGE);
1349
1350 // Parse the command line and initialize the package library
1351 CommandLine CmdL(Args,_config);
1352 if (pkgInitConfig(*_config) == false ||
1353 CmdL.Parse(argc,argv) == false ||
1354 pkgInitSystem(*_config,_system) == false)
1355 {
1356 _error->DumpErrors();
1357 return 100;
1358 }
1359
1360 // See if the help should be shown
1361 if (_config->FindB("help") == true ||
1362 CmdL.FileSize() == 0)
1363 {
1364 ShowHelp(CmdL);
1365 return 0;
1366 }
1367
1368 // Deal with stdout not being a tty
1369 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1370 _config->Set("quiet","1");
1371
1372 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
1373 {
1374 MMap *Map = 0;
1375 if (_config->FindB("APT::Cache::Generate",true) == false)
1376 {
1377 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
1378 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
1379 }
1380 else
1381 {
1382 // Open the cache file
1383 SrcList = new pkgSourceList;
1384 SrcList->ReadMainList();
1385
1386 // Generate it and map it
1387 OpProgress Prog;
1388 pkgMakeStatusCache(*SrcList,Prog,&Map,true);
1389 }
1390
1391 if (_error->PendingError() == false)
1392 {
1393 pkgCache Cache(Map);
1394 GCache = &Cache;
1395 if (_error->PendingError() == false)
1396 CmdL.DispatchArg(CmdsB);
1397 }
1398 delete Map;
1399 }
1400
1401 // Print any errors or warnings found during parsing
1402 if (_error->empty() == false)
1403 {
1404 bool Errors = _error->PendingError();
1405 _error->DumpErrors();
1406 return Errors == true?100:0;
1407 }
1408
1409 return 0;
1410 }