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