]>
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 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
const &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 string
const arch
= _config
->Find("APT::Architecture");
499 if (StripMultiArch
== true) {
500 size_t const found
= Package
.rfind(':');
501 if (found
!= string::npos
&&
502 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
503 strcmp(Package
.c_str() + found
, ":native") == 0 ||
504 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
505 Package
= Package
.substr(0,found
);
508 // Skip white space to the '('
509 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
512 if (I
!= Stop
&& *I
== '(')
515 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
518 I
= ConvertRelation(I
,Op
);
521 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
523 for (;I
!= Stop
&& *I
!= ')'; I
++);
524 if (I
== Stop
|| Start
== I
)
527 // Skip trailing whitespace
529 for (; End
> Start
&& isspace(End
[-1]); End
--);
531 Ver
.assign(Start
,End
-Start
);
537 Op
= pkgCache::Dep::NoOp
;
541 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
543 if (ParseArchFlags
== true)
545 string completeArch
= CompleteArch(arch
);
547 // Parse an architecture
548 if (I
!= Stop
&& *I
== '[')
557 bool NegArch
= false;
560 // look for whitespace or ending ']'
561 while (End
!= Stop
&& !isspace(*End
) && *End
!= ']')
573 if (stringcmp(arch
,I
,End
) == 0) {
576 std::string wildcard
= SubstVar(string(I
, End
), "any", "*");
577 if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0)
587 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
594 Package
= ""; /* not for this arch */
598 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
601 if (I
!= Stop
&& *I
== '|')
602 Op
|= pkgCache::Dep::Or
;
604 if (I
== Stop
|| *I
== ',' || *I
== '|')
607 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
614 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
615 // ---------------------------------------------------------------------
616 /* This is the higher level depends parser. It takes a tag and generates
617 a complete depends tree for the given version. */
618 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
619 const char *Tag
,unsigned int Type
)
623 if (Section
.Find(Tag
,Start
,Stop
) == false)
627 string
const pkgArch
= Ver
.Arch();
633 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
);
635 return _error
->Error("Problem parsing dependency %s",Tag
);
637 if (MultiArchEnabled
== true &&
638 (Type
== pkgCache::Dep::Conflicts
||
639 Type
== pkgCache::Dep::DpkgBreaks
||
640 Type
== pkgCache::Dep::Replaces
))
642 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
643 a
!= Architectures
.end(); ++a
)
644 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
647 else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
655 // ListParser::ParseProvides - Parse the provides list /*{{{*/
656 // ---------------------------------------------------------------------
658 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
662 if (Section
.Find("Provides",Start
,Stop
) == true)
666 string
const Arch
= Ver
.Arch();
671 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
673 return _error
->Error("Problem parsing Provides line");
674 if (Op
!= pkgCache::Dep::NoOp
) {
675 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
677 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
686 if (MultiArchEnabled
== false)
688 else if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
690 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
691 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
693 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
694 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
699 // ListParser::NewProvides - add provides for all architectures /*{{{*/
700 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
701 string
const &Version
) {
702 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
703 a
!= Architectures
.end(); ++a
)
705 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
711 // ListParser::GrabWord - Matches a word and returns /*{{{*/
712 // ---------------------------------------------------------------------
713 /* Looks for a word in a list of words - for ParseStatus */
714 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
716 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
718 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
727 // ListParser::Step - Move to the next section in the file /*{{{*/
728 // ---------------------------------------------------------------------
729 /* This has to be carefull to only process the correct architecture */
730 bool debListParser::Step()
732 iOffset
= Tags
.Offset();
733 while (Tags
.Step(Section
) == true)
735 /* See if this is the correct Architecture, if it isn't then we
736 drop the whole section. A missing arch tag only happens (in theory)
737 inside the Status file, so that is a positive return */
738 string
const Architecture
= Section
.FindS("Architecture");
739 if (Architecture
.empty() == true)
742 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
744 if (APT::Configuration::checkArchitecture(Architecture
) == true)
749 if (Architecture
== Arch
)
752 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
756 iOffset
= Tags
.Offset();
761 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
762 // ---------------------------------------------------------------------
764 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
765 FileFd
&File
, string component
)
767 // apt-secure does no longer download individual (per-section) Release
768 // file. to provide Component pinning we use the section name now
769 FileI
->Component
= WriteUniqString(component
);
771 FILE* release
= fdopen(dup(File
.Fd()), "r");
776 bool gpgClose
= false;
777 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
782 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
)
801 if (buffer
[len
] == '\0')
803 char* dataStart
= buffer
+ len
;
804 for (++dataStart
; *dataStart
== ' '; ++dataStart
)
807 char* dataEnd
= dataStart
;
808 for (++dataEnd
; *dataEnd
!= '\0'; ++dataEnd
)
811 // The last char should be a newline, but we can never be sure: #633350
812 char* lineEnd
= dataEnd
;
813 for (--lineEnd
; *lineEnd
== '\r' || *lineEnd
== '\n'; --lineEnd
)
818 // which datastorage need to be updated
819 map_ptrloc
* writeTo
= NULL
;
820 if (buffer
[0] == ' ')
822 #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
823 APT_PARSER_WRITETO(FileI
->Archive
, "Suite")
824 APT_PARSER_WRITETO(FileI
->Component
, "Component")
825 APT_PARSER_WRITETO(FileI
->Version
, "Version")
826 APT_PARSER_WRITETO(FileI
->Origin
, "Origin")
827 APT_PARSER_WRITETO(FileI
->Codename
, "Codename")
828 APT_PARSER_WRITETO(FileI
->Label
, "Label")
829 #undef APT_PARSER_WRITETO
830 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
831 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd);
832 APT_PARSER_FLAGIT(NotAutomatic
)
833 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
834 #undef APT_PARSER_FLAGIT
836 // load all data from the line and save it
839 data
.append(dataStart
, dataEnd
);
840 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
842 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
846 if (strlen(buffer
) != sizeof(buffer
) - 1)
852 // remove spaces and stuff from the end of the data line
853 for (std::string::reverse_iterator s
= data
.rbegin();
854 s
!= data
.rend(); ++s
)
856 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
860 *writeTo
= WriteUniqString(data
);
865 return !_error
->PendingError();
868 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
869 // ---------------------------------------------------------------------
871 unsigned char debListParser::GetPrio(string Str
)
874 if (GrabWord(Str
,PrioList
,Out
) == false)
875 Out
= pkgCache::State::Extra
;