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 map_stringitem_t
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 string
const static myArch
= _config
->Find("APT::Architecture");
259 // Possible values are: "all", "native", "installed" and "none"
260 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
261 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
262 if (essential
== "all" ||
263 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
264 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
266 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
269 if (strcmp(Pkg
.Name(),"apt") == 0)
271 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
273 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
275 Pkg
->Flags
|= pkgCache::Flag::Important
;
278 if (ParseStatus(Pkg
,Ver
) == false)
283 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
284 // ---------------------------------------------------------------------
286 unsigned short debListParser::VersionHash()
288 const char *Sections
[] ={"Installed-Size",
296 unsigned long Result
= INIT_FCS
;
298 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
302 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
305 /* Strip out any spaces from the text, this undoes dpkgs reformatting
306 of certain fields. dpkg also has the rather interesting notion of
307 reformatting depends operators < -> <= */
309 for (; Start
!= End
; ++Start
)
311 if (isspace(*Start
) != 0)
313 *J
++ = tolower_ascii(*Start
);
315 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
319 Result
= AddCRC16(Result
,S
,J
- S
);
325 // ListParser::ParseStatus - Parse the status field /*{{{*/
326 // ---------------------------------------------------------------------
327 /* Status lines are of the form,
328 Status: want flag status
329 want = unknown, install, hold, deinstall, purge
330 flag = ok, reinstreq, hold, hold-reinstreq
331 status = not-installed, unpacked, half-configured,
332 half-installed, config-files, post-inst-failed,
333 removal-failed, installed
335 Some of the above are obsolete (I think?) flag = hold-* and
336 status = post-inst-failed, removal-failed at least.
338 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
339 pkgCache::VerIterator
&Ver
)
343 if (Section
.Find("Status",Start
,Stop
) == false)
346 // UsePackage() is responsible for setting the flag in the default case
347 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
348 if (essential
== true &&
349 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
352 // Isolate the first word
353 const char *I
= Start
;
354 for(; I
< Stop
&& *I
!= ' '; I
++);
355 if (I
>= Stop
|| *I
!= ' ')
356 return _error
->Error("Malformed Status line");
358 // Process the want field
359 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
360 {"install",pkgCache::State::Install
},
361 {"hold",pkgCache::State::Hold
},
362 {"deinstall",pkgCache::State::DeInstall
},
363 {"purge",pkgCache::State::Purge
},
365 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
366 return _error
->Error("Malformed 1st word in the Status line");
368 // Isloate the next word
371 for(; I
< Stop
&& *I
!= ' '; I
++);
372 if (I
>= Stop
|| *I
!= ' ')
373 return _error
->Error("Malformed status line, no 2nd word");
375 // Process the flag field
376 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
377 {"reinstreq",pkgCache::State::ReInstReq
},
378 {"hold",pkgCache::State::HoldInst
},
379 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
381 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
382 return _error
->Error("Malformed 2nd word in the Status line");
384 // Isloate the last word
387 for(; I
< Stop
&& *I
!= ' '; I
++);
389 return _error
->Error("Malformed Status line, no 3rd word");
391 // Process the flag field
392 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
393 {"unpacked",pkgCache::State::UnPacked
},
394 {"half-configured",pkgCache::State::HalfConfigured
},
395 {"installed",pkgCache::State::Installed
},
396 {"half-installed",pkgCache::State::HalfInstalled
},
397 {"config-files",pkgCache::State::ConfigFiles
},
398 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
399 {"triggers-pending",pkgCache::State::TriggersPending
},
400 {"post-inst-failed",pkgCache::State::HalfConfigured
},
401 {"removal-failed",pkgCache::State::HalfInstalled
},
403 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
404 return _error
->Error("Malformed 3rd word in the Status line");
406 /* A Status line marks the package as indicating the current
407 version as well. Only if it is actually installed.. Otherwise
408 the interesting dpkg handling of the status file creates bogus
410 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
411 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
413 if (Ver
.end() == true)
414 _error
->Warning("Encountered status field in a non-version description");
416 Pkg
->CurrentVer
= Ver
.Index();
422 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
424 // Determine the operator
432 Op
= pkgCache::Dep::LessEq
;
439 Op
= pkgCache::Dep::Less
;
443 // < is the same as <= and << is really Cs < for some reason
444 Op
= pkgCache::Dep::LessEq
;
452 Op
= pkgCache::Dep::GreaterEq
;
459 Op
= pkgCache::Dep::Greater
;
463 // > is the same as >= and >> is really Cs > for some reason
464 Op
= pkgCache::Dep::GreaterEq
;
468 Op
= pkgCache::Dep::Equals
;
472 // HACK around bad package definitions
474 Op
= pkgCache::Dep::Equals
;
480 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
481 // ---------------------------------------------------------------------
482 /* This parses the dependency elements out of a standard string in place,
484 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
485 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
486 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
487 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
488 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
489 bool const &ParseArchFlags
)
490 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
491 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
492 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
493 bool const &ParseArchFlags
, bool const &StripMultiArch
)
494 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
495 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
496 string
&Package
,string
&Ver
,
497 unsigned int &Op
, bool const &ParseArchFlags
,
498 bool const &StripMultiArch
,
499 bool const &ParseRestrictionsList
)
501 // Strip off leading space
502 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
504 // Parse off the package name
505 const char *I
= Start
;
506 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
507 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
508 *I
!= '<' && *I
!= '>'; ++I
);
511 if (I
!= Stop
&& *I
== ')')
517 // Stash the package name
518 Package
.assign(Start
,I
- Start
);
520 // We don't want to confuse library users which can't handle MultiArch
521 string
const arch
= _config
->Find("APT::Architecture");
522 if (StripMultiArch
== true) {
523 size_t const found
= Package
.rfind(':');
524 if (found
!= string::npos
&&
525 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
526 strcmp(Package
.c_str() + found
, ":native") == 0 ||
527 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
528 Package
= Package
.substr(0,found
);
531 // Skip white space to the '('
532 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
535 if (I
!= Stop
&& *I
== '(')
538 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
541 I
= ConvertRelation(I
,Op
);
544 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
546 I
= (const char*) memchr(I
, ')', Stop
- I
);
547 if (I
== NULL
|| Start
== I
)
550 // Skip trailing whitespace
552 for (; End
> Start
&& isspace(End
[-1]); End
--);
554 Ver
.assign(Start
,End
-Start
);
560 Op
= pkgCache::Dep::NoOp
;
564 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
566 if (ParseArchFlags
== true)
568 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
570 // Parse an architecture
571 if (I
!= Stop
&& *I
== '[')
575 if (unlikely(I
== Stop
))
580 bool NegArch
= false;
583 // look for whitespace or ending ']'
584 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
586 if (unlikely(End
== Stop
))
595 std::string
arch(I
, End
);
596 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
601 // we found a match, so fast-forward to the end of the wildcards
602 for (; End
!= Stop
&& *End
!= ']'; ++End
);
611 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
618 Package
= ""; /* not for this arch */
622 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
625 if (ParseRestrictionsList
== true)
627 // Parse a restrictions list
628 if (I
!= Stop
&& *I
== '<')
632 if (unlikely(I
== Stop
))
635 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
639 bool NegRestriction
= false;
642 // look for whitespace or ending '>'
643 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
645 if (unlikely(End
== Stop
))
650 NegRestriction
= true;
654 std::string
restriction(I
, End
);
656 std::string prefix
= "profile.";
657 // only support for "profile" prefix, ignore others
658 if (restriction
.size() > prefix
.size() &&
659 restriction
.substr(0, prefix
.size()) == prefix
)
661 // get the name of the profile
662 restriction
= restriction
.substr(prefix
.size());
664 if (restriction
.empty() == false && profiles
.empty() == false &&
665 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
669 NegRestriction
= false;
670 // we found a match, so fast-forward to the end of the wildcards
671 for (; End
!= Stop
&& *End
!= '>'; ++End
);
681 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
684 if (NegRestriction
== true)
688 Package
= ""; /* not for this restriction */
692 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
695 if (I
!= Stop
&& *I
== '|')
696 Op
|= pkgCache::Dep::Or
;
698 if (I
== Stop
|| *I
== ',' || *I
== '|')
701 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
708 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
709 // ---------------------------------------------------------------------
710 /* This is the higher level depends parser. It takes a tag and generates
711 a complete depends tree for the given version. */
712 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
713 const char *Tag
,unsigned int Type
)
717 if (Section
.Find(Tag
,Start
,Stop
) == false)
720 string
const pkgArch
= Ver
.Arch();
728 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
730 return _error
->Error("Problem parsing dependency %s",Tag
);
731 size_t const found
= Package
.rfind(':');
733 // If negative is unspecific it needs to apply on all architectures
734 if (MultiArchEnabled
== true && found
== string::npos
&&
735 (Type
== pkgCache::Dep::Conflicts
||
736 Type
== pkgCache::Dep::DpkgBreaks
||
737 Type
== pkgCache::Dep::Replaces
))
739 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
740 a
!= Architectures
.end(); ++a
)
741 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
743 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
746 else if (MultiArchEnabled
== true && found
!= string::npos
&&
747 strcmp(Package
.c_str() + found
, ":any") != 0)
749 string Arch
= Package
.substr(found
+1, string::npos
);
750 Package
= Package
.substr(0, found
);
751 // Such dependencies are not supposed to be accepted …
752 // … but this is probably the best thing to do.
753 if (Arch
== "native")
754 Arch
= _config
->Find("APT::Architecture");
755 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
760 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
762 if ((Type
== pkgCache::Dep::Conflicts
||
763 Type
== pkgCache::Dep::DpkgBreaks
||
764 Type
== pkgCache::Dep::Replaces
) &&
765 NewDepends(Ver
, Package
,
766 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
767 Version
,Op
,Type
) == false)
776 // ListParser::ParseProvides - Parse the provides list /*{{{*/
777 // ---------------------------------------------------------------------
779 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
783 if (Section
.Find("Provides",Start
,Stop
) == true)
787 string
const Arch
= Ver
.Arch();
792 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
794 return _error
->Error("Problem parsing Provides line");
795 if (Op
!= pkgCache::Dep::NoOp
) {
796 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
797 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
798 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
801 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
810 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
812 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
813 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
815 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
816 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
821 // ListParser::NewProvides - add provides for all architectures /*{{{*/
822 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
823 string
const &Version
) {
824 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
825 a
!= Architectures
.end(); ++a
)
827 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
833 // ListParser::GrabWord - Matches a word and returns /*{{{*/
834 // ---------------------------------------------------------------------
835 /* Looks for a word in a list of words - for ParseStatus */
836 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
838 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
840 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
849 // ListParser::Step - Move to the next section in the file /*{{{*/
850 // ---------------------------------------------------------------------
851 /* This has to be careful to only process the correct architecture */
852 bool debListParser::Step()
854 iOffset
= Tags
.Offset();
855 while (Tags
.Step(Section
) == true)
857 /* See if this is the correct Architecture, if it isn't then we
858 drop the whole section. A missing arch tag only happens (in theory)
859 inside the Status file, so that is a positive return */
860 string
const Architecture
= Section
.FindS("Architecture");
862 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
864 if (APT::Configuration::checkArchitecture(Architecture
) == true)
866 /* parse version stanzas without an architecture only in the status file
867 (and as misfortune bycatch flat-archives) */
868 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
873 if (Architecture
== Arch
)
876 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
880 iOffset
= Tags
.Offset();
885 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
886 // ---------------------------------------------------------------------
888 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
889 FileFd
&File
, string component
)
891 // apt-secure does no longer download individual (per-section) Release
892 // file. to provide Component pinning we use the section name now
893 map_stringitem_t
const storage
= WriteUniqString(component
);
894 FileI
->Component
= storage
;
896 pkgTagFile
TagFile(&File
, File
.Size());
897 pkgTagSection Section
;
898 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
902 #define APT_INRELEASE(TAG, STORE) \
903 data = Section.FindS(TAG); \
904 if (data.empty() == false) \
906 map_stringitem_t const storage = WriteUniqString(data); \
909 APT_INRELEASE("Suite", FileI
->Archive
)
910 APT_INRELEASE("Component", FileI
->Component
)
911 APT_INRELEASE("Version", FileI
->Version
)
912 APT_INRELEASE("Origin", FileI
->Origin
)
913 APT_INRELEASE("Codename", FileI
->Codename
)
914 APT_INRELEASE("Label", FileI
->Label
)
916 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
917 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
919 return !_error
->PendingError();
922 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
923 // ---------------------------------------------------------------------
925 unsigned char debListParser::GetPrio(string Str
)
928 if (GrabWord(Str
,PrioList
,Out
) == false)
929 Out
= pkgCache::State::Extra
;
934 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
935 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
936 pkgCache::VerIterator
const &Ver
)
938 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
940 // status file has no (Download)Size, but all others are fair game
941 // status file is parsed last, so the first version we encounter is
942 // probably also the version we have downloaded
943 unsigned long long const Size
= Section
.FindULL("Size");
944 if (Size
!= 0 && Size
!= Ver
->Size
)
946 // available everywhere, but easier to check here than to include in VersionHash
947 unsigned char MultiArch
= ParseMultiArch(false);
948 if (MultiArch
!= Ver
->MultiArch
)
950 // for all practical proposes (we can check): same version
957 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
958 : debListParser(File
, ""), DebFile(DebFile
)
962 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
963 pkgCache::VerIterator
&Ver
)
965 bool res
= debListParser::UsePackage(Pkg
, Ver
);
966 // we use the full file path as a provides so that the file is found
968 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)