]> git.saurik.com Git - apt.git/blob - apt-pkg/indexfile.cc
b592ae5a020b80a92cad32c8071e3a3543b5f388
[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/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30
31 #include <string>
32 #include <vector>
33 #include <clocale>
34 #include <cstring>
35 #include <memory>
36 /*}}}*/
37
38 // Global list of Item supported
39 static pkgIndexFile::Type *ItmList[10];
40 pkgIndexFile::Type **pkgIndexFile::Type::GlobalList = ItmList;
41 unsigned long pkgIndexFile::Type::GlobalListLen = 0;
42
43 // Type::Type - Constructor /*{{{*/
44 // ---------------------------------------------------------------------
45 /* */
46 pkgIndexFile::Type::Type()
47 {
48 ItmList[GlobalListLen] = this;
49 GlobalListLen++;
50 Label = NULL;
51 }
52 /*}}}*/
53 // Type::GetType - Locate the type by name /*{{{*/
54 // ---------------------------------------------------------------------
55 /* */
56 pkgIndexFile::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;
62 }
63 /*}}}*/
64 pkgIndexFile::pkgIndexFile(bool const Trusted) : /*{{{*/
65 d(NULL), Trusted(Trusted)
66 {
67 }
68 /*}}}*/
69 // IndexFile::ArchiveInfo - Stub /*{{{*/
70 std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator const &/*Ver*/) const
71 {
72 return std::string();
73 }
74 /*}}}*/
75 // IndexFile::FindInCache - Stub /*{{{*/
76 pkgCache::PkgFileIterator pkgIndexFile::FindInCache(pkgCache &Cache) const
77 {
78 return pkgCache::PkgFileIterator(Cache);
79 }
80 /*}}}*/
81 // IndexFile::SourceIndex - Stub /*{{{*/
82 std::string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &/*Record*/,
83 pkgSrcRecords::File const &/*File*/) const
84 {
85 return std::string();
86 }
87 /*}}}*/
88 // IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/
89 // ---------------------------------------------------------------------
90 /* */
91 bool pkgIndexFile::TranslationsAvailable() {
92 return (APT::Configuration::getLanguages().empty() != true);
93 }
94 /*}}}*/
95 // IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/
96 // ---------------------------------------------------------------------
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 */
101 APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char * const Lang)
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 /*}}}*/
112 // IndexFile::LanguageCode - Return the Language Code /*{{{*/
113 // ---------------------------------------------------------------------
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 */
117 APT_DEPRECATED std::string pkgIndexFile::LanguageCode() {
118 if (TranslationsAvailable() == false)
119 return "";
120 return APT::Configuration::getLanguages()[0];
121 }
122 /*}}}*/
123
124 // IndexTarget - Constructor /*{{{*/
125 IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc,
126 std::string const &LongDesc, std::string const &URI, bool const IsOptional,
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)
130 {
131 }
132 /*}}}*/
133 std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/
134 {
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);
146 APT_CASE(TARGET_OF);
147 APT_CASE(CREATED_BY);
148 #undef APT_CASE
149 case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
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 "";
162 }
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 /*}}}*/
169 std::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 /*}}}*/
183
184 pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
185 pkgDebianIndexFile(Trusted), d(NULL), Target(Target)
186 {
187 }
188 /*}}}*/
189 std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/
190 {
191 return Target.Option(IndexTarget::REPO_URI) + File;
192 }
193 /*}}}*/
194 std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/
195 {
196 if (Short)
197 return Target.Description;
198 return Target.Description + " (" + IndexFileName() + ")";
199 }
200 /*}}}*/
201 std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/
202 {
203 std::string const s = Target.Option(IndexTarget::FILENAME);
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 /*}}}*/
217 unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/
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 /*}}}*/
235 bool pkgDebianIndexTargetFile::Exists() const /*{{{*/
236 {
237 return FileExists(IndexFileName());
238 }
239 /*}}}*/
240 std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/
241 {
242 return Target.Option(IndexTarget::ARCHITECTURE);
243 }
244 /*}}}*/
245 std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/
246 {
247 return Target.Option(IndexTarget::COMPONENT);
248 }
249 /*}}}*/
250 bool 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 /*}}}*/
257 std::string pkgDebianIndexTargetFile::GetProgressDescription() const
258 {
259 return Target.Description;
260 }
261
262 pkgDebianIndexRealFile::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 /*{{{*/
268 unsigned 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 /*}}}*/
276 bool pkgDebianIndexRealFile::Exists() const /*{{{*/
277 {
278 return FileExists(File);
279 }
280 /*}}}*/
281 std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/
282 {
283 return File;
284 }
285 /*}}}*/
286 std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/
287 {
288 return "file:" + File;
289 }
290 /*}}}*/
291 std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/
292 {
293 return File;
294 }
295 /*}}}*/
296 std::string pkgDebianIndexRealFile::GetProgressDescription() const
297 {
298 return File;
299 }
300 bool 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
308 pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted)
309 {
310 }
311 pkgDebianIndexFile::~pkgDebianIndexFile()
312 {
313 }
314 pkgCacheListParser * 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 }
324 bool 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 }
354 pkgCache::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 }
383
384 APT_CONST pkgIndexFile::~pkgIndexFile() {}
385 APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {}
386 APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {}