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/mmap.h>
25 #include <apt-pkg/pkgcache.h>
26 #include <apt-pkg/cacheiterators.h>
27 #include <apt-pkg/tagfile.h>
28 #include <apt-pkg/macros.h>
40 static debListParser::WordList PrioList
[] = {
41 {"required",pkgCache::State::Required
},
42 {"important",pkgCache::State::Important
},
43 {"standard",pkgCache::State::Standard
},
44 {"optional",pkgCache::State::Optional
},
45 {"extra",pkgCache::State::Extra
},
48 // ListParser::debListParser - Constructor /*{{{*/
49 // ---------------------------------------------------------------------
50 /* Provide an architecture and only this one and "all" will be accepted
51 in Step(), if no Architecture is given we will accept every arch
52 we would accept in general with checkArchitecture() */
53 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
56 this->Arch
= _config
->Find("APT::Architecture");
57 Architectures
= APT::Configuration::getArchitectures();
58 MultiArchEnabled
= Architectures
.size() > 1;
61 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
62 // ---------------------------------------------------------------------
64 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
68 if (Section
.Find(Tag
,Start
,Stop
) == false)
70 return WriteUniqString(Start
,Stop
- Start
);
73 // ListParser::Package - Return the package name /*{{{*/
74 // ---------------------------------------------------------------------
75 /* This is to return the name of the package this section describes */
76 string
debListParser::Package() {
77 string
const Result
= Section
.FindS("Package");
78 if(unlikely(Result
.empty() == true))
79 _error
->Error("Encountered a section with no Package: header");
83 // ListParser::Architecture - Return the package arch /*{{{*/
84 // ---------------------------------------------------------------------
85 /* This will return the Architecture of the package this section describes */
86 string
debListParser::Architecture() {
87 return Section
.FindS("Architecture");
90 // ListParser::ArchitectureAll /*{{{*/
91 // ---------------------------------------------------------------------
93 bool debListParser::ArchitectureAll() {
94 return Section
.FindS("Architecture") == "all";
97 // ListParser::Version - Return the version string /*{{{*/
98 // ---------------------------------------------------------------------
99 /* This is to return the string describing the version in debian form,
100 epoch:upstream-release. If this returns the blank string then the
101 entry is assumed to only describe package properties */
102 string
debListParser::Version()
104 return Section
.FindS("Version");
107 unsigned char debListParser::ParseMultiArch(bool const showErrors
) /*{{{*/
110 string
const MultiArch
= Section
.FindS("Multi-Arch");
111 if (MultiArch
.empty() == true || MultiArch
== "no")
112 MA
= pkgCache::Version::None
;
113 else if (MultiArch
== "same") {
114 if (ArchitectureAll() == true)
116 if (showErrors
== true)
117 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
118 Section
.FindS("Package").c_str());
119 MA
= pkgCache::Version::None
;
122 MA
= pkgCache::Version::Same
;
124 else if (MultiArch
== "foreign")
125 MA
= pkgCache::Version::Foreign
;
126 else if (MultiArch
== "allowed")
127 MA
= pkgCache::Version::Allowed
;
130 if (showErrors
== true)
131 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
132 MultiArch
.c_str(), Section
.FindS("Package").c_str());
133 MA
= pkgCache::Version::None
;
136 if (ArchitectureAll() == true)
137 MA
|= pkgCache::Version::All
;
142 // ListParser::NewVersion - Fill in the version structure /*{{{*/
143 // ---------------------------------------------------------------------
145 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
148 unsigned long const idxSection
= UniqFindTagWrite("Section");
149 Ver
->Section
= idxSection
;
150 Ver
->MultiArch
= ParseMultiArch(true);
152 Ver
->Size
= Section
.FindULL("Size");
153 // Unpacked Size (in K)
154 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
155 Ver
->InstalledSize
*= 1024;
160 if (Section
.Find("Priority",Start
,Stop
) == true)
162 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
163 Ver
->Priority
= pkgCache::State::Extra
;
166 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
168 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
170 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
172 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
174 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
176 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
178 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
180 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
184 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
187 if (ParseProvides(Ver
) == false)
193 // ListParser::Description - Return the description string /*{{{*/
194 // ---------------------------------------------------------------------
195 /* This is to return the string describing the package in debian
196 form. If this returns the blank string then the entry is assumed to
197 only describe package properties */
198 string
debListParser::Description()
200 string
const lang
= DescriptionLanguage();
202 return Section
.FindS("Description");
204 return Section
.FindS(string("Description-").append(lang
).c_str());
207 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
208 // ---------------------------------------------------------------------
209 /* This is to return the string describing the language of
210 description. If this returns the blank string then the entry is
211 assumed to describe original description. */
212 string
debListParser::DescriptionLanguage()
214 if (Section
.FindS("Description").empty() == false)
217 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
218 for (std::vector
<string
>::const_iterator l
= lang
.begin();
219 l
!= lang
.end(); ++l
)
220 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
226 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
227 // ---------------------------------------------------------------------
228 /* This is to return the md5 string to allow the check if it is the right
229 description. If no Description-md5 is found in the section it will be
232 MD5SumValue
debListParser::Description_md5()
234 string
const value
= Section
.FindS("Description-md5");
235 if (value
.empty() == true)
237 std::string
const desc
= Description() + "\n";
239 return MD5SumValue();
242 md5
.Add(desc
.c_str());
245 else if (likely(value
.size() == 32))
247 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
248 return MD5SumValue(value
);
249 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
250 return MD5SumValue();
252 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
253 return MD5SumValue();
256 // ListParser::UsePackage - Update a package structure /*{{{*/
257 // ---------------------------------------------------------------------
258 /* This is called to update the package with any new information
259 that might be found in the section */
260 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
261 pkgCache::VerIterator
&Ver
)
263 if (Pkg
->Section
== 0)
265 unsigned long const idxSection
= UniqFindTagWrite("Section");
266 Pkg
->Section
= idxSection
;
269 string
const static myArch
= _config
->Find("APT::Architecture");
270 // Possible values are: "all", "native", "installed" and "none"
271 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
272 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
273 if (essential
== "all" ||
274 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
275 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
277 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
280 if (strcmp(Pkg
.Name(),"apt") == 0)
282 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
284 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
286 Pkg
->Flags
|= pkgCache::Flag::Important
;
289 if (ParseStatus(Pkg
,Ver
) == false)
294 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
295 // ---------------------------------------------------------------------
297 unsigned short debListParser::VersionHash()
299 const char *Sections
[] ={"Installed-Size",
307 unsigned long Result
= INIT_FCS
;
309 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
313 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
316 /* Strip out any spaces from the text, this undoes dpkgs reformatting
317 of certain fields. dpkg also has the rather interesting notion of
318 reformatting depends operators < -> <= */
320 for (; Start
!= End
; ++Start
)
322 if (isspace(*Start
) != 0)
324 *J
++ = tolower_ascii(*Start
);
326 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
330 Result
= AddCRC16(Result
,S
,J
- S
);
336 // ListParser::ParseStatus - Parse the status field /*{{{*/
337 // ---------------------------------------------------------------------
338 /* Status lines are of the form,
339 Status: want flag status
340 want = unknown, install, hold, deinstall, purge
342 status = not-installed, config-files, half-installed, unpacked,
343 half-configured, triggers-awaited, triggers-pending, installed
345 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
346 pkgCache::VerIterator
&Ver
)
350 if (Section
.Find("Status",Start
,Stop
) == false)
353 // UsePackage() is responsible for setting the flag in the default case
354 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
355 if (essential
== true &&
356 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
359 // Isolate the first word
360 const char *I
= Start
;
361 for(; I
< Stop
&& *I
!= ' '; I
++);
362 if (I
>= Stop
|| *I
!= ' ')
363 return _error
->Error("Malformed Status line");
365 // Process the want field
366 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
367 {"install",pkgCache::State::Install
},
368 {"hold",pkgCache::State::Hold
},
369 {"deinstall",pkgCache::State::DeInstall
},
370 {"purge",pkgCache::State::Purge
},
372 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
373 return _error
->Error("Malformed 1st word in the Status line");
375 // Isloate the next word
378 for(; I
< Stop
&& *I
!= ' '; I
++);
379 if (I
>= Stop
|| *I
!= ' ')
380 return _error
->Error("Malformed status line, no 2nd word");
382 // Process the flag field
383 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
384 {"reinstreq",pkgCache::State::ReInstReq
},
385 {"hold",pkgCache::State::HoldInst
},
386 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
388 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
389 return _error
->Error("Malformed 2nd word in the Status line");
391 // Isloate the last word
394 for(; I
< Stop
&& *I
!= ' '; I
++);
396 return _error
->Error("Malformed Status line, no 3rd word");
398 // Process the flag field
399 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
400 {"config-files",pkgCache::State::ConfigFiles
},
401 {"half-installed",pkgCache::State::HalfInstalled
},
402 {"unpacked",pkgCache::State::UnPacked
},
403 {"half-configured",pkgCache::State::HalfConfigured
},
404 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
405 {"triggers-pending",pkgCache::State::TriggersPending
},
406 {"installed",pkgCache::State::Installed
},
408 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
409 return _error
->Error("Malformed 3rd word in the Status line");
411 /* A Status line marks the package as indicating the current
412 version as well. Only if it is actually installed.. Otherwise
413 the interesting dpkg handling of the status file creates bogus
415 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
416 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
418 if (Ver
.end() == true)
419 _error
->Warning("Encountered status field in a non-version description");
421 Pkg
->CurrentVer
= Ver
.Index();
427 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
429 // Determine the operator
437 Op
= pkgCache::Dep::LessEq
;
444 Op
= pkgCache::Dep::Less
;
448 // < is the same as <= and << is really Cs < for some reason
449 Op
= pkgCache::Dep::LessEq
;
457 Op
= pkgCache::Dep::GreaterEq
;
464 Op
= pkgCache::Dep::Greater
;
468 // > is the same as >= and >> is really Cs > for some reason
469 Op
= pkgCache::Dep::GreaterEq
;
473 Op
= pkgCache::Dep::Equals
;
477 // HACK around bad package definitions
479 Op
= pkgCache::Dep::Equals
;
485 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
486 // ---------------------------------------------------------------------
487 /* This parses the dependency elements out of a standard string in place,
489 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
490 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
491 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
492 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
493 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
494 bool const &ParseArchFlags
)
495 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
496 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
497 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
498 bool const &ParseArchFlags
, bool const &StripMultiArch
)
499 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
500 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
501 string
&Package
,string
&Ver
,
502 unsigned int &Op
, bool const &ParseArchFlags
,
503 bool const &StripMultiArch
,
504 bool const &ParseRestrictionsList
)
506 // Strip off leading space
507 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
509 // Parse off the package name
510 const char *I
= Start
;
511 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
512 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
513 *I
!= '<' && *I
!= '>'; ++I
);
516 if (I
!= Stop
&& *I
== ')')
522 // Stash the package name
523 Package
.assign(Start
,I
- Start
);
525 // We don't want to confuse library users which can't handle MultiArch
526 string
const arch
= _config
->Find("APT::Architecture");
527 if (StripMultiArch
== true) {
528 size_t const found
= Package
.rfind(':');
529 if (found
!= string::npos
&&
530 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
531 strcmp(Package
.c_str() + found
, ":native") == 0 ||
532 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
533 Package
= Package
.substr(0,found
);
536 // Skip white space to the '('
537 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
540 if (I
!= Stop
&& *I
== '(')
543 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
546 I
= ConvertRelation(I
,Op
);
549 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
551 I
= (const char*) memchr(I
, ')', Stop
- I
);
552 if (I
== NULL
|| Start
== I
)
555 // Skip trailing whitespace
557 for (; End
> Start
&& isspace(End
[-1]); End
--);
559 Ver
.assign(Start
,End
-Start
);
565 Op
= pkgCache::Dep::NoOp
;
569 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
571 if (ParseArchFlags
== true)
573 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
575 // Parse an architecture
576 if (I
!= Stop
&& *I
== '[')
580 if (unlikely(I
== Stop
))
585 bool NegArch
= false;
588 // look for whitespace or ending ']'
589 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
591 if (unlikely(End
== Stop
))
600 std::string
arch(I
, End
);
601 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
606 // we found a match, so fast-forward to the end of the wildcards
607 for (; End
!= Stop
&& *End
!= ']'; ++End
);
616 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
623 Package
= ""; /* not for this arch */
627 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
630 if (ParseRestrictionsList
== true)
632 // Parse a restrictions formula which is in disjunctive normal form:
633 // (foo AND bar) OR (blub AND bla)
635 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
637 // if the next character is a restriction list, then by default the
638 // dependency does not apply and the conditions have to be checked
639 // if the next character is not a restriction list, then by default the
640 // dependency applies
641 bool applies1
= (*I
!= '<');
649 if (unlikely(I
== Stop
))
654 // if of the prior restriction list is already fulfilled, then
655 // we can just skip to the end of the current list
657 for (;End
!= Stop
&& *End
!= '>'; ++End
);
660 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
662 bool applies2
= true;
663 // all the conditions inside a restriction list have to be
664 // met so once we find one that is not met, we can skip to
665 // the end of this list
668 // look for whitespace or ending '>'
669 // End now points to the character after the current term
670 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
672 if (unlikely(End
== Stop
))
675 bool NegRestriction
= false;
678 NegRestriction
= true;
682 std::string
restriction(I
, End
);
684 if (restriction
.empty() == false && profiles
.empty() == false &&
685 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
687 if (NegRestriction
) {
689 // since one of the terms does not apply we don't have to check the others
690 for (; End
!= Stop
&& *End
!= '>'; ++End
);
693 if (!NegRestriction
) {
695 // since one of the terms does not apply we don't have to check the others
696 for (; End
!= Stop
&& *End
!= '>'; ++End
);
703 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
709 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
717 if (applies1
== false) {
718 Package
= ""; //not for this restriction
722 if (I
!= Stop
&& *I
== '|')
723 Op
|= pkgCache::Dep::Or
;
725 if (I
== Stop
|| *I
== ',' || *I
== '|')
728 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
735 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
736 // ---------------------------------------------------------------------
737 /* This is the higher level depends parser. It takes a tag and generates
738 a complete depends tree for the given version. */
739 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
740 const char *Tag
,unsigned int Type
)
744 if (Section
.Find(Tag
,Start
,Stop
) == false)
747 string
const pkgArch
= Ver
.Arch();
755 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
757 return _error
->Error("Problem parsing dependency %s",Tag
);
758 size_t const found
= Package
.rfind(':');
760 // If negative is unspecific it needs to apply on all architectures
761 if (MultiArchEnabled
== true && found
== string::npos
&&
762 (Type
== pkgCache::Dep::Conflicts
||
763 Type
== pkgCache::Dep::DpkgBreaks
||
764 Type
== pkgCache::Dep::Replaces
))
766 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
767 a
!= Architectures
.end(); ++a
)
768 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
770 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
773 else if (found
!= string::npos
&&
774 strcmp(Package
.c_str() + found
, ":any") != 0)
776 string Arch
= Package
.substr(found
+1, string::npos
);
777 Package
= Package
.substr(0, found
);
778 // Such dependencies are not supposed to be accepted …
779 // … but this is probably the best thing to do.
780 if (Arch
== "native")
781 Arch
= _config
->Find("APT::Architecture");
782 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
787 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
789 if ((Type
== pkgCache::Dep::Conflicts
||
790 Type
== pkgCache::Dep::DpkgBreaks
||
791 Type
== pkgCache::Dep::Replaces
) &&
792 NewDepends(Ver
, Package
,
793 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
794 Version
,Op
,Type
) == false)
803 // ListParser::ParseProvides - Parse the provides list /*{{{*/
804 // ---------------------------------------------------------------------
806 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
810 if (Section
.Find("Provides",Start
,Stop
) == true)
814 string
const Arch
= Ver
.Arch();
819 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
820 const size_t archfound
= Package
.rfind(':');
822 return _error
->Error("Problem parsing Provides line");
823 if (Op
!= pkgCache::Dep::NoOp
&& Op
!= pkgCache::Dep::Equals
) {
824 _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str());
825 } else if (archfound
!= string::npos
) {
826 string OtherArch
= Package
.substr(archfound
+1, string::npos
);
827 Package
= Package
.substr(0, archfound
);
828 if (NewProvides(Ver
, Package
, OtherArch
, Version
) == false)
830 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
831 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
834 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
843 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
845 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
846 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
848 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
849 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
854 // ListParser::NewProvides - add provides for all architectures /*{{{*/
855 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
856 string
const &Version
) {
857 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
858 a
!= Architectures
.end(); ++a
)
860 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
866 // ListParser::GrabWord - Matches a word and returns /*{{{*/
867 // ---------------------------------------------------------------------
868 /* Looks for a word in a list of words - for ParseStatus */
869 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
871 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
873 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
882 // ListParser::Step - Move to the next section in the file /*{{{*/
883 // ---------------------------------------------------------------------
884 /* This has to be careful to only process the correct architecture */
885 bool debListParser::Step()
887 iOffset
= Tags
.Offset();
888 while (Tags
.Step(Section
) == true)
890 /* See if this is the correct Architecture, if it isn't then we
891 drop the whole section. A missing arch tag only happens (in theory)
892 inside the Status file, so that is a positive return */
893 string
const Architecture
= Section
.FindS("Architecture");
895 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
897 if (APT::Configuration::checkArchitecture(Architecture
) == true)
899 /* parse version stanzas without an architecture only in the status file
900 (and as misfortune bycatch flat-archives) */
901 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
906 if (Architecture
== Arch
)
909 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
913 iOffset
= Tags
.Offset();
918 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
919 // ---------------------------------------------------------------------
921 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
922 FileFd
&File
, string component
)
924 // apt-secure does no longer download individual (per-section) Release
925 // file. to provide Component pinning we use the section name now
926 map_ptrloc
const storage
= WriteUniqString(component
);
927 FileI
->Component
= storage
;
929 pkgTagFile
TagFile(&File
, File
.Size());
930 pkgTagSection Section
;
931 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
935 #define APT_INRELEASE(TAG, STORE) \
936 data = Section.FindS(TAG); \
937 if (data.empty() == false) \
939 map_ptrloc const storage = WriteUniqString(data); \
942 APT_INRELEASE("Suite", FileI
->Archive
)
943 APT_INRELEASE("Component", FileI
->Component
)
944 APT_INRELEASE("Version", FileI
->Version
)
945 APT_INRELEASE("Origin", FileI
->Origin
)
946 APT_INRELEASE("Codename", FileI
->Codename
)
947 APT_INRELEASE("Label", FileI
->Label
)
949 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
950 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
952 return !_error
->PendingError();
955 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
956 // ---------------------------------------------------------------------
958 unsigned char debListParser::GetPrio(string Str
)
961 if (GrabWord(Str
,PrioList
,Out
) == false)
962 Out
= pkgCache::State::Extra
;
967 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
968 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
969 pkgCache::VerIterator
const &Ver
)
971 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
973 // status file has no (Download)Size, but all others are fair game
974 // status file is parsed last, so the first version we encounter is
975 // probably also the version we have downloaded
976 unsigned long long const Size
= Section
.FindULL("Size");
977 if (Size
!= 0 && Size
!= Ver
->Size
)
979 // available everywhere, but easier to check here than to include in VersionHash
980 unsigned char MultiArch
= ParseMultiArch(false);
981 if (MultiArch
!= Ver
->MultiArch
)
983 // for all practical proposes (we can check): same version