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