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
) :
54 pkgCacheListParser(), d(NULL
), Tags(File
)
58 // ListParser::Package - Return the package name /*{{{*/
59 // ---------------------------------------------------------------------
60 /* This is to return the name of the package this section describes */
61 string
debListParser::Package() {
62 string
const Result
= Section
.FindS("Package");
63 if(unlikely(Result
.empty() == true))
64 _error
->Error("Encountered a section with no Package: header");
68 // ListParser::Architecture - Return the package arch /*{{{*/
69 // ---------------------------------------------------------------------
70 /* This will return the Architecture of the package this section describes */
71 string
debListParser::Architecture() {
72 std::string
const Arch
= Section
.FindS("Architecture");
73 return Arch
.empty() ? "none" : Arch
;
76 // ListParser::ArchitectureAll /*{{{*/
77 // ---------------------------------------------------------------------
79 bool debListParser::ArchitectureAll() {
80 return Section
.FindS("Architecture") == "all";
83 // ListParser::Version - Return the version string /*{{{*/
84 // ---------------------------------------------------------------------
85 /* This is to return the string describing the version in debian form,
86 epoch:upstream-release. If this returns the blank string then the
87 entry is assumed to only describe package properties */
88 string
debListParser::Version()
90 return Section
.FindS("Version");
93 unsigned char debListParser::ParseMultiArch(bool const showErrors
) /*{{{*/
96 string
const MultiArch
= Section
.FindS("Multi-Arch");
97 if (MultiArch
.empty() == true || MultiArch
== "no")
98 MA
= pkgCache::Version::None
;
99 else if (MultiArch
== "same") {
100 if (ArchitectureAll() == true)
102 if (showErrors
== true)
103 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
104 Section
.FindS("Package").c_str());
105 MA
= pkgCache::Version::None
;
108 MA
= pkgCache::Version::Same
;
110 else if (MultiArch
== "foreign")
111 MA
= pkgCache::Version::Foreign
;
112 else if (MultiArch
== "allowed")
113 MA
= pkgCache::Version::Allowed
;
116 if (showErrors
== true)
117 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
118 MultiArch
.c_str(), Section
.FindS("Package").c_str());
119 MA
= pkgCache::Version::None
;
122 if (ArchitectureAll() == true)
123 MA
|= pkgCache::Version::All
;
128 // ListParser::NewVersion - Fill in the version structure /*{{{*/
129 // ---------------------------------------------------------------------
131 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
137 if (Section
.Find("Section",Start
,Stop
) == true)
139 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::SECTION
, Start
, Stop
- Start
);
142 // Parse the source package name
143 pkgCache::GrpIterator
const G
= Ver
.ParentPkg().Group();
144 Ver
->SourcePkgName
= G
->Name
;
145 Ver
->SourceVerStr
= Ver
->VerStr
;
146 if (Section
.Find("Source",Start
,Stop
) == true)
148 const char * const Space
= (const char * const) memchr(Start
, ' ', Stop
- Start
);
149 pkgCache::VerIterator V
;
154 const char * const Open
= (const char * const) memchr(Space
, '(', Stop
- Space
);
155 if (likely(Open
!= NULL
))
157 const char * const Close
= (const char * const) memchr(Open
, ')', Stop
- Open
);
158 if (likely(Close
!= NULL
))
160 std::string
const version(Open
+ 1, (Close
- Open
) - 1);
161 if (version
!= Ver
.VerStr())
163 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::VERSIONNUMBER
, version
);
164 Ver
->SourceVerStr
= idx
;
170 std::string
const pkgname(Start
, Stop
- Start
);
171 if (pkgname
!= G
.Name())
173 for (pkgCache::PkgIterator P
= G
.PackageList(); P
.end() == false; P
= G
.NextPkg(P
))
175 for (V
= P
.VersionList(); V
.end() == false; ++V
)
177 if (pkgname
== V
.SourcePkgName())
179 Ver
->SourcePkgName
= V
->SourcePkgName
;
183 if (V
.end() == false)
188 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::PKGNAME
, pkgname
);
189 Ver
->SourcePkgName
= idx
;
194 Ver
->MultiArch
= ParseMultiArch(true);
196 Ver
->Size
= Section
.FindULL("Size");
197 // Unpacked Size (in K)
198 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
199 Ver
->InstalledSize
*= 1024;
202 if (Section
.Find("Priority",Start
,Stop
) == true)
204 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
205 Ver
->Priority
= pkgCache::State::Extra
;
208 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
210 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
212 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
214 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
216 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
218 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
220 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
222 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
225 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
228 if (ParseProvides(Ver
) == false)
234 // ListParser::Description - Return the description string /*{{{*/
235 // ---------------------------------------------------------------------
236 /* This is to return the string describing the package in debian
237 form. If this returns the blank string then the entry is assumed to
238 only describe package properties */
239 string
debListParser::Description(std::string
const &lang
)
242 return Section
.FindS("Description");
244 return Section
.FindS(string("Description-").append(lang
).c_str());
247 // ListParser::AvailableDescriptionLanguages /*{{{*/
248 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages()
250 std::vector
<std::string
> const understood
= APT::Configuration::getLanguages();
251 std::vector
<std::string
> avail
;
252 if (Section
.Exists("Description") == true)
254 for (std::vector
<std::string
>::const_iterator lang
= understood
.begin(); lang
!= understood
.end(); ++lang
)
256 std::string
const tagname
= "Description-" + *lang
;
257 if (Section
.Exists(tagname
.c_str()) == true)
258 avail
.push_back(*lang
);
263 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
264 // ---------------------------------------------------------------------
265 /* This is to return the md5 string to allow the check if it is the right
266 description. If no Description-md5 is found in the section it will be
269 MD5SumValue
debListParser::Description_md5()
271 string
const value
= Section
.FindS("Description-md5");
272 if (value
.empty() == true)
274 std::string
const desc
= Description("") + "\n";
276 return MD5SumValue();
279 md5
.Add(desc
.c_str());
282 else if (likely(value
.size() == 32))
284 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
285 return MD5SumValue(value
);
286 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
287 return MD5SumValue();
289 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
290 return MD5SumValue();
293 // ListParser::UsePackage - Update a package structure /*{{{*/
294 // ---------------------------------------------------------------------
295 /* This is called to update the package with any new information
296 that might be found in the section */
297 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
298 pkgCache::VerIterator
&Ver
)
300 string
const static myArch
= _config
->Find("APT::Architecture");
301 // Possible values are: "all", "native", "installed" and "none"
302 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
303 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
304 if (essential
== "all" ||
305 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
306 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
308 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
311 if (strcmp(Pkg
.Name(),"apt") == 0)
313 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
315 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
317 Pkg
->Flags
|= pkgCache::Flag::Important
;
320 if (ParseStatus(Pkg
,Ver
) == false)
325 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
326 // ---------------------------------------------------------------------
328 unsigned short debListParser::VersionHash()
330 const char *Sections
[] ={"Installed-Size",
338 unsigned long Result
= INIT_FCS
;
340 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
344 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
347 /* Strip out any spaces from the text, this undoes dpkgs reformatting
348 of certain fields. dpkg also has the rather interesting notion of
349 reformatting depends operators < -> <= */
351 for (; Start
!= End
; ++Start
)
353 if (isspace(*Start
) != 0)
355 *J
++ = tolower_ascii(*Start
);
357 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
361 Result
= AddCRC16(Result
,S
,J
- S
);
367 // ListParser::ParseStatus - Parse the status field /*{{{*/
368 // ---------------------------------------------------------------------
369 /* Status lines are of the form,
370 Status: want flag status
371 want = unknown, install, hold, deinstall, purge
373 status = not-installed, config-files, half-installed, unpacked,
374 half-configured, triggers-awaited, triggers-pending, installed
376 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
377 pkgCache::VerIterator
&Ver
)
381 if (Section
.Find("Status",Start
,Stop
) == false)
384 // UsePackage() is responsible for setting the flag in the default case
385 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
386 if (essential
== true &&
387 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
390 // Isolate the first word
391 const char *I
= Start
;
392 for(; I
< Stop
&& *I
!= ' '; I
++);
393 if (I
>= Stop
|| *I
!= ' ')
394 return _error
->Error("Malformed Status line");
396 // Process the want field
397 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
398 {"install",pkgCache::State::Install
},
399 {"hold",pkgCache::State::Hold
},
400 {"deinstall",pkgCache::State::DeInstall
},
401 {"purge",pkgCache::State::Purge
},
403 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
404 return _error
->Error("Malformed 1st word in the Status line");
406 // Isloate the next word
409 for(; I
< Stop
&& *I
!= ' '; I
++);
410 if (I
>= Stop
|| *I
!= ' ')
411 return _error
->Error("Malformed status line, no 2nd word");
413 // Process the flag field
414 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
415 {"reinstreq",pkgCache::State::ReInstReq
},
416 {"hold",pkgCache::State::HoldInst
},
417 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
419 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
420 return _error
->Error("Malformed 2nd word in the Status line");
422 // Isloate the last word
425 for(; I
< Stop
&& *I
!= ' '; I
++);
427 return _error
->Error("Malformed Status line, no 3rd word");
429 // Process the flag field
430 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
431 {"config-files",pkgCache::State::ConfigFiles
},
432 {"half-installed",pkgCache::State::HalfInstalled
},
433 {"unpacked",pkgCache::State::UnPacked
},
434 {"half-configured",pkgCache::State::HalfConfigured
},
435 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
436 {"triggers-pending",pkgCache::State::TriggersPending
},
437 {"installed",pkgCache::State::Installed
},
439 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
440 return _error
->Error("Malformed 3rd word in the Status line");
442 /* A Status line marks the package as indicating the current
443 version as well. Only if it is actually installed.. Otherwise
444 the interesting dpkg handling of the status file creates bogus
446 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
447 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
449 if (Ver
.end() == true)
450 _error
->Warning("Encountered status field in a non-version description");
452 Pkg
->CurrentVer
= Ver
.Index();
458 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
460 // Determine the operator
468 Op
= pkgCache::Dep::LessEq
;
475 Op
= pkgCache::Dep::Less
;
479 // < is the same as <= and << is really Cs < for some reason
480 Op
= pkgCache::Dep::LessEq
;
488 Op
= pkgCache::Dep::GreaterEq
;
495 Op
= pkgCache::Dep::Greater
;
499 // > is the same as >= and >> is really Cs > for some reason
500 Op
= pkgCache::Dep::GreaterEq
;
504 Op
= pkgCache::Dep::Equals
;
508 // HACK around bad package definitions
510 Op
= pkgCache::Dep::Equals
;
516 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
517 // ---------------------------------------------------------------------
518 /* This parses the dependency elements out of a standard string in place,
520 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
521 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
522 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
523 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
524 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
525 bool const &ParseArchFlags
)
526 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, 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
, bool const &StripMultiArch
)
530 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
531 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
532 string
&Package
,string
&Ver
,
533 unsigned int &Op
, bool const &ParseArchFlags
,
534 bool const &StripMultiArch
,
535 bool const &ParseRestrictionsList
)
537 // Strip off leading space
538 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
540 // Parse off the package name
541 const char *I
= Start
;
542 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
543 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
544 *I
!= '<' && *I
!= '>'; ++I
);
547 if (I
!= Stop
&& *I
== ')')
553 // Stash the package name
554 Package
.assign(Start
,I
- Start
);
556 // We don't want to confuse library users which can't handle MultiArch
557 string
const arch
= _config
->Find("APT::Architecture");
558 if (StripMultiArch
== true) {
559 size_t const found
= Package
.rfind(':');
560 if (found
!= string::npos
&&
561 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
562 strcmp(Package
.c_str() + found
, ":native") == 0 ||
563 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
564 Package
= Package
.substr(0,found
);
567 // Skip white space to the '('
568 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
571 if (I
!= Stop
&& *I
== '(')
574 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
577 I
= ConvertRelation(I
,Op
);
580 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
582 I
= (const char*) memchr(I
, ')', Stop
- I
);
583 if (I
== NULL
|| Start
== I
)
586 // Skip trailing whitespace
588 for (; End
> Start
&& isspace(End
[-1]); End
--);
590 Ver
.assign(Start
,End
-Start
);
596 Op
= pkgCache::Dep::NoOp
;
600 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
602 if (ParseArchFlags
== true)
604 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
606 // Parse an architecture
607 if (I
!= Stop
&& *I
== '[')
611 if (unlikely(I
== Stop
))
616 bool NegArch
= false;
619 // look for whitespace or ending ']'
620 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
622 if (unlikely(End
== Stop
))
631 std::string
arch(I
, End
);
632 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
637 // we found a match, so fast-forward to the end of the wildcards
638 for (; End
!= Stop
&& *End
!= ']'; ++End
);
647 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
654 Package
= ""; /* not for this arch */
658 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
661 if (ParseRestrictionsList
== true)
663 // Parse a restrictions formula which is in disjunctive normal form:
664 // (foo AND bar) OR (blub AND bla)
666 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
668 // if the next character is a restriction list, then by default the
669 // dependency does not apply and the conditions have to be checked
670 // if the next character is not a restriction list, then by default the
671 // dependency applies
672 bool applies1
= (*I
!= '<');
680 if (unlikely(I
== Stop
))
685 // if of the prior restriction list is already fulfilled, then
686 // we can just skip to the end of the current list
688 for (;End
!= Stop
&& *End
!= '>'; ++End
);
691 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
693 bool applies2
= true;
694 // all the conditions inside a restriction list have to be
695 // met so once we find one that is not met, we can skip to
696 // the end of this list
699 // look for whitespace or ending '>'
700 // End now points to the character after the current term
701 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
703 if (unlikely(End
== Stop
))
706 bool NegRestriction
= false;
709 NegRestriction
= true;
713 std::string
restriction(I
, End
);
715 if (restriction
.empty() == false && profiles
.empty() == false &&
716 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
718 if (NegRestriction
) {
720 // since one of the terms does not apply we don't have to check the others
721 for (; End
!= Stop
&& *End
!= '>'; ++End
);
724 if (!NegRestriction
) {
726 // since one of the terms does not apply we don't have to check the others
727 for (; End
!= Stop
&& *End
!= '>'; ++End
);
734 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
740 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
748 if (applies1
== false) {
749 Package
= ""; //not for this restriction
753 if (I
!= Stop
&& *I
== '|')
754 Op
|= pkgCache::Dep::Or
;
756 if (I
== Stop
|| *I
== ',' || *I
== '|')
759 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
766 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
767 // ---------------------------------------------------------------------
768 /* This is the higher level depends parser. It takes a tag and generates
769 a complete depends tree for the given version. */
770 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
771 const char *Tag
,unsigned int Type
)
775 if (Section
.Find(Tag
,Start
,Stop
) == false)
778 string
const pkgArch
= Ver
.Arch();
786 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
788 return _error
->Error("Problem parsing dependency %s",Tag
);
789 size_t const found
= Package
.rfind(':');
791 if (found
== string::npos
|| strcmp(Package
.c_str() + found
, ":any") == 0)
793 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
798 string Arch
= Package
.substr(found
+1, string::npos
);
799 Package
= Package
.substr(0, found
);
800 // Such dependencies are not supposed to be accepted …
801 // … but this is probably the best thing to do anyway
802 if (Arch
== "native")
803 Arch
= _config
->Find("APT::Architecture");
804 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
| pkgCache::Dep::ArchSpecific
,Type
) == false)
814 // ListParser::ParseProvides - Parse the provides list /*{{{*/
815 // ---------------------------------------------------------------------
817 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
821 if (Section
.Find("Provides",Start
,Stop
) == true)
825 string
const Arch
= Ver
.Arch();
830 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
831 const size_t archfound
= Package
.rfind(':');
833 return _error
->Error("Problem parsing Provides line");
834 if (Op
!= pkgCache::Dep::NoOp
&& Op
!= pkgCache::Dep::Equals
) {
835 _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str());
836 } else if (archfound
!= string::npos
) {
837 string OtherArch
= Package
.substr(archfound
+1, string::npos
);
838 Package
= Package
.substr(0, archfound
);
839 if (NewProvides(Ver
, Package
, OtherArch
, Version
, pkgCache::Flag::ArchSpecific
) == false)
841 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
842 if (NewProvidesAllArch(Ver
, Package
, Version
, 0) == false)
845 if (NewProvides(Ver
, Package
, Arch
, Version
, 0) == false)
854 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
856 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
857 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr(), pkgCache::Flag::MultiArchImplicit
);
859 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
860 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr(), pkgCache::Flag::MultiArchImplicit
);
865 // ListParser::GrabWord - Matches a word and returns /*{{{*/
866 // ---------------------------------------------------------------------
867 /* Looks for a word in a list of words - for ParseStatus */
868 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
870 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
872 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
881 // ListParser::Step - Move to the next section in the file /*{{{*/
882 // ---------------------------------------------------------------------
883 /* This has to be careful to only process the correct architecture */
884 bool debListParser::Step()
886 iOffset
= Tags
.Offset();
887 return Tags
.Step(Section
);
890 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
891 // ---------------------------------------------------------------------
893 unsigned char debListParser::GetPrio(string Str
)
896 if (GrabWord(Str
,PrioList
,Out
) == false)
897 Out
= pkgCache::State::Extra
;
902 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
903 pkgCache::VerIterator
const &Ver
)
905 if (pkgCacheListParser::SameVersion(Hash
, Ver
) == false)
907 // status file has no (Download)Size, but all others are fair game
908 // status file is parsed last, so the first version we encounter is
909 // probably also the version we have downloaded
910 unsigned long long const Size
= Section
.FindULL("Size");
911 if (Size
!= 0 && Size
!= Ver
->Size
)
913 // available everywhere, but easier to check here than to include in VersionHash
914 unsigned char MultiArch
= ParseMultiArch(false);
915 if (MultiArch
!= Ver
->MultiArch
)
917 // for all practical proposes (we can check): same version
922 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
923 : debListParser(File
), DebFile(DebFile
)
927 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
928 pkgCache::VerIterator
&Ver
)
930 bool res
= debListParser::UsePackage(Pkg
, Ver
);
931 // we use the full file path as a provides so that the file is found
933 if(NewProvides(Ver
, DebFile
, Pkg
.Cache()->NativeArch(), Ver
.VerStr(), 0) == false)
938 debListParser::~debListParser() {}