]> git.saurik.com Git - apt.git/blame - apt-pkg/deb/debindexfile.cc
Merge branch 'feature/popen' into feature/apt-install-deb
[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{
676 // FIXME: we need to os.normpath(DebFile) here, this is a lame workaround
677 DebFileFullPath = SafeGetCWD() + DebFile;
678}
679
680std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
681{
682 return "file:" + DebFileFullPath;
683}
684
685bool debDebPkgFileIndex::Exists() const
686{
687 return FileExists(DebFile);
688}
689bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
690{
691 if(Prog)
692 Prog->SubProgress(0, "Reading deb file");
693
694 // get the control data out of the deb file vid dpkg -I
695 // ... can I haz libdpkg?
696 string cmd;
697 // FIXME: shell injection
698 strprintf(cmd, "dpkg -I %s control", DebFile.c_str());
699 FILE *p = popen(cmd.c_str(), "r");
700 if (p == NULL)
701 return _error->Error("popen failed");
702 // FIXME: static buffer
703 char buf[8*1024];
704 size_t n = fread(buf, 1, sizeof(buf)-1, p);
705 if (n == 0)
706 return _error->Errno("popen", "Failed to read dpkg pipe");
707 pclose(p);
708
709 // now write the control data to a tempfile
710 SPtr<FileFd> DebControl = GetTempFile("deb-file-" + DebFile);
711 if(DebControl == NULL)
712 return false;
713 DebControl->Write(buf, n);
714 // append size of the file
715 FileFd Fd(DebFile, FileFd::ReadOnly);
716 string Size;
717 strprintf(Size, "Size: %llu\n", Fd.Size());
718 DebControl->Write(Size.c_str(), Size.size());
719 // and rewind for the listparser
720 DebControl->Seek(0);
721
722 // and give it to the list parser
723 debDebFileParser Parser(DebControl, DebFile);
724 if(Gen.SelectFile(DebFile, "local", *this) == false)
725 return _error->Error("Problem with SelectFile %s", DebFile.c_str());
726
727 pkgCache::PkgFileIterator File = Gen.GetCurFile();
728 File->Size = DebControl->Size();
729 File->mtime = DebControl->ModificationTime();
730
731 if (Gen.MergeList(Parser) == false)
732 return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
733
734 return true;
735}
736pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
737{
738 // FIXME: we could simply always return pkgCache::PkgFileIterator(Cache);
739 // to indicate its never in the cache which will force a Merge()
740 pkgCache::PkgFileIterator File = Cache.FileBegin();
741 for (; File.end() == false; ++File)
742 {
743 if (File.FileName() == NULL || DebFile != File.FileName())
744 continue;
745
746 return File;
747 }
748
749 return File;
750}
751unsigned long debDebPkgFileIndex::Size() const
752{
753 struct stat buf;
754 if(stat(DebFile.c_str(), &buf) != 0)
755 return 0;
756 return buf.st_size;
757}
758 /*}}}*/
759
b2e465d6
AL
760// Index File types for Debian /*{{{*/
761class debIFTypeSrc : public pkgIndexFile::Type
762{
763 public:
764
765 debIFTypeSrc() {Label = "Debian Source Index";};
766};
767class debIFTypePkg : public pkgIndexFile::Type
768{
769 public:
770
771 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
772 {
773 return new debRecordParser(File.FileName(),*File.Cache());
774 };
775 debIFTypePkg() {Label = "Debian Package Index";};
776};
97234432
MV
777class debIFTypeTrans : public debIFTypePkg
778{
779 public:
780 debIFTypeTrans() {Label = "Debian Translation Index";};
781};
b2e465d6
AL
782class debIFTypeStatus : public pkgIndexFile::Type
783{
784 public:
785
786 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
787 {
788 return new debRecordParser(File.FileName(),*File.Cache());
789 };
790 debIFTypeStatus() {Label = "Debian dpkg status file";};
791};
0d29b9d4
MV
792class debIFTypeDebPkgFile : public pkgIndexFile::Type
793{
794 public:
795 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
796 {
797 return new debDebFileRecordParser(File.FileName(),*File.Cache());
798 };
799 debIFTypeDebPkgFile() {Label = "deb Package file";};
800};
b2e465d6
AL
801static debIFTypeSrc _apt_Src;
802static debIFTypePkg _apt_Pkg;
97234432 803static debIFTypeTrans _apt_Trans;
b2e465d6 804static debIFTypeStatus _apt_Status;
0d29b9d4 805static debIFTypeDebPkgFile _apt_DebPkgFile;
b2e465d6
AL
806
807const pkgIndexFile::Type *debSourcesIndex::GetType() const
808{
809 return &_apt_Src;
810}
811const pkgIndexFile::Type *debPackagesIndex::GetType() const
812{
813 return &_apt_Pkg;
814}
a52f938b
OS
815const pkgIndexFile::Type *debTranslationsIndex::GetType() const
816{
97234432 817 return &_apt_Trans;
a52f938b 818}
b2e465d6
AL
819const pkgIndexFile::Type *debStatusIndex::GetType() const
820{
821 return &_apt_Status;
822}
0d29b9d4
MV
823const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
824{
825 return &_apt_DebPkgFile;
826}
b2e465d6 827 /*}}}*/