1 // -*- mode: cpp; mode: fold -*-
3 // $Id: debindexfile.cc,v 1.5.2.3 2004/01/04 19:11:00 mdz Exp $
4 /* ######################################################################
6 Debian Specific sources.list types and the three sorts of Debian
9 ##################################################################### */
11 // Include Files /*{{{*/
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/sourcelist.h>
19 #include <apt-pkg/configuration.h>
20 #include <apt-pkg/progress.h>
21 #include <apt-pkg/error.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/acquire-item.h>
24 #include <apt-pkg/debmetaindex.h>
25 #include <apt-pkg/gpgv.h>
32 // SourcesIndex::debSourcesIndex - Constructor /*{{{*/
33 // ---------------------------------------------------------------------
35 debSourcesIndex::debSourcesIndex(string URI
,string Dist
,string Section
,bool Trusted
) :
36 pkgIndexFile(Trusted
), URI(URI
), Dist(Dist
), Section(Section
)
40 // SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
41 // ---------------------------------------------------------------------
42 /* The result looks like:
43 http://foo/debian/ stable/main src 1.1.1 (dsc) */
44 string
debSourcesIndex::SourceInfo(pkgSrcRecords::Parser
const &Record
,
45 pkgSrcRecords::File
const &File
) const
48 Res
= ::URI::NoUserPassword(URI
) + ' ';
49 if (Dist
[Dist
.size() - 1] == '/')
55 Res
+= Dist
+ '/' + Section
;
58 Res
+= Record
.Package();
60 Res
+= Record
.Version();
61 if (File
.Type
.empty() == false)
62 Res
+= " (" + File
.Type
+ ")";
66 // SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/
67 // ---------------------------------------------------------------------
69 pkgSrcRecords::Parser
*debSourcesIndex::CreateSrcParser() const
71 string SourcesURI
= _config
->FindDir("Dir::State::lists") +
72 URItoFileName(IndexURI("Sources"));
73 string SourcesURIgzip
= SourcesURI
+ ".gz";
75 if (!FileExists(SourcesURI
) && !FileExists(SourcesURIgzip
))
77 else if (!FileExists(SourcesURI
) && FileExists(SourcesURIgzip
))
78 SourcesURI
= SourcesURIgzip
;
80 return new debSrcRecordParser(SourcesURI
,this);
83 // SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
84 // ---------------------------------------------------------------------
86 string
debSourcesIndex::Describe(bool Short
) const
90 snprintf(S
,sizeof(S
),"%s",Info("Sources").c_str());
92 snprintf(S
,sizeof(S
),"%s (%s)",Info("Sources").c_str(),
93 IndexFile("Sources").c_str());
98 // SourcesIndex::Info - One liner describing the index URI /*{{{*/
99 // ---------------------------------------------------------------------
101 string
debSourcesIndex::Info(const char *Type
) const
103 string Info
= ::URI::NoUserPassword(URI
) + ' ';
104 if (Dist
[Dist
.size() - 1] == '/')
110 Info
+= Dist
+ '/' + Section
;
116 // SourcesIndex::Index* - Return the URI to the index files /*{{{*/
117 // ---------------------------------------------------------------------
119 inline string
debSourcesIndex::IndexFile(const char *Type
) const
121 string s
= URItoFileName(IndexURI(Type
));
122 string sgzip
= s
+ ".gz";
123 if (!FileExists(s
) && FileExists(sgzip
))
129 string
debSourcesIndex::IndexURI(const char *Type
) const
132 if (Dist
[Dist
.size() - 1] == '/')
140 Res
= URI
+ "dists/" + Dist
+ '/' + Section
+
147 // SourcesIndex::Exists - Check if the index is available /*{{{*/
148 // ---------------------------------------------------------------------
150 bool debSourcesIndex::Exists() const
152 return FileExists(IndexFile("Sources"));
155 // SourcesIndex::Size - Return the size of the index /*{{{*/
156 // ---------------------------------------------------------------------
158 unsigned long debSourcesIndex::Size() const
160 unsigned long size
= 0;
162 /* we need to ignore errors here; if the lists are absent, just return 0 */
163 _error
->PushToStack();
165 FileFd
f(IndexFile("Sources"), FileFd::ReadOnly
, FileFd::Extension
);
169 if (_error
->PendingError() == true)
171 _error
->RevertToStack();
177 // PackagesIndex::debPackagesIndex - Contructor /*{{{*/
178 // ---------------------------------------------------------------------
180 debPackagesIndex::debPackagesIndex(string
const &URI
, string
const &Dist
, string
const &Section
,
181 bool const &Trusted
, string
const &Arch
) :
182 pkgIndexFile(Trusted
), URI(URI
), Dist(Dist
), Section(Section
), Architecture(Arch
)
184 if (Architecture
== "native")
185 Architecture
= _config
->Find("APT::Architecture");
188 // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/
189 // ---------------------------------------------------------------------
190 /* This is a shorter version that is designed to be < 60 chars or so */
191 string
debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver
) const
193 string Res
= ::URI::NoUserPassword(URI
) + ' ';
194 if (Dist
[Dist
.size() - 1] == '/')
200 Res
+= Dist
+ '/' + Section
;
203 Res
+= Ver
.ParentPkg().Name();
205 if (Dist
[Dist
.size() - 1] != '/')
206 Res
.append(Ver
.Arch()).append(" ");
211 // PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/
212 // ---------------------------------------------------------------------
213 /* This should help the user find the index in the sources.list and
214 in the filesystem for problem solving */
215 string
debPackagesIndex::Describe(bool Short
) const
219 snprintf(S
,sizeof(S
),"%s",Info("Packages").c_str());
221 snprintf(S
,sizeof(S
),"%s (%s)",Info("Packages").c_str(),
222 IndexFile("Packages").c_str());
226 // PackagesIndex::Info - One liner describing the index URI /*{{{*/
227 // ---------------------------------------------------------------------
229 string
debPackagesIndex::Info(const char *Type
) const
231 string Info
= ::URI::NoUserPassword(URI
) + ' ';
232 if (Dist
[Dist
.size() - 1] == '/')
238 Info
+= Dist
+ '/' + Section
;
240 if (Dist
[Dist
.size() - 1] != '/')
241 Info
+= Architecture
+ " ";
246 // PackagesIndex::Index* - Return the URI to the index files /*{{{*/
247 // ---------------------------------------------------------------------
249 inline string
debPackagesIndex::IndexFile(const char *Type
) const
251 string s
=_config
->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type
));
252 string sgzip
= s
+ ".gz";
253 if (!FileExists(s
) && FileExists(sgzip
))
258 string
debPackagesIndex::IndexURI(const char *Type
) const
261 if (Dist
[Dist
.size() - 1] == '/')
269 Res
= URI
+ "dists/" + Dist
+ '/' + Section
+
270 "/binary-" + Architecture
+ '/';
276 // PackagesIndex::Exists - Check if the index is available /*{{{*/
277 // ---------------------------------------------------------------------
279 bool debPackagesIndex::Exists() const
281 return FileExists(IndexFile("Packages"));
284 // PackagesIndex::Size - Return the size of the index /*{{{*/
285 // ---------------------------------------------------------------------
286 /* This is really only used for progress reporting. */
287 unsigned long debPackagesIndex::Size() const
289 unsigned long size
= 0;
291 /* we need to ignore errors here; if the lists are absent, just return 0 */
292 _error
->PushToStack();
294 FileFd
f(IndexFile("Packages"), FileFd::ReadOnly
, FileFd::Extension
);
298 if (_error
->PendingError() == true)
300 _error
->RevertToStack();
305 // PackagesIndex::Merge - Load the index file into a cache /*{{{*/
306 // ---------------------------------------------------------------------
308 bool debPackagesIndex::Merge(pkgCacheGenerator
&Gen
,OpProgress
*Prog
) const
310 string PackageFile
= IndexFile("Packages");
311 FileFd
Pkg(PackageFile
,FileFd::ReadOnly
, FileFd::Extension
);
312 debListParser
Parser(&Pkg
, Architecture
);
314 if (_error
->PendingError() == true)
315 return _error
->Error("Problem opening %s",PackageFile
.c_str());
317 Prog
->SubProgress(0,Info("Packages"));
319 if (Gen
.SelectFile(PackageFile
,Tmp
.Host
,*this) == false)
320 return _error
->Error("Problem with SelectFile %s",PackageFile
.c_str());
322 // Store the IMS information
323 pkgCache::PkgFileIterator File
= Gen
.GetCurFile();
324 pkgCacheGenerator::Dynamic
<pkgCache::PkgFileIterator
> DynFile(File
);
325 File
->Size
= Pkg
.FileSize();
326 File
->mtime
= Pkg
.ModificationTime();
328 if (Gen
.MergeList(Parser
) == false)
329 return _error
->Error("Problem with MergeList %s",PackageFile
.c_str());
331 // Check the release file
332 string ReleaseFile
= debReleaseIndex(URI
,Dist
).MetaIndexFile("InRelease");
333 bool releaseExists
= false;
334 if (FileExists(ReleaseFile
) == true)
335 releaseExists
= true;
337 ReleaseFile
= debReleaseIndex(URI
,Dist
).MetaIndexFile("Release");
339 if (releaseExists
== true || FileExists(ReleaseFile
) == true)
342 // Beware: The 'Release' file might be clearsigned in case the
343 // signature for an 'InRelease' file couldn't be checked
344 if (OpenMaybeClearSignedFile(ReleaseFile
, Rel
) == false)
347 if (_error
->PendingError() == true)
349 Parser
.LoadReleaseInfo(File
,Rel
,Section
);
355 // PackagesIndex::FindInCache - Find this index /*{{{*/
356 // ---------------------------------------------------------------------
358 pkgCache::PkgFileIterator
debPackagesIndex::FindInCache(pkgCache
&Cache
) const
360 string FileName
= IndexFile("Packages");
361 pkgCache::PkgFileIterator File
= Cache
.FileBegin();
362 for (; File
.end() == false; ++File
)
364 if (File
.FileName() == NULL
|| FileName
!= File
.FileName())
368 if (stat(File
.FileName(),&St
) != 0)
370 if (_config
->FindB("Debug::pkgCacheGen", false))
371 std::clog
<< "PackagesIndex::FindInCache - stat failed on " << File
.FileName() << std::endl
;
372 return pkgCache::PkgFileIterator(Cache
);
374 if ((unsigned)St
.st_size
!= File
->Size
|| St
.st_mtime
!= File
->mtime
)
376 if (_config
->FindB("Debug::pkgCacheGen", false))
377 std::clog
<< "PackagesIndex::FindInCache - size (" << St
.st_size
<< " <> " << File
->Size
378 << ") or mtime (" << St
.st_mtime
<< " <> " << File
->mtime
379 << ") doesn't match for " << File
.FileName() << std::endl
;
380 return pkgCache::PkgFileIterator(Cache
);
389 // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
390 // ---------------------------------------------------------------------
392 debTranslationsIndex::debTranslationsIndex(string URI
,string Dist
,string Section
,
393 char const * const Translation
) :
394 pkgIndexFile(true), URI(URI
), Dist(Dist
), Section(Section
),
395 Language(Translation
)
398 // TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
399 // ---------------------------------------------------------------------
401 inline string
debTranslationsIndex::IndexFile(const char *Type
) const
403 string s
=_config
->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type
));
404 string sgzip
= s
+ ".gz";
405 if (!FileExists(s
) && FileExists(sgzip
))
410 string
debTranslationsIndex::IndexURI(const char *Type
) const
413 if (Dist
[Dist
.size() - 1] == '/')
421 Res
= URI
+ "dists/" + Dist
+ '/' + Section
+
422 "/i18n/Translation-";
428 // TranslationsIndex::GetIndexes - Fetch the index files /*{{{*/
429 // ---------------------------------------------------------------------
431 bool debTranslationsIndex::GetIndexes(pkgAcquire
*Owner
) const
433 string
const TranslationFile
= string("Translation-").append(Language
);
434 new pkgAcqIndexTrans(Owner
, IndexURI(Language
),
435 Info(TranslationFile
.c_str()),
441 // TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/
442 // ---------------------------------------------------------------------
443 /* This should help the user find the index in the sources.list and
444 in the filesystem for problem solving */
445 string
debTranslationsIndex::Describe(bool Short
) const
449 snprintf(S
,sizeof(S
),"%s",Info(TranslationFile().c_str()).c_str());
451 snprintf(S
,sizeof(S
),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
452 IndexFile(Language
).c_str());
456 // TranslationsIndex::Info - One liner describing the index URI /*{{{*/
457 // ---------------------------------------------------------------------
459 string
debTranslationsIndex::Info(const char *Type
) const
461 string Info
= ::URI::NoUserPassword(URI
) + ' ';
462 if (Dist
[Dist
.size() - 1] == '/')
468 Info
+= Dist
+ '/' + Section
;
474 bool debTranslationsIndex::HasPackages() const /*{{{*/
476 return FileExists(IndexFile(Language
));
479 // TranslationsIndex::Exists - Check if the index is available /*{{{*/
480 // ---------------------------------------------------------------------
482 bool debTranslationsIndex::Exists() const
484 return FileExists(IndexFile(Language
));
487 // TranslationsIndex::Size - Return the size of the index /*{{{*/
488 // ---------------------------------------------------------------------
489 /* This is really only used for progress reporting. */
490 unsigned long debTranslationsIndex::Size() const
492 unsigned long size
= 0;
494 /* we need to ignore errors here; if the lists are absent, just return 0 */
495 _error
->PushToStack();
497 FileFd
f(IndexFile(Language
), FileFd::ReadOnly
, FileFd::Extension
);
501 if (_error
->PendingError() == true)
503 _error
->RevertToStack();
508 // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
509 // ---------------------------------------------------------------------
511 bool debTranslationsIndex::Merge(pkgCacheGenerator
&Gen
,OpProgress
*Prog
) const
513 // Check the translation file, if in use
514 string TranslationFile
= IndexFile(Language
);
515 if (FileExists(TranslationFile
))
517 FileFd
Trans(TranslationFile
,FileFd::ReadOnly
, FileFd::Extension
);
518 debListParser
TransParser(&Trans
);
519 if (_error
->PendingError() == true)
523 Prog
->SubProgress(0, Info(TranslationFile
.c_str()));
524 if (Gen
.SelectFile(TranslationFile
,string(),*this) == false)
525 return _error
->Error("Problem with SelectFile %s",TranslationFile
.c_str());
527 // Store the IMS information
528 pkgCache::PkgFileIterator TransFile
= Gen
.GetCurFile();
529 TransFile
->Size
= Trans
.FileSize();
530 TransFile
->mtime
= Trans
.ModificationTime();
532 if (Gen
.MergeList(TransParser
) == false)
533 return _error
->Error("Problem with MergeList %s",TranslationFile
.c_str());
539 // TranslationsIndex::FindInCache - Find this index /*{{{*/
540 // ---------------------------------------------------------------------
542 pkgCache::PkgFileIterator
debTranslationsIndex::FindInCache(pkgCache
&Cache
) const
544 string FileName
= IndexFile(Language
);
546 pkgCache::PkgFileIterator File
= Cache
.FileBegin();
547 for (; File
.end() == false; ++File
)
549 if (FileName
!= File
.FileName())
553 if (stat(File
.FileName(),&St
) != 0)
555 if (_config
->FindB("Debug::pkgCacheGen", false))
556 std::clog
<< "TranslationIndex::FindInCache - stat failed on " << File
.FileName() << std::endl
;
557 return pkgCache::PkgFileIterator(Cache
);
559 if ((unsigned)St
.st_size
!= File
->Size
|| St
.st_mtime
!= File
->mtime
)
561 if (_config
->FindB("Debug::pkgCacheGen", false))
562 std::clog
<< "TranslationIndex::FindInCache - size (" << St
.st_size
<< " <> " << File
->Size
563 << ") or mtime (" << St
.st_mtime
<< " <> " << File
->mtime
564 << ") doesn't match for " << File
.FileName() << std::endl
;
565 return pkgCache::PkgFileIterator(Cache
);
572 // StatusIndex::debStatusIndex - Constructor /*{{{*/
573 // ---------------------------------------------------------------------
575 debStatusIndex::debStatusIndex(string File
) : pkgIndexFile(true), File(File
)
579 // StatusIndex::Size - Return the size of the index /*{{{*/
580 // ---------------------------------------------------------------------
582 unsigned long debStatusIndex::Size() const
585 if (stat(File
.c_str(),&S
) != 0)
590 // StatusIndex::Merge - Load the index file into a cache /*{{{*/
591 // ---------------------------------------------------------------------
593 bool debStatusIndex::Merge(pkgCacheGenerator
&Gen
,OpProgress
*Prog
) const
595 FileFd
Pkg(File
,FileFd::ReadOnly
, FileFd::Extension
);
596 if (_error
->PendingError() == true)
598 debListParser
Parser(&Pkg
);
599 if (_error
->PendingError() == true)
603 Prog
->SubProgress(0,File
);
604 if (Gen
.SelectFile(File
,string(),*this,pkgCache::Flag::NotSource
) == false)
605 return _error
->Error("Problem with SelectFile %s",File
.c_str());
607 // Store the IMS information
608 pkgCache::PkgFileIterator CFile
= Gen
.GetCurFile();
609 CFile
->Size
= Pkg
.FileSize();
610 CFile
->mtime
= Pkg
.ModificationTime();
611 map_ptrloc
const storage
= Gen
.WriteUniqString("now");
612 CFile
->Archive
= storage
;
614 if (Gen
.MergeList(Parser
) == false)
615 return _error
->Error("Problem with MergeList %s",File
.c_str());
619 // StatusIndex::FindInCache - Find this index /*{{{*/
620 // ---------------------------------------------------------------------
622 pkgCache::PkgFileIterator
debStatusIndex::FindInCache(pkgCache
&Cache
) const
624 pkgCache::PkgFileIterator File
= Cache
.FileBegin();
625 for (; File
.end() == false; ++File
)
627 if (this->File
!= File
.FileName())
631 if (stat(File
.FileName(),&St
) != 0)
633 if (_config
->FindB("Debug::pkgCacheGen", false))
634 std::clog
<< "StatusIndex::FindInCache - stat failed on " << File
.FileName() << std::endl
;
635 return pkgCache::PkgFileIterator(Cache
);
637 if ((unsigned)St
.st_size
!= File
->Size
|| St
.st_mtime
!= File
->mtime
)
639 if (_config
->FindB("Debug::pkgCacheGen", false))
640 std::clog
<< "StatusIndex::FindInCache - size (" << St
.st_size
<< " <> " << File
->Size
641 << ") or mtime (" << St
.st_mtime
<< " <> " << File
->mtime
642 << ") doesn't match for " << File
.FileName() << std::endl
;
643 return pkgCache::PkgFileIterator(Cache
);
650 // StatusIndex::Exists - Check if the index is available /*{{{*/
651 // ---------------------------------------------------------------------
653 bool debStatusIndex::Exists() const
655 // Abort if the file does not exist.
660 // Index File types for Debian /*{{{*/
661 class debIFTypeSrc
: public pkgIndexFile::Type
665 debIFTypeSrc() {Label
= "Debian Source Index";};
667 class debIFTypePkg
: public pkgIndexFile::Type
671 virtual pkgRecords::Parser
*CreatePkgParser(pkgCache::PkgFileIterator File
) const
673 return new debRecordParser(File
.FileName(),*File
.Cache());
675 debIFTypePkg() {Label
= "Debian Package Index";};
677 class debIFTypeTrans
: public debIFTypePkg
680 debIFTypeTrans() {Label
= "Debian Translation Index";};
682 class debIFTypeStatus
: public pkgIndexFile::Type
686 virtual pkgRecords::Parser
*CreatePkgParser(pkgCache::PkgFileIterator File
) const
688 return new debRecordParser(File
.FileName(),*File
.Cache());
690 debIFTypeStatus() {Label
= "Debian dpkg status file";};
692 static debIFTypeSrc _apt_Src
;
693 static debIFTypePkg _apt_Pkg
;
694 static debIFTypeTrans _apt_Trans
;
695 static debIFTypeStatus _apt_Status
;
697 const pkgIndexFile::Type
*debSourcesIndex::GetType() const
701 const pkgIndexFile::Type
*debPackagesIndex::GetType() const
705 const pkgIndexFile::Type
*debTranslationsIndex::GetType() const
709 const pkgIndexFile::Type
*debStatusIndex::GetType() const