]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
- backport forgotten Valid-Until patch from the obsolete experimental
[apt.git] / apt-pkg / deb / deblistparser.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $
4 /* ######################################################################
5
6 Package Cache Generator - Generator for the cache structure.
7
8 This builds the cache structure from the abstract package list parser.
9
10 ##################################################################### */
11 /*}}}*/
12 // Include Files /*{{{*/
13 #include <apt-pkg/deblistparser.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/configuration.h>
16 #include <apt-pkg/aptconfiguration.h>
17 #include <apt-pkg/strutl.h>
18 #include <apt-pkg/crc-16.h>
19 #include <apt-pkg/md5.h>
20 #include <apt-pkg/macros.h>
21
22 #include <ctype.h>
23 /*}}}*/
24
25 static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Important},
26 {"required",pkgCache::State::Required},
27 {"standard",pkgCache::State::Standard},
28 {"optional",pkgCache::State::Optional},
29 {"extra",pkgCache::State::Extra},
30 {}};
31
32 // ListParser::debListParser - Constructor /*{{{*/
33 // ---------------------------------------------------------------------
34 /* Provide an architecture and only this one and "all" will be accepted
35 in Step(), if no Architecture is given we will accept every arch
36 we would accept in general with checkArchitecture() */
37 debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
38 Arch(Arch) {
39 if (Arch == "native")
40 this->Arch = _config->Find("APT::Architecture");
41 }
42 /*}}}*/
43 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
44 // ---------------------------------------------------------------------
45 /* */
46 unsigned long debListParser::UniqFindTagWrite(const char *Tag)
47 {
48 const char *Start;
49 const char *Stop;
50 if (Section.Find(Tag,Start,Stop) == false)
51 return 0;
52 return WriteUniqString(Start,Stop - Start);
53 }
54 /*}}}*/
55 // ListParser::Package - Return the package name /*{{{*/
56 // ---------------------------------------------------------------------
57 /* This is to return the name of the package this section describes */
58 string debListParser::Package() {
59 string const Result = Section.FindS("Package");
60 if(unlikely(Result.empty() == true))
61 _error->Error("Encountered a section with no Package: header");
62 return Result;
63 }
64 /*}}}*/
65 // ListParser::Architecture - Return the package arch /*{{{*/
66 // ---------------------------------------------------------------------
67 /* This will return the Architecture of the package this section describes
68 Note that architecture "all" packages will get the architecture of the
69 Packages file parsed here. */
70 string debListParser::Architecture() {
71 string const Result = Section.FindS("Architecture");
72 if (Result.empty() == true || Result == "all")
73 {
74 if (Arch.empty() == true)
75 /* FIXME: this is a problem for installed arch all
76 packages as we don't know from which arch this
77 package was installed - and therefore which
78 dependency this package resolves. */
79 return _config->Find("APT::Architecture");
80 else
81 return Arch;
82 }
83 return Result;
84 }
85 /*}}}*/
86 // ListParser::ArchitectureAll /*{{{*/
87 // ---------------------------------------------------------------------
88 /* */
89 bool debListParser::ArchitectureAll() {
90 return Section.FindS("Architecture") == "all";
91 }
92 /*}}}*/
93 // ListParser::Version - Return the version string /*{{{*/
94 // ---------------------------------------------------------------------
95 /* This is to return the string describing the version in debian form,
96 epoch:upstream-release. If this returns the blank string then the
97 entry is assumed to only describe package properties */
98 string debListParser::Version()
99 {
100 return Section.FindS("Version");
101 }
102 /*}}}*/
103 // ListParser::NewVersion - Fill in the version structure /*{{{*/
104 // ---------------------------------------------------------------------
105 /* */
106 bool debListParser::NewVersion(pkgCache::VerIterator Ver)
107 {
108 // Parse the section
109 Ver->Section = UniqFindTagWrite("Section");
110
111 // Parse multi-arch
112 if (Section.FindS("Architecture") == "all")
113 /* Arch all packages can't have a Multi-Arch field,
114 but we need a special treatment for them nonetheless */
115 Ver->MultiArch = pkgCache::Version::All;
116 else
117 {
118 string const MultiArch = Section.FindS("Multi-Arch");
119 if (MultiArch.empty() == true)
120 Ver->MultiArch = pkgCache::Version::None;
121 else if (MultiArch == "same")
122 Ver->MultiArch = pkgCache::Version::Same;
123 else if (MultiArch == "foreign")
124 Ver->MultiArch = pkgCache::Version::Foreign;
125 else if (MultiArch == "allowed")
126 Ver->MultiArch = pkgCache::Version::Allowed;
127 else
128 {
129 _error->Warning("Unknown Multi-Arch type »%s« for package »%s«",
130 MultiArch.c_str(), Section.FindS("Package").c_str());
131 Ver->MultiArch = pkgCache::Version::None;
132 }
133 }
134
135 // Archive Size
136 Ver->Size = Section.FindULL("Size");
137 // Unpacked Size (in K)
138 Ver->InstalledSize = Section.FindULL("Installed-Size");
139 Ver->InstalledSize *= 1024;
140
141 // Priority
142 const char *Start;
143 const char *Stop;
144 if (Section.Find("Priority",Start,Stop) == true)
145 {
146 if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
147 Ver->Priority = pkgCache::State::Extra;
148 }
149
150 if (Ver->MultiArch == pkgCache::Version::All)
151 {
152 /* We maintain a "pseudo" arch=all package for architecture all versions
153 on which these versions can depend on. This pseudo package is many used
154 for downloading/installing: The other pseudo-packages will degenerate
155 to a NOP in the download/install step - this package will ensure that
156 it is downloaded only one time and installed only one time -- even if
157 the architecture bound versions coming in and out on regular basis. */
158 bool const static multiArch = APT::Configuration::getArchitectures().size() > 1;
159 if (strcmp(Ver.Arch(true),"all") == 0)
160 return true;
161 else if (multiArch == true)
162 {
163 // our pseudo packages have no size to not confuse the fetcher
164 Ver->Size = 0;
165 Ver->InstalledSize = 0;
166 }
167 }
168
169 if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
170 return false;
171 if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
172 return false;
173 if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
174 return false;
175 if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
176 return false;
177 if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
178 return false;
179 if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
180 return false;
181 if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
182 return false;
183 if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false)
184 return false;
185
186 // Obsolete.
187 if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
188 return false;
189
190 if (ParseProvides(Ver) == false)
191 return false;
192
193 return true;
194 }
195 /*}}}*/
196 // ListParser::Description - Return the description string /*{{{*/
197 // ---------------------------------------------------------------------
198 /* This is to return the string describing the package in debian
199 form. If this returns the blank string then the entry is assumed to
200 only describe package properties */
201 string debListParser::Description()
202 {
203 string const lang = DescriptionLanguage();
204 if (lang.empty())
205 return Section.FindS("Description");
206 else
207 return Section.FindS(string("Description-").append(lang).c_str());
208 }
209 /*}}}*/
210 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
211 // ---------------------------------------------------------------------
212 /* This is to return the string describing the language of
213 description. If this returns the blank string then the entry is
214 assumed to describe original description. */
215 string debListParser::DescriptionLanguage()
216 {
217 if (Section.FindS("Description").empty() == false)
218 return "";
219
220 std::vector<string> const lang = APT::Configuration::getLanguages();
221 for (std::vector<string>::const_iterator l = lang.begin();
222 l != lang.end(); l++)
223 if (Section.FindS(string("Description-").append(*l).c_str()).empty() == false)
224 return *l;
225
226 return "";
227 }
228 /*}}}*/
229 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
230 // ---------------------------------------------------------------------
231 /* This is to return the md5 string to allow the check if it is the right
232 description. If no Description-md5 is found in the section it will be
233 calculated.
234 */
235 MD5SumValue debListParser::Description_md5()
236 {
237 string value = Section.FindS("Description-md5");
238
239 if (value.empty())
240 {
241 MD5Summation md5;
242 md5.Add((Description() + "\n").c_str());
243 return md5.Result();
244 } else
245 return MD5SumValue(value);
246 }
247 /*}}}*/
248 // ListParser::UsePackage - Update a package structure /*{{{*/
249 // ---------------------------------------------------------------------
250 /* This is called to update the package with any new information
251 that might be found in the section */
252 bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
253 pkgCache::VerIterator Ver)
254 {
255 if (Pkg->Section == 0)
256 Pkg->Section = UniqFindTagWrite("Section");
257
258 // Packages which are not from the "native" arch doesn't get the essential flag
259 // in the default "native" mode - it is also possible to mark "all" or "none".
260 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
261 string const static myArch = _config->Find("APT::Architecture");
262 string const static essential = _config->Find("pkgCacheGen::Essential", "native");
263 if ((essential == "native" && Pkg->Arch != 0 && myArch == Pkg.Arch()) ||
264 essential == "all")
265 if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
266 return false;
267 if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
268 return false;
269
270 if (strcmp(Pkg.Name(),"apt") == 0)
271 Pkg->Flags |= pkgCache::Flag::Important;
272
273 if (ParseStatus(Pkg,Ver) == false)
274 return false;
275 return true;
276 }
277 /*}}}*/
278 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
279 // ---------------------------------------------------------------------
280 /* */
281 unsigned short debListParser::VersionHash()
282 {
283 const char *Sections[] ={"Installed-Size",
284 "Depends",
285 "Pre-Depends",
286 // "Suggests",
287 // "Recommends",
288 "Conflicts",
289 "Breaks",
290 "Replaces",0};
291 unsigned long Result = INIT_FCS;
292 char S[1024];
293 for (const char **I = Sections; *I != 0; I++)
294 {
295 const char *Start;
296 const char *End;
297 if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
298 continue;
299
300 /* Strip out any spaces from the text, this undoes dpkgs reformatting
301 of certain fields. dpkg also has the rather interesting notion of
302 reformatting depends operators < -> <= */
303 char *I = S;
304 for (; Start != End; Start++)
305 {
306 if (isspace(*Start) == 0)
307 *I++ = tolower_ascii(*Start);
308 if (*Start == '<' && Start[1] != '<' && Start[1] != '=')
309 *I++ = '=';
310 if (*Start == '>' && Start[1] != '>' && Start[1] != '=')
311 *I++ = '=';
312 }
313
314 Result = AddCRC16(Result,S,I - S);
315 }
316
317 return Result;
318 }
319 /*}}}*/
320 // ListParser::ParseStatus - Parse the status field /*{{{*/
321 // ---------------------------------------------------------------------
322 /* Status lines are of the form,
323 Status: want flag status
324 want = unknown, install, hold, deinstall, purge
325 flag = ok, reinstreq, hold, hold-reinstreq
326 status = not-installed, unpacked, half-configured,
327 half-installed, config-files, post-inst-failed,
328 removal-failed, installed
329
330 Some of the above are obsolete (I think?) flag = hold-* and
331 status = post-inst-failed, removal-failed at least.
332 */
333 bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
334 pkgCache::VerIterator Ver)
335 {
336 const char *Start;
337 const char *Stop;
338 if (Section.Find("Status",Start,Stop) == false)
339 return true;
340
341 // UsePackage() is responsible for setting the flag in the default case
342 bool const static essential = _config->Find("pkgCacheGen::Essential", "") == "installed";
343 if (essential == true &&
344 Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
345 return false;
346
347 // Isolate the first word
348 const char *I = Start;
349 for(; I < Stop && *I != ' '; I++);
350 if (I >= Stop || *I != ' ')
351 return _error->Error("Malformed Status line");
352
353 // Process the want field
354 WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
355 {"install",pkgCache::State::Install},
356 {"hold",pkgCache::State::Hold},
357 {"deinstall",pkgCache::State::DeInstall},
358 {"purge",pkgCache::State::Purge},
359 {}};
360 if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
361 return _error->Error("Malformed 1st word in the Status line");
362
363 // Isloate the next word
364 I++;
365 Start = I;
366 for(; I < Stop && *I != ' '; I++);
367 if (I >= Stop || *I != ' ')
368 return _error->Error("Malformed status line, no 2nd word");
369
370 // Process the flag field
371 WordList FlagList[] = {{"ok",pkgCache::State::Ok},
372 {"reinstreq",pkgCache::State::ReInstReq},
373 {"hold",pkgCache::State::HoldInst},
374 {"hold-reinstreq",pkgCache::State::HoldReInstReq},
375 {}};
376 if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
377 return _error->Error("Malformed 2nd word in the Status line");
378
379 // Isloate the last word
380 I++;
381 Start = I;
382 for(; I < Stop && *I != ' '; I++);
383 if (I != Stop)
384 return _error->Error("Malformed Status line, no 3rd word");
385
386 // Process the flag field
387 WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
388 {"unpacked",pkgCache::State::UnPacked},
389 {"half-configured",pkgCache::State::HalfConfigured},
390 {"installed",pkgCache::State::Installed},
391 {"half-installed",pkgCache::State::HalfInstalled},
392 {"config-files",pkgCache::State::ConfigFiles},
393 {"triggers-awaited",pkgCache::State::TriggersAwaited},
394 {"triggers-pending",pkgCache::State::TriggersPending},
395 {"post-inst-failed",pkgCache::State::HalfConfigured},
396 {"removal-failed",pkgCache::State::HalfInstalled},
397 {}};
398 if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
399 return _error->Error("Malformed 3rd word in the Status line");
400
401 /* A Status line marks the package as indicating the current
402 version as well. Only if it is actually installed.. Otherwise
403 the interesting dpkg handling of the status file creates bogus
404 entries. */
405 if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
406 Pkg->CurrentState == pkgCache::State::ConfigFiles))
407 {
408 if (Ver.end() == true)
409 _error->Warning("Encountered status field in a non-version description");
410 else
411 Pkg->CurrentVer = Ver.Index();
412 }
413
414 return true;
415 }
416
417 const char *debListParser::ConvertRelation(const char *I,unsigned int &Op)
418 {
419 // Determine the operator
420 switch (*I)
421 {
422 case '<':
423 I++;
424 if (*I == '=')
425 {
426 I++;
427 Op = pkgCache::Dep::LessEq;
428 break;
429 }
430
431 if (*I == '<')
432 {
433 I++;
434 Op = pkgCache::Dep::Less;
435 break;
436 }
437
438 // < is the same as <= and << is really Cs < for some reason
439 Op = pkgCache::Dep::LessEq;
440 break;
441
442 case '>':
443 I++;
444 if (*I == '=')
445 {
446 I++;
447 Op = pkgCache::Dep::GreaterEq;
448 break;
449 }
450
451 if (*I == '>')
452 {
453 I++;
454 Op = pkgCache::Dep::Greater;
455 break;
456 }
457
458 // > is the same as >= and >> is really Cs > for some reason
459 Op = pkgCache::Dep::GreaterEq;
460 break;
461
462 case '=':
463 Op = pkgCache::Dep::Equals;
464 I++;
465 break;
466
467 // HACK around bad package definitions
468 default:
469 Op = pkgCache::Dep::Equals;
470 break;
471 }
472 return I;
473 }
474
475 /*}}}*/
476 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
477 // ---------------------------------------------------------------------
478 /* This parses the dependency elements out of a standard string in place,
479 bit by bit. */
480 const char *debListParser::ParseDepends(const char *Start,const char *Stop,
481 string &Package,string &Ver,
482 unsigned int &Op, bool const &ParseArchFlags,
483 bool const &StripMultiArch)
484 {
485 // Strip off leading space
486 for (;Start != Stop && isspace(*Start) != 0; Start++);
487
488 // Parse off the package name
489 const char *I = Start;
490 for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
491 *I != ',' && *I != '|'; I++);
492
493 // Malformed, no '('
494 if (I != Stop && *I == ')')
495 return 0;
496
497 if (I == Start)
498 return 0;
499
500 // Stash the package name
501 Package.assign(Start,I - Start);
502
503 // We don't want to confuse library users which can't handle MultiArch
504 if (StripMultiArch == true) {
505 size_t const found = Package.rfind(':');
506 if (found != string::npos)
507 Package = Package.substr(0,found);
508 }
509
510 // Skip white space to the '('
511 for (;I != Stop && isspace(*I) != 0 ; I++);
512
513 // Parse a version
514 if (I != Stop && *I == '(')
515 {
516 // Skip the '('
517 for (I++; I != Stop && isspace(*I) != 0 ; I++);
518 if (I + 3 >= Stop)
519 return 0;
520 I = ConvertRelation(I,Op);
521
522 // Skip whitespace
523 for (;I != Stop && isspace(*I) != 0; I++);
524 Start = I;
525 for (;I != Stop && *I != ')'; I++);
526 if (I == Stop || Start == I)
527 return 0;
528
529 // Skip trailing whitespace
530 const char *End = I;
531 for (; End > Start && isspace(End[-1]); End--);
532
533 Ver.assign(Start,End-Start);
534 I++;
535 }
536 else
537 {
538 Ver.clear();
539 Op = pkgCache::Dep::NoOp;
540 }
541
542 // Skip whitespace
543 for (;I != Stop && isspace(*I) != 0; I++);
544
545 if (ParseArchFlags == true)
546 {
547 string arch = _config->Find("APT::Architecture");
548
549 // Parse an architecture
550 if (I != Stop && *I == '[')
551 {
552 // malformed
553 I++;
554 if (I == Stop)
555 return 0;
556
557 const char *End = I;
558 bool Found = false;
559 bool NegArch = false;
560 while (I != Stop)
561 {
562 // look for whitespace or ending ']'
563 while (End != Stop && !isspace(*End) && *End != ']')
564 End++;
565
566 if (End == Stop)
567 return 0;
568
569 if (*I == '!')
570 {
571 NegArch = true;
572 I++;
573 }
574
575 if (stringcmp(arch,I,End) == 0)
576 Found = true;
577
578 if (*End++ == ']') {
579 I = End;
580 break;
581 }
582
583 I = End;
584 for (;I != Stop && isspace(*I) != 0; I++);
585 }
586
587 if (NegArch)
588 Found = !Found;
589
590 if (Found == false)
591 Package = ""; /* not for this arch */
592 }
593
594 // Skip whitespace
595 for (;I != Stop && isspace(*I) != 0; I++);
596 }
597
598 if (I != Stop && *I == '|')
599 Op |= pkgCache::Dep::Or;
600
601 if (I == Stop || *I == ',' || *I == '|')
602 {
603 if (I != Stop)
604 for (I++; I != Stop && isspace(*I) != 0; I++);
605 return I;
606 }
607
608 return 0;
609 }
610 /*}}}*/
611 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
612 // ---------------------------------------------------------------------
613 /* This is the higher level depends parser. It takes a tag and generates
614 a complete depends tree for the given version. */
615 bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
616 const char *Tag,unsigned int Type)
617 {
618 const char *Start;
619 const char *Stop;
620 if (Section.Find(Tag,Start,Stop) == false)
621 return true;
622
623 static std::vector<std::string> const archs = APT::Configuration::getArchitectures();
624 static bool const multiArch = archs.size() <= 1;
625
626 string Package;
627 string const pkgArch = Ver.Arch(true);
628 string Version;
629 unsigned int Op;
630
631 while (1)
632 {
633 Start = ParseDepends(Start,Stop,Package,Version,Op);
634 if (Start == 0)
635 return _error->Error("Problem parsing dependency %s",Tag);
636
637 if (multiArch == true &&
638 (Type == pkgCache::Dep::Conflicts ||
639 Type == pkgCache::Dep::DpkgBreaks ||
640 Type == pkgCache::Dep::Replaces))
641 {
642 for (std::vector<std::string>::const_iterator a = archs.begin();
643 a != archs.end(); ++a)
644 if (NewDepends(Ver,Package,*a,Version,Op,Type) == false)
645 return false;
646 }
647 else if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
648 return false;
649 if (Start == Stop)
650 break;
651 }
652 return true;
653 }
654 /*}}}*/
655 // ListParser::ParseProvides - Parse the provides list /*{{{*/
656 // ---------------------------------------------------------------------
657 /* */
658 bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
659 {
660 const char *Start;
661 const char *Stop;
662 if (Section.Find("Provides",Start,Stop) == true)
663 {
664 string Package;
665 string Version;
666 string const Arch = Ver.Arch(true);
667 unsigned int Op;
668
669 while (1)
670 {
671 Start = ParseDepends(Start,Stop,Package,Version,Op);
672 if (Start == 0)
673 return _error->Error("Problem parsing Provides line");
674 if (Op != pkgCache::Dep::NoOp) {
675 _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str());
676 } else {
677 if (NewProvides(Ver, Package, Arch, Version) == false)
678 return false;
679 }
680
681 if (Start == Stop)
682 break;
683 }
684 }
685
686 if (Ver->MultiArch == pkgCache::Version::Allowed)
687 {
688 string const Package = string(Ver.ParentPkg().Name()).append(":").append("any");
689 NewProvides(Ver, Package, "any", Ver.VerStr());
690 }
691
692 if (Ver->MultiArch != pkgCache::Version::Foreign)
693 return true;
694
695 std::vector<string> const archs = APT::Configuration::getArchitectures();
696 if (archs.size() <= 1)
697 return true;
698
699 string const Package = Ver.ParentPkg().Name();
700 string const Version = Ver.VerStr();
701 for (std::vector<string>::const_iterator a = archs.begin();
702 a != archs.end(); ++a)
703 {
704 if (NewProvides(Ver, Package, *a, Version) == false)
705 return false;
706 }
707
708 return true;
709 }
710 /*}}}*/
711 // ListParser::GrabWord - Matches a word and returns /*{{{*/
712 // ---------------------------------------------------------------------
713 /* Looks for a word in a list of words - for ParseStatus */
714 bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
715 {
716 for (unsigned int C = 0; List[C].Str != 0; C++)
717 {
718 if (strcasecmp(Word.c_str(),List[C].Str) == 0)
719 {
720 Out = List[C].Val;
721 return true;
722 }
723 }
724 return false;
725 }
726 /*}}}*/
727 // ListParser::Step - Move to the next section in the file /*{{{*/
728 // ---------------------------------------------------------------------
729 /* This has to be carefull to only process the correct architecture */
730 bool debListParser::Step()
731 {
732 iOffset = Tags.Offset();
733 while (Tags.Step(Section) == true)
734 {
735 /* See if this is the correct Architecture, if it isn't then we
736 drop the whole section. A missing arch tag only happens (in theory)
737 inside the Status file, so that is a positive return */
738 string const Architecture = Section.FindS("Architecture");
739 if (Architecture.empty() == true)
740 return true;
741
742 if (Arch.empty() == true)
743 {
744 if (APT::Configuration::checkArchitecture(Architecture) == true)
745 return true;
746 }
747 else
748 {
749 if (Architecture == Arch)
750 return true;
751
752 if (Architecture == "all")
753 return true;
754 }
755
756 iOffset = Tags.Offset();
757 }
758 return false;
759 }
760 /*}}}*/
761 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
762 // ---------------------------------------------------------------------
763 /* */
764 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
765 FileFd &File, string component)
766 {
767 pkgTagFile Tags(&File, File.Size() + 256); // XXX
768 pkgTagSection Section;
769 if (Tags.Step(Section) == false)
770 return false;
771
772 // FIXME: Do we need it now for multi-arch?
773 // mvo: I don't think we need to fill that in (it's unused since apt-0.6)
774 // FileI->Architecture = WriteUniqString(Arch);
775
776 // apt-secure does no longer download individual (per-section) Release
777 // file. to provide Component pinning we use the section name now
778 FileI->Component = WriteUniqString(component);
779
780 const char *Start;
781 const char *Stop;
782 if (Section.Find("Suite",Start,Stop) == true)
783 FileI->Archive = WriteUniqString(Start,Stop - Start);
784 if (Section.Find("Component",Start,Stop) == true)
785 FileI->Component = WriteUniqString(Start,Stop - Start);
786 if (Section.Find("Version",Start,Stop) == true)
787 FileI->Version = WriteUniqString(Start,Stop - Start);
788 if (Section.Find("Origin",Start,Stop) == true)
789 FileI->Origin = WriteUniqString(Start,Stop - Start);
790 if (Section.Find("Codename",Start,Stop) == true)
791 FileI->Codename = WriteUniqString(Start,Stop - Start);
792 if (Section.Find("Label",Start,Stop) == true)
793 FileI->Label = WriteUniqString(Start,Stop - Start);
794 if (Section.Find("Architecture",Start,Stop) == true)
795 FileI->Architecture = WriteUniqString(Start,Stop - Start);
796
797 if (Section.FindFlag("NotAutomatic",FileI->Flags,
798 pkgCache::Flag::NotAutomatic) == false)
799 _error->Warning("Bad NotAutomatic flag");
800
801 return !_error->PendingError();
802 }
803 /*}}}*/
804 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
805 // ---------------------------------------------------------------------
806 /* */
807 unsigned char debListParser::GetPrio(string Str)
808 {
809 unsigned char Out;
810 if (GrabWord(Str,PrioList,Out) == false)
811 Out = pkgCache::State::Extra;
812
813 return Out;
814 }
815 /*}}}*/