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