]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
Sync
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.8 1998/09/26 05:34:29 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 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;
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;
75 }
76
77 return true;
78 }
79 /*}}}*/
80 // Stats - Dump some nice statistics /*{{{*/
81 // ---------------------------------------------------------------------
82 /* */
83 bool Stats(pkgCache &Cache)
84 {
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 /* */
138 bool Dump(pkgCache &Cache)
139 {
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 */
167 bool DumpAvail(pkgCache &Cache)
168 {
169 unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
170
171 for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
172 {
173 if ((I->Flags & pkgCache::Flag::NotSource) != 0)
174 continue;
175
176 if (I.IsOk() == false)
177 {
178 delete [] Buffer;
179 return _error->Error("Package file %s is out of sync.",I.FileName());
180 }
181
182 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
183 if (_error->PendingError() == true)
184 {
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++)
194 {
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 }
208 }
209 }
210 }
211
212 return true;
213 }
214 /*}}}*/
215 // DoAdd - Perform an adding operation /*{{{*/
216 // ---------------------------------------------------------------------
217 /* */
218 bool DoAdd(CommandLine &CmdL)
219 {
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");
223
224 // Open the cache
225 FileFd CacheF(_config->FindDir("Dir::Cache::srcpkgcache"),FileFd::ReadOnly);
226 if (_error->PendingError() == true)
227 return false;
228
229 DynamicMMap Map(CacheF,MMap::Public);
230 if (_error->PendingError() == true)
231 return false;
232
233 OpTextProgress Progress;
234 pkgCacheGenerator Gen(Map,Progress);
235 if (_error->PendingError() == true)
236 return false;
237
238 unsigned long Length = CmdL.FileSize() - 1;
239 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
240 {
241 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
242
243 // Do the merge
244 FileFd TagF(*I,FileFd::ReadOnly);
245 debListParser Parser(TagF);
246 if (_error->PendingError() == true)
247 return _error->Error("Problem opening %s",*I);
248
249 if (Gen.SelectFile(*I) == false)
250 return _error->Error("Problem with SelectFile");
251
252 if (Gen.MergeList(Parser) == false)
253 return _error->Error("Problem with MergeList");
254 }
255
256 Progress.Done();
257 Stats(Gen.GetCache());
258
259 return true;
260 }
261 /*}}}*/
262 // GenCaches - Call the main cache generator /*{{{*/
263 // ---------------------------------------------------------------------
264 /* */
265 bool GenCaches()
266 {
267 OpTextProgress Progress;
268 pkgSourceList List;
269 List.ReadMainList();
270 return pkgMakeStatusCache(List,Progress);
271 }
272 /*}}}*/
273 // ShowHelp - Show a help screen /*{{{*/
274 // ---------------------------------------------------------------------
275 /* */
276 int ShowHelp()
277 {
278 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
279 " compiled on " << __DATE__ << " " << __TIME__ << endl;
280
281 cout << "Usage: apt-cache [options] command" << endl;
282 cout << " apt-cache [options] add file1 [file1 ...]" << endl;
283 cout << " apt-cache [options] showpkg pkg2 [pkg2 ...]" << endl;
284 cout << endl;
285 cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl;
286 cout << "cache files stored in " << _config->FindDir("Dir::Cache") << endl;
287 cout << "It is not ment for ordinary use only as a debug aide." << endl;
288 cout << endl;
289 cout << "Commands:" << endl;
290 cout << " add - Add an package file to the source cache" << endl;
291 cout << " gencaches - Build both the package and source cache" << endl;
292 cout << " showpkg - Show some general information for a single package" << endl;
293 cout << " stats - Show some basic statistics" << endl;
294 cout << " dump - Show the entire file in a terse form" << endl;
295 cout << " dumpavail - Print an available file to stdout" << endl;
296 cout << endl;
297 cout << "Options:" << endl;
298 cout << " -h This help text." << endl;
299 cout << " -p=? The package cache. [" << _config->FindDir("Dir::Cache::pkgcache") << ']' << endl;
300 cout << " -s=? The source cache. [" << _config->FindDir("Dir::Cache::srcpkgcache") << ']' << endl;
301 cout << " -q Disable progress indicator. " << endl;
302 cout << " -c=? Read this configuration file" << endl;
303 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
304 cout << "See the apt-cache(8) and apt.conf(8) manual pages for more information." << endl;
305 return 100;
306 }
307 /*}}}*/
308
309 int main(int argc,const char *argv[])
310 {
311 CommandLine::Args Args[] = {
312 {'h',"help","help",0},
313 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
314 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
315 {'q',"quiet","quiet",CommandLine::IntLevel},
316 {'c',"config-file",0,CommandLine::ConfigFile},
317 {'o',"option",0,CommandLine::ArbItem},
318 {0,0,0,0}};
319
320 // Parse the command line and initialize the package library
321 CommandLine CmdL(Args,_config);
322 if (pkgInitialize(*_config) == false ||
323 CmdL.Parse(argc,argv) == false)
324 {
325 _error->DumpErrors();
326 return 100;
327 }
328
329 // See if the help should be shown
330 if (_config->FindB("help") == true ||
331 CmdL.FileSize() == 0)
332 return ShowHelp();
333
334 while (1)
335 {
336 if (strcmp(CmdL.FileList[0],"add") == 0)
337 {
338 DoAdd(CmdL);
339 break;
340 }
341
342 if (strcmp(CmdL.FileList[0],"gencaches") == 0)
343 {
344 GenCaches();
345 break;
346 }
347
348 // Open the cache file
349 FileFd CacheF(_config->FindDir("Dir::Cache::pkgcache"),FileFd::ReadOnly);
350 if (_error->PendingError() == true)
351 break;
352
353 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
354 if (_error->PendingError() == true)
355 break;
356
357 pkgCache Cache(Map);
358 if (_error->PendingError() == true)
359 break;
360
361 if (strcmp(CmdL.FileList[0],"showpkg") == 0)
362 {
363 DumpPackage(Cache,CmdL);
364 break;
365 }
366
367 if (strcmp(CmdL.FileList[0],"stats") == 0)
368 {
369 Stats(Cache);
370 break;
371 }
372
373 if (strcmp(CmdL.FileList[0],"dump") == 0)
374 {
375 Dump(Cache);
376 break;
377 }
378
379 if (strcmp(CmdL.FileList[0],"dumpavail") == 0)
380 {
381 DumpAvail(Cache);
382 break;
383 }
384
385 _error->Error("Invalid operation %s", CmdL.FileList[0]);
386 break;
387 }
388
389 // Print any errors or warnings found during parsing
390 if (_error->empty() == false)
391 {
392 _error->DumpErrors();
393 return 100;
394 }
395
396 return 0;
397 }