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