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