winch support
[ntk/apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
303a1703 3// $Id: apt-cache.cc,v 1.10 1998/10/19 23:45:35 jgg Exp $
1164783d
AL
4/* ######################################################################
5
e1b74f61 6 apt-cache - Manages the cache files
1164783d 7
e1b74f61
AL
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.
1164783d
AL
12
13 Returns 100 on failure, 0 on success.
14
15 ##################################################################### */
16 /*}}}*/
17// Include Files /*{{{*/
18#include <apt-pkg/error.h>
19#include <apt-pkg/pkgcachegen.h>
20#include <apt-pkg/deblistparser.h>
8efa2a3b 21#include <apt-pkg/init.h>
404ec98e 22#include <apt-pkg/progress.h>
880e9be4 23#include <apt-pkg/sourcelist.h>
08e8f724 24#include <apt-pkg/cmndline.h>
1164783d
AL
25
26#include <iostream.h>
e1b74f61 27#include <config.h>
1164783d
AL
28 /*}}}*/
29
1164783d
AL
30// DumpPackage - Show a dump of a package record /*{{{*/
31// ---------------------------------------------------------------------
32/* */
e1b74f61 33bool DumpPackage(pkgCache &Cache,CommandLine &CmdL)
ad00ae81 34{
e1b74f61 35 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1164783d 36 {
e1b74f61 37 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1164783d
AL
38 if (Pkg.end() == true)
39 {
e1b74f61 40 _error->Warning("Unable to locate package %s",*I);
1164783d
AL
41 continue;
42 }
43
44 cout << "Package: " << Pkg.Name() << endl;
45 cout << "Versions: ";
46 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
47 cout << Cur.VerStr() << ',';
48 cout << endl;
49
50 cout << "Reverse Depends: " << endl;
51 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
52 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
53
54 cout << "Dependencies: " << endl;
55 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
56 {
57 cout << Cur.VerStr() << " - ";
58 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
59 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
60 cout << endl;
61 }
62
63 cout << "Provides: " << endl;
64 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
65 {
66 cout << Cur.VerStr() << " - ";
67 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
68 cout << Prv.ParentPkg().Name() << " ";
69 cout << endl;
8efa2a3b
AL
70 }
71 cout << "Reverse Provides: " << endl;
72 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
73 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr();
74 cout << endl;
1164783d
AL
75 }
76
77 return true;
78}
79 /*}}}*/
80// Stats - Dump some nice statistics /*{{{*/
81// ---------------------------------------------------------------------
82/* */
ad00ae81 83bool Stats(pkgCache &Cache)
1164783d 84{
1164783d
AL
85 cout << "Total Package Names : " << Cache.Head().PackageCount << endl;
86 pkgCache::PkgIterator I = Cache.PkgBegin();
87
88 int Normal = 0;
89 int Virtual = 0;
90 int NVirt = 0;
91 int DVirt = 0;
92 int Missing = 0;
93 for (;I.end() != true; I++)
94 {
95 if (I->VersionList != 0 && I->ProvidesList == 0)
96 {
97 Normal++;
98 continue;
99 }
100
101 if (I->VersionList != 0 && I->ProvidesList != 0)
102 {
103 NVirt++;
104 continue;
105 }
106
107 if (I->VersionList == 0 && I->ProvidesList != 0)
108 {
109 // Only 1 provides
110 if (I.ProvidesList()->NextProvides == 0)
111 {
112 DVirt++;
113 }
114 else
115 Virtual++;
116 continue;
117 }
118 if (I->VersionList == 0 && I->ProvidesList == 0)
119 {
120 Missing++;
121 continue;
122 }
123 }
124 cout << " Normal Packages: " << Normal << endl;
125 cout << " Pure Virtual Packages: " << Virtual << endl;
126 cout << " Single Virtual Packages: " << DVirt << endl;
127 cout << " Mixed Virtual Packages: " << NVirt << endl;
128 cout << " Missing: " << Missing << endl;
129
130 cout << "Total Distinct Versions: " << Cache.Head().VersionCount << endl;
131 cout << "Total Dependencies: " << Cache.Head().DependsCount << endl;
132 return true;
133}
134 /*}}}*/
135// Dump - show everything /*{{{*/
136// ---------------------------------------------------------------------
137/* */
ad00ae81 138bool Dump(pkgCache &Cache)
1164783d 139{
1164783d
AL
140 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
141 {
142 cout << "Package: " << P.Name() << endl;
143 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
144 {
145 cout << " Version: " << V.VerStr() << endl;
146 cout << " File: " << V.FileList().File().FileName() << endl;
147 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
148 cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
149 }
150 }
151
152 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
153 {
154 cout << "File: " << F.FileName() << endl;
155 cout << " Size: " << F->Size << endl;
156 cout << " ID: " << F->ID << endl;
157 cout << " Flags: " << F->Flags << endl;
158 cout << " Time: " << ctime(&F->mtime) << endl;
159 }
160
161 return true;
162}
163 /*}}}*/
164// DumpAvail - Print out the available list /*{{{*/
165// ---------------------------------------------------------------------
166/* This is needed to make dpkg --merge happy */
ad00ae81 167bool DumpAvail(pkgCache &Cache)
1164783d 168{
ad00ae81 169 unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
1164783d 170
ad00ae81 171 for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
1164783d 172 {
ad00ae81 173 if ((I->Flags & pkgCache::Flag::NotSource) != 0)
1164783d
AL
174 continue;
175
ad00ae81
AL
176 if (I.IsOk() == false)
177 {
178 delete [] Buffer;
179 return _error->Error("Package file %s is out of sync.",I.FileName());
180 }
1164783d 181
8e06abb2 182 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
ad00ae81 183 if (_error->PendingError() == true)
1164783d 184 {
ad00ae81
AL
185 delete [] Buffer;
186 return false;
187 }
188
189 /* Write all of the records from this package file, we search the entire
190 structure to find them */
191 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
192 {
193 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
1164783d 194 {
ad00ae81
AL
195 if (V->FileList == 0)
196 continue;
197 if (V.FileList().File() != I)
198 continue;
199
200 // Read the record and then write it out again.
201 if (PkgF.Seek(V.FileList()->Offset) == false ||
202 PkgF.Read(Buffer,V.FileList()->Size) == false ||
203 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
204 {
205 delete [] Buffer;
206 return false;
207 }
1164783d 208 }
1164783d 209 }
ad00ae81
AL
210 }
211
212 return true;
213}
214 /*}}}*/
215// DoAdd - Perform an adding operation /*{{{*/
216// ---------------------------------------------------------------------
217/* */
e1b74f61 218bool DoAdd(CommandLine &CmdL)
ad00ae81 219{
e1b74f61
AL
220 // Make sure there is at least one argument
221 if (CmdL.FileSize() <= 1)
222 return _error->Error("You must give at least one file name");
ad00ae81
AL
223
224 // Open the cache
303a1703 225 FileFd CacheF(_config->FindFile("Dir::Cache::srcpkgcache"),FileFd::WriteAny);
ad00ae81
AL
226 if (_error->PendingError() == true)
227 return false;
228
229 DynamicMMap Map(CacheF,MMap::Public);
230 if (_error->PendingError() == true)
231 return false;
404ec98e 232
0a8e3465 233 OpTextProgress Progress(*_config);
404ec98e 234 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
235 if (_error->PendingError() == true)
236 return false;
237
e1b74f61
AL
238 unsigned long Length = CmdL.FileSize() - 1;
239 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 240 {
e1b74f61 241 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
1164783d 242
ad00ae81 243 // Do the merge
e1b74f61 244 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
245 debListParser Parser(TagF);
246 if (_error->PendingError() == true)
e1b74f61 247 return _error->Error("Problem opening %s",*I);
ad00ae81 248
e1b74f61 249 if (Gen.SelectFile(*I) == false)
ad00ae81
AL
250 return _error->Error("Problem with SelectFile");
251
252 if (Gen.MergeList(Parser) == false)
253 return _error->Error("Problem with MergeList");
1164783d 254 }
404ec98e
AL
255
256 Progress.Done();
ad00ae81
AL
257 Stats(Gen.GetCache());
258
1164783d
AL
259 return true;
260}
261 /*}}}*/
880e9be4
AL
262// GenCaches - Call the main cache generator /*{{{*/
263// ---------------------------------------------------------------------
264/* */
265bool GenCaches()
266{
0a8e3465
AL
267 OpTextProgress Progress(*_config);
268
880e9be4
AL
269 pkgSourceList List;
270 List.ReadMainList();
0a8e3465 271 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
272}
273 /*}}}*/
e1b74f61
AL
274// ShowHelp - Show a help screen /*{{{*/
275// ---------------------------------------------------------------------
276/* */
277int ShowHelp()
278{
279 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
280 " compiled on " << __DATE__ << " " << __TIME__ << endl;
281
282 cout << "Usage: apt-cache [options] command" << endl;
283 cout << " apt-cache [options] add file1 [file1 ...]" << endl;
0a8e3465 284 cout << " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl;
e1b74f61
AL
285 cout << endl;
286 cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl;
303a1703 287 cout << "cache files stored in " << _config->FindFile("Dir::Cache") << endl;
e1b74f61
AL
288 cout << "It is not ment for ordinary use only as a debug aide." << endl;
289 cout << endl;
290 cout << "Commands:" << endl;
291 cout << " add - Add an package file to the source cache" << endl;
292 cout << " gencaches - Build both the package and source cache" << endl;
293 cout << " showpkg - Show some general information for a single package" << endl;
294 cout << " stats - Show some basic statistics" << endl;
295 cout << " dump - Show the entire file in a terse form" << endl;
296 cout << " dumpavail - Print an available file to stdout" << endl;
297 cout << endl;
298 cout << "Options:" << endl;
299 cout << " -h This help text." << endl;
303a1703
AL
300 cout << " -p=? The package cache. [" << _config->FindFile("Dir::Cache::pkgcache") << ']' << endl;
301 cout << " -s=? The source cache. [" << _config->FindFile("Dir::Cache::srcpkgcache") << ']' << endl;
e1b74f61
AL
302 cout << " -q Disable progress indicator. " << endl;
303 cout << " -c=? Read this configuration file" << endl;
304 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
305 cout << "See the apt-cache(8) and apt.conf(8) manual pages for more information." << endl;
306 return 100;
307}
308 /*}}}*/
0a8e3465
AL
309// CacheInitialize - Initialize things for apt-cache /*{{{*/
310// ---------------------------------------------------------------------
311/* */
312void CacheInitialize()
313{
314 _config->Set("quiet",0);
315 _config->Set("help",false);
316}
317 /*}}}*/
1164783d 318
08e8f724 319int main(int argc,const char *argv[])
1164783d 320{
08e8f724
AL
321 CommandLine::Args Args[] = {
322 {'h',"help","help",0},
e1b74f61
AL
323 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
324 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
325 {'q',"quiet","quiet",CommandLine::IntLevel},
326 {'c',"config-file",0,CommandLine::ConfigFile},
327 {'o',"option",0,CommandLine::ArbItem},
08e8f724 328 {0,0,0,0}};
0a8e3465
AL
329
330 CacheInitialize();
e1b74f61
AL
331
332 // Parse the command line and initialize the package library
333 CommandLine CmdL(Args,_config);
08e8f724 334 if (pkgInitialize(*_config) == false ||
e1b74f61 335 CmdL.Parse(argc,argv) == false)
08e8f724
AL
336 {
337 _error->DumpErrors();
338 return 100;
1164783d 339 }
8efa2a3b 340
e1b74f61
AL
341 // See if the help should be shown
342 if (_config->FindB("help") == true ||
343 CmdL.FileSize() == 0)
344 return ShowHelp();
345
1164783d
AL
346 while (1)
347 {
e1b74f61 348 if (strcmp(CmdL.FileList[0],"add") == 0)
1164783d 349 {
e1b74f61 350 DoAdd(CmdL);
1164783d
AL
351 break;
352 }
ad00ae81 353
e1b74f61 354 if (strcmp(CmdL.FileList[0],"gencaches") == 0)
880e9be4
AL
355 {
356 GenCaches();
357 break;
358 }
359
ad00ae81 360 // Open the cache file
303a1703 361 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
ad00ae81
AL
362 if (_error->PendingError() == true)
363 break;
364
365 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
366 if (_error->PendingError() == true)
367 break;
368
369 pkgCache Cache(Map);
370 if (_error->PendingError() == true)
371 break;
1164783d 372
e1b74f61 373 if (strcmp(CmdL.FileList[0],"showpkg") == 0)
1164783d 374 {
e1b74f61 375 DumpPackage(Cache,CmdL);
1164783d
AL
376 break;
377 }
378
e1b74f61 379 if (strcmp(CmdL.FileList[0],"stats") == 0)
1164783d 380 {
ad00ae81 381 Stats(Cache);
1164783d
AL
382 break;
383 }
384
e1b74f61 385 if (strcmp(CmdL.FileList[0],"dump") == 0)
1164783d 386 {
ad00ae81 387 Dump(Cache);
1164783d
AL
388 break;
389 }
390
e1b74f61 391 if (strcmp(CmdL.FileList[0],"dumpavail") == 0)
1164783d 392 {
ad00ae81 393 DumpAvail(Cache);
1164783d
AL
394 break;
395 }
880e9be4 396
e1b74f61 397 _error->Error("Invalid operation %s", CmdL.FileList[0]);
1164783d
AL
398 break;
399 }
400
401 // Print any errors or warnings found during parsing
402 if (_error->empty() == false)
403 {
0a8e3465 404 bool Errors = _error->PendingError();
1164783d 405 _error->DumpErrors();
0a8e3465 406 return Errors == true?100:0;
1164783d
AL
407 }
408
409 return 0;
410}