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)
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 Ver
->Section
= UniqFindTagWrite("Section");
149 Ver
->MultiArch
= ParseMultiArch(true);
151 Ver
->Size
= Section
.FindULL("Size");
152 // Unpacked Size (in K)
153 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
154 Ver
->InstalledSize
*= 1024;
159 if (Section
.Find("Priority",Start
,Stop
) == true)
161 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
162 Ver
->Priority
= pkgCache::State::Extra
;
165 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
167 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
169 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
171 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
173 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
175 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
177 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
179 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
183 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
186 if (ParseProvides(Ver
) == false)
192 // ListParser::Description - Return the description string /*{{{*/
193 // ---------------------------------------------------------------------
194 /* This is to return the string describing the package in debian
195 form. If this returns the blank string then the entry is assumed to
196 only describe package properties */
197 string
debListParser::Description(std::string
const &lang
)
200 return Section
.FindS("Description");
202 return Section
.FindS(string("Description-").append(lang
).c_str());
205 // ListParser::AvailableDescriptionLanguages /*{{{*/
206 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages()
208 std::vector
<std::string
> const understood
= APT::Configuration::getLanguages();
209 std::vector
<std::string
> avail
;
210 if (Section
.Exists("Description") == true)
212 for (std::vector
<std::string
>::const_iterator lang
= understood
.begin(); lang
!= understood
.end(); ++lang
)
214 std::string
const tagname
= "Description-" + *lang
;
215 if (Section
.Exists(tagname
.c_str()) == true)
216 avail
.push_back(*lang
);
221 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
222 // ---------------------------------------------------------------------
223 /* This is to return the md5 string to allow the check if it is the right
224 description. If no Description-md5 is found in the section it will be
227 MD5SumValue
debListParser::Description_md5()
229 string
const value
= Section
.FindS("Description-md5");
230 if (value
.empty() == true)
232 std::string
const desc
= Description("") + "\n";
234 return MD5SumValue();
237 md5
.Add(desc
.c_str());
240 else if (likely(value
.size() == 32))
242 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
243 return MD5SumValue(value
);
244 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
245 return MD5SumValue();
247 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
248 return MD5SumValue();
251 // ListParser::UsePackage - Update a package structure /*{{{*/
252 // ---------------------------------------------------------------------
253 /* This is called to update the package with any new information
254 that might be found in the section */
255 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
256 pkgCache::VerIterator
&Ver
)
258 if (Pkg
->Section
== 0)
259 Pkg
->Section
= UniqFindTagWrite("Section");
261 string
const static myArch
= _config
->Find("APT::Architecture");
262 // Possible values are: "all", "native", "installed" and "none"
263 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
264 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
265 if (essential
== "all" ||
266 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
267 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
269 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
272 if (strcmp(Pkg
.Name(),"apt") == 0)
274 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
276 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
278 Pkg
->Flags
|= pkgCache::Flag::Important
;
281 if (ParseStatus(Pkg
,Ver
) == false)
286 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
287 // ---------------------------------------------------------------------
289 unsigned short debListParser::VersionHash()
291 const char *Sections
[] ={"Installed-Size",
299 unsigned long Result
= INIT_FCS
;
301 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
305 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
308 /* Strip out any spaces from the text, this undoes dpkgs reformatting
309 of certain fields. dpkg also has the rather interesting notion of
310 reformatting depends operators < -> <= */
312 for (; Start
!= End
; ++Start
)
314 if (isspace(*Start
) != 0)
316 *J
++ = tolower_ascii(*Start
);
318 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
322 Result
= AddCRC16(Result
,S
,J
- S
);
328 // ListParser::ParseStatus - Parse the status field /*{{{*/
329 // ---------------------------------------------------------------------
330 /* Status lines are of the form,
331 Status: want flag status
332 want = unknown, install, hold, deinstall, purge
333 flag = ok, reinstreq, hold, hold-reinstreq
334 status = not-installed, unpacked, half-configured,
335 half-installed, config-files, post-inst-failed,
336 removal-failed, installed
338 Some of the above are obsolete (I think?) flag = hold-* and
339 status = post-inst-failed, removal-failed at least.
341 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
342 pkgCache::VerIterator
&Ver
)
346 if (Section
.Find("Status",Start
,Stop
) == false)
349 // UsePackage() is responsible for setting the flag in the default case
350 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
351 if (essential
== true &&
352 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
355 // Isolate the first word
356 const char *I
= Start
;
357 for(; I
< Stop
&& *I
!= ' '; I
++);
358 if (I
>= Stop
|| *I
!= ' ')
359 return _error
->Error("Malformed Status line");
361 // Process the want field
362 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
363 {"install",pkgCache::State::Install
},
364 {"hold",pkgCache::State::Hold
},
365 {"deinstall",pkgCache::State::DeInstall
},
366 {"purge",pkgCache::State::Purge
},
368 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
369 return _error
->Error("Malformed 1st word in the Status line");
371 // Isloate the next word
374 for(; I
< Stop
&& *I
!= ' '; I
++);
375 if (I
>= Stop
|| *I
!= ' ')
376 return _error
->Error("Malformed status line, no 2nd word");
378 // Process the flag field
379 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
380 {"reinstreq",pkgCache::State::ReInstReq
},
381 {"hold",pkgCache::State::HoldInst
},
382 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
384 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
385 return _error
->Error("Malformed 2nd word in the Status line");
387 // Isloate the last word
390 for(; I
< Stop
&& *I
!= ' '; I
++);
392 return _error
->Error("Malformed Status line, no 3rd word");
394 // Process the flag field
395 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
396 {"unpacked",pkgCache::State::UnPacked
},
397 {"half-configured",pkgCache::State::HalfConfigured
},
398 {"installed",pkgCache::State::Installed
},
399 {"half-installed",pkgCache::State::HalfInstalled
},
400 {"config-files",pkgCache::State::ConfigFiles
},
401 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
402 {"triggers-pending",pkgCache::State::TriggersPending
},
403 {"post-inst-failed",pkgCache::State::HalfConfigured
},
404 {"removal-failed",pkgCache::State::HalfInstalled
},
406 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
407 return _error
->Error("Malformed 3rd word in the Status line");
409 /* A Status line marks the package as indicating the current
410 version as well. Only if it is actually installed.. Otherwise
411 the interesting dpkg handling of the status file creates bogus
413 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
414 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
416 if (Ver
.end() == true)
417 _error
->Warning("Encountered status field in a non-version description");
419 Pkg
->CurrentVer
= Ver
.Index();
425 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
427 // Determine the operator
435 Op
= pkgCache::Dep::LessEq
;
442 Op
= pkgCache::Dep::Less
;
446 // < is the same as <= and << is really Cs < for some reason
447 Op
= pkgCache::Dep::LessEq
;
455 Op
= pkgCache::Dep::GreaterEq
;
462 Op
= pkgCache::Dep::Greater
;
466 // > is the same as >= and >> is really Cs > for some reason
467 Op
= pkgCache::Dep::GreaterEq
;
471 Op
= pkgCache::Dep::Equals
;
475 // HACK around bad package definitions
477 Op
= pkgCache::Dep::Equals
;
483 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
484 // ---------------------------------------------------------------------
485 /* This parses the dependency elements out of a standard string in place,
487 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
488 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
489 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
490 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
491 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
492 bool const &ParseArchFlags
)
493 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
494 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
495 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
496 bool const &ParseArchFlags
, bool const &StripMultiArch
)
497 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
498 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
499 string
&Package
,string
&Ver
,
500 unsigned int &Op
, bool const &ParseArchFlags
,
501 bool const &StripMultiArch
,
502 bool const &ParseRestrictionsList
)
504 // Strip off leading space
505 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
507 // Parse off the package name
508 const char *I
= Start
;
509 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
510 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
511 *I
!= '<' && *I
!= '>'; ++I
);
514 if (I
!= Stop
&& *I
== ')')
520 // Stash the package name
521 Package
.assign(Start
,I
- Start
);
523 // We don't want to confuse library users which can't handle MultiArch
524 string
const arch
= _config
->Find("APT::Architecture");
525 if (StripMultiArch
== true) {
526 size_t const found
= Package
.rfind(':');
527 if (found
!= string::npos
&&
528 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
529 strcmp(Package
.c_str() + found
, ":native") == 0 ||
530 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
531 Package
= Package
.substr(0,found
);
534 // Skip white space to the '('
535 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
538 if (I
!= Stop
&& *I
== '(')
541 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
544 I
= ConvertRelation(I
,Op
);
547 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
549 I
= (const char*) memchr(I
, ')', Stop
- I
);
550 if (I
== NULL
|| Start
== I
)
553 // Skip trailing whitespace
555 for (; End
> Start
&& isspace(End
[-1]); End
--);
557 Ver
.assign(Start
,End
-Start
);
563 Op
= pkgCache::Dep::NoOp
;
567 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
569 if (ParseArchFlags
== true)
571 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
573 // Parse an architecture
574 if (I
!= Stop
&& *I
== '[')
578 if (unlikely(I
== Stop
))
583 bool NegArch
= false;
586 // look for whitespace or ending ']'
587 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
589 if (unlikely(End
== Stop
))
598 std::string
arch(I
, End
);
599 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
604 // we found a match, so fast-forward to the end of the wildcards
605 for (; End
!= Stop
&& *End
!= ']'; ++End
);
614 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
621 Package
= ""; /* not for this arch */
625 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
628 if (ParseRestrictionsList
== true)
630 // Parse a restrictions list
631 if (I
!= Stop
&& *I
== '<')
635 if (unlikely(I
== Stop
))
638 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
642 bool NegRestriction
= false;
645 // look for whitespace or ending '>'
646 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
648 if (unlikely(End
== Stop
))
653 NegRestriction
= true;
657 std::string
restriction(I
, End
);
659 std::string prefix
= "profile.";
660 // only support for "profile" prefix, ignore others
661 if (restriction
.size() > prefix
.size() &&
662 restriction
.substr(0, prefix
.size()) == prefix
)
664 // get the name of the profile
665 restriction
= restriction
.substr(prefix
.size());
667 if (restriction
.empty() == false && profiles
.empty() == false &&
668 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
672 NegRestriction
= false;
673 // we found a match, so fast-forward to the end of the wildcards
674 for (; End
!= Stop
&& *End
!= '>'; ++End
);
684 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
687 if (NegRestriction
== true)
691 Package
= ""; /* not for this restriction */
695 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
698 if (I
!= Stop
&& *I
== '|')
699 Op
|= pkgCache::Dep::Or
;
701 if (I
== Stop
|| *I
== ',' || *I
== '|')
704 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
711 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
712 // ---------------------------------------------------------------------
713 /* This is the higher level depends parser. It takes a tag and generates
714 a complete depends tree for the given version. */
715 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
716 const char *Tag
,unsigned int Type
)
720 if (Section
.Find(Tag
,Start
,Stop
) == false)
723 string
const pkgArch
= Ver
.Arch();
731 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
733 return _error
->Error("Problem parsing dependency %s",Tag
);
734 size_t const found
= Package
.rfind(':');
736 // If negative is unspecific it needs to apply on all architectures
737 if (MultiArchEnabled
== true && found
== string::npos
&&
738 (Type
== pkgCache::Dep::Conflicts
||
739 Type
== pkgCache::Dep::DpkgBreaks
||
740 Type
== pkgCache::Dep::Replaces
))
742 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
743 a
!= Architectures
.end(); ++a
)
744 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
746 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
749 else if (MultiArchEnabled
== true && found
!= string::npos
&&
750 strcmp(Package
.c_str() + found
, ":any") != 0)
752 string Arch
= Package
.substr(found
+1, string::npos
);
753 Package
= Package
.substr(0, found
);
754 // Such dependencies are not supposed to be accepted …
755 // … but this is probably the best thing to do.
756 if (Arch
== "native")
757 Arch
= _config
->Find("APT::Architecture");
758 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
763 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
765 if ((Type
== pkgCache::Dep::Conflicts
||
766 Type
== pkgCache::Dep::DpkgBreaks
||
767 Type
== pkgCache::Dep::Replaces
) &&
768 NewDepends(Ver
, Package
,
769 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
770 Version
,Op
,Type
) == false)
779 // ListParser::ParseProvides - Parse the provides list /*{{{*/
780 // ---------------------------------------------------------------------
782 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
786 if (Section
.Find("Provides",Start
,Stop
) == true)
790 string
const Arch
= Ver
.Arch();
795 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
797 return _error
->Error("Problem parsing Provides line");
798 if (Op
!= pkgCache::Dep::NoOp
) {
799 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
800 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
801 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
804 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
813 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
815 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
816 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
818 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
819 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
824 // ListParser::NewProvides - add provides for all architectures /*{{{*/
825 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
826 string
const &Version
) {
827 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
828 a
!= Architectures
.end(); ++a
)
830 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
836 // ListParser::GrabWord - Matches a word and returns /*{{{*/
837 // ---------------------------------------------------------------------
838 /* Looks for a word in a list of words - for ParseStatus */
839 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
841 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
843 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
852 // ListParser::Step - Move to the next section in the file /*{{{*/
853 // ---------------------------------------------------------------------
854 /* This has to be careful to only process the correct architecture */
855 bool debListParser::Step()
857 iOffset
= Tags
.Offset();
858 while (Tags
.Step(Section
) == true)
860 /* See if this is the correct Architecture, if it isn't then we
861 drop the whole section. A missing arch tag only happens (in theory)
862 inside the Status file, so that is a positive return */
863 string
const Architecture
= Section
.FindS("Architecture");
865 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
867 if (APT::Configuration::checkArchitecture(Architecture
) == true)
869 /* parse version stanzas without an architecture only in the status file
870 (and as misfortune bycatch flat-archives) */
871 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
876 if (Architecture
== Arch
)
879 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
883 iOffset
= Tags
.Offset();
888 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
889 // ---------------------------------------------------------------------
891 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
892 FileFd
&File
, string component
)
894 // apt-secure does no longer download individual (per-section) Release
895 // file. to provide Component pinning we use the section name now
896 map_ptrloc
const storage
= WriteUniqString(component
);
897 FileI
->Component
= storage
;
899 pkgTagFile
TagFile(&File
, File
.Size());
900 pkgTagSection Section
;
901 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
905 #define APT_INRELEASE(TAG, STORE) \
906 data = Section.FindS(TAG); \
907 if (data.empty() == false) \
909 map_ptrloc const storage = WriteUniqString(data); \
912 APT_INRELEASE("Suite", FileI
->Archive
)
913 APT_INRELEASE("Component", FileI
->Component
)
914 APT_INRELEASE("Version", FileI
->Version
)
915 APT_INRELEASE("Origin", FileI
->Origin
)
916 APT_INRELEASE("Codename", FileI
->Codename
)
917 APT_INRELEASE("Label", FileI
->Label
)
919 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
920 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
922 return !_error
->PendingError();
925 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
926 // ---------------------------------------------------------------------
928 unsigned char debListParser::GetPrio(string Str
)
931 if (GrabWord(Str
,PrioList
,Out
) == false)
932 Out
= pkgCache::State::Extra
;
937 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
938 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
939 pkgCache::VerIterator
const &Ver
)
941 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
943 // status file has no (Download)Size, but all others are fair game
944 // status file is parsed last, so the first version we encounter is
945 // probably also the version we have downloaded
946 unsigned long long const Size
= Section
.FindULL("Size");
947 if (Size
!= 0 && Size
!= Ver
->Size
)
949 // available everywhere, but easier to check here than to include in VersionHash
950 unsigned char MultiArch
= ParseMultiArch(false);
951 if (MultiArch
!= Ver
->MultiArch
)
953 // for all practical proposes (we can check): same version
960 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
961 : debListParser(File
, ""), DebFile(DebFile
)
965 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
966 pkgCache::VerIterator
&Ver
)
968 bool res
= debListParser::UsePackage(Pkg
, Ver
);
969 // we use the full file path as a provides so that the file is found
971 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)