]>
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 Note that architecture "all" packages will get the architecture of the
72 Packages file parsed here. */
73 string
debListParser::Architecture() {
74 string
const Result
= Section
.FindS("Architecture");
75 if (Result
.empty() == true || Result
== "all")
77 if (Arch
.empty() == true)
78 /* FIXME: this is a problem for installed arch all
79 packages as we don't know from which arch this
80 package was installed - and therefore which
81 dependency this package resolves. */
82 return _config
->Find("APT::Architecture");
89 // ListParser::ArchitectureAll /*{{{*/
90 // ---------------------------------------------------------------------
92 bool debListParser::ArchitectureAll() {
93 return Section
.FindS("Architecture") == "all";
96 // ListParser::Version - Return the version string /*{{{*/
97 // ---------------------------------------------------------------------
98 /* This is to return the string describing the version in debian form,
99 epoch:upstream-release. If this returns the blank string then the
100 entry is assumed to only describe package properties */
101 string
debListParser::Version()
103 return Section
.FindS("Version");
106 // ListParser::NewVersion - Fill in the version structure /*{{{*/
107 // ---------------------------------------------------------------------
109 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
112 Ver
->Section
= UniqFindTagWrite("Section");
115 if (Section
.FindS("Architecture") == "all")
116 /* Arch all packages can't have a Multi-Arch field,
117 but we need a special treatment for them nonetheless */
118 Ver
->MultiArch
= pkgCache::Version::All
;
121 string
const MultiArch
= Section
.FindS("Multi-Arch");
122 if (MultiArch
.empty() == true)
123 Ver
->MultiArch
= pkgCache::Version::None
;
124 else if (MultiArch
== "same")
125 Ver
->MultiArch
= pkgCache::Version::Same
;
126 else if (MultiArch
== "foreign")
127 Ver
->MultiArch
= pkgCache::Version::Foreign
;
128 else if (MultiArch
== "allowed")
129 Ver
->MultiArch
= pkgCache::Version::Allowed
;
132 _error
->Warning("Unknown Multi-Arch type »%s« for package »%s«",
133 MultiArch
.c_str(), Section
.FindS("Package").c_str());
134 Ver
->MultiArch
= pkgCache::Version::None
;
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 (Ver
->MultiArch
== pkgCache::Version::All
)
155 /* We maintain a "pseudo" arch=all package for architecture all versions
156 on which these versions can depend on. This pseudo package is many used
157 for downloading/installing: The other pseudo-packages will degenerate
158 to a NOP in the download/install step - this package will ensure that
159 it is downloaded only one time and installed only one time -- even if
160 the architecture bound versions coming in and out on regular basis. */
161 if (strcmp(Ver
.Arch(true),"all") == 0)
163 else if (MultiArchEnabled
== true)
165 // our pseudo packages have no size to not confuse the fetcher
167 Ver
->InstalledSize
= 0;
171 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
173 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
175 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
177 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
179 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
181 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
183 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
185 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
189 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
192 if (ParseProvides(Ver
) == false)
198 // ListParser::Description - Return the description string /*{{{*/
199 // ---------------------------------------------------------------------
200 /* This is to return the string describing the package in debian
201 form. If this returns the blank string then the entry is assumed to
202 only describe package properties */
203 string
debListParser::Description()
205 string
const lang
= DescriptionLanguage();
207 return Section
.FindS("Description");
209 return Section
.FindS(string("Description-").append(lang
).c_str());
212 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
213 // ---------------------------------------------------------------------
214 /* This is to return the string describing the language of
215 description. If this returns the blank string then the entry is
216 assumed to describe original description. */
217 string
debListParser::DescriptionLanguage()
219 if (Section
.FindS("Description").empty() == false)
222 std::vector
<string
> const lang
= APT::Configuration::getLanguages();
223 for (std::vector
<string
>::const_iterator l
= lang
.begin();
224 l
!= lang
.end(); l
++)
225 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
231 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
232 // ---------------------------------------------------------------------
233 /* This is to return the md5 string to allow the check if it is the right
234 description. If no Description-md5 is found in the section it will be
237 MD5SumValue
debListParser::Description_md5()
239 string value
= Section
.FindS("Description-md5");
244 md5
.Add((Description() + "\n").c_str());
247 return MD5SumValue(value
);
250 // ListParser::UsePackage - Update a package structure /*{{{*/
251 // ---------------------------------------------------------------------
252 /* This is called to update the package with any new information
253 that might be found in the section */
254 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
255 pkgCache::VerIterator
&Ver
)
257 if (Pkg
->Section
== 0)
258 Pkg
->Section
= UniqFindTagWrite("Section");
260 // Packages which are not from the "native" arch doesn't get the essential flag
261 // in the default "native" mode - it is also possible to mark "all" or "none".
262 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
263 string
const static myArch
= _config
->Find("APT::Architecture");
264 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "native");
265 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
267 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
269 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
272 if (strcmp(Pkg
.Name(),"apt") == 0)
273 Pkg
->Flags
|= pkgCache::Flag::Important
;
275 if (ParseStatus(Pkg
,Ver
) == false)
280 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
281 // ---------------------------------------------------------------------
283 unsigned short debListParser::VersionHash()
285 const char *Sections
[] ={"Installed-Size",
293 unsigned long Result
= INIT_FCS
;
295 for (const char **I
= Sections
; *I
!= 0; I
++)
299 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
302 /* Strip out any spaces from the text, this undoes dpkgs reformatting
303 of certain fields. dpkg also has the rather interesting notion of
304 reformatting depends operators < -> <= */
306 for (; Start
!= End
; Start
++)
308 if (isspace(*Start
) == 0)
309 *I
++ = tolower_ascii(*Start
);
310 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
312 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
316 Result
= AddCRC16(Result
,S
,I
- S
);
322 // ListParser::ParseStatus - Parse the status field /*{{{*/
323 // ---------------------------------------------------------------------
324 /* Status lines are of the form,
325 Status: want flag status
326 want = unknown, install, hold, deinstall, purge
327 flag = ok, reinstreq, hold, hold-reinstreq
328 status = not-installed, unpacked, half-configured,
329 half-installed, config-files, post-inst-failed,
330 removal-failed, installed
332 Some of the above are obsolete (I think?) flag = hold-* and
333 status = post-inst-failed, removal-failed at least.
335 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
336 pkgCache::VerIterator
&Ver
)
340 if (Section
.Find("Status",Start
,Stop
) == false)
343 // UsePackage() is responsible for setting the flag in the default case
344 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
345 if (essential
== true &&
346 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
349 // Isolate the first word
350 const char *I
= Start
;
351 for(; I
< Stop
&& *I
!= ' '; I
++);
352 if (I
>= Stop
|| *I
!= ' ')
353 return _error
->Error("Malformed Status line");
355 // Process the want field
356 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
357 {"install",pkgCache::State::Install
},
358 {"hold",pkgCache::State::Hold
},
359 {"deinstall",pkgCache::State::DeInstall
},
360 {"purge",pkgCache::State::Purge
},
362 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
363 return _error
->Error("Malformed 1st word in the Status line");
365 // Isloate the next word
368 for(; I
< Stop
&& *I
!= ' '; I
++);
369 if (I
>= Stop
|| *I
!= ' ')
370 return _error
->Error("Malformed status line, no 2nd word");
372 // Process the flag field
373 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
374 {"reinstreq",pkgCache::State::ReInstReq
},
375 {"hold",pkgCache::State::HoldInst
},
376 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
378 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
379 return _error
->Error("Malformed 2nd word in the Status line");
381 // Isloate the last word
384 for(; I
< Stop
&& *I
!= ' '; I
++);
386 return _error
->Error("Malformed Status line, no 3rd word");
388 // Process the flag field
389 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
390 {"unpacked",pkgCache::State::UnPacked
},
391 {"half-configured",pkgCache::State::HalfConfigured
},
392 {"installed",pkgCache::State::Installed
},
393 {"half-installed",pkgCache::State::HalfInstalled
},
394 {"config-files",pkgCache::State::ConfigFiles
},
395 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
396 {"triggers-pending",pkgCache::State::TriggersPending
},
397 {"post-inst-failed",pkgCache::State::HalfConfigured
},
398 {"removal-failed",pkgCache::State::HalfInstalled
},
400 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
401 return _error
->Error("Malformed 3rd word in the Status line");
403 /* A Status line marks the package as indicating the current
404 version as well. Only if it is actually installed.. Otherwise
405 the interesting dpkg handling of the status file creates bogus
407 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
408 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
410 if (Ver
.end() == true)
411 _error
->Warning("Encountered status field in a non-version description");
413 Pkg
->CurrentVer
= Ver
.Index();
419 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
421 // Determine the operator
429 Op
= pkgCache::Dep::LessEq
;
436 Op
= pkgCache::Dep::Less
;
440 // < is the same as <= and << is really Cs < for some reason
441 Op
= pkgCache::Dep::LessEq
;
449 Op
= pkgCache::Dep::GreaterEq
;
456 Op
= pkgCache::Dep::Greater
;
460 // > is the same as >= and >> is really Cs > for some reason
461 Op
= pkgCache::Dep::GreaterEq
;
465 Op
= pkgCache::Dep::Equals
;
469 // HACK around bad package definitions
471 Op
= pkgCache::Dep::Equals
;
480 * The complete architecture, consisting of <kernel>-<cpu>.
482 static string
CompleteArch(std::string
& arch
) {
483 if (arch
== "armel") return "linux-arm";
484 if (arch
== "armhf") return "linux-arm";
485 if (arch
== "lpia") return "linux-i386";
486 if (arch
== "powerpcspe") return "linux-powerpc";
487 if (arch
== "uclibc-linux-armel") return "linux-arm";
488 if (arch
== "uclinux-armel") return "uclinux-arm";
490 return (arch
.find("-") != string::npos
) ? arch
: "linux-" + arch
;
493 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
494 // ---------------------------------------------------------------------
495 /* This parses the dependency elements out of a standard string in place,
497 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
498 string
&Package
,string
&Ver
,
499 unsigned int &Op
, bool const &ParseArchFlags
,
500 bool const &StripMultiArch
)
502 // Strip off leading space
503 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
505 // Parse off the package name
506 const char *I
= Start
;
507 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
508 *I
!= ',' && *I
!= '|'; I
++);
511 if (I
!= Stop
&& *I
== ')')
517 // Stash the package name
518 Package
.assign(Start
,I
- Start
);
520 // We don't want to confuse library users which can't handle MultiArch
521 if (StripMultiArch
== true) {
522 size_t const found
= Package
.rfind(':');
523 if (found
!= string::npos
)
524 Package
= Package
.substr(0,found
);
527 // Skip white space to the '('
528 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
531 if (I
!= Stop
&& *I
== '(')
534 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
537 I
= ConvertRelation(I
,Op
);
540 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
542 for (;I
!= Stop
&& *I
!= ')'; I
++);
543 if (I
== Stop
|| Start
== I
)
546 // Skip trailing whitespace
548 for (; End
> Start
&& isspace(End
[-1]); End
--);
550 Ver
.assign(Start
,End
-Start
);
556 Op
= pkgCache::Dep::NoOp
;
560 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
562 if (ParseArchFlags
== true)
564 string arch
= _config
->Find("APT::Architecture");
565 string completeArch
= CompleteArch(arch
);
567 // Parse an architecture
568 if (I
!= Stop
&& *I
== '[')
577 bool NegArch
= false;
580 // look for whitespace or ending ']'
581 while (End
!= Stop
&& !isspace(*End
) && *End
!= ']')
593 if (stringcmp(arch
,I
,End
) == 0) {
596 std::string wildcard
= SubstVar(string(I
, End
), "any", "*");
597 if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0)
607 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
614 Package
= ""; /* not for this arch */
618 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
621 if (I
!= Stop
&& *I
== '|')
622 Op
|= pkgCache::Dep::Or
;
624 if (I
== Stop
|| *I
== ',' || *I
== '|')
627 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
634 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
635 // ---------------------------------------------------------------------
636 /* This is the higher level depends parser. It takes a tag and generates
637 a complete depends tree for the given version. */
638 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
639 const char *Tag
,unsigned int Type
)
643 if (Section
.Find(Tag
,Start
,Stop
) == false)
647 string
const pkgArch
= Ver
.Arch(true);
653 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
655 return _error
->Error("Problem parsing dependency %s",Tag
);
657 if (MultiArchEnabled
== true &&
658 (Type
== pkgCache::Dep::Conflicts
||
659 Type
== pkgCache::Dep::DpkgBreaks
||
660 Type
== pkgCache::Dep::Replaces
))
662 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
663 a
!= Architectures
.end(); ++a
)
664 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
667 else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
675 // ListParser::ParseProvides - Parse the provides list /*{{{*/
676 // ---------------------------------------------------------------------
678 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
682 if (Section
.Find("Provides",Start
,Stop
) == true)
686 string
const Arch
= Ver
.Arch(true);
691 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
693 return _error
->Error("Problem parsing Provides line");
694 if (Op
!= pkgCache::Dep::NoOp
) {
695 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
697 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
706 if (Ver
->MultiArch
== pkgCache::Version::Allowed
)
708 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
709 NewProvides(Ver
, Package
, "any", Ver
.VerStr());
712 if (Ver
->MultiArch
!= pkgCache::Version::Foreign
)
715 if (MultiArchEnabled
== false)
718 string
const Package
= Ver
.ParentPkg().Name();
719 string
const Version
= Ver
.VerStr();
720 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
721 a
!= Architectures
.end(); ++a
)
723 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
730 // ListParser::GrabWord - Matches a word and returns /*{{{*/
731 // ---------------------------------------------------------------------
732 /* Looks for a word in a list of words - for ParseStatus */
733 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
735 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
737 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
746 // ListParser::Step - Move to the next section in the file /*{{{*/
747 // ---------------------------------------------------------------------
748 /* This has to be carefull to only process the correct architecture */
749 bool debListParser::Step()
751 iOffset
= Tags
.Offset();
752 while (Tags
.Step(Section
) == true)
754 /* See if this is the correct Architecture, if it isn't then we
755 drop the whole section. A missing arch tag only happens (in theory)
756 inside the Status file, so that is a positive return */
757 string
const Architecture
= Section
.FindS("Architecture");
758 if (Architecture
.empty() == true)
761 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
763 if (APT::Configuration::checkArchitecture(Architecture
) == true)
768 if (Architecture
== Arch
)
771 if (Architecture
== "all")
775 iOffset
= Tags
.Offset();
780 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
781 // ---------------------------------------------------------------------
783 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
784 FileFd
&File
, string component
)
786 // apt-secure does no longer download individual (per-section) Release
787 // file. to provide Component pinning we use the section name now
788 FileI
->Component
= WriteUniqString(component
);
790 FILE* release
= fdopen(dup(File
.Fd()), "r");
795 bool gpgClose
= false;
796 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
801 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
);
802 if (buffer
[len
] == '\0')
805 // only evalute the first GPG section
806 if (strncmp("-----", buffer
, 5) == 0)
808 if (gpgClose
== true)
814 // seperate the tag from the data
815 for (; buffer
[len
] != ':' && buffer
[len
] != '\0'; ++len
);
816 if (buffer
[len
] == '\0')
818 char* dataStart
= buffer
+ len
;
819 for (++dataStart
; *dataStart
== ' '; ++dataStart
);
820 char* dataEnd
= dataStart
;
821 for (++dataEnd
; *dataEnd
!= '\0'; ++dataEnd
);
823 // which datastorage need to be updated
824 map_ptrloc
* writeTo
= NULL
;
825 if (buffer
[0] == ' ')
827 #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
828 APT_PARSER_WRITETO(FileI
->Archive
, "Suite")
829 APT_PARSER_WRITETO(FileI
->Component
, "Component")
830 APT_PARSER_WRITETO(FileI
->Version
, "Version")
831 APT_PARSER_WRITETO(FileI
->Origin
, "Origin")
832 APT_PARSER_WRITETO(FileI
->Codename
, "Codename")
833 APT_PARSER_WRITETO(FileI
->Label
, "Label")
834 #undef APT_PARSER_WRITETO
835 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
836 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, dataEnd-1);
837 APT_PARSER_FLAGIT(NotAutomatic
)
838 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
839 #undef APT_PARSER_FLAGIT
841 // load all data from the line and save it
844 data
.append(dataStart
, dataEnd
);
845 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
847 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
851 if (strlen(buffer
) != sizeof(buffer
) - 1)
857 // remove spaces and stuff from the end of the data line
858 for (std::string::reverse_iterator s
= data
.rbegin();
859 s
!= data
.rend(); ++s
)
861 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
865 *writeTo
= WriteUniqString(data
);
870 return !_error
->PendingError();
873 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
874 // ---------------------------------------------------------------------
876 unsigned char debListParser::GetPrio(string Str
)
879 if (GrabWord(Str
,PrioList
,Out
) == false)
880 Out
= pkgCache::State::Extra
;