]> git.saurik.com Git - apt.git/blame - apt-pkg/deb/debindexfile.cc
apt-private/acqprogress.cc: do not show file size on IMSHit, it wasn't fetched, so...
[apt.git] / apt-pkg / deb / debindexfile.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
7db98ffc 3// $Id: debindexfile.cc,v 1.5.2.3 2004/01/04 19:11:00 mdz Exp $
b2e465d6
AL
4/* ######################################################################
5
6 Debian Specific sources.list types and the three sorts of Debian
7 index files.
8
9 ##################################################################### */
10 /*}}}*/
11// Include Files /*{{{*/
ea542140
DK
12#include <config.h>
13
b2e465d6
AL
14#include <apt-pkg/debindexfile.h>
15#include <apt-pkg/debsrcrecords.h>
16#include <apt-pkg/deblistparser.h>
17#include <apt-pkg/debrecords.h>
b2e465d6
AL
18#include <apt-pkg/configuration.h>
19#include <apt-pkg/progress.h>
20#include <apt-pkg/error.h>
21#include <apt-pkg/strutl.h>
22#include <apt-pkg/acquire-item.h>
7db98ffc 23#include <apt-pkg/debmetaindex.h>
233b7808 24#include <apt-pkg/gpgv.h>
453b82a3
DK
25#include <apt-pkg/fileutl.h>
26#include <apt-pkg/indexfile.h>
27#include <apt-pkg/mmap.h>
28#include <apt-pkg/pkgcache.h>
29#include <apt-pkg/cacheiterators.h>
30#include <apt-pkg/pkgcachegen.h>
31#include <apt-pkg/pkgrecords.h>
32#include <apt-pkg/srcrecords.h>
0d29b9d4 33#include <apt-pkg/sptr.h>
e011829d 34
453b82a3
DK
35#include <stdio.h>
36#include <iostream>
37#include <string>
b2e465d6
AL
38#include <sys/stat.h>
39 /*}}}*/
40
73688d27
DK
41using std::string;
42
b2e465d6
AL
43// SourcesIndex::debSourcesIndex - Constructor /*{{{*/
44// ---------------------------------------------------------------------
45/* */
7db98ffc
MZ
46debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) :
47 pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
b2e465d6
AL
48{
49}
50 /*}}}*/
51// SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
52// ---------------------------------------------------------------------
53/* The result looks like:
5e02df82 54 http://foo/debian/ stable/main src 1.1.1 (dsc) */
b2e465d6
AL
55string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
56 pkgSrcRecords::File const &File) const
57{
58 string Res;
5e02df82 59 Res = ::URI::NoUserPassword(URI) + ' ';
b2e465d6
AL
60 if (Dist[Dist.size() - 1] == '/')
61 {
62 if (Dist != "/")
63 Res += Dist;
64 }
65 else
66 Res += Dist + '/' + Section;
67
68 Res += " ";
69 Res += Record.Package();
70 Res += " ";
71 Res += Record.Version();
72 if (File.Type.empty() == false)
73 Res += " (" + File.Type + ")";
74 return Res;
75}
76 /*}}}*/
77// SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/
78// ---------------------------------------------------------------------
79/* */
80pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
81{
94e8c9d4 82 string SourcesURI = _config->FindDir("Dir::State::lists") +
83 URItoFileName(IndexURI("Sources"));
84 string SourcesURIgzip = SourcesURI + ".gz";
1aadba5a
MV
85
86 if (!FileExists(SourcesURI) && !FileExists(SourcesURIgzip))
87 return NULL;
88 else if (!FileExists(SourcesURI) && FileExists(SourcesURIgzip))
94e8c9d4 89 SourcesURI = SourcesURIgzip;
90
91 return new debSrcRecordParser(SourcesURI,this);
b2e465d6
AL
92}
93 /*}}}*/
94// SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
95// ---------------------------------------------------------------------
96/* */
af87ab54 97string debSourcesIndex::Describe(bool Short) const
b2e465d6
AL
98{
99 char S[300];
af87ab54 100 if (Short == true)
cc742108 101 snprintf(S,sizeof(S),"%s",Info("Sources").c_str());
af87ab54 102 else
cc742108 103 snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(),
af87ab54
AL
104 IndexFile("Sources").c_str());
105
b2e465d6
AL
106 return S;
107}
108 /*}}}*/
109// SourcesIndex::Info - One liner describing the index URI /*{{{*/
110// ---------------------------------------------------------------------
111/* */
112string debSourcesIndex::Info(const char *Type) const
113{
5e02df82 114 string Info = ::URI::NoUserPassword(URI) + ' ';
b2e465d6
AL
115 if (Dist[Dist.size() - 1] == '/')
116 {
117 if (Dist != "/")
118 Info += Dist;
119 }
120 else
121 Info += Dist + '/' + Section;
122 Info += " ";
123 Info += Type;
124 return Info;
125}
126 /*}}}*/
127// SourcesIndex::Index* - Return the URI to the index files /*{{{*/
128// ---------------------------------------------------------------------
129/* */
130inline string debSourcesIndex::IndexFile(const char *Type) const
131{
ec7a129e 132 string s = URItoFileName(IndexURI(Type));
133 string sgzip = s + ".gz";
134 if (!FileExists(s) && FileExists(sgzip))
135 return sgzip;
136 else
137 return s;
b2e465d6 138}
ec7a129e 139
b2e465d6
AL
140string debSourcesIndex::IndexURI(const char *Type) const
141{
142 string Res;
143 if (Dist[Dist.size() - 1] == '/')
144 {
145 if (Dist != "/")
146 Res = URI + Dist;
147 else
148 Res = URI;
149 }
150 else
151 Res = URI + "dists/" + Dist + '/' + Section +
152 "/source/";
153
154 Res += Type;
155 return Res;
156}
157 /*}}}*/
b2e465d6
AL
158// SourcesIndex::Exists - Check if the index is available /*{{{*/
159// ---------------------------------------------------------------------
160/* */
161bool debSourcesIndex::Exists() const
162{
163 return FileExists(IndexFile("Sources"));
164}
165 /*}}}*/
166// SourcesIndex::Size - Return the size of the index /*{{{*/
167// ---------------------------------------------------------------------
168/* */
169unsigned long debSourcesIndex::Size() const
170{
915f0520
MP
171 unsigned long size = 0;
172
173 /* we need to ignore errors here; if the lists are absent, just return 0 */
174 _error->PushToStack();
175
f0e83599 176 FileFd f(IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension);
915f0520
MP
177 if (!f.Failed())
178 size = f.Size();
179
180 if (_error->PendingError() == true)
181 size = 0;
182 _error->RevertToStack();
5473df3f 183
915f0520 184 return size;
b2e465d6
AL
185}
186 /*}}}*/
187
188// PackagesIndex::debPackagesIndex - Contructor /*{{{*/
189// ---------------------------------------------------------------------
190/* */
5dd4c8b8
DK
191debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section,
192 bool const &Trusted, string const &Arch) :
193 pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch)
b2e465d6 194{
5dd4c8b8
DK
195 if (Architecture == "native")
196 Architecture = _config->Find("APT::Architecture");
b2e465d6
AL
197}
198 /*}}}*/
199// PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/
200// ---------------------------------------------------------------------
201/* This is a shorter version that is designed to be < 60 chars or so */
202string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
203{
5e02df82 204 string Res = ::URI::NoUserPassword(URI) + ' ';
b2e465d6
AL
205 if (Dist[Dist.size() - 1] == '/')
206 {
207 if (Dist != "/")
208 Res += Dist;
209 }
210 else
211 Res += Dist + '/' + Section;
212
213 Res += " ";
214 Res += Ver.ParentPkg().Name();
215 Res += " ";
dd13742e
DK
216 if (Dist[Dist.size() - 1] != '/')
217 Res.append(Ver.Arch()).append(" ");
b2e465d6
AL
218 Res += Ver.VerStr();
219 return Res;
220}
221 /*}}}*/
222// PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/
223// ---------------------------------------------------------------------
224/* This should help the user find the index in the sources.list and
225 in the filesystem for problem solving */
af87ab54 226string debPackagesIndex::Describe(bool Short) const
b2e465d6
AL
227{
228 char S[300];
af87ab54
AL
229 if (Short == true)
230 snprintf(S,sizeof(S),"%s",Info("Packages").c_str());
231 else
232 snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(),
233 IndexFile("Packages").c_str());
b2e465d6
AL
234 return S;
235}
236 /*}}}*/
237// PackagesIndex::Info - One liner describing the index URI /*{{{*/
238// ---------------------------------------------------------------------
239/* */
240string debPackagesIndex::Info(const char *Type) const
241{
5e02df82 242 string Info = ::URI::NoUserPassword(URI) + ' ';
b2e465d6
AL
243 if (Dist[Dist.size() - 1] == '/')
244 {
245 if (Dist != "/")
246 Info += Dist;
247 }
248 else
249 Info += Dist + '/' + Section;
250 Info += " ";
dd13742e
DK
251 if (Dist[Dist.size() - 1] != '/')
252 Info += Architecture + " ";
b2e465d6
AL
253 Info += Type;
254 return Info;
255}
256 /*}}}*/
257// PackagesIndex::Index* - Return the URI to the index files /*{{{*/
258// ---------------------------------------------------------------------
259/* */
260inline string debPackagesIndex::IndexFile(const char *Type) const
261{
ec7a129e 262 string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
263 string sgzip = s + ".gz";
264 if (!FileExists(s) && FileExists(sgzip))
265 return sgzip;
266 else
267 return s;
b2e465d6
AL
268}
269string debPackagesIndex::IndexURI(const char *Type) const
270{
271 string Res;
272 if (Dist[Dist.size() - 1] == '/')
273 {
274 if (Dist != "/")
275 Res = URI + Dist;
276 else
277 Res = URI;
278 }
279 else
280 Res = URI + "dists/" + Dist + '/' + Section +
5dd4c8b8 281 "/binary-" + Architecture + '/';
b2e465d6
AL
282
283 Res += Type;
284 return Res;
285}
286 /*}}}*/
b2e465d6
AL
287// PackagesIndex::Exists - Check if the index is available /*{{{*/
288// ---------------------------------------------------------------------
289/* */
290bool debPackagesIndex::Exists() const
291{
292 return FileExists(IndexFile("Packages"));
293}
294 /*}}}*/
295// PackagesIndex::Size - Return the size of the index /*{{{*/
296// ---------------------------------------------------------------------
297/* This is really only used for progress reporting. */
298unsigned long debPackagesIndex::Size() const
299{
915f0520
MP
300 unsigned long size = 0;
301
302 /* we need to ignore errors here; if the lists are absent, just return 0 */
303 _error->PushToStack();
304
f0e83599 305 FileFd f(IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension);
915f0520
MP
306 if (!f.Failed())
307 size = f.Size();
5473df3f 308
915f0520
MP
309 if (_error->PendingError() == true)
310 size = 0;
311 _error->RevertToStack();
312
313 return size;
b2e465d6
AL
314}
315 /*}}}*/
316// PackagesIndex::Merge - Load the index file into a cache /*{{{*/
317// ---------------------------------------------------------------------
318/* */
2e5f4e45 319bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
b2e465d6
AL
320{
321 string PackageFile = IndexFile("Packages");
468720c5 322 FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
5dd4c8b8 323 debListParser Parser(&Pkg, Architecture);
3184b4cf 324
b2e465d6
AL
325 if (_error->PendingError() == true)
326 return _error->Error("Problem opening %s",PackageFile.c_str());
2e5f4e45
DK
327 if (Prog != NULL)
328 Prog->SubProgress(0,Info("Packages"));
b2e465d6
AL
329 ::URI Tmp(URI);
330 if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
331 return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
332
333 // Store the IMS information
334 pkgCache::PkgFileIterator File = Gen.GetCurFile();
a9fe5928 335 pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
76a763e1
DK
336 File->Size = Pkg.FileSize();
337 File->mtime = Pkg.ModificationTime();
b2e465d6
AL
338
339 if (Gen.MergeList(Parser) == false)
340 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
341
342 // Check the release file
fe0f7911
DK
343 string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
344 bool releaseExists = false;
b2e465d6 345 if (FileExists(ReleaseFile) == true)
fe0f7911
DK
346 releaseExists = true;
347 else
348 ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
349
350 if (releaseExists == true || FileExists(ReleaseFile) == true)
b2e465d6 351 {
233b7808
DK
352 FileFd Rel;
353 // Beware: The 'Release' file might be clearsigned in case the
354 // signature for an 'InRelease' file couldn't be checked
355 if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
356 return false;
357
b2e465d6
AL
358 if (_error->PendingError() == true)
359 return false;
e011829d 360 Parser.LoadReleaseInfo(File,Rel,Section);
b2e465d6
AL
361 }
362
363 return true;
364}
365 /*}}}*/
366// PackagesIndex::FindInCache - Find this index /*{{{*/
367// ---------------------------------------------------------------------
368/* */
369pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
370{
371 string FileName = IndexFile("Packages");
372 pkgCache::PkgFileIterator File = Cache.FileBegin();
f7f0d6c7 373 for (; File.end() == false; ++File)
b2e465d6 374 {
f6442c77 375 if (File.FileName() == NULL || FileName != File.FileName())
b2e465d6
AL
376 continue;
377
378 struct stat St;
379 if (stat(File.FileName(),&St) != 0)
c8e572e3
MV
380 {
381 if (_config->FindB("Debug::pkgCacheGen", false))
382 std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
b2e465d6 383 return pkgCache::PkgFileIterator(Cache);
c8e572e3 384 }
b2e465d6 385 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
c8e572e3
MV
386 {
387 if (_config->FindB("Debug::pkgCacheGen", false))
388 std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
389 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
390 << ") doesn't match for " << File.FileName() << std::endl;
b2e465d6 391 return pkgCache::PkgFileIterator(Cache);
c8e572e3 392 }
b2e465d6
AL
393 return File;
394 }
395
396 return File;
397}
398 /*}}}*/
399
a52f938b
OS
400// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
401// ---------------------------------------------------------------------
402/* */
45df0ad2
DK
403debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section,
404 char const * const Translation) :
405 pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section),
406 Language(Translation)
407{}
a52f938b
OS
408 /*}}}*/
409// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
410// ---------------------------------------------------------------------
411/* */
412inline string debTranslationsIndex::IndexFile(const char *Type) const
413{
ec7a129e 414 string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
415 string sgzip = s + ".gz";
416 if (!FileExists(s) && FileExists(sgzip))
417 return sgzip;
418 else
419 return s;
a52f938b
OS
420}
421string debTranslationsIndex::IndexURI(const char *Type) const
422{
423 string Res;
424 if (Dist[Dist.size() - 1] == '/')
425 {
426 if (Dist != "/")
422eeaaa 427 Res = URI + Dist;
a52f938b 428 else
422eeaaa 429 Res = URI;
a52f938b
OS
430 }
431 else
422eeaaa 432 Res = URI + "dists/" + Dist + '/' + Section +
a52f938b
OS
433 "/i18n/Translation-";
434
435 Res += Type;
436 return Res;
437}
438 /*}}}*/
439// TranslationsIndex::GetIndexes - Fetch the index files /*{{{*/
440// ---------------------------------------------------------------------
441/* */
442bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const
443{
e4d30d3f
MV
444 string const TranslationFile = string("Translation-").append(Language);
445 new pkgAcqIndexTrans(Owner, IndexURI(Language),
446 Info(TranslationFile.c_str()),
447 TranslationFile);
a52f938b
OS
448
449 return true;
450}
451 /*}}}*/
452// TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/
453// ---------------------------------------------------------------------
454/* This should help the user find the index in the sources.list and
455 in the filesystem for problem solving */
456string debTranslationsIndex::Describe(bool Short) const
457{
458 char S[300];
459 if (Short == true)
460 snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
461 else
462 snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
45df0ad2 463 IndexFile(Language).c_str());
a52f938b
OS
464 return S;
465}
466 /*}}}*/
467// TranslationsIndex::Info - One liner describing the index URI /*{{{*/
468// ---------------------------------------------------------------------
469/* */
470string debTranslationsIndex::Info(const char *Type) const
471{
5e02df82 472 string Info = ::URI::NoUserPassword(URI) + ' ';
a52f938b
OS
473 if (Dist[Dist.size() - 1] == '/')
474 {
475 if (Dist != "/")
476 Info += Dist;
477 }
478 else
479 Info += Dist + '/' + Section;
480 Info += " ";
481 Info += Type;
482 return Info;
483}
484 /*}}}*/
45df0ad2 485bool debTranslationsIndex::HasPackages() const /*{{{*/
11680bfd 486{
45df0ad2 487 return FileExists(IndexFile(Language));
11680bfd 488}
45df0ad2 489 /*}}}*/
a52f938b
OS
490// TranslationsIndex::Exists - Check if the index is available /*{{{*/
491// ---------------------------------------------------------------------
492/* */
493bool debTranslationsIndex::Exists() const
494{
45df0ad2 495 return FileExists(IndexFile(Language));
a52f938b
OS
496}
497 /*}}}*/
498// TranslationsIndex::Size - Return the size of the index /*{{{*/
499// ---------------------------------------------------------------------
500/* This is really only used for progress reporting. */
501unsigned long debTranslationsIndex::Size() const
502{
915f0520
MP
503 unsigned long size = 0;
504
505 /* we need to ignore errors here; if the lists are absent, just return 0 */
506 _error->PushToStack();
507
f0e83599 508 FileFd f(IndexFile(Language), FileFd::ReadOnly, FileFd::Extension);
915f0520
MP
509 if (!f.Failed())
510 size = f.Size();
5473df3f 511
915f0520
MP
512 if (_error->PendingError() == true)
513 size = 0;
514 _error->RevertToStack();
5473df3f 515
915f0520 516 return size;
a52f938b
OS
517}
518 /*}}}*/
519// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
520// ---------------------------------------------------------------------
521/* */
2e5f4e45 522bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
a52f938b
OS
523{
524 // Check the translation file, if in use
45df0ad2 525 string TranslationFile = IndexFile(Language);
64c2bdc9 526 if (FileExists(TranslationFile))
a52f938b 527 {
468720c5 528 FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
a52f938b
OS
529 debListParser TransParser(&Trans);
530 if (_error->PendingError() == true)
531 return false;
532
2e5f4e45
DK
533 if (Prog != NULL)
534 Prog->SubProgress(0, Info(TranslationFile.c_str()));
a52f938b
OS
535 if (Gen.SelectFile(TranslationFile,string(),*this) == false)
536 return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
537
538 // Store the IMS information
539 pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
76a763e1
DK
540 TransFile->Size = Trans.FileSize();
541 TransFile->mtime = Trans.ModificationTime();
a52f938b
OS
542
543 if (Gen.MergeList(TransParser) == false)
544 return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
545 }
546
547 return true;
548}
549 /*}}}*/
c51c6f08
OS
550// TranslationsIndex::FindInCache - Find this index /*{{{*/
551// ---------------------------------------------------------------------
552/* */
553pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
554{
45df0ad2 555 string FileName = IndexFile(Language);
4d34acf1 556
c51c6f08 557 pkgCache::PkgFileIterator File = Cache.FileBegin();
f7f0d6c7 558 for (; File.end() == false; ++File)
f416d22e
MV
559 {
560 if (FileName != File.FileName())
561 continue;
4d34acf1 562
f416d22e
MV
563 struct stat St;
564 if (stat(File.FileName(),&St) != 0)
c8e572e3
MV
565 {
566 if (_config->FindB("Debug::pkgCacheGen", false))
567 std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
f416d22e 568 return pkgCache::PkgFileIterator(Cache);
c8e572e3 569 }
f416d22e 570 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
c8e572e3
MV
571 {
572 if (_config->FindB("Debug::pkgCacheGen", false))
573 std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
574 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
575 << ") doesn't match for " << File.FileName() << std::endl;
f416d22e 576 return pkgCache::PkgFileIterator(Cache);
c8e572e3 577 }
f416d22e
MV
578 return File;
579 }
c51c6f08
OS
580 return File;
581}
582 /*}}}*/
b2e465d6
AL
583// StatusIndex::debStatusIndex - Constructor /*{{{*/
584// ---------------------------------------------------------------------
585/* */
7db98ffc 586debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
b2e465d6
AL
587{
588}
589 /*}}}*/
590// StatusIndex::Size - Return the size of the index /*{{{*/
591// ---------------------------------------------------------------------
592/* */
593unsigned long debStatusIndex::Size() const
594{
595 struct stat S;
596 if (stat(File.c_str(),&S) != 0)
597 return 0;
598 return S.st_size;
599}
600 /*}}}*/
601// StatusIndex::Merge - Load the index file into a cache /*{{{*/
602// ---------------------------------------------------------------------
603/* */
2e5f4e45 604bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
b2e465d6 605{
468720c5 606 FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
b2e465d6
AL
607 if (_error->PendingError() == true)
608 return false;
609 debListParser Parser(&Pkg);
610 if (_error->PendingError() == true)
611 return false;
2e5f4e45
DK
612
613 if (Prog != NULL)
614 Prog->SubProgress(0,File);
b2e465d6
AL
615 if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
616 return _error->Error("Problem with SelectFile %s",File.c_str());
617
618 // Store the IMS information
619 pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
76a763e1
DK
620 CFile->Size = Pkg.FileSize();
621 CFile->mtime = Pkg.ModificationTime();
2b803d40
DK
622 map_ptrloc const storage = Gen.WriteUniqString("now");
623 CFile->Archive = storage;
b2e465d6
AL
624
625 if (Gen.MergeList(Parser) == false)
626 return _error->Error("Problem with MergeList %s",File.c_str());
627 return true;
628}
629 /*}}}*/
630// StatusIndex::FindInCache - Find this index /*{{{*/
631// ---------------------------------------------------------------------
632/* */
633pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
634{
635 pkgCache::PkgFileIterator File = Cache.FileBegin();
f7f0d6c7 636 for (; File.end() == false; ++File)
b2e465d6
AL
637 {
638 if (this->File != File.FileName())
639 continue;
640
641 struct stat St;
642 if (stat(File.FileName(),&St) != 0)
c8e572e3
MV
643 {
644 if (_config->FindB("Debug::pkgCacheGen", false))
645 std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
b2e465d6 646 return pkgCache::PkgFileIterator(Cache);
c8e572e3 647 }
b2e465d6 648 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
c8e572e3
MV
649 {
650 if (_config->FindB("Debug::pkgCacheGen", false))
651 std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
652 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
653 << ") doesn't match for " << File.FileName() << std::endl;
b2e465d6 654 return pkgCache::PkgFileIterator(Cache);
c8e572e3 655 }
b2e465d6
AL
656 return File;
657 }
658 return File;
659}
660 /*}}}*/
661// StatusIndex::Exists - Check if the index is available /*{{{*/
662// ---------------------------------------------------------------------
663/* */
a02db58f 664APT_CONST bool debStatusIndex::Exists() const
b2e465d6
AL
665{
666 // Abort if the file does not exist.
667 return true;
668}
669 /*}}}*/
670
0d29b9d4
MV
671// debDebPkgFile - Single .deb file /*{{{*/
672// ---------------------------------------------------------------------
673debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
674 : pkgIndexFile(true), DebFile(DebFile)
675{
fb11075f 676 DebFileFullPath = flAbsPath(DebFile);
0d29b9d4
MV
677}
678
679std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
680{
681 return "file:" + DebFileFullPath;
682}
683
684bool debDebPkgFileIndex::Exists() const
685{
686 return FileExists(DebFile);
687}
688bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
689{
690 if(Prog)
691 Prog->SubProgress(0, "Reading deb file");
692
693 // get the control data out of the deb file vid dpkg -I
694 // ... can I haz libdpkg?
a9d990a2
MV
695 const char *Args[5] = {"/usr/bin/dpkg",
696 "-I",
697 DebFile.c_str(),
698 "control",
699 NULL};
700 FileFd PipeFd;
701 pid_t Child;
702 if(Popen(Args, PipeFd, Child, FileFd::ReadOnly) == false)
703 return _error->Error("Popen failed");
0d29b9d4
MV
704 // FIXME: static buffer
705 char buf[8*1024];
a9d990a2
MV
706 unsigned long long n = 0;
707 if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false)
708 return _error->Errno("read", "Failed to read dpkg pipe");
709 ExecWait(Child, "Popen");
0d29b9d4
MV
710
711 // now write the control data to a tempfile
712 SPtr<FileFd> DebControl = GetTempFile("deb-file-" + DebFile);
713 if(DebControl == NULL)
714 return false;
715 DebControl->Write(buf, n);
716 // append size of the file
717 FileFd Fd(DebFile, FileFd::ReadOnly);
718 string Size;
719 strprintf(Size, "Size: %llu\n", Fd.Size());
720 DebControl->Write(Size.c_str(), Size.size());
721 // and rewind for the listparser
722 DebControl->Seek(0);
723
724 // and give it to the list parser
725 debDebFileParser Parser(DebControl, DebFile);
726 if(Gen.SelectFile(DebFile, "local", *this) == false)
727 return _error->Error("Problem with SelectFile %s", DebFile.c_str());
728
729 pkgCache::PkgFileIterator File = Gen.GetCurFile();
730 File->Size = DebControl->Size();
731 File->mtime = DebControl->ModificationTime();
732
733 if (Gen.MergeList(Parser) == false)
734 return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
735
736 return true;
737}
738pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
739{
740 // FIXME: we could simply always return pkgCache::PkgFileIterator(Cache);
741 // to indicate its never in the cache which will force a Merge()
742 pkgCache::PkgFileIterator File = Cache.FileBegin();
743 for (; File.end() == false; ++File)
744 {
745 if (File.FileName() == NULL || DebFile != File.FileName())
746 continue;
747
748 return File;
749 }
750
751 return File;
752}
753unsigned long debDebPkgFileIndex::Size() const
754{
755 struct stat buf;
756 if(stat(DebFile.c_str(), &buf) != 0)
757 return 0;
758 return buf.st_size;
759}
760 /*}}}*/
761
a49e7948
MV
762// debDscFileIndex stuff
763debDscFileIndex::debDscFileIndex(std::string &DscFile)
764 : pkgIndexFile(true), DscFile(DscFile)
765{
766}
767
768bool debDscFileIndex::Exists() const
769{
770 return FileExists(DscFile);
771}
772
773unsigned long debDscFileIndex::Size() const
774{
775 struct stat buf;
776 if(stat(DscFile.c_str(), &buf) == 0)
777 return buf.st_size;
778 return 0;
779}
780
781// DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/
782// ---------------------------------------------------------------------
783/* */
784pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
785{
786 if (!FileExists(DscFile))
787 return NULL;
788
789 return new debDscRecordParser(DscFile,this);
790}
791 /*}}}*/
792
793
794
795
796// ---------------------------------------------------------------------
b2e465d6
AL
797// Index File types for Debian /*{{{*/
798class debIFTypeSrc : public pkgIndexFile::Type
799{
800 public:
801
802 debIFTypeSrc() {Label = "Debian Source Index";};
803};
804class debIFTypePkg : public pkgIndexFile::Type
805{
806 public:
807
808 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
809 {
810 return new debRecordParser(File.FileName(),*File.Cache());
811 };
812 debIFTypePkg() {Label = "Debian Package Index";};
813};
97234432
MV
814class debIFTypeTrans : public debIFTypePkg
815{
816 public:
817 debIFTypeTrans() {Label = "Debian Translation Index";};
818};
b2e465d6
AL
819class debIFTypeStatus : public pkgIndexFile::Type
820{
821 public:
822
823 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
824 {
825 return new debRecordParser(File.FileName(),*File.Cache());
826 };
827 debIFTypeStatus() {Label = "Debian dpkg status file";};
828};
0d29b9d4
MV
829class debIFTypeDebPkgFile : public pkgIndexFile::Type
830{
831 public:
832 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
833 {
834 return new debDebFileRecordParser(File.FileName(),*File.Cache());
835 };
836 debIFTypeDebPkgFile() {Label = "deb Package file";};
837};
a49e7948
MV
838class debIFTypeDscFile : public pkgIndexFile::Type
839{
840 public:
841 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
842 {
843 return new debDscRecordParser(DscFile, NULL);
844 };
845 debIFTypeDscFile() {Label = "dsc File Source Index";};
846};
77da39b9
MV
847class debIFTypeDebianSourceDir : public pkgIndexFile::Type
848{
849 public:
850 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
851 {
852 return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
853 };
854 debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
855};
a49e7948 856
b2e465d6
AL
857static debIFTypeSrc _apt_Src;
858static debIFTypePkg _apt_Pkg;
97234432 859static debIFTypeTrans _apt_Trans;
b2e465d6 860static debIFTypeStatus _apt_Status;
0d29b9d4 861static debIFTypeDebPkgFile _apt_DebPkgFile;
a49e7948
MV
862// file based pseudo indexes
863static debIFTypeDscFile _apt_DscFile;
77da39b9 864static debIFTypeDebianSourceDir _apt_DebianSourceDir;
b2e465d6
AL
865
866const pkgIndexFile::Type *debSourcesIndex::GetType() const
867{
868 return &_apt_Src;
869}
870const pkgIndexFile::Type *debPackagesIndex::GetType() const
871{
872 return &_apt_Pkg;
873}
a52f938b
OS
874const pkgIndexFile::Type *debTranslationsIndex::GetType() const
875{
97234432 876 return &_apt_Trans;
a52f938b 877}
b2e465d6
AL
878const pkgIndexFile::Type *debStatusIndex::GetType() const
879{
880 return &_apt_Status;
881}
0d29b9d4
MV
882const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
883{
884 return &_apt_DebPkgFile;
070536e6 885}
a49e7948
MV
886const pkgIndexFile::Type *debDscFileIndex::GetType() const
887{
888 return &_apt_DscFile;
889}
77da39b9
MV
890const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
891{
892 return &_apt_DebianSourceDir;
0d29b9d4 893}
b2e465d6 894 /*}}}*/