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::Package - Return the package name /*{{{*/
62 // ---------------------------------------------------------------------
63 /* This is to return the name of the package this section describes */
64 string
debListParser::Package() {
65 string
const Result
= Section
.FindS("Package");
66 if(unlikely(Result
.empty() == true))
67 _error
->Error("Encountered a section with no Package: header");
71 // ListParser::Architecture - Return the package arch /*{{{*/
72 // ---------------------------------------------------------------------
73 /* This will return the Architecture of the package this section describes */
74 string
debListParser::Architecture() {
75 return Section
.FindS("Architecture");
78 // ListParser::ArchitectureAll /*{{{*/
79 // ---------------------------------------------------------------------
81 bool debListParser::ArchitectureAll() {
82 return Section
.FindS("Architecture") == "all";
85 // ListParser::Version - Return the version string /*{{{*/
86 // ---------------------------------------------------------------------
87 /* This is to return the string describing the version in debian form,
88 epoch:upstream-release. If this returns the blank string then the
89 entry is assumed to only describe package properties */
90 string
debListParser::Version()
92 return Section
.FindS("Version");
95 unsigned char debListParser::ParseMultiArch(bool const showErrors
) /*{{{*/
98 string
const MultiArch
= Section
.FindS("Multi-Arch");
99 if (MultiArch
.empty() == true || MultiArch
== "no")
100 MA
= pkgCache::Version::None
;
101 else if (MultiArch
== "same") {
102 if (ArchitectureAll() == true)
104 if (showErrors
== true)
105 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
106 Section
.FindS("Package").c_str());
107 MA
= pkgCache::Version::None
;
110 MA
= pkgCache::Version::Same
;
112 else if (MultiArch
== "foreign")
113 MA
= pkgCache::Version::Foreign
;
114 else if (MultiArch
== "allowed")
115 MA
= pkgCache::Version::Allowed
;
118 if (showErrors
== true)
119 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
120 MultiArch
.c_str(), Section
.FindS("Package").c_str());
121 MA
= pkgCache::Version::None
;
124 if (ArchitectureAll() == true)
125 MA
|= pkgCache::Version::All
;
130 // ListParser::NewVersion - Fill in the version structure /*{{{*/
131 // ---------------------------------------------------------------------
133 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
139 if (Section
.Find("Section",Start
,Stop
) == true)
141 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::SECTION
, Start
, Stop
- Start
);
145 Ver
->MultiArch
= ParseMultiArch(true);
147 Ver
->Size
= Section
.FindULL("Size");
148 // Unpacked Size (in K)
149 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
150 Ver
->InstalledSize
*= 1024;
153 if (Section
.Find("Priority",Start
,Stop
) == true)
155 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
156 Ver
->Priority
= pkgCache::State::Extra
;
159 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
161 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
163 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
165 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
167 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
169 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
171 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
173 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
177 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
180 if (ParseProvides(Ver
) == false)
186 // ListParser::Description - Return the description string /*{{{*/
187 // ---------------------------------------------------------------------
188 /* This is to return the string describing the package in debian
189 form. If this returns the blank string then the entry is assumed to
190 only describe package properties */
191 string
debListParser::Description(std::string
const &lang
)
194 return Section
.FindS("Description");
196 return Section
.FindS(string("Description-").append(lang
).c_str());
199 // ListParser::AvailableDescriptionLanguages /*{{{*/
200 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages()
202 std::vector
<std::string
> const understood
= APT::Configuration::getLanguages();
203 std::vector
<std::string
> avail
;
204 if (Section
.Exists("Description") == true)
206 for (std::vector
<std::string
>::const_iterator lang
= understood
.begin(); lang
!= understood
.end(); ++lang
)
208 std::string
const tagname
= "Description-" + *lang
;
209 if (Section
.Exists(tagname
.c_str()) == true)
210 avail
.push_back(*lang
);
215 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
216 // ---------------------------------------------------------------------
217 /* This is to return the md5 string to allow the check if it is the right
218 description. If no Description-md5 is found in the section it will be
221 MD5SumValue
debListParser::Description_md5()
223 string
const value
= Section
.FindS("Description-md5");
224 if (value
.empty() == true)
226 std::string
const desc
= Description("") + "\n";
228 return MD5SumValue();
231 md5
.Add(desc
.c_str());
234 else if (likely(value
.size() == 32))
236 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
237 return MD5SumValue(value
);
238 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
239 return MD5SumValue();
241 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
242 return MD5SumValue();
245 // ListParser::UsePackage - Update a package structure /*{{{*/
246 // ---------------------------------------------------------------------
247 /* This is called to update the package with any new information
248 that might be found in the section */
249 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
250 pkgCache::VerIterator
&Ver
)
252 string
const static myArch
= _config
->Find("APT::Architecture");
253 // Possible values are: "all", "native", "installed" and "none"
254 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
255 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
256 if (essential
== "all" ||
257 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
258 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
260 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
263 if (strcmp(Pkg
.Name(),"apt") == 0)
265 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
267 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
269 Pkg
->Flags
|= pkgCache::Flag::Important
;
272 if (ParseStatus(Pkg
,Ver
) == false)
277 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
278 // ---------------------------------------------------------------------
280 unsigned short debListParser::VersionHash()
282 const char *Sections
[] ={"Installed-Size",
290 unsigned long Result
= INIT_FCS
;
292 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
296 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
299 /* Strip out any spaces from the text, this undoes dpkgs reformatting
300 of certain fields. dpkg also has the rather interesting notion of
301 reformatting depends operators < -> <= */
303 for (; Start
!= End
; ++Start
)
305 if (isspace(*Start
) != 0)
307 *J
++ = tolower_ascii(*Start
);
309 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
313 Result
= AddCRC16(Result
,S
,J
- S
);
319 // ListParser::ParseStatus - Parse the status field /*{{{*/
320 // ---------------------------------------------------------------------
321 /* Status lines are of the form,
322 Status: want flag status
323 want = unknown, install, hold, deinstall, purge
324 flag = ok, reinstreq, hold, hold-reinstreq
325 status = not-installed, unpacked, half-configured,
326 half-installed, config-files, post-inst-failed,
327 removal-failed, installed
329 Some of the above are obsolete (I think?) flag = hold-* and
330 status = post-inst-failed, removal-failed at least.
332 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
333 pkgCache::VerIterator
&Ver
)
337 if (Section
.Find("Status",Start
,Stop
) == false)
340 // UsePackage() is responsible for setting the flag in the default case
341 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
342 if (essential
== true &&
343 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
346 // Isolate the first word
347 const char *I
= Start
;
348 for(; I
< Stop
&& *I
!= ' '; I
++);
349 if (I
>= Stop
|| *I
!= ' ')
350 return _error
->Error("Malformed Status line");
352 // Process the want field
353 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
354 {"install",pkgCache::State::Install
},
355 {"hold",pkgCache::State::Hold
},
356 {"deinstall",pkgCache::State::DeInstall
},
357 {"purge",pkgCache::State::Purge
},
359 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
360 return _error
->Error("Malformed 1st word in the Status line");
362 // Isloate the next word
365 for(; I
< Stop
&& *I
!= ' '; I
++);
366 if (I
>= Stop
|| *I
!= ' ')
367 return _error
->Error("Malformed status line, no 2nd word");
369 // Process the flag field
370 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
371 {"reinstreq",pkgCache::State::ReInstReq
},
372 {"hold",pkgCache::State::HoldInst
},
373 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
375 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
376 return _error
->Error("Malformed 2nd word in the Status line");
378 // Isloate the last word
381 for(; I
< Stop
&& *I
!= ' '; I
++);
383 return _error
->Error("Malformed Status line, no 3rd word");
385 // Process the flag field
386 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
387 {"unpacked",pkgCache::State::UnPacked
},
388 {"half-configured",pkgCache::State::HalfConfigured
},
389 {"installed",pkgCache::State::Installed
},
390 {"half-installed",pkgCache::State::HalfInstalled
},
391 {"config-files",pkgCache::State::ConfigFiles
},
392 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
393 {"triggers-pending",pkgCache::State::TriggersPending
},
394 {"post-inst-failed",pkgCache::State::HalfConfigured
},
395 {"removal-failed",pkgCache::State::HalfInstalled
},
397 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
398 return _error
->Error("Malformed 3rd word in the Status line");
400 /* A Status line marks the package as indicating the current
401 version as well. Only if it is actually installed.. Otherwise
402 the interesting dpkg handling of the status file creates bogus
404 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
405 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
407 if (Ver
.end() == true)
408 _error
->Warning("Encountered status field in a non-version description");
410 Pkg
->CurrentVer
= Ver
.Index();
416 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
418 // Determine the operator
426 Op
= pkgCache::Dep::LessEq
;
433 Op
= pkgCache::Dep::Less
;
437 // < is the same as <= and << is really Cs < for some reason
438 Op
= pkgCache::Dep::LessEq
;
446 Op
= pkgCache::Dep::GreaterEq
;
453 Op
= pkgCache::Dep::Greater
;
457 // > is the same as >= and >> is really Cs > for some reason
458 Op
= pkgCache::Dep::GreaterEq
;
462 Op
= pkgCache::Dep::Equals
;
466 // HACK around bad package definitions
468 Op
= pkgCache::Dep::Equals
;
474 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
475 // ---------------------------------------------------------------------
476 /* This parses the dependency elements out of a standard string in place,
478 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
479 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
480 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
481 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
482 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
483 bool const &ParseArchFlags
)
484 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
485 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
486 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
487 bool const &ParseArchFlags
, bool const &StripMultiArch
)
488 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
489 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
490 string
&Package
,string
&Ver
,
491 unsigned int &Op
, bool const &ParseArchFlags
,
492 bool const &StripMultiArch
,
493 bool const &ParseRestrictionsList
)
495 // Strip off leading space
496 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
498 // Parse off the package name
499 const char *I
= Start
;
500 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
501 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
502 *I
!= '<' && *I
!= '>'; ++I
);
505 if (I
!= Stop
&& *I
== ')')
511 // Stash the package name
512 Package
.assign(Start
,I
- Start
);
514 // We don't want to confuse library users which can't handle MultiArch
515 string
const arch
= _config
->Find("APT::Architecture");
516 if (StripMultiArch
== true) {
517 size_t const found
= Package
.rfind(':');
518 if (found
!= string::npos
&&
519 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
520 strcmp(Package
.c_str() + found
, ":native") == 0 ||
521 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
522 Package
= Package
.substr(0,found
);
525 // Skip white space to the '('
526 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
529 if (I
!= Stop
&& *I
== '(')
532 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
535 I
= ConvertRelation(I
,Op
);
538 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
540 I
= (const char*) memchr(I
, ')', Stop
- I
);
541 if (I
== NULL
|| Start
== I
)
544 // Skip trailing whitespace
546 for (; End
> Start
&& isspace(End
[-1]); End
--);
548 Ver
.assign(Start
,End
-Start
);
554 Op
= pkgCache::Dep::NoOp
;
558 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
560 if (ParseArchFlags
== true)
562 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
564 // Parse an architecture
565 if (I
!= Stop
&& *I
== '[')
569 if (unlikely(I
== Stop
))
574 bool NegArch
= false;
577 // look for whitespace or ending ']'
578 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
580 if (unlikely(End
== Stop
))
589 std::string
arch(I
, End
);
590 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
595 // we found a match, so fast-forward to the end of the wildcards
596 for (; End
!= Stop
&& *End
!= ']'; ++End
);
605 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
612 Package
= ""; /* not for this arch */
616 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
619 if (ParseRestrictionsList
== true)
621 // Parse a restrictions list
622 if (I
!= Stop
&& *I
== '<')
626 if (unlikely(I
== Stop
))
629 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
633 bool NegRestriction
= false;
636 // look for whitespace or ending '>'
637 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
639 if (unlikely(End
== Stop
))
644 NegRestriction
= true;
648 std::string
restriction(I
, End
);
650 std::string prefix
= "profile.";
651 // only support for "profile" prefix, ignore others
652 if (restriction
.size() > prefix
.size() &&
653 restriction
.substr(0, prefix
.size()) == prefix
)
655 // get the name of the profile
656 restriction
= restriction
.substr(prefix
.size());
658 if (restriction
.empty() == false && profiles
.empty() == false &&
659 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
663 NegRestriction
= false;
664 // we found a match, so fast-forward to the end of the wildcards
665 for (; End
!= Stop
&& *End
!= '>'; ++End
);
675 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
678 if (NegRestriction
== true)
682 Package
= ""; /* not for this restriction */
686 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
689 if (I
!= Stop
&& *I
== '|')
690 Op
|= pkgCache::Dep::Or
;
692 if (I
== Stop
|| *I
== ',' || *I
== '|')
695 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
702 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
703 // ---------------------------------------------------------------------
704 /* This is the higher level depends parser. It takes a tag and generates
705 a complete depends tree for the given version. */
706 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
707 const char *Tag
,unsigned int Type
)
711 if (Section
.Find(Tag
,Start
,Stop
) == false)
714 string
const pkgArch
= Ver
.Arch();
722 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
724 return _error
->Error("Problem parsing dependency %s",Tag
);
725 size_t const found
= Package
.rfind(':');
727 // If negative is unspecific it needs to apply on all architectures
728 if (MultiArchEnabled
== true && found
== string::npos
&&
729 (Type
== pkgCache::Dep::Conflicts
||
730 Type
== pkgCache::Dep::DpkgBreaks
||
731 Type
== pkgCache::Dep::Replaces
))
733 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
734 a
!= Architectures
.end(); ++a
)
735 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
737 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
740 else if (MultiArchEnabled
== true && found
!= string::npos
&&
741 strcmp(Package
.c_str() + found
, ":any") != 0)
743 string Arch
= Package
.substr(found
+1, string::npos
);
744 Package
= Package
.substr(0, found
);
745 // Such dependencies are not supposed to be accepted …
746 // … but this is probably the best thing to do.
747 if (Arch
== "native")
748 Arch
= _config
->Find("APT::Architecture");
749 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
754 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
756 if ((Type
== pkgCache::Dep::Conflicts
||
757 Type
== pkgCache::Dep::DpkgBreaks
||
758 Type
== pkgCache::Dep::Replaces
) &&
759 NewDepends(Ver
, Package
,
760 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
761 Version
,Op
,Type
) == false)
770 // ListParser::ParseProvides - Parse the provides list /*{{{*/
771 // ---------------------------------------------------------------------
773 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
777 if (Section
.Find("Provides",Start
,Stop
) == true)
781 string
const Arch
= Ver
.Arch();
786 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
788 return _error
->Error("Problem parsing Provides line");
789 if (Op
!= pkgCache::Dep::NoOp
&& Op
!= pkgCache::Dep::Equals
) {
790 _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str());
791 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
792 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
795 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
804 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
806 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
807 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
809 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
810 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
815 // ListParser::NewProvides - add provides for all architectures /*{{{*/
816 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
817 string
const &Version
) {
818 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
819 a
!= Architectures
.end(); ++a
)
821 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
827 // ListParser::GrabWord - Matches a word and returns /*{{{*/
828 // ---------------------------------------------------------------------
829 /* Looks for a word in a list of words - for ParseStatus */
830 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
832 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
834 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
843 // ListParser::Step - Move to the next section in the file /*{{{*/
844 // ---------------------------------------------------------------------
845 /* This has to be careful to only process the correct architecture */
846 bool debListParser::Step()
848 iOffset
= Tags
.Offset();
849 while (Tags
.Step(Section
) == true)
851 /* See if this is the correct Architecture, if it isn't then we
852 drop the whole section. A missing arch tag only happens (in theory)
853 inside the Status file, so that is a positive return */
854 string
const Architecture
= Section
.FindS("Architecture");
856 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
858 if (APT::Configuration::checkArchitecture(Architecture
) == true)
860 /* parse version stanzas without an architecture only in the status file
861 (and as misfortune bycatch flat-archives) */
862 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
867 if (Architecture
== Arch
)
870 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
874 iOffset
= Tags
.Offset();
879 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
880 // ---------------------------------------------------------------------
882 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
883 FileFd
&File
, string component
)
885 // apt-secure does no longer download individual (per-section) Release
886 // file. to provide Component pinning we use the section name now
887 map_stringitem_t
const storage
= StoreString(pkgCacheGenerator::MIXED
, component
);
888 FileI
->Component
= storage
;
890 pkgTagFile
TagFile(&File
, File
.Size());
891 pkgTagSection Section
;
892 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
896 #define APT_INRELEASE(TYPE, TAG, STORE) \
897 data = Section.FindS(TAG); \
898 if (data.empty() == false) \
900 map_stringitem_t const storage = StoreString(pkgCacheGenerator::TYPE, data); \
903 APT_INRELEASE(MIXED
, "Suite", FileI
->Archive
)
904 APT_INRELEASE(MIXED
, "Component", FileI
->Component
)
905 APT_INRELEASE(VERSION
, "Version", FileI
->Version
)
906 APT_INRELEASE(MIXED
, "Origin", FileI
->Origin
)
907 APT_INRELEASE(MIXED
, "Codename", FileI
->Codename
)
908 APT_INRELEASE(MIXED
, "Label", FileI
->Label
)
910 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
911 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
913 return !_error
->PendingError();
916 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
917 // ---------------------------------------------------------------------
919 unsigned char debListParser::GetPrio(string Str
)
922 if (GrabWord(Str
,PrioList
,Out
) == false)
923 Out
= pkgCache::State::Extra
;
928 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
929 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
930 pkgCache::VerIterator
const &Ver
)
932 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
934 // status file has no (Download)Size, but all others are fair game
935 // status file is parsed last, so the first version we encounter is
936 // probably also the version we have downloaded
937 unsigned long long const Size
= Section
.FindULL("Size");
938 if (Size
!= 0 && Size
!= Ver
->Size
)
940 // available everywhere, but easier to check here than to include in VersionHash
941 unsigned char MultiArch
= ParseMultiArch(false);
942 if (MultiArch
!= Ver
->MultiArch
)
944 // for all practical proposes (we can check): same version
951 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
952 : debListParser(File
, ""), DebFile(DebFile
)
956 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
957 pkgCache::VerIterator
&Ver
)
959 bool res
= debListParser::UsePackage(Pkg
, Ver
);
960 // we use the full file path as a provides so that the file is found
962 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)