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