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