]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debmetaindex.cc
08d8ef05e795c671645ec485f328214dfc59c966
[apt.git] / apt-pkg / deb / debmetaindex.cc
1 #include <config.h>
2
3 #include <apt-pkg/error.h>
4 #include <apt-pkg/debmetaindex.h>
5 #include <apt-pkg/debindexfile.h>
6 #include <apt-pkg/strutl.h>
7 #include <apt-pkg/fileutl.h>
8 #include <apt-pkg/acquire-item.h>
9 #include <apt-pkg/configuration.h>
10 #include <apt-pkg/aptconfiguration.h>
11 #include <apt-pkg/sourcelist.h>
12 #include <apt-pkg/hashes.h>
13 #include <apt-pkg/metaindex.h>
14 #include <apt-pkg/pkgcachegen.h>
15 #include <apt-pkg/tagfile.h>
16 #include <apt-pkg/gpgv.h>
17 #include <apt-pkg/macros.h>
18
19 #include <map>
20 #include <string>
21 #include <utility>
22 #include <vector>
23 #include <algorithm>
24 #include <sstream>
25
26 #include <sys/stat.h>
27 #include <string.h>
28
29 #include <apti18n.h>
30
31 class APT_HIDDEN debReleaseIndexPrivate /*{{{*/
32 {
33 public:
34 struct APT_HIDDEN debSectionEntry
35 {
36 std::string Name;
37 std::vector<std::string> Targets;
38 std::vector<std::string> Architectures;
39 std::vector<std::string> Languages;
40 bool UsePDiffs;
41 };
42
43 std::vector<debSectionEntry> DebEntries;
44 std::vector<debSectionEntry> DebSrcEntries;
45
46 metaIndex::TriState CheckValidUntil;
47 time_t ValidUntilMin;
48 time_t ValidUntilMax;
49
50 debReleaseIndexPrivate() : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0) {}
51 };
52 /*}}}*/
53 // ReleaseIndex::MetaIndex* - display helpers /*{{{*/
54 std::string debReleaseIndex::MetaIndexInfo(const char *Type) const
55 {
56 std::string Info = ::URI::ArchiveOnly(URI) + ' ';
57 if (Dist[Dist.size() - 1] == '/')
58 {
59 if (Dist != "/")
60 Info += Dist;
61 }
62 else
63 Info += Dist;
64 Info += " ";
65 Info += Type;
66 return Info;
67 }
68 std::string debReleaseIndex::Describe() const
69 {
70 return MetaIndexInfo("Release");
71 }
72
73 std::string debReleaseIndex::MetaIndexFile(const char *Type) const
74 {
75 return _config->FindDir("Dir::State::lists") +
76 URItoFileName(MetaIndexURI(Type));
77 }
78
79 std::string debReleaseIndex::MetaIndexURI(const char *Type) const
80 {
81 std::string Res;
82
83 if (Dist == "/")
84 Res = URI;
85 else if (Dist[Dist.size()-1] == '/')
86 Res = URI + Dist;
87 else
88 Res = URI + "dists/" + Dist + "/";
89
90 Res += Type;
91 return Res;
92 }
93 /*}}}*/
94 // ReleaseIndex Con- and Destructors /*{{{*/
95 debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist) :
96 metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate())
97 {}
98 debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const pTrusted) :
99 metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate())
100 {
101 Trusted = pTrusted ? TRI_YES : TRI_NO;
102 }
103 debReleaseIndex::~debReleaseIndex() {
104 if (d != NULL)
105 delete d;
106 }
107 /*}}}*/
108 // ReleaseIndex::GetIndexTargets /*{{{*/
109 static void GetIndexTargetsFor(char const * const Type, std::string const &URI, std::string const &Dist,
110 std::vector<debReleaseIndexPrivate::debSectionEntry> const &entries,
111 std::vector<IndexTarget> &IndexTargets)
112 {
113 bool const flatArchive = (Dist[Dist.length() - 1] == '/');
114 std::string baseURI = URI;
115 if (flatArchive)
116 {
117 if (Dist != "/")
118 baseURI += Dist;
119 }
120 else
121 baseURI += "dists/" + Dist + "/";
122 std::string const Release = (Dist == "/") ? "" : Dist;
123 std::string const Site = ::URI::ArchiveOnly(URI);
124
125 std::string DefCompressionTypes;
126 {
127 std::vector<std::string> types = APT::Configuration::getCompressionTypes();
128 if (types.empty() == false)
129 {
130 std::ostringstream os;
131 std::copy(types.begin(), types.end()-1, std::ostream_iterator<std::string>(os, " "));
132 os << *types.rbegin();
133 DefCompressionTypes = os.str();
134 }
135 }
136 bool const GzipIndex = _config->FindB("Acquire::GzipIndexes", false);
137 for (std::vector<debReleaseIndexPrivate::debSectionEntry>::const_iterator E = entries.begin(); E != entries.end(); ++E)
138 {
139 for (std::vector<std::string>::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T)
140 {
141 #define APT_T_CONFIG_STR(X, Y) _config->Find(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X), (Y))
142 #define APT_T_CONFIG_BOOL(X, Y) _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X), (Y))
143 std::string const tplMetaKey = APT_T_CONFIG_STR(flatArchive ? "flatMetaKey" : "MetaKey", "");
144 std::string const tplShortDesc = APT_T_CONFIG_STR("ShortDescription", "");
145 std::string const tplLongDesc = "$(SITE) " + APT_T_CONFIG_STR(flatArchive ? "flatDescription" : "Description", "");
146 bool const IsOptional = APT_T_CONFIG_BOOL("Optional", true);
147 bool const KeepCompressed = APT_T_CONFIG_BOOL("KeepCompressed", GzipIndex);
148 bool const DefaultEnabled = APT_T_CONFIG_BOOL("DefaultEnabled", true);
149 bool const UsePDiffs = APT_T_CONFIG_BOOL("PDiffs", E->UsePDiffs);
150 std::string const CompressionTypes = APT_T_CONFIG_STR("CompressionTypes", DefCompressionTypes);
151 #undef APT_T_CONFIG_BOOL
152 #undef APT_T_CONFIG_STR
153 if (tplMetaKey.empty())
154 continue;
155
156 for (std::vector<std::string>::const_iterator L = E->Languages.begin(); L != E->Languages.end(); ++L)
157 {
158 if (*L == "none" && tplMetaKey.find("$(LANGUAGE)") != std::string::npos)
159 continue;
160
161 for (std::vector<std::string>::const_iterator A = E->Architectures.begin(); A != E->Architectures.end(); ++A)
162 {
163 // available in templates
164 std::map<std::string, std::string> Options;
165 Options.insert(std::make_pair("SITE", Site));
166 Options.insert(std::make_pair("RELEASE", Release));
167 if (tplMetaKey.find("$(COMPONENT)") != std::string::npos)
168 Options.insert(std::make_pair("COMPONENT", E->Name));
169 if (tplMetaKey.find("$(LANGUAGE)") != std::string::npos)
170 Options.insert(std::make_pair("LANGUAGE", *L));
171 if (tplMetaKey.find("$(ARCHITECTURE)") != std::string::npos)
172 Options.insert(std::make_pair("ARCHITECTURE", *A));
173
174 std::string MetaKey = tplMetaKey;
175 std::string ShortDesc = tplShortDesc;
176 std::string LongDesc = tplLongDesc;
177 for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
178 {
179 MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second);
180 ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second);
181 LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second);
182 }
183
184 // not available in templates, but in the indextarget
185 Options.insert(std::make_pair("BASE_URI", baseURI));
186 Options.insert(std::make_pair("REPO_URI", URI));
187 Options.insert(std::make_pair("TARGET_OF", Type));
188 Options.insert(std::make_pair("CREATED_BY", *T));
189 Options.insert(std::make_pair("PDIFFS", UsePDiffs ? "yes" : "no"));
190 Options.insert(std::make_pair("DEFAULTENABLED", DefaultEnabled ? "yes" : "no"));
191 Options.insert(std::make_pair("COMPRESSIONTYPES", CompressionTypes));
192
193 IndexTarget Target(
194 MetaKey,
195 ShortDesc,
196 LongDesc,
197 Options.find("BASE_URI")->second + MetaKey,
198 IsOptional,
199 KeepCompressed,
200 Options
201 );
202 IndexTargets.push_back(Target);
203
204 if (tplMetaKey.find("$(ARCHITECTURE)") == std::string::npos)
205 break;
206
207 }
208
209 if (tplMetaKey.find("$(LANGUAGE)") == std::string::npos)
210 break;
211
212 }
213
214 }
215 }
216 }
217 std::vector<IndexTarget> debReleaseIndex::GetIndexTargets() const
218 {
219 std::vector<IndexTarget> IndexTargets;
220 GetIndexTargetsFor("deb-src", URI, Dist, d->DebSrcEntries, IndexTargets);
221 GetIndexTargetsFor("deb", URI, Dist, d->DebEntries, IndexTargets);
222 return IndexTargets;
223 }
224 /*}}}*/
225 void debReleaseIndex::AddComponent(bool const isSrc, std::string const &Name,/*{{{*/
226 std::vector<std::string> const &Targets,
227 std::vector<std::string> const &Architectures,
228 std::vector<std::string> Languages,
229 bool const usePDiffs)
230 {
231 if (Languages.empty() == true)
232 Languages.push_back("none");
233 debReleaseIndexPrivate::debSectionEntry const entry = {
234 Name, Targets, Architectures, Languages, usePDiffs
235 };
236 if (isSrc)
237 d->DebSrcEntries.push_back(entry);
238 else
239 d->DebEntries.push_back(entry);
240 }
241 /*}}}*/
242
243 bool debReleaseIndex::Load(std::string const &Filename, std::string * const ErrorText)/*{{{*/
244 {
245 LoadedSuccessfully = TRI_NO;
246 FileFd Fd;
247 if (OpenMaybeClearSignedFile(Filename, Fd) == false)
248 return false;
249
250 pkgTagFile TagFile(&Fd, Fd.Size());
251 if (_error->PendingError() == true)
252 {
253 if (ErrorText != NULL)
254 strprintf(*ErrorText, _("Unable to parse Release file %s"),Filename.c_str());
255 return false;
256 }
257
258 pkgTagSection Section;
259 const char *Start, *End;
260 if (TagFile.Step(Section) == false)
261 {
262 if (ErrorText != NULL)
263 strprintf(*ErrorText, _("No sections in Release file %s"), Filename.c_str());
264 return false;
265 }
266 // FIXME: find better tag name
267 SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false);
268
269 Suite = Section.FindS("Suite");
270 Codename = Section.FindS("Codename");
271
272 bool FoundHashSum = false;
273 for (int i=0;HashString::SupportedHashes()[i] != NULL; i++)
274 {
275 if (!Section.Find(HashString::SupportedHashes()[i], Start, End))
276 continue;
277
278 std::string Name;
279 std::string Hash;
280 unsigned long long Size;
281 while (Start < End)
282 {
283 if (!parseSumData(Start, End, Name, Hash, Size))
284 return false;
285
286 if (Entries.find(Name) == Entries.end())
287 {
288 metaIndex::checkSum *Sum = new metaIndex::checkSum;
289 Sum->MetaKeyFilename = Name;
290 Sum->Size = Size;
291 Sum->Hashes.FileSize(Size);
292 APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);)
293 Entries[Name] = Sum;
294 }
295 Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
296 FoundHashSum = true;
297 }
298 }
299
300 if(FoundHashSum == false)
301 {
302 if (ErrorText != NULL)
303 strprintf(*ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
304 return false;
305 }
306
307 std::string const StrDate = Section.FindS("Date");
308 if (RFC1123StrToTime(StrDate.c_str(), Date) == false)
309 {
310 if (ErrorText != NULL)
311 strprintf(*ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str());
312 return false;
313 }
314
315 bool CheckValidUntil = _config->FindB("Acquire::Check-Valid-Until", true);
316 if (d->CheckValidUntil == metaIndex::TRI_NO)
317 CheckValidUntil = false;
318 else if (d->CheckValidUntil == metaIndex::TRI_YES)
319 CheckValidUntil = true;
320
321 if (CheckValidUntil == true)
322 {
323 std::string const Label = Section.FindS("Label");
324 std::string const StrValidUntil = Section.FindS("Valid-Until");
325
326 // if we have a Valid-Until header in the Release file, use it as default
327 if (StrValidUntil.empty() == false)
328 {
329 if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false)
330 {
331 if (ErrorText != NULL)
332 strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str());
333 return false;
334 }
335 }
336 // get the user settings for this archive and use what expires earlier
337 time_t MaxAge = d->ValidUntilMax;
338 if (MaxAge == 0)
339 {
340 MaxAge = _config->FindI("Acquire::Max-ValidTime", 0);
341 if (Label.empty() == false)
342 MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge);
343 }
344 time_t MinAge = d->ValidUntilMin;
345 if (MinAge == 0)
346 {
347 MinAge = _config->FindI("Acquire::Min-ValidTime", 0);
348 if (Label.empty() == false)
349 MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge);
350 }
351
352 if (MinAge != 0 && ValidUntil != 0) {
353 time_t const min_date = Date + MinAge;
354 if (ValidUntil < min_date)
355 ValidUntil = min_date;
356 }
357 if (MaxAge != 0) {
358 time_t const max_date = Date + MaxAge;
359 if (ValidUntil == 0 || ValidUntil > max_date)
360 ValidUntil = max_date;
361 }
362 }
363
364 LoadedSuccessfully = TRI_YES;
365 return true;
366 }
367 /*}}}*/
368 metaIndex * debReleaseIndex::UnloadedClone() const /*{{{*/
369 {
370 if (Trusted == TRI_NO)
371 return new debReleaseIndex(URI, Dist, false);
372 else if (Trusted == TRI_YES)
373 return new debReleaseIndex(URI, Dist, true);
374 else
375 return new debReleaseIndex(URI, Dist);
376 }
377 /*}}}*/
378 bool debReleaseIndex::parseSumData(const char *&Start, const char *End, /*{{{*/
379 std::string &Name, std::string &Hash, unsigned long long &Size)
380 {
381 Name = "";
382 Hash = "";
383 Size = 0;
384 /* Skip over the first blank */
385 while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r')
386 && Start < End)
387 Start++;
388 if (Start >= End)
389 return false;
390
391 /* Move EntryEnd to the end of the first entry (the hash) */
392 const char *EntryEnd = Start;
393 while ((*EntryEnd != '\t' && *EntryEnd != ' ')
394 && EntryEnd < End)
395 EntryEnd++;
396 if (EntryEnd == End)
397 return false;
398
399 Hash.append(Start, EntryEnd-Start);
400
401 /* Skip over intermediate blanks */
402 Start = EntryEnd;
403 while (*Start == '\t' || *Start == ' ')
404 Start++;
405 if (Start >= End)
406 return false;
407
408 EntryEnd = Start;
409 /* Find the end of the second entry (the size) */
410 while ((*EntryEnd != '\t' && *EntryEnd != ' ' )
411 && EntryEnd < End)
412 EntryEnd++;
413 if (EntryEnd == End)
414 return false;
415
416 Size = strtoull (Start, NULL, 10);
417
418 /* Skip over intermediate blanks */
419 Start = EntryEnd;
420 while (*Start == '\t' || *Start == ' ')
421 Start++;
422 if (Start >= End)
423 return false;
424
425 EntryEnd = Start;
426 /* Find the end of the third entry (the filename) */
427 while ((*EntryEnd != '\t' && *EntryEnd != ' ' &&
428 *EntryEnd != '\n' && *EntryEnd != '\r')
429 && EntryEnd < End)
430 EntryEnd++;
431
432 Name.append(Start, EntryEnd-Start);
433 Start = EntryEnd; //prepare for the next round
434 return true;
435 }
436 /*}}}*/
437
438 bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/
439 {
440 std::vector<IndexTarget> const targets = GetIndexTargets();
441 #define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, false, std::map<std::string,std::string>())
442 pkgAcqMetaClearSig * const TransactionManager = new pkgAcqMetaClearSig(Owner,
443 APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"),
444 targets, this);
445 #undef APT_TARGET
446 // special case for --print-uris
447 if (GetAll)
448 for (auto const &Target: targets)
449 new pkgAcqIndex(Owner, TransactionManager, Target);
450
451 return true;
452 }
453 /*}}}*/
454 // ReleaseIndex::Set* TriState options /*{{{*/
455 bool debReleaseIndex::SetTrusted(TriState const pTrusted)
456 {
457 if (Trusted == TRI_UNSET)
458 Trusted = pTrusted;
459 else if (Trusted != pTrusted)
460 // TRANSLATOR: The first is an option name from sources.list manpage, the other two URI and Suite
461 return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str());
462 return true;
463 }
464 bool debReleaseIndex::SetCheckValidUntil(TriState const pCheckValidUntil)
465 {
466 if (d->CheckValidUntil == TRI_UNSET)
467 d->CheckValidUntil = pCheckValidUntil;
468 else if (d->CheckValidUntil != pCheckValidUntil)
469 return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Check-Valid-Until", URI.c_str(), Dist.c_str());
470 return true;
471 }
472 bool debReleaseIndex::SetValidUntilMin(time_t const Valid)
473 {
474 if (d->ValidUntilMin == 0)
475 d->ValidUntilMin = Valid;
476 else if (d->ValidUntilMin != Valid)
477 return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Min-ValidTime", URI.c_str(), Dist.c_str());
478 return true;
479 }
480 bool debReleaseIndex::SetValidUntilMax(time_t const Valid)
481 {
482 if (d->ValidUntilMax == 0)
483 d->ValidUntilMax = Valid;
484 else if (d->ValidUntilMax != Valid)
485 return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str());
486 return true;
487 }
488 bool debReleaseIndex::SetSignedBy(std::string const &pSignedBy)
489 {
490 if (SignedBy.empty() == true && pSignedBy.empty() == false)
491 {
492 if (pSignedBy[0] == '/') // no check for existence as we could be chrooting later or such things
493 ; // absolute path to a keyring file
494 else
495 {
496 // we could go all fancy and allow short/long/string matches as gpgv/apt-key does,
497 // but fingerprints are harder to fake than the others and this option is set once,
498 // not interactively all the time so easy to type is not really a concern.
499 std::string finger = pSignedBy;
500 finger.erase(std::remove(finger.begin(), finger.end(), ' '), finger.end());
501 std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper);
502 if (finger.length() != 40 || finger.find_first_not_of("0123456789ABCDEF") != std::string::npos)
503 return _error->Error(_("Invalid value set for option %s concerning source %s %s (%s)"), "Signed-By", URI.c_str(), Dist.c_str(), "not a fingerprint");
504 }
505 SignedBy = pSignedBy;
506 }
507 else if (SignedBy != pSignedBy)
508 return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Signed-By", URI.c_str(), Dist.c_str());
509 return true;
510 }
511 /*}}}*/
512 // ReleaseIndex::IsTrusted /*{{{*/
513 bool debReleaseIndex::IsTrusted() const
514 {
515 if (Trusted == TRI_YES)
516 return true;
517 else if (Trusted == TRI_NO)
518 return false;
519
520
521 if(_config->FindB("APT::Authentication::TrustCDROM", false))
522 if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
523 return true;
524
525 if (FileExists(MetaIndexFile("Release.gpg")))
526 return true;
527
528 return FileExists(MetaIndexFile("InRelease"));
529 }
530 /*}}}*/
531 std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() /*{{{*/
532 {
533 if (Indexes != NULL)
534 return Indexes;
535
536 Indexes = new std::vector<pkgIndexFile*>();
537 bool const istrusted = IsTrusted();
538 for (auto const &T: GetIndexTargets())
539 {
540 std::string const TargetName = T.Option(IndexTarget::CREATED_BY);
541 if (TargetName == "Packages")
542 Indexes->push_back(new debPackagesIndex(T, istrusted));
543 else if (TargetName == "Sources")
544 Indexes->push_back(new debSourcesIndex(T, istrusted));
545 else if (TargetName == "Translations")
546 Indexes->push_back(new debTranslationsIndex(T));
547 }
548 return Indexes;
549 }
550 /*}}}*/
551
552 static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile)/*{{{*/
553 {
554 ReleaseFile = That->MetaIndexFile("InRelease");
555 bool releaseExists = false;
556 if (FileExists(ReleaseFile) == true)
557 releaseExists = true;
558 else
559 {
560 ReleaseFile = That->MetaIndexFile("Release");
561 if (FileExists(ReleaseFile))
562 releaseExists = true;
563 }
564 return releaseExists;
565 }
566 /*}}}*/
567 bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/
568 {
569 std::string ReleaseFile;
570 bool const releaseExists = ReleaseFileName(this, ReleaseFile);
571
572 ::URI Tmp(URI);
573 if (Gen.SelectReleaseFile(ReleaseFile, Tmp.Host) == false)
574 return _error->Error("Problem with SelectReleaseFile %s", ReleaseFile.c_str());
575
576 if (releaseExists == false)
577 return true;
578
579 FileFd Rel;
580 // Beware: The 'Release' file might be clearsigned in case the
581 // signature for an 'InRelease' file couldn't be checked
582 if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
583 return false;
584 if (_error->PendingError() == true)
585 return false;
586
587 // Store the IMS information
588 pkgCache::RlsFileIterator File = Gen.GetCurRlsFile();
589 pkgCacheGenerator::Dynamic<pkgCache::RlsFileIterator> DynFile(File);
590 // Rel can't be used as this is potentially a temporary file
591 struct stat Buf;
592 if (stat(ReleaseFile.c_str(), &Buf) != 0)
593 return _error->Errno("fstat", "Unable to stat file %s", ReleaseFile.c_str());
594 File->Size = Buf.st_size;
595 File->mtime = Buf.st_mtime;
596
597 pkgTagFile TagFile(&Rel, Rel.Size());
598 pkgTagSection Section;
599 if (_error->PendingError() == true || TagFile.Step(Section) == false)
600 return false;
601
602 std::string data;
603 #define APT_INRELEASE(TYPE, TAG, STORE) \
604 data = Section.FindS(TAG); \
605 if (data.empty() == false) \
606 { \
607 map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::TYPE, data); \
608 STORE = storage; \
609 }
610 APT_INRELEASE(MIXED, "Suite", File->Archive)
611 APT_INRELEASE(VERSIONNUMBER, "Version", File->Version)
612 APT_INRELEASE(MIXED, "Origin", File->Origin)
613 APT_INRELEASE(MIXED, "Codename", File->Codename)
614 APT_INRELEASE(MIXED, "Label", File->Label)
615 #undef APT_INRELEASE
616 Section.FindFlag("NotAutomatic", File->Flags, pkgCache::Flag::NotAutomatic);
617 Section.FindFlag("ButAutomaticUpgrades", File->Flags, pkgCache::Flag::ButAutomaticUpgrades);
618
619 return !_error->PendingError();
620 }
621 /*}}}*/
622 // ReleaseIndex::FindInCache - Find this index /*{{{*/
623 pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool const ModifyCheck) const
624 {
625 std::string ReleaseFile;
626 bool const releaseExists = ReleaseFileName(this, ReleaseFile);
627
628 pkgCache::RlsFileIterator File = Cache.RlsFileBegin();
629 for (; File.end() == false; ++File)
630 {
631 if (File->FileName == 0 || ReleaseFile != File.FileName())
632 continue;
633
634 // empty means the file does not exist by "design"
635 if (ModifyCheck == false || (releaseExists == false && File->Size == 0))
636 return File;
637
638 struct stat St;
639 if (stat(File.FileName(),&St) != 0)
640 {
641 if (_config->FindB("Debug::pkgCacheGen", false))
642 std::clog << "ReleaseIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
643 return pkgCache::RlsFileIterator(Cache);
644 }
645 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
646 {
647 if (_config->FindB("Debug::pkgCacheGen", false))
648 std::clog << "ReleaseIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
649 << ") or mtime (" << St.st_mtime << " <> " << File->mtime
650 << ") doesn't match for " << File.FileName() << std::endl;
651 return pkgCache::RlsFileIterator(Cache);
652 }
653 return File;
654 }
655
656 return File;
657 }
658 /*}}}*/
659
660 static std::vector<std::string> parsePlusMinusOptions(std::string const &Name, /*{{{*/
661 std::map<std::string, std::string> const &Options, std::vector<std::string> const &defaultValues)
662 {
663 std::map<std::string, std::string>::const_iterator val = Options.find(Name);
664 std::vector<std::string> Values;
665 if (val != Options.end())
666 Values = VectorizeString(val->second, ',');
667 else
668 Values = defaultValues;
669
670 if ((val = Options.find(Name + "+")) != Options.end())
671 {
672 std::vector<std::string> const plus = VectorizeString(val->second, ',');
673 std::copy_if(plus.begin(), plus.end(), std::back_inserter(Values), [&Values](std::string const &v) {
674 return std::find(Values.begin(), Values.end(), v) == Values.end();
675 });
676 }
677 if ((val = Options.find(Name + "-")) != Options.end())
678 {
679 std::vector<std::string> const minus = VectorizeString(val->second, ',');
680 Values.erase(std::remove_if(Values.begin(), Values.end(), [&minus](std::string const &v) {
681 return std::find(minus.begin(), minus.end(), v) != minus.end();
682 }), Values.end());
683 }
684 return Values;
685 }
686 /*}}}*/
687 class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/
688 {
689 metaIndex::TriState GetTriStateOption(std::map<std::string, std::string>const &Options, char const * const name) const
690 {
691 std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
692 if (opt != Options.end())
693 return StringToBool(opt->second, false) ? metaIndex::TRI_YES : metaIndex::TRI_NO;
694 return metaIndex::TRI_DONTCARE;
695 }
696
697 time_t GetTimeOption(std::map<std::string, std::string>const &Options, char const * const name) const
698 {
699 std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
700 if (opt == Options.end())
701 return 0;
702 return strtoull(opt->second.c_str(), NULL, 10);
703 }
704
705 protected:
706
707 bool CreateItemInternal(std::vector<metaIndex *> &List, std::string const &URI,
708 std::string const &Dist, std::string const &Section,
709 bool const &IsSrc, std::map<std::string, std::string> const &Options) const
710 {
711 debReleaseIndex *Deb = NULL;
712 for (std::vector<metaIndex *>::const_iterator I = List.begin();
713 I != List.end(); ++I)
714 {
715 // We only worry about debian entries here
716 if (strcmp((*I)->GetType(), "deb") != 0)
717 continue;
718
719 /* This check insures that there will be only one Release file
720 queued for all the Packages files and Sources files it
721 corresponds to. */
722 if ((*I)->GetURI() == URI && (*I)->GetDist() == Dist)
723 {
724 Deb = dynamic_cast<debReleaseIndex*>(*I);
725 if (Deb != NULL)
726 break;
727 }
728 }
729
730 // No currently created Release file indexes this entry, so we create a new one.
731 if (Deb == NULL)
732 {
733 Deb = new debReleaseIndex(URI, Dist);
734 List.push_back(Deb);
735 }
736
737 std::vector<std::string> const alltargets = _config->FindVector(std::string("Acquire::IndexTargets::") + Name, "", true);
738 std::vector<std::string> deftargets;
739 deftargets.reserve(alltargets.size());
740 std::copy_if(alltargets.begin(), alltargets.end(), std::back_inserter(deftargets), [&](std::string const &t) {
741 std::string c = "Acquire::IndexTargets::";
742 c.append(Name).append("::").append(t).append("::DefaultEnabled");
743 return _config->FindB(c, true);
744 });
745 std::vector<std::string> mytargets = parsePlusMinusOptions("target", Options, deftargets);
746 for (auto const &target : alltargets)
747 {
748 std::map<std::string, std::string>::const_iterator const opt = Options.find(target);
749 if (opt == Options.end())
750 continue;
751 auto const tarItr = std::find(mytargets.begin(), mytargets.end(), target);
752 bool const optValue = StringToBool(opt->second);
753 if (optValue == true && tarItr == mytargets.end())
754 mytargets.push_back(target);
755 else if (optValue == false && tarItr != mytargets.end())
756 mytargets.erase(std::remove(mytargets.begin(), mytargets.end(), target), mytargets.end());
757 }
758
759 bool UsePDiffs = _config->FindB("Acquire::PDiffs", true);
760 {
761 std::map<std::string, std::string>::const_iterator const opt = Options.find("pdiffs");
762 if (opt != Options.end())
763 UsePDiffs = StringToBool(opt->second);
764 }
765
766 Deb->AddComponent(
767 IsSrc,
768 Section,
769 mytargets,
770 parsePlusMinusOptions("arch", Options, APT::Configuration::getArchitectures()),
771 parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)),
772 UsePDiffs
773 );
774
775 if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false ||
776 Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false ||
777 Deb->SetValidUntilMax(GetTimeOption(Options, "valid-until-max")) == false ||
778 Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false)
779 return false;
780
781 std::map<std::string, std::string>::const_iterator const signedby = Options.find("signed-by");
782 if (signedby == Options.end())
783 {
784 if (Deb->SetSignedBy("") == false)
785 return false;
786 }
787 else
788 {
789 if (Deb->SetSignedBy(signedby->second) == false)
790 return false;
791 }
792
793 return true;
794 }
795
796 debSLTypeDebian(char const * const Name, char const * const Label) : Type(Name, Label)
797 {
798 }
799 };
800 /*}}}*/
801 class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian /*{{{*/
802 {
803 public:
804
805 bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
806 std::string const &Dist, std::string const &Section,
807 std::map<std::string, std::string> const &Options) const APT_OVERRIDE
808 {
809 return CreateItemInternal(List, URI, Dist, Section, false, Options);
810 }
811
812 debSLTypeDeb() : debSLTypeDebian("deb", "Debian binary tree")
813 {
814 }
815 };
816 /*}}}*/
817 class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian /*{{{*/
818 {
819 public:
820
821 bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
822 std::string const &Dist, std::string const &Section,
823 std::map<std::string, std::string> const &Options) const APT_OVERRIDE
824 {
825 return CreateItemInternal(List, URI, Dist, Section, true, Options);
826 }
827
828 debSLTypeDebSrc() : debSLTypeDebian("deb-src", "Debian source tree")
829 {
830 }
831 };
832 /*}}}*/
833
834 APT_HIDDEN debSLTypeDeb _apt_DebType;
835 APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType;