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