]>
git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
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 switch (Ver
->MultiArch
)
133 case pkgCache::Version::Foreign
: Ver
->MultiArch
= pkgCache::Version::AllForeign
; break;
134 case pkgCache::Version::Allowed
: Ver
->MultiArch
= pkgCache::Version::AllAllowed
; break;
135 default: Ver
->MultiArch
= pkgCache::Version::All
;
139 Ver
->Size
= Section
.FindULL("Size");
140 // Unpacked Size (in K)
141 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
142 Ver
->InstalledSize
*= 1024;
147 if (Section
.Find("Priority",Start
,Stop
) == true)
149 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
150 Ver
->Priority
= pkgCache::State::Extra
;
153 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
155 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
157 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
159 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
161 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
163 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
165 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
167 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
171 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
174 if (ParseProvides(Ver
) == false)
180 // ListParser::Description - Return the description string /*{{{*/
181 // ---------------------------------------------------------------------
182 /* This is to return the string describing the package in debian
183 form. If this returns the blank string then the entry is assumed to
184 only describe package properties */
185 string
debListParser::Description()
187 string
const lang
= DescriptionLanguage();
189 return Section
.FindS("Description");
191 return Section
.FindS(string("Description-").append(lang
).c_str());
194 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
195 // ---------------------------------------------------------------------
196 /* This is to return the string describing the language of
197 description. If this returns the blank string then the entry is
198 assumed to describe original description. */
199 string
debListParser::DescriptionLanguage()
201 if (Section
.FindS("Description").empty() == false)
204 std::vector
<string
> const lang
= APT::Configuration::getLanguages();
205 for (std::vector
<string
>::const_iterator l
= lang
.begin();
206 l
!= lang
.end(); l
++)
207 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
213 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
214 // ---------------------------------------------------------------------
215 /* This is to return the md5 string to allow the check if it is the right
216 description. If no Description-md5 is found in the section it will be
219 MD5SumValue
debListParser::Description_md5()
221 string value
= Section
.FindS("Description-md5");
226 md5
.Add((Description() + "\n").c_str());
229 return MD5SumValue(value
);
232 // ListParser::UsePackage - Update a package structure /*{{{*/
233 // ---------------------------------------------------------------------
234 /* This is called to update the package with any new information
235 that might be found in the section */
236 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
237 pkgCache::VerIterator
&Ver
)
239 if (Pkg
->Section
== 0)
240 Pkg
->Section
= UniqFindTagWrite("Section");
242 // Packages which are not from the "native" arch doesn't get the essential flag
243 // in the default "native" mode - it is also possible to mark "all" or "none".
244 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
245 string
const static myArch
= _config
->Find("APT::Architecture");
246 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "native");
247 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
249 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
251 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
254 if (strcmp(Pkg
.Name(),"apt") == 0)
255 Pkg
->Flags
|= pkgCache::Flag::Important
;
257 if (ParseStatus(Pkg
,Ver
) == false)
262 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
263 // ---------------------------------------------------------------------
265 unsigned short debListParser::VersionHash()
267 const char *Sections
[] ={"Installed-Size",
275 unsigned long Result
= INIT_FCS
;
277 for (const char **I
= Sections
; *I
!= 0; I
++)
281 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
284 /* Strip out any spaces from the text, this undoes dpkgs reformatting
285 of certain fields. dpkg also has the rather interesting notion of
286 reformatting depends operators < -> <= */
288 for (; Start
!= End
; Start
++)
290 if (isspace(*Start
) == 0)
291 *I
++ = tolower_ascii(*Start
);
292 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
294 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
298 Result
= AddCRC16(Result
,S
,I
- S
);
304 // ListParser::ParseStatus - Parse the status field /*{{{*/
305 // ---------------------------------------------------------------------
306 /* Status lines are of the form,
307 Status: want flag status
308 want = unknown, install, hold, deinstall, purge
309 flag = ok, reinstreq, hold, hold-reinstreq
310 status = not-installed, unpacked, half-configured,
311 half-installed, config-files, post-inst-failed,
312 removal-failed, installed
314 Some of the above are obsolete (I think?) flag = hold-* and
315 status = post-inst-failed, removal-failed at least.
317 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
318 pkgCache::VerIterator
&Ver
)
322 if (Section
.Find("Status",Start
,Stop
) == false)
325 // UsePackage() is responsible for setting the flag in the default case
326 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
327 if (essential
== true &&
328 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
331 // Isolate the first word
332 const char *I
= Start
;
333 for(; I
< Stop
&& *I
!= ' '; I
++);
334 if (I
>= Stop
|| *I
!= ' ')
335 return _error
->Error("Malformed Status line");
337 // Process the want field
338 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
339 {"install",pkgCache::State::Install
},
340 {"hold",pkgCache::State::Hold
},
341 {"deinstall",pkgCache::State::DeInstall
},
342 {"purge",pkgCache::State::Purge
},
344 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
345 return _error
->Error("Malformed 1st word in the Status line");
347 // Isloate the next word
350 for(; I
< Stop
&& *I
!= ' '; I
++);
351 if (I
>= Stop
|| *I
!= ' ')
352 return _error
->Error("Malformed status line, no 2nd word");
354 // Process the flag field
355 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
356 {"reinstreq",pkgCache::State::ReInstReq
},
357 {"hold",pkgCache::State::HoldInst
},
358 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
360 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
361 return _error
->Error("Malformed 2nd word in the Status line");
363 // Isloate the last word
366 for(; I
< Stop
&& *I
!= ' '; I
++);
368 return _error
->Error("Malformed Status line, no 3rd word");
370 // Process the flag field
371 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
372 {"unpacked",pkgCache::State::UnPacked
},
373 {"half-configured",pkgCache::State::HalfConfigured
},
374 {"installed",pkgCache::State::Installed
},
375 {"half-installed",pkgCache::State::HalfInstalled
},
376 {"config-files",pkgCache::State::ConfigFiles
},
377 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
378 {"triggers-pending",pkgCache::State::TriggersPending
},
379 {"post-inst-failed",pkgCache::State::HalfConfigured
},
380 {"removal-failed",pkgCache::State::HalfInstalled
},
382 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
383 return _error
->Error("Malformed 3rd word in the Status line");
385 /* A Status line marks the package as indicating the current
386 version as well. Only if it is actually installed.. Otherwise
387 the interesting dpkg handling of the status file creates bogus
389 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
390 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
392 if (Ver
.end() == true)
393 _error
->Warning("Encountered status field in a non-version description");
395 Pkg
->CurrentVer
= Ver
.Index();
401 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
403 // Determine the operator
411 Op
= pkgCache::Dep::LessEq
;
418 Op
= pkgCache::Dep::Less
;
422 // < is the same as <= and << is really Cs < for some reason
423 Op
= pkgCache::Dep::LessEq
;
431 Op
= pkgCache::Dep::GreaterEq
;
438 Op
= pkgCache::Dep::Greater
;
442 // > is the same as >= and >> is really Cs > for some reason
443 Op
= pkgCache::Dep::GreaterEq
;
447 Op
= pkgCache::Dep::Equals
;
451 // HACK around bad package definitions
453 Op
= pkgCache::Dep::Equals
;
462 * The complete architecture, consisting of <kernel>-<cpu>.
464 static string
CompleteArch(std::string
& arch
) {
465 if (arch
== "armel") return "linux-arm";
466 if (arch
== "armhf") return "linux-arm";
467 if (arch
== "lpia") return "linux-i386";
468 if (arch
== "powerpcspe") return "linux-powerpc";
469 if (arch
== "uclibc-linux-armel") return "linux-arm";
470 if (arch
== "uclinux-armel") return "uclinux-arm";
472 return (arch
.find("-") != string::npos
) ? arch
: "linux-" + arch
;
475 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
476 // ---------------------------------------------------------------------
477 /* This parses the dependency elements out of a standard string in place,
479 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
480 string
&Package
,string
&Ver
,
481 unsigned int &Op
, bool const &ParseArchFlags
,
482 bool const &StripMultiArch
)
484 // Strip off leading space
485 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
487 // Parse off the package name
488 const char *I
= Start
;
489 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
490 *I
!= ',' && *I
!= '|'; I
++);
493 if (I
!= Stop
&& *I
== ')')
499 // Stash the package name
500 Package
.assign(Start
,I
- Start
);
502 // We don't want to confuse library users which can't handle MultiArch
503 if (StripMultiArch
== true) {
504 size_t const found
= Package
.rfind(':');
505 if (found
!= string::npos
)
506 Package
= Package
.substr(0,found
);
509 // Skip white space to the '('
510 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
513 if (I
!= Stop
&& *I
== '(')
516 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
519 I
= ConvertRelation(I
,Op
);
522 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
524 for (;I
!= Stop
&& *I
!= ')'; I
++);
525 if (I
== Stop
|| Start
== I
)
528 // Skip trailing whitespace
530 for (; End
> Start
&& isspace(End
[-1]); End
--);
532 Ver
.assign(Start
,End
-Start
);
538 Op
= pkgCache::Dep::NoOp
;
542 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
544 if (ParseArchFlags
== true)
546 string arch
= _config
->Find("APT::Architecture");
547 string completeArch
= CompleteArch(arch
);
549 // Parse an architecture
550 if (I
!= Stop
&& *I
== '[')
559 bool NegArch
= false;
562 // look for whitespace or ending ']'
563 while (End
!= Stop
&& !isspace(*End
) && *End
!= ']')
575 if (stringcmp(arch
,I
,End
) == 0) {
578 std::string wildcard
= SubstVar(string(I
, End
), "any", "*");
579 if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0)
589 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
596 Package
= ""; /* not for this arch */
600 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
603 if (I
!= Stop
&& *I
== '|')
604 Op
|= pkgCache::Dep::Or
;
606 if (I
== Stop
|| *I
== ',' || *I
== '|')
609 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
616 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
617 // ---------------------------------------------------------------------
618 /* This is the higher level depends parser. It takes a tag and generates
619 a complete depends tree for the given version. */
620 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
621 const char *Tag
,unsigned int Type
)
625 if (Section
.Find(Tag
,Start
,Stop
) == false)
629 string
const pkgArch
= Ver
.Arch();
635 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
);
637 return _error
->Error("Problem parsing dependency %s",Tag
);
639 if (MultiArchEnabled
== true &&
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)
649 else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
657 // ListParser::ParseProvides - Parse the provides list /*{{{*/
658 // ---------------------------------------------------------------------
660 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
664 if (Section
.Find("Provides",Start
,Stop
) == true)
668 string
const Arch
= Ver
.Arch();
673 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
675 return _error
->Error("Problem parsing Provides line");
676 if (Op
!= pkgCache::Dep::NoOp
) {
677 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
679 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
688 if (MultiArchEnabled
== false)
690 else if (Ver
->MultiArch
== pkgCache::Version::Allowed
|| Ver
->MultiArch
== pkgCache::Version::AllAllowed
)
692 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
693 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
695 else if (Ver
->MultiArch
== pkgCache::Version::Foreign
|| Ver
->MultiArch
== pkgCache::Version::AllForeign
)
696 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
701 // ListParser::NewProvides - add provides for all architectures /*{{{*/
702 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
703 string
const &Version
) {
704 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
705 a
!= Architectures
.end(); ++a
)
707 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
713 // ListParser::GrabWord - Matches a word and returns /*{{{*/
714 // ---------------------------------------------------------------------
715 /* Looks for a word in a list of words - for ParseStatus */
716 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
718 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
720 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
729 // ListParser::Step - Move to the next section in the file /*{{{*/
730 // ---------------------------------------------------------------------
731 /* This has to be carefull to only process the correct architecture */
732 bool debListParser::Step()
734 iOffset
= Tags
.Offset();
735 while (Tags
.Step(Section
) == true)
737 /* See if this is the correct Architecture, if it isn't then we
738 drop the whole section. A missing arch tag only happens (in theory)
739 inside the Status file, so that is a positive return */
740 string
const Architecture
= Section
.FindS("Architecture");
741 if (Architecture
.empty() == true)
744 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
746 if (APT::Configuration::checkArchitecture(Architecture
) == true)
751 if (Architecture
== Arch
)
754 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
758 iOffset
= Tags
.Offset();
763 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
764 // ---------------------------------------------------------------------
766 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
767 FileFd
&File
, string component
)
769 // apt-secure does no longer download individual (per-section) Release
770 // file. to provide Component pinning we use the section name now
771 FileI
->Component
= WriteUniqString(component
);
773 FILE* release
= fdopen(dup(File
.Fd()), "r");
778 bool gpgClose
= false;
779 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
784 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
);
785 if (buffer
[len
] == '\0')
788 // only evalute the first GPG section
789 if (strncmp("-----", buffer
, 5) == 0)
791 if (gpgClose
== true)
797 // seperate the tag from the data
798 for (; buffer
[len
] != ':' && buffer
[len
] != '\0'; ++len
);
799 if (buffer
[len
] == '\0')
801 char* dataStart
= buffer
+ len
;
802 for (++dataStart
; *dataStart
== ' '; ++dataStart
);
803 char* dataEnd
= dataStart
;
804 for (++dataEnd
; *dataEnd
!= '\0'; ++dataEnd
);
806 // which datastorage need to be updated
807 map_ptrloc
* writeTo
= NULL
;
808 if (buffer
[0] == ' ')
810 #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
811 APT_PARSER_WRITETO(FileI
->Archive
, "Suite")
812 APT_PARSER_WRITETO(FileI
->Component
, "Component")
813 APT_PARSER_WRITETO(FileI
->Version
, "Version")
814 APT_PARSER_WRITETO(FileI
->Origin
, "Origin")
815 APT_PARSER_WRITETO(FileI
->Codename
, "Codename")
816 APT_PARSER_WRITETO(FileI
->Label
, "Label")
817 #undef APT_PARSER_WRITETO
818 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
819 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, dataEnd-1);
820 APT_PARSER_FLAGIT(NotAutomatic
)
821 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
822 #undef APT_PARSER_FLAGIT
824 // load all data from the line and save it
827 data
.append(dataStart
, dataEnd
);
828 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
830 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
834 if (strlen(buffer
) != sizeof(buffer
) - 1)
840 // remove spaces and stuff from the end of the data line
841 for (std::string::reverse_iterator s
= data
.rbegin();
842 s
!= data
.rend(); ++s
)
844 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
848 *writeTo
= WriteUniqString(data
);
853 return !_error
->PendingError();
856 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
857 // ---------------------------------------------------------------------
859 unsigned char debListParser::GetPrio(string Str
)
862 if (GrabWord(Str
,PrioList
,Out
) == false)
863 Out
= pkgCache::State::Extra
;