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