]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
Be quiet in apt.post{inst,rm}.
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.62 2003/04/27 01:32:48 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 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
592
593 // xvcg - Generate a graph for xvcg /*{{{*/
594 // ---------------------------------------------------------------------
595 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
596
597 bool XVcg(CommandLine &CmdL)
598 {
599 pkgCache &Cache = *GCache;
600 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
601
602 /* Normal packages are boxes
603 Pure Provides are triangles
604 Mixed are diamonds
605 rhomb are missing packages*/
606 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
607
608 /* Initialize the list of packages to show.
609 1 = To Show
610 2 = To Show no recurse
611 3 = Emitted no recurse
612 4 = Emitted
613 0 = None */
614 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
615 enum TheFlags {ForceNR=(1<<0)};
616 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
617 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
618 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
619
620 // Show everything if no arguments given
621 if (CmdL.FileList[1] == 0)
622 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
623 Show[I] = ToShow;
624 else
625 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
626 Show[I] = None;
627 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
628
629 // Map the shapes
630 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
631 {
632 if (Pkg->VersionList == 0)
633 {
634 // Missing
635 if (Pkg->ProvidesList == 0)
636 ShapeMap[Pkg->ID] = 0;
637 else
638 ShapeMap[Pkg->ID] = 1;
639 }
640 else
641 {
642 // Normal
643 if (Pkg->ProvidesList == 0)
644 ShapeMap[Pkg->ID] = 2;
645 else
646 ShapeMap[Pkg->ID] = 3;
647 }
648 }
649
650 // Load the list of packages from the command line into the show list
651 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
652 {
653 // Process per-package flags
654 string P = *I;
655 bool Force = false;
656 if (P.length() > 3)
657 {
658 if (P.end()[-1] == '^')
659 {
660 Force = true;
661 P.erase(P.end()-1);
662 }
663
664 if (P.end()[-1] == ',')
665 P.erase(P.end()-1);
666 }
667
668 // Locate the package
669 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
670 if (Pkg.end() == true)
671 {
672 _error->Warning(_("Unable to locate package %s"),*I);
673 continue;
674 }
675 Show[Pkg->ID] = ToShow;
676
677 if (Force == true)
678 Flags[Pkg->ID] |= ForceNR;
679 }
680
681 // Little header
682 cout << "graph: { title: \"packages\"" << endl <<
683 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
684 "layout_downfactor: 8" << endl;
685
686 bool Act = true;
687 while (Act == true)
688 {
689 Act = false;
690 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
691 {
692 // See we need to show this package
693 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
694 continue;
695
696 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
697
698 // Colour as done
699 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
700 {
701 // Pure Provides and missing packages have no deps!
702 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
703 Show[Pkg->ID] = Done;
704 else
705 Show[Pkg->ID] = DoneNR;
706 }
707 else
708 Show[Pkg->ID] = Done;
709 Act = true;
710
711 // No deps to map out
712 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
713 continue;
714
715 pkgCache::VerIterator Ver = Pkg.VersionList();
716 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
717 {
718 // See if anything can meet this dep
719 // Walk along the actual package providing versions
720 bool Hit = false;
721 pkgCache::PkgIterator DPkg = D.TargetPkg();
722 for (pkgCache::VerIterator I = DPkg.VersionList();
723 I.end() == false && Hit == false; I++)
724 {
725 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
726 Hit = true;
727 }
728
729 // Follow all provides
730 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
731 I.end() == false && Hit == false; I++)
732 {
733 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
734 Hit = true;
735 }
736
737
738 // Only graph critical deps
739 if (D.IsCritical() == true)
740 {
741 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.Name(), D.TargetPkg().Name() );
742
743 // Colour the node for recursion
744 if (Show[D.TargetPkg()->ID] <= DoneNR)
745 {
746 /* If a conflicts does not meet anything in the database
747 then show the relation but do not recurse */
748 if (Hit == false &&
749 (D->Type == pkgCache::Dep::Conflicts ||
750 D->Type == pkgCache::Dep::Obsoletes))
751 {
752 if (Show[D.TargetPkg()->ID] == None &&
753 Show[D.TargetPkg()->ID] != ToShow)
754 Show[D.TargetPkg()->ID] = ToShowNR;
755 }
756 else
757 {
758 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
759 Show[D.TargetPkg()->ID] = ToShowNR;
760 else
761 Show[D.TargetPkg()->ID] = ToShow;
762 }
763 }
764
765 // Edge colour
766 switch(D->Type)
767 {
768 case pkgCache::Dep::Conflicts:
769 printf("label: \"conflicts\" color: lightgreen }\n");
770 break;
771 case pkgCache::Dep::Obsoletes:
772 printf("label: \"obsoletes\" color: lightgreen }\n");
773 break;
774
775 case pkgCache::Dep::PreDepends:
776 printf("label: \"predepends\" color: blue }\n");
777 break;
778
779 default:
780 printf("}\n");
781 break;
782 }
783 }
784 }
785 }
786 }
787
788 /* Draw the box colours after the fact since we can not tell what colour
789 they should be until everything is finished drawing */
790 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
791 {
792 if (Show[Pkg->ID] < DoneNR)
793 continue;
794
795 if (Show[Pkg->ID] == DoneNR)
796 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.Name(), Pkg.Name(),
797 Shapes[ShapeMap[Pkg->ID]]);
798 else
799 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.Name(), Pkg.Name(),
800 Shapes[ShapeMap[Pkg->ID]]);
801
802 }
803
804 printf("}\n");
805 return true;
806 }
807 /*}}}*/
808
809
810 // Dotty - Generate a graph for Dotty /*{{{*/
811 // ---------------------------------------------------------------------
812 /* Dotty is the graphvis program for generating graphs. It is a fairly
813 simple queuing algorithm that just writes dependencies and nodes.
814 http://www.research.att.com/sw/tools/graphviz/ */
815 bool Dotty(CommandLine &CmdL)
816 {
817 pkgCache &Cache = *GCache;
818 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
819
820 /* Normal packages are boxes
821 Pure Provides are triangles
822 Mixed are diamonds
823 Hexagons are missing packages*/
824 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
825
826 /* Initialize the list of packages to show.
827 1 = To Show
828 2 = To Show no recurse
829 3 = Emitted no recurse
830 4 = Emitted
831 0 = None */
832 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
833 enum TheFlags {ForceNR=(1<<0)};
834 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
835 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
836 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
837
838 // Show everything if no arguments given
839 if (CmdL.FileList[1] == 0)
840 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
841 Show[I] = ToShow;
842 else
843 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
844 Show[I] = None;
845 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
846
847 // Map the shapes
848 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
849 {
850 if (Pkg->VersionList == 0)
851 {
852 // Missing
853 if (Pkg->ProvidesList == 0)
854 ShapeMap[Pkg->ID] = 0;
855 else
856 ShapeMap[Pkg->ID] = 1;
857 }
858 else
859 {
860 // Normal
861 if (Pkg->ProvidesList == 0)
862 ShapeMap[Pkg->ID] = 2;
863 else
864 ShapeMap[Pkg->ID] = 3;
865 }
866 }
867
868 // Load the list of packages from the command line into the show list
869 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
870 {
871 // Process per-package flags
872 string P = *I;
873 bool Force = false;
874 if (P.length() > 3)
875 {
876 if (P.end()[-1] == '^')
877 {
878 Force = true;
879 P.erase(P.end()-1);
880 }
881
882 if (P.end()[-1] == ',')
883 P.erase(P.end()-1);
884 }
885
886 // Locate the package
887 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
888 if (Pkg.end() == true)
889 {
890 _error->Warning(_("Unable to locate package %s"),*I);
891 continue;
892 }
893 Show[Pkg->ID] = ToShow;
894
895 if (Force == true)
896 Flags[Pkg->ID] |= ForceNR;
897 }
898
899 // Little header
900 printf("digraph packages {\n");
901 printf("concentrate=true;\n");
902 printf("size=\"30,40\";\n");
903
904 bool Act = true;
905 while (Act == true)
906 {
907 Act = false;
908 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
909 {
910 // See we need to show this package
911 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
912 continue;
913
914 // Colour as done
915 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
916 {
917 // Pure Provides and missing packages have no deps!
918 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
919 Show[Pkg->ID] = Done;
920 else
921 Show[Pkg->ID] = DoneNR;
922 }
923 else
924 Show[Pkg->ID] = Done;
925 Act = true;
926
927 // No deps to map out
928 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
929 continue;
930
931 pkgCache::VerIterator Ver = Pkg.VersionList();
932 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
933 {
934 // See if anything can meet this dep
935 // Walk along the actual package providing versions
936 bool Hit = false;
937 pkgCache::PkgIterator DPkg = D.TargetPkg();
938 for (pkgCache::VerIterator I = DPkg.VersionList();
939 I.end() == false && Hit == false; I++)
940 {
941 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
942 Hit = true;
943 }
944
945 // Follow all provides
946 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
947 I.end() == false && Hit == false; I++)
948 {
949 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
950 Hit = true;
951 }
952
953 // Only graph critical deps
954 if (D.IsCritical() == true)
955 {
956 printf("\"%s\" -> \"%s\"",Pkg.Name(),D.TargetPkg().Name());
957
958 // Colour the node for recursion
959 if (Show[D.TargetPkg()->ID] <= DoneNR)
960 {
961 /* If a conflicts does not meet anything in the database
962 then show the relation but do not recurse */
963 if (Hit == false &&
964 (D->Type == pkgCache::Dep::Conflicts ||
965 D->Type == pkgCache::Dep::Obsoletes))
966 {
967 if (Show[D.TargetPkg()->ID] == None &&
968 Show[D.TargetPkg()->ID] != ToShow)
969 Show[D.TargetPkg()->ID] = ToShowNR;
970 }
971 else
972 {
973 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
974 Show[D.TargetPkg()->ID] = ToShowNR;
975 else
976 Show[D.TargetPkg()->ID] = ToShow;
977 }
978 }
979
980 // Edge colour
981 switch(D->Type)
982 {
983 case pkgCache::Dep::Conflicts:
984 case pkgCache::Dep::Obsoletes:
985 printf("[color=springgreen];\n");
986 break;
987
988 case pkgCache::Dep::PreDepends:
989 printf("[color=blue];\n");
990 break;
991
992 default:
993 printf(";\n");
994 break;
995 }
996 }
997 }
998 }
999 }
1000
1001 /* Draw the box colours after the fact since we can not tell what colour
1002 they should be until everything is finished drawing */
1003 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
1004 {
1005 if (Show[Pkg->ID] < DoneNR)
1006 continue;
1007
1008 // Orange box for early recursion stoppage
1009 if (Show[Pkg->ID] == DoneNR)
1010 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.Name(),
1011 Shapes[ShapeMap[Pkg->ID]]);
1012 else
1013 printf("\"%s\" [shape=%s];\n",Pkg.Name(),
1014 Shapes[ShapeMap[Pkg->ID]]);
1015 }
1016
1017 printf("}\n");
1018 return true;
1019 }
1020 /*}}}*/
1021 // DoAdd - Perform an adding operation /*{{{*/
1022 // ---------------------------------------------------------------------
1023 /* */
1024 bool DoAdd(CommandLine &CmdL)
1025 {
1026 return _error->Error("Unimplemented");
1027 #if 0
1028 // Make sure there is at least one argument
1029 if (CmdL.FileSize() <= 1)
1030 return _error->Error("You must give at least one file name");
1031
1032 // Open the cache
1033 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
1034 if (_error->PendingError() == true)
1035 return false;
1036
1037 DynamicMMap Map(CacheF,MMap::Public);
1038 if (_error->PendingError() == true)
1039 return false;
1040
1041 OpTextProgress Progress(*_config);
1042 pkgCacheGenerator Gen(Map,Progress);
1043 if (_error->PendingError() == true)
1044 return false;
1045
1046 unsigned long Length = CmdL.FileSize() - 1;
1047 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1048 {
1049 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
1050 Progress.SubProgress(Length);
1051
1052 // Do the merge
1053 FileFd TagF(*I,FileFd::ReadOnly);
1054 debListParser Parser(TagF);
1055 if (_error->PendingError() == true)
1056 return _error->Error("Problem opening %s",*I);
1057
1058 if (Gen.SelectFile(*I,"") == false)
1059 return _error->Error("Problem with SelectFile");
1060
1061 if (Gen.MergeList(Parser) == false)
1062 return _error->Error("Problem with MergeList");
1063 }
1064
1065 Progress.Done();
1066 GCache = &Gen.GetCache();
1067 Stats(CmdL);
1068
1069 return true;
1070 #endif
1071 }
1072 /*}}}*/
1073 // DisplayRecord - Displays the complete record for the package /*{{{*/
1074 // ---------------------------------------------------------------------
1075 /* This displays the package record from the proper package index file.
1076 It is not used by DumpAvail for performance reasons. */
1077 bool DisplayRecord(pkgCache::VerIterator V)
1078 {
1079 // Find an appropriate file
1080 pkgCache::VerFileIterator Vf = V.FileList();
1081 for (; Vf.end() == false; Vf++)
1082 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
1083 break;
1084 if (Vf.end() == true)
1085 Vf = V.FileList();
1086
1087 // Check and load the package list file
1088 pkgCache::PkgFileIterator I = Vf.File();
1089 if (I.IsOk() == false)
1090 return _error->Error(_("Package file %s is out of sync."),I.FileName());
1091
1092 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
1093 if (_error->PendingError() == true)
1094 return false;
1095
1096 // Read the record and then write it out again.
1097 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
1098 Buffer[V.FileList()->Size] = '\n';
1099 if (PkgF.Seek(V.FileList()->Offset) == false ||
1100 PkgF.Read(Buffer,V.FileList()->Size) == false ||
1101 write(STDOUT_FILENO,Buffer,V.FileList()->Size+1) != V.FileList()->Size+1)
1102 {
1103 delete [] Buffer;
1104 return false;
1105 }
1106
1107 delete [] Buffer;
1108
1109 return true;
1110 }
1111 /*}}}*/
1112 // Search - Perform a search /*{{{*/
1113 // ---------------------------------------------------------------------
1114 /* This searches the package names and pacakge descriptions for a pattern */
1115 struct ExVerFile
1116 {
1117 pkgCache::VerFile *Vf;
1118 bool NameMatch;
1119 };
1120
1121 bool Search(CommandLine &CmdL)
1122 {
1123 pkgCache &Cache = *GCache;
1124 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1125 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
1126 unsigned NumPatterns = CmdL.FileSize() -1;
1127
1128 pkgDepCache::Policy Plcy;
1129
1130 // Make sure there is at least one argument
1131 if (NumPatterns < 1)
1132 return _error->Error(_("You must give exactly one pattern"));
1133
1134 // Compile the regex pattern
1135 regex_t *Patterns = new regex_t[NumPatterns];
1136 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1137 for (unsigned I = 0; I != NumPatterns; I++)
1138 {
1139 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1140 REG_NOSUB) != 0)
1141 {
1142 for (; I != 0; I--)
1143 regfree(&Patterns[I]);
1144 return _error->Error("Regex compilation error");
1145 }
1146 }
1147
1148 // Create the text record parser
1149 pkgRecords Recs(Cache);
1150 if (_error->PendingError() == true)
1151 {
1152 for (unsigned I = 0; I != NumPatterns; I++)
1153 regfree(&Patterns[I]);
1154 return false;
1155 }
1156
1157 ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
1158 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
1159
1160 // Map versions that we want to write out onto the VerList array.
1161 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
1162 {
1163 VFList[P->ID].NameMatch = NumPatterns != 0;
1164 for (unsigned I = 0; I != NumPatterns; I++)
1165 {
1166 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
1167 VFList[P->ID].NameMatch &= true;
1168 else
1169 VFList[P->ID].NameMatch = false;
1170 }
1171
1172 // Doing names only, drop any that dont match..
1173 if (NamesOnly == true && VFList[P->ID].NameMatch == false)
1174 continue;
1175
1176 // Find the proper version to use.
1177 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
1178 if (V.end() == false)
1179 VFList[P->ID].Vf = V.FileList();
1180 }
1181
1182 // Include all the packages that provide matching names too
1183 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
1184 {
1185 if (VFList[P->ID].NameMatch == false)
1186 continue;
1187
1188 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
1189 {
1190 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
1191 if (V.end() == false)
1192 {
1193 VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
1194 VFList[Prv.OwnerPkg()->ID].NameMatch = true;
1195 }
1196 }
1197 }
1198
1199 LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
1200
1201 // Iterate over all the version records and check them
1202 for (ExVerFile *J = VFList; J->Vf != 0; J++)
1203 {
1204 pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
1205
1206 bool Match = true;
1207 if (J->NameMatch == false)
1208 {
1209 string LongDesc = P.LongDesc();
1210 Match = NumPatterns != 0;
1211 for (unsigned I = 0; I != NumPatterns; I++)
1212 {
1213 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
1214 Match &= true;
1215 else
1216 Match = false;
1217 }
1218 }
1219
1220 if (Match == true)
1221 {
1222 if (ShowFull == true)
1223 {
1224 const char *Start;
1225 const char *End;
1226 P.GetRec(Start,End);
1227 fwrite(Start,End-Start,1,stdout);
1228 putc('\n',stdout);
1229 }
1230 else
1231 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1232 }
1233 }
1234
1235 delete [] VFList;
1236 for (unsigned I = 0; I != NumPatterns; I++)
1237 regfree(&Patterns[I]);
1238 if (ferror(stdout))
1239 return _error->Error("Write to stdout failed");
1240 return true;
1241 }
1242 /*}}}*/
1243 // ShowPackage - Dump the package record to the screen /*{{{*/
1244 // ---------------------------------------------------------------------
1245 /* */
1246 bool ShowPackage(CommandLine &CmdL)
1247 {
1248 pkgCache &Cache = *GCache;
1249 pkgDepCache::Policy Plcy;
1250
1251 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1252 {
1253 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1254 if (Pkg.end() == true)
1255 {
1256 _error->Warning(_("Unable to locate package %s"),*I);
1257 continue;
1258 }
1259
1260 // Find the proper version to use.
1261 if (_config->FindB("APT::Cache::AllVersions","true") == true)
1262 {
1263 pkgCache::VerIterator V;
1264 for (V = Pkg.VersionList(); V.end() == false; V++)
1265 {
1266 if (DisplayRecord(V) == false)
1267 return false;
1268 }
1269 }
1270 else
1271 {
1272 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1273 if (V.end() == true || V.FileList().end() == true)
1274 continue;
1275 if (DisplayRecord(V) == false)
1276 return false;
1277 }
1278 }
1279 return true;
1280 }
1281 /*}}}*/
1282 // ShowPkgNames - Show package names /*{{{*/
1283 // ---------------------------------------------------------------------
1284 /* This does a prefix match on the first argument */
1285 bool ShowPkgNames(CommandLine &CmdL)
1286 {
1287 pkgCache &Cache = *GCache;
1288 pkgCache::PkgIterator I = Cache.PkgBegin();
1289 bool All = _config->FindB("APT::Cache::AllNames","false");
1290
1291 if (CmdL.FileList[1] != 0)
1292 {
1293 for (;I.end() != true; I++)
1294 {
1295 if (All == false && I->VersionList == 0)
1296 continue;
1297
1298 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1299 cout << I.Name() << endl;
1300 }
1301
1302 return true;
1303 }
1304
1305 // Show all pkgs
1306 for (;I.end() != true; I++)
1307 {
1308 if (All == false && I->VersionList == 0)
1309 continue;
1310 cout << I.Name() << endl;
1311 }
1312
1313 return true;
1314 }
1315 /*}}}*/
1316 // ShowSrcPackage - Show source package records /*{{{*/
1317 // ---------------------------------------------------------------------
1318 /* */
1319 bool ShowSrcPackage(CommandLine &CmdL)
1320 {
1321 pkgSourceList List;
1322 List.ReadMainList();
1323
1324 // Create the text record parsers
1325 pkgSrcRecords SrcRecs(List);
1326 if (_error->PendingError() == true)
1327 return false;
1328
1329 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1330 {
1331 SrcRecs.Restart();
1332
1333 pkgSrcRecords::Parser *Parse;
1334 while ((Parse = SrcRecs.Find(*I,false)) != 0)
1335 cout << Parse->AsStr() << endl;;
1336 }
1337 return true;
1338 }
1339 /*}}}*/
1340 // Policy - Show the results of the preferences file /*{{{*/
1341 // ---------------------------------------------------------------------
1342 /* */
1343 bool Policy(CommandLine &CmdL)
1344 {
1345 if (SrcList == 0)
1346 return _error->Error("Generate must be enabled for this function");
1347
1348 pkgCache &Cache = *GCache;
1349 pkgPolicy Plcy(&Cache);
1350 if (ReadPinFile(Plcy) == false)
1351 return false;
1352
1353 // Print out all of the package files
1354 if (CmdL.FileList[1] == 0)
1355 {
1356 cout << _("Package Files:") << endl;
1357 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1358 {
1359 // Locate the associated index files so we can derive a description
1360 pkgIndexFile *Indx;
1361 if (SrcList->FindIndex(F,Indx) == false &&
1362 _system->FindIndex(F,Indx) == false)
1363 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1364 printf(_("%4i %s\n"),
1365 Plcy.GetPriority(F),Indx->Describe(true).c_str());
1366
1367 // Print the reference information for the package
1368 string Str = F.RelStr();
1369 if (Str.empty() == false)
1370 printf(" release %s\n",F.RelStr().c_str());
1371 if (F.Site() != 0 && F.Site()[0] != 0)
1372 printf(" origin %s\n",F.Site());
1373 }
1374
1375 // Show any packages have explicit pins
1376 cout << _("Pinned Packages:") << endl;
1377 pkgCache::PkgIterator I = Cache.PkgBegin();
1378 for (;I.end() != true; I++)
1379 {
1380 if (Plcy.GetPriority(I) == 0)
1381 continue;
1382
1383 // Print the package name and the version we are forcing to
1384 cout << " " << I.Name() << " -> ";
1385
1386 pkgCache::VerIterator V = Plcy.GetMatch(I);
1387 if (V.end() == true)
1388 cout << _("(not found)") << endl;
1389 else
1390 cout << V.VerStr() << endl;
1391 }
1392
1393 return true;
1394 }
1395
1396 // Print out detailed information for each package
1397 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1398 {
1399 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1400 if (Pkg.end() == true)
1401 {
1402 _error->Warning(_("Unable to locate package %s"),*I);
1403 continue;
1404 }
1405
1406 cout << Pkg.Name() << ":" << endl;
1407
1408 // Installed version
1409 cout << _(" Installed: ");
1410 if (Pkg->CurrentVer == 0)
1411 cout << _("(none)") << endl;
1412 else
1413 cout << Pkg.CurrentVer().VerStr() << endl;
1414
1415 // Candidate Version
1416 cout << _(" Candidate: ");
1417 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1418 if (V.end() == true)
1419 cout << _("(none)") << endl;
1420 else
1421 cout << V.VerStr() << endl;
1422
1423 // Pinned version
1424 if (Plcy.GetPriority(Pkg) != 0)
1425 {
1426 cout << _(" Package Pin: ");
1427 V = Plcy.GetMatch(Pkg);
1428 if (V.end() == true)
1429 cout << _("(not found)") << endl;
1430 else
1431 cout << V.VerStr() << endl;
1432 }
1433
1434 // Show the priority tables
1435 cout << _(" Version Table:") << endl;
1436 for (V = Pkg.VersionList(); V.end() == false; V++)
1437 {
1438 if (Pkg.CurrentVer() == V)
1439 cout << " *** " << V.VerStr();
1440 else
1441 cout << " " << V.VerStr();
1442 cout << " " << Plcy.GetPriority(Pkg) << endl;
1443 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1444 {
1445 // Locate the associated index files so we can derive a description
1446 pkgIndexFile *Indx;
1447 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1448 _system->FindIndex(VF.File(),Indx) == false)
1449 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1450 printf(_(" %4i %s\n"),Plcy.GetPriority(VF.File()),
1451 Indx->Describe(true).c_str());
1452 }
1453 }
1454 }
1455
1456 return true;
1457 }
1458 /*}}}*/
1459 // GenCaches - Call the main cache generator /*{{{*/
1460 // ---------------------------------------------------------------------
1461 /* */
1462 bool GenCaches(CommandLine &Cmd)
1463 {
1464 OpTextProgress Progress(*_config);
1465
1466 pkgSourceList List;
1467 if (List.ReadMainList() == false)
1468 return false;
1469 return pkgMakeStatusCache(List,Progress);
1470 }
1471 /*}}}*/
1472 // ShowHelp - Show a help screen /*{{{*/
1473 // ---------------------------------------------------------------------
1474 /* */
1475 bool ShowHelp(CommandLine &Cmd)
1476 {
1477 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1478 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
1479
1480 cout <<
1481 _("Usage: apt-cache [options] command\n"
1482 " apt-cache [options] add file1 [file1 ...]\n"
1483 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1484 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1485 "\n"
1486 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1487 "cache files, and query information from them\n"
1488 "\n"
1489 "Commands:\n"
1490 " add - Add a package file to the source cache\n"
1491 " gencaches - Build both the package and source cache\n"
1492 " showpkg - Show some general information for a single package\n"
1493 " showsrc - Show source records\n"
1494 " stats - Show some basic statistics\n"
1495 " dump - Show the entire file in a terse form\n"
1496 " dumpavail - Print an available file to stdout\n"
1497 " unmet - Show unmet dependencies\n"
1498 " search - Search the package list for a regex pattern\n"
1499 " show - Show a readable record for the package\n"
1500 " depends - Show raw dependency information for a package\n"
1501 " pkgnames - List the names of all packages\n"
1502 " dotty - Generate package graphs for GraphVis\n"
1503 " xvcg - Generate package graphs for xvcg\n"
1504 " policy - Show policy settings\n"
1505 "\n"
1506 "Options:\n"
1507 " -h This help text.\n"
1508 " -p=? The package cache.\n"
1509 " -s=? The source cache.\n"
1510 " -q Disable progress indicator.\n"
1511 " -i Show only important deps for the unmet command.\n"
1512 " -c=? Read this configuration file\n"
1513 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1514 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1515 return true;
1516 }
1517 /*}}}*/
1518 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1519 // ---------------------------------------------------------------------
1520 /* */
1521 void CacheInitialize()
1522 {
1523 _config->Set("quiet",0);
1524 _config->Set("help",false);
1525 }
1526 /*}}}*/
1527
1528 int main(int argc,const char *argv[])
1529 {
1530 CommandLine::Args Args[] = {
1531 {'h',"help","help",0},
1532 {'v',"version","version",0},
1533 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1534 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1535 {'q',"quiet","quiet",CommandLine::IntLevel},
1536 {'i',"important","APT::Cache::Important",0},
1537 {'f',"full","APT::Cache::ShowFull",0},
1538 {'g',"generate","APT::Cache::Generate",0},
1539 {'a',"all-versions","APT::Cache::AllVersions",0},
1540 {0,"names-only","APT::Cache::NamesOnly",0},
1541 {'n',"all-names","APT::Cache::AllNames",0},
1542 {0,"recurse","APT::Cache::RecurseDepends",0},
1543 {'c',"config-file",0,CommandLine::ConfigFile},
1544 {'o',"option",0,CommandLine::ArbItem},
1545 {0,0,0,0}};
1546 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1547 {"add",&DoAdd},
1548 {"gencaches",&GenCaches},
1549 {"showsrc",&ShowSrcPackage},
1550 {0,0}};
1551 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1552 {"stats",&Stats},
1553 {"dump",&Dump},
1554 {"dumpavail",&DumpAvail},
1555 {"unmet",&UnMet},
1556 {"search",&Search},
1557 {"depends",&Depends},
1558 {"dotty",&Dotty},
1559 {"xvcg",&XVcg},
1560 {"show",&ShowPackage},
1561 {"pkgnames",&ShowPkgNames},
1562 {"policy",&Policy},
1563 {0,0}};
1564
1565 CacheInitialize();
1566
1567 // Set up gettext support
1568 setlocale(LC_ALL,"");
1569 textdomain(PACKAGE);
1570
1571 // Parse the command line and initialize the package library
1572 CommandLine CmdL(Args,_config);
1573 if (pkgInitConfig(*_config) == false ||
1574 CmdL.Parse(argc,argv) == false ||
1575 pkgInitSystem(*_config,_system) == false)
1576 {
1577 _error->DumpErrors();
1578 return 100;
1579 }
1580
1581 // See if the help should be shown
1582 if (_config->FindB("help") == true ||
1583 CmdL.FileSize() == 0)
1584 {
1585 ShowHelp(CmdL);
1586 return 0;
1587 }
1588
1589 // Deal with stdout not being a tty
1590 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1591 _config->Set("quiet","1");
1592
1593 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
1594 {
1595 MMap *Map = 0;
1596 if (_config->FindB("APT::Cache::Generate",true) == false)
1597 {
1598 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
1599 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
1600 }
1601 else
1602 {
1603 // Open the cache file
1604 SrcList = new pkgSourceList;
1605 SrcList->ReadMainList();
1606
1607 // Generate it and map it
1608 OpProgress Prog;
1609 pkgMakeStatusCache(*SrcList,Prog,&Map,true);
1610 }
1611
1612 if (_error->PendingError() == false)
1613 {
1614 pkgCache Cache(Map);
1615 GCache = &Cache;
1616 if (_error->PendingError() == false)
1617 CmdL.DispatchArg(CmdsB);
1618 }
1619 delete Map;
1620 }
1621
1622 // Print any errors or warnings found during parsing
1623 if (_error->empty() == false)
1624 {
1625 bool Errors = _error->PendingError();
1626 _error->DumpErrors();
1627 return Errors == true?100:0;
1628 }
1629
1630 return 0;
1631 }