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)
222 std::string
const desc
= Description() + "\n";
224 return MD5SumValue();
227 md5
.Add(desc
.c_str());
230 else if (likely(value
.size() == 32))
232 if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
))
233 return MD5SumValue(value
);
234 _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str());
235 return MD5SumValue();
237 _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str());
238 return MD5SumValue();
241 // ListParser::UsePackage - Update a package structure /*{{{*/
242 // ---------------------------------------------------------------------
243 /* This is called to update the package with any new information
244 that might be found in the section */
245 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
246 pkgCache::VerIterator
&Ver
)
248 if (Pkg
->Section
== 0)
249 Pkg
->Section
= UniqFindTagWrite("Section");
251 string
const static myArch
= _config
->Find("APT::Architecture");
252 // Possible values are: "all", "native", "installed" and "none"
253 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
254 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "all");
255 if (essential
== "all" ||
256 (essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()))
257 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
259 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
262 if (strcmp(Pkg
.Name(),"apt") == 0)
264 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
266 Pkg
->Flags
|= pkgCache::Flag::Essential
| pkgCache::Flag::Important
;
268 Pkg
->Flags
|= pkgCache::Flag::Important
;
271 if (ParseStatus(Pkg
,Ver
) == false)
276 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
277 // ---------------------------------------------------------------------
279 unsigned short debListParser::VersionHash()
281 const char *Sections
[] ={"Installed-Size",
289 unsigned long Result
= INIT_FCS
;
291 for (const char * const *I
= Sections
; *I
!= 0; ++I
)
295 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
298 /* Strip out any spaces from the text, this undoes dpkgs reformatting
299 of certain fields. dpkg also has the rather interesting notion of
300 reformatting depends operators < -> <= */
302 for (; Start
!= End
; ++Start
)
304 if (isspace(*Start
) != 0)
306 *J
++ = tolower_ascii(*Start
);
308 if ((*Start
== '<' || *Start
== '>') && Start
[1] != *Start
&& Start
[1] != '=')
312 Result
= AddCRC16(Result
,S
,J
- S
);
318 // ListParser::ParseStatus - Parse the status field /*{{{*/
319 // ---------------------------------------------------------------------
320 /* Status lines are of the form,
321 Status: want flag status
322 want = unknown, install, hold, deinstall, purge
323 flag = ok, reinstreq, hold, hold-reinstreq
324 status = not-installed, unpacked, half-configured,
325 half-installed, config-files, post-inst-failed,
326 removal-failed, installed
328 Some of the above are obsolete (I think?) flag = hold-* and
329 status = post-inst-failed, removal-failed at least.
331 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
332 pkgCache::VerIterator
&Ver
)
336 if (Section
.Find("Status",Start
,Stop
) == false)
339 // UsePackage() is responsible for setting the flag in the default case
340 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
341 if (essential
== true &&
342 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
345 // Isolate the first word
346 const char *I
= Start
;
347 for(; I
< Stop
&& *I
!= ' '; I
++);
348 if (I
>= Stop
|| *I
!= ' ')
349 return _error
->Error("Malformed Status line");
351 // Process the want field
352 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
353 {"install",pkgCache::State::Install
},
354 {"hold",pkgCache::State::Hold
},
355 {"deinstall",pkgCache::State::DeInstall
},
356 {"purge",pkgCache::State::Purge
},
358 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
359 return _error
->Error("Malformed 1st word in the Status line");
361 // Isloate the next word
364 for(; I
< Stop
&& *I
!= ' '; I
++);
365 if (I
>= Stop
|| *I
!= ' ')
366 return _error
->Error("Malformed status line, no 2nd word");
368 // Process the flag field
369 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
370 {"reinstreq",pkgCache::State::ReInstReq
},
371 {"hold",pkgCache::State::HoldInst
},
372 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
374 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
375 return _error
->Error("Malformed 2nd word in the Status line");
377 // Isloate the last word
380 for(; I
< Stop
&& *I
!= ' '; I
++);
382 return _error
->Error("Malformed Status line, no 3rd word");
384 // Process the flag field
385 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
386 {"unpacked",pkgCache::State::UnPacked
},
387 {"half-configured",pkgCache::State::HalfConfigured
},
388 {"installed",pkgCache::State::Installed
},
389 {"half-installed",pkgCache::State::HalfInstalled
},
390 {"config-files",pkgCache::State::ConfigFiles
},
391 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
392 {"triggers-pending",pkgCache::State::TriggersPending
},
393 {"post-inst-failed",pkgCache::State::HalfConfigured
},
394 {"removal-failed",pkgCache::State::HalfInstalled
},
396 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
397 return _error
->Error("Malformed 3rd word in the Status line");
399 /* A Status line marks the package as indicating the current
400 version as well. Only if it is actually installed.. Otherwise
401 the interesting dpkg handling of the status file creates bogus
403 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
404 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
406 if (Ver
.end() == true)
407 _error
->Warning("Encountered status field in a non-version description");
409 Pkg
->CurrentVer
= Ver
.Index();
415 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
417 // Determine the operator
425 Op
= pkgCache::Dep::LessEq
;
432 Op
= pkgCache::Dep::Less
;
436 // < is the same as <= and << is really Cs < for some reason
437 Op
= pkgCache::Dep::LessEq
;
445 Op
= pkgCache::Dep::GreaterEq
;
452 Op
= pkgCache::Dep::Greater
;
456 // > is the same as >= and >> is really Cs > for some reason
457 Op
= pkgCache::Dep::GreaterEq
;
461 Op
= pkgCache::Dep::Equals
;
465 // HACK around bad package definitions
467 Op
= pkgCache::Dep::Equals
;
473 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
474 // ---------------------------------------------------------------------
475 /* This parses the dependency elements out of a standard string in place,
477 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
478 string
&Package
,string
&Ver
,
479 unsigned int &Op
, bool const &ParseArchFlags
,
480 bool const &StripMultiArch
)
482 // Strip off leading space
483 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
485 // Parse off the package name
486 const char *I
= Start
;
487 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
488 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']'; I
++);
491 if (I
!= Stop
&& *I
== ')')
497 // Stash the package name
498 Package
.assign(Start
,I
- Start
);
500 // We don't want to confuse library users which can't handle MultiArch
501 string
const arch
= _config
->Find("APT::Architecture");
502 if (StripMultiArch
== true) {
503 size_t const found
= Package
.rfind(':');
504 if (found
!= string::npos
&&
505 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
506 strcmp(Package
.c_str() + found
, ":native") == 0 ||
507 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
508 Package
= Package
.substr(0,found
);
511 // Skip white space to the '('
512 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
515 if (I
!= Stop
&& *I
== '(')
518 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
521 I
= ConvertRelation(I
,Op
);
524 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
526 I
= (const char*) memchr(I
, ')', Stop
- I
);
527 if (I
== NULL
|| Start
== I
)
530 // Skip trailing whitespace
532 for (; End
> Start
&& isspace(End
[-1]); End
--);
534 Ver
.assign(Start
,End
-Start
);
540 Op
= pkgCache::Dep::NoOp
;
544 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
546 if (ParseArchFlags
== true)
548 APT::CacheFilter::PackageArchitectureMatchesSpecification
matchesArch(arch
, false);
550 // Parse an architecture
551 if (I
!= Stop
&& *I
== '[')
555 if (unlikely(I
== Stop
))
560 bool NegArch
= false;
563 // look for whitespace or ending ']'
564 for (;End
!= Stop
&& !isspace(*End
) && *End
!= ']'; ++End
);
566 if (unlikely(End
== Stop
))
575 std::string
arch(I
, End
);
576 if (arch
.empty() == false && matchesArch(arch
.c_str()) == true)
581 // we found a match, so fast-forward to the end of the wildcards
582 for (; End
!= Stop
&& *End
!= ']'; ++End
);
591 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
598 Package
= ""; /* not for this arch */
602 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
605 if (I
!= Stop
&& *I
== '|')
606 Op
|= pkgCache::Dep::Or
;
608 if (I
== Stop
|| *I
== ',' || *I
== '|')
611 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
618 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
619 // ---------------------------------------------------------------------
620 /* This is the higher level depends parser. It takes a tag and generates
621 a complete depends tree for the given version. */
622 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
623 const char *Tag
,unsigned int Type
)
627 if (Section
.Find(Tag
,Start
,Stop
) == false)
630 string
const pkgArch
= Ver
.Arch();
638 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
);
640 return _error
->Error("Problem parsing dependency %s",Tag
);
641 size_t const found
= Package
.rfind(':');
643 // If negative is unspecific it needs to apply on all architectures
644 if (MultiArchEnabled
== true && found
== string::npos
&&
645 (Type
== pkgCache::Dep::Conflicts
||
646 Type
== pkgCache::Dep::DpkgBreaks
||
647 Type
== pkgCache::Dep::Replaces
))
649 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
650 a
!= Architectures
.end(); ++a
)
651 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
653 if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false)
656 else if (MultiArchEnabled
== true && found
!= string::npos
&&
657 strcmp(Package
.c_str() + found
, ":any") != 0)
659 string Arch
= Package
.substr(found
+1, string::npos
);
660 Package
= Package
.substr(0, found
);
661 // Such dependencies are not supposed to be accepted …
662 // … but this is probably the best thing to do.
663 if (Arch
== "native")
664 Arch
= _config
->Find("APT::Architecture");
665 if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false)
670 if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
672 if ((Type
== pkgCache::Dep::Conflicts
||
673 Type
== pkgCache::Dep::DpkgBreaks
||
674 Type
== pkgCache::Dep::Replaces
) &&
675 NewDepends(Ver
, Package
,
676 (pkgArch
!= "none") ? "none" : _config
->Find("APT::Architecture"),
677 Version
,Op
,Type
) == false)
686 // ListParser::ParseProvides - Parse the provides list /*{{{*/
687 // ---------------------------------------------------------------------
689 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
693 if (Section
.Find("Provides",Start
,Stop
) == true)
697 string
const Arch
= Ver
.Arch();
702 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
704 return _error
->Error("Problem parsing Provides line");
705 if (Op
!= pkgCache::Dep::NoOp
) {
706 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
707 } else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) {
708 if (NewProvidesAllArch(Ver
, Package
, Version
) == false)
711 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
720 if (MultiArchEnabled
== false)
722 else if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
724 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
725 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
727 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
728 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
733 // ListParser::NewProvides - add provides for all architectures /*{{{*/
734 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
735 string
const &Version
) {
736 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
737 a
!= Architectures
.end(); ++a
)
739 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
745 // ListParser::GrabWord - Matches a word and returns /*{{{*/
746 // ---------------------------------------------------------------------
747 /* Looks for a word in a list of words - for ParseStatus */
748 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
750 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
752 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
761 // ListParser::Step - Move to the next section in the file /*{{{*/
762 // ---------------------------------------------------------------------
763 /* This has to be carefull to only process the correct architecture */
764 bool debListParser::Step()
766 iOffset
= Tags
.Offset();
767 while (Tags
.Step(Section
) == true)
769 /* See if this is the correct Architecture, if it isn't then we
770 drop the whole section. A missing arch tag only happens (in theory)
771 inside the Status file, so that is a positive return */
772 string
const Architecture
= Section
.FindS("Architecture");
774 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
776 if (APT::Configuration::checkArchitecture(Architecture
) == true)
778 /* parse version stanzas without an architecture only in the status file
779 (and as misfortune bycatch flat-archives) */
780 if ((Arch
.empty() == true || Arch
== "any") && Architecture
.empty() == true)
785 if (Architecture
== Arch
)
788 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
792 iOffset
= Tags
.Offset();
797 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
798 // ---------------------------------------------------------------------
800 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
801 FileFd
&File
, string component
)
803 // apt-secure does no longer download individual (per-section) Release
804 // file. to provide Component pinning we use the section name now
805 map_ptrloc
const storage
= WriteUniqString(component
);
806 FileI
->Component
= storage
;
808 // FIXME: should use FileFd and TagSection
809 FILE* release
= fdopen(dup(File
.Fd()), "r");
814 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
819 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
)
822 if (buffer
[len
] == '\0')
825 // seperate the tag from the data
826 const char* dataStart
= strchr(buffer
+ len
, ':');
827 if (dataStart
== NULL
)
829 len
= dataStart
- buffer
;
830 for (++dataStart
; *dataStart
== ' '; ++dataStart
)
833 const char* dataEnd
= (const char*)rawmemchr(dataStart
, '\0');
834 // The last char should be a newline, but we can never be sure: #633350
835 const char* lineEnd
= dataEnd
;
836 for (--lineEnd
; *lineEnd
== '\r' || *lineEnd
== '\n'; --lineEnd
)
841 // which datastorage need to be updated
842 enum { Suite
, Component
, Version
, Origin
, Codename
, Label
, None
} writeTo
= None
;
843 if (buffer
[0] == ' ')
845 #define APT_PARSER_WRITETO(X) else if (strncmp(#X, buffer, len) == 0) writeTo = X;
846 APT_PARSER_WRITETO(Suite
)
847 APT_PARSER_WRITETO(Component
)
848 APT_PARSER_WRITETO(Version
)
849 APT_PARSER_WRITETO(Origin
)
850 APT_PARSER_WRITETO(Codename
)
851 APT_PARSER_WRITETO(Label
)
852 #undef APT_PARSER_WRITETO
853 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
854 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd);
855 APT_PARSER_FLAGIT(NotAutomatic
)
856 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
857 #undef APT_PARSER_FLAGIT
859 // load all data from the line and save it
862 data
.append(dataStart
, dataEnd
);
863 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
865 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
869 if (strlen(buffer
) != sizeof(buffer
) - 1)
875 // remove spaces and stuff from the end of the data line
876 for (std::string::reverse_iterator s
= data
.rbegin();
877 s
!= data
.rend(); ++s
)
879 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
883 map_ptrloc
const storage
= WriteUniqString(data
);
885 case Suite
: FileI
->Archive
= storage
; break;
886 case Component
: FileI
->Component
= storage
; break;
887 case Version
: FileI
->Version
= storage
; break;
888 case Origin
: FileI
->Origin
= storage
; break;
889 case Codename
: FileI
->Codename
= storage
; break;
890 case Label
: FileI
->Label
= storage
; break;
897 return !_error
->PendingError();
900 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
901 // ---------------------------------------------------------------------
903 unsigned char debListParser::GetPrio(string Str
)
906 if (GrabWord(Str
,PrioList
,Out
) == false)
907 Out
= pkgCache::State::Extra
;