]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debindexfile.cc
use IndexTarget to get to IndexFile
[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(IndexTarget const &Target,bool const Trusted) :
48 pkgIndexTargetFile(Target, Trusted)
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 = Target.Description;
60 Res.erase(Target.Description.rfind(' '));
61
62 Res += " ";
63 Res += Record.Package();
64 Res += " ";
65 Res += Record.Version();
66 if (File.Type.empty() == false)
67 Res += " (" + File.Type + ")";
68 return Res;
69 }
70 /*}}}*/
71 // SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/
72 // ---------------------------------------------------------------------
73 /* */
74 pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
75 {
76 string const SourcesURI = IndexFileName();
77 if (FileExists(SourcesURI))
78 return new debSrcRecordParser(SourcesURI, this);
79 return NULL;
80 }
81 /*}}}*/
82
83 // PackagesIndex::debPackagesIndex - Contructor /*{{{*/
84 // ---------------------------------------------------------------------
85 /* */
86 debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) :
87 pkgIndexTargetFile(Target, Trusted)
88 {
89 }
90 /*}}}*/
91 // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/
92 // ---------------------------------------------------------------------
93 /* This is a shorter version that is designed to be < 60 chars or so */
94 string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
95 {
96 std::string const Dist = Target.Option("RELEASE");
97 string Res = Target.Option("SITE") + " " + Dist;
98 std::string const Component = Target.Option("COMPONENT");
99 if (Component.empty() == false)
100 Res += "/" + Component;
101
102 Res += " ";
103 Res += Ver.ParentPkg().Name();
104 Res += " ";
105 if (Dist.empty() == false && Dist[Dist.size() - 1] != '/')
106 Res.append(Ver.Arch()).append(" ");
107 Res += Ver.VerStr();
108 return Res;
109 }
110 /*}}}*/
111 // PackagesIndex::Merge - Load the index file into a cache /*{{{*/
112 // ---------------------------------------------------------------------
113 /* */
114 bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
115 {
116 string const PackageFile = IndexFileName();
117 FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
118 debListParser Parser(&Pkg, Target.Option("ARCHITECTURE"));
119
120 if (_error->PendingError() == true)
121 return _error->Error("Problem opening %s",PackageFile.c_str());
122 if (Prog != NULL)
123 Prog->SubProgress(0, Target.Description);
124
125
126 std::string const URI = Target.Option("REPO_URI");
127 std::string Dist = Target.Option("RELEASE");
128 if (Dist.empty())
129 Dist = "/";
130 ::URI Tmp(URI);
131 if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
132 return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
133
134 // Store the IMS information
135 pkgCache::PkgFileIterator File = Gen.GetCurFile();
136 pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
137 File->Size = Pkg.FileSize();
138 File->mtime = Pkg.ModificationTime();
139
140 if (Gen.MergeList(Parser) == false)
141 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
142
143 // Check the release file
144 string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
145 bool releaseExists = false;
146 if (FileExists(ReleaseFile) == true)
147 releaseExists = true;
148 else
149 ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
150
151 if (releaseExists == true || FileExists(ReleaseFile) == true)
152 {
153 FileFd Rel;
154 // Beware: The 'Release' file might be clearsigned in case the
155 // signature for an 'InRelease' file couldn't be checked
156 if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
157 return false;
158
159 if (_error->PendingError() == true)
160 return false;
161 Parser.LoadReleaseInfo(File, Rel, Target.Option("COMPONENT"));
162 }
163
164 return true;
165 }
166 /*}}}*/
167 // PackagesIndex::FindInCache - Find this index /*{{{*/
168 // ---------------------------------------------------------------------
169 /* */
170 pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
171 {
172 string const FileName = IndexFileName();
173 pkgCache::PkgFileIterator File = Cache.FileBegin();
174 for (; File.end() == false; ++File)
175 {
176 if (File.FileName() == NULL || FileName != File.FileName())
177 continue;
178
179 struct stat St;
180 if (stat(File.FileName(),&St) != 0)
181 {
182 if (_config->FindB("Debug::pkgCacheGen", false))
183 std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
184 return pkgCache::PkgFileIterator(Cache);
185 }
186 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
187 {
188 if (_config->FindB("Debug::pkgCacheGen", false))
189 std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
190 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
191 << ") doesn't match for " << File.FileName() << std::endl;
192 return pkgCache::PkgFileIterator(Cache);
193 }
194 return File;
195 }
196
197 return File;
198 }
199 /*}}}*/
200
201 // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
202 debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) :
203 pkgIndexTargetFile(Target, true)
204 {}
205 /*}}}*/
206 bool debTranslationsIndex::HasPackages() const /*{{{*/
207 {
208 return Exists();
209 }
210 /*}}}*/
211 // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
212 // ---------------------------------------------------------------------
213 /* */
214 bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
215 {
216 // Check the translation file, if in use
217 string const TranslationFile = IndexFileName();
218 if (FileExists(TranslationFile))
219 {
220 FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
221 debTranslationsParser TransParser(&Trans);
222 if (_error->PendingError() == true)
223 return false;
224
225 if (Prog != NULL)
226 Prog->SubProgress(0, Target.Description);
227 if (Gen.SelectFile(TranslationFile,string(),*this) == false)
228 return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
229
230 // Store the IMS information
231 pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
232 TransFile->Size = Trans.FileSize();
233 TransFile->mtime = Trans.ModificationTime();
234
235 if (Gen.MergeList(TransParser) == false)
236 return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
237 }
238
239 return true;
240 }
241 /*}}}*/
242 // TranslationsIndex::FindInCache - Find this index /*{{{*/
243 // ---------------------------------------------------------------------
244 /* */
245 pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
246 {
247 string FileName = IndexFileName();
248
249 pkgCache::PkgFileIterator File = Cache.FileBegin();
250 for (; File.end() == false; ++File)
251 {
252 if (FileName != File.FileName())
253 continue;
254
255 struct stat St;
256 if (stat(File.FileName(),&St) != 0)
257 {
258 if (_config->FindB("Debug::pkgCacheGen", false))
259 std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
260 return pkgCache::PkgFileIterator(Cache);
261 }
262 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
263 {
264 if (_config->FindB("Debug::pkgCacheGen", false))
265 std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
266 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
267 << ") doesn't match for " << File.FileName() << std::endl;
268 return pkgCache::PkgFileIterator(Cache);
269 }
270 return File;
271 }
272 return File;
273 }
274 /*}}}*/
275
276 // StatusIndex::debStatusIndex - Constructor /*{{{*/
277 // ---------------------------------------------------------------------
278 /* */
279 debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
280 {
281 }
282 /*}}}*/
283 // StatusIndex::Size - Return the size of the index /*{{{*/
284 // ---------------------------------------------------------------------
285 /* */
286 unsigned long debStatusIndex::Size() const
287 {
288 struct stat S;
289 if (stat(File.c_str(),&S) != 0)
290 return 0;
291 return S.st_size;
292 }
293 /*}}}*/
294 // StatusIndex::Merge - Load the index file into a cache /*{{{*/
295 // ---------------------------------------------------------------------
296 /* */
297 bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
298 {
299 FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
300 if (_error->PendingError() == true)
301 return false;
302 debListParser Parser(&Pkg);
303 if (_error->PendingError() == true)
304 return false;
305
306 if (Prog != NULL)
307 Prog->SubProgress(0,File);
308 if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
309 return _error->Error("Problem with SelectFile %s",File.c_str());
310
311 // Store the IMS information
312 pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
313 CFile->Size = Pkg.FileSize();
314 CFile->mtime = Pkg.ModificationTime();
315 map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now");
316 CFile->Archive = storage;
317
318 if (Gen.MergeList(Parser) == false)
319 return _error->Error("Problem with MergeList %s",File.c_str());
320 return true;
321 }
322 /*}}}*/
323 // StatusIndex::FindInCache - Find this index /*{{{*/
324 // ---------------------------------------------------------------------
325 /* */
326 pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
327 {
328 pkgCache::PkgFileIterator File = Cache.FileBegin();
329 for (; File.end() == false; ++File)
330 {
331 if (this->File != File.FileName())
332 continue;
333
334 struct stat St;
335 if (stat(File.FileName(),&St) != 0)
336 {
337 if (_config->FindB("Debug::pkgCacheGen", false))
338 std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
339 return pkgCache::PkgFileIterator(Cache);
340 }
341 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
342 {
343 if (_config->FindB("Debug::pkgCacheGen", false))
344 std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
345 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
346 << ") doesn't match for " << File.FileName() << std::endl;
347 return pkgCache::PkgFileIterator(Cache);
348 }
349 return File;
350 }
351 return File;
352 }
353 /*}}}*/
354 // StatusIndex::Exists - Check if the index is available /*{{{*/
355 // ---------------------------------------------------------------------
356 /* */
357 APT_CONST bool debStatusIndex::Exists() const
358 {
359 // Abort if the file does not exist.
360 return true;
361 }
362 /*}}}*/
363
364 // debDebPkgFile - Single .deb file /*{{{*/
365 debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
366 : pkgIndexFile(true), DebFile(DebFile)
367 {
368 DebFileFullPath = flAbsPath(DebFile);
369 }
370
371 std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
372 {
373 return "file:" + DebFileFullPath;
374 }
375
376 bool debDebPkgFileIndex::Exists() const
377 {
378 return FileExists(DebFile);
379 }
380 bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
381 {
382 // get the control data out of the deb file via dpkg-deb -I
383 std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb");
384 std::vector<const char *> Args;
385 Args.push_back(dpkg.c_str());
386 Args.push_back("-I");
387 Args.push_back(debfile.c_str());
388 Args.push_back("control");
389 Args.push_back(NULL);
390 FileFd PipeFd;
391 pid_t Child;
392 if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
393 return _error->Error("Popen failed");
394
395 char buffer[1024];
396 do {
397 unsigned long long actual = 0;
398 if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false)
399 return _error->Errno("read", "Failed to read dpkg pipe");
400 if (actual == 0)
401 break;
402 buffer[actual] = '\0';
403 content << buffer;
404 } while(true);
405 ExecWait(Child, "Popen");
406
407 content << "Filename: " << debfile << "\n";
408 struct stat Buf;
409 if (stat(debfile.c_str(), &Buf) != 0)
410 return false;
411 content << "Size: " << Buf.st_size << "\n";
412
413 return true;
414 }
415 bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
416 {
417 if(Prog)
418 Prog->SubProgress(0, "Reading deb file");
419
420 // write the control data to a tempfile
421 SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
422 if(DebControl == NULL)
423 return false;
424 std::ostringstream content;
425 if (GetContent(content, DebFile) == false)
426 return false;
427 std::string const contentstr = content.str();
428 DebControl->Write(contentstr.c_str(), contentstr.length());
429 // rewind for the listparser
430 DebControl->Seek(0);
431
432 // and give it to the list parser
433 debDebFileParser Parser(DebControl, DebFile);
434 if(Gen.SelectFile(DebFile, "local", *this, pkgCache::Flag::LocalSource) == false)
435 return _error->Error("Problem with SelectFile %s", DebFile.c_str());
436
437 pkgCache::PkgFileIterator File = Gen.GetCurFile();
438 File->Size = DebControl->Size();
439 File->mtime = DebControl->ModificationTime();
440
441 if (Gen.MergeList(Parser) == false)
442 return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
443
444 return true;
445 }
446 pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
447 {
448 pkgCache::PkgFileIterator File = Cache.FileBegin();
449 for (; File.end() == false; ++File)
450 {
451 if (File.FileName() == NULL || DebFile != File.FileName())
452 continue;
453
454 return File;
455 }
456
457 return File;
458 }
459 unsigned long debDebPkgFileIndex::Size() const
460 {
461 struct stat buf;
462 if(stat(DebFile.c_str(), &buf) != 0)
463 return 0;
464 return buf.st_size;
465 }
466 /*}}}*/
467
468 // debDscFileIndex stuff
469 debDscFileIndex::debDscFileIndex(std::string &DscFile)
470 : pkgIndexFile(true), DscFile(DscFile)
471 {
472 }
473
474 bool debDscFileIndex::Exists() const
475 {
476 return FileExists(DscFile);
477 }
478
479 unsigned long debDscFileIndex::Size() const
480 {
481 struct stat buf;
482 if(stat(DscFile.c_str(), &buf) == 0)
483 return buf.st_size;
484 return 0;
485 }
486
487 // DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/
488 pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
489 {
490 if (!FileExists(DscFile))
491 return NULL;
492
493 return new debDscRecordParser(DscFile,this);
494 }
495 /*}}}*/
496 // Index File types for Debian /*{{{*/
497 class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
498 {
499 public:
500
501 debIFTypeSrc() {Label = "Debian Source Index";};
502 };
503 class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
504 {
505 public:
506
507 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
508 {
509 return new debRecordParser(File.FileName(),*File.Cache());
510 };
511 debIFTypePkg() {Label = "Debian Package Index";};
512 };
513 class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
514 {
515 public:
516 debIFTypeTrans() {Label = "Debian Translation Index";};
517 };
518 class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
519 {
520 public:
521
522 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
523 {
524 return new debRecordParser(File.FileName(),*File.Cache());
525 };
526 debIFTypeStatus() {Label = "Debian dpkg status file";};
527 };
528 class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
529 {
530 public:
531 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
532 {
533 return new debDebFileRecordParser(File.FileName());
534 };
535 debIFTypeDebPkgFile() {Label = "deb Package file";};
536 };
537 class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
538 {
539 public:
540 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
541 {
542 return new debDscRecordParser(DscFile, NULL);
543 };
544 debIFTypeDscFile() {Label = "dsc File Source Index";};
545 };
546 class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
547 {
548 public:
549 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
550 {
551 return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
552 };
553 debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
554 };
555
556 APT_HIDDEN debIFTypeSrc _apt_Src;
557 APT_HIDDEN debIFTypePkg _apt_Pkg;
558 APT_HIDDEN debIFTypeTrans _apt_Trans;
559 APT_HIDDEN debIFTypeStatus _apt_Status;
560 APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
561 // file based pseudo indexes
562 APT_HIDDEN debIFTypeDscFile _apt_DscFile;
563 APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
564
565 const pkgIndexFile::Type *debSourcesIndex::GetType() const
566 {
567 return &_apt_Src;
568 }
569 const pkgIndexFile::Type *debPackagesIndex::GetType() const
570 {
571 return &_apt_Pkg;
572 }
573 const pkgIndexFile::Type *debTranslationsIndex::GetType() const
574 {
575 return &_apt_Trans;
576 }
577 const pkgIndexFile::Type *debStatusIndex::GetType() const
578 {
579 return &_apt_Status;
580 }
581 const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
582 {
583 return &_apt_DebPkgFile;
584 }
585 const pkgIndexFile::Type *debDscFileIndex::GetType() const
586 {
587 return &_apt_DscFile;
588 }
589 const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
590 {
591 return &_apt_DebianSourceDir;
592 }
593 /*}}}*/
594
595 debStatusIndex::~debStatusIndex() {}
596 debPackagesIndex::~debPackagesIndex() {}
597 debTranslationsIndex::~debTranslationsIndex() {}
598 debSourcesIndex::~debSourcesIndex() {}
599
600 debDebPkgFileIndex::~debDebPkgFileIndex() {}