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