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