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