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 // ListParser::NewVersion - Fill in the version structure /*{{{*/
108 // ---------------------------------------------------------------------
110 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
113 Ver
->Section
= UniqFindTagWrite("Section");
116 string
const MultiArch
= Section
.FindS("Multi-Arch");
117 if (MultiArch
.empty() == true)
118 Ver
->MultiArch
= pkgCache::Version::None
;
119 else if (MultiArch
== "same") {
121 if (ArchitectureAll() == true)
123 /* Arch all packages can't be Multi-Arch: same */
124 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
125 Section
.FindS("Package").c_str());
126 Ver
->MultiArch
= pkgCache::Version::None
;
129 Ver
->MultiArch
= pkgCache::Version::Same
;
131 else if (MultiArch
== "foreign")
132 Ver
->MultiArch
= pkgCache::Version::Foreign
;
133 else if (MultiArch
== "allowed")
134 Ver
->MultiArch
= pkgCache::Version::Allowed
;
137 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
138 MultiArch
.c_str(), Section
.FindS("Package").c_str());
139 Ver
->MultiArch
= pkgCache::Version::None
;
142 if (ArchitectureAll() == true)
143 Ver
->MultiArch
|= pkgCache::Version::All
;
146 Ver
->Size
= Section
.FindULL("Size");
147 // Unpacked Size (in K)
148 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
149 Ver
->InstalledSize
*= 1024;
154 if (Section
.Find("Priority",Start
,Stop
) == true)
156 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
157 Ver
->Priority
= pkgCache::State::Extra
;
160 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
162 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
164 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
166 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
168 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
170 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
172 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
174 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
178 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
181 if (ParseProvides(Ver
) == false)
187 // ListParser::Description - Return the description string /*{{{*/
188 // ---------------------------------------------------------------------
189 /* This is to return the string describing the package in debian
190 form. If this returns the blank string then the entry is assumed to
191 only describe package properties */
192 string
debListParser::Description()
194 string
const lang
= DescriptionLanguage();
196 return Section
.FindS("Description");
198 return Section
.FindS(string("Description-").append(lang
).c_str());
201 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
202 // ---------------------------------------------------------------------
203 /* This is to return the string describing the language of
204 description. If this returns the blank string then the entry is
205 assumed to describe original description. */
206 string
debListParser::DescriptionLanguage()
208 if (Section
.FindS("Description").empty() == false)
211 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
212 for (std::vector
<string
>::const_iterator l
= lang
.begin();
213 l
!= lang
.end(); ++l
)
214 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
220 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
221 // ---------------------------------------------------------------------
222 /* This is to return the md5 string to allow the check if it is the right
223 description. If no Description-md5 is found in the section it will be
226 MD5SumValue
debListParser::Description_md5()
228 string
const value
= Section
.FindS("Description-md5");
229 if (value
.empty() == true)
231 std::string
const desc
= Description() + "\n";
233 return MD5SumValue();
236 md5
.Add(desc
.c_str());
239 else if (likely(value
.size() == 32))
241 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
242 return MD5SumValue(value
);
243 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
244 return MD5SumValue();
246 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
247 return MD5SumValue();
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
)
257 if (Pkg
->Section
== 0)
258 Pkg
->Section
= UniqFindTagWrite("Section");
260 string
const static myArch
= _config
->Find("APT::Architecture");
261 // Possible values are: "all", "native", "installed" and "none"
262 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
263 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
264 if (essential
== "all" ||
265 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
266 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
268 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
271 if (strcmp(Pkg
.Name(),"apt") == 0)
273 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
275 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
277 Pkg
->Flags
|= pkgCache::Flag::Important
;
280 if (ParseStatus(Pkg
,Ver
) == false)
285 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
286 // ---------------------------------------------------------------------
288 unsigned short debListParser::VersionHash()
290 const char *Sections
[] ={"Installed-Size",
298 unsigned long Result
= INIT_FCS
;
300 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
304 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
307 /* Strip out any spaces from the text, this undoes dpkgs reformatting
308 of certain fields. dpkg also has the rather interesting notion of
309 reformatting depends operators < -> <= */
311 for (; Start
!= End
; ++Start
)
313 if (isspace(*Start
) != 0)
315 *J
++ = tolower_ascii(*Start
);
317 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
321 Result
= AddCRC16(Result
,S
,J
- S
);
327 // ListParser::ParseStatus - Parse the status field /*{{{*/
328 // ---------------------------------------------------------------------
329 /* Status lines are of the form,
330 Status: want flag status
331 want = unknown, install, hold, deinstall, purge
332 flag = ok, reinstreq, hold, hold-reinstreq
333 status = not-installed, unpacked, half-configured,
334 half-installed, config-files, post-inst-failed,
335 removal-failed, installed
337 Some of the above are obsolete (I think?) flag = hold-* and
338 status = post-inst-failed, removal-failed at least.
340 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
341 pkgCache::VerIterator
&Ver
)
345 if (Section
.Find("Status",Start
,Stop
) == false)
348 // UsePackage() is responsible for setting the flag in the default case
349 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
350 if (essential
== true &&
351 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
354 // Isolate the first word
355 const char *I
= Start
;
356 for(; I
< Stop
&& *I
!= ' '; I
++);
357 if (I
>= Stop
|| *I
!= ' ')
358 return _error
->Error("Malformed Status line");
360 // Process the want field
361 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
362 {"install",pkgCache::State::Install
},
363 {"hold",pkgCache::State::Hold
},
364 {"deinstall",pkgCache::State::DeInstall
},
365 {"purge",pkgCache::State::Purge
},
367 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
368 return _error
->Error("Malformed 1st word in the Status line");
370 // Isloate the next word
373 for(; I
< Stop
&& *I
!= ' '; I
++);
374 if (I
>= Stop
|| *I
!= ' ')
375 return _error
->Error("Malformed status line, no 2nd word");
377 // Process the flag field
378 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
379 {"reinstreq",pkgCache::State::ReInstReq
},
380 {"hold",pkgCache::State::HoldInst
},
381 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
383 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
384 return _error
->Error("Malformed 2nd word in the Status line");
386 // Isloate the last word
389 for(; I
< Stop
&& *I
!= ' '; I
++);
391 return _error
->Error("Malformed Status line, no 3rd word");
393 // Process the flag field
394 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
395 {"unpacked",pkgCache::State::UnPacked
},
396 {"half-configured",pkgCache::State::HalfConfigured
},
397 {"installed",pkgCache::State::Installed
},
398 {"half-installed",pkgCache::State::HalfInstalled
},
399 {"config-files",pkgCache::State::ConfigFiles
},
400 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
401 {"triggers-pending",pkgCache::State::TriggersPending
},
402 {"post-inst-failed",pkgCache::State::HalfConfigured
},
403 {"removal-failed",pkgCache::State::HalfInstalled
},
405 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
406 return _error
->Error("Malformed 3rd word in the Status line");
408 /* A Status line marks the package as indicating the current
409 version as well. Only if it is actually installed.. Otherwise
410 the interesting dpkg handling of the status file creates bogus
412 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
413 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
415 if (Ver
.end() == true)
416 _error
->Warning("Encountered status field in a non-version description");
418 Pkg
->CurrentVer
= Ver
.Index();
424 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
426 // Determine the operator
434 Op
= pkgCache::Dep::LessEq
;
441 Op
= pkgCache::Dep::Less
;
445 // < is the same as <= and << is really Cs < for some reason
446 Op
= pkgCache::Dep::LessEq
;
454 Op
= pkgCache::Dep::GreaterEq
;
461 Op
= pkgCache::Dep::Greater
;
465 // > is the same as >= and >> is really Cs > for some reason
466 Op
= pkgCache::Dep::GreaterEq
;
470 Op
= pkgCache::Dep::Equals
;
474 // HACK around bad package definitions
476 Op
= pkgCache::Dep::Equals
;
482 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
483 // ---------------------------------------------------------------------
484 /* This parses the dependency elements out of a standard string in place,
486 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
487 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
488 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
489 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
490 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
491 bool const &ParseArchFlags
)
492 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
493 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
494 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
495 bool const &ParseArchFlags
, bool const &StripMultiArch
)
496 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
497 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
498 string
&Package
,string
&Ver
,
499 unsigned int &Op
, bool const &ParseArchFlags
,
500 bool const &StripMultiArch
,
501 bool const &ParseRestrictionsList
)
503 // Strip off leading space
504 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
506 // Parse off the package name
507 const char *I
= Start
;
508 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
509 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
510 *I
!= '<' && *I
!= '>'; ++I
);
513 if (I
!= Stop
&& *I
== ')')
519 // Stash the package name
520 Package
.assign(Start
,I
- Start
);
522 // We don't want to confuse library users which can't handle MultiArch
523 string
const arch
= _config
->Find("APT::Architecture");
524 if (StripMultiArch
== true) {
525 size_t const found
= Package
.rfind(':');
526 if (found
!= string::npos
&&
527 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
528 strcmp(Package
.c_str() + found
, ":native") == 0 ||
529 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
530 Package
= Package
.substr(0,found
);
533 // Skip white space to the '('
534 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
537 if (I
!= Stop
&& *I
== '(')
540 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
543 I
= ConvertRelation(I
,Op
);
546 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
548 I
= (const char*) memchr(I
, ')', Stop
- I
);
549 if (I
== NULL
|| Start
== I
)
552 // Skip trailing whitespace
554 for (; End
> Start
&& isspace(End
[-1]); End
--);
556 Ver
.assign(Start
,End
-Start
);
562 Op
= pkgCache::Dep::NoOp
;
566 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
568 if (ParseArchFlags
== true)
570 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
572 // Parse an architecture
573 if (I
!= Stop
&& *I
== '[')
577 if (unlikely(I
== Stop
))
582 bool NegArch
= false;
585 // look for whitespace or ending ']'
586 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
588 if (unlikely(End
== Stop
))
597 std::string
arch(I
, End
);
598 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
603 // we found a match, so fast-forward to the end of the wildcards
604 for (; End
!= Stop
&& *End
!= ']'; ++End
);
613 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
620 Package
= ""; /* not for this arch */
624 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
627 if (ParseRestrictionsList
== true)
629 // Parse a restrictions list
630 if (I
!= Stop
&& *I
== '<')
634 if (unlikely(I
== Stop
))
637 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
641 bool NegRestriction
= false;
644 // look for whitespace or ending '>'
645 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
647 if (unlikely(End
== Stop
))
652 NegRestriction
= true;
656 std::string
restriction(I
, End
);
658 std::string prefix
= "profile.";
659 // only support for "profile" prefix, ignore others
660 if (restriction
.size() > prefix
.size() &&
661 restriction
.substr(0, prefix
.size()) == prefix
)
663 // get the name of the profile
664 restriction
= restriction
.substr(prefix
.size());
666 if (restriction
.empty() == false && profiles
.empty() == false &&
667 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
671 NegRestriction
= false;
672 // we found a match, so fast-forward to the end of the wildcards
673 for (; End
!= Stop
&& *End
!= '>'; ++End
);
683 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
686 if (NegRestriction
== true)
690 Package
= ""; /* not for this restriction */
694 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
697 if (I
!= Stop
&& *I
== '|')
698 Op
|= pkgCache::Dep::Or
;
700 if (I
== Stop
|| *I
== ',' || *I
== '|')
703 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
710 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
711 // ---------------------------------------------------------------------
712 /* This is the higher level depends parser. It takes a tag and generates
713 a complete depends tree for the given version. */
714 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
715 const char *Tag
,unsigned int Type
)
719 if (Section
.Find(Tag
,Start
,Stop
) == false)
722 string
const pkgArch
= Ver
.Arch();
730 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
732 return _error
->Error("Problem parsing dependency %s",Tag
);
733 size_t const found
= Package
.rfind(':');
735 // If negative is unspecific it needs to apply on all architectures
736 if (MultiArchEnabled
== true && found
== string::npos
&&
737 (Type
== pkgCache::Dep::Conflicts
||
738 Type
== pkgCache::Dep::DpkgBreaks
||
739 Type
== pkgCache::Dep::Replaces
))
741 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
742 a
!= Architectures
.end(); ++a
)
743 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
745 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
748 else if (MultiArchEnabled
== true && found
!= string::npos
&&
749 strcmp(Package
.c_str() + found
, ":any") != 0)
751 string Arch
= Package
.substr(found
+1, string::npos
);
752 Package
= Package
.substr(0, found
);
753 // Such dependencies are not supposed to be accepted …
754 // … but this is probably the best thing to do.
755 if (Arch
== "native")
756 Arch
= _config
->Find("APT::Architecture");
757 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
762 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
764 if ((Type
== pkgCache::Dep::Conflicts
||
765 Type
== pkgCache::Dep::DpkgBreaks
||
766 Type
== pkgCache::Dep::Replaces
) &&
767 NewDepends(Ver
, Package
,
768 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
769 Version
,Op
,Type
) == false)
778 // ListParser::ParseProvides - Parse the provides list /*{{{*/
779 // ---------------------------------------------------------------------
781 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
785 if (Section
.Find("Provides",Start
,Stop
) == true)
789 string
const Arch
= Ver
.Arch();
794 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
796 return _error
->Error("Problem parsing Provides line");
797 if (Op
!= pkgCache::Dep::NoOp
) {
798 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
799 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
800 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
803 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
812 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
814 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
815 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
817 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
818 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
823 // ListParser::NewProvides - add provides for all architectures /*{{{*/
824 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
825 string
const &Version
) {
826 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
827 a
!= Architectures
.end(); ++a
)
829 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
835 // ListParser::GrabWord - Matches a word and returns /*{{{*/
836 // ---------------------------------------------------------------------
837 /* Looks for a word in a list of words - for ParseStatus */
838 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
840 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
842 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
851 // ListParser::Step - Move to the next section in the file /*{{{*/
852 // ---------------------------------------------------------------------
853 /* This has to be careful to only process the correct architecture */
854 bool debListParser::Step()
856 iOffset
= Tags
.Offset();
857 while (Tags
.Step(Section
) == true)
859 /* See if this is the correct Architecture, if it isn't then we
860 drop the whole section. A missing arch tag only happens (in theory)
861 inside the Status file, so that is a positive return */
862 string
const Architecture
= Section
.FindS("Architecture");
864 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
866 if (APT::Configuration::checkArchitecture(Architecture
) == true)
868 /* parse version stanzas without an architecture only in the status file
869 (and as misfortune bycatch flat-archives) */
870 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
875 if (Architecture
== Arch
)
878 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
882 iOffset
= Tags
.Offset();
887 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
888 // ---------------------------------------------------------------------
890 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
891 FileFd
&File
, string component
)
893 // apt-secure does no longer download individual (per-section) Release
894 // file. to provide Component pinning we use the section name now
895 map_ptrloc
const storage
= WriteUniqString(component
);
896 FileI
->Component
= storage
;
898 pkgTagFile
TagFile(&File
, File
.Size());
899 pkgTagSection Section
;
900 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
904 #define APT_INRELEASE(TAG, STORE) \
905 data = Section.FindS(TAG); \
906 if (data.empty() == false) \
908 map_ptrloc const storage = WriteUniqString(data); \
911 APT_INRELEASE("Suite", FileI
->Archive
)
912 APT_INRELEASE("Component", FileI
->Component
)
913 APT_INRELEASE("Version", FileI
->Version
)
914 APT_INRELEASE("Origin", FileI
->Origin
)
915 APT_INRELEASE("Codename", FileI
->Codename
)
916 APT_INRELEASE("Label", FileI
->Label
)
918 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
919 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
921 return !_error
->PendingError();
924 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
925 // ---------------------------------------------------------------------
927 unsigned char debListParser::GetPrio(string Str
)
930 if (GrabWord(Str
,PrioList
,Out
) == false)
931 Out
= pkgCache::State::Extra
;