]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
apt-key: don't search PATH if command is a path already
[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>
9055d5e6 46#include <apt-private/private-depends.h>
501cd23e 47#include <apt-private/private-show.h>
631800b1 48#include <apt-private/private-search.h>
0a778f71 49#include <apt-private/private-unmet.h>
e7e10e47 50#include <apt-private/private-main.h>
b9179170 51
9dbb421f 52#include <regex.h>
453b82a3 53#include <stddef.h>
3e94da1b 54#include <stdio.h>
453b82a3
DK
55#include <stdlib.h>
56#include <unistd.h>
472ff00e 57#include <algorithm>
453b82a3
DK
58#include <cstring>
59#include <iomanip>
60#include <iostream>
61#include <list>
62#include <map>
63#include <set>
64#include <string>
65#include <vector>
ea542140
DK
66
67#include <apti18n.h>
1164783d
AL
68 /*}}}*/
69
8f312f45
AL
70using namespace std;
71
1164783d
AL
72// DumpPackage - Show a dump of a package record /*{{{*/
73// ---------------------------------------------------------------------
74/* */
c3ccac92 75static bool DumpPackage(CommandLine &CmdL)
d9eb210e
DK
76{
77 pkgCacheFile CacheFile;
cd7bbc47 78 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
c4cca791 79 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1164783d 80
c4cca791 81 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
78c32596 82 {
75ce2062 83 cout << "Package: " << Pkg.FullName(true) << endl;
b2e465d6 84 cout << "Versions: " << endl;
f7f0d6c7 85 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
03e39e59
AL
86 {
87 cout << Cur.VerStr();
f7f0d6c7 88 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; ++Vf)
a52f938b
OS
89 cout << " (" << Vf.File().FileName() << ")";
90 cout << endl;
f7f0d6c7 91 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; ++D)
a52f938b
OS
92 {
93 cout << " Description Language: " << D.LanguageCode() << endl
94 << " File: " << D.FileList().File().FileName() << endl
95 << " MD5: " << D.md5() << endl;
96 }
b2e465d6 97 cout << endl;
03e39e59
AL
98 }
99
1164783d
AL
100 cout << endl;
101
102 cout << "Reverse Depends: " << endl;
f7f0d6c7 103 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D)
b2e465d6 104 {
75ce2062 105 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
b2e465d6 106 if (D->Version != 0)
b1b663d1 107 cout << ' ' << DeNull(D.TargetVer()) << endl;
b2e465d6
AL
108 else
109 cout << endl;
110 }
111
1164783d 112 cout << "Dependencies: " << endl;
f7f0d6c7 113 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
1164783d
AL
114 {
115 cout << Cur.VerStr() << " - ";
f7f0d6c7 116 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; ++Dep)
75ce2062 117 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
1164783d
AL
118 cout << endl;
119 }
120
121 cout << "Provides: " << endl;
f7f0d6c7 122 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
1164783d
AL
123 {
124 cout << Cur.VerStr() << " - ";
f7f0d6c7 125 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; ++Prv)
ecc138f8 126 cout << Prv.ParentPkg().FullName(true) << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ") ";
1164783d 127 cout << endl;
8efa2a3b
AL
128 }
129 cout << "Reverse Provides: " << endl;
f7f0d6c7 130 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; ++Prv)
ecc138f8 131 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ")"<< endl;
1164783d
AL
132 }
133
134 return true;
135}
136 /*}}}*/
637c3b23
MV
137// ShowHashTableStats - Show stats about a hashtable /*{{{*/
138// ---------------------------------------------------------------------
139/* */
32ab4bd0
DK
140static map_pointer_t PackageNext(pkgCache::Package const * const P) { return P->NextPackage; }
141static map_pointer_t GroupNext(pkgCache::Group const * const G) { return G->Next; }
637c3b23
MV
142template<class T>
143static void ShowHashTableStats(std::string Type,
144 T *StartP,
ac2c559b 145 map_pointer_t *Hashtable,
32ab4bd0
DK
146 unsigned long Size,
147 map_pointer_t(*Next)(T const * const))
637c3b23
MV
148{
149 // hashtable stats for the HashTable
ac2c559b
DK
150 unsigned long NumBuckets = Size;
151 unsigned long UsedBuckets = 0;
152 unsigned long UnusedBuckets = 0;
153 unsigned long LongestBucket = 0;
154 unsigned long ShortestBucket = NumBuckets;
155 unsigned long Entries = 0;
637c3b23
MV
156 for (unsigned int i=0; i < NumBuckets; ++i)
157 {
158 T *P = StartP + Hashtable[i];
159 if(P == 0 || P == StartP)
160 {
ac2c559b 161 ++UnusedBuckets;
637c3b23
MV
162 continue;
163 }
ac2c559b
DK
164 ++UsedBuckets;
165 unsigned long ThisBucketSize = 0;
32ab4bd0 166 for (; P != StartP; P = StartP + Next(P))
ac2c559b
DK
167 ++ThisBucketSize;
168 Entries += ThisBucketSize;
637c3b23
MV
169 LongestBucket = std::max(ThisBucketSize, LongestBucket);
170 ShortestBucket = std::min(ThisBucketSize, ShortestBucket);
637c3b23 171 }
ac2c559b
DK
172 cout << "Total buckets in " << Type << ": " << NumBuckets << std::endl;
173 cout << " Unused: " << UnusedBuckets << std::endl;
637c3b23 174 cout << " Used: " << UsedBuckets << std::endl;
38a5b1ce 175 cout << " Utilization: " << 100.0 * UsedBuckets/NumBuckets << "%" << std::endl;
6d7fc45e 176 cout << " Average entries: " << Entries/(double)UsedBuckets << std::endl;
637c3b23
MV
177 cout << " Longest: " << LongestBucket << std::endl;
178 cout << " Shortest: " << ShortestBucket << std::endl;
179}
180 /*}}}*/
1164783d
AL
181// Stats - Dump some nice statistics /*{{{*/
182// ---------------------------------------------------------------------
183/* */
714c23a7 184static bool Stats(CommandLine &CmdL)
1164783d 185{
714c23a7
JAK
186 if (CmdL.FileSize() > 1) {
187 _error->Error(_("apt-cache stats does not take any arguments"));
188 return false;
189 }
7414af7f
DK
190
191 pkgCacheFile CacheFile;
192 pkgCache *Cache = CacheFile.GetPkgCache();
193
d9eb210e
DK
194 if (unlikely(Cache == NULL))
195 return false;
196
197 cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
198 SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
199 << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
200 SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
b2e465d6 201
1164783d
AL
202 int Normal = 0;
203 int Virtual = 0;
204 int NVirt = 0;
205 int DVirt = 0;
206 int Missing = 0;
d9eb210e 207 pkgCache::PkgIterator I = Cache->PkgBegin();
f7f0d6c7 208 for (;I.end() != true; ++I)
1164783d
AL
209 {
210 if (I->VersionList != 0 && I->ProvidesList == 0)
211 {
212 Normal++;
213 continue;
214 }
215
216 if (I->VersionList != 0 && I->ProvidesList != 0)
217 {
218 NVirt++;
219 continue;
220 }
221
222 if (I->VersionList == 0 && I->ProvidesList != 0)
223 {
224 // Only 1 provides
225 if (I.ProvidesList()->NextProvides == 0)
226 {
227 DVirt++;
228 }
229 else
230 Virtual++;
231 continue;
232 }
233 if (I->VersionList == 0 && I->ProvidesList == 0)
234 {
235 Missing++;
236 continue;
237 }
238 }
db0db9fe
CP
239 cout << _(" Normal packages: ") << Normal << endl;
240 cout << _(" Pure virtual packages: ") << Virtual << endl;
241 cout << _(" Single virtual packages: ") << DVirt << endl;
242 cout << _(" Mixed virtual packages: ") << NVirt << endl;
b2e465d6 243 cout << _(" Missing: ") << Missing << endl;
71c9e95b 244
d9eb210e
DK
245 cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
246 SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
247 cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
248 SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
71c9e95b
DK
249 cout << _("Total dependencies: ") << Cache->Head().DependsCount << "/" << Cache->Head().DependsDataCount << " (" <<
250 SizeToStr((Cache->Head().DependsCount*Cache->Head().DependencySz) +
251 (Cache->Head().DependsDataCount*Cache->Head().DependencyDataSz)) << ')' << endl;
d9eb210e
DK
252 cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
253 SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
254 cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
255 SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
256 cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
257 SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
b2e465d6 258
a3a91fd7
DK
259 // String list stats
260 std::set<map_stringitem_t> stritems;
261 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
262 stritems.insert(G->Name);
f7f0d6c7 263 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
b2e465d6 264 {
a3a91fd7 265 stritems.insert(P->Arch);
f7f0d6c7 266 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
b2e465d6 267 {
a3a91fd7
DK
268 if (V->VerStr != 0)
269 stritems.insert(V->VerStr);
270 if (V->Section != 0)
271 stritems.insert(V->Section);
a221efc3
DK
272 stritems.insert(V->SourcePkgName);
273 stritems.insert(V->SourceVerStr);
f7f0d6c7 274 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
b2e465d6
AL
275 {
276 if (D->Version != 0)
a3a91fd7
DK
277 stritems.insert(D->Version);
278 }
279 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
280 {
281 stritems.insert(D->md5sum);
282 stritems.insert(D->language_code);
b2e465d6
AL
283 }
284 }
a3a91fd7
DK
285 for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
286 {
287 if (Prv->ProvideVersion != 0)
288 stritems.insert(Prv->ProvideVersion);
289 }
b2e465d6 290 }
b07aeb1a 291 for (pkgCache::RlsFileIterator F = Cache->RlsFileBegin(); F != Cache->RlsFileEnd(); ++F)
a3a91fd7
DK
292 {
293 stritems.insert(F->FileName);
294 stritems.insert(F->Archive);
295 stritems.insert(F->Codename);
a3a91fd7
DK
296 stritems.insert(F->Version);
297 stritems.insert(F->Origin);
298 stritems.insert(F->Label);
a3a91fd7 299 stritems.insert(F->Site);
b07aeb1a
DK
300 }
301 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
302 {
303 stritems.insert(F->FileName);
304 stritems.insert(F->Architecture);
305 stritems.insert(F->Component);
a3a91fd7
DK
306 stritems.insert(F->IndexType);
307 }
4dc77823 308
a3a91fd7
DK
309 unsigned long Size = 0;
310 for (std::set<map_stringitem_t>::const_iterator i = stritems.begin(); i != stritems.end(); ++i)
311 Size += strlen(Cache->StrP + *i) + 1;
a3a91fd7
DK
312 cout << _("Total globbed strings: ") << stritems.size() << " (" << SizeToStr(Size) << ')' << endl;
313 stritems.clear();
ac2c559b 314
f826cfaa
AL
315 unsigned long Slack = 0;
316 for (int I = 0; I != 7; I++)
d9eb210e 317 Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
db0db9fe 318 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
ac2c559b 319
f826cfaa 320 unsigned long Total = 0;
ac2c559b
DK
321#define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
322 Total = Slack + Size +
323 APT_CACHESIZE(GroupCount, GroupSz) +
324 APT_CACHESIZE(PackageCount, PackageSz) +
325 APT_CACHESIZE(VersionCount, VersionSz) +
326 APT_CACHESIZE(DescriptionCount, DescriptionSz) +
327 APT_CACHESIZE(DependsCount, DependencySz) +
71c9e95b 328 APT_CACHESIZE(DependsDataCount, DependencyDataSz) +
b07aeb1a 329 APT_CACHESIZE(ReleaseFileCount, ReleaseFileSz) +
ac2c559b
DK
330 APT_CACHESIZE(PackageFileCount, PackageFileSz) +
331 APT_CACHESIZE(VerFileCount, VerFileSz) +
332 APT_CACHESIZE(DescFileCount, DescFileSz) +
333 APT_CACHESIZE(ProvidesCount, ProvidesSz) +
32ab4bd0 334 (2 * Cache->Head().GetHashTableSize() * sizeof(map_id_t));
db0db9fe 335 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
ac2c559b 336#undef APT_CACHESIZE
a93a32b5 337
637c3b23 338 // hashtable stats
32ab4bd0
DK
339 ShowHashTableStats<pkgCache::Package>("PkgHashTable", Cache->PkgP, Cache->Head().PkgHashTableP(), Cache->Head().GetHashTableSize(), PackageNext);
340 ShowHashTableStats<pkgCache::Group>("GrpHashTable", Cache->GrpP, Cache->Head().GrpHashTableP(), Cache->Head().GetHashTableSize(), GroupNext);
a93a32b5 341
83d89a9f
AL
342 return true;
343}
344 /*}}}*/
1164783d
AL
345// Dump - show everything /*{{{*/
346// ---------------------------------------------------------------------
b2e465d6 347/* This is worthless except fer debugging things */
65512241 348static bool Dump(CommandLine &)
1164783d 349{
d9eb210e
DK
350 pkgCacheFile CacheFile;
351 pkgCache *Cache = CacheFile.GetPkgCache();
352 if (unlikely(Cache == NULL))
353 return false;
354
b9179170 355 std::cout << "Using Versioning System: " << Cache->VS->Label << std::endl;
b2e465d6 356
f7f0d6c7 357 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
1164783d 358 {
b9179170 359 std::cout << "Package: " << P.FullName(true) << std::endl;
f7f0d6c7 360 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
1164783d 361 {
b9179170
MV
362 std::cout << " Version: " << V.VerStr() << std::endl;
363 std::cout << " File: " << V.FileList().File().FileName() << std::endl;
f7f0d6c7 364 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
b9179170
MV
365 std::cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
366 DeNull(D.TargetVer()) << std::endl;
f7f0d6c7 367 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
a52f938b 368 {
b9179170
MV
369 std::cout << " Description Language: " << D.LanguageCode() << std::endl
370 << " File: " << D.FileList().File().FileName() << std::endl
371 << " MD5: " << D.md5() << std::endl;
a52f938b 372 }
1164783d
AL
373 }
374 }
375
f7f0d6c7 376 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
1164783d 377 {
b9179170
MV
378 std::cout << "File: " << F.FileName() << std::endl;
379 std::cout << " Type: " << F.IndexType() << std::endl;
380 std::cout << " Size: " << F->Size << std::endl;
381 std::cout << " ID: " << F->ID << std::endl;
382 std::cout << " Flags: " << F->Flags << std::endl;
383 std::cout << " Time: " << TimeRFC1123(F->mtime) << std::endl;
384 std::cout << " Archive: " << DeNull(F.Archive()) << std::endl;
385 std::cout << " Component: " << DeNull(F.Component()) << std::endl;
386 std::cout << " Version: " << DeNull(F.Version()) << std::endl;
387 std::cout << " Origin: " << DeNull(F.Origin()) << std::endl;
388 std::cout << " Site: " << DeNull(F.Site()) << std::endl;
389 std::cout << " Label: " << DeNull(F.Label()) << std::endl;
390 std::cout << " Architecture: " << DeNull(F.Architecture()) << std::endl;
1164783d
AL
391 }
392
393 return true;
394}
395 /*}}}*/
396// DumpAvail - Print out the available list /*{{{*/
397// ---------------------------------------------------------------------
b2e465d6
AL
398/* This is needed to make dpkg --merge happy.. I spent a bit of time to
399 make this run really fast, perhaps I went a little overboard.. */
65512241 400static bool DumpAvail(CommandLine &)
1164783d 401{
d9eb210e
DK
402 pkgCacheFile CacheFile;
403 pkgCache *Cache = CacheFile.GetPkgCache();
404 if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
b2e465d6 405 return false;
d9eb210e
DK
406
407 unsigned long Count = Cache->HeaderP->PackageCount+1;
fe648919
AL
408 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
409 memset(VFList,0,sizeof(*VFList)*Count);
b2e465d6
AL
410
411 // Map versions that we want to write out onto the VerList array.
f7f0d6c7 412 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
b2e465d6
AL
413 {
414 if (P->VersionList == 0)
5b8c90bf
AL
415 continue;
416
b2e465d6
AL
417 /* Find the proper version to use. If the policy says there are no
418 possible selections we return the installed version, if available..
419 This prevents dselect from making it obsolete. */
d9eb210e 420 pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
b2e465d6 421 if (V.end() == true)
ad00ae81 422 {
b2e465d6
AL
423 if (P->CurrentVer == 0)
424 continue;
425 V = P.CurrentVer();
ad00ae81 426 }
1164783d 427
b2e465d6 428 pkgCache::VerFileIterator VF = V.FileList();
f7f0d6c7 429 for (; VF.end() == false ; ++VF)
b2e465d6
AL
430 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
431 break;
432
433 /* Okay, here we have a bit of a problem.. The policy has selected the
434 currently installed package - however it only exists in the
435 status file.. We need to write out something or dselect will mark
436 the package as obsolete! Thus we emit the status file entry, but
437 below we remove the status line to make it valid for the
438 available file. However! We only do this if their do exist *any*
439 non-source versions of the package - that way the dselect obsolete
440 handling works OK. */
441 if (VF.end() == true)
1164783d 442 {
f7f0d6c7 443 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; ++Cur)
b2e465d6 444 {
f7f0d6c7 445 for (VF = Cur.FileList(); VF.end() == false; ++VF)
b2e465d6
AL
446 {
447 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
448 {
449 VF = V.FileList();
450 break;
451 }
452 }
453
454 if (VF.end() == false)
455 break;
456 }
ad00ae81 457 }
b2e465d6
AL
458
459 VFList[P->ID] = VF;
460 }
461
fe648919 462 LocalitySort(VFList,Count,sizeof(*VFList));
ad00ae81 463
88593886
DK
464 std::vector<pkgTagSection::Tag> RW;
465 RW.push_back(pkgTagSection::Tag::Remove("Status"));
466 RW.push_back(pkgTagSection::Tag::Remove("Config-Version"));
467 FileFd stdoutfd;
468 stdoutfd.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false);
469
b2e465d6 470 // Iterate over all the package files and write them out.
d9eb210e 471 char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
b2e465d6
AL
472 for (pkgCache::VerFile **J = VFList; *J != 0;)
473 {
d9eb210e 474 pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
b2e465d6 475 if (File.IsOk() == false)
ad00ae81 476 {
b2e465d6
AL
477 _error->Error(_("Package file %s is out of sync."),File.FileName());
478 break;
479 }
bd432be3 480
4dde2b42 481 FileFd PkgF(File.FileName(),FileFd::ReadOnly, FileFd::Extension);
b2e465d6
AL
482 if (_error->PendingError() == true)
483 break;
484
485 /* Write all of the records from this package file, since we
486 already did locality sorting we can now just seek through the
487 file in read order. We apply 1 more optimization here, since often
488 there will be < 1 byte gaps between records (for the \n) we read that
489 into the next buffer and offset a bit.. */
490 unsigned long Pos = 0;
491 for (; *J != 0; J++)
492 {
d9eb210e 493 if ((*J)->File + Cache->PkgFileP != File)
b2e465d6 494 break;
bd432be3 495
b2e465d6
AL
496 const pkgCache::VerFile &VF = **J;
497
bd432be3 498 // Read the record and then write it out again.
b2e465d6
AL
499 unsigned long Jitter = VF.Offset - Pos;
500 if (Jitter > 8)
1164783d 501 {
b2e465d6
AL
502 if (PkgF.Seek(VF.Offset) == false)
503 break;
504 Jitter = 0;
505 }
506
507 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
508 break;
509 Buffer[VF.Size + Jitter] = '\n';
88593886 510
b2e465d6
AL
511 // See above..
512 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
513 {
514 pkgTagSection Tags;
b2e465d6 515 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
88593886
DK
516 Tags.Write(stdoutfd, NULL, RW) == false ||
517 stdoutfd.Write("\n", 1) == false)
b2e465d6
AL
518 {
519 _error->Error("Internal Error, Unable to parse a package record");
520 break;
521 }
b2e465d6
AL
522 }
523 else
524 {
88593886 525 if (stdoutfd.Write(Buffer + Jitter, VF.Size + 1) == false)
b2e465d6
AL
526 break;
527 }
88593886 528
b2e465d6 529 Pos = VF.Offset + VF.Size;
1164783d 530 }
b2e465d6 531
b2e465d6
AL
532 if (_error->PendingError() == true)
533 break;
ad00ae81 534 }
88593886 535
b2e465d6
AL
536 delete [] Buffer;
537 delete [] VFList;
538 return !_error->PendingError();
349cd3b8
AL
539}
540 /*}}}*/
fff4b7f3
AL
541// xvcg - Generate a graph for xvcg /*{{{*/
542// ---------------------------------------------------------------------
543// Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
544
c3ccac92 545static bool XVcg(CommandLine &CmdL)
fff4b7f3 546{
d9eb210e
DK
547 pkgCacheFile CacheFile;
548 pkgCache *Cache = CacheFile.GetPkgCache();
549 if (unlikely(Cache == NULL))
550 return false;
551
fff4b7f3
AL
552 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
553
554 /* Normal packages are boxes
555 Pure Provides are triangles
556 Mixed are diamonds
557 rhomb are missing packages*/
558 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
559
560 /* Initialize the list of packages to show.
561 1 = To Show
562 2 = To Show no recurse
563 3 = Emitted no recurse
564 4 = Emitted
565 0 = None */
566 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
567 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
568 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
569 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
570 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
fff4b7f3
AL
571
572 // Show everything if no arguments given
573 if (CmdL.FileList[1] == 0)
d9eb210e 574 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3
AL
575 Show[I] = ToShow;
576 else
d9eb210e 577 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3 578 Show[I] = None;
d9eb210e 579 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
fff4b7f3
AL
580
581 // Map the shapes
f7f0d6c7 582 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
583 {
584 if (Pkg->VersionList == 0)
585 {
586 // Missing
587 if (Pkg->ProvidesList == 0)
588 ShapeMap[Pkg->ID] = 0;
589 else
590 ShapeMap[Pkg->ID] = 1;
591 }
592 else
593 {
594 // Normal
595 if (Pkg->ProvidesList == 0)
596 ShapeMap[Pkg->ID] = 2;
597 else
598 ShapeMap[Pkg->ID] = 3;
599 }
600 }
3c977245 601
fff4b7f3 602 // Load the list of packages from the command line into the show list
cd7bbc47 603 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
fdba4d53
DK
604 std::list<APT::CacheSetHelper::PkgModifier> mods;
605 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
606 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
3c977245 607 std::map<unsigned short, APT::PackageSet> pkgsets =
cd7bbc47 608 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
3c977245
DK
609
610 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
611 Pkg != pkgsets[0].end(); ++Pkg)
612 Show[Pkg->ID] = ToShow;
613 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
614 Pkg != pkgsets[1].end(); ++Pkg)
fff4b7f3 615 {
fff4b7f3 616 Show[Pkg->ID] = ToShow;
3c977245 617 Flags[Pkg->ID] |= ForceNR;
fff4b7f3 618 }
3c977245 619
fff4b7f3
AL
620 // Little header
621 cout << "graph: { title: \"packages\"" << endl <<
622 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
623 "layout_downfactor: 8" << endl;
624
625 bool Act = true;
626 while (Act == true)
627 {
628 Act = false;
f7f0d6c7 629 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
630 {
631 // See we need to show this package
632 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
633 continue;
634
635 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
636
637 // Colour as done
638 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
639 {
640 // Pure Provides and missing packages have no deps!
641 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
642 Show[Pkg->ID] = Done;
643 else
644 Show[Pkg->ID] = DoneNR;
645 }
646 else
647 Show[Pkg->ID] = Done;
648 Act = true;
649
650 // No deps to map out
651 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
652 continue;
653
654 pkgCache::VerIterator Ver = Pkg.VersionList();
f7f0d6c7 655 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
fff4b7f3
AL
656 {
657 // See if anything can meet this dep
658 // Walk along the actual package providing versions
659 bool Hit = false;
660 pkgCache::PkgIterator DPkg = D.TargetPkg();
661 for (pkgCache::VerIterator I = DPkg.VersionList();
f7f0d6c7 662 I.end() == false && Hit == false; ++I)
fff4b7f3 663 {
d9eb210e 664 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
fff4b7f3
AL
665 Hit = true;
666 }
667
668 // Follow all provides
669 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
f7f0d6c7 670 I.end() == false && Hit == false; ++I)
fff4b7f3 671 {
d9eb210e 672 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
fff4b7f3
AL
673 Hit = true;
674 }
675
676
677 // Only graph critical deps
678 if (D.IsCritical() == true)
679 {
75ce2062 680 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
fff4b7f3
AL
681
682 // Colour the node for recursion
683 if (Show[D.TargetPkg()->ID] <= DoneNR)
684 {
685 /* If a conflicts does not meet anything in the database
686 then show the relation but do not recurse */
359e46db 687 if (Hit == false && D.IsNegative() == true)
fff4b7f3
AL
688 {
689 if (Show[D.TargetPkg()->ID] == None &&
690 Show[D.TargetPkg()->ID] != ToShow)
691 Show[D.TargetPkg()->ID] = ToShowNR;
692 }
693 else
694 {
695 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
696 Show[D.TargetPkg()->ID] = ToShowNR;
697 else
698 Show[D.TargetPkg()->ID] = ToShow;
699 }
700 }
701
702 // Edge colour
703 switch(D->Type)
704 {
705 case pkgCache::Dep::Conflicts:
706 printf("label: \"conflicts\" color: lightgreen }\n");
707 break;
308c7d30
IJ
708 case pkgCache::Dep::DpkgBreaks:
709 printf("label: \"breaks\" color: lightgreen }\n");
710 break;
fff4b7f3
AL
711 case pkgCache::Dep::Obsoletes:
712 printf("label: \"obsoletes\" color: lightgreen }\n");
713 break;
714
715 case pkgCache::Dep::PreDepends:
716 printf("label: \"predepends\" color: blue }\n");
717 break;
718
719 default:
720 printf("}\n");
721 break;
722 }
723 }
724 }
725 }
726 }
727
728 /* Draw the box colours after the fact since we can not tell what colour
729 they should be until everything is finished drawing */
f7f0d6c7 730 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
731 {
732 if (Show[Pkg->ID] < DoneNR)
733 continue;
734
735 if (Show[Pkg->ID] == DoneNR)
75ce2062 736 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
737 Shapes[ShapeMap[Pkg->ID]]);
738 else
75ce2062 739 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
740 Shapes[ShapeMap[Pkg->ID]]);
741
742 }
03496041
DK
743
744 delete[] Show;
745 delete[] Flags;
746 delete[] ShapeMap;
747
fff4b7f3
AL
748 printf("}\n");
749 return true;
750}
751 /*}}}*/
3e94da1b
AL
752// Dotty - Generate a graph for Dotty /*{{{*/
753// ---------------------------------------------------------------------
754/* Dotty is the graphvis program for generating graphs. It is a fairly
755 simple queuing algorithm that just writes dependencies and nodes.
756 http://www.research.att.com/sw/tools/graphviz/ */
c3ccac92 757static bool Dotty(CommandLine &CmdL)
3e94da1b 758{
d9eb210e
DK
759 pkgCacheFile CacheFile;
760 pkgCache *Cache = CacheFile.GetPkgCache();
761 if (unlikely(Cache == NULL))
762 return false;
763
3e94da1b
AL
764 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
765
766 /* Normal packages are boxes
767 Pure Provides are triangles
768 Mixed are diamonds
769 Hexagons are missing packages*/
770 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
771
772 /* Initialize the list of packages to show.
773 1 = To Show
774 2 = To Show no recurse
775 3 = Emitted no recurse
776 4 = Emitted
777 0 = None */
778 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
779 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
780 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
781 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
782 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
3e94da1b
AL
783
784 // Show everything if no arguments given
785 if (CmdL.FileList[1] == 0)
d9eb210e 786 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b
AL
787 Show[I] = ToShow;
788 else
d9eb210e 789 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b 790 Show[I] = None;
d9eb210e 791 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
3e94da1b
AL
792
793 // Map the shapes
f7f0d6c7 794 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
795 {
796 if (Pkg->VersionList == 0)
797 {
798 // Missing
799 if (Pkg->ProvidesList == 0)
800 ShapeMap[Pkg->ID] = 0;
801 else
802 ShapeMap[Pkg->ID] = 1;
803 }
804 else
805 {
806 // Normal
807 if (Pkg->ProvidesList == 0)
808 ShapeMap[Pkg->ID] = 2;
809 else
810 ShapeMap[Pkg->ID] = 3;
811 }
812 }
3c977245 813
3e94da1b 814 // Load the list of packages from the command line into the show list
cd7bbc47 815 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
fdba4d53
DK
816 std::list<APT::CacheSetHelper::PkgModifier> mods;
817 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
818 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
3c977245 819 std::map<unsigned short, APT::PackageSet> pkgsets =
cd7bbc47 820 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
3c977245
DK
821
822 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
823 Pkg != pkgsets[0].end(); ++Pkg)
824 Show[Pkg->ID] = ToShow;
825 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
826 Pkg != pkgsets[1].end(); ++Pkg)
3e94da1b 827 {
3e94da1b 828 Show[Pkg->ID] = ToShow;
3c977245 829 Flags[Pkg->ID] |= ForceNR;
3e94da1b 830 }
3c977245 831
3e94da1b
AL
832 // Little header
833 printf("digraph packages {\n");
834 printf("concentrate=true;\n");
835 printf("size=\"30,40\";\n");
836
837 bool Act = true;
838 while (Act == true)
839 {
840 Act = false;
f7f0d6c7 841 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
842 {
843 // See we need to show this package
844 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
845 continue;
846
847 // Colour as done
848 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
849 {
850 // Pure Provides and missing packages have no deps!
851 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
852 Show[Pkg->ID] = Done;
853 else
854 Show[Pkg->ID] = DoneNR;
855 }
856 else
857 Show[Pkg->ID] = Done;
858 Act = true;
859
860 // No deps to map out
861 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
862 continue;
863
864 pkgCache::VerIterator Ver = Pkg.VersionList();
f7f0d6c7 865 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
3e94da1b
AL
866 {
867 // See if anything can meet this dep
868 // Walk along the actual package providing versions
869 bool Hit = false;
870 pkgCache::PkgIterator DPkg = D.TargetPkg();
871 for (pkgCache::VerIterator I = DPkg.VersionList();
f7f0d6c7 872 I.end() == false && Hit == false; ++I)
3e94da1b 873 {
d9eb210e 874 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
875 Hit = true;
876 }
877
878 // Follow all provides
879 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
f7f0d6c7 880 I.end() == false && Hit == false; ++I)
3e94da1b 881 {
d9eb210e 882 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
883 Hit = true;
884 }
885
886 // Only graph critical deps
887 if (D.IsCritical() == true)
888 {
75ce2062 889 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
3e94da1b
AL
890
891 // Colour the node for recursion
892 if (Show[D.TargetPkg()->ID] <= DoneNR)
893 {
894 /* If a conflicts does not meet anything in the database
895 then show the relation but do not recurse */
359e46db 896 if (Hit == false && D.IsNegative() == true)
3e94da1b
AL
897 {
898 if (Show[D.TargetPkg()->ID] == None &&
899 Show[D.TargetPkg()->ID] != ToShow)
900 Show[D.TargetPkg()->ID] = ToShowNR;
901 }
902 else
903 {
904 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
905 Show[D.TargetPkg()->ID] = ToShowNR;
906 else
907 Show[D.TargetPkg()->ID] = ToShow;
908 }
909 }
910
911 // Edge colour
912 switch(D->Type)
913 {
914 case pkgCache::Dep::Conflicts:
b2e465d6 915 case pkgCache::Dep::Obsoletes:
359e46db 916 case pkgCache::Dep::DpkgBreaks:
3e94da1b
AL
917 printf("[color=springgreen];\n");
918 break;
919
920 case pkgCache::Dep::PreDepends:
921 printf("[color=blue];\n");
922 break;
923
924 default:
925 printf(";\n");
926 break;
927 }
928 }
929 }
930 }
931 }
932
933 /* Draw the box colours after the fact since we can not tell what colour
934 they should be until everything is finished drawing */
f7f0d6c7 935 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
936 {
937 if (Show[Pkg->ID] < DoneNR)
938 continue;
939
940 // Orange box for early recursion stoppage
941 if (Show[Pkg->ID] == DoneNR)
75ce2062 942 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
943 Shapes[ShapeMap[Pkg->ID]]);
944 else
75ce2062 945 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
946 Shapes[ShapeMap[Pkg->ID]]);
947 }
948
949 printf("}\n");
6070a346
DK
950 delete[] Show;
951 delete[] Flags;
952 delete[] ShapeMap;
ad00ae81 953 return true;
7e2e2d5d
AL
954}
955 /*}}}*/
182a6a55 956/* ShowAuto - show automatically installed packages (sorted) {{{*/
65512241 957static bool ShowAuto(CommandLine &)
6007c1d4 958{
d9eb210e
DK
959 pkgCacheFile CacheFile;
960 pkgCache *Cache = CacheFile.GetPkgCache();
961 pkgDepCache *DepCache = CacheFile.GetDepCache();
962 if (unlikely(Cache == NULL || DepCache == NULL))
963 return false;
6007c1d4
JAK
964
965 std::vector<string> packages;
d9eb210e 966 packages.reserve(Cache->HeaderP->PackageCount / 3);
6007c1d4 967
f7f0d6c7 968 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
d9eb210e 969 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
6007c1d4
JAK
970 packages.push_back(P.Name());
971
972 std::sort(packages.begin(), packages.end());
973
f7f0d6c7 974 for (vector<string>::iterator I = packages.begin(); I != packages.end(); ++I)
6007c1d4
JAK
975 cout << *I << "\n";
976
182a6a55 977 _error->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
6007c1d4
JAK
978 return true;
979}
1164783d 980 /*}}}*/
7c1133fe
AL
981// ShowPkgNames - Show package names /*{{{*/
982// ---------------------------------------------------------------------
983/* This does a prefix match on the first argument */
c3ccac92 984static bool ShowPkgNames(CommandLine &CmdL)
7c1133fe 985{
d9eb210e
DK
986 pkgCacheFile CacheFile;
987 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
988 return false;
989 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
6293e04f
DK
990 bool const All = _config->FindB("APT::Cache::AllNames","false");
991
7c1133fe
AL
992 if (CmdL.FileList[1] != 0)
993 {
f7f0d6c7 994 for (;I.end() != true; ++I)
7c1133fe 995 {
6293e04f
DK
996 if (All == false && I->FirstPackage == 0)
997 continue;
998 if (I.FindPkg("any")->VersionList == 0)
7c1133fe 999 continue;
7c1133fe
AL
1000 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1001 cout << I.Name() << endl;
1002 }
1003
1004 return true;
1005 }
1006
1007 // Show all pkgs
f7f0d6c7 1008 for (;I.end() != true; ++I)
7c1133fe 1009 {
6293e04f
DK
1010 if (All == false && I->FirstPackage == 0)
1011 continue;
1012 if (I.FindPkg("any")->VersionList == 0)
7c1133fe
AL
1013 continue;
1014 cout << I.Name() << endl;
1015 }
1016
f8f410f5
AL
1017 return true;
1018}
bd3d53ef
AL
1019 /*}}}*/
1020// Madison - Look a bit like katie's madison /*{{{*/
1021// ---------------------------------------------------------------------
1022/* */
c3ccac92 1023static bool Madison(CommandLine &CmdL)
bd3d53ef 1024{
d9eb210e
DK
1025 pkgCacheFile CacheFile;
1026 pkgSourceList *SrcList = CacheFile.GetSourceList();
bd3d53ef 1027
d9eb210e
DK
1028 if (SrcList == 0)
1029 return false;
bd3d53ef 1030
03cd434b
MV
1031 // Create the src text record parsers and ignore errors about missing
1032 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
bd3d53ef
AL
1033 pkgSrcRecords SrcRecs(*SrcList);
1034 if (_error->PendingError() == true)
03cd434b 1035 _error->Discard();
bd3d53ef 1036
cd7bbc47 1037 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
dc67d95f 1038 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
bd3d53ef 1039 {
dc67d95f 1040 _error->PushToStack();
c4cca791
DK
1041 APT::PackageList pkgset = APT::PackageList::FromString(CacheFile, *I, helper);
1042 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
bd3d53ef 1043 {
f7f0d6c7 1044 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; ++V)
bd3d53ef 1045 {
f7f0d6c7 1046 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
bd3d53ef 1047 {
a0e710af
AL
1048// This might be nice, but wouldn't uniquely identify the source -mdz
1049// if (VF.File().Archive() != 0)
1050// {
1051// cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1052// << VF.File().Archive() << endl;
1053// }
1054
1055 // Locate the associated index files so we can derive a description
f7f0d6c7 1056 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S)
bd3d53ef 1057 {
7db98ffc
MZ
1058 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1059 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
f7f0d6c7 1060 IF != Indexes->end(); ++IF)
7db98ffc
MZ
1061 {
1062 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1063 {
75ce2062 1064 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
7db98ffc
MZ
1065 << (*IF)->Describe(true) << endl;
1066 }
1067 }
bd3d53ef
AL
1068 }
1069 }
1070 }
1071 }
1072
bd3d53ef
AL
1073 SrcRecs.Restart();
1074 pkgSrcRecords::Parser *SrcParser;
dc67d95f
DK
1075 bool foundSomething = false;
1076 while ((SrcParser = SrcRecs.Find(*I, false)) != 0)
bd3d53ef 1077 {
dc67d95f 1078 foundSomething = true;
bd3d53ef
AL
1079 // Maybe support Release info here too eventually
1080 cout << setw(10) << SrcParser->Package() << " | "
1081 << setw(10) << SrcParser->Version() << " | "
1082 << SrcParser->Index().Describe(true) << endl;
1083 }
dc67d95f
DK
1084 if (foundSomething == true)
1085 _error->RevertToStack();
1086 else
1087 _error->MergeWithStack();
bd3d53ef
AL
1088 }
1089
1090 return true;
1091}
f8f410f5 1092 /*}}}*/
880e9be4
AL
1093// GenCaches - Call the main cache generator /*{{{*/
1094// ---------------------------------------------------------------------
1095/* */
65512241 1096static bool GenCaches(CommandLine &)
880e9be4 1097{
0a8e3465 1098 OpTextProgress Progress(*_config);
d9eb210e
DK
1099
1100 pkgCacheFile CacheFile;
1101 return CacheFile.BuildCaches(&Progress, true);
880e9be4
AL
1102}
1103 /*}}}*/
f6777222 1104static bool ShowHelp(CommandLine &) /*{{{*/
e1b74f61 1105{
cbbee23e 1106 std::cout <<
b2e465d6 1107 _("Usage: apt-cache [options] command\n"
cbbee23e 1108 " apt-cache [options] show pkg1 [pkg2 ...]\n"
b2e465d6 1109 "\n"
8561c2fe 1110 "apt-cache queries and displays available information about installed\n"
d04e44ac
JR
1111 "and installable packages. It works exclusively on the data acquired\n"
1112 "into the local cache via the 'update' command of e.g. apt-get. The\n"
1113 "displayed information may therefore be outdated if the last update was\n"
1114 "too long ago, but in exchange apt-cache works independently of the\n"
8561c2fe 1115 "availability of the configured sources (e.g. offline).\n");
b2e465d6 1116 return true;
e1b74f61
AL
1117}
1118 /*}}}*/
f6777222 1119static std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
1164783d 1120{
011188e3 1121 return {
cbbee23e
DK
1122 {"gencaches",&GenCaches, nullptr},
1123 {"showsrc",&ShowSrcPackage, _("Show source records")},
1124 {"showpkg",&DumpPackage, nullptr},
1125 {"stats",&Stats, nullptr},
1126 {"dump",&Dump, nullptr},
1127 {"dumpavail",&DumpAvail, nullptr},
1128 {"unmet",&UnMet, nullptr},
1129 {"search",&DoSearch, _("Search the package list for a regex pattern")},
1130 {"depends",&Depends, _("Show raw dependency information for a package")},
1131 {"rdepends",&RDepends, _("Show reverse dependency information for a package")},
1132 {"dotty",&Dotty, nullptr},
1133 {"xvcg",&XVcg, nullptr},
1134 {"show",&ShowPackage, _("Show a readable record for the package")},
1135 {"pkgnames",&ShowPkgNames, _("List the names of all packages in the system")},
1136 {"showauto",&ShowAuto, nullptr},
1137 {"policy",&Policy, _("Show policy settings")},
1138 {"madison",&Madison, nullptr},
1139 {nullptr, nullptr, nullptr}
1140 };
011188e3
DK
1141}
1142 /*}}}*/
1143int main(int argc,const char *argv[]) /*{{{*/
1144{
e1b74f61 1145 // Parse the command line and initialize the package library
ad7e0941 1146 CommandLine CmdL;
90986d4d 1147 auto const Cmds = ParseCommandLine(CmdL, APT_CMD::APT_CACHE, &_config, &_system, argc, argv, &ShowHelp, &GetCommands);
8efa2a3b 1148
d9e518c6 1149 InitOutput();
a9a5908d 1150
320352e0
DK
1151 if (_config->Exists("APT::Cache::Generate") == true)
1152 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1153
e7e10e47 1154 return DispatchCommandLine(CmdL, Cmds);
1164783d 1155}
92fcbfc1 1156 /*}}}*/