]>
git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
95a2e6d47a19d1a1fe92152f59157eba8214f9d6
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>
30 static debListParser::WordList PrioList
[] = {{"important",pkgCache::State::Important
},
31 {"required",pkgCache::State::Required
},
32 {"standard",pkgCache::State::Standard
},
33 {"optional",pkgCache::State::Optional
},
34 {"extra",pkgCache::State::Extra
},
37 // ListParser::debListParser - Constructor /*{{{*/
38 // ---------------------------------------------------------------------
39 /* Provide an architecture and only this one and "all" will be accepted
40 in Step(), if no Architecture is given we will accept every arch
41 we would accept in general with checkArchitecture() */
42 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
45 this->Arch
= _config
->Find("APT::Architecture");
46 Architectures
= APT::Configuration::getArchitectures();
47 MultiArchEnabled
= Architectures
.size() > 1;
50 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
51 // ---------------------------------------------------------------------
53 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
57 if (Section
.Find(Tag
,Start
,Stop
) == false)
59 return WriteUniqString(Start
,Stop
- Start
);
62 // ListParser::Package - Return the package name /*{{{*/
63 // ---------------------------------------------------------------------
64 /* This is to return the name of the package this section describes */
65 string
debListParser::Package() {
66 string
const Result
= Section
.FindS("Package");
67 if(unlikely(Result
.empty() == true))
68 _error
->Error("Encountered a section with no Package: header");
72 // ListParser::Architecture - Return the package arch /*{{{*/
73 // ---------------------------------------------------------------------
74 /* This will return the Architecture of the package this section describes */
75 string
debListParser::Architecture() {
76 std::string
const Arch
= Section
.FindS("Architecture");
77 if (Arch
.empty() == true)
78 return _config
->Find("APT::Architecture");
82 // ListParser::ArchitectureAll /*{{{*/
83 // ---------------------------------------------------------------------
85 bool debListParser::ArchitectureAll() {
86 return Section
.FindS("Architecture") == "all";
89 // ListParser::Version - Return the version string /*{{{*/
90 // ---------------------------------------------------------------------
91 /* This is to return the string describing the version in debian form,
92 epoch:upstream-release. If this returns the blank string then the
93 entry is assumed to only describe package properties */
94 string
debListParser::Version()
96 return Section
.FindS("Version");
99 // ListParser::NewVersion - Fill in the version structure /*{{{*/
100 // ---------------------------------------------------------------------
102 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
105 Ver
->Section
= UniqFindTagWrite("Section");
108 string
const MultiArch
= Section
.FindS("Multi-Arch");
109 if (MultiArch
.empty() == true)
110 Ver
->MultiArch
= pkgCache::Version::None
;
111 else if (MultiArch
== "same") {
113 if (ArchitectureAll() == true)
115 /* Arch all packages can't be Multi-Arch: same */
116 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
117 Section
.FindS("Package").c_str());
118 Ver
->MultiArch
= pkgCache::Version::None
;
121 Ver
->MultiArch
= pkgCache::Version::Same
;
123 else if (MultiArch
== "foreign")
124 Ver
->MultiArch
= pkgCache::Version::Foreign
;
125 else if (MultiArch
== "allowed")
126 Ver
->MultiArch
= pkgCache::Version::Allowed
;
129 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
130 MultiArch
.c_str(), Section
.FindS("Package").c_str());
131 Ver
->MultiArch
= pkgCache::Version::None
;
134 if (ArchitectureAll() == true)
135 Ver
->MultiArch
|= pkgCache::Version::All
;
138 Ver
->Size
= Section
.FindULL("Size");
139 // Unpacked Size (in K)
140 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
141 Ver
->InstalledSize
*= 1024;
146 if (Section
.Find("Priority",Start
,Stop
) == true)
148 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
149 Ver
->Priority
= pkgCache::State::Extra
;
152 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
154 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
156 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
158 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
160 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
162 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
164 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
166 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
170 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
173 if (ParseProvides(Ver
) == false)
179 // ListParser::Description - Return the description string /*{{{*/
180 // ---------------------------------------------------------------------
181 /* This is to return the string describing the package in debian
182 form. If this returns the blank string then the entry is assumed to
183 only describe package properties */
184 string
debListParser::Description()
186 string
const lang
= DescriptionLanguage();
188 return Section
.FindS("Description");
190 return Section
.FindS(string("Description-").append(lang
).c_str());
193 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
194 // ---------------------------------------------------------------------
195 /* This is to return the string describing the language of
196 description. If this returns the blank string then the entry is
197 assumed to describe original description. */
198 string
debListParser::DescriptionLanguage()
200 if (Section
.FindS("Description").empty() == false)
203 std::vector
<string
> const lang
= APT::Configuration::getLanguages(true);
204 for (std::vector
<string
>::const_iterator l
= lang
.begin();
205 l
!= lang
.end(); ++l
)
206 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
212 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
213 // ---------------------------------------------------------------------
214 /* This is to return the md5 string to allow the check if it is the right
215 description. If no Description-md5 is found in the section it will be
218 MD5SumValue
debListParser::Description_md5()
220 string value
= Section
.FindS("Description-md5");
225 md5
.Add((Description() + "\n").c_str());
228 return MD5SumValue(value
);
231 // ListParser::UsePackage - Update a package structure /*{{{*/
232 // ---------------------------------------------------------------------
233 /* This is called to update the package with any new information
234 that might be found in the section */
235 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
236 pkgCache::VerIterator
&Ver
)
238 if (Pkg
->Section
== 0)
239 Pkg
->Section
= UniqFindTagWrite("Section");
241 // Packages which are not from the "native" arch doesn't get the essential flag
242 // in the default "native" mode - it is also possible to mark "all" or "none".
243 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
244 string
const static myArch
= _config
->Find("APT::Architecture");
245 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "native");
246 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
248 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
250 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
253 if (strcmp(Pkg
.Name(),"apt") == 0)
254 Pkg
->Flags
|= pkgCache::Flag::Important
;
256 if (ParseStatus(Pkg
,Ver
) == false)
261 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
262 // ---------------------------------------------------------------------
264 unsigned short debListParser::VersionHash()
266 const char *Sections
[] ={"Installed-Size",
274 unsigned long Result
= INIT_FCS
;
276 for (const char **I
= Sections
; *I
!= 0; I
++)
280 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
283 /* Strip out any spaces from the text, this undoes dpkgs reformatting
284 of certain fields. dpkg also has the rather interesting notion of
285 reformatting depends operators < -> <= */
287 for (; Start
!= End
; Start
++)
289 if (isspace(*Start
) == 0)
290 *J
++ = tolower_ascii(*Start
);
291 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
293 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
297 Result
= AddCRC16(Result
,S
,J
- S
);
303 // ListParser::ParseStatus - Parse the status field /*{{{*/
304 // ---------------------------------------------------------------------
305 /* Status lines are of the form,
306 Status: want flag status
307 want = unknown, install, hold, deinstall, purge
308 flag = ok, reinstreq, hold, hold-reinstreq
309 status = not-installed, unpacked, half-configured,
310 half-installed, config-files, post-inst-failed,
311 removal-failed, installed
313 Some of the above are obsolete (I think?) flag = hold-* and
314 status = post-inst-failed, removal-failed at least.
316 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
317 pkgCache::VerIterator
&Ver
)
321 if (Section
.Find("Status",Start
,Stop
) == false)
324 // UsePackage() is responsible for setting the flag in the default case
325 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
326 if (essential
== true &&
327 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
330 // Isolate the first word
331 const char *I
= Start
;
332 for(; I
< Stop
&& *I
!= ' '; I
++);
333 if (I
>= Stop
|| *I
!= ' ')
334 return _error
->Error("Malformed Status line");
336 // Process the want field
337 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
338 {"install",pkgCache::State::Install
},
339 {"hold",pkgCache::State::Hold
},
340 {"deinstall",pkgCache::State::DeInstall
},
341 {"purge",pkgCache::State::Purge
},
343 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
344 return _error
->Error("Malformed 1st word in the Status line");
346 // Isloate the next word
349 for(; I
< Stop
&& *I
!= ' '; I
++);
350 if (I
>= Stop
|| *I
!= ' ')
351 return _error
->Error("Malformed status line, no 2nd word");
353 // Process the flag field
354 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
355 {"reinstreq",pkgCache::State::ReInstReq
},
356 {"hold",pkgCache::State::HoldInst
},
357 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
359 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
360 return _error
->Error("Malformed 2nd word in the Status line");
362 // Isloate the last word
365 for(; I
< Stop
&& *I
!= ' '; I
++);
367 return _error
->Error("Malformed Status line, no 3rd word");
369 // Process the flag field
370 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
371 {"unpacked",pkgCache::State::UnPacked
},
372 {"half-configured",pkgCache::State::HalfConfigured
},
373 {"installed",pkgCache::State::Installed
},
374 {"half-installed",pkgCache::State::HalfInstalled
},
375 {"config-files",pkgCache::State::ConfigFiles
},
376 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
377 {"triggers-pending",pkgCache::State::TriggersPending
},
378 {"post-inst-failed",pkgCache::State::HalfConfigured
},
379 {"removal-failed",pkgCache::State::HalfInstalled
},
381 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
382 return _error
->Error("Malformed 3rd word in the Status line");
384 /* A Status line marks the package as indicating the current
385 version as well. Only if it is actually installed.. Otherwise
386 the interesting dpkg handling of the status file creates bogus
388 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
389 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
391 if (Ver
.end() == true)
392 _error
->Warning("Encountered status field in a non-version description");
394 Pkg
->CurrentVer
= Ver
.Index();
400 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
402 // Determine the operator
410 Op
= pkgCache::Dep::LessEq
;
417 Op
= pkgCache::Dep::Less
;
421 // < is the same as <= and << is really Cs < for some reason
422 Op
= pkgCache::Dep::LessEq
;
430 Op
= pkgCache::Dep::GreaterEq
;
437 Op
= pkgCache::Dep::Greater
;
441 // > is the same as >= and >> is really Cs > for some reason
442 Op
= pkgCache::Dep::GreaterEq
;
446 Op
= pkgCache::Dep::Equals
;
450 // HACK around bad package definitions
452 Op
= pkgCache::Dep::Equals
;
461 * The complete architecture, consisting of <kernel>-<cpu>.
463 static string
CompleteArch(std::string
const &arch
) {
464 if (arch
== "armel") return "linux-arm";
465 if (arch
== "armhf") return "linux-arm";
466 if (arch
== "lpia") return "linux-i386";
467 if (arch
== "powerpcspe") return "linux-powerpc";
468 if (arch
== "uclibc-linux-armel") return "linux-arm";
469 if (arch
== "uclinux-armel") return "uclinux-arm";
471 return (arch
.find("-") != string::npos
) ? arch
: "linux-" + arch
;
474 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
475 // ---------------------------------------------------------------------
476 /* This parses the dependency elements out of a standard string in place,
478 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
479 string
&Package
,string
&Ver
,
480 unsigned int &Op
, bool const &ParseArchFlags
,
481 bool const &StripMultiArch
)
483 // Strip off leading space
484 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
486 // Parse off the package name
487 const char *I
= Start
;
488 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
489 *I
!= ',' && *I
!= '|' && *I
!= '[' && *I
!= ']'; I
++);
492 if (I
!= Stop
&& *I
== ')')
498 // Stash the package name
499 Package
.assign(Start
,I
- Start
);
501 // We don't want to confuse library users which can't handle MultiArch
502 string
const arch
= _config
->Find("APT::Architecture");
503 if (StripMultiArch
== true) {
504 size_t const found
= Package
.rfind(':');
505 if (found
!= string::npos
&&
506 (strcmp(Package
.c_str() + found
, ":any") == 0 ||
507 strcmp(Package
.c_str() + found
, ":native") == 0 ||
508 strcmp(Package
.c_str() + found
+ 1, arch
.c_str()) == 0))
509 Package
= Package
.substr(0,found
);
512 // Skip white space to the '('
513 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
516 if (I
!= Stop
&& *I
== '(')
519 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
522 I
= ConvertRelation(I
,Op
);
525 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
527 for (;I
!= Stop
&& *I
!= ')'; I
++);
528 if (I
== Stop
|| Start
== I
)
531 // Skip trailing whitespace
533 for (; End
> Start
&& isspace(End
[-1]); End
--);
535 Ver
.assign(Start
,End
-Start
);
541 Op
= pkgCache::Dep::NoOp
;
545 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
547 if (ParseArchFlags
== true)
549 string completeArch
= CompleteArch(arch
);
551 // Parse an architecture
552 if (I
!= Stop
&& *I
== '[')
561 bool NegArch
= false;
564 // look for whitespace or ending ']'
565 while (End
!= Stop
&& !isspace(*End
) && *End
!= ']')
577 if (stringcmp(arch
,I
,End
) == 0) {
580 std::string wildcard
= SubstVar(string(I
, End
), "any", "*");
581 if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0)
591 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
598 Package
= ""; /* not for this arch */
602 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
605 if (I
!= Stop
&& *I
== '|')
606 Op
|= pkgCache::Dep::Or
;
608 if (I
== Stop
|| *I
== ',' || *I
== '|')
611 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
618 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
619 // ---------------------------------------------------------------------
620 /* This is the higher level depends parser. It takes a tag and generates
621 a complete depends tree for the given version. */
622 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
623 const char *Tag
,unsigned int Type
)
627 if (Section
.Find(Tag
,Start
,Stop
) == false)
631 string
const pkgArch
= Ver
.Arch();
637 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
);
639 return _error
->Error("Problem parsing dependency %s",Tag
);
641 if (MultiArchEnabled
== true &&
642 (Type
== pkgCache::Dep::Conflicts
||
643 Type
== pkgCache::Dep::DpkgBreaks
||
644 Type
== pkgCache::Dep::Replaces
))
646 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
647 a
!= Architectures
.end(); ++a
)
648 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
651 else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
659 // ListParser::ParseProvides - Parse the provides list /*{{{*/
660 // ---------------------------------------------------------------------
662 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
666 if (Section
.Find("Provides",Start
,Stop
) == true)
670 string
const Arch
= Ver
.Arch();
675 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
677 return _error
->Error("Problem parsing Provides line");
678 if (Op
!= pkgCache::Dep::NoOp
) {
679 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
681 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
690 if (MultiArchEnabled
== false)
692 else if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
694 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
695 return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr());
697 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
698 return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr());
703 // ListParser::NewProvides - add provides for all architectures /*{{{*/
704 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator
&Ver
, string
const &Package
,
705 string
const &Version
) {
706 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
707 a
!= Architectures
.end(); ++a
)
709 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
715 // ListParser::GrabWord - Matches a word and returns /*{{{*/
716 // ---------------------------------------------------------------------
717 /* Looks for a word in a list of words - for ParseStatus */
718 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
720 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
722 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
731 // ListParser::Step - Move to the next section in the file /*{{{*/
732 // ---------------------------------------------------------------------
733 /* This has to be carefull to only process the correct architecture */
734 bool debListParser::Step()
736 iOffset
= Tags
.Offset();
737 while (Tags
.Step(Section
) == true)
739 /* See if this is the correct Architecture, if it isn't then we
740 drop the whole section. A missing arch tag only happens (in theory)
741 inside the Status file, so that is a positive return */
742 string
const Architecture
= Section
.FindS("Architecture");
743 if (Architecture
.empty() == true)
746 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
748 if (APT::Configuration::checkArchitecture(Architecture
) == true)
753 if (Architecture
== Arch
)
756 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
760 iOffset
= Tags
.Offset();
765 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
766 // ---------------------------------------------------------------------
768 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
769 FileFd
&File
, string component
)
771 // apt-secure does no longer download individual (per-section) Release
772 // file. to provide Component pinning we use the section name now
773 FileI
->Component
= WriteUniqString(component
);
775 FILE* release
= fdopen(dup(File
.Fd()), "r");
780 bool gpgClose
= false;
781 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
786 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
)
789 if (buffer
[len
] == '\0')
792 // only evalute the first GPG section
793 if (strncmp("-----", buffer
, 5) == 0)
795 if (gpgClose
== true)
801 // seperate the tag from the data
802 for (; buffer
[len
] != ':' && buffer
[len
] != '\0'; ++len
)
805 if (buffer
[len
] == '\0')
807 char* dataStart
= buffer
+ len
;
808 for (++dataStart
; *dataStart
== ' '; ++dataStart
)
811 char* dataEnd
= dataStart
;
812 for (++dataEnd
; *dataEnd
!= '\0'; ++dataEnd
)
815 // The last char should be a newline, but we can never be sure: #633350
816 char* lineEnd
= dataEnd
;
817 for (--lineEnd
; *lineEnd
== '\r' || *lineEnd
== '\n'; --lineEnd
)
822 // which datastorage need to be updated
823 map_ptrloc
* writeTo
= NULL
;
824 if (buffer
[0] == ' ')
826 #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
827 APT_PARSER_WRITETO(FileI
->Archive
, "Suite")
828 APT_PARSER_WRITETO(FileI
->Component
, "Component")
829 APT_PARSER_WRITETO(FileI
->Version
, "Version")
830 APT_PARSER_WRITETO(FileI
->Origin
, "Origin")
831 APT_PARSER_WRITETO(FileI
->Codename
, "Codename")
832 APT_PARSER_WRITETO(FileI
->Label
, "Label")
833 #undef APT_PARSER_WRITETO
834 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
835 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd);
836 APT_PARSER_FLAGIT(NotAutomatic
)
837 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
838 #undef APT_PARSER_FLAGIT
840 // load all data from the line and save it
843 data
.append(dataStart
, dataEnd
);
844 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
846 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
850 if (strlen(buffer
) != sizeof(buffer
) - 1)
856 // remove spaces and stuff from the end of the data line
857 for (std::string::reverse_iterator s
= data
.rbegin();
858 s
!= data
.rend(); ++s
)
860 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
864 *writeTo
= WriteUniqString(data
);
869 return !_error
->PendingError();
872 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
873 // ---------------------------------------------------------------------
875 unsigned char debListParser::GetPrio(string Str
)
878 if (GrabWord(Str
,PrioList
,Out
) == false)
879 Out
= pkgCache::State::Extra
;