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