]>
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 /*{{{*/
15 #include <apt-pkg/deblistparser.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/configuration.h>
18 #include <apt-pkg/aptconfiguration.h>
19 #include <apt-pkg/strutl.h>
20 #include <apt-pkg/crc-16.h>
21 #include <apt-pkg/md5.h>
22 #include <apt-pkg/macros.h>
28 static debListParser::WordList PrioList
[] = {{"important",pkgCache::State::Important
},
29 {"required",pkgCache::State::Required
},
30 {"standard",pkgCache::State::Standard
},
31 {"optional",pkgCache::State::Optional
},
32 {"extra",pkgCache::State::Extra
},
35 // ListParser::debListParser - Constructor /*{{{*/
36 // ---------------------------------------------------------------------
37 /* Provide an architecture and only this one and "all" will be accepted
38 in Step(), if no Architecture is given we will accept every arch
39 we would accept in general with checkArchitecture() */
40 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
43 this->Arch
= _config
->Find("APT::Architecture");
44 Architectures
= APT::Configuration::getArchitectures();
45 MultiArchEnabled
= Architectures
.size() > 1;
48 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
49 // ---------------------------------------------------------------------
51 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
55 if (Section
.Find(Tag
,Start
,Stop
) == false)
57 return WriteUniqString(Start
,Stop
- Start
);
60 // ListParser::Package - Return the package name /*{{{*/
61 // ---------------------------------------------------------------------
62 /* This is to return the name of the package this section describes */
63 string
debListParser::Package() {
64 string
const Result
= Section
.FindS("Package");
65 if(unlikely(Result
.empty() == true))
66 _error
->Error("Encountered a section with no Package: header");
70 // ListParser::Architecture - Return the package arch /*{{{*/
71 // ---------------------------------------------------------------------
72 /* This will return the Architecture of the package this section describes */
73 string
debListParser::Architecture() {
74 std::string
const Arch
= Section
.FindS("Architecture");
75 if (Arch
.empty() == true)
76 return _config
->Find("APT::Architecture");
80 // ListParser::ArchitectureAll /*{{{*/
81 // ---------------------------------------------------------------------
83 bool debListParser::ArchitectureAll() {
84 return Section
.FindS("Architecture") == "all";
87 // ListParser::Version - Return the version string /*{{{*/
88 // ---------------------------------------------------------------------
89 /* This is to return the string describing the version in debian form,
90 epoch:upstream-release. If this returns the blank string then the
91 entry is assumed to only describe package properties */
92 string
debListParser::Version()
94 return Section
.FindS("Version");
97 // ListParser::NewVersion - Fill in the version structure /*{{{*/
98 // ---------------------------------------------------------------------
100 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
103 Ver
->Section
= UniqFindTagWrite("Section");
106 string
const MultiArch
= Section
.FindS("Multi-Arch");
107 if (MultiArch
.empty() == true)
108 Ver
->MultiArch
= pkgCache::Version::None
;
109 else if (MultiArch
== "same") {
111 if (ArchitectureAll() == true)
113 /* Arch all packages can't be Multi-Arch: same */
114 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
115 Section
.FindS("Package").c_str());
116 Ver
->MultiArch
= pkgCache::Version::None
;
119 Ver
->MultiArch
= pkgCache::Version::Same
;
121 else if (MultiArch
== "foreign")
122 Ver
->MultiArch
= pkgCache::Version::Foreign
;
123 else if (MultiArch
== "allowed")
124 Ver
->MultiArch
= pkgCache::Version::Allowed
;
127 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
128 MultiArch
.c_str(), Section
.FindS("Package").c_str());
129 Ver
->MultiArch
= pkgCache::Version::None
;
132 if (ArchitectureAll() == true)
133 Ver
->MultiArch
|= pkgCache::Version::All
;
136 Ver
->Size
= Section
.FindULL("Size");
137 // Unpacked Size (in K)
138 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
139 Ver
->InstalledSize
*= 1024;
144 if (Section
.Find("Priority",Start
,Stop
) == true)
146 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
147 Ver
->Priority
= pkgCache::State::Extra
;
150 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
152 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
154 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
156 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
158 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
160 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
162 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
164 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
168 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
171 if (ParseProvides(Ver
) == false)
177 // ListParser::Description - Return the description string /*{{{*/
178 // ---------------------------------------------------------------------
179 /* This is to return the string describing the package in debian
180 form. If this returns the blank string then the entry is assumed to
181 only describe package properties */
182 string
debListParser::Description()
184 string
const lang
= DescriptionLanguage();
186 return Section
.FindS("Description");
188 return Section
.FindS(string("Description-").append(lang
).c_str());
191 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
192 // ---------------------------------------------------------------------
193 /* This is to return the string describing the language of
194 description. If this returns the blank string then the entry is
195 assumed to describe original description. */
196 string
debListParser::DescriptionLanguage()
198 if (Section
.FindS("Description").empty() == false)
201 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
202 for (std::vector
<string
>::const_iterator l
= lang
.begin();
203 l
!= lang
.end(); ++l
)
204 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
210 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
211 // ---------------------------------------------------------------------
212 /* This is to return the md5 string to allow the check if it is the right
213 description. If no Description-md5 is found in the section it will be
216 MD5SumValue
debListParser::Description_md5()
218 string value
= Section
.FindS("Description-md5");
223 md5
.Add((Description() + "\n").c_str());
226 return MD5SumValue(value
);
229 // ListParser::UsePackage - Update a package structure /*{{{*/
230 // ---------------------------------------------------------------------
231 /* This is called to update the package with any new information
232 that might be found in the section */
233 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
234 pkgCache::VerIterator
&Ver
)
236 if (Pkg
->Section
== 0)
237 Pkg
->Section
= UniqFindTagWrite("Section");
239 // Packages which are not from the "native" arch doesn't get the essential flag
240 // in the default "native" mode - it is also possible to mark "all" or "none".
241 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
242 string
const static myArch
= _config
->Find("APT::Architecture");
243 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "native");
244 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
246 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
248 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
251 if (strcmp(Pkg
.Name(),"apt") == 0)
252 Pkg
->Flags
|= pkgCache::Flag::Important
;
254 if (ParseStatus(Pkg
,Ver
) == false)
259 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
260 // ---------------------------------------------------------------------
262 unsigned short debListParser::VersionHash()
264 const char *Sections
[] ={"Installed-Size",
272 unsigned long Result
= INIT_FCS
;
274 for (const char **I
= Sections
; *I
!= 0; I
++)
278 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
281 /* Strip out any spaces from the text, this undoes dpkgs reformatting
282 of certain fields. dpkg also has the rather interesting notion of
283 reformatting depends operators < -> <= */
285 for (; Start
!= End
; Start
++)
287 if (isspace(*Start
) == 0)
288 *J
++ = tolower_ascii(*Start
);
289 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
291 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
295 Result
= AddCRC16(Result
,S
,J
- S
);
301 // ListParser::ParseStatus - Parse the status field /*{{{*/
302 // ---------------------------------------------------------------------
303 /* Status lines are of the form,
304 Status: want flag status
305 want = unknown, install, hold, deinstall, purge
306 flag = ok, reinstreq, hold, hold-reinstreq
307 status = not-installed, unpacked, half-configured,
308 half-installed, config-files, post-inst-failed,
309 removal-failed, installed
311 Some of the above are obsolete (I think?) flag = hold-* and
312 status = post-inst-failed, removal-failed at least.
314 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
315 pkgCache::VerIterator
&Ver
)
319 if (Section
.Find("Status",Start
,Stop
) == false)
322 // UsePackage() is responsible for setting the flag in the default case
323 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
324 if (essential
== true &&
325 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
328 // Isolate the first word
329 const char *I
= Start
;
330 for(; I
< Stop
&& *I
!= ' '; I
++);
331 if (I
>= Stop
|| *I
!= ' ')
332 return _error
->Error("Malformed Status line");
334 // Process the want field
335 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
336 {"install",pkgCache::State::Install
},
337 {"hold",pkgCache::State::Hold
},
338 {"deinstall",pkgCache::State::DeInstall
},
339 {"purge",pkgCache::State::Purge
},
341 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
342 return _error
->Error("Malformed 1st word in the Status line");
344 // Isloate the next word
347 for(; I
< Stop
&& *I
!= ' '; I
++);
348 if (I
>= Stop
|| *I
!= ' ')
349 return _error
->Error("Malformed status line, no 2nd word");
351 // Process the flag field
352 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
353 {"reinstreq",pkgCache::State::ReInstReq
},
354 {"hold",pkgCache::State::HoldInst
},
355 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
357 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
358 return _error
->Error("Malformed 2nd word in the Status line");
360 // Isloate the last word
363 for(; I
< Stop
&& *I
!= ' '; I
++);
365 return _error
->Error("Malformed Status line, no 3rd word");
367 // Process the flag field
368 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
369 {"unpacked",pkgCache::State::UnPacked
},
370 {"half-configured",pkgCache::State::HalfConfigured
},
371 {"installed",pkgCache::State::Installed
},
372 {"half-installed",pkgCache::State::HalfInstalled
},
373 {"config-files",pkgCache::State::ConfigFiles
},
374 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
375 {"triggers-pending",pkgCache::State::TriggersPending
},
376 {"post-inst-failed",pkgCache::State::HalfConfigured
},
377 {"removal-failed",pkgCache::State::HalfInstalled
},
379 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
380 return _error
->Error("Malformed 3rd word in the Status line");
382 /* A Status line marks the package as indicating the current
383 version as well. Only if it is actually installed.. Otherwise
384 the interesting dpkg handling of the status file creates bogus
386 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
387 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
389 if (Ver
.end() == true)
390 _error
->Warning("Encountered status field in a non-version description");
392 Pkg
->CurrentVer
= Ver
.Index();
398 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
400 // Determine the operator
408 Op
= pkgCache::Dep::LessEq
;
415 Op
= pkgCache::Dep::Less
;
419 // < is the same as <= and << is really Cs < for some reason
420 Op
= pkgCache::Dep::LessEq
;
428 Op
= pkgCache::Dep::GreaterEq
;
435 Op
= pkgCache::Dep::Greater
;
439 // > is the same as >= and >> is really Cs > for some reason
440 Op
= pkgCache::Dep::GreaterEq
;
444 Op
= pkgCache::Dep::Equals
;
448 // HACK around bad package definitions
450 Op
= pkgCache::Dep::Equals
;
459 * The complete architecture, consisting of <kernel>-<cpu>.
461 static string
CompleteArch(std::string
const &arch
) {
462 if (arch
== "armel") return "linux-arm";
463 if (arch
== "armhf") return "linux-arm";
464 if (arch
== "lpia") return "linux-i386";
465 if (arch
== "powerpcspe") return "linux-powerpc";
466 if (arch
== "uclibc-linux-armel") return "linux-arm";
467 if (arch
== "uclinux-armel") return "uclinux-arm";
469 return (arch
.find("-") != string::npos
) ? arch
: "linux-" + arch
;
472 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
473 // ---------------------------------------------------------------------
474 /* This parses the dependency elements out of a standard string in place,
476 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
477 string
&Package
,string
&Ver
,
478 unsigned int &Op
, bool const &ParseArchFlags
,
479 bool const &StripMultiArch
)
481 // Strip off leading space
482 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
484 // Parse off the package name
485 const char *I
= Start
;
486 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
487 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']'; I
++);
490 if (I
!= Stop
&& *I
== ')')
496 // Stash the package name
497 Package
.assign(Start
,I
- Start
);
499 // We don't want to confuse library users which can't handle MultiArch
500 string
const arch
= _config
->Find("APT::Architecture");
501 if (StripMultiArch
== true) {
502 size_t const found
= Package
.rfind(':');
503 if (found
!= string::npos
&&
504 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
505 strcmp(Package
.c_str() + found
, ":native") == 0 ||
506 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
507 Package
= Package
.substr(0,found
);
510 // Skip white space to the '('
511 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
514 if (I
!= Stop
&& *I
== '(')
517 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
520 I
= ConvertRelation(I
,Op
);
523 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
525 for (;I
!= Stop
&& *I
!= ')'; I
++);
526 if (I
== Stop
|| Start
== I
)
529 // Skip trailing whitespace
531 for (; End
> Start
&& isspace(End
[-1]); End
--);
533 Ver
.assign(Start
,End
-Start
);
539 Op
= pkgCache::Dep::NoOp
;
543 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
545 if (ParseArchFlags
== true)
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
) == pkgCache::Version::Allowed
)
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
) == pkgCache::Version::Foreign
)
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
)
787 if (buffer
[len
] == '\0')
790 // only evalute the first GPG section
791 if (strncmp("-----", buffer
, 5) == 0)
793 if (gpgClose
== true)
799 // seperate the tag from the data
800 for (; buffer
[len
] != ':' && buffer
[len
] != '\0'; ++len
)
803 if (buffer
[len
] == '\0')
805 char* dataStart
= buffer
+ len
;
806 for (++dataStart
; *dataStart
== ' '; ++dataStart
)
809 char* dataEnd
= dataStart
;
810 for (++dataEnd
; *dataEnd
!= '\0'; ++dataEnd
)
813 // The last char should be a newline, but we can never be sure: #633350
814 char* lineEnd
= dataEnd
;
815 for (--lineEnd
; *lineEnd
== '\r' || *lineEnd
== '\n'; --lineEnd
)
820 // which datastorage need to be updated
821 map_ptrloc
* writeTo
= NULL
;
822 if (buffer
[0] == ' ')
824 #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
825 APT_PARSER_WRITETO(FileI
->Archive
, "Suite")
826 APT_PARSER_WRITETO(FileI
->Component
, "Component")
827 APT_PARSER_WRITETO(FileI
->Version
, "Version")
828 APT_PARSER_WRITETO(FileI
->Origin
, "Origin")
829 APT_PARSER_WRITETO(FileI
->Codename
, "Codename")
830 APT_PARSER_WRITETO(FileI
->Label
, "Label")
831 #undef APT_PARSER_WRITETO
832 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
833 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd);
834 APT_PARSER_FLAGIT(NotAutomatic
)
835 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
836 #undef APT_PARSER_FLAGIT
838 // load all data from the line and save it
841 data
.append(dataStart
, dataEnd
);
842 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
844 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
848 if (strlen(buffer
) != sizeof(buffer
) - 1)
854 // remove spaces and stuff from the end of the data line
855 for (std::string::reverse_iterator s
= data
.rbegin();
856 s
!= data
.rend(); ++s
)
858 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
862 *writeTo
= WriteUniqString(data
);
867 return !_error
->PendingError();
870 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
871 // ---------------------------------------------------------------------
873 unsigned char debListParser::GetPrio(string Str
)
876 if (GrabWord(Str
,PrioList
,Out
) == false)
877 Out
= pkgCache::State::Extra
;