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