1 // -*- mode: cpp; mode: fold -*-
3 // $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $
4 /* ######################################################################
6 Package Cache Generator - Generator for the cache structure.
8 This builds the cache structure from the abstract package list parser.
10 ##################################################################### */
12 // Include Files /*{{{*/
15 #include <apt-pkg/deblistparser.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/configuration.h>
18 #include <apt-pkg/cachefilter.h>
19 #include <apt-pkg/aptconfiguration.h>
20 #include <apt-pkg/strutl.h>
21 #include <apt-pkg/fileutl.h>
22 #include <apt-pkg/crc-16.h>
23 #include <apt-pkg/md5.h>
24 #include <apt-pkg/macros.h>
31 static debListParser::WordList PrioList
[] = {
32 {"required",pkgCache::State::Required
},
33 {"important",pkgCache::State::Important
},
34 {"standard",pkgCache::State::Standard
},
35 {"optional",pkgCache::State::Optional
},
36 {"extra",pkgCache::State::Extra
},
39 // ListParser::debListParser - Constructor /*{{{*/
40 // ---------------------------------------------------------------------
41 /* Provide an architecture and only this one and "all" will be accepted
42 in Step(), if no Architecture is given we will accept every arch
43 we would accept in general with checkArchitecture() */
44 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
47 this->Arch
= _config
->Find("APT::Architecture");
48 Architectures
= APT::Configuration::getArchitectures();
49 MultiArchEnabled
= Architectures
.size() > 1;
52 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
53 // ---------------------------------------------------------------------
55 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
59 if (Section
.Find(Tag
,Start
,Stop
) == false)
61 return WriteUniqString(Start
,Stop
- Start
);
64 // ListParser::Package - Return the package name /*{{{*/
65 // ---------------------------------------------------------------------
66 /* This is to return the name of the package this section describes */
67 string
debListParser::Package() {
68 string
const Result
= Section
.FindS("Package");
69 if(unlikely(Result
.empty() == true))
70 _error
->Error("Encountered a section with no Package: header");
74 // ListParser::Architecture - Return the package arch /*{{{*/
75 // ---------------------------------------------------------------------
76 /* This will return the Architecture of the package this section describes */
77 string
debListParser::Architecture() {
78 return Section
.FindS("Architecture");
81 // ListParser::ArchitectureAll /*{{{*/
82 // ---------------------------------------------------------------------
84 bool debListParser::ArchitectureAll() {
85 return Section
.FindS("Architecture") == "all";
88 // ListParser::Version - Return the version string /*{{{*/
89 // ---------------------------------------------------------------------
90 /* This is to return the string describing the version in debian form,
91 epoch:upstream-release. If this returns the blank string then the
92 entry is assumed to only describe package properties */
93 string
debListParser::Version()
95 return Section
.FindS("Version");
98 // ListParser::NewVersion - Fill in the version structure /*{{{*/
99 // ---------------------------------------------------------------------
101 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
104 Ver
->Section
= UniqFindTagWrite("Section");
107 string
const MultiArch
= Section
.FindS("Multi-Arch");
108 if (MultiArch
.empty() == true)
109 Ver
->MultiArch
= pkgCache::Version::None
;
110 else if (MultiArch
== "same") {
112 if (ArchitectureAll() == true)
114 /* Arch all packages can't be Multi-Arch: same */
115 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
116 Section
.FindS("Package").c_str());
117 Ver
->MultiArch
= pkgCache::Version::None
;
120 Ver
->MultiArch
= pkgCache::Version::Same
;
122 else if (MultiArch
== "foreign")
123 Ver
->MultiArch
= pkgCache::Version::Foreign
;
124 else if (MultiArch
== "allowed")
125 Ver
->MultiArch
= pkgCache::Version::Allowed
;
128 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
129 MultiArch
.c_str(), Section
.FindS("Package").c_str());
130 Ver
->MultiArch
= pkgCache::Version::None
;
133 if (ArchitectureAll() == true)
134 Ver
->MultiArch
|= pkgCache::Version::All
;
137 Ver
->Size
= Section
.FindULL("Size");
138 // Unpacked Size (in K)
139 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
140 Ver
->InstalledSize
*= 1024;
145 if (Section
.Find("Priority",Start
,Stop
) == true)
147 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
148 Ver
->Priority
= pkgCache::State::Extra
;
151 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
153 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
155 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
157 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
159 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
161 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
163 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
165 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
169 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
172 if (ParseProvides(Ver
) == false)
178 // ListParser::Description - Return the description string /*{{{*/
179 // ---------------------------------------------------------------------
180 /* This is to return the string describing the package in debian
181 form. If this returns the blank string then the entry is assumed to
182 only describe package properties */
183 string
debListParser::Description()
185 string
const lang
= DescriptionLanguage();
187 return Section
.FindS("Description");
189 return Section
.FindS(string("Description-").append(lang
).c_str());
192 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
193 // ---------------------------------------------------------------------
194 /* This is to return the string describing the language of
195 description. If this returns the blank string then the entry is
196 assumed to describe original description. */
197 string
debListParser::DescriptionLanguage()
199 if (Section
.FindS("Description").empty() == false)
202 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
203 for (std::vector
<string
>::const_iterator l
= lang
.begin();
204 l
!= lang
.end(); ++l
)
205 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
211 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
212 // ---------------------------------------------------------------------
213 /* This is to return the md5 string to allow the check if it is the right
214 description. If no Description-md5 is found in the section it will be
217 MD5SumValue
debListParser::Description_md5()
219 string
const value
= Section
.FindS("Description-md5");
220 if (value
.empty() == true)
222 std::string
const desc
= Description() + "\n";
224 return MD5SumValue();
227 md5
.Add(desc
.c_str());
230 else if (likely(value
.size() == 32))
232 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
233 return MD5SumValue(value
);
234 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
235 return MD5SumValue();
237 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
238 return MD5SumValue();
241 // ListParser::UsePackage - Update a package structure /*{{{*/
242 // ---------------------------------------------------------------------
243 /* This is called to update the package with any new information
244 that might be found in the section */
245 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
246 pkgCache::VerIterator
&Ver
)
248 if (Pkg
->Section
== 0)
249 Pkg
->Section
= UniqFindTagWrite("Section");
251 string
const static myArch
= _config
->Find("APT::Architecture");
252 // Possible values are: "all", "native", "installed" and "none"
253 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
254 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
255 if (essential
== "all" ||
256 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
257 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
259 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
262 if (strcmp(Pkg
.Name(),"apt") == 0)
264 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
266 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
268 Pkg
->Flags
|= pkgCache::Flag::Important
;
271 if (ParseStatus(Pkg
,Ver
) == false)
276 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
277 // ---------------------------------------------------------------------
279 unsigned short debListParser::VersionHash()
281 const char *Sections
[] ={"Installed-Size",
289 unsigned long Result
= INIT_FCS
;
291 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
295 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
298 /* Strip out any spaces from the text, this undoes dpkgs reformatting
299 of certain fields. dpkg also has the rather interesting notion of
300 reformatting depends operators < -> <= */
302 for (; Start
!= End
; ++Start
)
304 if (isspace(*Start
) != 0)
306 *J
++ = tolower_ascii(*Start
);
308 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
312 Result
= AddCRC16(Result
,S
,J
- S
);
318 // ListParser::ParseStatus - Parse the status field /*{{{*/
319 // ---------------------------------------------------------------------
320 /* Status lines are of the form,
321 Status: want flag status
322 want = unknown, install, hold, deinstall, purge
323 flag = ok, reinstreq, hold, hold-reinstreq
324 status = not-installed, unpacked, half-configured,
325 half-installed, config-files, post-inst-failed,
326 removal-failed, installed
328 Some of the above are obsolete (I think?) flag = hold-* and
329 status = post-inst-failed, removal-failed at least.
331 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
332 pkgCache::VerIterator
&Ver
)
336 if (Section
.Find("Status",Start
,Stop
) == false)
339 // UsePackage() is responsible for setting the flag in the default case
340 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
341 if (essential
== true &&
342 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
345 // Isolate the first word
346 const char *I
= Start
;
347 for(; I
< Stop
&& *I
!= ' '; I
++);
348 if (I
>= Stop
|| *I
!= ' ')
349 return _error
->Error("Malformed Status line");
351 // Process the want field
352 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
353 {"install",pkgCache::State::Install
},
354 {"hold",pkgCache::State::Hold
},
355 {"deinstall",pkgCache::State::DeInstall
},
356 {"purge",pkgCache::State::Purge
},
358 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
359 return _error
->Error("Malformed 1st word in the Status line");
361 // Isloate the next word
364 for(; I
< Stop
&& *I
!= ' '; I
++);
365 if (I
>= Stop
|| *I
!= ' ')
366 return _error
->Error("Malformed status line, no 2nd word");
368 // Process the flag field
369 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
370 {"reinstreq",pkgCache::State::ReInstReq
},
371 {"hold",pkgCache::State::HoldInst
},
372 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
374 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
375 return _error
->Error("Malformed 2nd word in the Status line");
377 // Isloate the last word
380 for(; I
< Stop
&& *I
!= ' '; I
++);
382 return _error
->Error("Malformed Status line, no 3rd word");
384 // Process the flag field
385 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
386 {"unpacked",pkgCache::State::UnPacked
},
387 {"half-configured",pkgCache::State::HalfConfigured
},
388 {"installed",pkgCache::State::Installed
},
389 {"half-installed",pkgCache::State::HalfInstalled
},
390 {"config-files",pkgCache::State::ConfigFiles
},
391 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
392 {"triggers-pending",pkgCache::State::TriggersPending
},
393 {"post-inst-failed",pkgCache::State::HalfConfigured
},
394 {"removal-failed",pkgCache::State::HalfInstalled
},
396 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
397 return _error
->Error("Malformed 3rd word in the Status line");
399 /* A Status line marks the package as indicating the current
400 version as well. Only if it is actually installed.. Otherwise
401 the interesting dpkg handling of the status file creates bogus
403 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
404 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
406 if (Ver
.end() == true)
407 _error
->Warning("Encountered status field in a non-version description");
409 Pkg
->CurrentVer
= Ver
.Index();
415 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
417 // Determine the operator
425 Op
= pkgCache::Dep::LessEq
;
432 Op
= pkgCache::Dep::Less
;
436 // < is the same as <= and << is really Cs < for some reason
437 Op
= pkgCache::Dep::LessEq
;
445 Op
= pkgCache::Dep::GreaterEq
;
452 Op
= pkgCache::Dep::Greater
;
456 // > is the same as >= and >> is really Cs > for some reason
457 Op
= pkgCache::Dep::GreaterEq
;
461 Op
= pkgCache::Dep::Equals
;
465 // HACK around bad package definitions
467 Op
= pkgCache::Dep::Equals
;
473 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
474 // ---------------------------------------------------------------------
475 /* This parses the dependency elements out of a standard string in place,
477 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
478 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
479 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
480 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
481 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
482 bool const &ParseArchFlags
)
483 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
484 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
485 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
486 bool const &ParseArchFlags
, bool const &StripMultiArch
)
487 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
488 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
489 string
&Package
,string
&Ver
,
490 unsigned int &Op
, bool const &ParseArchFlags
,
491 bool const &StripMultiArch
,
492 bool const &ParseRestrictionsList
)
494 // Strip off leading space
495 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
497 // Parse off the package name
498 const char *I
= Start
;
499 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
500 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
501 *I
!= '<' && *I
!= '>'; ++I
);
504 if (I
!= Stop
&& *I
== ')')
510 // Stash the package name
511 Package
.assign(Start
,I
- Start
);
513 // We don't want to confuse library users which can't handle MultiArch
514 string
const arch
= _config
->Find("APT::Architecture");
515 if (StripMultiArch
== true) {
516 size_t const found
= Package
.rfind(':');
517 if (found
!= string::npos
&&
518 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
519 strcmp(Package
.c_str() + found
, ":native") == 0 ||
520 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
521 Package
= Package
.substr(0,found
);
524 // Skip white space to the '('
525 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
528 if (I
!= Stop
&& *I
== '(')
531 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
534 I
= ConvertRelation(I
,Op
);
537 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
539 I
= (const char*) memchr(I
, ')', Stop
- I
);
540 if (I
== NULL
|| Start
== I
)
543 // Skip trailing whitespace
545 for (; End
> Start
&& isspace(End
[-1]); End
--);
547 Ver
.assign(Start
,End
-Start
);
553 Op
= pkgCache::Dep::NoOp
;
557 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
559 if (ParseArchFlags
== true)
561 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
563 // Parse an architecture
564 if (I
!= Stop
&& *I
== '[')
568 if (unlikely(I
== Stop
))
573 bool NegArch
= false;
576 // look for whitespace or ending ']'
577 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
579 if (unlikely(End
== Stop
))
588 std::string
arch(I
, End
);
589 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
594 // we found a match, so fast-forward to the end of the wildcards
595 for (; End
!= Stop
&& *End
!= ']'; ++End
);
604 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
611 Package
= ""; /* not for this arch */
615 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
618 if (ParseRestrictionsList
== true)
620 // Parse a restrictions list
621 if (I
!= Stop
&& *I
== '<')
625 if (unlikely(I
== Stop
))
628 std::vector
<string
> const profiles
= _config
->FindVector("APT::Build-Profiles");
632 bool NegRestriction
= false;
635 // look for whitespace or ending '>'
636 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
638 if (unlikely(End
== Stop
))
643 NegRestriction
= true;
647 std::string
restriction(I
, End
);
649 std::string prefix
= "profile.";
650 // only support for "profile" prefix, ignore others
651 if (restriction
.size() > prefix
.size() &&
652 restriction
.substr(0, prefix
.size()) == prefix
)
654 // get the name of the profile
655 restriction
= restriction
.substr(prefix
.size());
657 if (restriction
.empty() == false && profiles
.empty() == false &&
658 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
662 NegRestriction
= false;
663 // we found a match, so fast-forward to the end of the wildcards
664 for (; End
!= Stop
&& *End
!= '>'; ++End
);
674 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
677 if (NegRestriction
== true)
681 Package
= ""; /* not for this restriction */
685 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
688 if (I
!= Stop
&& *I
== '|')
689 Op
|= pkgCache::Dep::Or
;
691 if (I
== Stop
|| *I
== ',' || *I
== '|')
694 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
701 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
702 // ---------------------------------------------------------------------
703 /* This is the higher level depends parser. It takes a tag and generates
704 a complete depends tree for the given version. */
705 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
706 const char *Tag
,unsigned int Type
)
710 if (Section
.Find(Tag
,Start
,Stop
) == false)
713 string
const pkgArch
= Ver
.Arch();
721 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
723 return _error
->Error("Problem parsing dependency %s",Tag
);
724 size_t const found
= Package
.rfind(':');
726 // If negative is unspecific it needs to apply on all architectures
727 if (MultiArchEnabled
== true && found
== string::npos
&&
728 (Type
== pkgCache::Dep::Conflicts
||
729 Type
== pkgCache::Dep::DpkgBreaks
||
730 Type
== pkgCache::Dep::Replaces
))
732 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
733 a
!= Architectures
.end(); ++a
)
734 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
736 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
739 else if (MultiArchEnabled
== true && found
!= string::npos
&&
740 strcmp(Package
.c_str() + found
, ":any") != 0)
742 string Arch
= Package
.substr(found
+1, string::npos
);
743 Package
= Package
.substr(0, found
);
744 // Such dependencies are not supposed to be accepted …
745 // … but this is probably the best thing to do.
746 if (Arch
== "native")
747 Arch
= _config
->Find("APT::Architecture");
748 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
753 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
755 if ((Type
== pkgCache::Dep::Conflicts
||
756 Type
== pkgCache::Dep::DpkgBreaks
||
757 Type
== pkgCache::Dep::Replaces
) &&
758 NewDepends(Ver
, Package
,
759 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
760 Version
,Op
,Type
) == false)
769 // ListParser::ParseProvides - Parse the provides list /*{{{*/
770 // ---------------------------------------------------------------------
772 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
776 if (Section
.Find("Provides",Start
,Stop
) == true)
780 string
const Arch
= Ver
.Arch();
785 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
787 return _error
->Error("Problem parsing Provides line");
788 if (Op
!= pkgCache::Dep::NoOp
) {
789 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
790 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
791 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
794 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
803 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
805 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
806 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
808 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
809 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
814 // ListParser::NewProvides - add provides for all architectures /*{{{*/
815 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
816 string
const &Version
) {
817 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
818 a
!= Architectures
.end(); ++a
)
820 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
826 // ListParser::GrabWord - Matches a word and returns /*{{{*/
827 // ---------------------------------------------------------------------
828 /* Looks for a word in a list of words - for ParseStatus */
829 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
831 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
833 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
842 // ListParser::Step - Move to the next section in the file /*{{{*/
843 // ---------------------------------------------------------------------
844 /* This has to be careful to only process the correct architecture */
845 bool debListParser::Step()
847 iOffset
= Tags
.Offset();
848 while (Tags
.Step(Section
) == true)
850 /* See if this is the correct Architecture, if it isn't then we
851 drop the whole section. A missing arch tag only happens (in theory)
852 inside the Status file, so that is a positive return */
853 string
const Architecture
= Section
.FindS("Architecture");
855 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
857 if (APT::Configuration::checkArchitecture(Architecture
) == true)
859 /* parse version stanzas without an architecture only in the status file
860 (and as misfortune bycatch flat-archives) */
861 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
866 if (Architecture
== Arch
)
869 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
873 iOffset
= Tags
.Offset();
878 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
879 // ---------------------------------------------------------------------
881 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
882 FileFd
&File
, string component
)
884 // apt-secure does no longer download individual (per-section) Release
885 // file. to provide Component pinning we use the section name now
886 map_ptrloc
const storage
= WriteUniqString(component
);
887 FileI
->Component
= storage
;
889 pkgTagFile
TagFile(&File
, File
.Size());
890 pkgTagSection Section
;
891 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
895 #define APT_INRELEASE(TAG, STORE) \
896 data = Section.FindS(TAG); \
897 if (data.empty() == false) \
899 map_ptrloc const storage = WriteUniqString(data); \
902 APT_INRELEASE("Suite", FileI
->Archive
)
903 APT_INRELEASE("Component", FileI
->Component
)
904 APT_INRELEASE("Version", FileI
->Version
)
905 APT_INRELEASE("Origin", FileI
->Origin
)
906 APT_INRELEASE("Codename", FileI
->Codename
)
907 APT_INRELEASE("Label", FileI
->Label
)
909 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
910 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
912 return !_error
->PendingError();
915 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
916 // ---------------------------------------------------------------------
918 unsigned char debListParser::GetPrio(string Str
)
921 if (GrabWord(Str
,PrioList
,Out
) == false)
922 Out
= pkgCache::State::Extra
;