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
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
214 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
216 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
218 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
220 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
222 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
224 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
226 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
229 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
232 if (ParseProvides(Ver
) == false)
238 // ListParser::Description - Return the description string /*{{{*/
239 // ---------------------------------------------------------------------
240 /* This is to return the string describing the package in debian
241 form. If this returns the blank string then the entry is assumed to
242 only describe package properties */
243 string
debListParser::Description(std::string
const &lang
)
246 return Section
.FindS("Description");
248 return Section
.FindS(string("Description-").append(lang
).c_str());
251 // ListParser::AvailableDescriptionLanguages /*{{{*/
252 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages()
254 std::vector
<std::string
> const understood
= APT::Configuration::getLanguages();
255 std::vector
<std::string
> avail
;
256 if (Section
.Exists("Description") == true)
258 for (std::vector
<std::string
>::const_iterator lang
= understood
.begin(); lang
!= understood
.end(); ++lang
)
260 std::string
const tagname
= "Description-" + *lang
;
261 if (Section
.Exists(tagname
.c_str()) == true)
262 avail
.push_back(*lang
);
267 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
268 // ---------------------------------------------------------------------
269 /* This is to return the md5 string to allow the check if it is the right
270 description. If no Description-md5 is found in the section it will be
273 MD5SumValue
debListParser::Description_md5()
275 string
const value
= Section
.FindS("Description-md5");
276 if (value
.empty() == true)
278 std::string
const desc
= Description("") + "\n";
280 return MD5SumValue();
283 md5
.Add(desc
.c_str());
286 else if (likely(value
.size() == 32))
288 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
289 return MD5SumValue(value
);
290 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
291 return MD5SumValue();
293 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
294 return MD5SumValue();
297 // ListParser::UsePackage - Update a package structure /*{{{*/
298 // ---------------------------------------------------------------------
299 /* This is called to update the package with any new information
300 that might be found in the section */
301 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
302 pkgCache::VerIterator
&Ver
)
304 string
const static myArch
= _config
->Find("APT::Architecture");
305 // Possible values are: "all", "native", "installed" and "none"
306 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
307 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
308 if (essential
== "all" ||
309 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
310 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
312 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
315 if (strcmp(Pkg
.Name(),"apt") == 0)
317 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
319 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
321 Pkg
->Flags
|= pkgCache::Flag::Important
;
324 if (ParseStatus(Pkg
,Ver
) == false)
329 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
330 // ---------------------------------------------------------------------
332 unsigned short debListParser::VersionHash()
334 const char *Sections
[] ={"Installed-Size",
342 unsigned long Result
= INIT_FCS
;
344 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
348 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
351 /* Strip out any spaces from the text, this undoes dpkgs reformatting
352 of certain fields. dpkg also has the rather interesting notion of
353 reformatting depends operators < -> <= */
355 for (; Start
!= End
; ++Start
)
357 if (isspace(*Start
) != 0)
359 *J
++ = tolower_ascii(*Start
);
361 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
365 Result
= AddCRC16(Result
,S
,J
- S
);
371 // ListParser::ParseStatus - Parse the status field /*{{{*/
372 // ---------------------------------------------------------------------
373 /* Status lines are of the form,
374 Status: want flag status
375 want = unknown, install, hold, deinstall, purge
377 status = not-installed, config-files, half-installed, unpacked,
378 half-configured, triggers-awaited, triggers-pending, installed
380 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
381 pkgCache::VerIterator
&Ver
)
385 if (Section
.Find("Status",Start
,Stop
) == false)
388 // UsePackage() is responsible for setting the flag in the default case
389 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
390 if (essential
== true &&
391 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
394 // Isolate the first word
395 const char *I
= Start
;
396 for(; I
< Stop
&& *I
!= ' '; I
++);
397 if (I
>= Stop
|| *I
!= ' ')
398 return _error
->Error("Malformed Status line");
400 // Process the want field
401 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
402 {"install",pkgCache::State::Install
},
403 {"hold",pkgCache::State::Hold
},
404 {"deinstall",pkgCache::State::DeInstall
},
405 {"purge",pkgCache::State::Purge
},
407 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
408 return _error
->Error("Malformed 1st word in the Status line");
410 // Isloate the next word
413 for(; I
< Stop
&& *I
!= ' '; I
++);
414 if (I
>= Stop
|| *I
!= ' ')
415 return _error
->Error("Malformed status line, no 2nd word");
417 // Process the flag field
418 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
419 {"reinstreq",pkgCache::State::ReInstReq
},
420 {"hold",pkgCache::State::HoldInst
},
421 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
423 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
424 return _error
->Error("Malformed 2nd word in the Status line");
426 // Isloate the last word
429 for(; I
< Stop
&& *I
!= ' '; I
++);
431 return _error
->Error("Malformed Status line, no 3rd word");
433 // Process the flag field
434 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
435 {"config-files",pkgCache::State::ConfigFiles
},
436 {"half-installed",pkgCache::State::HalfInstalled
},
437 {"unpacked",pkgCache::State::UnPacked
},
438 {"half-configured",pkgCache::State::HalfConfigured
},
439 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
440 {"triggers-pending",pkgCache::State::TriggersPending
},
441 {"installed",pkgCache::State::Installed
},
443 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
444 return _error
->Error("Malformed 3rd word in the Status line");
446 /* A Status line marks the package as indicating the current
447 version as well. Only if it is actually installed.. Otherwise
448 the interesting dpkg handling of the status file creates bogus
450 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
451 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
453 if (Ver
.end() == true)
454 _error
->Warning("Encountered status field in a non-version description");
456 Pkg
->CurrentVer
= Ver
.Index();
462 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
464 // Determine the operator
472 Op
= pkgCache::Dep::LessEq
;
479 Op
= pkgCache::Dep::Less
;
483 // < is the same as <= and << is really Cs < for some reason
484 Op
= pkgCache::Dep::LessEq
;
492 Op
= pkgCache::Dep::GreaterEq
;
499 Op
= pkgCache::Dep::Greater
;
503 // > is the same as >= and >> is really Cs > for some reason
504 Op
= pkgCache::Dep::GreaterEq
;
508 Op
= pkgCache::Dep::Equals
;
512 // HACK around bad package definitions
514 Op
= pkgCache::Dep::Equals
;
520 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
521 // ---------------------------------------------------------------------
522 /* This parses the dependency elements out of a standard string in place,
524 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
525 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
526 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
527 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
528 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
529 bool const &ParseArchFlags
)
530 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
531 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
532 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
533 bool const &ParseArchFlags
, bool const &StripMultiArch
)
534 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
535 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
536 string
&Package
,string
&Ver
,
537 unsigned int &Op
, bool const &ParseArchFlags
,
538 bool const &StripMultiArch
,
539 bool const &ParseRestrictionsList
)
541 // Strip off leading space
542 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
544 // Parse off the package name
545 const char *I
= Start
;
546 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
547 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
548 *I
!= '<' && *I
!= '>'; ++I
);
551 if (I
!= Stop
&& *I
== ')')
557 // Stash the package name
558 Package
.assign(Start
,I
- Start
);
560 // We don't want to confuse library users which can't handle MultiArch
561 string
const arch
= _config
->Find("APT::Architecture");
562 if (StripMultiArch
== true) {
563 size_t const found
= Package
.rfind(':');
564 if (found
!= string::npos
&&
565 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
566 strcmp(Package
.c_str() + found
, ":native") == 0 ||
567 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
568 Package
= Package
.substr(0,found
);
571 // Skip white space to the '('
572 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
575 if (I
!= Stop
&& *I
== '(')
578 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
581 I
= ConvertRelation(I
,Op
);
584 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
586 I
= (const char*) memchr(I
, ')', Stop
- I
);
587 if (I
== NULL
|| Start
== I
)
590 // Skip trailing whitespace
592 for (; End
> Start
&& isspace(End
[-1]); End
--);
594 Ver
.assign(Start
,End
-Start
);
600 Op
= pkgCache::Dep::NoOp
;
604 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
606 if (ParseArchFlags
== true)
608 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
610 // Parse an architecture
611 if (I
!= Stop
&& *I
== '[')
615 if (unlikely(I
== Stop
))
620 bool NegArch
= false;
623 // look for whitespace or ending ']'
624 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
626 if (unlikely(End
== Stop
))
635 std::string
arch(I
, End
);
636 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
641 // we found a match, so fast-forward to the end of the wildcards
642 for (; End
!= Stop
&& *End
!= ']'; ++End
);
651 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
658 Package
= ""; /* not for this arch */
662 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
665 if (ParseRestrictionsList
== true)
667 // Parse a restrictions formula which is in disjunctive normal form:
668 // (foo AND bar) OR (blub AND bla)
670 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
672 // if the next character is a restriction list, then by default the
673 // dependency does not apply and the conditions have to be checked
674 // if the next character is not a restriction list, then by default the
675 // dependency applies
676 bool applies1
= (*I
!= '<');
684 if (unlikely(I
== Stop
))
689 // if of the prior restriction list is already fulfilled, then
690 // we can just skip to the end of the current list
692 for (;End
!= Stop
&& *End
!= '>'; ++End
);
695 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
697 bool applies2
= true;
698 // all the conditions inside a restriction list have to be
699 // met so once we find one that is not met, we can skip to
700 // the end of this list
703 // look for whitespace or ending '>'
704 // End now points to the character after the current term
705 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
707 if (unlikely(End
== Stop
))
710 bool NegRestriction
= false;
713 NegRestriction
= true;
717 std::string
restriction(I
, End
);
719 if (restriction
.empty() == false && profiles
.empty() == false &&
720 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
722 if (NegRestriction
) {
724 // since one of the terms does not apply we don't have to check the others
725 for (; End
!= Stop
&& *End
!= '>'; ++End
);
728 if (!NegRestriction
) {
730 // since one of the terms does not apply we don't have to check the others
731 for (; End
!= Stop
&& *End
!= '>'; ++End
);
738 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
744 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
752 if (applies1
== false) {
753 Package
= ""; //not for this restriction
757 if (I
!= Stop
&& *I
== '|')
758 Op
|= pkgCache::Dep::Or
;
760 if (I
== Stop
|| *I
== ',' || *I
== '|')
763 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
770 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
771 // ---------------------------------------------------------------------
772 /* This is the higher level depends parser. It takes a tag and generates
773 a complete depends tree for the given version. */
774 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
775 const char *Tag
,unsigned int Type
)
779 if (Section
.Find(Tag
,Start
,Stop
) == false)
782 string
const pkgArch
= Ver
.Arch();
790 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
792 return _error
->Error("Problem parsing dependency %s",Tag
);
793 size_t const found
= Package
.rfind(':');
795 // If negative is unspecific it needs to apply on all architectures
796 if (MultiArchEnabled
== true && found
== string::npos
&&
797 (Type
== pkgCache::Dep::Conflicts
||
798 Type
== pkgCache::Dep::DpkgBreaks
||
799 Type
== pkgCache::Dep::Replaces
))
801 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
802 a
!= Architectures
.end(); ++a
)
803 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
805 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
808 else if (found
!= string::npos
&&
809 strcmp(Package
.c_str() + found
, ":any") != 0)
811 string Arch
= Package
.substr(found
+1, string::npos
);
812 Package
= Package
.substr(0, found
);
813 // Such dependencies are not supposed to be accepted …
814 // … but this is probably the best thing to do.
815 if (Arch
== "native")
816 Arch
= _config
->Find("APT::Architecture");
817 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
822 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
824 if ((Type
== pkgCache::Dep::Conflicts
||
825 Type
== pkgCache::Dep::DpkgBreaks
||
826 Type
== pkgCache::Dep::Replaces
) &&
827 NewDepends(Ver
, Package
,
828 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
829 Version
,Op
,Type
) == false)
838 // ListParser::ParseProvides - Parse the provides list /*{{{*/
839 // ---------------------------------------------------------------------
841 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
845 if (Section
.Find("Provides",Start
,Stop
) == true)
849 string
const Arch
= Ver
.Arch();
854 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
855 const size_t archfound
= Package
.rfind(':');
857 return _error
->Error("Problem parsing Provides line");
858 if (Op
!= pkgCache::Dep::NoOp
&& Op
!= pkgCache::Dep::Equals
) {
859 _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str());
860 } else if (archfound
!= string::npos
) {
861 string OtherArch
= Package
.substr(archfound
+1, string::npos
);
862 Package
= Package
.substr(0, archfound
);
863 if (NewProvides(Ver
, Package
, OtherArch
, Version
) == false)
865 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
866 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
869 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
878 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
880 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
881 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
883 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
884 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
889 // ListParser::NewProvides - add provides for all architectures /*{{{*/
890 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
891 string
const &Version
) {
892 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
893 a
!= Architectures
.end(); ++a
)
895 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
901 // ListParser::GrabWord - Matches a word and returns /*{{{*/
902 // ---------------------------------------------------------------------
903 /* Looks for a word in a list of words - for ParseStatus */
904 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
906 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
908 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
917 // ListParser::Step - Move to the next section in the file /*{{{*/
918 // ---------------------------------------------------------------------
919 /* This has to be careful to only process the correct architecture */
920 bool debListParser::Step()
922 iOffset
= Tags
.Offset();
923 while (Tags
.Step(Section
) == true)
925 /* See if this is the correct Architecture, if it isn't then we
926 drop the whole section. A missing arch tag only happens (in theory)
927 inside the Status file, so that is a positive return */
928 string
const Architecture
= Section
.FindS("Architecture");
930 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
932 if (APT::Configuration::checkArchitecture(Architecture
) == true)
934 /* parse version stanzas without an architecture only in the status file
935 (and as misfortune bycatch flat-archives) */
936 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
941 if (Architecture
== Arch
)
944 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
948 iOffset
= Tags
.Offset();
953 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
954 // ---------------------------------------------------------------------
956 unsigned char debListParser::GetPrio(string Str
)
959 if (GrabWord(Str
,PrioList
,Out
) == false)
960 Out
= pkgCache::State::Extra
;
965 #if APT_PKG_ABI >= 413
966 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
967 pkgCache::VerIterator
const &Ver
)
969 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
971 // status file has no (Download)Size, but all others are fair game
972 // status file is parsed last, so the first version we encounter is
973 // probably also the version we have downloaded
974 unsigned long long const Size
= Section
.FindULL("Size");
975 if (Size
!= 0 && Size
!= Ver
->Size
)
977 // available everywhere, but easier to check here than to include in VersionHash
978 unsigned char MultiArch
= ParseMultiArch(false);
979 if (MultiArch
!= Ver
->MultiArch
)
981 // for all practical proposes (we can check): same version
988 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
989 : debListParser(File
, ""), DebFile(DebFile
)
993 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
994 pkgCache::VerIterator
&Ver
)
996 bool res
= debListParser::UsePackage(Pkg
, Ver
);
997 // we use the full file path as a provides so that the file is found
999 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)
1004 debListParser::~debListParser() {}