]> git.saurik.com Git - apt.git/blame - apt-pkg/indexfile.cc
try xz instead of bz2 first for compressed files
[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>
453b82a3 24#include <apt-pkg/macros.h>
a52f938b 25
c9443c01
DK
26#include <apt-pkg/deblistparser.h>
27
c9443c01 28#include <sys/stat.h>
c9443c01 29
453b82a3
DK
30#include <string>
31#include <vector>
a52f938b 32#include <clocale>
4f333a8b 33#include <cstring>
c9443c01 34#include <memory>
b2e465d6
AL
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;
dd688285
DK
48 GlobalListLen++;
49 Label = NULL;
b2e465d6
AL
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;
e3c1cfc7
DK
61}
62 /*}}}*/
c9443c01 63pkgIndexFile::pkgIndexFile(bool const Trusted) : /*{{{*/
6c55f07a 64 d(NULL), Trusted(Trusted)
e3c1cfc7 65{
b2e465d6
AL
66}
67 /*}}}*/
b2e465d6 68// IndexFile::ArchiveInfo - Stub /*{{{*/
c9443c01 69std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator const &/*Ver*/) const
b2e465d6 70{
8f3ba4e8 71 return std::string();
b2e465d6
AL
72}
73 /*}}}*/
74// IndexFile::FindInCache - Stub /*{{{*/
b2e465d6
AL
75pkgCache::PkgFileIterator pkgIndexFile::FindInCache(pkgCache &Cache) const
76{
77 return pkgCache::PkgFileIterator(Cache);
78}
79 /*}}}*/
80// IndexFile::SourceIndex - Stub /*{{{*/
65512241
DK
81std::string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &/*Record*/,
82 pkgSrcRecords::File const &/*File*/) const
b2e465d6 83{
8f3ba4e8 84 return std::string();
b2e465d6
AL
85}
86 /*}}}*/
45df0ad2 87// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
a52f938b
OS
88// ---------------------------------------------------------------------
89/* */
45df0ad2
DK
90bool pkgIndexFile::TranslationsAvailable() {
91 return (APT::Configuration::getLanguages().empty() != true);
a52f938b
OS
92}
93 /*}}}*/
45df0ad2 94// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
a52f938b 95// ---------------------------------------------------------------------
45df0ad2
DK
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 */
c9443c01 100APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char * const Lang)
a52f938b
OS
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 /*}}}*/
45df0ad2 111// IndexFile::LanguageCode - Return the Language Code /*{{{*/
a52f938b 112// ---------------------------------------------------------------------
45df0ad2
DK
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 */
453b82a3 116APT_DEPRECATED std::string pkgIndexFile::LanguageCode() {
45df0ad2
DK
117 if (TranslationsAvailable() == false)
118 return "";
119 return APT::Configuration::getLanguages()[0];
a52f938b
OS
120}
121 /*}}}*/
e3c1cfc7
DK
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,
653ef26c
DK
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)
e3c1cfc7
DK
129{
130}
131 /*}}}*/
001c76fe 132std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/
e3c1cfc7 133{
001c76fe
DK
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);
8881b11e 145 APT_CASE(TARGET_OF);
001c76fe 146 APT_CASE(CREATED_BY);
1a3a14ac 147 APT_CASE(PDIFFS);
9adb9778 148 APT_CASE(DEFAULTENABLED);
d7a51997 149 APT_CASE(COMPRESSIONTYPES);
001c76fe 150#undef APT_CASE
8881b11e 151 case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
3fd89e62
DK
152 case EXISTING_FILENAME:
153 std::string const filename = Option(FILENAME);
d7a51997 154 std::vector<std::string> const types = VectorizeString(Option(COMPRESSIONTYPES), ' ');
3fd89e62
DK
155 for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
156 {
157 if (t->empty())
158 continue;
159 std::string const file = (*t == "uncompressed") ? filename : (filename + "." + *t);
160 if (FileExists(file))
161 return file;
162 }
163 return "";
001c76fe 164 }
e3c1cfc7
DK
165 std::map<std::string,std::string>::const_iterator const M = Options.find(Key);
166 if (M == Options.end())
167 return "";
168 return M->second;
169}
170 /*}}}*/
1a3a14ac
DK
171bool IndexTarget::OptionBool(OptionKeys const EnumKey) const /*{{{*/
172{
173 return StringToBool(Option(EnumKey));
174}
175 /*}}}*/
8881b11e
DK
176std::string IndexTarget::Format(std::string format) const /*{{{*/
177{
178 for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
179 {
180 format = SubstVar(format, std::string("$(") + O->first + ")", O->second);
181 }
182 format = SubstVar(format, "$(METAKEY)", MetaKey);
183 format = SubstVar(format, "$(SHORTDESC)", ShortDesc);
184 format = SubstVar(format, "$(DESCRIPTION)", Description);
185 format = SubstVar(format, "$(URI)", URI);
186 format = SubstVar(format, "$(FILENAME)", Option(IndexTarget::FILENAME));
187 return format;
188}
189 /*}}}*/
e3c1cfc7 190
c9443c01
DK
191pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
192 pkgDebianIndexFile(Trusted), d(NULL), Target(Target)
e3c1cfc7
DK
193{
194}
195 /*}}}*/
c9443c01 196std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/
e3c1cfc7 197{
001c76fe 198 return Target.Option(IndexTarget::REPO_URI) + File;
e3c1cfc7
DK
199}
200 /*}}}*/
c9443c01 201std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/
e3c1cfc7
DK
202{
203 if (Short)
204 return Target.Description;
205 return Target.Description + " (" + IndexFileName() + ")";
206}
207 /*}}}*/
c9443c01 208std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/
e3c1cfc7 209{
8881b11e 210 std::string const s = Target.Option(IndexTarget::FILENAME);
e3c1cfc7
DK
211 if (FileExists(s))
212 return s;
213
d7a51997 214 std::vector<std::string> const types = VectorizeString(Target.Option(IndexTarget::COMPRESSIONTYPES), ' ');
e3c1cfc7
DK
215 for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
216 {
217 std::string p = s + '.' + *t;
218 if (FileExists(p))
219 return p;
220 }
221 return s;
222}
223 /*}}}*/
c9443c01 224unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/
e3c1cfc7
DK
225{
226 unsigned long size = 0;
227
228 /* we need to ignore errors here; if the lists are absent, just return 0 */
229 _error->PushToStack();
230
231 FileFd f(IndexFileName(), FileFd::ReadOnly, FileFd::Extension);
232 if (!f.Failed())
233 size = f.Size();
234
235 if (_error->PendingError() == true)
236 size = 0;
237 _error->RevertToStack();
238
239 return size;
240}
241 /*}}}*/
c9443c01 242bool pkgDebianIndexTargetFile::Exists() const /*{{{*/
e3c1cfc7
DK
243{
244 return FileExists(IndexFileName());
245}
246 /*}}}*/
c9443c01
DK
247std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/
248{
249 return Target.Option(IndexTarget::ARCHITECTURE);
250}
251 /*}}}*/
252std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/
253{
254 return Target.Option(IndexTarget::COMPONENT);
255}
256 /*}}}*/
257bool pkgDebianIndexTargetFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/
258{
259 if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::Extension) == false)
260 return _error->Error("Problem opening %s",FileName.c_str());
261 return true;
262}
263 /*}}}*/
264std::string pkgDebianIndexTargetFile::GetProgressDescription() const
265{
266 return Target.Description;
267}
268
269pkgDebianIndexRealFile::pkgDebianIndexRealFile(std::string const &File, bool const Trusted) :/*{{{*/
270 pkgDebianIndexFile(Trusted), d(NULL), File(flAbsPath(File))
271{
272}
273 /*}}}*/
274// IndexRealFile::Size - Return the size of the index /*{{{*/
275unsigned long pkgDebianIndexRealFile::Size() const
276{
277 struct stat S;
278 if (stat(File.c_str(),&S) != 0)
279 return 0;
280 return S.st_size;
281}
282 /*}}}*/
283bool pkgDebianIndexRealFile::Exists() const /*{{{*/
284{
285 return FileExists(File);
286}
287 /*}}}*/
288std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/
289{
290 return File;
291}
292 /*}}}*/
293std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/
294{
295 return "file:" + File;
296}
297 /*}}}*/
298std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/
299{
300 return File;
301}
302 /*}}}*/
303std::string pkgDebianIndexRealFile::GetProgressDescription() const
304{
305 return File;
306}
307bool pkgDebianIndexRealFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/
308{
309 if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::None) == false)
310 return _error->Error("Problem opening %s",FileName.c_str());
311 return true;
312}
313 /*}}}*/
314
315pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted)
316{
317}
318pkgDebianIndexFile::~pkgDebianIndexFile()
319{
320}
321pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg)
322{
323 if (Pkg.IsOpen() == false)
324 return NULL;
325 _error->PushToStack();
7f8c0eed 326 pkgCacheListParser * const Parser = new debListParser(&Pkg);
c9443c01
DK
327 bool const newError = _error->PendingError();
328 _error->MergeWithStack();
329 return newError ? NULL : Parser;
330}
331bool pkgDebianIndexFile::Merge(pkgCacheGenerator &Gen,OpProgress * const Prog)
332{
333 std::string const PackageFile = IndexFileName();
334 FileFd Pkg;
335 if (OpenListFile(Pkg, PackageFile) == false)
336 return false;
337 _error->PushToStack();
338 std::unique_ptr<pkgCacheListParser> Parser(CreateListParser(Pkg));
339 bool const newError = _error->PendingError();
340 if (newError == false && Parser == nullptr)
341 return true;
342 if (Parser == NULL)
343 return false;
344
345 if (Prog != NULL)
346 Prog->SubProgress(0, GetProgressDescription());
347
348 if (Gen.SelectFile(PackageFile, *this, GetArchitecture(), GetComponent(), GetIndexFlags()) == false)
349 return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
350
351 // Store the IMS information
352 pkgCache::PkgFileIterator File = Gen.GetCurFile();
353 pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
354 File->Size = Pkg.FileSize();
355 File->mtime = Pkg.ModificationTime();
356
357 if (Gen.MergeList(*Parser) == false)
358 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
359 return true;
360}
361pkgCache::PkgFileIterator pkgDebianIndexFile::FindInCache(pkgCache &Cache) const
362{
363 std::string const FileName = IndexFileName();
364 pkgCache::PkgFileIterator File = Cache.FileBegin();
365 for (; File.end() == false; ++File)
366 {
367 if (File.FileName() == NULL || FileName != File.FileName())
368 continue;
369
370 struct stat St;
371 if (stat(File.FileName(),&St) != 0)
372 {
373 if (_config->FindB("Debug::pkgCacheGen", false))
374 std::clog << "DebianIndexFile::FindInCache - stat failed on " << File.FileName() << std::endl;
375 return pkgCache::PkgFileIterator(Cache);
376 }
377 if ((map_filesize_t)St.st_size != File->Size || St.st_mtime != File->mtime)
378 {
379 if (_config->FindB("Debug::pkgCacheGen", false))
380 std::clog << "DebianIndexFile::FindInCache - size (" << St.st_size << " <> " << File->Size
381 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
382 << ") doesn't match for " << File.FileName() << std::endl;
383 return pkgCache::PkgFileIterator(Cache);
384 }
385 return File;
386 }
387
388 return File;
389}
c8a4ce6c
DK
390
391APT_CONST pkgIndexFile::~pkgIndexFile() {}
c9443c01
DK
392APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {}
393APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {}