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