]> git.saurik.com Git - apt.git/blame_incremental - apt-pkg/indexfile.cc
detect and deal with indextarget duplicates
[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(DEFAULTENABLED);
149 APT_CASE(COMPRESSIONTYPES);
150 APT_CASE(SOURCESENTRY);
151#undef APT_CASE
152 case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
153 case EXISTING_FILENAME:
154 std::string const filename = Option(FILENAME);
155 std::vector<std::string> const types = VectorizeString(Option(COMPRESSIONTYPES), ' ');
156 for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
157 {
158 if (t->empty())
159 continue;
160 std::string const file = (*t == "uncompressed") ? filename : (filename + "." + *t);
161 if (FileExists(file))
162 return file;
163 }
164 return "";
165 }
166 std::map<std::string,std::string>::const_iterator const M = Options.find(Key);
167 if (M == Options.end())
168 return "";
169 return M->second;
170}
171 /*}}}*/
172bool IndexTarget::OptionBool(OptionKeys const EnumKey) const /*{{{*/
173{
174 return StringToBool(Option(EnumKey));
175}
176 /*}}}*/
177std::string IndexTarget::Format(std::string format) const /*{{{*/
178{
179 for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
180 {
181 format = SubstVar(format, std::string("$(") + O->first + ")", O->second);
182 }
183 format = SubstVar(format, "$(METAKEY)", MetaKey);
184 format = SubstVar(format, "$(SHORTDESC)", ShortDesc);
185 format = SubstVar(format, "$(DESCRIPTION)", Description);
186 format = SubstVar(format, "$(URI)", URI);
187 format = SubstVar(format, "$(FILENAME)", Option(IndexTarget::FILENAME));
188 return format;
189}
190 /*}}}*/
191
192pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
193 pkgDebianIndexFile(Trusted), d(NULL), Target(Target)
194{
195}
196 /*}}}*/
197std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/
198{
199 return Target.Option(IndexTarget::REPO_URI) + File;
200}
201 /*}}}*/
202std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/
203{
204 if (Short)
205 return Target.Description;
206 return Target.Description + " (" + IndexFileName() + ")";
207}
208 /*}}}*/
209std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/
210{
211 std::string const s = Target.Option(IndexTarget::FILENAME);
212 if (FileExists(s))
213 return s;
214
215 std::vector<std::string> const types = VectorizeString(Target.Option(IndexTarget::COMPRESSIONTYPES), ' ');
216 for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
217 {
218 std::string p = s + '.' + *t;
219 if (FileExists(p))
220 return p;
221 }
222 return s;
223}
224 /*}}}*/
225unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/
226{
227 unsigned long size = 0;
228
229 /* we need to ignore errors here; if the lists are absent, just return 0 */
230 _error->PushToStack();
231
232 FileFd f(IndexFileName(), FileFd::ReadOnly, FileFd::Extension);
233 if (!f.Failed())
234 size = f.Size();
235
236 if (_error->PendingError() == true)
237 size = 0;
238 _error->RevertToStack();
239
240 return size;
241}
242 /*}}}*/
243bool pkgDebianIndexTargetFile::Exists() const /*{{{*/
244{
245 return FileExists(IndexFileName());
246}
247 /*}}}*/
248std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/
249{
250 return Target.Option(IndexTarget::ARCHITECTURE);
251}
252 /*}}}*/
253std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/
254{
255 return Target.Option(IndexTarget::COMPONENT);
256}
257 /*}}}*/
258bool pkgDebianIndexTargetFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/
259{
260 if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::Extension) == false)
261 return _error->Error("Problem opening %s",FileName.c_str());
262 return true;
263}
264 /*}}}*/
265std::string pkgDebianIndexTargetFile::GetProgressDescription() const
266{
267 return Target.Description;
268}
269
270pkgDebianIndexRealFile::pkgDebianIndexRealFile(std::string const &File, bool const Trusted) :/*{{{*/
271 pkgDebianIndexFile(Trusted), d(NULL), File(flAbsPath(File))
272{
273}
274 /*}}}*/
275// IndexRealFile::Size - Return the size of the index /*{{{*/
276unsigned long pkgDebianIndexRealFile::Size() const
277{
278 struct stat S;
279 if (stat(File.c_str(),&S) != 0)
280 return 0;
281 return S.st_size;
282}
283 /*}}}*/
284bool pkgDebianIndexRealFile::Exists() const /*{{{*/
285{
286 return FileExists(File);
287}
288 /*}}}*/
289std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/
290{
291 return File;
292}
293 /*}}}*/
294std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/
295{
296 return "file:" + File;
297}
298 /*}}}*/
299std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/
300{
301 return File;
302}
303 /*}}}*/
304std::string pkgDebianIndexRealFile::GetProgressDescription() const
305{
306 return File;
307}
308bool pkgDebianIndexRealFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/
309{
310 if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::None) == false)
311 return _error->Error("Problem opening %s",FileName.c_str());
312 return true;
313}
314 /*}}}*/
315
316pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted)
317{
318}
319pkgDebianIndexFile::~pkgDebianIndexFile()
320{
321}
322pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg)
323{
324 if (Pkg.IsOpen() == false)
325 return NULL;
326 _error->PushToStack();
327 pkgCacheListParser * const Parser = new debListParser(&Pkg);
328 bool const newError = _error->PendingError();
329 _error->MergeWithStack();
330 return newError ? NULL : Parser;
331}
332bool pkgDebianIndexFile::Merge(pkgCacheGenerator &Gen,OpProgress * const Prog)
333{
334 std::string const PackageFile = IndexFileName();
335 FileFd Pkg;
336 if (OpenListFile(Pkg, PackageFile) == false)
337 return false;
338 _error->PushToStack();
339 std::unique_ptr<pkgCacheListParser> Parser(CreateListParser(Pkg));
340 bool const newError = _error->PendingError();
341 if (newError == false && Parser == nullptr)
342 return true;
343 if (Parser == NULL)
344 return false;
345
346 if (Prog != NULL)
347 Prog->SubProgress(0, GetProgressDescription());
348
349 if (Gen.SelectFile(PackageFile, *this, GetArchitecture(), GetComponent(), GetIndexFlags()) == false)
350 return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
351
352 // Store the IMS information
353 pkgCache::PkgFileIterator File = Gen.GetCurFile();
354 pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
355 File->Size = Pkg.FileSize();
356 File->mtime = Pkg.ModificationTime();
357
358 if (Gen.MergeList(*Parser) == false)
359 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
360 return true;
361}
362pkgCache::PkgFileIterator pkgDebianIndexFile::FindInCache(pkgCache &Cache) const
363{
364 std::string const FileName = IndexFileName();
365 pkgCache::PkgFileIterator File = Cache.FileBegin();
366 for (; File.end() == false; ++File)
367 {
368 if (File.FileName() == NULL || FileName != File.FileName())
369 continue;
370
371 struct stat St;
372 if (stat(File.FileName(),&St) != 0)
373 {
374 if (_config->FindB("Debug::pkgCacheGen", false))
375 std::clog << "DebianIndexFile::FindInCache - stat failed on " << File.FileName() << std::endl;
376 return pkgCache::PkgFileIterator(Cache);
377 }
378 if ((map_filesize_t)St.st_size != File->Size || St.st_mtime != File->mtime)
379 {
380 if (_config->FindB("Debug::pkgCacheGen", false))
381 std::clog << "DebianIndexFile::FindInCache - size (" << St.st_size << " <> " << File->Size
382 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
383 << ") doesn't match for " << File.FileName() << std::endl;
384 return pkgCache::PkgFileIterator(Cache);
385 }
386 return File;
387 }
388
389 return File;
390}
391
392APT_CONST pkgIndexFile::~pkgIndexFile() {}
393APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {}
394APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {}