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 // Parse the source package name
145 pkgCache::GrpIterator
const G
= Ver
.ParentPkg().Group();
146 Ver
->SourcePkgName
= G
->Name
;
147 Ver
->SourceVerStr
= Ver
->VerStr
;
148 if (Section
.Find("Source",Start
,Stop
) == true)
150 const char * const Space
= (const char * const) memchr(Start
, ' ', Stop
- Start
);
151 pkgCache::VerIterator V
;
156 const char * const Open
= (const char * const) memchr(Space
, '(', Stop
- Space
);
157 if (likely(Open
!= NULL
))
159 const char * const Close
= (const char * const) memchr(Open
, ')', Stop
- Open
);
160 if (likely(Close
!= NULL
))
162 std::string
const version(Open
+ 1, (Close
- Open
) - 1);
163 if (version
!= Ver
.VerStr())
165 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::VERSIONNUMBER
, version
);
166 Ver
->SourceVerStr
= idx
;
172 std::string
const pkgname(Start
, Stop
- Start
);
173 if (pkgname
!= G
.Name())
175 for (pkgCache::PkgIterator P
= G
.PackageList(); P
.end() == false; P
= G
.NextPkg(P
))
177 for (V
= P
.VersionList(); V
.end() == false; ++V
)
179 if (pkgname
== V
.SourcePkgName())
181 Ver
->SourcePkgName
= V
->SourcePkgName
;
185 if (V
.end() == false)
190 map_stringitem_t
const idx
= StoreString(pkgCacheGenerator::PKGNAME
, pkgname
);
191 Ver
->SourcePkgName
= idx
;
196 Ver
->MultiArch
= ParseMultiArch(true);
198 Ver
->Size
= Section
.FindULL("Size");
199 // Unpacked Size (in K)
200 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
201 Ver
->InstalledSize
*= 1024;
204 if (Section
.Find("Priority",Start
,Stop
) == true)
206 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
207 Ver
->Priority
= pkgCache::State::Extra
;
210 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
212 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
214 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
216 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
218 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
220 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
222 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
224 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
227 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
230 if (ParseProvides(Ver
) == false)
236 // ListParser::Description - Return the description string /*{{{*/
237 // ---------------------------------------------------------------------
238 /* This is to return the string describing the package in debian
239 form. If this returns the blank string then the entry is assumed to
240 only describe package properties */
241 string
debListParser::Description(std::string
const &lang
)
244 return Section
.FindS("Description");
246 return Section
.FindS(string("Description-").append(lang
).c_str());
249 // ListParser::AvailableDescriptionLanguages /*{{{*/
250 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages()
252 std::vector
<std::string
> const understood
= APT::Configuration::getLanguages();
253 std::vector
<std::string
> avail
;
254 if (Section
.Exists("Description") == true)
256 for (std::vector
<std::string
>::const_iterator lang
= understood
.begin(); lang
!= understood
.end(); ++lang
)
258 std::string
const tagname
= "Description-" + *lang
;
259 if (Section
.Exists(tagname
.c_str()) == true)
260 avail
.push_back(*lang
);
265 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
266 // ---------------------------------------------------------------------
267 /* This is to return the md5 string to allow the check if it is the right
268 description. If no Description-md5 is found in the section it will be
271 MD5SumValue
debListParser::Description_md5()
273 string
const value
= Section
.FindS("Description-md5");
274 if (value
.empty() == true)
276 std::string
const desc
= Description("") + "\n";
278 return MD5SumValue();
281 md5
.Add(desc
.c_str());
284 else if (likely(value
.size() == 32))
286 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
287 return MD5SumValue(value
);
288 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
289 return MD5SumValue();
291 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
292 return MD5SumValue();
295 // ListParser::UsePackage - Update a package structure /*{{{*/
296 // ---------------------------------------------------------------------
297 /* This is called to update the package with any new information
298 that might be found in the section */
299 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
300 pkgCache::VerIterator
&Ver
)
302 string
const static myArch
= _config
->Find("APT::Architecture");
303 // Possible values are: "all", "native", "installed" and "none"
304 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
305 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
306 if (essential
== "all" ||
307 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
308 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
310 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
313 if (strcmp(Pkg
.Name(),"apt") == 0)
315 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
317 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
319 Pkg
->Flags
|= pkgCache::Flag::Important
;
322 if (ParseStatus(Pkg
,Ver
) == false)
327 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
328 // ---------------------------------------------------------------------
330 unsigned short debListParser::VersionHash()
332 const char *Sections
[] ={"Installed-Size",
340 unsigned long Result
= INIT_FCS
;
342 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
346 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
349 /* Strip out any spaces from the text, this undoes dpkgs reformatting
350 of certain fields. dpkg also has the rather interesting notion of
351 reformatting depends operators < -> <= */
353 for (; Start
!= End
; ++Start
)
355 if (isspace(*Start
) != 0)
357 *J
++ = tolower_ascii(*Start
);
359 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
363 Result
= AddCRC16(Result
,S
,J
- S
);
369 // ListParser::ParseStatus - Parse the status field /*{{{*/
370 // ---------------------------------------------------------------------
371 /* Status lines are of the form,
372 Status: want flag status
373 want = unknown, install, hold, deinstall, purge
375 status = not-installed, config-files, half-installed, unpacked,
376 half-configured, triggers-awaited, triggers-pending, installed
378 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
379 pkgCache::VerIterator
&Ver
)
383 if (Section
.Find("Status",Start
,Stop
) == false)
386 // UsePackage() is responsible for setting the flag in the default case
387 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
388 if (essential
== true &&
389 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
392 // Isolate the first word
393 const char *I
= Start
;
394 for(; I
< Stop
&& *I
!= ' '; I
++);
395 if (I
>= Stop
|| *I
!= ' ')
396 return _error
->Error("Malformed Status line");
398 // Process the want field
399 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
400 {"install",pkgCache::State::Install
},
401 {"hold",pkgCache::State::Hold
},
402 {"deinstall",pkgCache::State::DeInstall
},
403 {"purge",pkgCache::State::Purge
},
405 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
406 return _error
->Error("Malformed 1st word in the Status line");
408 // Isloate the next word
411 for(; I
< Stop
&& *I
!= ' '; I
++);
412 if (I
>= Stop
|| *I
!= ' ')
413 return _error
->Error("Malformed status line, no 2nd word");
415 // Process the flag field
416 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
417 {"reinstreq",pkgCache::State::ReInstReq
},
418 {"hold",pkgCache::State::HoldInst
},
419 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
421 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
422 return _error
->Error("Malformed 2nd word in the Status line");
424 // Isloate the last word
427 for(; I
< Stop
&& *I
!= ' '; I
++);
429 return _error
->Error("Malformed Status line, no 3rd word");
431 // Process the flag field
432 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
433 {"config-files",pkgCache::State::ConfigFiles
},
434 {"half-installed",pkgCache::State::HalfInstalled
},
435 {"unpacked",pkgCache::State::UnPacked
},
436 {"half-configured",pkgCache::State::HalfConfigured
},
437 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
438 {"triggers-pending",pkgCache::State::TriggersPending
},
439 {"installed",pkgCache::State::Installed
},
441 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
442 return _error
->Error("Malformed 3rd word in the Status line");
444 /* A Status line marks the package as indicating the current
445 version as well. Only if it is actually installed.. Otherwise
446 the interesting dpkg handling of the status file creates bogus
448 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
449 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
451 if (Ver
.end() == true)
452 _error
->Warning("Encountered status field in a non-version description");
454 Pkg
->CurrentVer
= Ver
.Index();
460 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
462 // Determine the operator
470 Op
= pkgCache::Dep::LessEq
;
477 Op
= pkgCache::Dep::Less
;
481 // < is the same as <= and << is really Cs < for some reason
482 Op
= pkgCache::Dep::LessEq
;
490 Op
= pkgCache::Dep::GreaterEq
;
497 Op
= pkgCache::Dep::Greater
;
501 // > is the same as >= and >> is really Cs > for some reason
502 Op
= pkgCache::Dep::GreaterEq
;
506 Op
= pkgCache::Dep::Equals
;
510 // HACK around bad package definitions
512 Op
= pkgCache::Dep::Equals
;
518 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
519 // ---------------------------------------------------------------------
520 /* This parses the dependency elements out of a standard string in place,
522 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
523 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
524 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
525 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
526 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
527 bool const &ParseArchFlags
)
528 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
529 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
530 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
531 bool const &ParseArchFlags
, bool const &StripMultiArch
)
532 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
533 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
534 string
&Package
,string
&Ver
,
535 unsigned int &Op
, bool const &ParseArchFlags
,
536 bool const &StripMultiArch
,
537 bool const &ParseRestrictionsList
)
539 // Strip off leading space
540 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
542 // Parse off the package name
543 const char *I
= Start
;
544 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
545 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
546 *I
!= '<' && *I
!= '>'; ++I
);
549 if (I
!= Stop
&& *I
== ')')
555 // Stash the package name
556 Package
.assign(Start
,I
- Start
);
558 // We don't want to confuse library users which can't handle MultiArch
559 string
const arch
= _config
->Find("APT::Architecture");
560 if (StripMultiArch
== true) {
561 size_t const found
= Package
.rfind(':');
562 if (found
!= string::npos
&&
563 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
564 strcmp(Package
.c_str() + found
, ":native") == 0 ||
565 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
566 Package
= Package
.substr(0,found
);
569 // Skip white space to the '('
570 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
573 if (I
!= Stop
&& *I
== '(')
576 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
579 I
= ConvertRelation(I
,Op
);
582 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
584 I
= (const char*) memchr(I
, ')', Stop
- I
);
585 if (I
== NULL
|| Start
== I
)
588 // Skip trailing whitespace
590 for (; End
> Start
&& isspace(End
[-1]); End
--);
592 Ver
.assign(Start
,End
-Start
);
598 Op
= pkgCache::Dep::NoOp
;
602 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
604 if (ParseArchFlags
== true)
606 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
608 // Parse an architecture
609 if (I
!= Stop
&& *I
== '[')
613 if (unlikely(I
== Stop
))
618 bool NegArch
= false;
621 // look for whitespace or ending ']'
622 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
624 if (unlikely(End
== Stop
))
633 std::string
arch(I
, End
);
634 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
639 // we found a match, so fast-forward to the end of the wildcards
640 for (; End
!= Stop
&& *End
!= ']'; ++End
);
649 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
656 Package
= ""; /* not for this arch */
660 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
663 if (ParseRestrictionsList
== true)
665 // Parse a restrictions formula which is in disjunctive normal form:
666 // (foo AND bar) OR (blub AND bla)
668 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
670 // if the next character is a restriction list, then by default the
671 // dependency does not apply and the conditions have to be checked
672 // if the next character is not a restriction list, then by default the
673 // dependency applies
674 bool applies1
= (*I
!= '<');
682 if (unlikely(I
== Stop
))
687 // if of the prior restriction list is already fulfilled, then
688 // we can just skip to the end of the current list
690 for (;End
!= Stop
&& *End
!= '>'; ++End
);
693 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
695 bool applies2
= true;
696 // all the conditions inside a restriction list have to be
697 // met so once we find one that is not met, we can skip to
698 // the end of this list
701 // look for whitespace or ending '>'
702 // End now points to the character after the current term
703 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
705 if (unlikely(End
== Stop
))
708 bool NegRestriction
= false;
711 NegRestriction
= true;
715 std::string
restriction(I
, End
);
717 if (restriction
.empty() == false && profiles
.empty() == false &&
718 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
720 if (NegRestriction
) {
722 // since one of the terms does not apply we don't have to check the others
723 for (; End
!= Stop
&& *End
!= '>'; ++End
);
726 if (!NegRestriction
) {
728 // since one of the terms does not apply we don't have to check the others
729 for (; End
!= Stop
&& *End
!= '>'; ++End
);
736 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
742 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
750 if (applies1
== false) {
751 Package
= ""; //not for this restriction
755 if (I
!= Stop
&& *I
== '|')
756 Op
|= pkgCache::Dep::Or
;
758 if (I
== Stop
|| *I
== ',' || *I
== '|')
761 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
768 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
769 // ---------------------------------------------------------------------
770 /* This is the higher level depends parser. It takes a tag and generates
771 a complete depends tree for the given version. */
772 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
773 const char *Tag
,unsigned int Type
)
777 if (Section
.Find(Tag
,Start
,Stop
) == false)
780 string
const pkgArch
= Ver
.Arch();
788 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
790 return _error
->Error("Problem parsing dependency %s",Tag
);
791 size_t const found
= Package
.rfind(':');
793 // If negative is unspecific it needs to apply on all architectures
794 if (MultiArchEnabled
== true && found
== string::npos
&&
795 (Type
== pkgCache::Dep::Conflicts
||
796 Type
== pkgCache::Dep::DpkgBreaks
||
797 Type
== pkgCache::Dep::Replaces
))
799 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
800 a
!= Architectures
.end(); ++a
)
801 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
803 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
806 else if (found
!= string::npos
&&
807 strcmp(Package
.c_str() + found
, ":any") != 0)
809 string Arch
= Package
.substr(found
+1, string::npos
);
810 Package
= Package
.substr(0, found
);
811 // Such dependencies are not supposed to be accepted …
812 // … but this is probably the best thing to do.
813 if (Arch
== "native")
814 Arch
= _config
->Find("APT::Architecture");
815 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
820 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
822 if ((Type
== pkgCache::Dep::Conflicts
||
823 Type
== pkgCache::Dep::DpkgBreaks
||
824 Type
== pkgCache::Dep::Replaces
) &&
825 NewDepends(Ver
, Package
,
826 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
827 Version
,Op
,Type
) == false)
836 // ListParser::ParseProvides - Parse the provides list /*{{{*/
837 // ---------------------------------------------------------------------
839 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
843 if (Section
.Find("Provides",Start
,Stop
) == true)
847 string
const Arch
= Ver
.Arch();
852 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
853 const size_t archfound
= Package
.rfind(':');
855 return _error
->Error("Problem parsing Provides line");
856 if (Op
!= pkgCache::Dep::NoOp
&& Op
!= pkgCache::Dep::Equals
) {
857 _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str());
858 } else if (archfound
!= string::npos
) {
859 string OtherArch
= Package
.substr(archfound
+1, string::npos
);
860 Package
= Package
.substr(0, archfound
);
861 if (NewProvides(Ver
, Package
, OtherArch
, Version
) == false)
863 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
864 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
867 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
876 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
878 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
879 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
881 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
882 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
887 // ListParser::NewProvides - add provides for all architectures /*{{{*/
888 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
889 string
const &Version
) {
890 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
891 a
!= Architectures
.end(); ++a
)
893 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
899 // ListParser::GrabWord - Matches a word and returns /*{{{*/
900 // ---------------------------------------------------------------------
901 /* Looks for a word in a list of words - for ParseStatus */
902 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
904 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
906 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
915 // ListParser::Step - Move to the next section in the file /*{{{*/
916 // ---------------------------------------------------------------------
917 /* This has to be careful to only process the correct architecture */
918 bool debListParser::Step()
920 iOffset
= Tags
.Offset();
921 while (Tags
.Step(Section
) == true)
923 /* See if this is the correct Architecture, if it isn't then we
924 drop the whole section. A missing arch tag only happens (in theory)
925 inside the Status file, so that is a positive return */
926 string
const Architecture
= Section
.FindS("Architecture");
928 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
930 if (APT::Configuration::checkArchitecture(Architecture
) == true)
932 /* parse version stanzas without an architecture only in the status file
933 (and as misfortune bycatch flat-archives) */
934 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
939 if (Architecture
== Arch
)
942 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
946 iOffset
= Tags
.Offset();
951 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
952 // ---------------------------------------------------------------------
954 unsigned char debListParser::GetPrio(string Str
)
957 if (GrabWord(Str
,PrioList
,Out
) == false)
958 Out
= pkgCache::State::Extra
;
963 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
964 pkgCache::VerIterator
const &Ver
)
966 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
968 // status file has no (Download)Size, but all others are fair game
969 // status file is parsed last, so the first version we encounter is
970 // probably also the version we have downloaded
971 unsigned long long const Size
= Section
.FindULL("Size");
972 if (Size
!= 0 && Size
!= Ver
->Size
)
974 // available everywhere, but easier to check here than to include in VersionHash
975 unsigned char MultiArch
= ParseMultiArch(false);
976 if (MultiArch
!= Ver
->MultiArch
)
978 // for all practical proposes (we can check): same version
983 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
984 : debListParser(File
, ""), DebFile(DebFile
)
988 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
989 pkgCache::VerIterator
&Ver
)
991 bool res
= debListParser::UsePackage(Pkg
, Ver
);
992 // we use the full file path as a provides so that the file is found
994 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)
999 debListParser::~debListParser() {}