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