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