]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
Fixed a possible segfault
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
2a3f3893 3// $Id: apt-cache.cc,v 1.54 2001/12/26 06:47:58 jgg Exp $
1164783d
AL
4/* ######################################################################
5
e1b74f61 6 apt-cache - Manages the cache files
1164783d 7
e1b74f61 8 apt-cache provides some functions fo manipulating the cache files.
b2e465d6 9 It uses the command line interface common to all the APT tools.
1164783d
AL
10
11 Returns 100 on failure, 0 on success.
12
13 ##################################################################### */
14 /*}}}*/
15// Include Files /*{{{*/
16#include <apt-pkg/error.h>
17#include <apt-pkg/pkgcachegen.h>
8efa2a3b 18#include <apt-pkg/init.h>
404ec98e 19#include <apt-pkg/progress.h>
880e9be4 20#include <apt-pkg/sourcelist.h>
08e8f724 21#include <apt-pkg/cmndline.h>
cdcc6d34 22#include <apt-pkg/strutl.h>
9dbb421f 23#include <apt-pkg/pkgrecords.h>
f8f410f5 24#include <apt-pkg/srcrecords.h>
3e94da1b 25#include <apt-pkg/version.h>
b2e465d6
AL
26#include <apt-pkg/policy.h>
27#include <apt-pkg/tagfile.h>
28#include <apt-pkg/algorithms.h>
29#include <apt-pkg/sptr.h>
30
43981212 31#include <config.h>
b2e465d6 32#include <apti18n.h>
1164783d
AL
33
34#include <iostream.h>
cdb970c7 35#include <unistd.h>
43981212 36#include <errno.h>
9dbb421f 37#include <regex.h>
3e94da1b 38#include <stdio.h>
1164783d
AL
39 /*}}}*/
40
b0b4efb9 41pkgCache *GCache = 0;
af87ab54 42pkgSourceList *SrcList = 0;
b0b4efb9 43
b2e465d6
AL
44// LocalitySort - Sort a version list by package file locality /*{{{*/
45// ---------------------------------------------------------------------
46/* */
47int LocalityCompare(const void *a, const void *b)
48{
49 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
50 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
51
52 if (A == 0 && B == 0)
53 return 0;
54 if (A == 0)
55 return 1;
56 if (B == 0)
57 return -1;
58
59 if (A->File == B->File)
60 return A->Offset - B->Offset;
61 return A->File - B->File;
62}
63
64void LocalitySort(pkgCache::VerFile **begin,
65 unsigned long Count,size_t Size)
66{
67 qsort(begin,Count,Size,LocalityCompare);
68}
69 /*}}}*/
cc718e9a
AL
70// UnMet - Show unmet dependencies /*{{{*/
71// ---------------------------------------------------------------------
72/* */
b0b4efb9 73bool UnMet(CommandLine &CmdL)
cc718e9a 74{
b0b4efb9 75 pkgCache &Cache = *GCache;
76fbce56 76 bool Important = _config->FindB("APT::Cache::Important",false);
018f1533 77
cc718e9a
AL
78 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
79 {
80 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
81 {
82 bool Header = false;
018f1533 83 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
84 {
85 // Collect or groups
86 pkgCache::DepIterator Start;
87 pkgCache::DepIterator End;
88 D.GlobOr(Start,End);
89
018f1533 90 // Skip conflicts and replaces
cc718e9a
AL
91 if (End->Type != pkgCache::Dep::PreDepends &&
92 End->Type != pkgCache::Dep::Depends &&
93 End->Type != pkgCache::Dep::Suggests &&
94 End->Type != pkgCache::Dep::Recommends)
95 continue;
96
018f1533
AL
97 // Important deps only
98 if (Important == true)
99 if (End->Type != pkgCache::Dep::PreDepends &&
100 End->Type != pkgCache::Dep::Depends)
101 continue;
102
cc718e9a
AL
103 // Verify the or group
104 bool OK = false;
105 pkgCache::DepIterator RealStart = Start;
106 do
107 {
108 // See if this dep is Ok
109 pkgCache::Version **VList = Start.AllTargets();
110 if (*VList != 0)
111 {
112 OK = true;
113 delete [] VList;
114 break;
115 }
116 delete [] VList;
117
118 if (Start == End)
119 break;
120 Start++;
121 }
122 while (1);
123
124 // The group is OK
125 if (OK == true)
126 continue;
127
128 // Oops, it failed..
129 if (Header == false)
b2e465d6
AL
130 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
131 P.Name(),V.VerStr());
cc718e9a
AL
132 Header = true;
133
134 // Print out the dep type
135 cout << " " << End.DepType() << ": ";
136
137 // Show the group
138 Start = RealStart;
139 do
140 {
141 cout << Start.TargetPkg().Name();
142 if (Start.TargetVer() != 0)
143 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
144 ")";
145 if (Start == End)
146 break;
147 cout << " | ";
148 Start++;
149 }
150 while (1);
151
152 cout << endl;
153 }
154 }
155 }
156 return true;
157}
158 /*}}}*/
1164783d
AL
159// DumpPackage - Show a dump of a package record /*{{{*/
160// ---------------------------------------------------------------------
161/* */
b0b4efb9 162bool DumpPackage(CommandLine &CmdL)
ad00ae81 163{
b0b4efb9 164 pkgCache &Cache = *GCache;
e1b74f61 165 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1164783d 166 {
e1b74f61 167 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1164783d
AL
168 if (Pkg.end() == true)
169 {
b2e465d6 170 _error->Warning(_("Unable to locate package %s"),*I);
1164783d
AL
171 continue;
172 }
173
174 cout << "Package: " << Pkg.Name() << endl;
b2e465d6 175 cout << "Versions: " << endl;
1164783d 176 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
03e39e59
AL
177 {
178 cout << Cur.VerStr();
179 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
180 cout << "(" << Vf.File().FileName() << ")";
b2e465d6 181 cout << endl;
03e39e59
AL
182 }
183
1164783d
AL
184 cout << endl;
185
186 cout << "Reverse Depends: " << endl;
187 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
b2e465d6
AL
188 {
189 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
190 if (D->Version != 0)
b1b663d1 191 cout << ' ' << DeNull(D.TargetVer()) << endl;
b2e465d6
AL
192 else
193 cout << endl;
194 }
195
1164783d
AL
196 cout << "Dependencies: " << endl;
197 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
198 {
199 cout << Cur.VerStr() << " - ";
200 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
b1b663d1 201 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
1164783d
AL
202 cout << endl;
203 }
204
205 cout << "Provides: " << endl;
206 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
207 {
208 cout << Cur.VerStr() << " - ";
209 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
210 cout << Prv.ParentPkg().Name() << " ";
211 cout << endl;
8efa2a3b
AL
212 }
213 cout << "Reverse Provides: " << endl;
214 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
2d6751b9 215 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;
1164783d
AL
216 }
217
218 return true;
219}
220 /*}}}*/
221// Stats - Dump some nice statistics /*{{{*/
222// ---------------------------------------------------------------------
223/* */
b0b4efb9 224bool Stats(CommandLine &Cmd)
1164783d 225{
b0b4efb9 226 pkgCache &Cache = *GCache;
b2e465d6 227 cout << _("Total Package Names : ") << Cache.Head().PackageCount << " (" <<
f826cfaa 228 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
b2e465d6 229
1164783d
AL
230 int Normal = 0;
231 int Virtual = 0;
232 int NVirt = 0;
233 int DVirt = 0;
234 int Missing = 0;
b2e465d6 235 pkgCache::PkgIterator I = Cache.PkgBegin();
1164783d
AL
236 for (;I.end() != true; I++)
237 {
238 if (I->VersionList != 0 && I->ProvidesList == 0)
239 {
240 Normal++;
241 continue;
242 }
243
244 if (I->VersionList != 0 && I->ProvidesList != 0)
245 {
246 NVirt++;
247 continue;
248 }
249
250 if (I->VersionList == 0 && I->ProvidesList != 0)
251 {
252 // Only 1 provides
253 if (I.ProvidesList()->NextProvides == 0)
254 {
255 DVirt++;
256 }
257 else
258 Virtual++;
259 continue;
260 }
261 if (I->VersionList == 0 && I->ProvidesList == 0)
262 {
263 Missing++;
264 continue;
265 }
266 }
b2e465d6
AL
267 cout << _(" Normal Packages: ") << Normal << endl;
268 cout << _(" Pure Virtual Packages: ") << Virtual << endl;
269 cout << _(" Single Virtual Packages: ") << DVirt << endl;
270 cout << _(" Mixed Virtual Packages: ") << NVirt << endl;
271 cout << _(" Missing: ") << Missing << endl;
1164783d 272
b2e465d6 273 cout << _("Total Distinct Versions: ") << Cache.Head().VersionCount << " (" <<
f826cfaa 274 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
b2e465d6 275 cout << _("Total Dependencies: ") << Cache.Head().DependsCount << " (" <<
f826cfaa
AL
276 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
277
b2e465d6 278 cout << _("Total Ver/File relations: ") << Cache.Head().VerFileCount << " (" <<
a7e66b17 279 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
b2e465d6 280 cout << _("Total Provides Mappings: ") << Cache.Head().ProvidesCount << " (" <<
a7e66b17 281 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
f826cfaa
AL
282
283 // String list stats
284 unsigned long Size = 0;
285 unsigned long Count = 0;
286 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
287 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
288 {
289 Count++;
b2e465d6 290 Size += strlen(Cache.StrP + I->String) + 1;
f826cfaa 291 }
b2e465d6
AL
292 cout << _("Total Globbed Strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
293
294 unsigned long DepVerSize = 0;
295 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
296 {
297 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
298 {
299 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
300 {
301 if (D->Version != 0)
302 DepVerSize += strlen(D.TargetVer()) + 1;
303 }
304 }
305 }
306 cout << _("Total Dependency Version space: ") << SizeToStr(DepVerSize) << endl;
307
f826cfaa
AL
308 unsigned long Slack = 0;
309 for (int I = 0; I != 7; I++)
310 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
b2e465d6 311 cout << _("Total Slack space: ") << SizeToStr(Slack) << endl;
f826cfaa
AL
312
313 unsigned long Total = 0;
314 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
315 Cache.Head().VersionCount*Cache.Head().VersionSz +
a7e66b17
AL
316 Cache.Head().PackageCount*Cache.Head().PackageSz +
317 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
318 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
b2e465d6 319 cout << _("Total Space Accounted for: ") << SizeToStr(Total) << endl;
f826cfaa 320
83d89a9f
AL
321 return true;
322}
323 /*}}}*/
1164783d
AL
324// Dump - show everything /*{{{*/
325// ---------------------------------------------------------------------
b2e465d6 326/* This is worthless except fer debugging things */
b0b4efb9 327bool Dump(CommandLine &Cmd)
1164783d 328{
b0b4efb9 329 pkgCache &Cache = *GCache;
b2e465d6
AL
330 cout << "Using Versioning System: " << Cache.VS->Label << endl;
331
1164783d
AL
332 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
333 {
334 cout << "Package: " << P.Name() << endl;
335 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
336 {
337 cout << " Version: " << V.VerStr() << endl;
338 cout << " File: " << V.FileList().File().FileName() << endl;
339 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
076d01b0
AL
340 cout << " Depends: " << D.TargetPkg().Name() << ' ' <<
341 DeNull(D.TargetVer()) << endl;
1164783d
AL
342 }
343 }
344
b2e465d6 345 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1164783d
AL
346 {
347 cout << "File: " << F.FileName() << endl;
b2e465d6 348 cout << " Type: " << F.IndexType() << endl;
1164783d
AL
349 cout << " Size: " << F->Size << endl;
350 cout << " ID: " << F->ID << endl;
351 cout << " Flags: " << F->Flags << endl;
b0b4efb9 352 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
076d01b0
AL
353 cout << " Archive: " << DeNull(F.Archive()) << endl;
354 cout << " Component: " << DeNull(F.Component()) << endl;
355 cout << " Version: " << DeNull(F.Version()) << endl;
356 cout << " Origin: " << DeNull(F.Origin()) << endl;
357 cout << " Site: " << DeNull(F.Site()) << endl;
358 cout << " Label: " << DeNull(F.Label()) << endl;
359 cout << " Architecture: " << DeNull(F.Architecture()) << endl;
1164783d
AL
360 }
361
362 return true;
363}
364 /*}}}*/
365// DumpAvail - Print out the available list /*{{{*/
366// ---------------------------------------------------------------------
b2e465d6
AL
367/* This is needed to make dpkg --merge happy.. I spent a bit of time to
368 make this run really fast, perhaps I went a little overboard.. */
b0b4efb9 369bool DumpAvail(CommandLine &Cmd)
1164783d 370{
b0b4efb9 371 pkgCache &Cache = *GCache;
1164783d 372
b2e465d6
AL
373 pkgPolicy Plcy(&Cache);
374 if (ReadPinFile(Plcy) == false)
375 return false;
376
fe648919
AL
377 unsigned long Count = Cache.HeaderP->PackageCount+1;
378 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
379 memset(VFList,0,sizeof(*VFList)*Count);
b2e465d6
AL
380
381 // Map versions that we want to write out onto the VerList array.
382 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
383 {
384 if (P->VersionList == 0)
5b8c90bf
AL
385 continue;
386
b2e465d6
AL
387 /* Find the proper version to use. If the policy says there are no
388 possible selections we return the installed version, if available..
389 This prevents dselect from making it obsolete. */
390 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
391 if (V.end() == true)
ad00ae81 392 {
b2e465d6
AL
393 if (P->CurrentVer == 0)
394 continue;
395 V = P.CurrentVer();
ad00ae81 396 }
1164783d 397
b2e465d6
AL
398 pkgCache::VerFileIterator VF = V.FileList();
399 for (; VF.end() == false ; VF++)
400 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
401 break;
402
403 /* Okay, here we have a bit of a problem.. The policy has selected the
404 currently installed package - however it only exists in the
405 status file.. We need to write out something or dselect will mark
406 the package as obsolete! Thus we emit the status file entry, but
407 below we remove the status line to make it valid for the
408 available file. However! We only do this if their do exist *any*
409 non-source versions of the package - that way the dselect obsolete
410 handling works OK. */
411 if (VF.end() == true)
1164783d 412 {
b2e465d6
AL
413 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
414 {
415 for (VF = Cur.FileList(); VF.end() == false; VF++)
416 {
417 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
418 {
419 VF = V.FileList();
420 break;
421 }
422 }
423
424 if (VF.end() == false)
425 break;
426 }
ad00ae81 427 }
b2e465d6
AL
428
429 VFList[P->ID] = VF;
430 }
431
fe648919 432 LocalitySort(VFList,Count,sizeof(*VFList));
ad00ae81 433
b2e465d6
AL
434 // Iterate over all the package files and write them out.
435 char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
436 for (pkgCache::VerFile **J = VFList; *J != 0;)
437 {
438 pkgCache::PkgFileIterator File(Cache,(*J)->File + Cache.PkgFileP);
439 if (File.IsOk() == false)
ad00ae81 440 {
b2e465d6
AL
441 _error->Error(_("Package file %s is out of sync."),File.FileName());
442 break;
443 }
bd432be3 444
b2e465d6
AL
445 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
446 if (_error->PendingError() == true)
447 break;
448
449 /* Write all of the records from this package file, since we
450 already did locality sorting we can now just seek through the
451 file in read order. We apply 1 more optimization here, since often
452 there will be < 1 byte gaps between records (for the \n) we read that
453 into the next buffer and offset a bit.. */
454 unsigned long Pos = 0;
455 for (; *J != 0; J++)
456 {
457 if ((*J)->File + Cache.PkgFileP != File)
458 break;
bd432be3 459
b2e465d6
AL
460 const pkgCache::VerFile &VF = **J;
461
bd432be3 462 // Read the record and then write it out again.
b2e465d6
AL
463 unsigned long Jitter = VF.Offset - Pos;
464 if (Jitter > 8)
1164783d 465 {
b2e465d6
AL
466 if (PkgF.Seek(VF.Offset) == false)
467 break;
468 Jitter = 0;
469 }
470
471 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
472 break;
473 Buffer[VF.Size + Jitter] = '\n';
474
475 // See above..
476 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
477 {
478 pkgTagSection Tags;
e8cbb49f 479 TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
b2e465d6
AL
480 const char *Zero = 0;
481 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
482 TFRewrite(stdout,Tags,&Zero,RW) == false)
483 {
484 _error->Error("Internal Error, Unable to parse a package record");
485 break;
486 }
487 fputc('\n',stdout);
488 }
489 else
490 {
491 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
492 break;
493 }
494
495 Pos = VF.Offset + VF.Size;
1164783d 496 }
b2e465d6
AL
497
498 fflush(stdout);
499 if (_error->PendingError() == true)
500 break;
ad00ae81
AL
501 }
502
b2e465d6
AL
503 delete [] Buffer;
504 delete [] VFList;
505 return !_error->PendingError();
349cd3b8
AL
506}
507 /*}}}*/
4b1b89c5 508// Depends - Print out a dependency tree /*{{{*/
349cd3b8
AL
509// ---------------------------------------------------------------------
510/* */
511bool Depends(CommandLine &CmdL)
512{
513 pkgCache &Cache = *GCache;
b2e465d6
AL
514 SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
515 memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
349cd3b8
AL
516
517 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
518 {
519 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
520 if (Pkg.end() == true)
521 {
b2e465d6 522 _error->Warning(_("Unable to locate package %s"),*I);
349cd3b8
AL
523 continue;
524 }
b2e465d6
AL
525 Colours[Pkg->ID] = 1;
526 }
527
528 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
529 bool DidSomething;
530 do
531 {
532 DidSomething = false;
533 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
349cd3b8 534 {
b2e465d6
AL
535 if (Colours[Pkg->ID] != 1)
536 continue;
537 Colours[Pkg->ID] = 2;
538 DidSomething = true;
349cd3b8 539
b2e465d6
AL
540 pkgCache::VerIterator Ver = Pkg.VersionList();
541 if (Ver.end() == true)
349cd3b8 542 {
b2e465d6
AL
543 cout << '<' << Pkg.Name() << '>' << endl;
544 continue;
349cd3b8 545 }
b2e465d6
AL
546
547 cout << Pkg.Name() << endl;
548
549 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
550 {
551 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
552 cout << " |";
553 else
554 cout << " ";
555
556 // Show the package
557 pkgCache::PkgIterator Trg = D.TargetPkg();
558 if (Trg->VersionList == 0)
559 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
560 else
561 cout << D.DepType() << ": " << Trg.Name() << endl;
562
563 if (Recurse == true)
564 Colours[D.TargetPkg()->ID]++;
565
566 // Display all solutions
567 SPtrArray<pkgCache::Version *> List = D.AllTargets();
568 pkgPrioSortList(Cache,List);
569 for (pkgCache::Version **I = List; *I != 0; I++)
570 {
571 pkgCache::VerIterator V(Cache,*I);
572 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
573 V->ParentPkg == D->Package)
574 continue;
575 cout << " " << V.ParentPkg().Name() << endl;
576
577 if (Recurse == true)
578 Colours[D.ParentPkg()->ID]++;
579 }
580 }
581 }
349cd3b8 582 }
b2e465d6 583 while (DidSomething == true);
349cd3b8 584
3e94da1b
AL
585 return true;
586}
587 /*}}}*/
588// Dotty - Generate a graph for Dotty /*{{{*/
589// ---------------------------------------------------------------------
590/* Dotty is the graphvis program for generating graphs. It is a fairly
591 simple queuing algorithm that just writes dependencies and nodes.
592 http://www.research.att.com/sw/tools/graphviz/ */
593bool Dotty(CommandLine &CmdL)
594{
595 pkgCache &Cache = *GCache;
596 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
597
598 /* Normal packages are boxes
599 Pure Provides are triangles
600 Mixed are diamonds
601 Hexagons are missing packages*/
602 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
603
604 /* Initialize the list of packages to show.
605 1 = To Show
606 2 = To Show no recurse
607 3 = Emitted no recurse
608 4 = Emitted
609 0 = None */
610 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
611 enum TheFlags {ForceNR=(1<<0)};
612 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
613 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
614 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
615
616 // Show everything if no arguments given
617 if (CmdL.FileList[1] == 0)
618 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
619 Show[I] = ToShow;
620 else
621 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
622 Show[I] = None;
623 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
624
625 // Map the shapes
626 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
627 {
628 if (Pkg->VersionList == 0)
629 {
630 // Missing
631 if (Pkg->ProvidesList == 0)
632 ShapeMap[Pkg->ID] = 0;
633 else
634 ShapeMap[Pkg->ID] = 1;
635 }
636 else
637 {
638 // Normal
639 if (Pkg->ProvidesList == 0)
640 ShapeMap[Pkg->ID] = 2;
641 else
642 ShapeMap[Pkg->ID] = 3;
643 }
644 }
645
646 // Load the list of packages from the command line into the show list
647 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
648 {
649 // Process per-package flags
650 string P = *I;
651 bool Force = false;
652 if (P.length() > 3)
653 {
654 if (P.end()[-1] == '^')
655 {
656 Force = true;
657 P.erase(P.end()-1);
658 }
659
660 if (P.end()[-1] == ',')
661 P.erase(P.end()-1);
662 }
663
664 // Locate the package
665 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
666 if (Pkg.end() == true)
667 {
b2e465d6 668 _error->Warning(_("Unable to locate package %s"),*I);
3e94da1b
AL
669 continue;
670 }
671 Show[Pkg->ID] = ToShow;
672
673 if (Force == true)
674 Flags[Pkg->ID] |= ForceNR;
675 }
676
677 // Little header
678 printf("digraph packages {\n");
679 printf("concentrate=true;\n");
680 printf("size=\"30,40\";\n");
681
682 bool Act = true;
683 while (Act == true)
684 {
685 Act = false;
686 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
687 {
688 // See we need to show this package
689 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
690 continue;
691
692 // Colour as done
693 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
694 {
695 // Pure Provides and missing packages have no deps!
696 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
697 Show[Pkg->ID] = Done;
698 else
699 Show[Pkg->ID] = DoneNR;
700 }
701 else
702 Show[Pkg->ID] = Done;
703 Act = true;
704
705 // No deps to map out
706 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
707 continue;
708
709 pkgCache::VerIterator Ver = Pkg.VersionList();
710 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
711 {
712 // See if anything can meet this dep
713 // Walk along the actual package providing versions
714 bool Hit = false;
715 pkgCache::PkgIterator DPkg = D.TargetPkg();
716 for (pkgCache::VerIterator I = DPkg.VersionList();
717 I.end() == false && Hit == false; I++)
718 {
b2e465d6 719 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
720 Hit = true;
721 }
722
723 // Follow all provides
724 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
725 I.end() == false && Hit == false; I++)
726 {
b2e465d6 727 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
728 Hit = true;
729 }
730
731 // Only graph critical deps
732 if (D.IsCritical() == true)
733 {
734 printf("\"%s\" -> \"%s\"",Pkg.Name(),D.TargetPkg().Name());
735
736 // Colour the node for recursion
737 if (Show[D.TargetPkg()->ID] <= DoneNR)
738 {
739 /* If a conflicts does not meet anything in the database
740 then show the relation but do not recurse */
b2e465d6
AL
741 if (Hit == false &&
742 (D->Type == pkgCache::Dep::Conflicts ||
743 D->Type == pkgCache::Dep::Obsoletes))
3e94da1b
AL
744 {
745 if (Show[D.TargetPkg()->ID] == None &&
746 Show[D.TargetPkg()->ID] != ToShow)
747 Show[D.TargetPkg()->ID] = ToShowNR;
748 }
749 else
750 {
751 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
752 Show[D.TargetPkg()->ID] = ToShowNR;
753 else
754 Show[D.TargetPkg()->ID] = ToShow;
755 }
756 }
757
758 // Edge colour
759 switch(D->Type)
760 {
761 case pkgCache::Dep::Conflicts:
b2e465d6 762 case pkgCache::Dep::Obsoletes:
3e94da1b
AL
763 printf("[color=springgreen];\n");
764 break;
765
766 case pkgCache::Dep::PreDepends:
767 printf("[color=blue];\n");
768 break;
769
770 default:
771 printf(";\n");
772 break;
773 }
774 }
775 }
776 }
777 }
778
779 /* Draw the box colours after the fact since we can not tell what colour
780 they should be until everything is finished drawing */
781 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
782 {
783 if (Show[Pkg->ID] < DoneNR)
784 continue;
785
786 // Orange box for early recursion stoppage
787 if (Show[Pkg->ID] == DoneNR)
788 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.Name(),
789 Shapes[ShapeMap[Pkg->ID]]);
790 else
791 printf("\"%s\" [shape=%s];\n",Pkg.Name(),
792 Shapes[ShapeMap[Pkg->ID]]);
793 }
794
795 printf("}\n");
ad00ae81
AL
796 return true;
797}
798 /*}}}*/
799// DoAdd - Perform an adding operation /*{{{*/
800// ---------------------------------------------------------------------
801/* */
e1b74f61 802bool DoAdd(CommandLine &CmdL)
ad00ae81 803{
b2e465d6
AL
804 return _error->Error("Unimplemented");
805#if 0
e1b74f61
AL
806 // Make sure there is at least one argument
807 if (CmdL.FileSize() <= 1)
808 return _error->Error("You must give at least one file name");
ad00ae81
AL
809
810 // Open the cache
018f1533 811 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
ad00ae81
AL
812 if (_error->PendingError() == true)
813 return false;
814
815 DynamicMMap Map(CacheF,MMap::Public);
816 if (_error->PendingError() == true)
817 return false;
404ec98e 818
0a8e3465 819 OpTextProgress Progress(*_config);
404ec98e 820 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
821 if (_error->PendingError() == true)
822 return false;
823
e1b74f61
AL
824 unsigned long Length = CmdL.FileSize() - 1;
825 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 826 {
e1b74f61 827 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
018f1533
AL
828 Progress.SubProgress(Length);
829
ad00ae81 830 // Do the merge
e1b74f61 831 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
832 debListParser Parser(TagF);
833 if (_error->PendingError() == true)
e1b74f61 834 return _error->Error("Problem opening %s",*I);
ad00ae81 835
b2e465d6 836 if (Gen.SelectFile(*I,"") == false)
ad00ae81
AL
837 return _error->Error("Problem with SelectFile");
838
839 if (Gen.MergeList(Parser) == false)
840 return _error->Error("Problem with MergeList");
1164783d 841 }
404ec98e
AL
842
843 Progress.Done();
b0b4efb9
AL
844 GCache = &Gen.GetCache();
845 Stats(CmdL);
ad00ae81 846
7e2e2d5d 847 return true;
b2e465d6 848#endif
7e2e2d5d
AL
849}
850 /*}}}*/
851// DisplayRecord - Displays the complete record for the package /*{{{*/
852// ---------------------------------------------------------------------
853/* This displays the package record from the proper package index file.
854 It is not used by DumpAvail for performance reasons. */
855bool DisplayRecord(pkgCache::VerIterator V)
856{
857 // Find an appropriate file
858 pkgCache::VerFileIterator Vf = V.FileList();
859 for (; Vf.end() == false; Vf++)
860 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
861 break;
862 if (Vf.end() == true)
863 Vf = V.FileList();
864
865 // Check and load the package list file
866 pkgCache::PkgFileIterator I = Vf.File();
867 if (I.IsOk() == false)
b2e465d6 868 return _error->Error(_("Package file %s is out of sync."),I.FileName());
7e2e2d5d
AL
869
870 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
871 if (_error->PendingError() == true)
872 return false;
873
874 // Read the record and then write it out again.
b2e465d6
AL
875 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
876 Buffer[V.FileList()->Size] = '\n';
7e2e2d5d
AL
877 if (PkgF.Seek(V.FileList()->Offset) == false ||
878 PkgF.Read(Buffer,V.FileList()->Size) == false ||
b2e465d6 879 write(STDOUT_FILENO,Buffer,V.FileList()->Size+1) != V.FileList()->Size+1)
7e2e2d5d
AL
880 {
881 delete [] Buffer;
882 return false;
883 }
884
885 delete [] Buffer;
886
9dbb421f
AL
887 return true;
888}
889 /*}}}*/
890// Search - Perform a search /*{{{*/
891// ---------------------------------------------------------------------
892/* This searches the package names and pacakge descriptions for a pattern */
b2e465d6
AL
893struct ExVerFile
894{
895 pkgCache::VerFile *Vf;
896 bool NameMatch;
897};
898
9dbb421f
AL
899bool Search(CommandLine &CmdL)
900{
901 pkgCache &Cache = *GCache;
7e2e2d5d
AL
902 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
903 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
b2e465d6
AL
904 unsigned NumPatterns = CmdL.FileSize() -1;
905
906 pkgDepCache::Policy Plcy;
9dbb421f
AL
907
908 // Make sure there is at least one argument
b2e465d6
AL
909 if (NumPatterns < 1)
910 return _error->Error(_("You must give exactly one pattern"));
9dbb421f
AL
911
912 // Compile the regex pattern
b2e465d6
AL
913 regex_t *Patterns = new regex_t[NumPatterns];
914 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
915 for (unsigned I = 0; I != NumPatterns; I++)
916 {
917 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
918 REG_NOSUB) != 0)
919 {
920 for (; I != 0; I--)
921 regfree(&Patterns[I]);
922 return _error->Error("Regex compilation error");
923 }
924 }
9dbb421f
AL
925
926 // Create the text record parser
927 pkgRecords Recs(Cache);
928 if (_error->PendingError() == true)
b2e465d6
AL
929 {
930 for (unsigned I = 0; I != NumPatterns; I++)
931 regfree(&Patterns[I]);
9dbb421f 932 return false;
b2e465d6 933 }
9dbb421f 934
b2e465d6
AL
935 ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
936 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
937
938 // Map versions that we want to write out onto the VerList array.
939 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
9dbb421f 940 {
0f2fa322 941 VFList[P->ID].NameMatch = NumPatterns != 0;
b2e465d6
AL
942 for (unsigned I = 0; I != NumPatterns; I++)
943 {
944 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
0f2fa322
AL
945 VFList[P->ID].NameMatch &= true;
946 else
947 VFList[P->ID].NameMatch = false;
b2e465d6 948 }
c29652b0 949
b2e465d6
AL
950 // Doing names only, drop any that dont match..
951 if (NamesOnly == true && VFList[P->ID].NameMatch == false)
952 continue;
953
954 // Find the proper version to use.
955 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
c29652b0
AL
956 if (V.end() == false)
957 VFList[P->ID].Vf = V.FileList();
958 }
959
960 // Include all the packages that provide matching names too
961 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
962 {
963 if (VFList[P->ID].NameMatch == false)
7e2e2d5d 964 continue;
c29652b0
AL
965
966 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
967 {
968 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
969 if (V.end() == false)
970 {
971 VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
972 VFList[Prv.OwnerPkg()->ID].NameMatch = true;
973 }
974 }
b2e465d6 975 }
c29652b0 976
b2e465d6 977 LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
7e2e2d5d 978
b2e465d6
AL
979 // Iterate over all the version records and check them
980 for (ExVerFile *J = VFList; J->Vf != 0; J++)
981 {
982 pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
0f2fa322
AL
983
984 bool Match = true;
985 if (J->NameMatch == false)
986 {
987 string LongDesc = P.LongDesc();
988 Match = NumPatterns != 0;
989 for (unsigned I = 0; I != NumPatterns; I++)
990 {
991 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
992 Match &= true;
993 else
994 Match = false;
995 }
996 }
b2e465d6
AL
997
998 if (Match == true)
9dbb421f 999 {
7e2e2d5d 1000 if (ShowFull == true)
b2e465d6
AL
1001 {
1002 const char *Start;
1003 const char *End;
1004 P.GetRec(Start,End);
1005 fwrite(Start,End-Start,1,stdout);
1006 putc('\n',stdout);
1007 }
7e2e2d5d 1008 else
b2e465d6
AL
1009 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1010 }
9dbb421f
AL
1011 }
1012
b2e465d6
AL
1013 delete [] VFList;
1014 for (unsigned I = 0; I != NumPatterns; I++)
1015 regfree(&Patterns[I]);
1016 if (ferror(stdout))
1017 return _error->Error("Write to stdout failed");
1164783d
AL
1018 return true;
1019}
1020 /*}}}*/
7e2e2d5d
AL
1021// ShowPackage - Dump the package record to the screen /*{{{*/
1022// ---------------------------------------------------------------------
1023/* */
1024bool ShowPackage(CommandLine &CmdL)
1025{
1026 pkgCache &Cache = *GCache;
b2e465d6
AL
1027 pkgDepCache::Policy Plcy;
1028
7e2e2d5d
AL
1029 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1030 {
1031 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1032 if (Pkg.end() == true)
1033 {
b2e465d6 1034 _error->Warning(_("Unable to locate package %s"),*I);
7e2e2d5d
AL
1035 continue;
1036 }
b2e465d6
AL
1037
1038 // Find the proper version to use.
648e3cb4
AL
1039 if (_config->FindB("APT::Cache::AllVersions","true") == true)
1040 {
1041 pkgCache::VerIterator V;
1042 for (V = Pkg.VersionList(); V.end() == false; V++)
1043 {
1044 if (DisplayRecord(V) == false)
1045 return false;
1046 }
1047 }
1048 else
1049 {
b2e465d6 1050 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
648e3cb4
AL
1051 if (V.end() == true || V.FileList().end() == true)
1052 continue;
1053 if (DisplayRecord(V) == false)
1054 return false;
1055 }
7e2e2d5d 1056 }
7c1133fe
AL
1057 return true;
1058}
1059 /*}}}*/
1060// ShowPkgNames - Show package names /*{{{*/
1061// ---------------------------------------------------------------------
1062/* This does a prefix match on the first argument */
1063bool ShowPkgNames(CommandLine &CmdL)
1064{
1065 pkgCache &Cache = *GCache;
1066 pkgCache::PkgIterator I = Cache.PkgBegin();
1067 bool All = _config->FindB("APT::Cache::AllNames","false");
1068
1069 if (CmdL.FileList[1] != 0)
1070 {
1071 for (;I.end() != true; I++)
1072 {
1073 if (All == false && I->VersionList == 0)
1074 continue;
1075
1076 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1077 cout << I.Name() << endl;
1078 }
1079
1080 return true;
1081 }
1082
1083 // Show all pkgs
1084 for (;I.end() != true; I++)
1085 {
1086 if (All == false && I->VersionList == 0)
1087 continue;
1088 cout << I.Name() << endl;
1089 }
1090
7e2e2d5d
AL
1091 return true;
1092}
1093 /*}}}*/
f8f410f5
AL
1094// ShowSrcPackage - Show source package records /*{{{*/
1095// ---------------------------------------------------------------------
1096/* */
1097bool ShowSrcPackage(CommandLine &CmdL)
1098{
1099 pkgSourceList List;
1100 List.ReadMainList();
1101
1102 // Create the text record parsers
1103 pkgSrcRecords SrcRecs(List);
1104 if (_error->PendingError() == true)
1105 return false;
1106
1107 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1108 {
aaee8293
AL
1109 SrcRecs.Restart();
1110
f8f410f5
AL
1111 pkgSrcRecords::Parser *Parse;
1112 while ((Parse = SrcRecs.Find(*I,false)) != 0)
b2e465d6 1113 cout << Parse->AsStr() << endl;;
f8f410f5 1114 }
af87ab54
AL
1115 return true;
1116}
1117 /*}}}*/
1118// Policy - Show the results of the preferences file /*{{{*/
1119// ---------------------------------------------------------------------
1120/* */
1121bool Policy(CommandLine &CmdL)
1122{
1123 if (SrcList == 0)
1124 return _error->Error("Generate must be enabled for this function");
1125
1126 pkgCache &Cache = *GCache;
1127 pkgPolicy Plcy(&Cache);
1128 if (ReadPinFile(Plcy) == false)
1129 return false;
1130
1131 // Print out all of the package files
1132 if (CmdL.FileList[1] == 0)
1133 {
1134 cout << _("Package Files:") << endl;
1135 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1136 {
1137 // Locate the associated index files so we can derive a description
1138 pkgIndexFile *Indx;
1139 if (SrcList->FindIndex(F,Indx) == false &&
1140 _system->FindIndex(F,Indx) == false)
1141 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1142 printf(_("%4i %s\n"),
1143 Plcy.GetPriority(F),Indx->Describe(true).c_str());
1144
1145 // Print the reference information for the package
1146 string Str = F.RelStr();
1147 if (Str.empty() == false)
1148 printf(" release %s\n",F.RelStr().c_str());
1149 if (F.Site() != 0 && F.Site()[0] != 0)
1150 printf(" origin %s\n",F.Site());
1151 }
1152
1153 // Show any packages have explicit pins
1154 cout << _("Pinned Packages:") << endl;
1155 pkgCache::PkgIterator I = Cache.PkgBegin();
1156 for (;I.end() != true; I++)
1157 {
1158 if (Plcy.GetPriority(I) == 0)
1159 continue;
1160
1161 // Print the package name and the version we are forcing to
1162 cout << " " << I.Name() << " -> ";
1163
1164 pkgCache::VerIterator V = Plcy.GetMatch(I);
1165 if (V.end() == true)
1166 cout << _("(not found)") << endl;
1167 else
1168 cout << V.VerStr() << endl;
1169 }
1170
1171 return true;
1172 }
1173
1174 // Print out detailed information for each package
1175 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1176 {
1177 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1178 if (Pkg.end() == true)
1179 {
1180 _error->Warning(_("Unable to locate package %s"),*I);
1181 continue;
1182 }
1183
1184 cout << Pkg.Name() << ":" << endl;
1185
1186 // Installed version
1187 cout << _(" Installed: ");
1188 if (Pkg->CurrentVer == 0)
1189 cout << _("(none)") << endl;
1190 else
1191 cout << Pkg.CurrentVer().VerStr() << endl;
1192
1193 // Candidate Version
1194 cout << _(" Candidate: ");
1195 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1196 if (V.end() == true)
1197 cout << _("(none)") << endl;
1198 else
1199 cout << V.VerStr() << endl;
1200
1201 // Pinned version
1202 if (Plcy.GetPriority(Pkg) != 0)
1203 {
1204 cout << _(" Package Pin: ");
1205 V = Plcy.GetMatch(Pkg);
1206 if (V.end() == true)
1207 cout << _("(not found)") << endl;
1208 else
1209 cout << V.VerStr() << endl;
1210 }
1211
1212 // Show the priority tables
1213 cout << _(" Version Table:") << endl;
1214 for (V = Pkg.VersionList(); V.end() == false; V++)
1215 {
1216 if (Pkg.CurrentVer() == V)
1217 cout << " *** " << V.VerStr();
1218 else
1219 cout << " " << V.VerStr();
1220 cout << " " << Plcy.GetPriority(Pkg) << endl;
1221 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1222 {
1223 // Locate the associated index files so we can derive a description
1224 pkgIndexFile *Indx;
1225 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1226 _system->FindIndex(VF.File(),Indx) == false)
1227 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1228 printf(_(" %4i %s\n"),Plcy.GetPriority(VF.File()),
1229 Indx->Describe(true).c_str());
1230 }
1231 }
1232 }
1233
f8f410f5
AL
1234 return true;
1235}
1236 /*}}}*/
880e9be4
AL
1237// GenCaches - Call the main cache generator /*{{{*/
1238// ---------------------------------------------------------------------
1239/* */
b0b4efb9 1240bool GenCaches(CommandLine &Cmd)
880e9be4 1241{
0a8e3465
AL
1242 OpTextProgress Progress(*_config);
1243
880e9be4 1244 pkgSourceList List;
b2e465d6
AL
1245 if (List.ReadMainList() == false)
1246 return false;
0a8e3465 1247 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
1248}
1249 /*}}}*/
e1b74f61
AL
1250// ShowHelp - Show a help screen /*{{{*/
1251// ---------------------------------------------------------------------
1252/* */
b0b4efb9 1253bool ShowHelp(CommandLine &Cmd)
e1b74f61 1254{
b2e465d6
AL
1255 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1256 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
e1b74f61 1257
b2e465d6
AL
1258 cout <<
1259 _("Usage: apt-cache [options] command\n"
1260 " apt-cache [options] add file1 [file1 ...]\n"
1261 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1262 "\n"
1263 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1264 "cache files, and query information from them\n"
1265 "\n"
1266 "Commands:\n"
1267 " add - Add an package file to the source cache\n"
1268 " gencaches - Build both the package and source cache\n"
1269 " showpkg - Show some general information for a single package\n"
1270 " stats - Show some basic statistics\n"
1271 " dump - Show the entire file in a terse form\n"
1272 " dumpavail - Print an available file to stdout\n"
1273 " unmet - Show unmet dependencies\n"
b2e465d6
AL
1274 " search - Search the package list for a regex pattern\n"
1275 " show - Show a readable record for the package\n"
1276 " depends - Show raw dependency information for a package\n"
1277 " pkgnames - List the names of all packages\n"
1278 " dotty - Generate package graphs for GraphVis\n"
eba05d54 1279 " policy - Show policy settings\n"
b2e465d6
AL
1280 "\n"
1281 "Options:\n"
1282 " -h This help text.\n"
1283 " -p=? The package cache.\n"
1284 " -s=? The source cache.\n"
1285 " -q Disable progress indicator.\n"
1286 " -i Show only important deps for the unmet command.\n"
1287 " -c=? Read this configuration file\n"
1288 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1289 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1290 return true;
e1b74f61
AL
1291}
1292 /*}}}*/
0a8e3465
AL
1293// CacheInitialize - Initialize things for apt-cache /*{{{*/
1294// ---------------------------------------------------------------------
1295/* */
1296void CacheInitialize()
1297{
1298 _config->Set("quiet",0);
1299 _config->Set("help",false);
1300}
1301 /*}}}*/
1164783d 1302
08e8f724 1303int main(int argc,const char *argv[])
1164783d 1304{
08e8f724
AL
1305 CommandLine::Args Args[] = {
1306 {'h',"help","help",0},
04aa15a8 1307 {'v',"version","version",0},
e1b74f61
AL
1308 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1309 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1310 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 1311 {'i',"important","APT::Cache::Important",0},
7e2e2d5d 1312 {'f',"full","APT::Cache::ShowFull",0},
b2e465d6 1313 {'g',"generate","APT::Cache::Generate",0},
648e3cb4 1314 {'a',"all-versions","APT::Cache::AllVersions",0},
7e2e2d5d 1315 {0,"names-only","APT::Cache::NamesOnly",0},
7c1133fe 1316 {0,"all-names","APT::Cache::AllNames",0},
b2e465d6 1317 {0,"recurse","APT::Cache::RecurseDepends",0},
e1b74f61
AL
1318 {'c',"config-file",0,CommandLine::ConfigFile},
1319 {'o',"option",0,CommandLine::ArbItem},
08e8f724 1320 {0,0,0,0}};
b0b4efb9
AL
1321 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1322 {"add",&DoAdd},
1323 {"gencaches",&GenCaches},
f8f410f5 1324 {"showsrc",&ShowSrcPackage},
b0b4efb9
AL
1325 {0,0}};
1326 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1327 {"stats",&Stats},
1328 {"dump",&Dump},
1329 {"dumpavail",&DumpAvail},
1330 {"unmet",&UnMet},
9dbb421f 1331 {"search",&Search},
349cd3b8 1332 {"depends",&Depends},
3e94da1b 1333 {"dotty",&Dotty},
7e2e2d5d 1334 {"show",&ShowPackage},
7c1133fe 1335 {"pkgnames",&ShowPkgNames},
af87ab54 1336 {"policy",&Policy},
b0b4efb9 1337 {0,0}};
0a8e3465
AL
1338
1339 CacheInitialize();
e1b74f61
AL
1340
1341 // Parse the command line and initialize the package library
1342 CommandLine CmdL(Args,_config);
b2e465d6
AL
1343 if (pkgInitConfig(*_config) == false ||
1344 CmdL.Parse(argc,argv) == false ||
1345 pkgInitSystem(*_config,_system) == false)
08e8f724
AL
1346 {
1347 _error->DumpErrors();
1348 return 100;
1164783d 1349 }
8efa2a3b 1350
e1b74f61
AL
1351 // See if the help should be shown
1352 if (_config->FindB("help") == true ||
1353 CmdL.FileSize() == 0)
b2e465d6
AL
1354 {
1355 ShowHelp(CmdL);
1356 return 0;
1357 }
1358
a9a5908d
AL
1359 // Deal with stdout not being a tty
1360 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1361 _config->Set("quiet","1");
1362
b0b4efb9 1363 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
4b1b89c5 1364 {
2a3f3893 1365 MMap *Map = 0;
b2e465d6 1366 if (_config->FindB("APT::Cache::Generate",true) == false)
4b1b89c5
AL
1367 {
1368 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
1369 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
1370 }
1371 else
1372 {
1373 // Open the cache file
af87ab54
AL
1374 SrcList = new pkgSourceList;
1375 SrcList->ReadMainList();
f8f410f5 1376
4b1b89c5
AL
1377 // Generate it and map it
1378 OpProgress Prog;
af87ab54 1379 pkgMakeStatusCache(*SrcList,Prog,&Map,true);
4b1b89c5
AL
1380 }
1381
b0b4efb9 1382 if (_error->PendingError() == false)
1164783d 1383 {
b2e465d6 1384 pkgCache Cache(Map);
b0b4efb9
AL
1385 GCache = &Cache;
1386 if (_error->PendingError() == false)
1387 CmdL.DispatchArg(CmdsB);
803fafcb
AL
1388 }
1389 delete Map;
1164783d
AL
1390 }
1391
1392 // Print any errors or warnings found during parsing
1393 if (_error->empty() == false)
1394 {
0a8e3465 1395 bool Errors = _error->PendingError();
1164783d 1396 _error->DumpErrors();
0a8e3465 1397 return Errors == true?100:0;
1164783d
AL
1398 }
1399
1400 return 0;
1401}