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