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