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