1 // -*- mode: cpp; mode: fold -*-
3 // $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $
4 /* ######################################################################
6 Package Cache Generator - Generator for the cache structure.
8 This builds the cache structure from the abstract package list parser.
10 ##################################################################### */
12 // Include Files /*{{{*/
15 #include <apt-pkg/deblistparser.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/configuration.h>
18 #include <apt-pkg/cachefilter.h>
19 #include <apt-pkg/aptconfiguration.h>
20 #include <apt-pkg/strutl.h>
21 #include <apt-pkg/fileutl.h>
22 #include <apt-pkg/crc-16.h>
23 #include <apt-pkg/md5.h>
24 #include <apt-pkg/mmap.h>
25 #include <apt-pkg/pkgcache.h>
26 #include <apt-pkg/cacheiterators.h>
27 #include <apt-pkg/tagfile.h>
28 #include <apt-pkg/macros.h>
40 static debListParser::WordList PrioList
[] = {
41 {"required",pkgCache::State::Required
},
42 {"important",pkgCache::State::Important
},
43 {"standard",pkgCache::State::Standard
},
44 {"optional",pkgCache::State::Optional
},
45 {"extra",pkgCache::State::Extra
},
48 // ListParser::debListParser - Constructor /*{{{*/
49 // ---------------------------------------------------------------------
50 /* Provide an architecture and only this one and "all" will be accepted
51 in Step(), if no Architecture is given we will accept every arch
52 we would accept in general with checkArchitecture() */
53 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
56 this->Arch
= _config
->Find("APT::Architecture");
57 Architectures
= APT::Configuration::getArchitectures();
58 MultiArchEnabled
= Architectures
.size() > 1;
61 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
62 // ---------------------------------------------------------------------
64 map_stringitem_t
debListParser::UniqFindTagWrite(const char *Tag
)
68 if (Section
.Find(Tag
,Start
,Stop
) == false)
70 return WriteUniqString(Start
,Stop
- Start
);
73 // ListParser::Package - Return the package name /*{{{*/
74 // ---------------------------------------------------------------------
75 /* This is to return the name of the package this section describes */
76 string
debListParser::Package() {
77 string
const Result
= Section
.FindS("Package");
78 if(unlikely(Result
.empty() == true))
79 _error
->Error("Encountered a section with no Package: header");
83 // ListParser::Architecture - Return the package arch /*{{{*/
84 // ---------------------------------------------------------------------
85 /* This will return the Architecture of the package this section describes */
86 string
debListParser::Architecture() {
87 return Section
.FindS("Architecture");
90 // ListParser::ArchitectureAll /*{{{*/
91 // ---------------------------------------------------------------------
93 bool debListParser::ArchitectureAll() {
94 return Section
.FindS("Architecture") == "all";
97 // ListParser::Version - Return the version string /*{{{*/
98 // ---------------------------------------------------------------------
99 /* This is to return the string describing the version in debian form,
100 epoch:upstream-release. If this returns the blank string then the
101 entry is assumed to only describe package properties */
102 string
debListParser::Version()
104 return Section
.FindS("Version");
107 unsigned char debListParser::ParseMultiArch(bool const showErrors
) /*{{{*/
110 string
const MultiArch
= Section
.FindS("Multi-Arch");
111 if (MultiArch
.empty() == true || MultiArch
== "no")
112 MA
= pkgCache::Version::None
;
113 else if (MultiArch
== "same") {
114 if (ArchitectureAll() == true)
116 if (showErrors
== true)
117 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
118 Section
.FindS("Package").c_str());
119 MA
= pkgCache::Version::None
;
122 MA
= pkgCache::Version::Same
;
124 else if (MultiArch
== "foreign")
125 MA
= pkgCache::Version::Foreign
;
126 else if (MultiArch
== "allowed")
127 MA
= pkgCache::Version::Allowed
;
130 if (showErrors
== true)
131 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
132 MultiArch
.c_str(), Section
.FindS("Package").c_str());
133 MA
= pkgCache::Version::None
;
136 if (ArchitectureAll() == true)
137 MA
|= pkgCache::Version::All
;
142 // ListParser::NewVersion - Fill in the version structure /*{{{*/
143 // ---------------------------------------------------------------------
145 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
148 unsigned long const idxSection
= UniqFindTagWrite("Section");
149 Ver
->Section
= idxSection
;
150 Ver
->MultiArch
= ParseMultiArch(true);
152 Ver
->Size
= Section
.FindULL("Size");
153 // Unpacked Size (in K)
154 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
155 Ver
->InstalledSize
*= 1024;
160 if (Section
.Find("Priority",Start
,Stop
) == true)
162 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
163 Ver
->Priority
= pkgCache::State::Extra
;
166 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
168 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
170 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
172 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
174 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
176 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
178 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
180 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
184 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
187 if (ParseProvides(Ver
) == false)
193 // ListParser::Description - Return the description string /*{{{*/
194 // ---------------------------------------------------------------------
195 /* This is to return the string describing the package in debian
196 form. If this returns the blank string then the entry is assumed to
197 only describe package properties */
198 string
debListParser::Description(std::string
const &lang
)
201 return Section
.FindS("Description");
203 return Section
.FindS(string("Description-").append(lang
).c_str());
206 // ListParser::AvailableDescriptionLanguages /*{{{*/
207 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages()
209 std::vector
<std::string
> const understood
= APT::Configuration::getLanguages();
210 std::vector
<std::string
> avail
;
211 if (Section
.Exists("Description") == true)
213 for (std::vector
<std::string
>::const_iterator lang
= understood
.begin(); lang
!= understood
.end(); ++lang
)
215 std::string
const tagname
= "Description-" + *lang
;
216 if (Section
.Exists(tagname
.c_str()) == true)
217 avail
.push_back(*lang
);
222 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
223 // ---------------------------------------------------------------------
224 /* This is to return the md5 string to allow the check if it is the right
225 description. If no Description-md5 is found in the section it will be
228 MD5SumValue
debListParser::Description_md5()
230 string
const value
= Section
.FindS("Description-md5");
231 if (value
.empty() == true)
233 std::string
const desc
= Description("") + "\n";
235 return MD5SumValue();
238 md5
.Add(desc
.c_str());
241 else if (likely(value
.size() == 32))
243 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
244 return MD5SumValue(value
);
245 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
246 return MD5SumValue();
248 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
249 return MD5SumValue();
252 // ListParser::UsePackage - Update a package structure /*{{{*/
253 // ---------------------------------------------------------------------
254 /* This is called to update the package with any new information
255 that might be found in the section */
256 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
257 pkgCache::VerIterator
&Ver
)
259 string
const static myArch
= _config
->Find("APT::Architecture");
260 // Possible values are: "all", "native", "installed" and "none"
261 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
262 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
263 if (essential
== "all" ||
264 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
265 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
267 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
270 if (strcmp(Pkg
.Name(),"apt") == 0)
272 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
274 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
276 Pkg
->Flags
|= pkgCache::Flag::Important
;
279 if (ParseStatus(Pkg
,Ver
) == false)
284 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
285 // ---------------------------------------------------------------------
287 unsigned short debListParser::VersionHash()
289 const char *Sections
[] ={"Installed-Size",
297 unsigned long Result
= INIT_FCS
;
299 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
303 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
306 /* Strip out any spaces from the text, this undoes dpkgs reformatting
307 of certain fields. dpkg also has the rather interesting notion of
308 reformatting depends operators < -> <= */
310 for (; Start
!= End
; ++Start
)
312 if (isspace(*Start
) != 0)
314 *J
++ = tolower_ascii(*Start
);
316 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
320 Result
= AddCRC16(Result
,S
,J
- S
);
326 // ListParser::ParseStatus - Parse the status field /*{{{*/
327 // ---------------------------------------------------------------------
328 /* Status lines are of the form,
329 Status: want flag status
330 want = unknown, install, hold, deinstall, purge
331 flag = ok, reinstreq, hold, hold-reinstreq
332 status = not-installed, unpacked, half-configured,
333 half-installed, config-files, post-inst-failed,
334 removal-failed, installed
336 Some of the above are obsolete (I think?) flag = hold-* and
337 status = post-inst-failed, removal-failed at least.
339 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
340 pkgCache::VerIterator
&Ver
)
344 if (Section
.Find("Status",Start
,Stop
) == false)
347 // UsePackage() is responsible for setting the flag in the default case
348 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
349 if (essential
== true &&
350 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
353 // Isolate the first word
354 const char *I
= Start
;
355 for(; I
< Stop
&& *I
!= ' '; I
++);
356 if (I
>= Stop
|| *I
!= ' ')
357 return _error
->Error("Malformed Status line");
359 // Process the want field
360 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
361 {"install",pkgCache::State::Install
},
362 {"hold",pkgCache::State::Hold
},
363 {"deinstall",pkgCache::State::DeInstall
},
364 {"purge",pkgCache::State::Purge
},
366 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
367 return _error
->Error("Malformed 1st word in the Status line");
369 // Isloate the next word
372 for(; I
< Stop
&& *I
!= ' '; I
++);
373 if (I
>= Stop
|| *I
!= ' ')
374 return _error
->Error("Malformed status line, no 2nd word");
376 // Process the flag field
377 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
378 {"reinstreq",pkgCache::State::ReInstReq
},
379 {"hold",pkgCache::State::HoldInst
},
380 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
382 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
383 return _error
->Error("Malformed 2nd word in the Status line");
385 // Isloate the last word
388 for(; I
< Stop
&& *I
!= ' '; I
++);
390 return _error
->Error("Malformed Status line, no 3rd word");
392 // Process the flag field
393 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
394 {"unpacked",pkgCache::State::UnPacked
},
395 {"half-configured",pkgCache::State::HalfConfigured
},
396 {"installed",pkgCache::State::Installed
},
397 {"half-installed",pkgCache::State::HalfInstalled
},
398 {"config-files",pkgCache::State::ConfigFiles
},
399 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
400 {"triggers-pending",pkgCache::State::TriggersPending
},
401 {"post-inst-failed",pkgCache::State::HalfConfigured
},
402 {"removal-failed",pkgCache::State::HalfInstalled
},
404 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
405 return _error
->Error("Malformed 3rd word in the Status line");
407 /* A Status line marks the package as indicating the current
408 version as well. Only if it is actually installed.. Otherwise
409 the interesting dpkg handling of the status file creates bogus
411 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
412 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
414 if (Ver
.end() == true)
415 _error
->Warning("Encountered status field in a non-version description");
417 Pkg
->CurrentVer
= Ver
.Index();
423 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
425 // Determine the operator
433 Op
= pkgCache::Dep::LessEq
;
440 Op
= pkgCache::Dep::Less
;
444 // < is the same as <= and << is really Cs < for some reason
445 Op
= pkgCache::Dep::LessEq
;
453 Op
= pkgCache::Dep::GreaterEq
;
460 Op
= pkgCache::Dep::Greater
;
464 // > is the same as >= and >> is really Cs > for some reason
465 Op
= pkgCache::Dep::GreaterEq
;
469 Op
= pkgCache::Dep::Equals
;
473 // HACK around bad package definitions
475 Op
= pkgCache::Dep::Equals
;
481 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
482 // ---------------------------------------------------------------------
483 /* This parses the dependency elements out of a standard string in place,
485 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
486 std::string
&Package
,std::string
&Ver
,unsigned int &Op
)
487 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); }
488 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
489 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
490 bool const &ParseArchFlags
)
491 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); }
492 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
493 std::string
&Package
,std::string
&Ver
,unsigned int &Op
,
494 bool const &ParseArchFlags
, bool const &StripMultiArch
)
495 { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); }
496 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
497 string
&Package
,string
&Ver
,
498 unsigned int &Op
, bool const &ParseArchFlags
,
499 bool const &StripMultiArch
,
500 bool const &ParseRestrictionsList
)
502 // Strip off leading space
503 for (;Start
!= Stop
&& isspace(*Start
) != 0; ++Start
);
505 // Parse off the package name
506 const char *I
= Start
;
507 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
508 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']' &&
509 *I
!= '<' && *I
!= '>'; ++I
);
512 if (I
!= Stop
&& *I
== ')')
518 // Stash the package name
519 Package
.assign(Start
,I
- Start
);
521 // We don't want to confuse library users which can't handle MultiArch
522 string
const arch
= _config
->Find("APT::Architecture");
523 if (StripMultiArch
== true) {
524 size_t const found
= Package
.rfind(':');
525 if (found
!= string::npos
&&
526 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
527 strcmp(Package
.c_str() + found
, ":native") == 0 ||
528 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
529 Package
= Package
.substr(0,found
);
532 // Skip white space to the '('
533 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
536 if (I
!= Stop
&& *I
== '(')
539 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
542 I
= ConvertRelation(I
,Op
);
545 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
547 I
= (const char*) memchr(I
, ')', Stop
- I
);
548 if (I
== NULL
|| Start
== I
)
551 // Skip trailing whitespace
553 for (; End
> Start
&& isspace(End
[-1]); End
--);
555 Ver
.assign(Start
,End
-Start
);
561 Op
= pkgCache::Dep::NoOp
;
565 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
567 if (ParseArchFlags
== true)
569 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
571 // Parse an architecture
572 if (I
!= Stop
&& *I
== '[')
576 if (unlikely(I
== Stop
))
581 bool NegArch
= false;
584 // look for whitespace or ending ']'
585 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
587 if (unlikely(End
== Stop
))
596 std::string
arch(I
, End
);
597 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
602 // we found a match, so fast-forward to the end of the wildcards
603 for (; End
!= Stop
&& *End
!= ']'; ++End
);
612 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
619 Package
= ""; /* not for this arch */
623 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
626 if (ParseRestrictionsList
== true)
628 // Parse a restrictions list
629 if (I
!= Stop
&& *I
== '<')
633 if (unlikely(I
== Stop
))
636 std::vector
<string
> const profiles
= APT::Configuration::getBuildProfiles();
640 bool NegRestriction
= false;
643 // look for whitespace or ending '>'
644 for (;End
!= Stop
&& !isspace(*End
) && *End
!= '>'; ++End
);
646 if (unlikely(End
== Stop
))
651 NegRestriction
= true;
655 std::string
restriction(I
, End
);
657 std::string prefix
= "profile.";
658 // only support for "profile" prefix, ignore others
659 if (restriction
.size() > prefix
.size() &&
660 restriction
.substr(0, prefix
.size()) == prefix
)
662 // get the name of the profile
663 restriction
= restriction
.substr(prefix
.size());
665 if (restriction
.empty() == false && profiles
.empty() == false &&
666 std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end())
670 NegRestriction
= false;
671 // we found a match, so fast-forward to the end of the wildcards
672 for (; End
!= Stop
&& *End
!= '>'; ++End
);
682 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
685 if (NegRestriction
== true)
689 Package
= ""; /* not for this restriction */
693 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
696 if (I
!= Stop
&& *I
== '|')
697 Op
|= pkgCache::Dep::Or
;
699 if (I
== Stop
|| *I
== ',' || *I
== '|')
702 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
709 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
710 // ---------------------------------------------------------------------
711 /* This is the higher level depends parser. It takes a tag and generates
712 a complete depends tree for the given version. */
713 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
714 const char *Tag
,unsigned int Type
)
718 if (Section
.Find(Tag
,Start
,Stop
) == false)
721 string
const pkgArch
= Ver
.Arch();
729 Start
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false);
731 return _error
->Error("Problem parsing dependency %s",Tag
);
732 size_t const found
= Package
.rfind(':');
734 // If negative is unspecific it needs to apply on all architectures
735 if (MultiArchEnabled
== true && found
== string::npos
&&
736 (Type
== pkgCache::Dep::Conflicts
||
737 Type
== pkgCache::Dep::DpkgBreaks
||
738 Type
== pkgCache::Dep::Replaces
))
740 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
741 a
!= Architectures
.end(); ++a
)
742 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
744 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
747 else if (MultiArchEnabled
== true && found
!= string::npos
&&
748 strcmp(Package
.c_str() + found
, ":any") != 0)
750 string Arch
= Package
.substr(found
+1, string::npos
);
751 Package
= Package
.substr(0, found
);
752 // Such dependencies are not supposed to be accepted …
753 // … but this is probably the best thing to do.
754 if (Arch
== "native")
755 Arch
= _config
->Find("APT::Architecture");
756 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
761 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
763 if ((Type
== pkgCache::Dep::Conflicts
||
764 Type
== pkgCache::Dep::DpkgBreaks
||
765 Type
== pkgCache::Dep::Replaces
) &&
766 NewDepends(Ver
, Package
,
767 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
768 Version
,Op
,Type
) == false)
777 // ListParser::ParseProvides - Parse the provides list /*{{{*/
778 // ---------------------------------------------------------------------
780 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
784 if (Section
.Find("Provides",Start
,Stop
) == true)
788 string
const Arch
= Ver
.Arch();
793 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
795 return _error
->Error("Problem parsing Provides line");
796 if (Op
!= pkgCache::Dep::NoOp
) {
797 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
798 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
799 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
802 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
811 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
813 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
814 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
816 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
817 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
822 // ListParser::NewProvides - add provides for all architectures /*{{{*/
823 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
824 string
const &Version
) {
825 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
826 a
!= Architectures
.end(); ++a
)
828 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
834 // ListParser::GrabWord - Matches a word and returns /*{{{*/
835 // ---------------------------------------------------------------------
836 /* Looks for a word in a list of words - for ParseStatus */
837 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
839 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
841 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
850 // ListParser::Step - Move to the next section in the file /*{{{*/
851 // ---------------------------------------------------------------------
852 /* This has to be careful to only process the correct architecture */
853 bool debListParser::Step()
855 iOffset
= Tags
.Offset();
856 while (Tags
.Step(Section
) == true)
858 /* See if this is the correct Architecture, if it isn't then we
859 drop the whole section. A missing arch tag only happens (in theory)
860 inside the Status file, so that is a positive return */
861 string
const Architecture
= Section
.FindS("Architecture");
863 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
865 if (APT::Configuration::checkArchitecture(Architecture
) == true)
867 /* parse version stanzas without an architecture only in the status file
868 (and as misfortune bycatch flat-archives) */
869 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
874 if (Architecture
== Arch
)
877 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
881 iOffset
= Tags
.Offset();
886 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
887 // ---------------------------------------------------------------------
889 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
890 FileFd
&File
, string component
)
892 // apt-secure does no longer download individual (per-section) Release
893 // file. to provide Component pinning we use the section name now
894 map_stringitem_t
const storage
= WriteUniqString(component
);
895 FileI
->Component
= storage
;
897 pkgTagFile
TagFile(&File
, File
.Size());
898 pkgTagSection Section
;
899 if (_error
->PendingError() == true || TagFile
.Step(Section
) == false)
903 #define APT_INRELEASE(TAG, STORE) \
904 data = Section.FindS(TAG); \
905 if (data.empty() == false) \
907 map_stringitem_t const storage = WriteUniqString(data); \
910 APT_INRELEASE("Suite", FileI
->Archive
)
911 APT_INRELEASE("Component", FileI
->Component
)
912 APT_INRELEASE("Version", FileI
->Version
)
913 APT_INRELEASE("Origin", FileI
->Origin
)
914 APT_INRELEASE("Codename", FileI
->Codename
)
915 APT_INRELEASE("Label", FileI
->Label
)
917 Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
);
918 Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
);
920 return !_error
->PendingError();
923 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
924 // ---------------------------------------------------------------------
926 unsigned char debListParser::GetPrio(string Str
)
929 if (GrabWord(Str
,PrioList
,Out
) == false)
930 Out
= pkgCache::State::Extra
;
935 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
936 bool debListParser::SameVersion(unsigned short const Hash
, /*{{{*/
937 pkgCache::VerIterator
const &Ver
)
939 if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false)
941 // status file has no (Download)Size, but all others are fair game
942 // status file is parsed last, so the first version we encounter is
943 // probably also the version we have downloaded
944 unsigned long long const Size
= Section
.FindULL("Size");
945 if (Size
!= 0 && Size
!= Ver
->Size
)
947 // available everywhere, but easier to check here than to include in VersionHash
948 unsigned char MultiArch
= ParseMultiArch(false);
949 if (MultiArch
!= Ver
->MultiArch
)
951 // for all practical proposes (we can check): same version
958 debDebFileParser::debDebFileParser(FileFd
*File
, std::string
const &DebFile
)
959 : debListParser(File
, ""), DebFile(DebFile
)
963 bool debDebFileParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
964 pkgCache::VerIterator
&Ver
)
966 bool res
= debListParser::UsePackage(Pkg
, Ver
);
967 // we use the full file path as a provides so that the file is found
969 if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)