]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.13 1998/11/27 01:52:53 jgg Exp $
4 /* ######################################################################
6 apt-cache - Manages the cache files
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools. The
10 only really usefull function right now is dumpavail which is used
11 by the dselect method. Everything else is ment as a debug aide.
13 Returns 100 on failure, 0 on success.
15 ##################################################################### */
17 // Include Files /*{{{*/
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/pkgcachegen.h>
20 #include <apt-pkg/deblistparser.h>
21 #include <apt-pkg/init.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/cmndline.h>
30 // UnMet - Show unmet dependencies /*{{{*/
31 // ---------------------------------------------------------------------
33 bool UnMet(pkgCache
&Cache
)
35 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
37 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
40 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
43 pkgCache::DepIterator Start
;
44 pkgCache::DepIterator End
;
47 // Skip everything but depends
48 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
49 End
->Type
!= pkgCache::Dep::Depends
&&
50 End
->Type
!= pkgCache::Dep::Suggests
&&
51 End
->Type
!= pkgCache::Dep::Recommends
)
54 // Verify the or group
56 pkgCache::DepIterator RealStart
= Start
;
59 // See if this dep is Ok
60 pkgCache::Version
**VList
= Start
.AllTargets();
81 cout
<< "Package " << P
.Name() << " version " <<
82 V
.VerStr() << " has an unmet dep:" << endl
;
85 // Print out the dep type
86 cout
<< " " << End
.DepType() << ": ";
92 cout
<< Start
.TargetPkg().Name();
93 if (Start
.TargetVer() != 0)
94 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
110 // DumpPackage - Show a dump of a package record /*{{{*/
111 // ---------------------------------------------------------------------
113 bool DumpPackage(pkgCache
&Cache
,CommandLine
&CmdL
)
115 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
117 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(*I
);
118 if (Pkg
.end() == true)
120 _error
->Warning("Unable to locate package %s",*I
);
124 cout
<< "Package: " << Pkg
.Name() << endl
;
125 cout
<< "Versions: ";
126 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
128 cout
<< Cur
.VerStr();
129 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
130 cout
<< "(" << Vf
.File().FileName() << ")";
136 cout
<< "Reverse Depends: " << endl
;
137 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
138 cout
<< " " << D
.ParentPkg().Name() << ',' << D
.TargetPkg().Name() << endl
;
140 cout
<< "Dependencies: " << endl
;
141 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
143 cout
<< Cur
.VerStr() << " - ";
144 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
145 cout
<< Dep
.TargetPkg().Name() << " (" << (int)Dep
->CompareOp
<< " " << Dep
.TargetVer() << ") ";
149 cout
<< "Provides: " << endl
;
150 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
152 cout
<< Cur
.VerStr() << " - ";
153 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
154 cout
<< Prv
.ParentPkg().Name() << " ";
157 cout
<< "Reverse Provides: " << endl
;
158 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
159 cout
<< Prv
.OwnerPkg().Name() << " " << Prv
.OwnerVer().VerStr();
167 // Stats - Dump some nice statistics /*{{{*/
168 // ---------------------------------------------------------------------
170 bool Stats(pkgCache
&Cache
)
172 cout
<< "Total Package Names : " << Cache
.Head().PackageCount
<< endl
;
173 pkgCache::PkgIterator I
= Cache
.PkgBegin();
180 for (;I
.end() != true; I
++)
182 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
188 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
194 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
197 if (I
.ProvidesList()->NextProvides
== 0)
205 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
211 cout
<< " Normal Packages: " << Normal
<< endl
;
212 cout
<< " Pure Virtual Packages: " << Virtual
<< endl
;
213 cout
<< " Single Virtual Packages: " << DVirt
<< endl
;
214 cout
<< " Mixed Virtual Packages: " << NVirt
<< endl
;
215 cout
<< " Missing: " << Missing
<< endl
;
217 cout
<< "Total Distinct Versions: " << Cache
.Head().VersionCount
<< endl
;
218 cout
<< "Total Dependencies: " << Cache
.Head().DependsCount
<< endl
;
222 // Check - Check some things about the cache /*{{{*/
223 // ---------------------------------------------------------------------
224 /* Debug aide mostly */
225 bool Check(pkgCache
&Cache
)
227 pkgCache::PkgIterator Pkg
= Cache
.PkgBegin();
228 for (;Pkg
.end() != true; Pkg
++)
230 if (Pkg
.Section() == 0 && Pkg
->VersionList
!= 0)
231 cout
<< "Bad section " << Pkg
.Name() << endl
;
233 for (pkgCache::VerIterator Cur
= Pkg
.VersionList();
234 Cur
.end() != true; Cur
++)
236 if (Cur
->Priority
< 1 || Cur
->Priority
> 5)
237 cout
<< "Bad prio " << Pkg
.Name() << ',' << Cur
.VerStr() << " == " << (int)Cur
->Priority
<< endl
;
243 // Dump - show everything /*{{{*/
244 // ---------------------------------------------------------------------
246 bool Dump(pkgCache
&Cache
)
248 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
250 cout
<< "Package: " << P
.Name() << endl
;
251 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
253 cout
<< " Version: " << V
.VerStr() << endl
;
254 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
255 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
256 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
260 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
262 cout
<< "File: " << F
.FileName() << endl
;
263 cout
<< " Size: " << F
->Size
<< endl
;
264 cout
<< " ID: " << F
->ID
<< endl
;
265 cout
<< " Flags: " << F
->Flags
<< endl
;
266 cout
<< " Time: " << ctime(&F
->mtime
) << endl
;
272 // DumpAvail - Print out the available list /*{{{*/
273 // ---------------------------------------------------------------------
274 /* This is needed to make dpkg --merge happy */
275 bool DumpAvail(pkgCache
&Cache
)
277 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
279 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
281 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
284 if (I
.IsOk() == false)
287 return _error
->Error("Package file %s is out of sync.",I
.FileName());
290 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
291 if (_error
->PendingError() == true)
297 /* Write all of the records from this package file, we search the entire
298 structure to find them */
299 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
301 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
303 if (V
->FileList
== 0)
305 if (V
.FileList().File() != I
)
308 // Read the record and then write it out again.
309 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
310 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
311 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
323 // DoAdd - Perform an adding operation /*{{{*/
324 // ---------------------------------------------------------------------
326 bool DoAdd(CommandLine
&CmdL
)
328 // Make sure there is at least one argument
329 if (CmdL
.FileSize() <= 1)
330 return _error
->Error("You must give at least one file name");
333 FileFd
CacheF(_config
->FindFile("Dir::Cache::srcpkgcache"),FileFd::WriteAny
);
334 if (_error
->PendingError() == true)
337 DynamicMMap
Map(CacheF
,MMap::Public
);
338 if (_error
->PendingError() == true)
341 OpTextProgress
Progress(*_config
);
342 pkgCacheGenerator
Gen(Map
,Progress
);
343 if (_error
->PendingError() == true)
346 unsigned long Length
= CmdL
.FileSize() - 1;
347 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
349 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
352 FileFd
TagF(*I
,FileFd::ReadOnly
);
353 debListParser
Parser(TagF
);
354 if (_error
->PendingError() == true)
355 return _error
->Error("Problem opening %s",*I
);
357 if (Gen
.SelectFile(*I
) == false)
358 return _error
->Error("Problem with SelectFile");
360 if (Gen
.MergeList(Parser
) == false)
361 return _error
->Error("Problem with MergeList");
365 Stats(Gen
.GetCache());
370 // GenCaches - Call the main cache generator /*{{{*/
371 // ---------------------------------------------------------------------
375 OpTextProgress
Progress(*_config
);
379 return pkgMakeStatusCache(List
,Progress
);
382 // ShowHelp - Show a help screen /*{{{*/
383 // ---------------------------------------------------------------------
387 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
388 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
390 cout
<< "Usage: apt-cache [options] command" << endl
;
391 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
392 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
394 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
395 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
396 cout
<< "It is not ment for ordinary use only as a debug aide." << endl
;
398 cout
<< "Commands:" << endl
;
399 cout
<< " add - Add an package file to the source cache" << endl
;
400 cout
<< " gencaches - Build both the package and source cache" << endl
;
401 cout
<< " showpkg - Show some general information for a single package" << endl
;
402 cout
<< " stats - Show some basic statistics" << endl
;
403 cout
<< " dump - Show the entire file in a terse form" << endl
;
404 cout
<< " dumpavail - Print an available file to stdout" << endl
;
405 cout
<< " unmet - Show unmet dependencies" << endl
;
406 cout
<< " check - Check the cache a bit" << endl
;
408 cout
<< "Options:" << endl
;
409 cout
<< " -h This help text." << endl
;
410 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
411 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
412 cout
<< " -q Disable progress indicator. " << endl
;
413 cout
<< " -c=? Read this configuration file" << endl
;
414 cout
<< " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl
;
415 cout
<< "See the apt-cache(8) and apt.conf(8) manual pages for more information." << endl
;
419 // CacheInitialize - Initialize things for apt-cache /*{{{*/
420 // ---------------------------------------------------------------------
422 void CacheInitialize()
424 _config
->Set("quiet",0);
425 _config
->Set("help",false);
429 int main(int argc
,const char *argv
[])
431 CommandLine::Args Args
[] = {
432 {'h',"help","help",0},
433 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
434 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
435 {'q',"quiet","quiet",CommandLine::IntLevel
},
436 {'c',"config-file",0,CommandLine::ConfigFile
},
437 {'o',"option",0,CommandLine::ArbItem
},
442 // Parse the command line and initialize the package library
443 CommandLine
CmdL(Args
,_config
);
444 if (pkgInitialize(*_config
) == false ||
445 CmdL
.Parse(argc
,argv
) == false)
447 _error
->DumpErrors();
451 // See if the help should be shown
452 if (_config
->FindB("help") == true ||
453 CmdL
.FileSize() == 0)
458 if (strcmp(CmdL
.FileList
[0],"add") == 0)
464 if (strcmp(CmdL
.FileList
[0],"gencaches") == 0)
470 // Open the cache file
471 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly
);
472 if (_error
->PendingError() == true)
475 MMap
Map(CacheF
,MMap::Public
| MMap::ReadOnly
);
476 if (_error
->PendingError() == true)
480 if (_error
->PendingError() == true)
483 if (strcmp(CmdL
.FileList
[0],"showpkg") == 0)
485 DumpPackage(Cache
,CmdL
);
489 if (strcmp(CmdL
.FileList
[0],"stats") == 0)
495 if (strcmp(CmdL
.FileList
[0],"dump") == 0)
501 if (strcmp(CmdL
.FileList
[0],"dumpavail") == 0)
507 if (strcmp(CmdL
.FileList
[0],"unmet") == 0)
513 if (strcmp(CmdL
.FileList
[0],"check") == 0)
519 _error
->Error("Invalid operation %s", CmdL
.FileList
[0]);
523 // Print any errors or warnings found during parsing
524 if (_error
->empty() == false)
526 bool Errors
= _error
->PendingError();
527 _error
->DumpErrors();
528 return Errors
== true?100:0;