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