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