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()
199 string
const lang
= DescriptionLanguage();
201 return Section
.FindS("Description");
203 return Section
.FindS(string("Description-").append(lang
).c_str());
206 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
207 // ---------------------------------------------------------------------
208 /* This is to return the string describing the language of
209 description. If this returns the blank string then the entry is
210 assumed to describe original description. */
211 string
debListParser::DescriptionLanguage()
213 if (Section
.FindS("Description").empty() == false)
216 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
217 for (std::vector
<string
>::const_iterator l
= lang
.begin();
218 l
!= lang
.end(); ++l
)
219 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
225 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
226 // ---------------------------------------------------------------------
227 /* This is to return the md5 string to allow the check if it is the right
228 description. If no Description-md5 is found in the section it will be
231 MD5SumValue
debListParser::Description_md5()
233 string
const value
= Section
.FindS("Description-md5");
234 if (value
.empty() == true)
236 std::string
const desc
= Description() + "\n";
238 return MD5SumValue();
241 md5
.Add(desc
.c_str());
244 else if (likely(value
.size() == 32))
246 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
247 return MD5SumValue(value
);
248 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
249 return MD5SumValue();
251 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
252 return MD5SumValue();
255 // ListParser::UsePackage - Update a package structure /*{{{*/
256 // ---------------------------------------------------------------------
257 /* This is called to update the package with any new information
258 that might be found in the section */
259 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
260 pkgCache::VerIterator
&Ver
)
262 if (Pkg
->Section
== 0)
263 Pkg
->Section
= UniqFindTagWrite("Section");
265 string
const static myArch
= _config
->Find("APT::Architecture");
266 // Possible values are: "all", "native", "installed" and "none"
267 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
268 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
269 if (essential
== "all" ||
270 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
271 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
273 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
276 if (strcmp(Pkg
.Name(),"apt") == 0)
278 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
280 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
282 Pkg
->Flags
|= pkgCache::Flag::Important
;
285 if (ParseStatus(Pkg
,Ver
) == false)
290 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
291 // ---------------------------------------------------------------------
293 unsigned short debListParser::VersionHash()
295 const char *Sections
[] ={"Installed-Size",
303 unsigned long Result
= INIT_FCS
;
305 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
309 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
312 /* Strip out any spaces from the text, this undoes dpkgs reformatting
313 of certain fields. dpkg also has the rather interesting notion of
314 reformatting depends operators < -> <= */
316 for (; Start
!= End
; ++Start
)
318 if (isspace(*Start
) != 0)
320 *J
++ = tolower_ascii(*Start
);
322 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
326 Result
= AddCRC16(Result
,S
,J
- S
);
332 // ListParser::ParseStatus - Parse the status field /*{{{*/
333 // ---------------------------------------------------------------------
334 /* Status lines are of the form,
335 Status: want flag status
336 want = unknown, install, hold, deinstall, purge
337 flag = ok, reinstreq, hold, hold-reinstreq
338 status = not-installed, unpacked, half-configured,
339 half-installed, config-files, post-inst-failed,
340 removal-failed, installed
342 Some of the above are obsolete (I think?) flag = hold-* and
343 status = post-inst-failed, removal-failed at least.
345 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
346 pkgCache::VerIterator
&Ver
)
350 if (Section
.Find("Status",Start
,Stop
) == false)
353 // UsePackage() is responsible for setting the flag in the default case
354 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
355 if (essential
== true &&
356 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
359 // Isolate the first word
360 const char *I
= Start
;
361 for(; I
< Stop
&& *I
!= ' '; I
++);
362 if (I
>= Stop
|| *I
!= ' ')
363 return _error
->Error("Malformed Status line");
365 // Process the want field
366 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
367 {"install",pkgCache::State::Install
},
368 {"hold",pkgCache::State::Hold
},
369 {"deinstall",pkgCache::State::DeInstall
},
370 {"purge",pkgCache::State::Purge
},
372 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
373 return _error
->Error("Malformed 1st word in the Status line");
375 // Isloate the next word
378 for(; I
< Stop
&& *I
!= ' '; I
++);
379 if (I
>= Stop
|| *I
!= ' ')
380 return _error
->Error("Malformed status line, no 2nd word");
382 // Process the flag field
383 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
384 {"reinstreq",pkgCache::State::ReInstReq
},
385 {"hold",pkgCache::State::HoldInst
},
386 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
388 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
389 return _error
->Error("Malformed 2nd word in the Status line");
391 // Isloate the last word
394 for(; I
< Stop
&& *I
!= ' '; I
++);
396 return _error
->Error("Malformed Status line, no 3rd word");
398 // Process the flag field
399 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
400 {"unpacked",pkgCache::State::UnPacked
},
401 {"half-configured",pkgCache::State::HalfConfigured
},
402 {"installed",pkgCache::State::Installed
},
403 {"half-installed",pkgCache::State::HalfInstalled
},
404 {"config-files",pkgCache::State::ConfigFiles
},
405 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
406 {"triggers-pending",pkgCache::State::TriggersPending
},
407 {"post-inst-failed",pkgCache::State::HalfConfigured
},
408 {"removal-failed",pkgCache::State::HalfInstalled
},
410 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
411 return _error
->Error("Malformed 3rd word in the Status line");
413 /* A Status line marks the package as indicating the current
414 version as well. Only if it is actually installed.. Otherwise
415 the interesting dpkg handling of the status file creates bogus
417 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
418 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
420 if (Ver
.end() == true)
421 _error
->Warning("Encountered status field in a non-version description");
423 Pkg
->CurrentVer
= Ver
.Index();
429 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
431 // Determine the operator
439 Op
= pkgCache::Dep::LessEq
;
446 Op
= pkgCache::Dep::Less
;
450 // < is the same as <= and << is really Cs < for some reason
451 Op
= pkgCache::Dep::LessEq
;
459 Op
= pkgCache::Dep::GreaterEq
;
466 Op
= pkgCache::Dep::Greater
;
470 // > is the same as >= and >> is really Cs > for some reason
471 Op
= pkgCache::Dep::GreaterEq
;
475 Op
= pkgCache::Dep::Equals
;
479 // HACK around bad package definitions
481 Op
= pkgCache::Dep::Equals
;
487 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
488 // ---------------------------------------------------------------------
489 /* This parses the dependency elements out of a standard string in place,
491 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
492 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
493 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, 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
)
497 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
498 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
499 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
500 bool const &ParseArchFlags
, bool const &StripMultiArch
)
501 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
502 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
503 string
&Package
,string
&Ver
,
504 unsigned int &Op
, bool const &ParseArchFlags
,
505 bool const &StripMultiArch
,
506 bool const &ParseRestrictionsList
)
508 // Strip off leading space
509 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
511 // Parse off the package name
512 const char *I
= Start
;
513 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
514 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
515 *I
!= '<' && *I
!= '>'; ++I
);
518 if (I
!= Stop
&& *I
== ')')
524 // Stash the package name
525 Package
.assign(Start
,I
- Start
);
527 // We don't want to confuse library users which can't handle MultiArch
528 string
const arch
= _config
->Find("APT::Architecture");
529 if (StripMultiArch
== true) {
530 size_t const found
= Package
.rfind(':');
531 if (found
!= string::npos
&&
532 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
533 strcmp(Package
.c_str() + found
, ":native") == 0 ||
534 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
535 Package
= Package
.substr(0,found
);
538 // Skip white space to the '('
539 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
542 if (I
!= Stop
&& *I
== '(')
545 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
548 I
= ConvertRelation(I
,Op
);
551 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
553 I
= (const char*) memchr(I
, ')', Stop
- I
);
554 if (I
== NULL
|| Start
== I
)
557 // Skip trailing whitespace
559 for (; End
> Start
&& isspace(End
[-1]); End
--);
561 Ver
.assign(Start
,End
-Start
);
567 Op
= pkgCache::Dep::NoOp
;
571 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
573 if (ParseArchFlags
== true)
575 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
577 // Parse an architecture
578 if (I
!= Stop
&& *I
== '[')
582 if (unlikely(I
== Stop
))
587 bool NegArch
= false;
590 // look for whitespace or ending ']'
591 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
593 if (unlikely(End
== Stop
))
602 std::string
arch(I
, End
);
603 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
608 // we found a match, so fast-forward to the end of the wildcards
609 for (; End
!= Stop
&& *End
!= ']'; ++End
);
618 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
625 Package
= ""; /* not for this arch */
629 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
632 if (ParseRestrictionsList
== true)
634 // Parse a restrictions list
635 if (I
!= Stop
&& *I
== '<')
639 if (unlikely(I
== Stop
))
642 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
646 bool NegRestriction
= false;
649 // look for whitespace or ending '>'
650 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
652 if (unlikely(End
== Stop
))
657 NegRestriction
= true;
661 std::string
restriction(I
, End
);
663 std::string prefix
= "profile.";
664 // only support for "profile" prefix, ignore others
665 if (restriction
.size() > prefix
.size() &&
666 restriction
.substr(0, prefix
.size()) == prefix
)
668 // get the name of the profile
669 restriction
= restriction
.substr(prefix
.size());
671 if (restriction
.empty() == false && profiles
.empty() == false &&
672 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
676 NegRestriction
= false;
677 // we found a match, so fast-forward to the end of the wildcards
678 for (; End
!= Stop
&& *End
!= '>'; ++End
);
688 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
691 if (NegRestriction
== true)
695 Package
= ""; /* not for this restriction */
699 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
702 if (I
!= Stop
&& *I
== '|')
703 Op
|= pkgCache::Dep::Or
;
705 if (I
== Stop
|| *I
== ',' || *I
== '|')
708 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
715 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
716 // ---------------------------------------------------------------------
717 /* This is the higher level depends parser. It takes a tag and generates
718 a complete depends tree for the given version. */
719 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
720 const char *Tag
,unsigned int Type
)
724 if (Section
.Find(Tag
,Start
,Stop
) == false)
727 string
const pkgArch
= Ver
.Arch();
735 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
737 return _error
->Error("Problem parsing dependency %s",Tag
);
738 size_t const found
= Package
.rfind(':');
740 // If negative is unspecific it needs to apply on all architectures
741 if (MultiArchEnabled
== true && found
== string::npos
&&
742 (Type
== pkgCache::Dep::Conflicts
||
743 Type
== pkgCache::Dep::DpkgBreaks
||
744 Type
== pkgCache::Dep::Replaces
))
746 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
747 a
!= Architectures
.end(); ++a
)
748 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
750 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
753 else if (MultiArchEnabled
== true && found
!= string::npos
&&
754 strcmp(Package
.c_str() + found
, ":any") != 0)
756 string Arch
= Package
.substr(found
+1, string::npos
);
757 Package
= Package
.substr(0, found
);
758 // Such dependencies are not supposed to be accepted …
759 // … but this is probably the best thing to do.
760 if (Arch
== "native")
761 Arch
= _config
->Find("APT::Architecture");
762 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
767 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
769 if ((Type
== pkgCache::Dep::Conflicts
||
770 Type
== pkgCache::Dep::DpkgBreaks
||
771 Type
== pkgCache::Dep::Replaces
) &&
772 NewDepends(Ver
, Package
,
773 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
774 Version
,Op
,Type
) == false)
783 // ListParser::ParseProvides - Parse the provides list /*{{{*/
784 // ---------------------------------------------------------------------
786 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
790 if (Section
.Find("Provides",Start
,Stop
) == true)
794 string
const Arch
= Ver
.Arch();
799 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
801 return _error
->Error("Problem parsing Provides line");
802 if (Op
!= pkgCache::Dep::NoOp
) {
803 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
804 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
805 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
808 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
817 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
819 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
820 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
822 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
823 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
828 // ListParser::NewProvides - add provides for all architectures /*{{{*/
829 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
830 string
const &Version
) {
831 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
832 a
!= Architectures
.end(); ++a
)
834 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
840 // ListParser::GrabWord - Matches a word and returns /*{{{*/
841 // ---------------------------------------------------------------------
842 /* Looks for a word in a list of words - for ParseStatus */
843 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
845 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
847 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
856 // ListParser::Step - Move to the next section in the file /*{{{*/
857 // ---------------------------------------------------------------------
858 /* This has to be careful to only process the correct architecture */
859 bool debListParser::Step()
861 iOffset
= Tags
.Offset();
862 while (Tags
.Step(Section
) == true)
864 /* See if this is the correct Architecture, if it isn't then we
865 drop the whole section. A missing arch tag only happens (in theory)
866 inside the Status file, so that is a positive return */
867 string
const Architecture
= Section
.FindS("Architecture");
869 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
871 if (APT::Configuration::checkArchitecture(Architecture
) == true)
873 /* parse version stanzas without an architecture only in the status file
874 (and as misfortune bycatch flat-archives) */
875 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
880 if (Architecture
== Arch
)
883 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
887 iOffset
= Tags
.Offset();
892 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
893 // ---------------------------------------------------------------------
895 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
896 FileFd
&File
, string component
)
898 // apt-secure does no longer download individual (per-section) Release
899 // file. to provide Component pinning we use the section name now
900 map_ptrloc
const storage
= WriteUniqString(component
);
901 FileI
->Component
= storage
;
903 pkgTagFile
TagFile(&File
, File
.Size());
904 pkgTagSection Section
;
905 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
909 #define APT_INRELEASE(TAG, STORE) \
910 data = Section.FindS(TAG); \
911 if (data.empty() == false) \
913 map_ptrloc const storage = WriteUniqString(data); \
916 APT_INRELEASE("Suite", FileI
->Archive
)
917 APT_INRELEASE("Component", FileI
->Component
)
918 APT_INRELEASE("Version", FileI
->Version
)
919 APT_INRELEASE("Origin", FileI
->Origin
)
920 APT_INRELEASE("Codename", FileI
->Codename
)
921 APT_INRELEASE("Label", FileI
->Label
)
923 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
924 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
926 return !_error
->PendingError();
929 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
930 // ---------------------------------------------------------------------
932 unsigned char debListParser::GetPrio(string Str
)
935 if (GrabWord(Str
,PrioList
,Out
) == false)
936 Out
= pkgCache::State::Extra
;
941 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
942 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
943 pkgCache::VerIterator
const &Ver
)
945 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
947 // status file has no (Download)Size, but all others are fair game
948 // status file is parsed last, so the first version we encounter is
949 // probably also the version we have downloaded
950 unsigned long long const Size
= Section
.FindULL("Size");
951 if (Size
!= 0 && Size
!= Ver
->Size
)
953 // available everywhere, but easier to check here than to include in VersionHash
954 unsigned char MultiArch
= ParseMultiArch(false);
955 if (MultiArch
!= Ver
->MultiArch
)
957 // for all practical proposes (we can check): same version
964 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
965 : debListParser(File
, ""), DebFile(DebFile
)
969 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
970 pkgCache::VerIterator
&Ver
)
972 bool res
= debListParser::UsePackage(Pkg
, Ver
);
973 // we use the full file path as a provides so that the file is found
975 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)