]> git.saurik.com Git - apt.git/blame - apt-pkg/indexfile.cc
do not segfault in cache generation on mmap failure
[apt.git] / apt-pkg / indexfile.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
7db98ffc 3// $Id: indexfile.cc,v 1.2.2.1 2003/12/24 23:09:17 mdz Exp $
b2e465d6
AL
4/* ######################################################################
5
6 Index File - Abstraction for an index of archive/souce file.
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
ea542140
DK
11#include<config.h>
12
e3c1cfc7 13#include <apt-pkg/configuration.h>
b2e465d6
AL
14#include <apt-pkg/indexfile.h>
15#include <apt-pkg/error.h>
e3c1cfc7 16#include <apt-pkg/fileutl.h>
45df0ad2 17#include <apt-pkg/aptconfiguration.h>
453b82a3 18#include <apt-pkg/pkgcache.h>
c9443c01 19#include <apt-pkg/pkgcachegen.h>
453b82a3
DK
20#include <apt-pkg/cacheiterators.h>
21#include <apt-pkg/srcrecords.h>
d7a51997 22#include <apt-pkg/strutl.h>
c9443c01 23#include <apt-pkg/progress.h>
64b66a46 24#include <apt-pkg/deblistparser.h>
453b82a3 25#include <apt-pkg/macros.h>
a52f938b 26
64b66a46 27#include <apt-pkg/debindexfile.h>
c9443c01 28
c9443c01 29#include <sys/stat.h>
c9443c01 30
453b82a3
DK
31#include <string>
32#include <vector>
a52f938b 33#include <clocale>
4f333a8b 34#include <cstring>
c9443c01 35#include <memory>
b2e465d6
AL
36 /*}}}*/
37
38// Global list of Item supported
39static pkgIndexFile::Type *ItmList[10];
40pkgIndexFile::Type **pkgIndexFile::Type::GlobalList = ItmList;
41unsigned long pkgIndexFile::Type::GlobalListLen = 0;
42
43// Type::Type - Constructor /*{{{*/
44// ---------------------------------------------------------------------
45/* */
46pkgIndexFile::Type::Type()
47{
48 ItmList[GlobalListLen] = this;
dd688285
DK
49 GlobalListLen++;
50 Label = NULL;
b2e465d6
AL
51}
52 /*}}}*/
53// Type::GetType - Locate the type by name /*{{{*/
54// ---------------------------------------------------------------------
55/* */
56pkgIndexFile::Type *pkgIndexFile::Type::GetType(const char *Type)
57{
58 for (unsigned I = 0; I != GlobalListLen; I++)
59 if (strcmp(GlobalList[I]->Label,Type) == 0)
60 return GlobalList[I];
61 return 0;
e3c1cfc7
DK
62}
63 /*}}}*/
c9443c01 64pkgIndexFile::pkgIndexFile(bool const Trusted) : /*{{{*/
6c55f07a 65 d(NULL), Trusted(Trusted)
e3c1cfc7 66{
b2e465d6
AL
67}
68 /*}}}*/
b2e465d6 69// IndexFile::ArchiveInfo - Stub /*{{{*/
64b66a46 70std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator const &Ver) const
b2e465d6 71{
64b66a46
DK
72 debDebPkgFileIndex const * const debfile = dynamic_cast<debDebPkgFileIndex const*>(this);
73 if (debfile != nullptr)
74 return debfile->ArchiveInfo_impl(Ver);
8f3ba4e8 75 return std::string();
b2e465d6
AL
76}
77 /*}}}*/
78// IndexFile::FindInCache - Stub /*{{{*/
b2e465d6
AL
79pkgCache::PkgFileIterator pkgIndexFile::FindInCache(pkgCache &Cache) const
80{
81 return pkgCache::PkgFileIterator(Cache);
82}
83 /*}}}*/
84// IndexFile::SourceIndex - Stub /*{{{*/
65512241
DK
85std::string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &/*Record*/,
86 pkgSrcRecords::File const &/*File*/) const
b2e465d6 87{
8f3ba4e8 88 return std::string();
b2e465d6
AL
89}
90 /*}}}*/
45df0ad2 91// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
a52f938b
OS
92// ---------------------------------------------------------------------
93/* */
45df0ad2
DK
94bool pkgIndexFile::TranslationsAvailable() {
95 return (APT::Configuration::getLanguages().empty() != true);
a52f938b
OS
96}
97 /*}}}*/
45df0ad2 98// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
a52f938b 99// ---------------------------------------------------------------------
45df0ad2
DK
100/* No intern need for this method anymore as the check for correctness
101 is already done in getLanguages(). Note also that this check is
102 rather bad (doesn't take three character like ast into account).
103 TODO: Remove method with next API break */
c9443c01 104APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char * const Lang)
a52f938b
OS
105{
106 if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_'))
107 return true;
108
109 if (strcmp(Lang,"C") != 0)
110 _error->Warning("Wrong language code %s", Lang);
111
112 return false;
113}
114 /*}}}*/
45df0ad2 115// IndexFile::LanguageCode - Return the Language Code /*{{{*/
a52f938b 116// ---------------------------------------------------------------------
45df0ad2
DK
117/* As we have now possibly more than one LanguageCode this method is
118 supersided by a) private classmembers or b) getLanguages().
119 TODO: Remove method with next API break */
453b82a3 120APT_DEPRECATED std::string pkgIndexFile::LanguageCode() {
45df0ad2
DK
121 if (TranslationsAvailable() == false)
122 return "";
123 return APT::Configuration::getLanguages()[0];
a52f938b
OS
124}
125 /*}}}*/
e3c1cfc7
DK
126
127// IndexTarget - Constructor /*{{{*/
128IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc,
129 std::string const &LongDesc, std::string const &URI, bool const IsOptional,
653ef26c
DK
130 bool const KeepCompressed, std::map<std::string, std::string> const &Options) :
131 URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey),
132 IsOptional(IsOptional), KeepCompressed(KeepCompressed), Options(Options)
e3c1cfc7
DK
133{
134}
135 /*}}}*/
001c76fe 136std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/
e3c1cfc7 137{
001c76fe
DK
138 std::string Key;
139 switch (EnumKey)
140 {
141#define APT_CASE(X) case X: Key = #X; break
142 APT_CASE(SITE);
143 APT_CASE(RELEASE);
144 APT_CASE(COMPONENT);
145 APT_CASE(LANGUAGE);
146 APT_CASE(ARCHITECTURE);
147 APT_CASE(BASE_URI);
148 APT_CASE(REPO_URI);
8881b11e 149 APT_CASE(TARGET_OF);
001c76fe 150 APT_CASE(CREATED_BY);
1a3a14ac 151 APT_CASE(PDIFFS);
9adb9778 152 APT_CASE(DEFAULTENABLED);
d7a51997 153 APT_CASE(COMPRESSIONTYPES);
3090ae69 154 APT_CASE(SOURCESENTRY);
24e8f24e 155 APT_CASE(BY_HASH);
001c76fe 156#undef APT_CASE
8881b11e 157 case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
3fd89e62
DK
158 case EXISTING_FILENAME:
159 std::string const filename = Option(FILENAME);
d7a51997 160 std::vector<std::string> const types = VectorizeString(Option(COMPRESSIONTYPES), ' ');
3fd89e62
DK
161 for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
162 {
163 if (t->empty())
164 continue;
165 std::string const file = (*t == "uncompressed") ? filename : (filename + "." + *t);
166 if (FileExists(file))
167 return file;
168 }
169 return "";
001c76fe 170 }
e3c1cfc7
DK
171 std::map<std::string,std::string>::const_iterator const M = Options.find(Key);
172 if (M == Options.end())
173 return "";
174 return M->second;
175}
176 /*}}}*/
1a3a14ac
DK
177bool IndexTarget::OptionBool(OptionKeys const EnumKey) const /*{{{*/
178{
179 return StringToBool(Option(EnumKey));
180}
181 /*}}}*/
8881b11e
DK
182std::string IndexTarget::Format(std::string format) const /*{{{*/
183{
184 for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
185 {
186 format = SubstVar(format, std::string("$(") + O->first + ")", O->second);
187 }
188 format = SubstVar(format, "$(METAKEY)", MetaKey);
189 format = SubstVar(format, "$(SHORTDESC)", ShortDesc);
190 format = SubstVar(format, "$(DESCRIPTION)", Description);
191 format = SubstVar(format, "$(URI)", URI);
192 format = SubstVar(format, "$(FILENAME)", Option(IndexTarget::FILENAME));
193 return format;
194}
195 /*}}}*/
e3c1cfc7 196
c9443c01
DK
197pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
198 pkgDebianIndexFile(Trusted), d(NULL), Target(Target)
e3c1cfc7
DK
199{
200}
201 /*}}}*/
c9443c01 202std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/
e3c1cfc7 203{
001c76fe 204 return Target.Option(IndexTarget::REPO_URI) + File;
e3c1cfc7
DK
205}
206 /*}}}*/
c9443c01 207std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/
e3c1cfc7
DK
208{
209 if (Short)
210 return Target.Description;
211 return Target.Description + " (" + IndexFileName() + ")";
212}
213 /*}}}*/
c9443c01 214std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/
e3c1cfc7 215{
8881b11e 216 std::string const s = Target.Option(IndexTarget::FILENAME);
e3c1cfc7
DK
217 if (FileExists(s))
218 return s;
219
d7a51997 220 std::vector<std::string> const types = VectorizeString(Target.Option(IndexTarget::COMPRESSIONTYPES), ' ');
e3c1cfc7
DK
221 for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
222 {
223 std::string p = s + '.' + *t;
224 if (FileExists(p))
225 return p;
226 }
227 return s;
228}
229 /*}}}*/
c9443c01 230unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/
e3c1cfc7
DK
231{
232 unsigned long size = 0;
233
234 /* we need to ignore errors here; if the lists are absent, just return 0 */
235 _error->PushToStack();
236
237 FileFd f(IndexFileName(), FileFd::ReadOnly, FileFd::Extension);
238 if (!f.Failed())
239 size = f.Size();
240
241 if (_error->PendingError() == true)
242 size = 0;
243 _error->RevertToStack();
244
245 return size;
246}
247 /*}}}*/
c9443c01 248bool pkgDebianIndexTargetFile::Exists() const /*{{{*/
e3c1cfc7
DK
249{
250 return FileExists(IndexFileName());
251}
252 /*}}}*/
c9443c01
DK
253std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/
254{
255 return Target.Option(IndexTarget::ARCHITECTURE);
256}
257 /*}}}*/
258std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/
259{
260 return Target.Option(IndexTarget::COMPONENT);
261}
262 /*}}}*/
263bool pkgDebianIndexTargetFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/
264{
265 if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::Extension) == false)
266 return _error->Error("Problem opening %s",FileName.c_str());
267 return true;
268}
269 /*}}}*/
270std::string pkgDebianIndexTargetFile::GetProgressDescription() const
271{
272 return Target.Description;
273}
274
7f58427b
DK
275pkgDebianIndexRealFile::pkgDebianIndexRealFile(std::string const &pFile, bool const Trusted) :/*{{{*/
276 pkgDebianIndexFile(Trusted), d(NULL)
c9443c01 277{
7f58427b
DK
278 if (pFile == "/nonexistent/stdin")
279 File = pFile;
280 else
281 File = flAbsPath(pFile);
c9443c01
DK
282}
283 /*}}}*/
284// IndexRealFile::Size - Return the size of the index /*{{{*/
285unsigned long pkgDebianIndexRealFile::Size() const
286{
287 struct stat S;
288 if (stat(File.c_str(),&S) != 0)
289 return 0;
290 return S.st_size;
291}
292 /*}}}*/
293bool pkgDebianIndexRealFile::Exists() const /*{{{*/
294{
295 return FileExists(File);
296}
297 /*}}}*/
298std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/
299{
300 return File;
301}
302 /*}}}*/
303std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/
304{
305 return "file:" + File;
306}
307 /*}}}*/
308std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/
309{
310 return File;
311}
312 /*}}}*/
313std::string pkgDebianIndexRealFile::GetProgressDescription() const
314{
315 return File;
316}
317bool pkgDebianIndexRealFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/
318{
319 if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::None) == false)
320 return _error->Error("Problem opening %s",FileName.c_str());
321 return true;
322}
323 /*}}}*/
324
325pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted)
326{
327}
328pkgDebianIndexFile::~pkgDebianIndexFile()
329{
330}
331pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg)
332{
333 if (Pkg.IsOpen() == false)
334 return NULL;
335 _error->PushToStack();
7f8c0eed 336 pkgCacheListParser * const Parser = new debListParser(&Pkg);
c9443c01
DK
337 bool const newError = _error->PendingError();
338 _error->MergeWithStack();
339 return newError ? NULL : Parser;
340}
341bool pkgDebianIndexFile::Merge(pkgCacheGenerator &Gen,OpProgress * const Prog)
342{
343 std::string const PackageFile = IndexFileName();
344 FileFd Pkg;
345 if (OpenListFile(Pkg, PackageFile) == false)
346 return false;
347 _error->PushToStack();
348 std::unique_ptr<pkgCacheListParser> Parser(CreateListParser(Pkg));
349 bool const newError = _error->PendingError();
95278287 350 _error->MergeWithStack();
c9443c01
DK
351 if (newError == false && Parser == nullptr)
352 return true;
353 if (Parser == NULL)
354 return false;
355
356 if (Prog != NULL)
357 Prog->SubProgress(0, GetProgressDescription());
358
359 if (Gen.SelectFile(PackageFile, *this, GetArchitecture(), GetComponent(), GetIndexFlags()) == false)
360 return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
361
362 // Store the IMS information
363 pkgCache::PkgFileIterator File = Gen.GetCurFile();
364 pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
365 File->Size = Pkg.FileSize();
366 File->mtime = Pkg.ModificationTime();
367
368 if (Gen.MergeList(*Parser) == false)
369 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
370 return true;
371}
372pkgCache::PkgFileIterator pkgDebianIndexFile::FindInCache(pkgCache &Cache) const
373{
374 std::string const FileName = IndexFileName();
375 pkgCache::PkgFileIterator File = Cache.FileBegin();
376 for (; File.end() == false; ++File)
377 {
378 if (File.FileName() == NULL || FileName != File.FileName())
379 continue;
380
381 struct stat St;
382 if (stat(File.FileName(),&St) != 0)
383 {
384 if (_config->FindB("Debug::pkgCacheGen", false))
385 std::clog << "DebianIndexFile::FindInCache - stat failed on " << File.FileName() << std::endl;
386 return pkgCache::PkgFileIterator(Cache);
387 }
388 if ((map_filesize_t)St.st_size != File->Size || St.st_mtime != File->mtime)
389 {
390 if (_config->FindB("Debug::pkgCacheGen", false))
391 std::clog << "DebianIndexFile::FindInCache - size (" << St.st_size << " <> " << File->Size
392 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
393 << ") doesn't match for " << File.FileName() << std::endl;
394 return pkgCache::PkgFileIterator(Cache);
395 }
396 return File;
397 }
398
399 return File;
400}
c8a4ce6c
DK
401
402APT_CONST pkgIndexFile::~pkgIndexFile() {}
c9443c01
DK
403APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {}
404APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {}