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