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