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