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