]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debindexfile.cc
WIP local deb install
[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 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 /* */
97 string 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 /* */
112 string 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 /* */
130 inline 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
140 string 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 /* */
161 bool debSourcesIndex::Exists() const
162 {
163 return FileExists(IndexFile("Sources"));
164 }
165 /*}}}*/
166 // SourcesIndex::Size - Return the size of the index /*{{{*/
167 // ---------------------------------------------------------------------
168 /* */
169 unsigned 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 /* */
191 debPackagesIndex::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 */
202 string 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 */
226 string 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 /* */
240 string 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 /* */
260 inline 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 }
269 string 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 /* */
290 bool 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. */
298 unsigned 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 /* */
319 bool 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 /* */
369 pkgCache::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 /* */
403 debTranslationsIndex::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 /* */
412 inline 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 }
421 string 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 /* */
442 bool 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 */
456 string 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 /* */
470 string 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 /*}}}*/
485 bool debTranslationsIndex::HasPackages() const /*{{{*/
486 {
487 return FileExists(IndexFile(Language));
488 }
489 /*}}}*/
490 // TranslationsIndex::Exists - Check if the index is available /*{{{*/
491 // ---------------------------------------------------------------------
492 /* */
493 bool 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. */
501 unsigned 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 /* */
522 bool 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 debListParser 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 /* */
553 pkgCache::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 /* */
586 debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
587 {
588 }
589 /*}}}*/
590 // StatusIndex::Size - Return the size of the index /*{{{*/
591 // ---------------------------------------------------------------------
592 /* */
593 unsigned 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 /* */
604 bool 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_ptrloc 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 /* */
633 pkgCache::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 /* */
664 APT_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 // ---------------------------------------------------------------------
673 debDebPkgFileIndex::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
680 std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
681 {
682 return "file:" + DebFileFullPath;
683 }
684
685 bool debDebPkgFileIndex::Exists() const
686 {
687 return FileExists(DebFile);
688 }
689 bool 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 }
736 pkgCache::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 }
751 unsigned 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
760 // Index File types for Debian /*{{{*/
761 class debIFTypeSrc : public pkgIndexFile::Type
762 {
763 public:
764
765 debIFTypeSrc() {Label = "Debian Source Index";};
766 };
767 class 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 };
777 class debIFTypeTrans : public debIFTypePkg
778 {
779 public:
780 debIFTypeTrans() {Label = "Debian Translation Index";};
781 };
782 class 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 };
792 class 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 };
801 static debIFTypeSrc _apt_Src;
802 static debIFTypePkg _apt_Pkg;
803 static debIFTypeTrans _apt_Trans;
804 static debIFTypeStatus _apt_Status;
805 static debIFTypeDebPkgFile _apt_DebPkgFile;
806
807 const pkgIndexFile::Type *debSourcesIndex::GetType() const
808 {
809 return &_apt_Src;
810 }
811 const pkgIndexFile::Type *debPackagesIndex::GetType() const
812 {
813 return &_apt_Pkg;
814 }
815 const pkgIndexFile::Type *debTranslationsIndex::GetType() const
816 {
817 return &_apt_Trans;
818 }
819 const pkgIndexFile::Type *debStatusIndex::GetType() const
820 {
821 return &_apt_Status;
822 }
823 const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
824 {
825 return &_apt_DebPkgFile;
826 }
827 /*}}}*/