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