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
[] = {
32 {"required",pkgCache::State::Required
},
33 {"important",pkgCache::State::Important
},
34 {"standard",pkgCache::State::Standard
},
35 {"optional",pkgCache::State::Optional
},
36 {"extra",pkgCache::State::Extra
},
39 // ListParser::debListParser - Constructor /*{{{*/
40 // ---------------------------------------------------------------------
41 /* Provide an architecture and only this one and "all" will be accepted
42 in Step(), if no Architecture is given we will accept every arch
43 we would accept in general with checkArchitecture() */
44 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
47 this->Arch
= _config
->Find("APT::Architecture");
48 Architectures
= APT::Configuration::getArchitectures();
49 MultiArchEnabled
= Architectures
.size() > 1;
52 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
53 // ---------------------------------------------------------------------
55 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
59 if (Section
.Find(Tag
,Start
,Stop
) == false)
61 return WriteUniqString(Start
,Stop
- Start
);
64 // ListParser::Package - Return the package name /*{{{*/
65 // ---------------------------------------------------------------------
66 /* This is to return the name of the package this section describes */
67 string
debListParser::Package() {
68 string
const Result
= Section
.FindS("Package");
69 if(unlikely(Result
.empty() == true))
70 _error
->Error("Encountered a section with no Package: header");
74 // ListParser::Architecture - Return the package arch /*{{{*/
75 // ---------------------------------------------------------------------
76 /* This will return the Architecture of the package this section describes */
77 string
debListParser::Architecture() {
78 return Section
.FindS("Architecture");
81 // ListParser::ArchitectureAll /*{{{*/
82 // ---------------------------------------------------------------------
84 bool debListParser::ArchitectureAll() {
85 return Section
.FindS("Architecture") == "all";
88 // ListParser::Version - Return the version string /*{{{*/
89 // ---------------------------------------------------------------------
90 /* This is to return the string describing the version in debian form,
91 epoch:upstream-release. If this returns the blank string then the
92 entry is assumed to only describe package properties */
93 string
debListParser::Version()
95 return Section
.FindS("Version");
98 // ListParser::NewVersion - Fill in the version structure /*{{{*/
99 // ---------------------------------------------------------------------
101 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
104 Ver
->Section
= UniqFindTagWrite("Section");
107 string
const MultiArch
= Section
.FindS("Multi-Arch");
108 if (MultiArch
.empty() == true)
109 Ver
->MultiArch
= pkgCache::Version::None
;
110 else if (MultiArch
== "same") {
112 if (ArchitectureAll() == true)
114 /* Arch all packages can't be Multi-Arch: same */
115 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
116 Section
.FindS("Package").c_str());
117 Ver
->MultiArch
= pkgCache::Version::None
;
120 Ver
->MultiArch
= pkgCache::Version::Same
;
122 else if (MultiArch
== "foreign")
123 Ver
->MultiArch
= pkgCache::Version::Foreign
;
124 else if (MultiArch
== "allowed")
125 Ver
->MultiArch
= pkgCache::Version::Allowed
;
128 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
129 MultiArch
.c_str(), Section
.FindS("Package").c_str());
130 Ver
->MultiArch
= pkgCache::Version::None
;
133 if (ArchitectureAll() == true)
134 Ver
->MultiArch
|= pkgCache::Version::All
;
137 Ver
->Size
= Section
.FindULL("Size");
138 // Unpacked Size (in K)
139 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
140 Ver
->InstalledSize
*= 1024;
145 if (Section
.Find("Priority",Start
,Stop
) == true)
147 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
148 Ver
->Priority
= pkgCache::State::Extra
;
151 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
153 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
155 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
157 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
159 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
161 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
163 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
165 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
169 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
172 if (ParseProvides(Ver
) == false)
178 // ListParser::Description - Return the description string /*{{{*/
179 // ---------------------------------------------------------------------
180 /* This is to return the string describing the package in debian
181 form. If this returns the blank string then the entry is assumed to
182 only describe package properties */
183 string
debListParser::Description()
185 string
const lang
= DescriptionLanguage();
187 return Section
.FindS("Description");
189 return Section
.FindS(string("Description-").append(lang
).c_str());
192 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
193 // ---------------------------------------------------------------------
194 /* This is to return the string describing the language of
195 description. If this returns the blank string then the entry is
196 assumed to describe original description. */
197 string
debListParser::DescriptionLanguage()
199 if (Section
.FindS("Description").empty() == false)
202 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
203 for (std::vector
<string
>::const_iterator l
= lang
.begin();
204 l
!= lang
.end(); ++l
)
205 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
211 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
212 // ---------------------------------------------------------------------
213 /* This is to return the md5 string to allow the check if it is the right
214 description. If no Description-md5 is found in the section it will be
217 MD5SumValue
debListParser::Description_md5()
219 string
const value
= Section
.FindS("Description-md5");
220 if (value
.empty() == true)
223 md5
.Add((Description() + "\n").c_str());
226 else if (likely(value
.size() == 32))
228 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
229 return MD5SumValue(value
);
230 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
231 return MD5SumValue();
233 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
234 return MD5SumValue();
237 // ListParser::UsePackage - Update a package structure /*{{{*/
238 // ---------------------------------------------------------------------
239 /* This is called to update the package with any new information
240 that might be found in the section */
241 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
242 pkgCache::VerIterator
&Ver
)
244 if (Pkg
->Section
== 0)
245 Pkg
->Section
= UniqFindTagWrite("Section");
247 string
const static myArch
= _config
->Find("APT::Architecture");
248 // Possible values are: "all", "native", "installed" and "none"
249 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
250 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
251 if (essential
== "all" ||
252 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
253 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
255 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
258 if (strcmp(Pkg
.Name(),"apt") == 0)
260 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
262 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
264 Pkg
->Flags
|= pkgCache::Flag::Important
;
267 if (ParseStatus(Pkg
,Ver
) == false)
272 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
273 // ---------------------------------------------------------------------
275 unsigned short debListParser::VersionHash()
277 const char *Sections
[] ={"Installed-Size",
285 unsigned long Result
= INIT_FCS
;
287 for (const char **I
= Sections
; *I
!= 0; I
++)
291 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
294 /* Strip out any spaces from the text, this undoes dpkgs reformatting
295 of certain fields. dpkg also has the rather interesting notion of
296 reformatting depends operators < -> <= */
298 for (; Start
!= End
; Start
++)
300 if (isspace(*Start
) == 0)
301 *J
++ = tolower_ascii(*Start
);
302 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
304 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
308 Result
= AddCRC16(Result
,S
,J
- S
);
314 // ListParser::ParseStatus - Parse the status field /*{{{*/
315 // ---------------------------------------------------------------------
316 /* Status lines are of the form,
317 Status: want flag status
318 want = unknown, install, hold, deinstall, purge
319 flag = ok, reinstreq, hold, hold-reinstreq
320 status = not-installed, unpacked, half-configured,
321 half-installed, config-files, post-inst-failed,
322 removal-failed, installed
324 Some of the above are obsolete (I think?) flag = hold-* and
325 status = post-inst-failed, removal-failed at least.
327 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
328 pkgCache::VerIterator
&Ver
)
332 if (Section
.Find("Status",Start
,Stop
) == false)
335 // UsePackage() is responsible for setting the flag in the default case
336 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
337 if (essential
== true &&
338 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
341 // Isolate the first word
342 const char *I
= Start
;
343 for(; I
< Stop
&& *I
!= ' '; I
++);
344 if (I
>= Stop
|| *I
!= ' ')
345 return _error
->Error("Malformed Status line");
347 // Process the want field
348 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
349 {"install",pkgCache::State::Install
},
350 {"hold",pkgCache::State::Hold
},
351 {"deinstall",pkgCache::State::DeInstall
},
352 {"purge",pkgCache::State::Purge
},
354 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
355 return _error
->Error("Malformed 1st word in the Status line");
357 // Isloate the next word
360 for(; I
< Stop
&& *I
!= ' '; I
++);
361 if (I
>= Stop
|| *I
!= ' ')
362 return _error
->Error("Malformed status line, no 2nd word");
364 // Process the flag field
365 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
366 {"reinstreq",pkgCache::State::ReInstReq
},
367 {"hold",pkgCache::State::HoldInst
},
368 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
370 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
371 return _error
->Error("Malformed 2nd word in the Status line");
373 // Isloate the last word
376 for(; I
< Stop
&& *I
!= ' '; I
++);
378 return _error
->Error("Malformed Status line, no 3rd word");
380 // Process the flag field
381 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
382 {"unpacked",pkgCache::State::UnPacked
},
383 {"half-configured",pkgCache::State::HalfConfigured
},
384 {"installed",pkgCache::State::Installed
},
385 {"half-installed",pkgCache::State::HalfInstalled
},
386 {"config-files",pkgCache::State::ConfigFiles
},
387 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
388 {"triggers-pending",pkgCache::State::TriggersPending
},
389 {"post-inst-failed",pkgCache::State::HalfConfigured
},
390 {"removal-failed",pkgCache::State::HalfInstalled
},
392 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
393 return _error
->Error("Malformed 3rd word in the Status line");
395 /* A Status line marks the package as indicating the current
396 version as well. Only if it is actually installed.. Otherwise
397 the interesting dpkg handling of the status file creates bogus
399 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
400 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
402 if (Ver
.end() == true)
403 _error
->Warning("Encountered status field in a non-version description");
405 Pkg
->CurrentVer
= Ver
.Index();
411 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
413 // Determine the operator
421 Op
= pkgCache::Dep::LessEq
;
428 Op
= pkgCache::Dep::Less
;
432 // < is the same as <= and << is really Cs < for some reason
433 Op
= pkgCache::Dep::LessEq
;
441 Op
= pkgCache::Dep::GreaterEq
;
448 Op
= pkgCache::Dep::Greater
;
452 // > is the same as >= and >> is really Cs > for some reason
453 Op
= pkgCache::Dep::GreaterEq
;
457 Op
= pkgCache::Dep::Equals
;
461 // HACK around bad package definitions
463 Op
= pkgCache::Dep::Equals
;
469 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
470 // ---------------------------------------------------------------------
471 /* This parses the dependency elements out of a standard string in place,
473 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
474 string
&Package
,string
&Ver
,
475 unsigned int &Op
, bool const &ParseArchFlags
,
476 bool const &StripMultiArch
)
478 // Strip off leading space
479 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
481 // Parse off the package name
482 const char *I
= Start
;
483 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
484 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']'; I
++);
487 if (I
!= Stop
&& *I
== ')')
493 // Stash the package name
494 Package
.assign(Start
,I
- Start
);
496 // We don't want to confuse library users which can't handle MultiArch
497 string
const arch
= _config
->Find("APT::Architecture");
498 if (StripMultiArch
== true) {
499 size_t const found
= Package
.rfind(':');
500 if (found
!= string::npos
&&
501 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
502 strcmp(Package
.c_str() + found
, ":native") == 0 ||
503 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
504 Package
= Package
.substr(0,found
);
507 // Skip white space to the '('
508 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
511 if (I
!= Stop
&& *I
== '(')
514 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
517 I
= ConvertRelation(I
,Op
);
520 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
522 I
= (const char*) memchr(I
, ')', Stop
- I
);
523 if (I
== NULL
|| Start
== I
)
526 // Skip trailing whitespace
528 for (; End
> Start
&& isspace(End
[-1]); End
--);
530 Ver
.assign(Start
,End
-Start
);
536 Op
= pkgCache::Dep::NoOp
;
540 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
542 if (ParseArchFlags
== true)
544 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
546 // Parse an architecture
547 if (I
!= Stop
&& *I
== '[')
551 if (unlikely(I
== Stop
))
556 bool NegArch
= false;
559 // look for whitespace or ending ']'
560 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
562 if (unlikely(End
== Stop
))
571 std::string
arch(I
, End
);
572 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
577 // we found a match, so fast-forward to the end of the wildcards
578 for (; End
!= Stop
&& *End
!= ']'; ++End
);
587 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
594 Package
= ""; /* not for this arch */
598 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
601 if (I
!= Stop
&& *I
== '|')
602 Op
|= pkgCache::Dep::Or
;
604 if (I
== Stop
|| *I
== ',' || *I
== '|')
607 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
614 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
615 // ---------------------------------------------------------------------
616 /* This is the higher level depends parser. It takes a tag and generates
617 a complete depends tree for the given version. */
618 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
619 const char *Tag
,unsigned int Type
)
623 if (Section
.Find(Tag
,Start
,Stop
) == false)
626 string
const pkgArch
= Ver
.Arch();
634 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
);
636 return _error
->Error("Problem parsing dependency %s",Tag
);
637 size_t const found
= Package
.rfind(':');
639 // If negative is unspecific it needs to apply on all architectures
640 if (MultiArchEnabled
== true && found
== string::npos
&&
641 (Type
== pkgCache::Dep::Conflicts
||
642 Type
== pkgCache::Dep::DpkgBreaks
||
643 Type
== pkgCache::Dep::Replaces
))
645 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
646 a
!= Architectures
.end(); ++a
)
647 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
649 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
652 else if (MultiArchEnabled
== true && found
!= string::npos
&&
653 strcmp(Package
.c_str() + found
, ":any") != 0)
655 string Arch
= Package
.substr(found
+1, string::npos
);
656 Package
= Package
.substr(0, found
);
657 // Such dependencies are not supposed to be accepted …
658 // … but this is probably the best thing to do.
659 if (Arch
== "native")
660 Arch
= _config
->Find("APT::Architecture");
661 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
666 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
668 if ((Type
== pkgCache::Dep::Conflicts
||
669 Type
== pkgCache::Dep::DpkgBreaks
||
670 Type
== pkgCache::Dep::Replaces
) &&
671 NewDepends(Ver
, Package
,
672 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
673 Version
,Op
,Type
) == false)
682 // ListParser::ParseProvides - Parse the provides list /*{{{*/
683 // ---------------------------------------------------------------------
685 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
689 if (Section
.Find("Provides",Start
,Stop
) == true)
693 string
const Arch
= Ver
.Arch();
698 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
700 return _error
->Error("Problem parsing Provides line");
701 if (Op
!= pkgCache::Dep::NoOp
) {
702 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
703 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
704 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
707 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
716 if (MultiArchEnabled
== false)
718 else if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
720 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
721 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
723 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
724 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
729 // ListParser::NewProvides - add provides for all architectures /*{{{*/
730 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
731 string
const &Version
) {
732 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
733 a
!= Architectures
.end(); ++a
)
735 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
741 // ListParser::GrabWord - Matches a word and returns /*{{{*/
742 // ---------------------------------------------------------------------
743 /* Looks for a word in a list of words - for ParseStatus */
744 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
746 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
748 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
757 // ListParser::Step - Move to the next section in the file /*{{{*/
758 // ---------------------------------------------------------------------
759 /* This has to be carefull to only process the correct architecture */
760 bool debListParser::Step()
762 iOffset
= Tags
.Offset();
763 while (Tags
.Step(Section
) == true)
765 /* See if this is the correct Architecture, if it isn't then we
766 drop the whole section. A missing arch tag only happens (in theory)
767 inside the Status file, so that is a positive return */
768 string
const Architecture
= Section
.FindS("Architecture");
770 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
772 if (APT::Configuration::checkArchitecture(Architecture
) == true)
774 /* parse version stanzas without an architecture only in the status file
775 (and as misfortune bycatch flat-archives) */
776 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
781 if (Architecture
== Arch
)
784 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
788 iOffset
= Tags
.Offset();
793 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
794 // ---------------------------------------------------------------------
796 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
797 FileFd
&File
, string component
)
799 // apt-secure does no longer download individual (per-section) Release
800 // file. to provide Component pinning we use the section name now
801 map_ptrloc
const storage
= WriteUniqString(component
);
802 FileI
->Component
= storage
;
804 // FIXME: should use FileFd and TagSection
805 FILE* release
= fdopen(dup(File
.Fd()), "r");
810 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
815 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
)
818 if (buffer
[len
] == '\0')
821 // seperate the tag from the data
822 const char* dataStart
= strchr(buffer
+ len
, ':');
823 if (dataStart
== NULL
)
825 len
= dataStart
- buffer
;
826 for (++dataStart
; *dataStart
== ' '; ++dataStart
)
829 const char* dataEnd
= (const char*)rawmemchr(dataStart
, '\0');
830 // The last char should be a newline, but we can never be sure: #633350
831 const char* lineEnd
= dataEnd
;
832 for (--lineEnd
; *lineEnd
== '\r' || *lineEnd
== '\n'; --lineEnd
)
837 // which datastorage need to be updated
838 enum { Suite
, Component
, Version
, Origin
, Codename
, Label
, None
} writeTo
= None
;
839 if (buffer
[0] == ' ')
841 #define APT_PARSER_WRITETO(X) else if (strncmp(#X, buffer, len) == 0) writeTo = X;
842 APT_PARSER_WRITETO(Suite
)
843 APT_PARSER_WRITETO(Component
)
844 APT_PARSER_WRITETO(Version
)
845 APT_PARSER_WRITETO(Origin
)
846 APT_PARSER_WRITETO(Codename
)
847 APT_PARSER_WRITETO(Label
)
848 #undef APT_PARSER_WRITETO
849 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
850 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd);
851 APT_PARSER_FLAGIT(NotAutomatic
)
852 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
853 #undef APT_PARSER_FLAGIT
855 // load all data from the line and save it
858 data
.append(dataStart
, dataEnd
);
859 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
861 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
865 if (strlen(buffer
) != sizeof(buffer
) - 1)
871 // remove spaces and stuff from the end of the data line
872 for (std::string::reverse_iterator s
= data
.rbegin();
873 s
!= data
.rend(); ++s
)
875 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
879 map_ptrloc
const storage
= WriteUniqString(data
);
881 case Suite
: FileI
->Archive
= storage
; break;
882 case Component
: FileI
->Component
= storage
; break;
883 case Version
: FileI
->Version
= storage
; break;
884 case Origin
: FileI
->Origin
= storage
; break;
885 case Codename
: FileI
->Codename
= storage
; break;
886 case Label
: FileI
->Label
= storage
; break;
893 return !_error
->PendingError();
896 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
897 // ---------------------------------------------------------------------
899 unsigned char debListParser::GetPrio(string Str
)
902 if (GrabWord(Str
,PrioList
,Out
) == false)
903 Out
= pkgCache::State::Extra
;