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