]> git.saurik.com Git - apt.git/blob - apt-pkg/indexfile.cc
1ed7984101f03bf8a2a418ce21cd07c140462620
[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/strutl.h>
23 #include <apt-pkg/progress.h>
24 #include <apt-pkg/macros.h>
25
26 #include <apt-pkg/deblistparser.h>
27
28 #include <sys/stat.h>
29
30 #include <string>
31 #include <vector>
32 #include <clocale>
33 #include <cstring>
34 #include <memory>
35 /*}}}*/
36
37 // Global list of Item supported
38 static pkgIndexFile::Type *ItmList[10];
39 pkgIndexFile::Type **pkgIndexFile::Type::GlobalList = ItmList;
40 unsigned long pkgIndexFile::Type::GlobalListLen = 0;
41
42 // Type::Type - Constructor /*{{{*/
43 // ---------------------------------------------------------------------
44 /* */
45 pkgIndexFile::Type::Type()
46 {
47 ItmList[GlobalListLen] = this;
48 GlobalListLen++;
49 Label = NULL;
50 }
51 /*}}}*/
52 // Type::GetType - Locate the type by name /*{{{*/
53 // ---------------------------------------------------------------------
54 /* */
55 pkgIndexFile::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;
61 }
62 /*}}}*/
63 pkgIndexFile::pkgIndexFile(bool const Trusted) : /*{{{*/
64 d(NULL), Trusted(Trusted)
65 {
66 }
67 /*}}}*/
68 // IndexFile::ArchiveInfo - Stub /*{{{*/
69 std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator const &/*Ver*/) const
70 {
71 return std::string();
72 }
73 /*}}}*/
74 // IndexFile::FindInCache - Stub /*{{{*/
75 pkgCache::PkgFileIterator pkgIndexFile::FindInCache(pkgCache &Cache) const
76 {
77 return pkgCache::PkgFileIterator(Cache);
78 }
79 /*}}}*/
80 // IndexFile::SourceIndex - Stub /*{{{*/
81 std::string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &/*Record*/,
82 pkgSrcRecords::File const &/*File*/) const
83 {
84 return std::string();
85 }
86 /*}}}*/
87 // IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
88 // ---------------------------------------------------------------------
89 /* */
90 bool pkgIndexFile::TranslationsAvailable() {
91 return (APT::Configuration::getLanguages().empty() != true);
92 }
93 /*}}}*/
94 // IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
95 // ---------------------------------------------------------------------
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 */
100 APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char * const Lang)
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 /*}}}*/
111 // IndexFile::LanguageCode - Return the Language Code /*{{{*/
112 // ---------------------------------------------------------------------
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 */
116 APT_DEPRECATED std::string pkgIndexFile::LanguageCode() {
117 if (TranslationsAvailable() == false)
118 return "";
119 return APT::Configuration::getLanguages()[0];
120 }
121 /*}}}*/
122
123 // IndexTarget - Constructor /*{{{*/
124 IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc,
125 std::string const &LongDesc, std::string const &URI, bool const IsOptional,
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)
129 {
130 }
131 /*}}}*/
132 std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/
133 {
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);
145 APT_CASE(TARGET_OF);
146 APT_CASE(CREATED_BY);
147 APT_CASE(PDIFFS);
148 APT_CASE(DEFAULTENABLED);
149 APT_CASE(COMPRESSIONTYPES);
150 #undef APT_CASE
151 case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
152 case EXISTING_FILENAME:
153 std::string const filename = Option(FILENAME);
154 std::vector<std::string> const types = VectorizeString(Option(COMPRESSIONTYPES), ' ');
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 "";
164 }
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 /*}}}*/
171 bool IndexTarget::OptionBool(OptionKeys const EnumKey) const /*{{{*/
172 {
173 return StringToBool(Option(EnumKey));
174 }
175 /*}}}*/
176 std::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 /*}}}*/
190
191 pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
192 pkgDebianIndexFile(Trusted), d(NULL), Target(Target)
193 {
194 }
195 /*}}}*/
196 std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/
197 {
198 return Target.Option(IndexTarget::REPO_URI) + File;
199 }
200 /*}}}*/
201 std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/
202 {
203 if (Short)
204 return Target.Description;
205 return Target.Description + " (" + IndexFileName() + ")";
206 }
207 /*}}}*/
208 std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/
209 {
210 std::string const s = Target.Option(IndexTarget::FILENAME);
211 if (FileExists(s))
212 return s;
213
214 std::vector<std::string> const types = VectorizeString(Target.Option(IndexTarget::COMPRESSIONTYPES), ' ');
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 /*}}}*/
224 unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/
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 /*}}}*/
242 bool pkgDebianIndexTargetFile::Exists() const /*{{{*/
243 {
244 return FileExists(IndexFileName());
245 }
246 /*}}}*/
247 std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/
248 {
249 return Target.Option(IndexTarget::ARCHITECTURE);
250 }
251 /*}}}*/
252 std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/
253 {
254 return Target.Option(IndexTarget::COMPONENT);
255 }
256 /*}}}*/
257 bool 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 /*}}}*/
264 std::string pkgDebianIndexTargetFile::GetProgressDescription() const
265 {
266 return Target.Description;
267 }
268
269 pkgDebianIndexRealFile::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 /*{{{*/
275 unsigned 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 /*}}}*/
283 bool pkgDebianIndexRealFile::Exists() const /*{{{*/
284 {
285 return FileExists(File);
286 }
287 /*}}}*/
288 std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/
289 {
290 return File;
291 }
292 /*}}}*/
293 std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/
294 {
295 return "file:" + File;
296 }
297 /*}}}*/
298 std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/
299 {
300 return File;
301 }
302 /*}}}*/
303 std::string pkgDebianIndexRealFile::GetProgressDescription() const
304 {
305 return File;
306 }
307 bool 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
315 pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted)
316 {
317 }
318 pkgDebianIndexFile::~pkgDebianIndexFile()
319 {
320 }
321 pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg)
322 {
323 if (Pkg.IsOpen() == false)
324 return NULL;
325 _error->PushToStack();
326 pkgCacheListParser * const Parser = new debListParser(&Pkg);
327 bool const newError = _error->PendingError();
328 _error->MergeWithStack();
329 return newError ? NULL : Parser;
330 }
331 bool 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 }
361 pkgCache::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 }
390
391 APT_CONST pkgIndexFile::~pkgIndexFile() {}
392 APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {}
393 APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {}