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
341 flag = ok, reinstreq, hold, hold-reinstreq
342 status = not-installed, unpacked, half-configured,
343 half-installed, config-files, post-inst-failed,
344 removal-failed, installed
346 Some of the above are obsolete (I think?) flag = hold-* and
347 status = post-inst-failed, removal-failed at least.
349 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
350 pkgCache::VerIterator
&Ver
)
354 if (Section
.Find("Status",Start
,Stop
) == false)
357 // UsePackage() is responsible for setting the flag in the default case
358 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
359 if (essential
== true &&
360 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
363 // Isolate the first word
364 const char *I
= Start
;
365 for(; I
< Stop
&& *I
!= ' '; I
++);
366 if (I
>= Stop
|| *I
!= ' ')
367 return _error
->Error("Malformed Status line");
369 // Process the want field
370 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
371 {"install",pkgCache::State::Install
},
372 {"hold",pkgCache::State::Hold
},
373 {"deinstall",pkgCache::State::DeInstall
},
374 {"purge",pkgCache::State::Purge
},
376 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
377 return _error
->Error("Malformed 1st word in the Status line");
379 // Isloate the next word
382 for(; I
< Stop
&& *I
!= ' '; I
++);
383 if (I
>= Stop
|| *I
!= ' ')
384 return _error
->Error("Malformed status line, no 2nd word");
386 // Process the flag field
387 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
388 {"reinstreq",pkgCache::State::ReInstReq
},
389 {"hold",pkgCache::State::HoldInst
},
390 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
392 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
393 return _error
->Error("Malformed 2nd word in the Status line");
395 // Isloate the last word
398 for(; I
< Stop
&& *I
!= ' '; I
++);
400 return _error
->Error("Malformed Status line, no 3rd word");
402 // Process the flag field
403 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
404 {"unpacked",pkgCache::State::UnPacked
},
405 {"half-configured",pkgCache::State::HalfConfigured
},
406 {"installed",pkgCache::State::Installed
},
407 {"half-installed",pkgCache::State::HalfInstalled
},
408 {"config-files",pkgCache::State::ConfigFiles
},
409 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
410 {"triggers-pending",pkgCache::State::TriggersPending
},
411 {"post-inst-failed",pkgCache::State::HalfConfigured
},
412 {"removal-failed",pkgCache::State::HalfInstalled
},
414 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
415 return _error
->Error("Malformed 3rd word in the Status line");
417 /* A Status line marks the package as indicating the current
418 version as well. Only if it is actually installed.. Otherwise
419 the interesting dpkg handling of the status file creates bogus
421 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
422 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
424 if (Ver
.end() == true)
425 _error
->Warning("Encountered status field in a non-version description");
427 Pkg
->CurrentVer
= Ver
.Index();
433 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
435 // Determine the operator
443 Op
= pkgCache::Dep::LessEq
;
450 Op
= pkgCache::Dep::Less
;
454 // < is the same as <= and << is really Cs < for some reason
455 Op
= pkgCache::Dep::LessEq
;
463 Op
= pkgCache::Dep::GreaterEq
;
470 Op
= pkgCache::Dep::Greater
;
474 // > is the same as >= and >> is really Cs > for some reason
475 Op
= pkgCache::Dep::GreaterEq
;
479 Op
= pkgCache::Dep::Equals
;
483 // HACK around bad package definitions
485 Op
= pkgCache::Dep::Equals
;
491 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
492 // ---------------------------------------------------------------------
493 /* This parses the dependency elements out of a standard string in place,
495 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
496 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
497 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
498 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
499 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
500 bool const &ParseArchFlags
)
501 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
502 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
503 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
504 bool const &ParseArchFlags
, bool const &StripMultiArch
)
505 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
506 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
507 string
&Package
,string
&Ver
,
508 unsigned int &Op
, bool const &ParseArchFlags
,
509 bool const &StripMultiArch
,
510 bool const &ParseRestrictionsList
)
512 // Strip off leading space
513 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
515 // Parse off the package name
516 const char *I
= Start
;
517 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
518 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
519 *I
!= '<' && *I
!= '>'; ++I
);
522 if (I
!= Stop
&& *I
== ')')
528 // Stash the package name
529 Package
.assign(Start
,I
- Start
);
531 // We don't want to confuse library users which can't handle MultiArch
532 string
const arch
= _config
->Find("APT::Architecture");
533 if (StripMultiArch
== true) {
534 size_t const found
= Package
.rfind(':');
535 if (found
!= string::npos
&&
536 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
537 strcmp(Package
.c_str() + found
, ":native") == 0 ||
538 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
539 Package
= Package
.substr(0,found
);
542 // Skip white space to the '('
543 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
546 if (I
!= Stop
&& *I
== '(')
549 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
552 I
= ConvertRelation(I
,Op
);
555 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
557 I
= (const char*) memchr(I
, ')', Stop
- I
);
558 if (I
== NULL
|| Start
== I
)
561 // Skip trailing whitespace
563 for (; End
> Start
&& isspace(End
[-1]); End
--);
565 Ver
.assign(Start
,End
-Start
);
571 Op
= pkgCache::Dep::NoOp
;
575 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
577 if (ParseArchFlags
== true)
579 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
581 // Parse an architecture
582 if (I
!= Stop
&& *I
== '[')
586 if (unlikely(I
== Stop
))
591 bool NegArch
= false;
594 // look for whitespace or ending ']'
595 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
597 if (unlikely(End
== Stop
))
606 std::string
arch(I
, End
);
607 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
612 // we found a match, so fast-forward to the end of the wildcards
613 for (; End
!= Stop
&& *End
!= ']'; ++End
);
622 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
629 Package
= ""; /* not for this arch */
633 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
636 if (ParseRestrictionsList
== true)
638 // Parse a restrictions list
639 if (I
!= Stop
&& *I
== '<')
643 if (unlikely(I
== Stop
))
646 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
650 bool NegRestriction
= false;
653 // look for whitespace or ending '>'
654 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
656 if (unlikely(End
== Stop
))
661 NegRestriction
= true;
665 std::string
restriction(I
, End
);
667 std::string prefix
= "profile.";
668 // only support for "profile" prefix, ignore others
669 if (restriction
.size() > prefix
.size() &&
670 restriction
.substr(0, prefix
.size()) == prefix
)
672 // get the name of the profile
673 restriction
= restriction
.substr(prefix
.size());
675 if (restriction
.empty() == false && profiles
.empty() == false &&
676 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
680 NegRestriction
= false;
681 // we found a match, so fast-forward to the end of the wildcards
682 for (; End
!= Stop
&& *End
!= '>'; ++End
);
692 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
695 if (NegRestriction
== true)
699 Package
= ""; /* not for this restriction */
703 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
706 if (I
!= Stop
&& *I
== '|')
707 Op
|= pkgCache::Dep::Or
;
709 if (I
== Stop
|| *I
== ',' || *I
== '|')
712 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
719 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
720 // ---------------------------------------------------------------------
721 /* This is the higher level depends parser. It takes a tag and generates
722 a complete depends tree for the given version. */
723 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
724 const char *Tag
,unsigned int Type
)
728 if (Section
.Find(Tag
,Start
,Stop
) == false)
731 string
const pkgArch
= Ver
.Arch();
739 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
741 return _error
->Error("Problem parsing dependency %s",Tag
);
742 size_t const found
= Package
.rfind(':');
744 // If negative is unspecific it needs to apply on all architectures
745 if (MultiArchEnabled
== true && found
== string::npos
&&
746 (Type
== pkgCache::Dep::Conflicts
||
747 Type
== pkgCache::Dep::DpkgBreaks
||
748 Type
== pkgCache::Dep::Replaces
))
750 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
751 a
!= Architectures
.end(); ++a
)
752 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
754 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
757 else if (MultiArchEnabled
== true && found
!= string::npos
&&
758 strcmp(Package
.c_str() + found
, ":any") != 0)
760 string Arch
= Package
.substr(found
+1, string::npos
);
761 Package
= Package
.substr(0, found
);
762 // Such dependencies are not supposed to be accepted …
763 // … but this is probably the best thing to do.
764 if (Arch
== "native")
765 Arch
= _config
->Find("APT::Architecture");
766 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
771 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
773 if ((Type
== pkgCache::Dep::Conflicts
||
774 Type
== pkgCache::Dep::DpkgBreaks
||
775 Type
== pkgCache::Dep::Replaces
) &&
776 NewDepends(Ver
, Package
,
777 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
778 Version
,Op
,Type
) == false)
787 // ListParser::ParseProvides - Parse the provides list /*{{{*/
788 // ---------------------------------------------------------------------
790 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
794 if (Section
.Find("Provides",Start
,Stop
) == true)
798 string
const Arch
= Ver
.Arch();
803 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
805 return _error
->Error("Problem parsing Provides line");
806 if (Op
!= pkgCache::Dep::NoOp
&& Op
!= pkgCache::Dep::Equals
) {
807 _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str());
808 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
809 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
812 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
821 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
823 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
824 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
826 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
827 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
832 // ListParser::NewProvides - add provides for all architectures /*{{{*/
833 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
834 string
const &Version
) {
835 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
836 a
!= Architectures
.end(); ++a
)
838 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
844 // ListParser::GrabWord - Matches a word and returns /*{{{*/
845 // ---------------------------------------------------------------------
846 /* Looks for a word in a list of words - for ParseStatus */
847 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
849 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
851 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
860 // ListParser::Step - Move to the next section in the file /*{{{*/
861 // ---------------------------------------------------------------------
862 /* This has to be careful to only process the correct architecture */
863 bool debListParser::Step()
865 iOffset
= Tags
.Offset();
866 while (Tags
.Step(Section
) == true)
868 /* See if this is the correct Architecture, if it isn't then we
869 drop the whole section. A missing arch tag only happens (in theory)
870 inside the Status file, so that is a positive return */
871 string
const Architecture
= Section
.FindS("Architecture");
873 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
875 if (APT::Configuration::checkArchitecture(Architecture
) == true)
877 /* parse version stanzas without an architecture only in the status file
878 (and as misfortune bycatch flat-archives) */
879 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
884 if (Architecture
== Arch
)
887 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
891 iOffset
= Tags
.Offset();
896 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
897 // ---------------------------------------------------------------------
899 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
900 FileFd
&File
, string component
)
902 // apt-secure does no longer download individual (per-section) Release
903 // file. to provide Component pinning we use the section name now
904 map_ptrloc
const storage
= WriteUniqString(component
);
905 FileI
->Component
= storage
;
907 pkgTagFile
TagFile(&File
, File
.Size());
908 pkgTagSection Section
;
909 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
913 #define APT_INRELEASE(TAG, STORE) \
914 data = Section.FindS(TAG); \
915 if (data.empty() == false) \
917 map_ptrloc const storage = WriteUniqString(data); \
920 APT_INRELEASE("Suite", FileI
->Archive
)
921 APT_INRELEASE("Component", FileI
->Component
)
922 APT_INRELEASE("Version", FileI
->Version
)
923 APT_INRELEASE("Origin", FileI
->Origin
)
924 APT_INRELEASE("Codename", FileI
->Codename
)
925 APT_INRELEASE("Label", FileI
->Label
)
927 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
928 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
930 return !_error
->PendingError();
933 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
934 // ---------------------------------------------------------------------
936 unsigned char debListParser::GetPrio(string Str
)
939 if (GrabWord(Str
,PrioList
,Out
) == false)
940 Out
= pkgCache::State::Extra
;
945 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
946 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
947 pkgCache::VerIterator
const &Ver
)
949 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
951 // status file has no (Download)Size, but all others are fair game
952 // status file is parsed last, so the first version we encounter is
953 // probably also the version we have downloaded
954 unsigned long long const Size
= Section
.FindULL("Size");
955 if (Size
!= 0 && Size
!= Ver
->Size
)
957 // available everywhere, but easier to check here than to include in VersionHash
958 unsigned char MultiArch
= ParseMultiArch(false);
959 if (MultiArch
!= Ver
->MultiArch
)
961 // for all practical proposes (we can check): same version