]> git.saurik.com Git - apt.git/blob - apt-pkg/indexfile.cc
add by-hash sources.list option and document all of by-hash
[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 APT_CASE(SOURCESENTRY);
151 APT_CASE(BY_HASH);
152 #undef APT_CASE
153 case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI);
154 case EXISTING_FILENAME:
155 std::string const filename = Option(FILENAME);
156 std::vector<std::string> const types = VectorizeString(Option(COMPRESSIONTYPES), ' ');
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 "";
166 }
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 /*}}}*/
173 bool IndexTarget::OptionBool(OptionKeys const EnumKey) const /*{{{*/
174 {
175 return StringToBool(Option(EnumKey));
176 }
177 /*}}}*/
178 std::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 /*}}}*/
192
193 pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/
194 pkgDebianIndexFile(Trusted), d(NULL), Target(Target)
195 {
196 }
197 /*}}}*/
198 std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/
199 {
200 return Target.Option(IndexTarget::REPO_URI) + File;
201 }
202 /*}}}*/
203 std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/
204 {
205 if (Short)
206 return Target.Description;
207 return Target.Description + " (" + IndexFileName() + ")";
208 }
209 /*}}}*/
210 std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/
211 {
212 std::string const s = Target.Option(IndexTarget::FILENAME);
213 if (FileExists(s))
214 return s;
215
216 std::vector<std::string> const types = VectorizeString(Target.Option(IndexTarget::COMPRESSIONTYPES), ' ');
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 /*}}}*/
226 unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/
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 /*}}}*/
244 bool pkgDebianIndexTargetFile::Exists() const /*{{{*/
245 {
246 return FileExists(IndexFileName());
247 }
248 /*}}}*/
249 std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/
250 {
251 return Target.Option(IndexTarget::ARCHITECTURE);
252 }
253 /*}}}*/
254 std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/
255 {
256 return Target.Option(IndexTarget::COMPONENT);
257 }
258 /*}}}*/
259 bool 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 /*}}}*/
266 std::string pkgDebianIndexTargetFile::GetProgressDescription() const
267 {
268 return Target.Description;
269 }
270
271 pkgDebianIndexRealFile::pkgDebianIndexRealFile(std::string const &pFile, bool const Trusted) :/*{{{*/
272 pkgDebianIndexFile(Trusted), d(NULL)
273 {
274 if (pFile == "/nonexistent/stdin")
275 File = pFile;
276 else
277 File = flAbsPath(pFile);
278 }
279 /*}}}*/
280 // IndexRealFile::Size - Return the size of the index /*{{{*/
281 unsigned 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 /*}}}*/
289 bool pkgDebianIndexRealFile::Exists() const /*{{{*/
290 {
291 return FileExists(File);
292 }
293 /*}}}*/
294 std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/
295 {
296 return File;
297 }
298 /*}}}*/
299 std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/
300 {
301 return "file:" + File;
302 }
303 /*}}}*/
304 std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/
305 {
306 return File;
307 }
308 /*}}}*/
309 std::string pkgDebianIndexRealFile::GetProgressDescription() const
310 {
311 return File;
312 }
313 bool 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
321 pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted)
322 {
323 }
324 pkgDebianIndexFile::~pkgDebianIndexFile()
325 {
326 }
327 pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg)
328 {
329 if (Pkg.IsOpen() == false)
330 return NULL;
331 _error->PushToStack();
332 pkgCacheListParser * const Parser = new debListParser(&Pkg);
333 bool const newError = _error->PendingError();
334 _error->MergeWithStack();
335 return newError ? NULL : Parser;
336 }
337 bool 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();
346 _error->MergeWithStack();
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 }
368 pkgCache::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 }
397
398 APT_CONST pkgIndexFile::~pkgIndexFile() {}
399 APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {}
400 APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {}