]>
git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
b708296d3fd53511349dfc3e739da3d0d2519741
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 /*{{{*/
13 #include <apt-pkg/deblistparser.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/configuration.h>
16 #include <apt-pkg/aptconfiguration.h>
17 #include <apt-pkg/strutl.h>
18 #include <apt-pkg/crc-16.h>
19 #include <apt-pkg/md5.h>
20 #include <apt-pkg/macros.h>
26 static debListParser::WordList PrioList
[] = {{"important",pkgCache::State::Important
},
27 {"required",pkgCache::State::Required
},
28 {"standard",pkgCache::State::Standard
},
29 {"optional",pkgCache::State::Optional
},
30 {"extra",pkgCache::State::Extra
},
33 // ListParser::debListParser - Constructor /*{{{*/
34 // ---------------------------------------------------------------------
35 /* Provide an architecture and only this one and "all" will be accepted
36 in Step(), if no Architecture is given we will accept every arch
37 we would accept in general with checkArchitecture() */
38 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
41 this->Arch
= _config
->Find("APT::Architecture");
42 Architectures
= APT::Configuration::getArchitectures();
43 MultiArchEnabled
= Architectures
.size() > 1;
46 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
47 // ---------------------------------------------------------------------
49 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
53 if (Section
.Find(Tag
,Start
,Stop
) == false)
55 return WriteUniqString(Start
,Stop
- Start
);
58 // ListParser::Package - Return the package name /*{{{*/
59 // ---------------------------------------------------------------------
60 /* This is to return the name of the package this section describes */
61 string
debListParser::Package() {
62 string
const Result
= Section
.FindS("Package");
63 if(unlikely(Result
.empty() == true))
64 _error
->Error("Encountered a section with no Package: header");
68 // ListParser::Architecture - Return the package arch /*{{{*/
69 // ---------------------------------------------------------------------
70 /* This will return the Architecture of the package this section describes */
71 string
debListParser::Architecture() {
72 std::string
const Arch
= Section
.FindS("Architecture");
73 if (Arch
.empty() == true)
74 return _config
->Find("APT::Architecture");
78 // ListParser::ArchitectureAll /*{{{*/
79 // ---------------------------------------------------------------------
81 bool debListParser::ArchitectureAll() {
82 return Section
.FindS("Architecture") == "all";
85 // ListParser::Version - Return the version string /*{{{*/
86 // ---------------------------------------------------------------------
87 /* This is to return the string describing the version in debian form,
88 epoch:upstream-release. If this returns the blank string then the
89 entry is assumed to only describe package properties */
90 string
debListParser::Version()
92 return Section
.FindS("Version");
95 // ListParser::NewVersion - Fill in the version structure /*{{{*/
96 // ---------------------------------------------------------------------
98 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
101 Ver
->Section
= UniqFindTagWrite("Section");
104 string
const MultiArch
= Section
.FindS("Multi-Arch");
105 if (MultiArch
.empty() == true)
106 Ver
->MultiArch
= pkgCache::Version::None
;
107 else if (MultiArch
== "same") {
109 if (ArchitectureAll() == true)
111 /* Arch all packages can't be Multi-Arch: same */
112 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
113 Section
.FindS("Package").c_str());
114 Ver
->MultiArch
= pkgCache::Version::None
;
117 Ver
->MultiArch
= pkgCache::Version::Same
;
119 else if (MultiArch
== "foreign")
120 Ver
->MultiArch
= pkgCache::Version::Foreign
;
121 else if (MultiArch
== "allowed")
122 Ver
->MultiArch
= pkgCache::Version::Allowed
;
125 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
126 MultiArch
.c_str(), Section
.FindS("Package").c_str());
127 Ver
->MultiArch
= pkgCache::Version::None
;
130 if (ArchitectureAll() == true)
131 Ver
->MultiArch
|= pkgCache::Version::All
;
134 Ver
->Size
= Section
.FindULL("Size");
135 // Unpacked Size (in K)
136 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
137 Ver
->InstalledSize
*= 1024;
142 if (Section
.Find("Priority",Start
,Stop
) == true)
144 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
145 Ver
->Priority
= pkgCache::State::Extra
;
148 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
150 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
152 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
154 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
156 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
158 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
160 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
162 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
166 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
169 if (ParseProvides(Ver
) == false)
175 // ListParser::Description - Return the description string /*{{{*/
176 // ---------------------------------------------------------------------
177 /* This is to return the string describing the package in debian
178 form. If this returns the blank string then the entry is assumed to
179 only describe package properties */
180 string
debListParser::Description()
182 string
const lang
= DescriptionLanguage();
184 return Section
.FindS("Description");
186 return Section
.FindS(string("Description-").append(lang
).c_str());
189 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
190 // ---------------------------------------------------------------------
191 /* This is to return the string describing the language of
192 description. If this returns the blank string then the entry is
193 assumed to describe original description. */
194 string
debListParser::DescriptionLanguage()
196 if (Section
.FindS("Description").empty() == false)
199 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
200 for (std::vector
<string
>::const_iterator l
= lang
.begin();
201 l
!= lang
.end(); l
++)
202 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
208 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
209 // ---------------------------------------------------------------------
210 /* This is to return the md5 string to allow the check if it is the right
211 description. If no Description-md5 is found in the section it will be
214 MD5SumValue
debListParser::Description_md5()
216 string value
= Section
.FindS("Description-md5");
221 md5
.Add((Description() + "\n").c_str());
224 return MD5SumValue(value
);
227 // ListParser::UsePackage - Update a package structure /*{{{*/
228 // ---------------------------------------------------------------------
229 /* This is called to update the package with any new information
230 that might be found in the section */
231 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
232 pkgCache::VerIterator
&Ver
)
234 if (Pkg
->Section
== 0)
235 Pkg
->Section
= UniqFindTagWrite("Section");
237 // Packages which are not from the "native" arch doesn't get the essential flag
238 // in the default "native" mode - it is also possible to mark "all" or "none".
239 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
240 string
const static myArch
= _config
->Find("APT::Architecture");
241 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "native");
242 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
244 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
246 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
249 if (strcmp(Pkg
.Name(),"apt") == 0)
250 Pkg
->Flags
|= pkgCache::Flag::Important
;
252 if (ParseStatus(Pkg
,Ver
) == false)
257 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
258 // ---------------------------------------------------------------------
260 unsigned short debListParser::VersionHash()
262 const char *Sections
[] ={"Installed-Size",
270 unsigned long Result
= INIT_FCS
;
272 for (const char **I
= Sections
; *I
!= 0; I
++)
276 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
279 /* Strip out any spaces from the text, this undoes dpkgs reformatting
280 of certain fields. dpkg also has the rather interesting notion of
281 reformatting depends operators < -> <= */
283 for (; Start
!= End
; Start
++)
285 if (isspace(*Start
) == 0)
286 *J
++ = tolower_ascii(*Start
);
287 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
289 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
293 Result
= AddCRC16(Result
,S
,J
- S
);
299 // ListParser::ParseStatus - Parse the status field /*{{{*/
300 // ---------------------------------------------------------------------
301 /* Status lines are of the form,
302 Status: want flag status
303 want = unknown, install, hold, deinstall, purge
304 flag = ok, reinstreq, hold, hold-reinstreq
305 status = not-installed, unpacked, half-configured,
306 half-installed, config-files, post-inst-failed,
307 removal-failed, installed
309 Some of the above are obsolete (I think?) flag = hold-* and
310 status = post-inst-failed, removal-failed at least.
312 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
313 pkgCache::VerIterator
&Ver
)
317 if (Section
.Find("Status",Start
,Stop
) == false)
320 // UsePackage() is responsible for setting the flag in the default case
321 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
322 if (essential
== true &&
323 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
326 // Isolate the first word
327 const char *I
= Start
;
328 for(; I
< Stop
&& *I
!= ' '; I
++);
329 if (I
>= Stop
|| *I
!= ' ')
330 return _error
->Error("Malformed Status line");
332 // Process the want field
333 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
334 {"install",pkgCache::State::Install
},
335 {"hold",pkgCache::State::Hold
},
336 {"deinstall",pkgCache::State::DeInstall
},
337 {"purge",pkgCache::State::Purge
},
339 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
340 return _error
->Error("Malformed 1st word in the Status line");
342 // Isloate the next word
345 for(; I
< Stop
&& *I
!= ' '; I
++);
346 if (I
>= Stop
|| *I
!= ' ')
347 return _error
->Error("Malformed status line, no 2nd word");
349 // Process the flag field
350 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
351 {"reinstreq",pkgCache::State::ReInstReq
},
352 {"hold",pkgCache::State::HoldInst
},
353 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
355 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
356 return _error
->Error("Malformed 2nd word in the Status line");
358 // Isloate the last word
361 for(; I
< Stop
&& *I
!= ' '; I
++);
363 return _error
->Error("Malformed Status line, no 3rd word");
365 // Process the flag field
366 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
367 {"unpacked",pkgCache::State::UnPacked
},
368 {"half-configured",pkgCache::State::HalfConfigured
},
369 {"installed",pkgCache::State::Installed
},
370 {"half-installed",pkgCache::State::HalfInstalled
},
371 {"config-files",pkgCache::State::ConfigFiles
},
372 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
373 {"triggers-pending",pkgCache::State::TriggersPending
},
374 {"post-inst-failed",pkgCache::State::HalfConfigured
},
375 {"removal-failed",pkgCache::State::HalfInstalled
},
377 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
378 return _error
->Error("Malformed 3rd word in the Status line");
380 /* A Status line marks the package as indicating the current
381 version as well. Only if it is actually installed.. Otherwise
382 the interesting dpkg handling of the status file creates bogus
384 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
385 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
387 if (Ver
.end() == true)
388 _error
->Warning("Encountered status field in a non-version description");
390 Pkg
->CurrentVer
= Ver
.Index();
396 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
398 // Determine the operator
406 Op
= pkgCache::Dep::LessEq
;
413 Op
= pkgCache::Dep::Less
;
417 // < is the same as <= and << is really Cs < for some reason
418 Op
= pkgCache::Dep::LessEq
;
426 Op
= pkgCache::Dep::GreaterEq
;
433 Op
= pkgCache::Dep::Greater
;
437 // > is the same as >= and >> is really Cs > for some reason
438 Op
= pkgCache::Dep::GreaterEq
;
442 Op
= pkgCache::Dep::Equals
;
446 // HACK around bad package definitions
448 Op
= pkgCache::Dep::Equals
;
457 * The complete architecture, consisting of <kernel>-<cpu>.
459 static string
CompleteArch(std::string
& arch
) {
460 if (arch
== "armel") return "linux-arm";
461 if (arch
== "armhf") return "linux-arm";
462 if (arch
== "lpia") return "linux-i386";
463 if (arch
== "powerpcspe") return "linux-powerpc";
464 if (arch
== "uclibc-linux-armel") return "linux-arm";
465 if (arch
== "uclinux-armel") return "uclinux-arm";
467 return (arch
.find("-") != string::npos
) ? arch
: "linux-" + arch
;
470 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
471 // ---------------------------------------------------------------------
472 /* This parses the dependency elements out of a standard string in place,
474 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
475 string
&Package
,string
&Ver
,
476 unsigned int &Op
, bool const &ParseArchFlags
,
477 bool const &StripMultiArch
)
479 // Strip off leading space
480 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
482 // Parse off the package name
483 const char *I
= Start
;
484 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
485 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']'; I
++);
488 if (I
!= Stop
&& *I
== ')')
494 // Stash the package name
495 Package
.assign(Start
,I
- Start
);
497 // We don't want to confuse library users which can't handle MultiArch
498 if (StripMultiArch
== true) {
499 size_t const found
= Package
.rfind(':');
500 if (found
!= string::npos
)
501 Package
= Package
.substr(0,found
);
504 // Skip white space to the '('
505 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
508 if (I
!= Stop
&& *I
== '(')
511 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
514 I
= ConvertRelation(I
,Op
);
517 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
519 for (;I
!= Stop
&& *I
!= ')'; I
++);
520 if (I
== Stop
|| Start
== I
)
523 // Skip trailing whitespace
525 for (; End
> Start
&& isspace(End
[-1]); End
--);
527 Ver
.assign(Start
,End
-Start
);
533 Op
= pkgCache::Dep::NoOp
;
537 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
539 if (ParseArchFlags
== true)
541 string arch
= _config
->Find("APT::Architecture");
542 string completeArch
= CompleteArch(arch
);
544 // Parse an architecture
545 if (I
!= Stop
&& *I
== '[')
554 bool NegArch
= false;
557 // look for whitespace or ending ']'
558 while (End
!= Stop
&& !isspace(*End
) && *End
!= ']')
570 if (stringcmp(arch
,I
,End
) == 0) {
573 std::string wildcard
= SubstVar(string(I
, End
), "any", "*");
574 if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0)
584 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
591 Package
= ""; /* not for this arch */
595 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
598 if (I
!= Stop
&& *I
== '|')
599 Op
|= pkgCache::Dep::Or
;
601 if (I
== Stop
|| *I
== ',' || *I
== '|')
604 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
611 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
612 // ---------------------------------------------------------------------
613 /* This is the higher level depends parser. It takes a tag and generates
614 a complete depends tree for the given version. */
615 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
616 const char *Tag
,unsigned int Type
)
620 if (Section
.Find(Tag
,Start
,Stop
) == false)
624 string
const pkgArch
= Ver
.Arch();
630 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
);
632 return _error
->Error("Problem parsing dependency %s",Tag
);
634 if (MultiArchEnabled
== true &&
635 (Type
== pkgCache::Dep::Conflicts
||
636 Type
== pkgCache::Dep::DpkgBreaks
||
637 Type
== pkgCache::Dep::Replaces
))
639 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
640 a
!= Architectures
.end(); ++a
)
641 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
644 else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
652 // ListParser::ParseProvides - Parse the provides list /*{{{*/
653 // ---------------------------------------------------------------------
655 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
659 if (Section
.Find("Provides",Start
,Stop
) == true)
663 string
const Arch
= Ver
.Arch();
668 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
670 return _error
->Error("Problem parsing Provides line");
671 if (Op
!= pkgCache::Dep::NoOp
) {
672 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
674 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
683 if (MultiArchEnabled
== false)
685 else if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
687 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
688 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
690 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
691 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
696 // ListParser::NewProvides - add provides for all architectures /*{{{*/
697 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
698 string
const &Version
) {
699 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
700 a
!= Architectures
.end(); ++a
)
702 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
708 // ListParser::GrabWord - Matches a word and returns /*{{{*/
709 // ---------------------------------------------------------------------
710 /* Looks for a word in a list of words - for ParseStatus */
711 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
713 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
715 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
724 // ListParser::Step - Move to the next section in the file /*{{{*/
725 // ---------------------------------------------------------------------
726 /* This has to be carefull to only process the correct architecture */
727 bool debListParser::Step()
729 iOffset
= Tags
.Offset();
730 while (Tags
.Step(Section
) == true)
732 /* See if this is the correct Architecture, if it isn't then we
733 drop the whole section. A missing arch tag only happens (in theory)
734 inside the Status file, so that is a positive return */
735 string
const Architecture
= Section
.FindS("Architecture");
736 if (Architecture
.empty() == true)
739 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
741 if (APT::Configuration::checkArchitecture(Architecture
) == true)
746 if (Architecture
== Arch
)
749 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
753 iOffset
= Tags
.Offset();
758 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
759 // ---------------------------------------------------------------------
761 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
762 FileFd
&File
, string component
)
764 // apt-secure does no longer download individual (per-section) Release
765 // file. to provide Component pinning we use the section name now
766 FileI
->Component
= WriteUniqString(component
);
768 FILE* release
= fdopen(dup(File
.Fd()), "r");
773 bool gpgClose
= false;
774 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
779 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
);
780 if (buffer
[len
] == '\0')
783 // only evalute the first GPG section
784 if (strncmp("-----", buffer
, 5) == 0)
786 if (gpgClose
== true)
792 // seperate the tag from the data
793 for (; buffer
[len
] != ':' && buffer
[len
] != '\0'; ++len
);
794 if (buffer
[len
] == '\0')
796 char* dataStart
= buffer
+ len
;
797 for (++dataStart
; *dataStart
== ' '; ++dataStart
);
798 char* dataEnd
= dataStart
;
799 for (++dataEnd
; *dataEnd
!= '\0'; ++dataEnd
);
801 // which datastorage need to be updated
802 map_ptrloc
* writeTo
= NULL
;
803 if (buffer
[0] == ' ')
805 #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
806 APT_PARSER_WRITETO(FileI
->Archive
, "Suite")
807 APT_PARSER_WRITETO(FileI
->Component
, "Component")
808 APT_PARSER_WRITETO(FileI
->Version
, "Version")
809 APT_PARSER_WRITETO(FileI
->Origin
, "Origin")
810 APT_PARSER_WRITETO(FileI
->Codename
, "Codename")
811 APT_PARSER_WRITETO(FileI
->Label
, "Label")
812 #undef APT_PARSER_WRITETO
813 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
814 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, dataEnd-1);
815 APT_PARSER_FLAGIT(NotAutomatic
)
816 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
817 #undef APT_PARSER_FLAGIT
819 // load all data from the line and save it
822 data
.append(dataStart
, dataEnd
);
823 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
825 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
829 if (strlen(buffer
) != sizeof(buffer
) - 1)
835 // remove spaces and stuff from the end of the data line
836 for (std::string::reverse_iterator s
= data
.rbegin();
837 s
!= data
.rend(); ++s
)
839 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
843 *writeTo
= WriteUniqString(data
);
848 return !_error
->PendingError();
851 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
852 // ---------------------------------------------------------------------
854 unsigned char debListParser::GetPrio(string Str
)
857 if (GrabWord(Str
,PrioList
,Out
) == false)
858 Out
= pkgCache::State::Extra
;