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