]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debindexfile.cc
d672b4fd86afa7dd59c8aeeaf711c03256860cf6
[apt.git] / apt-pkg / deb / debindexfile.cc
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 <sstream>
38 #include <string>
39 #include <sys/stat.h>
40 /*}}}*/
41
42 using std::string;
43
44 // SourcesIndex::debSourcesIndex - Constructor /*{{{*/
45 // ---------------------------------------------------------------------
46 /* */
47 debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) :
48 pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
49 {
50 }
51 /*}}}*/
52 // SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
53 // ---------------------------------------------------------------------
54 /* The result looks like:
55 http://foo/debian/ stable/main src 1.1.1 (dsc) */
56 string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
57 pkgSrcRecords::File const &File) const
58 {
59 string Res;
60 Res = ::URI::NoUserPassword(URI) + ' ';
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 /* */
81 pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
82 {
83 string SourcesURI = _config->FindDir("Dir::State::lists") +
84 URItoFileName(IndexURI("Sources"));
85
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;
97 }
98 /*}}}*/
99 // SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
100 // ---------------------------------------------------------------------
101 /* */
102 string debSourcesIndex::Describe(bool Short) const
103 {
104 char S[300];
105 if (Short == true)
106 snprintf(S,sizeof(S),"%s",Info("Sources").c_str());
107 else
108 snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(),
109 IndexFile("Sources").c_str());
110
111 return S;
112 }
113 /*}}}*/
114 // SourcesIndex::Info - One liner describing the index URI /*{{{*/
115 // ---------------------------------------------------------------------
116 /* */
117 string debSourcesIndex::Info(const char *Type) const
118 {
119 string Info = ::URI::NoUserPassword(URI) + ' ';
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 /* */
135 string debSourcesIndex::IndexFile(const char *Type) const
136 {
137 string s = URItoFileName(IndexURI(Type));
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;
147 }
148
149 string 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 /*}}}*/
167 // SourcesIndex::Exists - Check if the index is available /*{{{*/
168 // ---------------------------------------------------------------------
169 /* */
170 bool debSourcesIndex::Exists() const
171 {
172 return FileExists(IndexFile("Sources"));
173 }
174 /*}}}*/
175 // SourcesIndex::Size - Return the size of the index /*{{{*/
176 // ---------------------------------------------------------------------
177 /* */
178 unsigned long debSourcesIndex::Size() const
179 {
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
185 FileFd f(IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension);
186 if (!f.Failed())
187 size = f.Size();
188
189 if (_error->PendingError() == true)
190 size = 0;
191 _error->RevertToStack();
192
193 return size;
194 }
195 /*}}}*/
196
197 // PackagesIndex::debPackagesIndex - Contructor /*{{{*/
198 // ---------------------------------------------------------------------
199 /* */
200 debPackagesIndex::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)
203 {
204 if (Architecture == "native")
205 Architecture = _config->Find("APT::Architecture");
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 */
211 string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
212 {
213 string Res = ::URI::NoUserPassword(URI) + ' ';
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 += " ";
225 if (Dist[Dist.size() - 1] != '/')
226 Res.append(Ver.Arch()).append(" ");
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 */
235 string debPackagesIndex::Describe(bool Short) const
236 {
237 char S[300];
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());
243 return S;
244 }
245 /*}}}*/
246 // PackagesIndex::Info - One liner describing the index URI /*{{{*/
247 // ---------------------------------------------------------------------
248 /* */
249 string debPackagesIndex::Info(const char *Type) const
250 {
251 string Info = ::URI::NoUserPassword(URI) + ' ';
252 if (Dist[Dist.size() - 1] == '/')
253 {
254 if (Dist != "/")
255 Info += Dist;
256 }
257 else
258 Info += Dist + '/' + Section;
259 Info += " ";
260 if (Dist[Dist.size() - 1] != '/')
261 Info += Architecture + " ";
262 Info += Type;
263 return Info;
264 }
265 /*}}}*/
266 // PackagesIndex::Index* - Return the URI to the index files /*{{{*/
267 // ---------------------------------------------------------------------
268 /* */
269 string debPackagesIndex::IndexFile(const char *Type) const
270 {
271 string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
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;
281 }
282 string 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 +
294 "/binary-" + Architecture + '/';
295
296 Res += Type;
297 return Res;
298 }
299 /*}}}*/
300 // PackagesIndex::Exists - Check if the index is available /*{{{*/
301 // ---------------------------------------------------------------------
302 /* */
303 bool 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. */
311 unsigned long debPackagesIndex::Size() const
312 {
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
318 FileFd f(IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension);
319 if (!f.Failed())
320 size = f.Size();
321
322 if (_error->PendingError() == true)
323 size = 0;
324 _error->RevertToStack();
325
326 return size;
327 }
328 /*}}}*/
329 // PackagesIndex::Merge - Load the index file into a cache /*{{{*/
330 // ---------------------------------------------------------------------
331 /* */
332 bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
333 {
334 string PackageFile = IndexFile("Packages");
335 FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
336 debListParser Parser(&Pkg, Architecture);
337
338 if (_error->PendingError() == true)
339 return _error->Error("Problem opening %s",PackageFile.c_str());
340 if (Prog != NULL)
341 Prog->SubProgress(0,Info("Packages"));
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();
348 pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
349 File->Size = Pkg.FileSize();
350 File->mtime = Pkg.ModificationTime();
351
352 if (Gen.MergeList(Parser) == false)
353 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
354
355 // Check the release file
356 string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
357 bool releaseExists = false;
358 if (FileExists(ReleaseFile) == true)
359 releaseExists = true;
360 else
361 ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
362
363 if (releaseExists == true || FileExists(ReleaseFile) == true)
364 {
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
371 if (_error->PendingError() == true)
372 return false;
373 Parser.LoadReleaseInfo(File,Rel,Section);
374 }
375
376 return true;
377 }
378 /*}}}*/
379 // PackagesIndex::FindInCache - Find this index /*{{{*/
380 // ---------------------------------------------------------------------
381 /* */
382 pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
383 {
384 string FileName = IndexFile("Packages");
385 pkgCache::PkgFileIterator File = Cache.FileBegin();
386 for (; File.end() == false; ++File)
387 {
388 if (File.FileName() == NULL || FileName != File.FileName())
389 continue;
390
391 struct stat St;
392 if (stat(File.FileName(),&St) != 0)
393 {
394 if (_config->FindB("Debug::pkgCacheGen", false))
395 std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
396 return pkgCache::PkgFileIterator(Cache);
397 }
398 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
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;
404 return pkgCache::PkgFileIterator(Cache);
405 }
406 return File;
407 }
408
409 return File;
410 }
411 /*}}}*/
412
413 // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
414 // ---------------------------------------------------------------------
415 /* */
416 debTranslationsIndex::debTranslationsIndex(std::string const &URI, std::string const &Dist,
417 std::string const &Section, std::string const &Translation) :
418 pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section),
419 Language(Translation)
420 {}
421 /*}}}*/
422 // TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
423 // ---------------------------------------------------------------------
424 /* */
425 string debTranslationsIndex::IndexFile(const char *Type) const
426 {
427 string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
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;
437 }
438 string debTranslationsIndex::IndexURI(const char *Type) const
439 {
440 string Res;
441 if (Dist[Dist.size() - 1] == '/')
442 {
443 if (Dist != "/")
444 Res = URI + Dist;
445 else
446 Res = URI;
447 }
448 else
449 Res = URI + "dists/" + Dist + '/' + Section +
450 "/i18n/Translation-";
451
452 Res += Type;
453 return Res;
454 }
455 /*}}}*/
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 */
460 string debTranslationsIndex::Describe(bool Short) const
461 {
462 std::string S;
463 if (Short == true)
464 strprintf(S,"%s",Info(TranslationFile().c_str()).c_str());
465 else
466 strprintf(S,"%s (%s)",Info(TranslationFile().c_str()).c_str(),
467 IndexFile(Language.c_str()).c_str());
468 return S;
469 }
470 /*}}}*/
471 // TranslationsIndex::Info - One liner describing the index URI /*{{{*/
472 // ---------------------------------------------------------------------
473 /* */
474 string debTranslationsIndex::Info(const char *Type) const
475 {
476 string Info = ::URI::NoUserPassword(URI) + ' ';
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 /*}}}*/
489 bool debTranslationsIndex::HasPackages() const /*{{{*/
490 {
491 return FileExists(IndexFile(Language.c_str()));
492 }
493 /*}}}*/
494 // TranslationsIndex::Exists - Check if the index is available /*{{{*/
495 // ---------------------------------------------------------------------
496 /* */
497 bool debTranslationsIndex::Exists() const
498 {
499 return FileExists(IndexFile(Language.c_str()));
500 }
501 /*}}}*/
502 // TranslationsIndex::Size - Return the size of the index /*{{{*/
503 // ---------------------------------------------------------------------
504 /* This is really only used for progress reporting. */
505 unsigned long debTranslationsIndex::Size() const
506 {
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
512 FileFd f(IndexFile(Language.c_str()), FileFd::ReadOnly, FileFd::Extension);
513 if (!f.Failed())
514 size = f.Size();
515
516 if (_error->PendingError() == true)
517 size = 0;
518 _error->RevertToStack();
519
520 return size;
521 }
522 /*}}}*/
523 // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
524 // ---------------------------------------------------------------------
525 /* */
526 bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
527 {
528 // Check the translation file, if in use
529 string TranslationFile = IndexFile(Language.c_str());
530 if (FileExists(TranslationFile))
531 {
532 FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
533 debTranslationsParser TransParser(&Trans);
534 if (_error->PendingError() == true)
535 return false;
536
537 if (Prog != NULL)
538 Prog->SubProgress(0, Info(TranslationFile.c_str()));
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();
544 TransFile->Size = Trans.FileSize();
545 TransFile->mtime = Trans.ModificationTime();
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 /*}}}*/
554 // TranslationsIndex::FindInCache - Find this index /*{{{*/
555 // ---------------------------------------------------------------------
556 /* */
557 pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
558 {
559 string FileName = IndexFile(Language.c_str());
560
561 pkgCache::PkgFileIterator File = Cache.FileBegin();
562 for (; File.end() == false; ++File)
563 {
564 if (FileName != File.FileName())
565 continue;
566
567 struct stat St;
568 if (stat(File.FileName(),&St) != 0)
569 {
570 if (_config->FindB("Debug::pkgCacheGen", false))
571 std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
572 return pkgCache::PkgFileIterator(Cache);
573 }
574 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
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;
580 return pkgCache::PkgFileIterator(Cache);
581 }
582 return File;
583 }
584 return File;
585 }
586 /*}}}*/
587 // StatusIndex::debStatusIndex - Constructor /*{{{*/
588 // ---------------------------------------------------------------------
589 /* */
590 debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
591 {
592 }
593 /*}}}*/
594 // StatusIndex::Size - Return the size of the index /*{{{*/
595 // ---------------------------------------------------------------------
596 /* */
597 unsigned 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 /* */
608 bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
609 {
610 FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
611 if (_error->PendingError() == true)
612 return false;
613 debListParser Parser(&Pkg);
614 if (_error->PendingError() == true)
615 return false;
616
617 if (Prog != NULL)
618 Prog->SubProgress(0,File);
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();
624 CFile->Size = Pkg.FileSize();
625 CFile->mtime = Pkg.ModificationTime();
626 map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now");
627 CFile->Archive = storage;
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 /* */
637 pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
638 {
639 pkgCache::PkgFileIterator File = Cache.FileBegin();
640 for (; File.end() == false; ++File)
641 {
642 if (this->File != File.FileName())
643 continue;
644
645 struct stat St;
646 if (stat(File.FileName(),&St) != 0)
647 {
648 if (_config->FindB("Debug::pkgCacheGen", false))
649 std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
650 return pkgCache::PkgFileIterator(Cache);
651 }
652 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
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;
658 return pkgCache::PkgFileIterator(Cache);
659 }
660 return File;
661 }
662 return File;
663 }
664 /*}}}*/
665 // StatusIndex::Exists - Check if the index is available /*{{{*/
666 // ---------------------------------------------------------------------
667 /* */
668 APT_CONST bool debStatusIndex::Exists() const
669 {
670 // Abort if the file does not exist.
671 return true;
672 }
673 /*}}}*/
674
675 // debDebPkgFile - Single .deb file /*{{{*/
676 debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
677 : pkgIndexFile(true), DebFile(DebFile)
678 {
679 DebFileFullPath = flAbsPath(DebFile);
680 }
681
682 std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
683 {
684 return "file:" + DebFileFullPath;
685 }
686
687 bool debDebPkgFileIndex::Exists() const
688 {
689 return FileExists(DebFile);
690 }
691 bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
692 {
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");
695 std::vector<const char *> Args;
696 Args.push_back(dpkg.c_str());
697 Args.push_back("-I");
698 Args.push_back(debfile.c_str());
699 Args.push_back("control");
700 Args.push_back(NULL);
701 FileFd PipeFd;
702 pid_t Child;
703 if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
704 return _error->Error("Popen failed");
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);
716 ExecWait(Child, "Popen");
717
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 }
726 bool 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
732 SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
733 if(DebControl == NULL)
734 return false;
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
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 }
757 pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
758 {
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 }
770 unsigned 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
779 // debDscFileIndex stuff
780 debDscFileIndex::debDscFileIndex(std::string &DscFile)
781 : pkgIndexFile(true), DscFile(DscFile)
782 {
783 }
784
785 bool debDscFileIndex::Exists() const
786 {
787 return FileExists(DscFile);
788 }
789
790 unsigned 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 /*{{{*/
799 pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
800 {
801 if (!FileExists(DscFile))
802 return NULL;
803
804 return new debDscRecordParser(DscFile,this);
805 }
806 /*}}}*/
807 // Index File types for Debian /*{{{*/
808 class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
809 {
810 public:
811
812 debIFTypeSrc() {Label = "Debian Source Index";};
813 };
814 class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
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 };
824 class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
825 {
826 public:
827 debIFTypeTrans() {Label = "Debian Translation Index";};
828 };
829 class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
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 };
839 class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
840 {
841 public:
842 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
843 {
844 return new debDebFileRecordParser(File.FileName());
845 };
846 debIFTypeDebPkgFile() {Label = "deb Package file";};
847 };
848 class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
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 };
857 class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
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 };
866
867 APT_HIDDEN debIFTypeSrc _apt_Src;
868 APT_HIDDEN debIFTypePkg _apt_Pkg;
869 APT_HIDDEN debIFTypeTrans _apt_Trans;
870 APT_HIDDEN debIFTypeStatus _apt_Status;
871 APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
872 // file based pseudo indexes
873 APT_HIDDEN debIFTypeDscFile _apt_DscFile;
874 APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
875
876 const pkgIndexFile::Type *debSourcesIndex::GetType() const
877 {
878 return &_apt_Src;
879 }
880 const pkgIndexFile::Type *debPackagesIndex::GetType() const
881 {
882 return &_apt_Pkg;
883 }
884 const pkgIndexFile::Type *debTranslationsIndex::GetType() const
885 {
886 return &_apt_Trans;
887 }
888 const pkgIndexFile::Type *debStatusIndex::GetType() const
889 {
890 return &_apt_Status;
891 }
892 const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
893 {
894 return &_apt_DebPkgFile;
895 }
896 const pkgIndexFile::Type *debDscFileIndex::GetType() const
897 {
898 return &_apt_DscFile;
899 }
900 const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
901 {
902 return &_apt_DebianSourceDir;
903 }
904 /*}}}*/
905
906 debStatusIndex::~debStatusIndex() {}
907 debPackagesIndex::~debPackagesIndex() {}
908 debTranslationsIndex::~debTranslationsIndex() {}
909 debSourcesIndex::~debSourcesIndex() {}
910
911 debDebPkgFileIndex::~debDebPkgFileIndex() {}