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