]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.12 1998/11/14 07:20:29 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 // Dump - show everything /*{{{*/
223 // ---------------------------------------------------------------------
225 bool Dump(pkgCache
&Cache
)
227 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
229 cout
<< "Package: " << P
.Name() << endl
;
230 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
232 cout
<< " Version: " << V
.VerStr() << endl
;
233 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
234 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
235 cout
<< " Depends: " << D
.TargetPkg().Name() << ' ' << D
.TargetVer() << endl
;
239 for (pkgCache::PkgFileIterator
F(Cache
); F
.end() == false; F
++)
241 cout
<< "File: " << F
.FileName() << endl
;
242 cout
<< " Size: " << F
->Size
<< endl
;
243 cout
<< " ID: " << F
->ID
<< endl
;
244 cout
<< " Flags: " << F
->Flags
<< endl
;
245 cout
<< " Time: " << ctime(&F
->mtime
) << endl
;
251 // DumpAvail - Print out the available list /*{{{*/
252 // ---------------------------------------------------------------------
253 /* This is needed to make dpkg --merge happy */
254 bool DumpAvail(pkgCache
&Cache
)
256 unsigned char *Buffer
= new unsigned char[Cache
.HeaderP
->MaxVerFileSize
];
258 for (pkgCache::PkgFileIterator I
= Cache
.FileBegin(); I
.end() == false; I
++)
260 if ((I
->Flags
& pkgCache::Flag::NotSource
) != 0)
263 if (I
.IsOk() == false)
266 return _error
->Error("Package file %s is out of sync.",I
.FileName());
269 FileFd
PkgF(I
.FileName(),FileFd::ReadOnly
);
270 if (_error
->PendingError() == true)
276 /* Write all of the records from this package file, we search the entire
277 structure to find them */
278 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; P
++)
280 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
282 if (V
->FileList
== 0)
284 if (V
.FileList().File() != I
)
287 // Read the record and then write it out again.
288 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
289 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false ||
290 write(STDOUT_FILENO
,Buffer
,V
.FileList()->Size
) != V
.FileList()->Size
)
302 // DoAdd - Perform an adding operation /*{{{*/
303 // ---------------------------------------------------------------------
305 bool DoAdd(CommandLine
&CmdL
)
307 // Make sure there is at least one argument
308 if (CmdL
.FileSize() <= 1)
309 return _error
->Error("You must give at least one file name");
312 FileFd
CacheF(_config
->FindFile("Dir::Cache::srcpkgcache"),FileFd::WriteAny
);
313 if (_error
->PendingError() == true)
316 DynamicMMap
Map(CacheF
,MMap::Public
);
317 if (_error
->PendingError() == true)
320 OpTextProgress
Progress(*_config
);
321 pkgCacheGenerator
Gen(Map
,Progress
);
322 if (_error
->PendingError() == true)
325 unsigned long Length
= CmdL
.FileSize() - 1;
326 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
328 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
331 FileFd
TagF(*I
,FileFd::ReadOnly
);
332 debListParser
Parser(TagF
);
333 if (_error
->PendingError() == true)
334 return _error
->Error("Problem opening %s",*I
);
336 if (Gen
.SelectFile(*I
) == false)
337 return _error
->Error("Problem with SelectFile");
339 if (Gen
.MergeList(Parser
) == false)
340 return _error
->Error("Problem with MergeList");
344 Stats(Gen
.GetCache());
349 // GenCaches - Call the main cache generator /*{{{*/
350 // ---------------------------------------------------------------------
354 OpTextProgress
Progress(*_config
);
358 return pkgMakeStatusCache(List
,Progress
);
361 // ShowHelp - Show a help screen /*{{{*/
362 // ---------------------------------------------------------------------
366 cout
<< PACKAGE
<< ' ' << VERSION
<< " for " << ARCHITECTURE
<<
367 " compiled on " << __DATE__
<< " " << __TIME__
<< endl
;
369 cout
<< "Usage: apt-cache [options] command" << endl
;
370 cout
<< " apt-cache [options] add file1 [file1 ...]" << endl
;
371 cout
<< " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl
;
373 cout
<< "apt-cache is a low-level tool used to manipulate APT's binary" << endl
;
374 cout
<< "cache files stored in " << _config
->FindFile("Dir::Cache") << endl
;
375 cout
<< "It is not ment for ordinary use only as a debug aide." << endl
;
377 cout
<< "Commands:" << endl
;
378 cout
<< " add - Add an package file to the source cache" << endl
;
379 cout
<< " gencaches - Build both the package and source cache" << endl
;
380 cout
<< " showpkg - Show some general information for a single package" << endl
;
381 cout
<< " stats - Show some basic statistics" << endl
;
382 cout
<< " dump - Show the entire file in a terse form" << endl
;
383 cout
<< " dumpavail - Print an available file to stdout" << endl
;
384 cout
<< " unmet - Show unmet dependencies" << endl
;
386 cout
<< "Options:" << endl
;
387 cout
<< " -h This help text." << endl
;
388 cout
<< " -p=? The package cache. [" << _config
->FindFile("Dir::Cache::pkgcache") << ']' << endl
;
389 cout
<< " -s=? The source cache. [" << _config
->FindFile("Dir::Cache::srcpkgcache") << ']' << endl
;
390 cout
<< " -q Disable progress indicator. " << endl
;
391 cout
<< " -c=? Read this configuration file" << endl
;
392 cout
<< " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl
;
393 cout
<< "See the apt-cache(8) and apt.conf(8) manual pages for more information." << endl
;
397 // CacheInitialize - Initialize things for apt-cache /*{{{*/
398 // ---------------------------------------------------------------------
400 void CacheInitialize()
402 _config
->Set("quiet",0);
403 _config
->Set("help",false);
407 int main(int argc
,const char *argv
[])
409 CommandLine::Args Args
[] = {
410 {'h',"help","help",0},
411 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
412 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
413 {'q',"quiet","quiet",CommandLine::IntLevel
},
414 {'c',"config-file",0,CommandLine::ConfigFile
},
415 {'o',"option",0,CommandLine::ArbItem
},
420 // Parse the command line and initialize the package library
421 CommandLine
CmdL(Args
,_config
);
422 if (pkgInitialize(*_config
) == false ||
423 CmdL
.Parse(argc
,argv
) == false)
425 _error
->DumpErrors();
429 // See if the help should be shown
430 if (_config
->FindB("help") == true ||
431 CmdL
.FileSize() == 0)
436 if (strcmp(CmdL
.FileList
[0],"add") == 0)
442 if (strcmp(CmdL
.FileList
[0],"gencaches") == 0)
448 // Open the cache file
449 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly
);
450 if (_error
->PendingError() == true)
453 MMap
Map(CacheF
,MMap::Public
| MMap::ReadOnly
);
454 if (_error
->PendingError() == true)
458 if (_error
->PendingError() == true)
461 if (strcmp(CmdL
.FileList
[0],"showpkg") == 0)
463 DumpPackage(Cache
,CmdL
);
467 if (strcmp(CmdL
.FileList
[0],"stats") == 0)
473 if (strcmp(CmdL
.FileList
[0],"dump") == 0)
479 if (strcmp(CmdL
.FileList
[0],"dumpavail") == 0)
485 if (strcmp(CmdL
.FileList
[0],"unmet") == 0)
491 _error
->Error("Invalid operation %s", CmdL
.FileList
[0]);
495 // Print any errors or warnings found during parsing
496 if (_error
->empty() == false)
498 bool Errors
= _error
->PendingError();
499 _error
->DumpErrors();
500 return Errors
== true?100:0;