Implement the first step toward Multi-Arch by setting up a Group
[ntk/apt.git] / apt-pkg / deb / deblistparser.cc
CommitLineData
f55a958f
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b3d44315 3// $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $
f55a958f
AL
4/* ######################################################################
5
6 Package Cache Generator - Generator for the cache structure.
7
8 This builds the cache structure from the abstract package list parser.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
094a497d
AL
13#include <apt-pkg/deblistparser.h>
14#include <apt-pkg/error.h>
15#include <apt-pkg/configuration.h>
45df0ad2 16#include <apt-pkg/aptconfiguration.h>
cdcc6d34 17#include <apt-pkg/strutl.h>
204fbdcc 18#include <apt-pkg/crc-16.h>
a52f938b 19#include <apt-pkg/md5.h>
9c14e3d6 20
e7b470ee
AL
21#include <ctype.h>
22
f55a958f
AL
23#include <system.h>
24 /*}}}*/
25
b2e465d6
AL
26static 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},
31 {}};
32
f55a958f
AL
33// ListParser::debListParser - Constructor /*{{{*/
34// ---------------------------------------------------------------------
35/* */
b2e465d6 36debListParser::debListParser(FileFd *File) : Tags(File)
f55a958f 37{
ddc1d8d0 38 Arch = _config->Find("APT::architecture");
0149949b
AL
39}
40 /*}}}*/
f55a958f
AL
41// ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
42// ---------------------------------------------------------------------
43/* */
44unsigned long debListParser::UniqFindTagWrite(const char *Tag)
45{
46 const char *Start;
47 const char *Stop;
48 if (Section.Find(Tag,Start,Stop) == false)
49 return 0;
50 return WriteUniqString(Start,Stop - Start);
51}
52 /*}}}*/
f55a958f
AL
53// ListParser::Package - Return the package name /*{{{*/
54// ---------------------------------------------------------------------
55/* This is to return the name of the package this section describes */
5bf15716
DK
56string debListParser::Package() {
57 string const Result = Section.FindS("Package");
58 if(unlikely(Result.empty() == true))
59 _error->Error("Encountered a section with no Package: header");
60 return Result;
61}
62 /*}}}*/
63// ListParser::Architecture - Return the package arch /*{{{*/
64// ---------------------------------------------------------------------
65/* This will return the Architecture of the package this section describes
66 Note that architecture "all" packages will get the architecture of the
67 Packages file parsed here */
68string debListParser::Architecture() {
69 string const Result = Section.FindS("Architecture");
70 if (Result.empty() == true)
71 return Arch;
72 if (Result == "all")
73 return Arch;
74 return Result;
f55a958f
AL
75}
76 /*}}}*/
77// ListParser::Version - Return the version string /*{{{*/
78// ---------------------------------------------------------------------
79/* This is to return the string describing the version in debian form,
80 epoch:upstream-release. If this returns the blank string then the
81 entry is assumed to only describe package properties */
82string debListParser::Version()
83{
b0b4efb9 84 return Section.FindS("Version");
f55a958f
AL
85}
86 /*}}}*/
f55a958f
AL
87// ListParser::NewVersion - Fill in the version structure /*{{{*/
88// ---------------------------------------------------------------------
89/* */
90bool debListParser::NewVersion(pkgCache::VerIterator Ver)
0149949b
AL
91{
92 // Parse the section
b35d2f5f 93 Ver->Section = UniqFindTagWrite("Section");
5bf15716
DK
94
95 // Parse the architecture
96 Ver->Arch = WriteUniqString(Architecture());
97
0149949b 98 // Archive Size
b0b4efb9 99 Ver->Size = (unsigned)Section.FindI("Size");
0149949b
AL
100
101 // Unpacked Size (in K)
b0b4efb9 102 Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
0149949b
AL
103 Ver->InstalledSize *= 1024;
104
105 // Priority
106 const char *Start;
107 const char *Stop;
108 if (Section.Find("Priority",Start,Stop) == true)
b2e465d6
AL
109 {
110 if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
421c8d10 111 Ver->Priority = pkgCache::State::Extra;
0149949b 112 }
dcb79bae 113
6c139d6e 114 if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
dcb79bae 115 return false;
8efa2a3b 116 if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
dcb79bae 117 return false;
6c139d6e 118 if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
dcb79bae 119 return false;
6c139d6e 120 if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
dcb79bae 121 return false;
6c139d6e 122 if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
dcb79bae 123 return false;
308c7d30
IJ
124 if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
125 return false;
f55ece0e 126 if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
dcb79bae 127 return false;
f8ae7e8b 128 if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false)
129 return false;
dcb79bae 130
b2e465d6
AL
131 // Obsolete.
132 if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
133 return false;
134
dcb79bae
AL
135 if (ParseProvides(Ver) == false)
136 return false;
0149949b 137
f55a958f
AL
138 return true;
139}
140 /*}}}*/
a52f938b
OS
141// ListParser::Description - Return the description string /*{{{*/
142// ---------------------------------------------------------------------
143/* This is to return the string describing the package in debian
144 form. If this returns the blank string then the entry is assumed to
145 only describe package properties */
146string debListParser::Description()
147{
45df0ad2
DK
148 string const lang = DescriptionLanguage();
149 if (lang.empty())
a52f938b
OS
150 return Section.FindS("Description");
151 else
45df0ad2 152 return Section.FindS(string("Description-").append(lang).c_str());
a52f938b
OS
153}
154 /*}}}*/
155// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
156// ---------------------------------------------------------------------
157/* This is to return the string describing the language of
158 description. If this returns the blank string then the entry is
159 assumed to describe original description. */
160string debListParser::DescriptionLanguage()
161{
45df0ad2
DK
162 if (Section.FindS("Description").empty() == false)
163 return "";
164
165 std::vector<string> const lang = APT::Configuration::getLanguages();
166 for (std::vector<string>::const_iterator l = lang.begin();
167 l != lang.end(); l++)
168 if (Section.FindS(string("Description-").append(*l).c_str()).empty() == false)
169 return *l;
170
171 return "";
a52f938b
OS
172}
173 /*}}}*/
174// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
175// ---------------------------------------------------------------------
770c32ec
MV
176/* This is to return the md5 string to allow the check if it is the right
177 description. If no Description-md5 is found in the section it will be
178 calculated.
179 */
a52f938b
OS
180MD5SumValue debListParser::Description_md5()
181{
182 string value = Section.FindS("Description-md5");
183
770c32ec
MV
184 if (value.empty())
185 {
a52f938b
OS
186 MD5Summation md5;
187 md5.Add((Description() + "\n").c_str());
188 return md5.Result();
189 } else
190 return MD5SumValue(value);
191}
192 /*}}}*/
f55a958f
AL
193// ListParser::UsePackage - Update a package structure /*{{{*/
194// ---------------------------------------------------------------------
195/* This is called to update the package with any new information
196 that might be found in the section */
197bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
198 pkgCache::VerIterator Ver)
199{
200 if (Pkg->Section == 0)
b35d2f5f 201 Pkg->Section = UniqFindTagWrite("Section");
b0b4efb9 202 if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
f55a958f 203 return false;
138d4b3d 204 if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
f55a958f 205 return false;
138d4b3d
AL
206
207 if (strcmp(Pkg.Name(),"apt") == 0)
208 Pkg->Flags |= pkgCache::Flag::Important;
209
f55a958f
AL
210 if (ParseStatus(Pkg,Ver) == false)
211 return false;
212 return true;
213}
214 /*}}}*/
204fbdcc
AL
215// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
216// ---------------------------------------------------------------------
217/* */
218unsigned short debListParser::VersionHash()
219{
220 const char *Sections[] ={"Installed-Size",
221 "Depends",
222 "Pre-Depends",
f78439bf
AL
223// "Suggests",
224// "Recommends",
204fbdcc 225 "Conflicts",
308c7d30 226 "Breaks",
204fbdcc
AL
227 "Replaces",0};
228 unsigned long Result = INIT_FCS;
418a471f 229 char S[1024];
204fbdcc
AL
230 for (const char **I = Sections; *I != 0; I++)
231 {
232 const char *Start;
233 const char *End;
234 if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
235 continue;
236
237 /* Strip out any spaces from the text, this undoes dpkgs reformatting
421c8d10
AL
238 of certain fields. dpkg also has the rather interesting notion of
239 reformatting depends operators < -> <= */
204fbdcc
AL
240 char *I = S;
241 for (; Start != End; Start++)
421c8d10 242 {
204fbdcc 243 if (isspace(*Start) == 0)
4e86942a 244 *I++ = tolower_ascii(*Start);
421c8d10
AL
245 if (*Start == '<' && Start[1] != '<' && Start[1] != '=')
246 *I++ = '=';
247 if (*Start == '>' && Start[1] != '>' && Start[1] != '=')
248 *I++ = '=';
249 }
418a471f 250
204fbdcc
AL
251 Result = AddCRC16(Result,S,I - S);
252 }
253
254 return Result;
255}
256 /*}}}*/
dcb79bae 257// ListParser::ParseStatus - Parse the status field /*{{{*/
f55a958f
AL
258// ---------------------------------------------------------------------
259/* Status lines are of the form,
260 Status: want flag status
261 want = unknown, install, hold, deinstall, purge
262 flag = ok, reinstreq, hold, hold-reinstreq
a005475e 263 status = not-installed, unpacked, half-configured,
f55a958f
AL
264 half-installed, config-files, post-inst-failed,
265 removal-failed, installed
266
267 Some of the above are obsolete (I think?) flag = hold-* and
268 status = post-inst-failed, removal-failed at least.
269 */
270bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
271 pkgCache::VerIterator Ver)
272{
273 const char *Start;
274 const char *Stop;
275 if (Section.Find("Status",Start,Stop) == false)
276 return true;
277
278 // Isolate the first word
279 const char *I = Start;
280 for(; I < Stop && *I != ' '; I++);
281 if (I >= Stop || *I != ' ')
282 return _error->Error("Malformed Status line");
283
284 // Process the want field
6c139d6e
AL
285 WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
286 {"install",pkgCache::State::Install},
287 {"hold",pkgCache::State::Hold},
288 {"deinstall",pkgCache::State::DeInstall},
b2e465d6
AL
289 {"purge",pkgCache::State::Purge},
290 {}};
291 if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
f55a958f
AL
292 return _error->Error("Malformed 1st word in the Status line");
293
294 // Isloate the next word
295 I++;
296 Start = I;
297 for(; I < Stop && *I != ' '; I++);
298 if (I >= Stop || *I != ' ')
299 return _error->Error("Malformed status line, no 2nd word");
300
301 // Process the flag field
6c139d6e
AL
302 WordList FlagList[] = {{"ok",pkgCache::State::Ok},
303 {"reinstreq",pkgCache::State::ReInstReq},
304 {"hold",pkgCache::State::HoldInst},
b2e465d6
AL
305 {"hold-reinstreq",pkgCache::State::HoldReInstReq},
306 {}};
307 if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
f55a958f
AL
308 return _error->Error("Malformed 2nd word in the Status line");
309
310 // Isloate the last word
311 I++;
312 Start = I;
313 for(; I < Stop && *I != ' '; I++);
314 if (I != Stop)
315 return _error->Error("Malformed Status line, no 3rd word");
316
317 // Process the flag field
6c139d6e
AL
318 WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
319 {"unpacked",pkgCache::State::UnPacked},
320 {"half-configured",pkgCache::State::HalfConfigured},
321 {"installed",pkgCache::State::Installed},
6c139d6e
AL
322 {"half-installed",pkgCache::State::HalfInstalled},
323 {"config-files",pkgCache::State::ConfigFiles},
9d06bc80
MV
324 {"triggers-awaited",pkgCache::State::TriggersAwaited},
325 {"triggers-pending",pkgCache::State::TriggersPending},
6c139d6e 326 {"post-inst-failed",pkgCache::State::HalfConfigured},
b2e465d6
AL
327 {"removal-failed",pkgCache::State::HalfInstalled},
328 {}};
329 if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
f55a958f
AL
330 return _error->Error("Malformed 3rd word in the Status line");
331
332 /* A Status line marks the package as indicating the current
333 version as well. Only if it is actually installed.. Otherwise
334 the interesting dpkg handling of the status file creates bogus
335 entries. */
6c139d6e
AL
336 if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
337 Pkg->CurrentState == pkgCache::State::ConfigFiles))
f55a958f
AL
338 {
339 if (Ver.end() == true)
340 _error->Warning("Encountered status field in a non-version description");
341 else
342 Pkg->CurrentVer = Ver.Index();
343 }
344
dcb79bae
AL
345 return true;
346}
a1826878 347
b2e465d6
AL
348const char *debListParser::ConvertRelation(const char *I,unsigned int &Op)
349{
350 // Determine the operator
351 switch (*I)
352 {
353 case '<':
354 I++;
355 if (*I == '=')
356 {
357 I++;
358 Op = pkgCache::Dep::LessEq;
359 break;
360 }
361
362 if (*I == '<')
363 {
364 I++;
365 Op = pkgCache::Dep::Less;
366 break;
367 }
368
369 // < is the same as <= and << is really Cs < for some reason
370 Op = pkgCache::Dep::LessEq;
371 break;
372
373 case '>':
374 I++;
375 if (*I == '=')
376 {
377 I++;
378 Op = pkgCache::Dep::GreaterEq;
379 break;
380 }
381
382 if (*I == '>')
383 {
384 I++;
385 Op = pkgCache::Dep::Greater;
386 break;
387 }
388
389 // > is the same as >= and >> is really Cs > for some reason
390 Op = pkgCache::Dep::GreaterEq;
391 break;
392
393 case '=':
394 Op = pkgCache::Dep::Equals;
395 I++;
396 break;
397
398 // HACK around bad package definitions
399 default:
400 Op = pkgCache::Dep::Equals;
401 break;
402 }
403 return I;
404}
405
a1826878
AL
406 /*}}}*/
407// ListParser::ParseDepends - Parse a dependency element /*{{{*/
408// ---------------------------------------------------------------------
409/* This parses the dependency elements out of a standard string in place,
410 bit by bit. */
dcb79bae
AL
411const char *debListParser::ParseDepends(const char *Start,const char *Stop,
412 string &Package,string &Ver,
41c81fd8
DK
413 unsigned int &Op, bool const &ParseArchFlags,
414 bool const &StripMultiArch)
dcb79bae
AL
415{
416 // Strip off leading space
417 for (;Start != Stop && isspace(*Start) != 0; Start++);
418
419 // Parse off the package name
420 const char *I = Start;
421 for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
422 *I != ',' && *I != '|'; I++);
423
424 // Malformed, no '('
425 if (I != Stop && *I == ')')
426 return 0;
427
428 if (I == Start)
429 return 0;
430
431 // Stash the package name
432 Package.assign(Start,I - Start);
41c81fd8
DK
433
434 // We don't want to confuse library users which can't handle MultiArch
435 if (StripMultiArch == true) {
436 size_t const found = Package.rfind(':');
437 if (found != string::npos)
438 Package = Package.substr(0,found);
439 }
440
dcb79bae
AL
441 // Skip white space to the '('
442 for (;I != Stop && isspace(*I) != 0 ; I++);
443
444 // Parse a version
445 if (I != Stop && *I == '(')
446 {
447 // Skip the '('
448 for (I++; I != Stop && isspace(*I) != 0 ; I++);
449 if (I + 3 >= Stop)
450 return 0;
b2e465d6 451 I = ConvertRelation(I,Op);
dcb79bae
AL
452
453 // Skip whitespace
454 for (;I != Stop && isspace(*I) != 0; I++);
455 Start = I;
456 for (;I != Stop && *I != ')'; I++);
457 if (I == Stop || Start == I)
458 return 0;
459
02f000a9
AL
460 // Skip trailing whitespace
461 const char *End = I;
462 for (; End > Start && isspace(End[-1]); End--);
463
171c75f1 464 Ver.assign(Start,End-Start);
dcb79bae
AL
465 I++;
466 }
467 else
468 {
171c75f1 469 Ver.clear();
6c139d6e 470 Op = pkgCache::Dep::NoOp;
dcb79bae
AL
471 }
472
473 // Skip whitespace
474 for (;I != Stop && isspace(*I) != 0; I++);
b2e465d6
AL
475
476 if (ParseArchFlags == true)
477 {
478 string arch = _config->Find("APT::Architecture");
9e10ad8a 479
b2e465d6
AL
480 // Parse an architecture
481 if (I != Stop && *I == '[')
482 {
483 // malformed
484 I++;
485 if (I == Stop)
486 return 0;
487
488 const char *End = I;
489 bool Found = false;
9e10ad8a 490 bool NegArch = false;
b2e465d6
AL
491 while (I != Stop)
492 {
493 // look for whitespace or ending ']'
494 while (End != Stop && !isspace(*End) && *End != ']')
495 End++;
496
497 if (End == Stop)
498 return 0;
9e10ad8a
AL
499
500 if (*I == '!')
501 {
502 NegArch = true;
503 I++;
504 }
505
3e18cc75 506 if (stringcmp(arch,I,End) == 0)
b2e465d6
AL
507 Found = true;
508
509 if (*End++ == ']') {
510 I = End;
511 break;
512 }
513
514 I = End;
515 for (;I != Stop && isspace(*I) != 0; I++);
516 }
9e10ad8a
AL
517
518 if (NegArch)
519 Found = !Found;
b2e465d6 520
9e10ad8a 521 if (Found == false)
b2e465d6
AL
522 Package = ""; /* not for this arch */
523 }
524
525 // Skip whitespace
526 for (;I != Stop && isspace(*I) != 0; I++);
527 }
528
dcb79bae 529 if (I != Stop && *I == '|')
6c139d6e 530 Op |= pkgCache::Dep::Or;
dcb79bae
AL
531
532 if (I == Stop || *I == ',' || *I == '|')
533 {
534 if (I != Stop)
535 for (I++; I != Stop && isspace(*I) != 0; I++);
536 return I;
537 }
538
539 return 0;
540}
541 /*}}}*/
542// ListParser::ParseDepends - Parse a dependency list /*{{{*/
543// ---------------------------------------------------------------------
544/* This is the higher level depends parser. It takes a tag and generates
545 a complete depends tree for the given version. */
546bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
547 const char *Tag,unsigned int Type)
548{
549 const char *Start;
550 const char *Stop;
551 if (Section.Find(Tag,Start,Stop) == false)
552 return true;
553
554 string Package;
5bf15716 555 string const pkgArch = Ver.Arch();
dcb79bae
AL
556 string Version;
557 unsigned int Op;
558
8efa2a3b 559 while (1)
dcb79bae 560 {
8efa2a3b 561 Start = ParseDepends(Start,Stop,Package,Version,Op);
dcb79bae
AL
562 if (Start == 0)
563 return _error->Error("Problem parsing dependency %s",Tag);
8efa2a3b 564
5bf15716 565 if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
dcb79bae 566 return false;
8efa2a3b
AL
567 if (Start == Stop)
568 break;
dcb79bae
AL
569 }
570 return true;
571}
572 /*}}}*/
573// ListParser::ParseProvides - Parse the provides list /*{{{*/
574// ---------------------------------------------------------------------
575/* */
576bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
577{
578 const char *Start;
579 const char *Stop;
580 if (Section.Find("Provides",Start,Stop) == false)
581 return true;
582
583 string Package;
584 string Version;
585 unsigned int Op;
586
587 while (1)
588 {
589 Start = ParseDepends(Start,Stop,Package,Version,Op);
590 if (Start == 0)
591 return _error->Error("Problem parsing Provides line");
b63380b0
MV
592 if (Op != pkgCache::Dep::NoOp) {
593 _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str());
594 } else {
595 if (NewProvides(Ver,Package,Version) == false)
596 return false;
597 }
dcb79bae
AL
598
599 if (Start == Stop)
600 break;
601 }
602
f55a958f
AL
603 return true;
604}
605 /*}}}*/
606// ListParser::GrabWord - Matches a word and returns /*{{{*/
607// ---------------------------------------------------------------------
608/* Looks for a word in a list of words - for ParseStatus */
b2e465d6 609bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
f55a958f 610{
b2e465d6 611 for (unsigned int C = 0; List[C].Str != 0; C++)
f55a958f
AL
612 {
613 if (strcasecmp(Word.c_str(),List[C].Str) == 0)
614 {
615 Out = List[C].Val;
616 return true;
617 }
618 }
619 return false;
620}
621 /*}}}*/
622// ListParser::Step - Move to the next section in the file /*{{{*/
623// ---------------------------------------------------------------------
0149949b 624/* This has to be carefull to only process the correct architecture */
f55a958f
AL
625bool debListParser::Step()
626{
dcb79bae 627 iOffset = Tags.Offset();
0149949b 628 while (Tags.Step(Section) == true)
ddc1d8d0
AL
629 {
630 /* See if this is the correct Architecture, if it isn't then we
631 drop the whole section. A missing arch tag only happens (in theory)
632 inside the Status file, so that is a positive return */
0149949b
AL
633 const char *Start;
634 const char *Stop;
635 if (Section.Find("Architecture",Start,Stop) == false)
636 return true;
9c14e3d6 637
5bf15716 638 //FIXME: Accept different Architectures here
3e18cc75 639 if (stringcmp(Arch,Start,Stop) == 0)
0149949b
AL
640 return true;
641
9c14e3d6 642 if (stringcmp(Start,Stop,"all") == 0)
0149949b 643 return true;
dcb79bae
AL
644
645 iOffset = Tags.Offset();
0149949b
AL
646 }
647 return false;
f55a958f
AL
648}
649 /*}}}*/
b0b4efb9
AL
650// ListParser::LoadReleaseInfo - Load the release information /*{{{*/
651// ---------------------------------------------------------------------
652/* */
653bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
f2152f03 654 FileFd &File, string component)
b0b4efb9 655{
b3d44315 656 pkgTagFile Tags(&File, File.Size() + 256); // XXX
b0b4efb9
AL
657 pkgTagSection Section;
658 if (Tags.Step(Section) == false)
659 return false;
660
5bf15716
DK
661 // FIXME: Do we need it now for multi-arch?
662 // mvo: I don't think we need to fill that in (it's unused since apt-0.6)
663// FileI->Architecture = WriteUniqString(Arch);
f2152f03
MV
664
665 // apt-secure does no longer download individual (per-section) Release
666 // file. to provide Component pinning we use the section name now
667 FileI->Component = WriteUniqString(component);
668
b0b4efb9
AL
669 const char *Start;
670 const char *Stop;
b3d44315 671 if (Section.Find("Suite",Start,Stop) == true)
b0b4efb9
AL
672 FileI->Archive = WriteUniqString(Start,Stop - Start);
673 if (Section.Find("Component",Start,Stop) == true)
674 FileI->Component = WriteUniqString(Start,Stop - Start);
675 if (Section.Find("Version",Start,Stop) == true)
676 FileI->Version = WriteUniqString(Start,Stop - Start);
677 if (Section.Find("Origin",Start,Stop) == true)
678 FileI->Origin = WriteUniqString(Start,Stop - Start);
efc487fb
DK
679 if (Section.Find("Codename",Start,Stop) == true)
680 FileI->Codename = WriteUniqString(Start,Stop - Start);
b0b4efb9
AL
681 if (Section.Find("Label",Start,Stop) == true)
682 FileI->Label = WriteUniqString(Start,Stop - Start);
683 if (Section.Find("Architecture",Start,Stop) == true)
684 FileI->Architecture = WriteUniqString(Start,Stop - Start);
0dbb95d8 685
3c124dde
AL
686 if (Section.FindFlag("NotAutomatic",FileI->Flags,
687 pkgCache::Flag::NotAutomatic) == false)
0dbb95d8 688 _error->Warning("Bad NotAutomatic flag");
f2152f03 689
b0b4efb9
AL
690 return !_error->PendingError();
691}
692 /*}}}*/
b2e465d6
AL
693// ListParser::GetPrio - Convert the priority from a string /*{{{*/
694// ---------------------------------------------------------------------
695/* */
696unsigned char debListParser::GetPrio(string Str)
697{
698 unsigned char Out;
699 if (GrabWord(Str,PrioList,Out) == false)
700 Out = pkgCache::State::Extra;
701
702 return Out;
703}
704 /*}}}*/