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