]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
336ac544b50e11a5cb2a7f7a7b9db6774ebf2409
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz 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<config.h>
17
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/init.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/cmndline.h>
25 #include <apt-pkg/strutl.h>
26 #include <apt-pkg/fileutl.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/srcrecords.h>
29 #include <apt-pkg/version.h>
30 #include <apt-pkg/policy.h>
31 #include <apt-pkg/tagfile.h>
32 #include <apt-pkg/algorithms.h>
33 #include <apt-pkg/sptr.h>
34 #include <apt-pkg/pkgsystem.h>
35 #include <apt-pkg/indexfile.h>
36 #include <apt-pkg/metaindex.h>
37
38 #include <cassert>
39 #include <locale.h>
40 #include <iostream>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <regex.h>
44 #include <stdio.h>
45 #include <iomanip>
46 #include <algorithm>
47
48 #include <apti18n.h>
49 /*}}}*/
50
51 using namespace std;
52
53 // CacheSetHelper saving virtual packages /*{{{*/
54 class CacheSetHelperVirtuals: public APT::CacheSetHelper {
55 public:
56 APT::PackageSet virtualPkgs;
57
58 virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
59 virtualPkgs.insert(Pkg);
60 return CacheSetHelper::canNotFindCandidateVer(Cache, Pkg);
61 }
62
63 virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
64 virtualPkgs.insert(Pkg);
65 return CacheSetHelper::canNotFindNewestVer(Cache, Pkg);
66 }
67
68 virtual void canNotFindAllVer(APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
69 virtualPkgs.insert(Pkg);
70 CacheSetHelper::canNotFindAllVer(vci, Cache, Pkg);
71 }
72
73 CacheSetHelperVirtuals(bool const ShowErrors = true, GlobalError::MsgType const &ErrorType = GlobalError::NOTICE) : CacheSetHelper(ShowErrors, ErrorType) {}
74 };
75 /*}}}*/
76 // LocalitySort - Sort a version list by package file locality /*{{{*/
77 // ---------------------------------------------------------------------
78 /* */
79 int LocalityCompare(const void *a, const void *b)
80 {
81 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
82 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
83
84 if (A == 0 && B == 0)
85 return 0;
86 if (A == 0)
87 return 1;
88 if (B == 0)
89 return -1;
90
91 if (A->File == B->File)
92 return A->Offset - B->Offset;
93 return A->File - B->File;
94 }
95
96 void LocalitySort(pkgCache::VerFile **begin,
97 unsigned long Count,size_t Size)
98 {
99 qsort(begin,Count,Size,LocalityCompare);
100 }
101
102 void LocalitySort(pkgCache::DescFile **begin,
103 unsigned long Count,size_t Size)
104 {
105 qsort(begin,Count,Size,LocalityCompare);
106 }
107 /*}}}*/
108 // UnMet - Show unmet dependencies /*{{{*/
109 // ---------------------------------------------------------------------
110 /* */
111 bool ShowUnMet(pkgCache::VerIterator const &V, bool const Important)
112 {
113 bool Header = false;
114 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
115 {
116 // Collect or groups
117 pkgCache::DepIterator Start;
118 pkgCache::DepIterator End;
119 D.GlobOr(Start,End);
120
121 // Important deps only
122 if (Important == true)
123 if (End->Type != pkgCache::Dep::PreDepends &&
124 End->Type != pkgCache::Dep::Depends)
125 continue;
126
127 // Skip conflicts and replaces
128 if (End.IsNegative() == true)
129 continue;
130
131 // Verify the or group
132 bool OK = false;
133 pkgCache::DepIterator RealStart = Start;
134 do
135 {
136 // See if this dep is Ok
137 pkgCache::Version **VList = Start.AllTargets();
138 if (*VList != 0)
139 {
140 OK = true;
141 delete [] VList;
142 break;
143 }
144 delete [] VList;
145
146 if (Start == End)
147 break;
148 ++Start;
149 }
150 while (1);
151
152 // The group is OK
153 if (OK == true)
154 continue;
155
156 // Oops, it failed..
157 if (Header == false)
158 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
159 V.ParentPkg().FullName(true).c_str(),V.VerStr());
160 Header = true;
161
162 // Print out the dep type
163 cout << " " << End.DepType() << ": ";
164
165 // Show the group
166 Start = RealStart;
167 do
168 {
169 cout << Start.TargetPkg().FullName(true);
170 if (Start.TargetVer() != 0)
171 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
172 ")";
173 if (Start == End)
174 break;
175 cout << " | ";
176 ++Start;
177 }
178 while (1);
179
180 cout << endl;
181 }
182 return true;
183 }
184 bool UnMet(CommandLine &CmdL)
185 {
186 bool const Important = _config->FindB("APT::Cache::Important",false);
187
188 pkgCacheFile CacheFile;
189 if (unlikely(CacheFile.GetPkgCache() == NULL))
190 return false;
191
192 if (CmdL.FileSize() <= 1)
193 {
194 for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; ++P)
195 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
196 if (ShowUnMet(V, Important) == false)
197 return false;
198 }
199 else
200 {
201 CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
202 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1,
203 APT::VersionList::CANDIDATE, helper);
204 for (APT::VersionList::iterator V = verset.begin(); V != verset.end(); ++V)
205 if (ShowUnMet(V, Important) == false)
206 return false;
207 }
208 return true;
209 }
210 /*}}}*/
211 // DumpPackage - Show a dump of a package record /*{{{*/
212 // ---------------------------------------------------------------------
213 /* */
214 bool DumpPackage(CommandLine &CmdL)
215 {
216 pkgCacheFile CacheFile;
217 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
218 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
219
220 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
221 {
222 cout << "Package: " << Pkg.FullName(true) << endl;
223 cout << "Versions: " << endl;
224 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
225 {
226 cout << Cur.VerStr();
227 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; ++Vf)
228 cout << " (" << Vf.File().FileName() << ")";
229 cout << endl;
230 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; ++D)
231 {
232 cout << " Description Language: " << D.LanguageCode() << endl
233 << " File: " << D.FileList().File().FileName() << endl
234 << " MD5: " << D.md5() << endl;
235 }
236 cout << endl;
237 }
238
239 cout << endl;
240
241 cout << "Reverse Depends: " << endl;
242 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D)
243 {
244 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
245 if (D->Version != 0)
246 cout << ' ' << DeNull(D.TargetVer()) << endl;
247 else
248 cout << endl;
249 }
250
251 cout << "Dependencies: " << endl;
252 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
253 {
254 cout << Cur.VerStr() << " - ";
255 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; ++Dep)
256 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
257 cout << endl;
258 }
259
260 cout << "Provides: " << endl;
261 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
262 {
263 cout << Cur.VerStr() << " - ";
264 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; ++Prv)
265 cout << Prv.ParentPkg().FullName(true) << " ";
266 cout << endl;
267 }
268 cout << "Reverse Provides: " << endl;
269 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; ++Prv)
270 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << endl;
271 }
272
273 return true;
274 }
275 /*}}}*/
276 // Stats - Dump some nice statistics /*{{{*/
277 // ---------------------------------------------------------------------
278 /* */
279 bool Stats(CommandLine &Cmd)
280 {
281 pkgCacheFile CacheFile;
282 pkgCache *Cache = CacheFile.GetPkgCache();
283 if (unlikely(Cache == NULL))
284 return false;
285
286 cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
287 SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
288 << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
289 SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
290
291 int Normal = 0;
292 int Virtual = 0;
293 int NVirt = 0;
294 int DVirt = 0;
295 int Missing = 0;
296 pkgCache::PkgIterator I = Cache->PkgBegin();
297 for (;I.end() != true; ++I)
298 {
299 if (I->VersionList != 0 && I->ProvidesList == 0)
300 {
301 Normal++;
302 continue;
303 }
304
305 if (I->VersionList != 0 && I->ProvidesList != 0)
306 {
307 NVirt++;
308 continue;
309 }
310
311 if (I->VersionList == 0 && I->ProvidesList != 0)
312 {
313 // Only 1 provides
314 if (I.ProvidesList()->NextProvides == 0)
315 {
316 DVirt++;
317 }
318 else
319 Virtual++;
320 continue;
321 }
322 if (I->VersionList == 0 && I->ProvidesList == 0)
323 {
324 Missing++;
325 continue;
326 }
327 }
328 cout << _(" Normal packages: ") << Normal << endl;
329 cout << _(" Pure virtual packages: ") << Virtual << endl;
330 cout << _(" Single virtual packages: ") << DVirt << endl;
331 cout << _(" Mixed virtual packages: ") << NVirt << endl;
332 cout << _(" Missing: ") << Missing << endl;
333
334 cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
335 SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
336 cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
337 SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
338 cout << _("Total dependencies: ") << Cache->Head().DependsCount << " (" <<
339 SizeToStr(Cache->Head().DependsCount*Cache->Head().DependencySz) << ')' << endl;
340
341 cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
342 SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
343 cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
344 SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
345 cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
346 SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
347
348 // String list stats
349 unsigned long Size = 0;
350 unsigned long Count = 0;
351 for (pkgCache::StringItem *I = Cache->StringItemP + Cache->Head().StringList;
352 I!= Cache->StringItemP; I = Cache->StringItemP + I->NextItem)
353 {
354 Count++;
355 Size += strlen(Cache->StrP + I->String) + 1;
356 }
357 cout << _("Total globbed strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
358
359 unsigned long DepVerSize = 0;
360 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
361 {
362 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
363 {
364 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
365 {
366 if (D->Version != 0)
367 DepVerSize += strlen(D.TargetVer()) + 1;
368 }
369 }
370 }
371 cout << _("Total dependency version space: ") << SizeToStr(DepVerSize) << endl;
372
373 unsigned long Slack = 0;
374 for (int I = 0; I != 7; I++)
375 Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
376 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
377
378 unsigned long Total = 0;
379 Total = Slack + Size + Cache->Head().DependsCount*Cache->Head().DependencySz +
380 Cache->Head().VersionCount*Cache->Head().VersionSz +
381 Cache->Head().PackageCount*Cache->Head().PackageSz +
382 Cache->Head().VerFileCount*Cache->Head().VerFileSz +
383 Cache->Head().ProvidesCount*Cache->Head().ProvidesSz;
384 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
385
386 return true;
387 }
388 /*}}}*/
389 // Dump - show everything /*{{{*/
390 // ---------------------------------------------------------------------
391 /* This is worthless except fer debugging things */
392 bool Dump(CommandLine &Cmd)
393 {
394 pkgCacheFile CacheFile;
395 pkgCache *Cache = CacheFile.GetPkgCache();
396 if (unlikely(Cache == NULL))
397 return false;
398
399 cout << "Using Versioning System: " << Cache->VS->Label << endl;
400
401 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
402 {
403 cout << "Package: " << P.FullName(true) << endl;
404 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
405 {
406 cout << " Version: " << V.VerStr() << endl;
407 cout << " File: " << V.FileList().File().FileName() << endl;
408 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
409 cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
410 DeNull(D.TargetVer()) << endl;
411 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
412 {
413 cout << " Description Language: " << D.LanguageCode() << endl
414 << " File: " << D.FileList().File().FileName() << endl
415 << " MD5: " << D.md5() << endl;
416 }
417 }
418 }
419
420 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
421 {
422 cout << "File: " << F.FileName() << endl;
423 cout << " Type: " << F.IndexType() << endl;
424 cout << " Size: " << F->Size << endl;
425 cout << " ID: " << F->ID << endl;
426 cout << " Flags: " << F->Flags << endl;
427 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
428 cout << " Archive: " << DeNull(F.Archive()) << endl;
429 cout << " Component: " << DeNull(F.Component()) << endl;
430 cout << " Version: " << DeNull(F.Version()) << endl;
431 cout << " Origin: " << DeNull(F.Origin()) << endl;
432 cout << " Site: " << DeNull(F.Site()) << endl;
433 cout << " Label: " << DeNull(F.Label()) << endl;
434 cout << " Architecture: " << DeNull(F.Architecture()) << endl;
435 }
436
437 return true;
438 }
439 /*}}}*/
440 // DumpAvail - Print out the available list /*{{{*/
441 // ---------------------------------------------------------------------
442 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
443 make this run really fast, perhaps I went a little overboard.. */
444 bool DumpAvail(CommandLine &Cmd)
445 {
446 pkgCacheFile CacheFile;
447 pkgCache *Cache = CacheFile.GetPkgCache();
448 if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
449 return false;
450
451 unsigned long Count = Cache->HeaderP->PackageCount+1;
452 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
453 memset(VFList,0,sizeof(*VFList)*Count);
454
455 // Map versions that we want to write out onto the VerList array.
456 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
457 {
458 if (P->VersionList == 0)
459 continue;
460
461 /* Find the proper version to use. If the policy says there are no
462 possible selections we return the installed version, if available..
463 This prevents dselect from making it obsolete. */
464 pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
465 if (V.end() == true)
466 {
467 if (P->CurrentVer == 0)
468 continue;
469 V = P.CurrentVer();
470 }
471
472 pkgCache::VerFileIterator VF = V.FileList();
473 for (; VF.end() == false ; ++VF)
474 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
475 break;
476
477 /* Okay, here we have a bit of a problem.. The policy has selected the
478 currently installed package - however it only exists in the
479 status file.. We need to write out something or dselect will mark
480 the package as obsolete! Thus we emit the status file entry, but
481 below we remove the status line to make it valid for the
482 available file. However! We only do this if their do exist *any*
483 non-source versions of the package - that way the dselect obsolete
484 handling works OK. */
485 if (VF.end() == true)
486 {
487 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; ++Cur)
488 {
489 for (VF = Cur.FileList(); VF.end() == false; ++VF)
490 {
491 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
492 {
493 VF = V.FileList();
494 break;
495 }
496 }
497
498 if (VF.end() == false)
499 break;
500 }
501 }
502
503 VFList[P->ID] = VF;
504 }
505
506 LocalitySort(VFList,Count,sizeof(*VFList));
507
508 // Iterate over all the package files and write them out.
509 char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
510 for (pkgCache::VerFile **J = VFList; *J != 0;)
511 {
512 pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
513 if (File.IsOk() == false)
514 {
515 _error->Error(_("Package file %s is out of sync."),File.FileName());
516 break;
517 }
518
519 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
520 if (_error->PendingError() == true)
521 break;
522
523 /* Write all of the records from this package file, since we
524 already did locality sorting we can now just seek through the
525 file in read order. We apply 1 more optimization here, since often
526 there will be < 1 byte gaps between records (for the \n) we read that
527 into the next buffer and offset a bit.. */
528 unsigned long Pos = 0;
529 for (; *J != 0; J++)
530 {
531 if ((*J)->File + Cache->PkgFileP != File)
532 break;
533
534 const pkgCache::VerFile &VF = **J;
535
536 // Read the record and then write it out again.
537 unsigned long Jitter = VF.Offset - Pos;
538 if (Jitter > 8)
539 {
540 if (PkgF.Seek(VF.Offset) == false)
541 break;
542 Jitter = 0;
543 }
544
545 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
546 break;
547 Buffer[VF.Size + Jitter] = '\n';
548
549 // See above..
550 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
551 {
552 pkgTagSection Tags;
553 TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
554 const char *Zero = 0;
555 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
556 TFRewrite(stdout,Tags,&Zero,RW) == false)
557 {
558 _error->Error("Internal Error, Unable to parse a package record");
559 break;
560 }
561 fputc('\n',stdout);
562 }
563 else
564 {
565 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
566 break;
567 }
568
569 Pos = VF.Offset + VF.Size;
570 }
571
572 fflush(stdout);
573 if (_error->PendingError() == true)
574 break;
575 }
576
577 delete [] Buffer;
578 delete [] VFList;
579 return !_error->PendingError();
580 }
581 /*}}}*/
582 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
583 bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
584 {
585 pkgCacheFile CacheFile;
586 pkgCache *Cache = CacheFile.GetPkgCache();
587 if (unlikely(Cache == NULL))
588 return false;
589
590 CacheSetHelperVirtuals helper(false);
591 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
592 if (verset.empty() == true && helper.virtualPkgs.empty() == true)
593 return _error->Error(_("No packages found"));
594 std::vector<bool> Shown(Cache->Head().PackageCount);
595
596 bool const Recurse = _config->FindB("APT::Cache::RecurseDepends", false);
597 bool const Installed = _config->FindB("APT::Cache::Installed", false);
598 bool const Important = _config->FindB("APT::Cache::Important", false);
599 bool const ShowDepType = _config->FindB("APT::Cache::ShowDependencyType", RevDepends == false);
600 bool const ShowVersion = _config->FindB("APT::Cache::ShowVersion", false);
601 bool const ShowPreDepends = _config->FindB("APT::Cache::ShowPre-Depends", true);
602 bool const ShowDepends = _config->FindB("APT::Cache::ShowDepends", true);
603 bool const ShowRecommends = _config->FindB("APT::Cache::ShowRecommends", Important == false);
604 bool const ShowSuggests = _config->FindB("APT::Cache::ShowSuggests", Important == false);
605 bool const ShowReplaces = _config->FindB("APT::Cache::ShowReplaces", Important == false);
606 bool const ShowConflicts = _config->FindB("APT::Cache::ShowConflicts", Important == false);
607 bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
608 bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
609 bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false);
610
611 while (verset.empty() != true)
612 {
613 pkgCache::VerIterator Ver = *verset.begin();
614 verset.erase(verset.begin());
615 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
616 Shown[Pkg->ID] = true;
617
618 cout << Pkg.FullName(true) << endl;
619
620 if (RevDepends == true)
621 cout << "Reverse Depends:" << endl;
622 for (pkgCache::DepIterator D = RevDepends ? Pkg.RevDependsList() : Ver.DependsList();
623 D.end() == false; ++D)
624 {
625 switch (D->Type) {
626 case pkgCache::Dep::PreDepends: if (!ShowPreDepends) continue; break;
627 case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
628 case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
629 case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break;
630 case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break;
631 case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
632 case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
633 case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
634 }
635
636 pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg();
637
638 if((Installed && Trg->CurrentVer != 0) || !Installed)
639 {
640
641 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or && ShowOnlyFirstOr == false)
642 cout << " |";
643 else
644 cout << " ";
645
646 // Show the package
647 if (ShowDepType == true)
648 cout << D.DepType() << ": ";
649 if (Trg->VersionList == 0)
650 cout << "<" << Trg.FullName(true) << ">";
651 else
652 cout << Trg.FullName(true);
653 if (ShowVersion == true && D->Version != 0)
654 cout << " (" << pkgCache::CompTypeDeb(D->CompareOp) << ' ' << D.TargetVer() << ')';
655 cout << std::endl;
656
657 if (Recurse == true && Shown[Trg->ID] == false)
658 {
659 Shown[Trg->ID] = true;
660 verset.insert(APT::VersionSet::FromPackage(CacheFile, Trg, APT::VersionSet::CANDIDATE, helper));
661 }
662
663 }
664
665 // Display all solutions
666 SPtrArray<pkgCache::Version *> List = D.AllTargets();
667 pkgPrioSortList(*Cache,List);
668 for (pkgCache::Version **I = List; *I != 0; I++)
669 {
670 pkgCache::VerIterator V(*Cache,*I);
671 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
672 V->ParentPkg == D->Package)
673 continue;
674 cout << " " << V.ParentPkg().FullName(true) << endl;
675
676 if (Recurse == true && Shown[V.ParentPkg()->ID] == false)
677 {
678 Shown[V.ParentPkg()->ID] = true;
679 verset.insert(APT::VersionSet::FromPackage(CacheFile, V.ParentPkg(), APT::VersionSet::CANDIDATE, helper));
680 }
681 }
682
683 if (ShowOnlyFirstOr == true)
684 while ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) ++D;
685 }
686 }
687
688 for (APT::PackageSet::const_iterator Pkg = helper.virtualPkgs.begin();
689 Pkg != helper.virtualPkgs.end(); ++Pkg)
690 cout << '<' << Pkg.FullName(true) << '>' << endl;
691
692 return true;
693 }
694 /*}}}*/
695 // Depends - Print out a dependency tree /*{{{*/
696 // ---------------------------------------------------------------------
697 /* */
698 bool Depends(CommandLine &CmdL)
699 {
700 return ShowDepends(CmdL, false);
701 }
702 /*}}}*/
703 // RDepends - Print out a reverse dependency tree /*{{{*/
704 // ---------------------------------------------------------------------
705 /* */
706 bool RDepends(CommandLine &CmdL)
707 {
708 return ShowDepends(CmdL, true);
709 }
710 /*}}}*/
711 // xvcg - Generate a graph for xvcg /*{{{*/
712 // ---------------------------------------------------------------------
713 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
714
715 bool XVcg(CommandLine &CmdL)
716 {
717 pkgCacheFile CacheFile;
718 pkgCache *Cache = CacheFile.GetPkgCache();
719 if (unlikely(Cache == NULL))
720 return false;
721
722 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
723
724 /* Normal packages are boxes
725 Pure Provides are triangles
726 Mixed are diamonds
727 rhomb are missing packages*/
728 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
729
730 /* Initialize the list of packages to show.
731 1 = To Show
732 2 = To Show no recurse
733 3 = Emitted no recurse
734 4 = Emitted
735 0 = None */
736 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
737 enum TheFlags {ForceNR=(1<<0)};
738 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
739 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
740 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
741
742 // Show everything if no arguments given
743 if (CmdL.FileList[1] == 0)
744 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
745 Show[I] = ToShow;
746 else
747 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
748 Show[I] = None;
749 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
750
751 // Map the shapes
752 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
753 {
754 if (Pkg->VersionList == 0)
755 {
756 // Missing
757 if (Pkg->ProvidesList == 0)
758 ShapeMap[Pkg->ID] = 0;
759 else
760 ShapeMap[Pkg->ID] = 1;
761 }
762 else
763 {
764 // Normal
765 if (Pkg->ProvidesList == 0)
766 ShapeMap[Pkg->ID] = 2;
767 else
768 ShapeMap[Pkg->ID] = 3;
769 }
770 }
771
772 // Load the list of packages from the command line into the show list
773 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
774 std::list<APT::PackageSet::Modifier> mods;
775 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
776 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
777 std::map<unsigned short, APT::PackageSet> pkgsets =
778 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
779
780 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
781 Pkg != pkgsets[0].end(); ++Pkg)
782 Show[Pkg->ID] = ToShow;
783 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
784 Pkg != pkgsets[1].end(); ++Pkg)
785 {
786 Show[Pkg->ID] = ToShow;
787 Flags[Pkg->ID] |= ForceNR;
788 }
789
790 // Little header
791 cout << "graph: { title: \"packages\"" << endl <<
792 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
793 "layout_downfactor: 8" << endl;
794
795 bool Act = true;
796 while (Act == true)
797 {
798 Act = false;
799 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
800 {
801 // See we need to show this package
802 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
803 continue;
804
805 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
806
807 // Colour as done
808 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
809 {
810 // Pure Provides and missing packages have no deps!
811 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
812 Show[Pkg->ID] = Done;
813 else
814 Show[Pkg->ID] = DoneNR;
815 }
816 else
817 Show[Pkg->ID] = Done;
818 Act = true;
819
820 // No deps to map out
821 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
822 continue;
823
824 pkgCache::VerIterator Ver = Pkg.VersionList();
825 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
826 {
827 // See if anything can meet this dep
828 // Walk along the actual package providing versions
829 bool Hit = false;
830 pkgCache::PkgIterator DPkg = D.TargetPkg();
831 for (pkgCache::VerIterator I = DPkg.VersionList();
832 I.end() == false && Hit == false; ++I)
833 {
834 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
835 Hit = true;
836 }
837
838 // Follow all provides
839 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
840 I.end() == false && Hit == false; ++I)
841 {
842 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
843 Hit = true;
844 }
845
846
847 // Only graph critical deps
848 if (D.IsCritical() == true)
849 {
850 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
851
852 // Colour the node for recursion
853 if (Show[D.TargetPkg()->ID] <= DoneNR)
854 {
855 /* If a conflicts does not meet anything in the database
856 then show the relation but do not recurse */
857 if (Hit == false && D.IsNegative() == true)
858 {
859 if (Show[D.TargetPkg()->ID] == None &&
860 Show[D.TargetPkg()->ID] != ToShow)
861 Show[D.TargetPkg()->ID] = ToShowNR;
862 }
863 else
864 {
865 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
866 Show[D.TargetPkg()->ID] = ToShowNR;
867 else
868 Show[D.TargetPkg()->ID] = ToShow;
869 }
870 }
871
872 // Edge colour
873 switch(D->Type)
874 {
875 case pkgCache::Dep::Conflicts:
876 printf("label: \"conflicts\" color: lightgreen }\n");
877 break;
878 case pkgCache::Dep::DpkgBreaks:
879 printf("label: \"breaks\" color: lightgreen }\n");
880 break;
881 case pkgCache::Dep::Obsoletes:
882 printf("label: \"obsoletes\" color: lightgreen }\n");
883 break;
884
885 case pkgCache::Dep::PreDepends:
886 printf("label: \"predepends\" color: blue }\n");
887 break;
888
889 default:
890 printf("}\n");
891 break;
892 }
893 }
894 }
895 }
896 }
897
898 /* Draw the box colours after the fact since we can not tell what colour
899 they should be until everything is finished drawing */
900 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
901 {
902 if (Show[Pkg->ID] < DoneNR)
903 continue;
904
905 if (Show[Pkg->ID] == DoneNR)
906 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
907 Shapes[ShapeMap[Pkg->ID]]);
908 else
909 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
910 Shapes[ShapeMap[Pkg->ID]]);
911
912 }
913
914 delete[] Show;
915 delete[] Flags;
916 delete[] ShapeMap;
917
918 printf("}\n");
919 return true;
920 }
921 /*}}}*/
922 // Dotty - Generate a graph for Dotty /*{{{*/
923 // ---------------------------------------------------------------------
924 /* Dotty is the graphvis program for generating graphs. It is a fairly
925 simple queuing algorithm that just writes dependencies and nodes.
926 http://www.research.att.com/sw/tools/graphviz/ */
927 bool Dotty(CommandLine &CmdL)
928 {
929 pkgCacheFile CacheFile;
930 pkgCache *Cache = CacheFile.GetPkgCache();
931 if (unlikely(Cache == NULL))
932 return false;
933
934 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
935
936 /* Normal packages are boxes
937 Pure Provides are triangles
938 Mixed are diamonds
939 Hexagons are missing packages*/
940 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
941
942 /* Initialize the list of packages to show.
943 1 = To Show
944 2 = To Show no recurse
945 3 = Emitted no recurse
946 4 = Emitted
947 0 = None */
948 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
949 enum TheFlags {ForceNR=(1<<0)};
950 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
951 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
952 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
953
954 // Show everything if no arguments given
955 if (CmdL.FileList[1] == 0)
956 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
957 Show[I] = ToShow;
958 else
959 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
960 Show[I] = None;
961 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
962
963 // Map the shapes
964 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
965 {
966 if (Pkg->VersionList == 0)
967 {
968 // Missing
969 if (Pkg->ProvidesList == 0)
970 ShapeMap[Pkg->ID] = 0;
971 else
972 ShapeMap[Pkg->ID] = 1;
973 }
974 else
975 {
976 // Normal
977 if (Pkg->ProvidesList == 0)
978 ShapeMap[Pkg->ID] = 2;
979 else
980 ShapeMap[Pkg->ID] = 3;
981 }
982 }
983
984 // Load the list of packages from the command line into the show list
985 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
986 std::list<APT::PackageSet::Modifier> mods;
987 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
988 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
989 std::map<unsigned short, APT::PackageSet> pkgsets =
990 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
991
992 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
993 Pkg != pkgsets[0].end(); ++Pkg)
994 Show[Pkg->ID] = ToShow;
995 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
996 Pkg != pkgsets[1].end(); ++Pkg)
997 {
998 Show[Pkg->ID] = ToShow;
999 Flags[Pkg->ID] |= ForceNR;
1000 }
1001
1002 // Little header
1003 printf("digraph packages {\n");
1004 printf("concentrate=true;\n");
1005 printf("size=\"30,40\";\n");
1006
1007 bool Act = true;
1008 while (Act == true)
1009 {
1010 Act = false;
1011 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
1012 {
1013 // See we need to show this package
1014 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
1015 continue;
1016
1017 // Colour as done
1018 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
1019 {
1020 // Pure Provides and missing packages have no deps!
1021 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
1022 Show[Pkg->ID] = Done;
1023 else
1024 Show[Pkg->ID] = DoneNR;
1025 }
1026 else
1027 Show[Pkg->ID] = Done;
1028 Act = true;
1029
1030 // No deps to map out
1031 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
1032 continue;
1033
1034 pkgCache::VerIterator Ver = Pkg.VersionList();
1035 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
1036 {
1037 // See if anything can meet this dep
1038 // Walk along the actual package providing versions
1039 bool Hit = false;
1040 pkgCache::PkgIterator DPkg = D.TargetPkg();
1041 for (pkgCache::VerIterator I = DPkg.VersionList();
1042 I.end() == false && Hit == false; ++I)
1043 {
1044 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
1045 Hit = true;
1046 }
1047
1048 // Follow all provides
1049 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
1050 I.end() == false && Hit == false; ++I)
1051 {
1052 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
1053 Hit = true;
1054 }
1055
1056 // Only graph critical deps
1057 if (D.IsCritical() == true)
1058 {
1059 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
1060
1061 // Colour the node for recursion
1062 if (Show[D.TargetPkg()->ID] <= DoneNR)
1063 {
1064 /* If a conflicts does not meet anything in the database
1065 then show the relation but do not recurse */
1066 if (Hit == false && D.IsNegative() == true)
1067 {
1068 if (Show[D.TargetPkg()->ID] == None &&
1069 Show[D.TargetPkg()->ID] != ToShow)
1070 Show[D.TargetPkg()->ID] = ToShowNR;
1071 }
1072 else
1073 {
1074 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1075 Show[D.TargetPkg()->ID] = ToShowNR;
1076 else
1077 Show[D.TargetPkg()->ID] = ToShow;
1078 }
1079 }
1080
1081 // Edge colour
1082 switch(D->Type)
1083 {
1084 case pkgCache::Dep::Conflicts:
1085 case pkgCache::Dep::Obsoletes:
1086 case pkgCache::Dep::DpkgBreaks:
1087 printf("[color=springgreen];\n");
1088 break;
1089
1090 case pkgCache::Dep::PreDepends:
1091 printf("[color=blue];\n");
1092 break;
1093
1094 default:
1095 printf(";\n");
1096 break;
1097 }
1098 }
1099 }
1100 }
1101 }
1102
1103 /* Draw the box colours after the fact since we can not tell what colour
1104 they should be until everything is finished drawing */
1105 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
1106 {
1107 if (Show[Pkg->ID] < DoneNR)
1108 continue;
1109
1110 // Orange box for early recursion stoppage
1111 if (Show[Pkg->ID] == DoneNR)
1112 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
1113 Shapes[ShapeMap[Pkg->ID]]);
1114 else
1115 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
1116 Shapes[ShapeMap[Pkg->ID]]);
1117 }
1118
1119 printf("}\n");
1120 delete[] Show;
1121 delete[] Flags;
1122 delete[] ShapeMap;
1123 return true;
1124 }
1125 /*}}}*/
1126 // DisplayRecord - Displays the complete record for the package /*{{{*/
1127 // ---------------------------------------------------------------------
1128 /* This displays the package record from the proper package index file.
1129 It is not used by DumpAvail for performance reasons. */
1130
1131 static unsigned char const* skipDescriptionFields(unsigned char const * DescP)
1132 {
1133 while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL)
1134 {
1135 if (DescP[1] == ' ')
1136 DescP += 2;
1137 else if (strncmp((char*)DescP, "\nDescription", strlen("\nDescription")) == 0)
1138 DescP += strlen("\nDescription");
1139 else
1140 break;
1141 }
1142 if (DescP != NULL)
1143 ++DescP;
1144 return DescP;
1145 }
1146 bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
1147 {
1148 pkgCache *Cache = CacheFile.GetPkgCache();
1149 if (unlikely(Cache == NULL))
1150 return false;
1151
1152 // Find an appropriate file
1153 pkgCache::VerFileIterator Vf = V.FileList();
1154 for (; Vf.end() == false; ++Vf)
1155 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
1156 break;
1157 if (Vf.end() == true)
1158 Vf = V.FileList();
1159
1160 // Check and load the package list file
1161 pkgCache::PkgFileIterator I = Vf.File();
1162 if (I.IsOk() == false)
1163 return _error->Error(_("Package file %s is out of sync."),I.FileName());
1164
1165 FileFd PkgF;
1166 if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false)
1167 return false;
1168
1169 // Read the record
1170 unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+1];
1171 Buffer[V.FileList()->Size] = '\n';
1172 if (PkgF.Seek(V.FileList()->Offset) == false ||
1173 PkgF.Read(Buffer,V.FileList()->Size) == false)
1174 {
1175 delete [] Buffer;
1176 return false;
1177 }
1178
1179 // Get a pointer to start of Description field
1180 const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "\nDescription");
1181 if (DescP != NULL)
1182 ++DescP;
1183 else
1184 DescP = Buffer + V.FileList()->Size;
1185
1186 // Write all but Description
1187 if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
1188 {
1189 delete [] Buffer;
1190 return false;
1191 }
1192
1193 // Show the right description
1194 pkgRecords Recs(*Cache);
1195 pkgCache::DescIterator Desc = V.TranslatedDescription();
1196 if (Desc.end() == false)
1197 {
1198 pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
1199 cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
1200 cout << std::endl << "Description-md5: " << Desc.md5() << std::endl;
1201
1202 // Find the first field after the description (if there is any)
1203 DescP = skipDescriptionFields(DescP);
1204 }
1205 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
1206
1207 // write the rest of the buffer, but skip mixed in Descriptions* fields
1208 while (DescP != NULL)
1209 {
1210 const unsigned char * const Start = DescP;
1211 const unsigned char *End = (unsigned char*)strstr((char*)DescP, "\nDescription");
1212 if (End == NULL)
1213 {
1214 End = &Buffer[V.FileList()->Size];
1215 DescP = NULL;
1216 }
1217 else
1218 {
1219 ++End; // get the newline into the output
1220 DescP = skipDescriptionFields(End + strlen("Description"));
1221 }
1222 size_t const length = End - Start;
1223 if (fwrite(Start, 1, length, stdout) < length)
1224 {
1225 delete [] Buffer;
1226 return false;
1227 }
1228 }
1229
1230 // write a final newline after the last field
1231 cout<<endl;
1232 delete [] Buffer;
1233
1234 return true;
1235 }
1236 /*}}}*/
1237
1238 struct ExDescFile
1239 {
1240 pkgCache::DescFile *Df;
1241 map_ptrloc ID;
1242 };
1243
1244 // Search - Perform a search /*{{{*/
1245 // ---------------------------------------------------------------------
1246 /* This searches the package names and package descriptions for a pattern */
1247 bool Search(CommandLine &CmdL)
1248 {
1249 bool const ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1250 bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
1251 unsigned int const NumPatterns = CmdL.FileSize() -1;
1252
1253 pkgCacheFile CacheFile;
1254 pkgCache *Cache = CacheFile.GetPkgCache();
1255 pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
1256 if (unlikely(Cache == NULL || Plcy == NULL))
1257 return false;
1258
1259 // Make sure there is at least one argument
1260 if (NumPatterns < 1)
1261 return _error->Error(_("You must give at least one search pattern"));
1262
1263 // Compile the regex pattern
1264 regex_t *Patterns = new regex_t[NumPatterns];
1265 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1266 for (unsigned I = 0; I != NumPatterns; I++)
1267 {
1268 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1269 REG_NOSUB) != 0)
1270 {
1271 for (; I != 0; I--)
1272 regfree(&Patterns[I]);
1273 return _error->Error("Regex compilation error");
1274 }
1275 }
1276
1277 if (_error->PendingError() == true)
1278 {
1279 for (unsigned I = 0; I != NumPatterns; I++)
1280 regfree(&Patterns[I]);
1281 return false;
1282 }
1283
1284 size_t const descCount = Cache->HeaderP->GroupCount + 1;
1285 ExDescFile *DFList = new ExDescFile[descCount];
1286 memset(DFList,0,sizeof(*DFList) * descCount);
1287
1288 bool PatternMatch[descCount * NumPatterns];
1289 memset(PatternMatch,false,sizeof(PatternMatch));
1290
1291 // Map versions that we want to write out onto the VerList array.
1292 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
1293 {
1294 size_t const PatternOffset = G->ID * NumPatterns;
1295 size_t unmatched = 0, matched = 0;
1296 for (unsigned I = 0; I < NumPatterns; ++I)
1297 {
1298 if (PatternMatch[PatternOffset + I] == true)
1299 ++matched;
1300 else if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
1301 PatternMatch[PatternOffset + I] = true;
1302 else
1303 ++unmatched;
1304 }
1305
1306 // already dealt with this package?
1307 if (matched == NumPatterns)
1308 continue;
1309
1310 // Doing names only, drop any that don't match..
1311 if (NamesOnly == true && unmatched == NumPatterns)
1312 continue;
1313
1314 // Find the proper version to use
1315 pkgCache::PkgIterator P = G.FindPreferredPkg();
1316 if (P.end() == true)
1317 continue;
1318 pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
1319 if (V.end() == false)
1320 {
1321 DFList[G->ID].Df = V.TranslatedDescription().FileList();
1322 DFList[G->ID].ID = G->ID;
1323 }
1324
1325 if (unmatched == NumPatterns)
1326 continue;
1327
1328 // Include all the packages that provide matching names too
1329 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; ++Prv)
1330 {
1331 pkgCache::VerIterator V = Plcy->GetCandidateVer(Prv.OwnerPkg());
1332 if (V.end() == true)
1333 continue;
1334
1335 unsigned long id = Prv.OwnerPkg().Group()->ID;
1336 DFList[id].Df = V.TranslatedDescription().FileList();
1337 DFList[id].ID = id;
1338
1339 size_t const PrvPatternOffset = id * NumPatterns;
1340 for (unsigned I = 0; I < NumPatterns; ++I)
1341 PatternMatch[PrvPatternOffset + I] = PatternMatch[PatternOffset + I];
1342 }
1343 }
1344
1345 LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
1346
1347 // Create the text record parser
1348 pkgRecords Recs(*Cache);
1349 // Iterate over all the version records and check them
1350 for (ExDescFile *J = DFList; J->Df != 0; ++J)
1351 {
1352 pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
1353 size_t const PatternOffset = J->ID * NumPatterns;
1354
1355 if (NamesOnly == false)
1356 {
1357 string const LongDesc = P.LongDesc();
1358 for (unsigned I = 0; I < NumPatterns; ++I)
1359 {
1360 if (PatternMatch[PatternOffset + I] == true)
1361 continue;
1362 else if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
1363 PatternMatch[PatternOffset + I] = true;
1364 }
1365 }
1366
1367 bool matchedAll = true;
1368 for (unsigned I = 0; I < NumPatterns; ++I)
1369 if (PatternMatch[PatternOffset + I] == false)
1370 {
1371 matchedAll = false;
1372 break;
1373 }
1374
1375 if (matchedAll == true)
1376 {
1377 if (ShowFull == true)
1378 {
1379 const char *Start;
1380 const char *End;
1381 P.GetRec(Start,End);
1382 fwrite(Start,End-Start,1,stdout);
1383 putc('\n',stdout);
1384 }
1385 else
1386 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1387 }
1388 }
1389
1390 delete [] DFList;
1391 for (unsigned I = 0; I != NumPatterns; I++)
1392 regfree(&Patterns[I]);
1393 if (ferror(stdout))
1394 return _error->Error("Write to stdout failed");
1395 return true;
1396 }
1397 /*}}}*/
1398 /* ShowAuto - show automatically installed packages (sorted) {{{*/
1399 bool ShowAuto(CommandLine &CmdL)
1400 {
1401 pkgCacheFile CacheFile;
1402 pkgCache *Cache = CacheFile.GetPkgCache();
1403 pkgDepCache *DepCache = CacheFile.GetDepCache();
1404 if (unlikely(Cache == NULL || DepCache == NULL))
1405 return false;
1406
1407 std::vector<string> packages;
1408 packages.reserve(Cache->HeaderP->PackageCount / 3);
1409
1410 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
1411 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
1412 packages.push_back(P.Name());
1413
1414 std::sort(packages.begin(), packages.end());
1415
1416 for (vector<string>::iterator I = packages.begin(); I != packages.end(); ++I)
1417 cout << *I << "\n";
1418
1419 _error->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
1420 return true;
1421 }
1422 /*}}}*/
1423 // ShowPackage - Dump the package record to the screen /*{{{*/
1424 // ---------------------------------------------------------------------
1425 /* */
1426 bool ShowPackage(CommandLine &CmdL)
1427 {
1428 pkgCacheFile CacheFile;
1429 CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
1430 APT::VersionList::Version const select = _config->FindB("APT::Cache::AllVersions", true) ?
1431 APT::VersionList::ALL : APT::VersionList::CANDIDATE;
1432 APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper);
1433 for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
1434 if (DisplayRecord(CacheFile, Ver) == false)
1435 return false;
1436
1437 if (verset.empty() == true)
1438 {
1439 if (helper.virtualPkgs.empty() == true)
1440 return _error->Error(_("No packages found"));
1441 else
1442 _error->Notice(_("No packages found"));
1443 }
1444 return true;
1445 }
1446 /*}}}*/
1447 // ShowPkgNames - Show package names /*{{{*/
1448 // ---------------------------------------------------------------------
1449 /* This does a prefix match on the first argument */
1450 bool ShowPkgNames(CommandLine &CmdL)
1451 {
1452 pkgCacheFile CacheFile;
1453 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1454 return false;
1455 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
1456 bool const All = _config->FindB("APT::Cache::AllNames","false");
1457
1458 if (CmdL.FileList[1] != 0)
1459 {
1460 for (;I.end() != true; ++I)
1461 {
1462 if (All == false && I->FirstPackage == 0)
1463 continue;
1464 if (I.FindPkg("any")->VersionList == 0)
1465 continue;
1466 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1467 cout << I.Name() << endl;
1468 }
1469
1470 return true;
1471 }
1472
1473 // Show all pkgs
1474 for (;I.end() != true; ++I)
1475 {
1476 if (All == false && I->FirstPackage == 0)
1477 continue;
1478 if (I.FindPkg("any")->VersionList == 0)
1479 continue;
1480 cout << I.Name() << endl;
1481 }
1482
1483 return true;
1484 }
1485 /*}}}*/
1486 // ShowSrcPackage - Show source package records /*{{{*/
1487 // ---------------------------------------------------------------------
1488 /* */
1489 bool ShowSrcPackage(CommandLine &CmdL)
1490 {
1491 pkgCacheFile CacheFile;
1492 pkgSourceList *List = CacheFile.GetSourceList();
1493 if (unlikely(List == NULL))
1494 return false;
1495
1496 // Create the text record parsers
1497 pkgSrcRecords SrcRecs(*List);
1498 if (_error->PendingError() == true)
1499 return false;
1500
1501 unsigned found = 0;
1502 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1503 {
1504 SrcRecs.Restart();
1505
1506 pkgSrcRecords::Parser *Parse;
1507 unsigned found_this = 0;
1508 while ((Parse = SrcRecs.Find(*I,false)) != 0) {
1509 cout << Parse->AsStr() << endl;;
1510 found++;
1511 found_this++;
1512 }
1513 if (found_this == 0) {
1514 _error->Warning(_("Unable to locate package %s"),*I);
1515 continue;
1516 }
1517 }
1518 if (found == 0)
1519 _error->Notice(_("No packages found"));
1520 return true;
1521 }
1522 /*}}}*/
1523 // Policy - Show the results of the preferences file /*{{{*/
1524 // ---------------------------------------------------------------------
1525 /* */
1526 bool Policy(CommandLine &CmdL)
1527 {
1528 pkgCacheFile CacheFile;
1529 pkgCache *Cache = CacheFile.GetPkgCache();
1530 pkgPolicy *Plcy = CacheFile.GetPolicy();
1531 pkgSourceList *SrcList = CacheFile.GetSourceList();
1532 if (unlikely(Cache == NULL || Plcy == NULL || SrcList == NULL))
1533 return false;
1534
1535 /* Should the MultiArchKiller be run to see which pseudo packages for an
1536 arch all package are currently installed? Activating it gives a speed
1537 penality for no real gain beside enhanced debugging, so in general no. */
1538 if (_config->FindB("APT::Cache::Policy::DepCache", false) == true)
1539 CacheFile.GetDepCache();
1540
1541 // Print out all of the package files
1542 if (CmdL.FileList[1] == 0)
1543 {
1544 cout << _("Package files:") << endl;
1545 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
1546 {
1547 // Locate the associated index files so we can derive a description
1548 pkgIndexFile *Indx;
1549 if (SrcList->FindIndex(F,Indx) == false &&
1550 _system->FindIndex(F,Indx) == false)
1551 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1552
1553 printf("%4i %s\n",
1554 Plcy->GetPriority(F),Indx->Describe(true).c_str());
1555
1556 // Print the reference information for the package
1557 string Str = F.RelStr();
1558 if (Str.empty() == false)
1559 printf(" release %s\n",F.RelStr().c_str());
1560 if (F.Site() != 0 && F.Site()[0] != 0)
1561 printf(" origin %s\n",F.Site());
1562 }
1563
1564 // Show any packages have explicit pins
1565 cout << _("Pinned packages:") << endl;
1566 pkgCache::PkgIterator I = Cache->PkgBegin();
1567 for (;I.end() != true; ++I)
1568 {
1569 if (Plcy->GetPriority(I) == 0)
1570 continue;
1571
1572 // Print the package name and the version we are forcing to
1573 cout << " " << I.FullName(true) << " -> ";
1574
1575 pkgCache::VerIterator V = Plcy->GetMatch(I);
1576 if (V.end() == true)
1577 cout << _("(not found)") << endl;
1578 else
1579 cout << V.VerStr() << endl;
1580 }
1581
1582 return true;
1583 }
1584
1585 char const * const msgInstalled = _(" Installed: ");
1586 char const * const msgCandidate = _(" Candidate: ");
1587 short const InstalledLessCandidate =
1588 mbstowcs(NULL, msgInstalled, 0) - mbstowcs(NULL, msgCandidate, 0);
1589 short const deepInstalled =
1590 (InstalledLessCandidate < 0 ? (InstalledLessCandidate*-1) : 0) - 1;
1591 short const deepCandidate =
1592 (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
1593
1594 // Print out detailed information for each package
1595 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1596 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1597 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
1598 {
1599 cout << Pkg.FullName(true) << ":" << endl;
1600
1601 // Installed version
1602 cout << msgInstalled << OutputInDepth(deepInstalled, " ");
1603 if (Pkg->CurrentVer == 0)
1604 cout << _("(none)") << endl;
1605 else
1606 cout << Pkg.CurrentVer().VerStr() << endl;
1607
1608 // Candidate Version
1609 cout << msgCandidate << OutputInDepth(deepCandidate, " ");
1610 pkgCache::VerIterator V = Plcy->GetCandidateVer(Pkg);
1611 if (V.end() == true)
1612 cout << _("(none)") << endl;
1613 else
1614 cout << V.VerStr() << endl;
1615
1616 // Pinned version
1617 if (Plcy->GetPriority(Pkg) != 0)
1618 {
1619 cout << _(" Package pin: ");
1620 V = Plcy->GetMatch(Pkg);
1621 if (V.end() == true)
1622 cout << _("(not found)") << endl;
1623 else
1624 cout << V.VerStr() << endl;
1625 }
1626
1627 // Show the priority tables
1628 cout << _(" Version table:") << endl;
1629 for (V = Pkg.VersionList(); V.end() == false; ++V)
1630 {
1631 if (Pkg.CurrentVer() == V)
1632 cout << " *** " << V.VerStr();
1633 else
1634 cout << " " << V.VerStr();
1635 cout << " " << Plcy->GetPriority(Pkg) << endl;
1636 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
1637 {
1638 // Locate the associated index files so we can derive a description
1639 pkgIndexFile *Indx;
1640 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1641 _system->FindIndex(VF.File(),Indx) == false)
1642 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1643 printf(" %4i %s\n",Plcy->GetPriority(VF.File()),
1644 Indx->Describe(true).c_str());
1645 }
1646 }
1647 }
1648
1649 return true;
1650 }
1651 /*}}}*/
1652 // Madison - Look a bit like katie's madison /*{{{*/
1653 // ---------------------------------------------------------------------
1654 /* */
1655 bool Madison(CommandLine &CmdL)
1656 {
1657 pkgCacheFile CacheFile;
1658 pkgSourceList *SrcList = CacheFile.GetSourceList();
1659
1660 if (SrcList == 0)
1661 return false;
1662
1663 // Create the src text record parsers and ignore errors about missing
1664 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1665 pkgSrcRecords SrcRecs(*SrcList);
1666 if (_error->PendingError() == true)
1667 _error->Discard();
1668
1669 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1670 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1671 {
1672 _error->PushToStack();
1673 APT::PackageList pkgset = APT::PackageList::FromString(CacheFile, *I, helper);
1674 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
1675 {
1676 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; ++V)
1677 {
1678 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
1679 {
1680 // This might be nice, but wouldn't uniquely identify the source -mdz
1681 // if (VF.File().Archive() != 0)
1682 // {
1683 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1684 // << VF.File().Archive() << endl;
1685 // }
1686
1687 // Locate the associated index files so we can derive a description
1688 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S)
1689 {
1690 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1691 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
1692 IF != Indexes->end(); ++IF)
1693 {
1694 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1695 {
1696 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
1697 << (*IF)->Describe(true) << endl;
1698 }
1699 }
1700 }
1701 }
1702 }
1703 }
1704
1705 SrcRecs.Restart();
1706 pkgSrcRecords::Parser *SrcParser;
1707 bool foundSomething = false;
1708 while ((SrcParser = SrcRecs.Find(*I, false)) != 0)
1709 {
1710 foundSomething = true;
1711 // Maybe support Release info here too eventually
1712 cout << setw(10) << SrcParser->Package() << " | "
1713 << setw(10) << SrcParser->Version() << " | "
1714 << SrcParser->Index().Describe(true) << endl;
1715 }
1716 if (foundSomething == true)
1717 _error->RevertToStack();
1718 else
1719 _error->MergeWithStack();
1720 }
1721
1722 return true;
1723 }
1724 /*}}}*/
1725 // GenCaches - Call the main cache generator /*{{{*/
1726 // ---------------------------------------------------------------------
1727 /* */
1728 bool GenCaches(CommandLine &Cmd)
1729 {
1730 OpTextProgress Progress(*_config);
1731
1732 pkgCacheFile CacheFile;
1733 return CacheFile.BuildCaches(&Progress, true);
1734 }
1735 /*}}}*/
1736 // ShowHelp - Show a help screen /*{{{*/
1737 // ---------------------------------------------------------------------
1738 /* */
1739 bool ShowHelp(CommandLine &Cmd)
1740 {
1741 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION,
1742 COMMON_ARCH,__DATE__,__TIME__);
1743
1744 if (_config->FindB("version") == true)
1745 return true;
1746
1747 cout <<
1748 _("Usage: apt-cache [options] command\n"
1749 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1750 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1751 "\n"
1752 "apt-cache is a low-level tool used to query information\n"
1753 "from APT's binary cache files\n"
1754 "\n"
1755 "Commands:\n"
1756 " gencaches - Build both the package and source cache\n"
1757 " showpkg - Show some general information for a single package\n"
1758 " showsrc - Show source records\n"
1759 " stats - Show some basic statistics\n"
1760 " dump - Show the entire file in a terse form\n"
1761 " dumpavail - Print an available file to stdout\n"
1762 " unmet - Show unmet dependencies\n"
1763 " search - Search the package list for a regex pattern\n"
1764 " show - Show a readable record for the package\n"
1765 " depends - Show raw dependency information for a package\n"
1766 " rdepends - Show reverse dependency information for a package\n"
1767 " pkgnames - List the names of all packages in the system\n"
1768 " dotty - Generate package graphs for GraphViz\n"
1769 " xvcg - Generate package graphs for xvcg\n"
1770 " policy - Show policy settings\n"
1771 "\n"
1772 "Options:\n"
1773 " -h This help text.\n"
1774 " -p=? The package cache.\n"
1775 " -s=? The source cache.\n"
1776 " -q Disable progress indicator.\n"
1777 " -i Show only important deps for the unmet command.\n"
1778 " -c=? Read this configuration file\n"
1779 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1780 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1781 return true;
1782 }
1783 /*}}}*/
1784 int main(int argc,const char *argv[]) /*{{{*/
1785 {
1786 CommandLine::Args Args[] = {
1787 {'h',"help","help",0},
1788 {'v',"version","version",0},
1789 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1790 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1791 {'q',"quiet","quiet",CommandLine::IntLevel},
1792 {'i',"important","APT::Cache::Important",0},
1793 {'f',"full","APT::Cache::ShowFull",0},
1794 {'g',"generate","APT::Cache::Generate",0},
1795 {'a',"all-versions","APT::Cache::AllVersions",0},
1796 {'n',"names-only","APT::Cache::NamesOnly",0},
1797 {0,"all-names","APT::Cache::AllNames",0},
1798 {0,"recurse","APT::Cache::RecurseDepends",0},
1799 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
1800 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
1801 {'c',"config-file",0,CommandLine::ConfigFile},
1802 {'o',"option",0,CommandLine::ArbItem},
1803 {0,"installed","APT::Cache::Installed",0},
1804 {0,"pre-depends","APT::Cache::ShowPre-Depends",0},
1805 {0,"depends","APT::Cache::ShowDepends",0},
1806 {0,"recommends","APT::Cache::ShowRecommends",0},
1807 {0,"suggests","APT::Cache::ShowSuggests",0},
1808 {0,"replaces","APT::Cache::ShowReplaces",0},
1809 {0,"breaks","APT::Cache::ShowBreaks",0},
1810 {0,"conflicts","APT::Cache::ShowConflicts",0},
1811 {0,"enhances","APT::Cache::ShowEnhances",0},
1812 {0,0,0,0}};
1813 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1814 {"gencaches",&GenCaches},
1815 {"showsrc",&ShowSrcPackage},
1816 {0,0}};
1817 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1818 {"stats",&Stats},
1819 {"dump",&Dump},
1820 {"dumpavail",&DumpAvail},
1821 {"unmet",&UnMet},
1822 {"search",&Search},
1823 {"depends",&Depends},
1824 {"rdepends",&RDepends},
1825 {"dotty",&Dotty},
1826 {"xvcg",&XVcg},
1827 {"show",&ShowPackage},
1828 {"pkgnames",&ShowPkgNames},
1829 {"showauto",&ShowAuto},
1830 {"policy",&Policy},
1831 {"madison",&Madison},
1832 {0,0}};
1833
1834 // Set up gettext support
1835 setlocale(LC_ALL,"");
1836 textdomain(PACKAGE);
1837
1838 // Parse the command line and initialize the package library
1839 CommandLine CmdL(Args,_config);
1840 if (pkgInitConfig(*_config) == false ||
1841 CmdL.Parse(argc,argv) == false ||
1842 pkgInitSystem(*_config,_system) == false)
1843 {
1844 _error->DumpErrors();
1845 return 100;
1846 }
1847
1848 // See if the help should be shown
1849 if (_config->FindB("help") == true ||
1850 CmdL.FileSize() == 0)
1851 {
1852 ShowHelp(CmdL);
1853 return 0;
1854 }
1855
1856 // Deal with stdout not being a tty
1857 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
1858 _config->Set("quiet","1");
1859
1860 if (_config->Exists("APT::Cache::Generate") == true)
1861 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1862
1863 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
1864 CmdL.DispatchArg(CmdsB);
1865
1866 // Print any errors or warnings found during parsing
1867 bool const Errors = _error->PendingError();
1868 if (_config->FindI("quiet",0) > 0)
1869 _error->DumpErrors();
1870 else
1871 _error->DumpErrors(GlobalError::DEBUG);
1872 return Errors == true ? 100 : 0;
1873 }
1874 /*}}}*/