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/macros.h>
31 static debListParser::WordList PrioList
[] = {{"important",pkgCache::State::Important
},
32 {"required",pkgCache::State::Required
},
33 {"standard",pkgCache::State::Standard
},
34 {"optional",pkgCache::State::Optional
},
35 {"extra",pkgCache::State::Extra
},
38 // ListParser::debListParser - Constructor /*{{{*/
39 // ---------------------------------------------------------------------
40 /* Provide an architecture and only this one and "all" will be accepted
41 in Step(), if no Architecture is given we will accept every arch
42 we would accept in general with checkArchitecture() */
43 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
46 this->Arch
= _config
->Find("APT::Architecture");
47 Architectures
= APT::Configuration::getArchitectures();
48 MultiArchEnabled
= Architectures
.size() > 1;
51 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
52 // ---------------------------------------------------------------------
54 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
58 if (Section
.Find(Tag
,Start
,Stop
) == false)
60 return WriteUniqString(Start
,Stop
- Start
);
63 // ListParser::Package - Return the package name /*{{{*/
64 // ---------------------------------------------------------------------
65 /* This is to return the name of the package this section describes */
66 string
debListParser::Package() {
67 string
const Result
= Section
.FindS("Package");
68 if(unlikely(Result
.empty() == true))
69 _error
->Error("Encountered a section with no Package: header");
73 // ListParser::Architecture - Return the package arch /*{{{*/
74 // ---------------------------------------------------------------------
75 /* This will return the Architecture of the package this section describes */
76 string
debListParser::Architecture() {
77 return Section
.FindS("Architecture");
80 // ListParser::ArchitectureAll /*{{{*/
81 // ---------------------------------------------------------------------
83 bool debListParser::ArchitectureAll() {
84 return Section
.FindS("Architecture") == "all";
87 // ListParser::Version - Return the version string /*{{{*/
88 // ---------------------------------------------------------------------
89 /* This is to return the string describing the version in debian form,
90 epoch:upstream-release. If this returns the blank string then the
91 entry is assumed to only describe package properties */
92 string
debListParser::Version()
94 return Section
.FindS("Version");
97 // ListParser::NewVersion - Fill in the version structure /*{{{*/
98 // ---------------------------------------------------------------------
100 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
103 Ver
->Section
= UniqFindTagWrite("Section");
106 string
const MultiArch
= Section
.FindS("Multi-Arch");
107 if (MultiArch
.empty() == true)
108 Ver
->MultiArch
= pkgCache::Version::None
;
109 else if (MultiArch
== "same") {
111 if (ArchitectureAll() == true)
113 /* Arch all packages can't be Multi-Arch: same */
114 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
115 Section
.FindS("Package").c_str());
116 Ver
->MultiArch
= pkgCache::Version::None
;
119 Ver
->MultiArch
= pkgCache::Version::Same
;
121 else if (MultiArch
== "foreign")
122 Ver
->MultiArch
= pkgCache::Version::Foreign
;
123 else if (MultiArch
== "allowed")
124 Ver
->MultiArch
= pkgCache::Version::Allowed
;
127 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
128 MultiArch
.c_str(), Section
.FindS("Package").c_str());
129 Ver
->MultiArch
= pkgCache::Version::None
;
132 if (ArchitectureAll() == true)
133 Ver
->MultiArch
|= pkgCache::Version::All
;
136 Ver
->Size
= Section
.FindULL("Size");
137 // Unpacked Size (in K)
138 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
139 Ver
->InstalledSize
*= 1024;
144 if (Section
.Find("Priority",Start
,Stop
) == true)
146 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
147 Ver
->Priority
= pkgCache::State::Extra
;
150 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
152 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
154 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
156 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
158 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
160 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
162 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
164 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
168 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
171 if (ParseProvides(Ver
) == false)
177 // ListParser::Description - Return the description string /*{{{*/
178 // ---------------------------------------------------------------------
179 /* This is to return the string describing the package in debian
180 form. If this returns the blank string then the entry is assumed to
181 only describe package properties */
182 string
debListParser::Description()
184 string
const lang
= DescriptionLanguage();
186 return Section
.FindS("Description");
188 return Section
.FindS(string("Description-").append(lang
).c_str());
191 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
192 // ---------------------------------------------------------------------
193 /* This is to return the string describing the language of
194 description. If this returns the blank string then the entry is
195 assumed to describe original description. */
196 string
debListParser::DescriptionLanguage()
198 if (Section
.FindS("Description").empty() == false)
201 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
202 for (std::vector
<string
>::const_iterator l
= lang
.begin();
203 l
!= lang
.end(); ++l
)
204 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
210 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
211 // ---------------------------------------------------------------------
212 /* This is to return the md5 string to allow the check if it is the right
213 description. If no Description-md5 is found in the section it will be
216 MD5SumValue
debListParser::Description_md5()
218 string
const value
= Section
.FindS("Description-md5");
219 if (value
.empty() == true)
222 md5
.Add((Description() + "\n").c_str());
225 else if (likely(value
.size() == 32))
227 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
228 return MD5SumValue(value
);
229 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
230 return MD5SumValue();
232 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
233 return MD5SumValue();
236 // ListParser::UsePackage - Update a package structure /*{{{*/
237 // ---------------------------------------------------------------------
238 /* This is called to update the package with any new information
239 that might be found in the section */
240 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
241 pkgCache::VerIterator
&Ver
)
243 if (Pkg
->Section
== 0)
244 Pkg
->Section
= UniqFindTagWrite("Section");
246 string
const static myArch
= _config
->Find("APT::Architecture");
247 // Possible values are: "all", "native", "installed" and "none"
248 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
249 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
250 if (essential
== "all" ||
251 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
252 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
254 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
257 if (strcmp(Pkg
.Name(),"apt") == 0)
259 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
261 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
263 Pkg
->Flags
|= pkgCache::Flag::Important
;
266 if (ParseStatus(Pkg
,Ver
) == false)
271 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
272 // ---------------------------------------------------------------------
274 unsigned short debListParser::VersionHash()
276 const char *Sections
[] ={"Installed-Size",
284 unsigned long Result
= INIT_FCS
;
286 for (const char **I
= Sections
; *I
!= 0; I
++)
290 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
293 /* Strip out any spaces from the text, this undoes dpkgs reformatting
294 of certain fields. dpkg also has the rather interesting notion of
295 reformatting depends operators < -> <= */
297 for (; Start
!= End
; Start
++)
299 if (isspace(*Start
) == 0)
300 *J
++ = tolower_ascii(*Start
);
301 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
303 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
307 Result
= AddCRC16(Result
,S
,J
- S
);
313 // ListParser::ParseStatus - Parse the status field /*{{{*/
314 // ---------------------------------------------------------------------
315 /* Status lines are of the form,
316 Status: want flag status
317 want = unknown, install, hold, deinstall, purge
318 flag = ok, reinstreq, hold, hold-reinstreq
319 status = not-installed, unpacked, half-configured,
320 half-installed, config-files, post-inst-failed,
321 removal-failed, installed
323 Some of the above are obsolete (I think?) flag = hold-* and
324 status = post-inst-failed, removal-failed at least.
326 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
327 pkgCache::VerIterator
&Ver
)
331 if (Section
.Find("Status",Start
,Stop
) == false)
334 // UsePackage() is responsible for setting the flag in the default case
335 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
336 if (essential
== true &&
337 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
340 // Isolate the first word
341 const char *I
= Start
;
342 for(; I
< Stop
&& *I
!= ' '; I
++);
343 if (I
>= Stop
|| *I
!= ' ')
344 return _error
->Error("Malformed Status line");
346 // Process the want field
347 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
348 {"install",pkgCache::State::Install
},
349 {"hold",pkgCache::State::Hold
},
350 {"deinstall",pkgCache::State::DeInstall
},
351 {"purge",pkgCache::State::Purge
},
353 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
354 return _error
->Error("Malformed 1st word in the Status line");
356 // Isloate the next word
359 for(; I
< Stop
&& *I
!= ' '; I
++);
360 if (I
>= Stop
|| *I
!= ' ')
361 return _error
->Error("Malformed status line, no 2nd word");
363 // Process the flag field
364 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
365 {"reinstreq",pkgCache::State::ReInstReq
},
366 {"hold",pkgCache::State::HoldInst
},
367 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
369 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
370 return _error
->Error("Malformed 2nd word in the Status line");
372 // Isloate the last word
375 for(; I
< Stop
&& *I
!= ' '; I
++);
377 return _error
->Error("Malformed Status line, no 3rd word");
379 // Process the flag field
380 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
381 {"unpacked",pkgCache::State::UnPacked
},
382 {"half-configured",pkgCache::State::HalfConfigured
},
383 {"installed",pkgCache::State::Installed
},
384 {"half-installed",pkgCache::State::HalfInstalled
},
385 {"config-files",pkgCache::State::ConfigFiles
},
386 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
387 {"triggers-pending",pkgCache::State::TriggersPending
},
388 {"post-inst-failed",pkgCache::State::HalfConfigured
},
389 {"removal-failed",pkgCache::State::HalfInstalled
},
391 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
392 return _error
->Error("Malformed 3rd word in the Status line");
394 /* A Status line marks the package as indicating the current
395 version as well. Only if it is actually installed.. Otherwise
396 the interesting dpkg handling of the status file creates bogus
398 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
399 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
401 if (Ver
.end() == true)
402 _error
->Warning("Encountered status field in a non-version description");
404 Pkg
->CurrentVer
= Ver
.Index();
410 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
412 // Determine the operator
420 Op
= pkgCache::Dep::LessEq
;
427 Op
= pkgCache::Dep::Less
;
431 // < is the same as <= and << is really Cs < for some reason
432 Op
= pkgCache::Dep::LessEq
;
440 Op
= pkgCache::Dep::GreaterEq
;
447 Op
= pkgCache::Dep::Greater
;
451 // > is the same as >= and >> is really Cs > for some reason
452 Op
= pkgCache::Dep::GreaterEq
;
456 Op
= pkgCache::Dep::Equals
;
460 // HACK around bad package definitions
462 Op
= pkgCache::Dep::Equals
;
468 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
469 // ---------------------------------------------------------------------
470 /* This parses the dependency elements out of a standard string in place,
472 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
473 string
&Package
,string
&Ver
,
474 unsigned int &Op
, bool const &ParseArchFlags
,
475 bool const &StripMultiArch
)
477 // Strip off leading space
478 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
480 // Parse off the package name
481 const char *I
= Start
;
482 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
483 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']'; I
++);
486 if (I
!= Stop
&& *I
== ')')
492 // Stash the package name
493 Package
.assign(Start
,I
- Start
);
495 // We don't want to confuse library users which can't handle MultiArch
496 string
const arch
= _config
->Find("APT::Architecture");
497 if (StripMultiArch
== true) {
498 size_t const found
= Package
.rfind(':');
499 if (found
!= string::npos
&&
500 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
501 strcmp(Package
.c_str() + found
, ":native") == 0 ||
502 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
503 Package
= Package
.substr(0,found
);
506 // Skip white space to the '('
507 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
510 if (I
!= Stop
&& *I
== '(')
513 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
516 I
= ConvertRelation(I
,Op
);
519 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
521 I
= (const char*) memchr(I
, ')', Stop
- I
);
522 if (I
== NULL
|| Start
== I
)
525 // Skip trailing whitespace
527 for (; End
> Start
&& isspace(End
[-1]); End
--);
529 Ver
.assign(Start
,End
-Start
);
535 Op
= pkgCache::Dep::NoOp
;
539 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
541 if (ParseArchFlags
== true)
543 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
545 // Parse an architecture
546 if (I
!= Stop
&& *I
== '[')
550 if (unlikely(I
== Stop
))
555 bool NegArch
= false;
558 // look for whitespace or ending ']'
559 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
561 if (unlikely(End
== Stop
))
570 std::string
arch(I
, End
);
571 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
576 // we found a match, so fast-forward to the end of the wildcards
577 for (; End
!= Stop
&& *End
!= ']'; ++End
);
586 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
593 Package
= ""; /* not for this arch */
597 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
600 if (I
!= Stop
&& *I
== '|')
601 Op
|= pkgCache::Dep::Or
;
603 if (I
== Stop
|| *I
== ',' || *I
== '|')
606 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
613 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
614 // ---------------------------------------------------------------------
615 /* This is the higher level depends parser. It takes a tag and generates
616 a complete depends tree for the given version. */
617 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
618 const char *Tag
,unsigned int Type
)
622 if (Section
.Find(Tag
,Start
,Stop
) == false)
625 string
const pkgArch
= Ver
.Arch();
633 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
);
635 return _error
->Error("Problem parsing dependency %s",Tag
);
636 size_t const found
= Package
.rfind(':');
638 // If negative is unspecific it needs to apply on all architectures
639 if (MultiArchEnabled
== true && found
== string::npos
&&
640 (Type
== pkgCache::Dep::Conflicts
||
641 Type
== pkgCache::Dep::DpkgBreaks
||
642 Type
== pkgCache::Dep::Replaces
))
644 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
645 a
!= Architectures
.end(); ++a
)
646 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
648 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
651 else if (MultiArchEnabled
== true && found
!= string::npos
&&
652 strcmp(Package
.c_str() + found
, ":any") != 0)
654 string Arch
= Package
.substr(found
+1, string::npos
);
655 Package
= Package
.substr(0, found
);
656 // Such dependencies are not supposed to be accepted …
657 // … but this is probably the best thing to do.
658 if (Arch
== "native")
659 Arch
= _config
->Find("APT::Architecture");
660 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
665 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
667 if ((Type
== pkgCache::Dep::Conflicts
||
668 Type
== pkgCache::Dep::DpkgBreaks
||
669 Type
== pkgCache::Dep::Replaces
) &&
670 NewDepends(Ver
, Package
,
671 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
672 Version
,Op
,Type
) == false)
681 // ListParser::ParseProvides - Parse the provides list /*{{{*/
682 // ---------------------------------------------------------------------
684 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
688 if (Section
.Find("Provides",Start
,Stop
) == true)
692 string
const Arch
= Ver
.Arch();
697 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
699 return _error
->Error("Problem parsing Provides line");
700 if (Op
!= pkgCache::Dep::NoOp
) {
701 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
702 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
703 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
706 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
715 if (MultiArchEnabled
== false)
717 else if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
719 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
720 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
722 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
723 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
728 // ListParser::NewProvides - add provides for all architectures /*{{{*/
729 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
730 string
const &Version
) {
731 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
732 a
!= Architectures
.end(); ++a
)
734 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
740 // ListParser::GrabWord - Matches a word and returns /*{{{*/
741 // ---------------------------------------------------------------------
742 /* Looks for a word in a list of words - for ParseStatus */
743 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
745 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
747 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
756 // ListParser::Step - Move to the next section in the file /*{{{*/
757 // ---------------------------------------------------------------------
758 /* This has to be carefull to only process the correct architecture */
759 bool debListParser::Step()
761 iOffset
= Tags
.Offset();
762 while (Tags
.Step(Section
) == true)
764 /* See if this is the correct Architecture, if it isn't then we
765 drop the whole section. A missing arch tag only happens (in theory)
766 inside the Status file, so that is a positive return */
767 string
const Architecture
= Section
.FindS("Architecture");
769 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
771 if (APT::Configuration::checkArchitecture(Architecture
) == true)
773 /* parse version stanzas without an architecture only in the status file
774 (and as misfortune bycatch flat-archives) */
775 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
780 if (Architecture
== Arch
)
783 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
787 iOffset
= Tags
.Offset();
792 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
793 // ---------------------------------------------------------------------
795 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
796 FileFd
&File
, string component
)
798 // apt-secure does no longer download individual (per-section) Release
799 // file. to provide Component pinning we use the section name now
800 map_ptrloc
const storage
= WriteUniqString(component
);
801 FileI
->Component
= storage
;
803 // FIXME: Code depends on the fact that Release files aren't compressed
804 FILE* release
= fdopen(dup(File
.Fd()), "r");
809 bool gpgClose
= false;
810 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
815 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
)
818 if (buffer
[len
] == '\0')
821 // only evalute the first GPG section
822 if (strncmp("-----", buffer
, 5) == 0)
824 if (gpgClose
== true)
830 // seperate the tag from the data
831 const char* dataStart
= strchr(buffer
+ len
, ':');
832 if (dataStart
== NULL
)
834 len
= dataStart
- buffer
;
835 for (++dataStart
; *dataStart
== ' '; ++dataStart
)
838 const char* dataEnd
= (const char*)rawmemchr(dataStart
, '\0');
839 // The last char should be a newline, but we can never be sure: #633350
840 const char* lineEnd
= dataEnd
;
841 for (--lineEnd
; *lineEnd
== '\r' || *lineEnd
== '\n'; --lineEnd
)
846 // which datastorage need to be updated
847 enum { Suite
, Component
, Version
, Origin
, Codename
, Label
, None
} writeTo
= None
;
848 if (buffer
[0] == ' ')
850 #define APT_PARSER_WRITETO(X) else if (strncmp(#X, buffer, len) == 0) writeTo = X;
851 APT_PARSER_WRITETO(Suite
)
852 APT_PARSER_WRITETO(Component
)
853 APT_PARSER_WRITETO(Version
)
854 APT_PARSER_WRITETO(Origin
)
855 APT_PARSER_WRITETO(Codename
)
856 APT_PARSER_WRITETO(Label
)
857 #undef APT_PARSER_WRITETO
858 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
859 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd);
860 APT_PARSER_FLAGIT(NotAutomatic
)
861 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
862 #undef APT_PARSER_FLAGIT
864 // load all data from the line and save it
867 data
.append(dataStart
, dataEnd
);
868 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
870 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
874 if (strlen(buffer
) != sizeof(buffer
) - 1)
880 // remove spaces and stuff from the end of the data line
881 for (std::string::reverse_iterator s
= data
.rbegin();
882 s
!= data
.rend(); ++s
)
884 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
888 map_ptrloc
const storage
= WriteUniqString(data
);
890 case Suite
: FileI
->Archive
= storage
; break;
891 case Component
: FileI
->Component
= storage
; break;
892 case Version
: FileI
->Version
= storage
; break;
893 case Origin
: FileI
->Origin
= storage
; break;
894 case Codename
: FileI
->Codename
= storage
; break;
895 case Label
: FileI
->Label
= storage
; break;
902 return !_error
->PendingError();
905 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
906 // ---------------------------------------------------------------------
908 unsigned char debListParser::GetPrio(string Str
)
911 if (GrabWord(Str
,PrioList
,Out
) == false)
912 Out
= pkgCache::State::Extra
;