]> git.saurik.com Git - apt.git/blame_incremental - apt-pkg/deb/debindexfile.cc
Rework TransactionID stuff
[apt.git] / apt-pkg / deb / debindexfile.cc
... / ...
CommitLineData
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: debindexfile.cc,v 1.5.2.3 2004/01/04 19:11:00 mdz Exp $
4/* ######################################################################
5
6 Debian Specific sources.list types and the three sorts of Debian
7 index files.
8
9 ##################################################################### */
10 /*}}}*/
11// Include Files /*{{{*/
12#include <config.h>
13
14#include <apt-pkg/debindexfile.h>
15#include <apt-pkg/debsrcrecords.h>
16#include <apt-pkg/deblistparser.h>
17#include <apt-pkg/debrecords.h>
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>
23#include <apt-pkg/debmetaindex.h>
24#include <apt-pkg/gpgv.h>
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>
33#include <apt-pkg/sptr.h>
34
35#include <stdio.h>
36#include <iostream>
37#include <string>
38#include <sys/stat.h>
39 /*}}}*/
40
41using std::string;
42
43// SourcesIndex::debSourcesIndex - Constructor /*{{{*/
44// ---------------------------------------------------------------------
45/* */
46debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) :
47 pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
48{
49}
50 /*}}}*/
51// SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
52// ---------------------------------------------------------------------
53/* The result looks like:
54 http://foo/debian/ stable/main src 1.1.1 (dsc) */
55string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
56 pkgSrcRecords::File const &File) const
57{
58 string Res;
59 Res = ::URI::NoUserPassword(URI) + ' ';
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{
82 string SourcesURI = _config->FindDir("Dir::State::lists") +
83 URItoFileName(IndexURI("Sources"));
84 string SourcesURIgzip = SourcesURI + ".gz";
85
86 if (!FileExists(SourcesURI) && !FileExists(SourcesURIgzip))
87 return NULL;
88 else if (!FileExists(SourcesURI) && FileExists(SourcesURIgzip))
89 SourcesURI = SourcesURIgzip;
90
91 return new debSrcRecordParser(SourcesURI,this);
92}
93 /*}}}*/
94// SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
95// ---------------------------------------------------------------------
96/* */
97string debSourcesIndex::Describe(bool Short) const
98{
99 char S[300];
100 if (Short == true)
101 snprintf(S,sizeof(S),"%s",Info("Sources").c_str());
102 else
103 snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(),
104 IndexFile("Sources").c_str());
105
106 return S;
107}
108 /*}}}*/
109// SourcesIndex::Info - One liner describing the index URI /*{{{*/
110// ---------------------------------------------------------------------
111/* */
112string debSourcesIndex::Info(const char *Type) const
113{
114 string Info = ::URI::NoUserPassword(URI) + ' ';
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{
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;
138}
139
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 /*}}}*/
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{
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
176 FileFd f(IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension);
177 if (!f.Failed())
178 size = f.Size();
179
180 if (_error->PendingError() == true)
181 size = 0;
182 _error->RevertToStack();
183
184 return size;
185}
186 /*}}}*/
187
188// PackagesIndex::debPackagesIndex - Contructor /*{{{*/
189// ---------------------------------------------------------------------
190/* */
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)
194{
195 if (Architecture == "native")
196 Architecture = _config->Find("APT::Architecture");
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{
204 string Res = ::URI::NoUserPassword(URI) + ' ';
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 += " ";
216 if (Dist[Dist.size() - 1] != '/')
217 Res.append(Ver.Arch()).append(" ");
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 */
226string debPackagesIndex::Describe(bool Short) const
227{
228 char S[300];
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());
234 return S;
235}
236 /*}}}*/
237// PackagesIndex::Info - One liner describing the index URI /*{{{*/
238// ---------------------------------------------------------------------
239/* */
240string debPackagesIndex::Info(const char *Type) const
241{
242 string Info = ::URI::NoUserPassword(URI) + ' ';
243 if (Dist[Dist.size() - 1] == '/')
244 {
245 if (Dist != "/")
246 Info += Dist;
247 }
248 else
249 Info += Dist + '/' + Section;
250 Info += " ";
251 if (Dist[Dist.size() - 1] != '/')
252 Info += Architecture + " ";
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{
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;
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 +
281 "/binary-" + Architecture + '/';
282
283 Res += Type;
284 return Res;
285}
286 /*}}}*/
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{
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
305 FileFd f(IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension);
306 if (!f.Failed())
307 size = f.Size();
308
309 if (_error->PendingError() == true)
310 size = 0;
311 _error->RevertToStack();
312
313 return size;
314}
315 /*}}}*/
316// PackagesIndex::Merge - Load the index file into a cache /*{{{*/
317// ---------------------------------------------------------------------
318/* */
319bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
320{
321 string PackageFile = IndexFile("Packages");
322 FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
323 debListParser Parser(&Pkg, Architecture);
324
325 if (_error->PendingError() == true)
326 return _error->Error("Problem opening %s",PackageFile.c_str());
327 if (Prog != NULL)
328 Prog->SubProgress(0,Info("Packages"));
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();
335 pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
336 File->Size = Pkg.FileSize();
337 File->mtime = Pkg.ModificationTime();
338
339 if (Gen.MergeList(Parser) == false)
340 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
341
342 // Check the release file
343 string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
344 bool releaseExists = false;
345 if (FileExists(ReleaseFile) == true)
346 releaseExists = true;
347 else
348 ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
349
350 if (releaseExists == true || FileExists(ReleaseFile) == true)
351 {
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
358 if (_error->PendingError() == true)
359 return false;
360 Parser.LoadReleaseInfo(File,Rel,Section);
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();
373 for (; File.end() == false; ++File)
374 {
375 if (File.FileName() == NULL || FileName != File.FileName())
376 continue;
377
378 struct stat St;
379 if (stat(File.FileName(),&St) != 0)
380 {
381 if (_config->FindB("Debug::pkgCacheGen", false))
382 std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
383 return pkgCache::PkgFileIterator(Cache);
384 }
385 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
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;
391 return pkgCache::PkgFileIterator(Cache);
392 }
393 return File;
394 }
395
396 return File;
397}
398 /*}}}*/
399
400// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
401// ---------------------------------------------------------------------
402/* */
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{}
408 /*}}}*/
409// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
410// ---------------------------------------------------------------------
411/* */
412inline string debTranslationsIndex::IndexFile(const char *Type) const
413{
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;
420}
421string debTranslationsIndex::IndexURI(const char *Type) const
422{
423 string Res;
424 if (Dist[Dist.size() - 1] == '/')
425 {
426 if (Dist != "/")
427 Res = URI + Dist;
428 else
429 Res = URI;
430 }
431 else
432 Res = URI + "dists/" + Dist + '/' + Section +
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{
444 string const TranslationFile = string("Translation-").append(Language);
445 new pkgAcqIndexTrans(Owner, IndexURI(Language),
446 Info(TranslationFile.c_str()),
447 TranslationFile);
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(),
463 IndexFile(Language).c_str());
464 return S;
465}
466 /*}}}*/
467// TranslationsIndex::Info - One liner describing the index URI /*{{{*/
468// ---------------------------------------------------------------------
469/* */
470string debTranslationsIndex::Info(const char *Type) const
471{
472 string Info = ::URI::NoUserPassword(URI) + ' ';
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 /*}}}*/
485bool debTranslationsIndex::HasPackages() const /*{{{*/
486{
487 return FileExists(IndexFile(Language));
488}
489 /*}}}*/
490// TranslationsIndex::Exists - Check if the index is available /*{{{*/
491// ---------------------------------------------------------------------
492/* */
493bool debTranslationsIndex::Exists() const
494{
495 return FileExists(IndexFile(Language));
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{
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
508 FileFd f(IndexFile(Language), FileFd::ReadOnly, FileFd::Extension);
509 if (!f.Failed())
510 size = f.Size();
511
512 if (_error->PendingError() == true)
513 size = 0;
514 _error->RevertToStack();
515
516 return size;
517}
518 /*}}}*/
519// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
520// ---------------------------------------------------------------------
521/* */
522bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
523{
524 // Check the translation file, if in use
525 string TranslationFile = IndexFile(Language);
526 if (FileExists(TranslationFile))
527 {
528 FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
529 debTranslationsParser TransParser(&Trans);
530 if (_error->PendingError() == true)
531 return false;
532
533 if (Prog != NULL)
534 Prog->SubProgress(0, Info(TranslationFile.c_str()));
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();
540 TransFile->Size = Trans.FileSize();
541 TransFile->mtime = Trans.ModificationTime();
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 /*}}}*/
550// TranslationsIndex::FindInCache - Find this index /*{{{*/
551// ---------------------------------------------------------------------
552/* */
553pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
554{
555 string FileName = IndexFile(Language);
556
557 pkgCache::PkgFileIterator File = Cache.FileBegin();
558 for (; File.end() == false; ++File)
559 {
560 if (FileName != File.FileName())
561 continue;
562
563 struct stat St;
564 if (stat(File.FileName(),&St) != 0)
565 {
566 if (_config->FindB("Debug::pkgCacheGen", false))
567 std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
568 return pkgCache::PkgFileIterator(Cache);
569 }
570 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
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;
576 return pkgCache::PkgFileIterator(Cache);
577 }
578 return File;
579 }
580 return File;
581}
582 /*}}}*/
583// StatusIndex::debStatusIndex - Constructor /*{{{*/
584// ---------------------------------------------------------------------
585/* */
586debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
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/* */
604bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
605{
606 FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
607 if (_error->PendingError() == true)
608 return false;
609 debListParser Parser(&Pkg);
610 if (_error->PendingError() == true)
611 return false;
612
613 if (Prog != NULL)
614 Prog->SubProgress(0,File);
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();
620 CFile->Size = Pkg.FileSize();
621 CFile->mtime = Pkg.ModificationTime();
622 map_stringitem_t const storage = Gen.WriteUniqString("now");
623 CFile->Archive = storage;
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();
636 for (; File.end() == false; ++File)
637 {
638 if (this->File != File.FileName())
639 continue;
640
641 struct stat St;
642 if (stat(File.FileName(),&St) != 0)
643 {
644 if (_config->FindB("Debug::pkgCacheGen", false))
645 std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
646 return pkgCache::PkgFileIterator(Cache);
647 }
648 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
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;
654 return pkgCache::PkgFileIterator(Cache);
655 }
656 return File;
657 }
658 return File;
659}
660 /*}}}*/
661// StatusIndex::Exists - Check if the index is available /*{{{*/
662// ---------------------------------------------------------------------
663/* */
664APT_CONST bool debStatusIndex::Exists() const
665{
666 // Abort if the file does not exist.
667 return true;
668}
669 /*}}}*/
670
671// debDebPkgFile - Single .deb file /*{{{*/
672// ---------------------------------------------------------------------
673debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
674 : pkgIndexFile(true), DebFile(DebFile)
675{
676 DebFileFullPath = flAbsPath(DebFile);
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?
695 Configuration::Item const *Opts = _config->Tree("DPkg::Options");
696 std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg");
697 std::vector<const char *> Args;
698 Args.push_back(dpkg.c_str());
699 if (Opts != 0)
700 {
701 Opts = Opts->Child;
702 for (; Opts != 0; Opts = Opts->Next)
703 {
704 if (Opts->Value.empty() == true)
705 continue;
706 Args.push_back(Opts->Value.c_str());
707 }
708 }
709 Args.push_back("-I");
710 Args.push_back(DebFile.c_str());
711 Args.push_back("control");
712 Args.push_back(NULL);
713 FileFd PipeFd;
714 pid_t Child;
715 if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
716 return _error->Error("Popen failed");
717 // FIXME: static buffer
718 char buf[8*1024];
719 unsigned long long n = 0;
720 if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false)
721 return _error->Errno("read", "Failed to read dpkg pipe");
722 ExecWait(Child, "Popen");
723
724 // now write the control data to a tempfile
725 SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
726 if(DebControl == NULL)
727 return false;
728 DebControl->Write(buf, n);
729 // append size of the file
730 FileFd Fd(DebFile, FileFd::ReadOnly);
731 string Size;
732 strprintf(Size, "Size: %llu\n", Fd.Size());
733 DebControl->Write(Size.c_str(), Size.size());
734 // and rewind for the listparser
735 DebControl->Seek(0);
736
737 // and give it to the list parser
738 debDebFileParser Parser(DebControl, DebFile);
739 if(Gen.SelectFile(DebFile, "local", *this) == false)
740 return _error->Error("Problem with SelectFile %s", DebFile.c_str());
741
742 pkgCache::PkgFileIterator File = Gen.GetCurFile();
743 File->Size = DebControl->Size();
744 File->mtime = DebControl->ModificationTime();
745
746 if (Gen.MergeList(Parser) == false)
747 return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
748
749 return true;
750}
751pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
752{
753 pkgCache::PkgFileIterator File = Cache.FileBegin();
754 for (; File.end() == false; ++File)
755 {
756 if (File.FileName() == NULL || DebFile != File.FileName())
757 continue;
758
759 return File;
760 }
761
762 return File;
763}
764unsigned long debDebPkgFileIndex::Size() const
765{
766 struct stat buf;
767 if(stat(DebFile.c_str(), &buf) != 0)
768 return 0;
769 return buf.st_size;
770}
771 /*}}}*/
772
773// debDscFileIndex stuff
774debDscFileIndex::debDscFileIndex(std::string &DscFile)
775 : pkgIndexFile(true), DscFile(DscFile)
776{
777}
778
779bool debDscFileIndex::Exists() const
780{
781 return FileExists(DscFile);
782}
783
784unsigned long debDscFileIndex::Size() const
785{
786 struct stat buf;
787 if(stat(DscFile.c_str(), &buf) == 0)
788 return buf.st_size;
789 return 0;
790}
791
792// DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/
793// ---------------------------------------------------------------------
794/* */
795pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
796{
797 if (!FileExists(DscFile))
798 return NULL;
799
800 return new debDscRecordParser(DscFile,this);
801}
802 /*}}}*/
803
804
805
806
807// ---------------------------------------------------------------------
808// Index File types for Debian /*{{{*/
809class debIFTypeSrc : public pkgIndexFile::Type
810{
811 public:
812
813 debIFTypeSrc() {Label = "Debian Source Index";};
814};
815class debIFTypePkg : public pkgIndexFile::Type
816{
817 public:
818
819 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
820 {
821 return new debRecordParser(File.FileName(),*File.Cache());
822 };
823 debIFTypePkg() {Label = "Debian Package Index";};
824};
825class debIFTypeTrans : public debIFTypePkg
826{
827 public:
828 debIFTypeTrans() {Label = "Debian Translation Index";};
829};
830class debIFTypeStatus : public pkgIndexFile::Type
831{
832 public:
833
834 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
835 {
836 return new debRecordParser(File.FileName(),*File.Cache());
837 };
838 debIFTypeStatus() {Label = "Debian dpkg status file";};
839};
840class debIFTypeDebPkgFile : public pkgIndexFile::Type
841{
842 public:
843 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
844 {
845 return new debDebFileRecordParser(File.FileName(),*File.Cache());
846 };
847 debIFTypeDebPkgFile() {Label = "deb Package file";};
848};
849class debIFTypeDscFile : public pkgIndexFile::Type
850{
851 public:
852 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
853 {
854 return new debDscRecordParser(DscFile, NULL);
855 };
856 debIFTypeDscFile() {Label = "dsc File Source Index";};
857};
858class debIFTypeDebianSourceDir : public pkgIndexFile::Type
859{
860 public:
861 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
862 {
863 return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
864 };
865 debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
866};
867
868static debIFTypeSrc _apt_Src;
869static debIFTypePkg _apt_Pkg;
870static debIFTypeTrans _apt_Trans;
871static debIFTypeStatus _apt_Status;
872static debIFTypeDebPkgFile _apt_DebPkgFile;
873// file based pseudo indexes
874static debIFTypeDscFile _apt_DscFile;
875static debIFTypeDebianSourceDir _apt_DebianSourceDir;
876
877const pkgIndexFile::Type *debSourcesIndex::GetType() const
878{
879 return &_apt_Src;
880}
881const pkgIndexFile::Type *debPackagesIndex::GetType() const
882{
883 return &_apt_Pkg;
884}
885const pkgIndexFile::Type *debTranslationsIndex::GetType() const
886{
887 return &_apt_Trans;
888}
889const pkgIndexFile::Type *debStatusIndex::GetType() const
890{
891 return &_apt_Status;
892}
893const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
894{
895 return &_apt_DebPkgFile;
896}
897const pkgIndexFile::Type *debDscFileIndex::GetType() const
898{
899 return &_apt_DscFile;
900}
901const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
902{
903 return &_apt_DebianSourceDir;
904}
905 /*}}}*/