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