]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debindexfile.cc
944cbe0bf20deab08093ede58fc08c9604eb5076
[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(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)
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), 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 // debDebPkgFile - Single .deb file /*{{{*/
343 debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
344 : pkgIndexFile(true), DebFile(DebFile)
345 {
346 DebFileFullPath = flAbsPath(DebFile);
347 }
348
349 std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
350 {
351 return "file:" + DebFileFullPath;
352 }
353
354 bool debDebPkgFileIndex::Exists() const
355 {
356 return FileExists(DebFile);
357 }
358 bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
359 {
360 // get the control data out of the deb file via dpkg-deb -I
361 std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb");
362 std::vector<const char *> Args;
363 Args.push_back(dpkg.c_str());
364 Args.push_back("-I");
365 Args.push_back(debfile.c_str());
366 Args.push_back("control");
367 Args.push_back(NULL);
368 FileFd PipeFd;
369 pid_t Child;
370 if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
371 return _error->Error("Popen failed");
372
373 char buffer[1024];
374 do {
375 unsigned long long actual = 0;
376 if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false)
377 return _error->Errno("read", "Failed to read dpkg pipe");
378 if (actual == 0)
379 break;
380 buffer[actual] = '\0';
381 content << buffer;
382 } while(true);
383 ExecWait(Child, "Popen");
384
385 content << "Filename: " << debfile << "\n";
386 struct stat Buf;
387 if (stat(debfile.c_str(), &Buf) != 0)
388 return false;
389 content << "Size: " << Buf.st_size << "\n";
390
391 return true;
392 }
393 bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
394 {
395 if(Prog)
396 Prog->SubProgress(0, "Reading deb file");
397
398 // write the control data to a tempfile
399 SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
400 if(DebControl == NULL)
401 return false;
402 std::ostringstream content;
403 if (GetContent(content, DebFile) == false)
404 return false;
405 std::string const contentstr = content.str();
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 stuff
447 debDscFileIndex::debDscFileIndex(std::string &DscFile)
448 : pkgIndexFile(true), DscFile(DscFile)
449 {
450 }
451
452 bool debDscFileIndex::Exists() const
453 {
454 return FileExists(DscFile);
455 }
456
457 unsigned long debDscFileIndex::Size() const
458 {
459 struct stat buf;
460 if(stat(DscFile.c_str(), &buf) == 0)
461 return buf.st_size;
462 return 0;
463 }
464
465 // DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/
466 pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
467 {
468 if (!FileExists(DscFile))
469 return NULL;
470
471 return new debDscRecordParser(DscFile,this);
472 }
473 /*}}}*/
474 // Index File types for Debian /*{{{*/
475 class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
476 {
477 public:
478
479 debIFTypeSrc() {Label = "Debian Source Index";};
480 };
481 class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
482 {
483 public:
484
485 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
486 {
487 return new debRecordParser(File.FileName(),*File.Cache());
488 };
489 debIFTypePkg() {Label = "Debian Package Index";};
490 };
491 class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
492 {
493 public:
494 debIFTypeTrans() {Label = "Debian Translation Index";};
495 };
496 class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
497 {
498 public:
499
500 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
501 {
502 return new debRecordParser(File.FileName(),*File.Cache());
503 };
504 debIFTypeStatus() {Label = "Debian dpkg status file";};
505 };
506 class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
507 {
508 public:
509 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
510 {
511 return new debDebFileRecordParser(File.FileName());
512 };
513 debIFTypeDebPkgFile() {Label = "deb Package file";};
514 };
515 class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
516 {
517 public:
518 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
519 {
520 return new debDscRecordParser(DscFile, NULL);
521 };
522 debIFTypeDscFile() {Label = "dsc File Source Index";};
523 };
524 class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
525 {
526 public:
527 virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
528 {
529 return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
530 };
531 debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
532 };
533
534 APT_HIDDEN debIFTypeSrc _apt_Src;
535 APT_HIDDEN debIFTypePkg _apt_Pkg;
536 APT_HIDDEN debIFTypeTrans _apt_Trans;
537 APT_HIDDEN debIFTypeStatus _apt_Status;
538 APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
539 // file based pseudo indexes
540 APT_HIDDEN debIFTypeDscFile _apt_DscFile;
541 APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
542
543 const pkgIndexFile::Type *debSourcesIndex::GetType() const
544 {
545 return &_apt_Src;
546 }
547 const pkgIndexFile::Type *debPackagesIndex::GetType() const
548 {
549 return &_apt_Pkg;
550 }
551 const pkgIndexFile::Type *debTranslationsIndex::GetType() const
552 {
553 return &_apt_Trans;
554 }
555 const pkgIndexFile::Type *debStatusIndex::GetType() const
556 {
557 return &_apt_Status;
558 }
559 const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
560 {
561 return &_apt_DebPkgFile;
562 }
563 const pkgIndexFile::Type *debDscFileIndex::GetType() const
564 {
565 return &_apt_DscFile;
566 }
567 const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
568 {
569 return &_apt_DebianSourceDir;
570 }
571 /*}}}*/
572
573 debStatusIndex::~debStatusIndex() {}
574 debPackagesIndex::~debPackagesIndex() {}
575 debTranslationsIndex::~debTranslationsIndex() {}
576 debSourcesIndex::~debSourcesIndex() {}
577
578 debDebPkgFileIndex::~debDebPkgFileIndex() {}