]> git.saurik.com Git - apt.git/blame_incremental - apt-pkg/indexfile.cc
do not cleanup .diff/Index files on Hit
[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/deblistparser.h>
25#include <apt-pkg/macros.h>
26
27#include <apt-pkg/debindexfile.h>
28
29#include <sys/stat.h>
30
31#include <string>
32#include <vector>
33#include <clocale>
34#include <cstring>
35#include <memory>
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;
49 GlobalListLen++;
50 Label = NULL;
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;
62}
63 /*}}}*/
64pkgIndexFile::pkgIndexFile(bool const Trusted) : /*{{{*/
65 d(NULL), Trusted(Trusted)
66{
67}
68 /*}}}*/
69// IndexFile::ArchiveInfo - Stub /*{{{*/
70std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator const &Ver) const
71{
72 debDebPkgFileIndex const * const debfile = dynamic_cast<debDebPkgFileIndex const*>(this);
73 if (debfile != nullptr)
74 return debfile->ArchiveInfo_impl(Ver);
75 return std::string();
76}
77 /*}}}*/
78// IndexFile::FindInCache - Stub /*{{{*/
79pkgCache::PkgFileIterator pkgIndexFile::FindInCache(pkgCache &Cache) const
80{
81 return pkgCache::PkgFileIterator(Cache);
82}
83 /*}}}*/
84// IndexFile::SourceIndex - Stub /*{{{*/
85std::string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &/*Record*/,
86 pkgSrcRecords::File const &/*File*/) const
87{
88 return std::string();
89}
90 /*}}}*/
91// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
92// ---------------------------------------------------------------------
93/* */
94bool pkgIndexFile::TranslationsAvailable() {
95 return (APT::Configuration::getLanguages().empty() != true);
96}
97 /*}}}*/
98// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
99// ---------------------------------------------------------------------
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 */
104APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char * const Lang)
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 /*}}}*/
115// IndexFile::LanguageCode - Return the Language Code /*{{{*/
116// ---------------------------------------------------------------------
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 */
120APT_DEPRECATED std::string pkgIndexFile::LanguageCode() {
121 if (TranslationsAvailable() == false)
122 return "";
123 return APT::Configuration::getLanguages()[0];
124}
125 /*}}}*/
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,
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)
133{
134}
135 /*}}}*/
136std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/
137{
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);
149 APT_CASE(TARGET_OF);
150 APT_CASE(CREATED_BY);
151 APT_CASE(PDIFFS);
152 APT_CASE(DEFAULTENABLED);
153 APT_CASE(COMPRESSIONTYPES);
154 APT_CASE(SOURCESENTRY);
155 APT_CASE(BY_HASH);
156#undef APT_CASE
157 case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
158 case EXISTING_FILENAME:
159 std::string const filename = Option(FILENAME);
160 std::vector<std::string> const types = VectorizeString(Option(COMPRESSIONTYPES), ' ');
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 "";
170 }
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 /*}}}*/
177bool IndexTarget::OptionBool(OptionKeys const EnumKey) const /*{{{*/
178{
179 return StringToBool(Option(EnumKey));
180}
181 /*}}}*/
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 /*}}}*/
196
197pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
198 pkgDebianIndexFile(Trusted), d(NULL), Target(Target)
199{
200}
201 /*}}}*/
202std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/
203{
204 return Target.Option(IndexTarget::REPO_URI) + File;
205}
206 /*}}}*/
207std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/
208{
209 if (Short)
210 return Target.Description;
211 return Target.Description + " (" + IndexFileName() + ")";
212}
213 /*}}}*/
214std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/
215{
216 std::string const s = Target.Option(IndexTarget::FILENAME);
217 if (FileExists(s))
218 return s;
219
220 std::vector<std::string> const types = VectorizeString(Target.Option(IndexTarget::COMPRESSIONTYPES), ' ');
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 /*}}}*/
230unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/
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 /*}}}*/
248bool pkgDebianIndexTargetFile::Exists() const /*{{{*/
249{
250 return FileExists(IndexFileName());
251}
252 /*}}}*/
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
275pkgDebianIndexRealFile::pkgDebianIndexRealFile(std::string const &pFile, bool const Trusted) :/*{{{*/
276 pkgDebianIndexFile(Trusted), d(NULL)
277{
278 if (pFile == "/nonexistent/stdin")
279 File = pFile;
280 else
281 File = flAbsPath(pFile);
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();
336 pkgCacheListParser * const Parser = new debListParser(&Pkg);
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();
350 _error->MergeWithStack();
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}
401
402APT_CONST pkgIndexFile::~pkgIndexFile() {}
403APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {}
404APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {}