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