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
) : d(NULL
), 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
);
144 #if APT_PKG_ABI >= 413
145 // Parse the source package name
146 pkgCache::GrpIterator
const G
= Ver
.ParentPkg().Group();
147 Ver
->SourcePkgName
= G
->Name
;
148 Ver
->SourceVerStr
= Ver
->VerStr
;
149 if (Section
.Find("Source",Start
,Stop
) == true)
151 const char * const Space
= (const char * const) memchr(Start
, ' ', Stop
- Start
);
152 pkgCache::VerIterator V
;
157 const char * const Open
= (const char * const) memchr(Space
, '(', Stop
- Space
);
158 if (likely(Open
!= NULL
))
160 const char * const Close
= (const char * const) memchr(Open
, ')', Stop
- Open
);
161 if (likely(Close
!= NULL
))
163 std::string
const version(Open
+ 1, (Close
- Open
) - 1);
164 if (version
!= Ver
.VerStr())
166 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::VERSIONNUMBER
, version
);
167 Ver
->SourceVerStr
= idx
;
173 std::string
const pkgname(Start
, Stop
- Start
);
174 if (pkgname
!= G
.Name())
176 for (pkgCache::PkgIterator P
= G
.PackageList(); P
.end() == false; P
= G
.NextPkg(P
))
178 for (V
= P
.VersionList(); V
.end() == false; ++V
)
180 if (pkgname
== V
.SourcePkgName())
182 Ver
->SourcePkgName
= V
->SourcePkgName
;
186 if (V
.end() == false)
191 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::PKGNAME
, pkgname
);
192 Ver
->SourcePkgName
= idx
;
198 Ver
->MultiArch
= ParseMultiArch(true);
200 Ver
->Size
= Section
.FindULL("Size");
201 // Unpacked Size (in K)
202 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
203 Ver
->InstalledSize
*= 1024;
206 if (Section
.Find("Priority",Start
,Stop
) == true)
208 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
209 Ver
->Priority
= pkgCache::State::Extra
;
212 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
214 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
216 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
218 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
220 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
222 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
224 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
226 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
230 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
233 if (ParseProvides(Ver
) == false)
239 // ListParser::Description - Return the description string /*{{{*/
240 // ---------------------------------------------------------------------
241 /* This is to return the string describing the package in debian
242 form. If this returns the blank string then the entry is assumed to
243 only describe package properties */
244 string
debListParser::Description(std::string
const &lang
)
247 return Section
.FindS("Description");
249 return Section
.FindS(string("Description-").append(lang
).c_str());
252 // ListParser::AvailableDescriptionLanguages /*{{{*/
253 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages()
255 std::vector
<std::string
> const understood
= APT::Configuration::getLanguages();
256 std::vector
<std::string
> avail
;
257 if (Section
.Exists("Description") == true)
259 for (std::vector
<std::string
>::const_iterator lang
= understood
.begin(); lang
!= understood
.end(); ++lang
)
261 std::string
const tagname
= "Description-" + *lang
;
262 if (Section
.Exists(tagname
.c_str()) == true)
263 avail
.push_back(*lang
);
268 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
269 // ---------------------------------------------------------------------
270 /* This is to return the md5 string to allow the check if it is the right
271 description. If no Description-md5 is found in the section it will be
274 MD5SumValue
debListParser::Description_md5()
276 string
const value
= Section
.FindS("Description-md5");
277 if (value
.empty() == true)
279 std::string
const desc
= Description("") + "\n";
281 return MD5SumValue();
284 md5
.Add(desc
.c_str());
287 else if (likely(value
.size() == 32))
289 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
290 return MD5SumValue(value
);
291 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
292 return MD5SumValue();
294 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
295 return MD5SumValue();
298 // ListParser::UsePackage - Update a package structure /*{{{*/
299 // ---------------------------------------------------------------------
300 /* This is called to update the package with any new information
301 that might be found in the section */
302 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
303 pkgCache::VerIterator
&Ver
)
305 string
const static myArch
= _config
->Find("APT::Architecture");
306 // Possible values are: "all", "native", "installed" and "none"
307 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
308 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
309 if (essential
== "all" ||
310 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
311 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
313 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
316 if (strcmp(Pkg
.Name(),"apt") == 0)
318 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
320 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
322 Pkg
->Flags
|= pkgCache::Flag::Important
;
325 if (ParseStatus(Pkg
,Ver
) == false)
330 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
331 // ---------------------------------------------------------------------
333 unsigned short debListParser::VersionHash()
335 const char *Sections
[] ={"Installed-Size",
343 unsigned long Result
= INIT_FCS
;
345 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
349 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
352 /* Strip out any spaces from the text, this undoes dpkgs reformatting
353 of certain fields. dpkg also has the rather interesting notion of
354 reformatting depends operators < -> <= */
356 for (; Start
!= End
; ++Start
)
358 if (isspace(*Start
) != 0)
360 *J
++ = tolower_ascii(*Start
);
362 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
366 Result
= AddCRC16(Result
,S
,J
- S
);
372 // ListParser::ParseStatus - Parse the status field /*{{{*/
373 // ---------------------------------------------------------------------
374 /* Status lines are of the form,
375 Status: want flag status
376 want = unknown, install, hold, deinstall, purge
378 status = not-installed, config-files, half-installed, unpacked,
379 half-configured, triggers-awaited, triggers-pending, installed
381 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
382 pkgCache::VerIterator
&Ver
)
386 if (Section
.Find("Status",Start
,Stop
) == false)
389 // UsePackage() is responsible for setting the flag in the default case
390 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
391 if (essential
== true &&
392 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
395 // Isolate the first word
396 const char *I
= Start
;
397 for(; I
< Stop
&& *I
!= ' '; I
++);
398 if (I
>= Stop
|| *I
!= ' ')
399 return _error
->Error("Malformed Status line");
401 // Process the want field
402 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
403 {"install",pkgCache::State::Install
},
404 {"hold",pkgCache::State::Hold
},
405 {"deinstall",pkgCache::State::DeInstall
},
406 {"purge",pkgCache::State::Purge
},
408 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
409 return _error
->Error("Malformed 1st word in the Status line");
411 // Isloate the next word
414 for(; I
< Stop
&& *I
!= ' '; I
++);
415 if (I
>= Stop
|| *I
!= ' ')
416 return _error
->Error("Malformed status line, no 2nd word");
418 // Process the flag field
419 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
420 {"reinstreq",pkgCache::State::ReInstReq
},
421 {"hold",pkgCache::State::HoldInst
},
422 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
424 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
425 return _error
->Error("Malformed 2nd word in the Status line");
427 // Isloate the last word
430 for(; I
< Stop
&& *I
!= ' '; I
++);
432 return _error
->Error("Malformed Status line, no 3rd word");
434 // Process the flag field
435 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
436 {"config-files",pkgCache::State::ConfigFiles
},
437 {"half-installed",pkgCache::State::HalfInstalled
},
438 {"unpacked",pkgCache::State::UnPacked
},
439 {"half-configured",pkgCache::State::HalfConfigured
},
440 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
441 {"triggers-pending",pkgCache::State::TriggersPending
},
442 {"installed",pkgCache::State::Installed
},
444 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
445 return _error
->Error("Malformed 3rd word in the Status line");
447 /* A Status line marks the package as indicating the current
448 version as well. Only if it is actually installed.. Otherwise
449 the interesting dpkg handling of the status file creates bogus
451 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
452 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
454 if (Ver
.end() == true)
455 _error
->Warning("Encountered status field in a non-version description");
457 Pkg
->CurrentVer
= Ver
.Index();
463 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
465 // Determine the operator
473 Op
= pkgCache::Dep::LessEq
;
480 Op
= pkgCache::Dep::Less
;
484 // < is the same as <= and << is really Cs < for some reason
485 Op
= pkgCache::Dep::LessEq
;
493 Op
= pkgCache::Dep::GreaterEq
;
500 Op
= pkgCache::Dep::Greater
;
504 // > is the same as >= and >> is really Cs > for some reason
505 Op
= pkgCache::Dep::GreaterEq
;
509 Op
= pkgCache::Dep::Equals
;
513 // HACK around bad package definitions
515 Op
= pkgCache::Dep::Equals
;
521 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
522 // ---------------------------------------------------------------------
523 /* This parses the dependency elements out of a standard string in place,
525 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
526 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
527 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
528 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
529 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
530 bool const &ParseArchFlags
)
531 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
532 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
533 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
534 bool const &ParseArchFlags
, bool const &StripMultiArch
)
535 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
536 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
537 string
&Package
,string
&Ver
,
538 unsigned int &Op
, bool const &ParseArchFlags
,
539 bool const &StripMultiArch
,
540 bool const &ParseRestrictionsList
)
542 // Strip off leading space
543 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
545 // Parse off the package name
546 const char *I
= Start
;
547 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
548 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
549 *I
!= '<' && *I
!= '>'; ++I
);
552 if (I
!= Stop
&& *I
== ')')
558 // Stash the package name
559 Package
.assign(Start
,I
- Start
);
561 // We don't want to confuse library users which can't handle MultiArch
562 string
const arch
= _config
->Find("APT::Architecture");
563 if (StripMultiArch
== true) {
564 size_t const found
= Package
.rfind(':');
565 if (found
!= string::npos
&&
566 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
567 strcmp(Package
.c_str() + found
, ":native") == 0 ||
568 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
569 Package
= Package
.substr(0,found
);
572 // Skip white space to the '('
573 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
576 if (I
!= Stop
&& *I
== '(')
579 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
582 I
= ConvertRelation(I
,Op
);
585 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
587 I
= (const char*) memchr(I
, ')', Stop
- I
);
588 if (I
== NULL
|| Start
== I
)
591 // Skip trailing whitespace
593 for (; End
> Start
&& isspace(End
[-1]); End
--);
595 Ver
.assign(Start
,End
-Start
);
601 Op
= pkgCache::Dep::NoOp
;
605 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
607 if (ParseArchFlags
== true)
609 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
611 // Parse an architecture
612 if (I
!= Stop
&& *I
== '[')
616 if (unlikely(I
== Stop
))
621 bool NegArch
= false;
624 // look for whitespace or ending ']'
625 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
627 if (unlikely(End
== Stop
))
636 std::string
arch(I
, End
);
637 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
642 // we found a match, so fast-forward to the end of the wildcards
643 for (; End
!= Stop
&& *End
!= ']'; ++End
);
652 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
659 Package
= ""; /* not for this arch */
663 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
666 if (ParseRestrictionsList
== true)
668 // Parse a restrictions formula which is in disjunctive normal form:
669 // (foo AND bar) OR (blub AND bla)
671 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
673 // if the next character is a restriction list, then by default the
674 // dependency does not apply and the conditions have to be checked
675 // if the next character is not a restriction list, then by default the
676 // dependency applies
677 bool applies1
= (*I
!= '<');
685 if (unlikely(I
== Stop
))
690 // if of the prior restriction list is already fulfilled, then
691 // we can just skip to the end of the current list
693 for (;End
!= Stop
&& *End
!= '>'; ++End
);
696 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
698 bool applies2
= true;
699 // all the conditions inside a restriction list have to be
700 // met so once we find one that is not met, we can skip to
701 // the end of this list
704 // look for whitespace or ending '>'
705 // End now points to the character after the current term
706 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
708 if (unlikely(End
== Stop
))
711 bool NegRestriction
= false;
714 NegRestriction
= true;
718 std::string
restriction(I
, End
);
720 if (restriction
.empty() == false && profiles
.empty() == false &&
721 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
723 if (NegRestriction
) {
725 // since one of the terms does not apply we don't have to check the others
726 for (; End
!= Stop
&& *End
!= '>'; ++End
);
729 if (!NegRestriction
) {
731 // since one of the terms does not apply we don't have to check the others
732 for (; End
!= Stop
&& *End
!= '>'; ++End
);
739 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
745 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
753 if (applies1
== false) {
754 Package
= ""; //not for this restriction
758 if (I
!= Stop
&& *I
== '|')
759 Op
|= pkgCache::Dep::Or
;
761 if (I
== Stop
|| *I
== ',' || *I
== '|')
764 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
771 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
772 // ---------------------------------------------------------------------
773 /* This is the higher level depends parser. It takes a tag and generates
774 a complete depends tree for the given version. */
775 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
776 const char *Tag
,unsigned int Type
)
780 if (Section
.Find(Tag
,Start
,Stop
) == false)
783 string
const pkgArch
= Ver
.Arch();
791 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
793 return _error
->Error("Problem parsing dependency %s",Tag
);
794 size_t const found
= Package
.rfind(':');
796 // If negative is unspecific it needs to apply on all architectures
797 if (MultiArchEnabled
== true && found
== string::npos
&&
798 (Type
== pkgCache::Dep::Conflicts
||
799 Type
== pkgCache::Dep::DpkgBreaks
||
800 Type
== pkgCache::Dep::Replaces
))
802 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
803 a
!= Architectures
.end(); ++a
)
804 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
806 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
809 else if (found
!= string::npos
&&
810 strcmp(Package
.c_str() + found
, ":any") != 0)
812 string Arch
= Package
.substr(found
+1, string::npos
);
813 Package
= Package
.substr(0, found
);
814 // Such dependencies are not supposed to be accepted …
815 // … but this is probably the best thing to do.
816 if (Arch
== "native")
817 Arch
= _config
->Find("APT::Architecture");
818 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
823 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
825 if ((Type
== pkgCache::Dep::Conflicts
||
826 Type
== pkgCache::Dep::DpkgBreaks
||
827 Type
== pkgCache::Dep::Replaces
) &&
828 NewDepends(Ver
, Package
,
829 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
830 Version
,Op
,Type
) == false)
839 // ListParser::ParseProvides - Parse the provides list /*{{{*/
840 // ---------------------------------------------------------------------
842 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
846 if (Section
.Find("Provides",Start
,Stop
) == true)
850 string
const Arch
= Ver
.Arch();
855 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
856 const size_t archfound
= Package
.rfind(':');
858 return _error
->Error("Problem parsing Provides line");
859 if (Op
!= pkgCache::Dep::NoOp
&& Op
!= pkgCache::Dep::Equals
) {
860 _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str());
861 } else if (archfound
!= string::npos
) {
862 string OtherArch
= Package
.substr(archfound
+1, string::npos
);
863 Package
= Package
.substr(0, archfound
);
864 if (NewProvides(Ver
, Package
, OtherArch
, Version
) == false)
866 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
867 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
870 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
879 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
881 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
882 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
884 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
885 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
890 // ListParser::NewProvides - add provides for all architectures /*{{{*/
891 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
892 string
const &Version
) {
893 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
894 a
!= Architectures
.end(); ++a
)
896 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
902 // ListParser::GrabWord - Matches a word and returns /*{{{*/
903 // ---------------------------------------------------------------------
904 /* Looks for a word in a list of words - for ParseStatus */
905 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
907 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
909 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
918 // ListParser::Step - Move to the next section in the file /*{{{*/
919 // ---------------------------------------------------------------------
920 /* This has to be careful to only process the correct architecture */
921 bool debListParser::Step()
923 iOffset
= Tags
.Offset();
924 while (Tags
.Step(Section
) == true)
926 /* See if this is the correct Architecture, if it isn't then we
927 drop the whole section. A missing arch tag only happens (in theory)
928 inside the Status file, so that is a positive return */
929 string
const Architecture
= Section
.FindS("Architecture");
931 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
933 if (APT::Configuration::checkArchitecture(Architecture
) == true)
935 /* parse version stanzas without an architecture only in the status file
936 (and as misfortune bycatch flat-archives) */
937 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
942 if (Architecture
== Arch
)
945 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
949 iOffset
= Tags
.Offset();
954 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
955 // ---------------------------------------------------------------------
957 unsigned char debListParser::GetPrio(string Str
)
960 if (GrabWord(Str
,PrioList
,Out
) == false)
961 Out
= pkgCache::State::Extra
;
966 #if APT_PKG_ABI >= 413
967 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
968 pkgCache::VerIterator
const &Ver
)
970 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
972 // status file has no (Download)Size, but all others are fair game
973 // status file is parsed last, so the first version we encounter is
974 // probably also the version we have downloaded
975 unsigned long long const Size
= Section
.FindULL("Size");
976 if (Size
!= 0 && Size
!= Ver
->Size
)
978 // available everywhere, but easier to check here than to include in VersionHash
979 unsigned char MultiArch
= ParseMultiArch(false);
980 if (MultiArch
!= Ver
->MultiArch
)
982 // for all practical proposes (we can check): same version
989 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
990 : debListParser(File
, ""), DebFile(DebFile
)
994 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
995 pkgCache::VerIterator
&Ver
)
997 bool res
= debListParser::UsePackage(Pkg
, Ver
);
998 // we use the full file path as a provides so that the file is found
1000 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)
1005 debListParser::~debListParser() {}