Arch() on a MultiArch:all version should return "all" to be compatible
[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// ---------------------------------------------------------------------
5dd4c8b8
DK
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() */
38debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
39 Arch(Arch) {
40 if (Arch == "native")
41 this->Arch = _config->Find("APT::Architecture");
0149949b
AL
42}
43 /*}}}*/
f55a958f
AL
44// ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
45// ---------------------------------------------------------------------
46/* */
47unsigned 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 /*}}}*/
f55a958f
AL
56// ListParser::Package - Return the package name /*{{{*/
57// ---------------------------------------------------------------------
58/* This is to return the name of the package this section describes */
5bf15716
DK
59string 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
5dd4c8b8 70 Packages file parsed here. */
5bf15716
DK
71string debListParser::Architecture() {
72 string const Result = Section.FindS("Architecture");
5dd4c8b8
DK
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 }
5bf15716 83 return Result;
f55a958f
AL
84}
85 /*}}}*/
857e9c13
DK
86// ListParser::ArchitectureAll /*{{{*/
87// ---------------------------------------------------------------------
88/* */
89bool debListParser::ArchitectureAll() {
90 return Section.FindS("Architecture") == "all";
91}
92 /*}}}*/
f55a958f
AL
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 */
98string debListParser::Version()
99{
b0b4efb9 100 return Section.FindS("Version");
f55a958f
AL
101}
102 /*}}}*/
f55a958f
AL
103// ListParser::NewVersion - Fill in the version structure /*{{{*/
104// ---------------------------------------------------------------------
105/* */
106bool debListParser::NewVersion(pkgCache::VerIterator Ver)
0149949b
AL
107{
108 // Parse the section
b35d2f5f 109 Ver->Section = UniqFindTagWrite("Section");
5bf15716 110
25396fb0
DK
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
0149949b 135 // Archive Size
b0b4efb9 136 Ver->Size = (unsigned)Section.FindI("Size");
0149949b
AL
137
138 // Unpacked Size (in K)
b0b4efb9 139 Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
0149949b
AL
140 Ver->InstalledSize *= 1024;
141
142 // Priority
143 const char *Start;
144 const char *Stop;
145 if (Section.Find("Priority",Start,Stop) == true)
b2e465d6
AL
146 {
147 if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
421c8d10 148 Ver->Priority = pkgCache::State::Extra;
0149949b 149 }
dcb79bae 150
6c139d6e 151 if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
dcb79bae 152 return false;
8efa2a3b 153 if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
dcb79bae 154 return false;
6c139d6e 155 if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
dcb79bae 156 return false;
6c139d6e 157 if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
dcb79bae 158 return false;
6c139d6e 159 if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
dcb79bae 160 return false;
308c7d30
IJ
161 if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
162 return false;
f55ece0e 163 if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
dcb79bae 164 return false;
f8ae7e8b 165 if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false)
166 return false;
dcb79bae 167
b2e465d6
AL
168 // Obsolete.
169 if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
170 return false;
171
dcb79bae
AL
172 if (ParseProvides(Ver) == false)
173 return false;
0149949b 174
f55a958f
AL
175 return true;
176}
177 /*}}}*/
a52f938b
OS
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 */
183string debListParser::Description()
184{
45df0ad2
DK
185 string const lang = DescriptionLanguage();
186 if (lang.empty())
a52f938b
OS
187 return Section.FindS("Description");
188 else
45df0ad2 189 return Section.FindS(string("Description-").append(lang).c_str());
a52f938b
OS
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. */
197string debListParser::DescriptionLanguage()
198{
45df0ad2
DK
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 "";
a52f938b
OS
209}
210 /*}}}*/
211// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
212// ---------------------------------------------------------------------
770c32ec
MV
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 */
a52f938b
OS
217MD5SumValue debListParser::Description_md5()
218{
219 string value = Section.FindS("Description-md5");
220
770c32ec
MV
221 if (value.empty())
222 {
a52f938b
OS
223 MD5Summation md5;
224 md5.Add((Description() + "\n").c_str());
225 return md5.Result();
226 } else
227 return MD5SumValue(value);
228}
229 /*}}}*/
f55a958f
AL
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 */
234bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
235 pkgCache::VerIterator Ver)
236{
237 if (Pkg->Section == 0)
b35d2f5f 238 Pkg->Section = UniqFindTagWrite("Section");
5dd4c8b8
DK
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;
138d4b3d 245 if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
f55a958f 246 return false;
138d4b3d
AL
247
248 if (strcmp(Pkg.Name(),"apt") == 0)
249 Pkg->Flags |= pkgCache::Flag::Important;
250
f55a958f
AL
251 if (ParseStatus(Pkg,Ver) == false)
252 return false;
253 return true;
254}
255 /*}}}*/
204fbdcc
AL
256// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
257// ---------------------------------------------------------------------
258/* */
259unsigned short debListParser::VersionHash()
260{
261 const char *Sections[] ={"Installed-Size",
262 "Depends",
263 "Pre-Depends",
f78439bf
AL
264// "Suggests",
265// "Recommends",
204fbdcc 266 "Conflicts",
308c7d30 267 "Breaks",
204fbdcc
AL
268 "Replaces",0};
269 unsigned long Result = INIT_FCS;
418a471f 270 char S[1024];
204fbdcc
AL
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
421c8d10
AL
279 of certain fields. dpkg also has the rather interesting notion of
280 reformatting depends operators < -> <= */
204fbdcc
AL
281 char *I = S;
282 for (; Start != End; Start++)
421c8d10 283 {
204fbdcc 284 if (isspace(*Start) == 0)
4e86942a 285 *I++ = tolower_ascii(*Start);
421c8d10
AL
286 if (*Start == '<' && Start[1] != '<' && Start[1] != '=')
287 *I++ = '=';
288 if (*Start == '>' && Start[1] != '>' && Start[1] != '=')
289 *I++ = '=';
290 }
418a471f 291
204fbdcc
AL
292 Result = AddCRC16(Result,S,I - S);
293 }
294
295 return Result;
296}
297 /*}}}*/
dcb79bae 298// ListParser::ParseStatus - Parse the status field /*{{{*/
f55a958f
AL
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
a005475e 304 status = not-installed, unpacked, half-configured,
f55a958f
AL
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 */
311bool 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
6c139d6e
AL
326 WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
327 {"install",pkgCache::State::Install},
328 {"hold",pkgCache::State::Hold},
329 {"deinstall",pkgCache::State::DeInstall},
b2e465d6
AL
330 {"purge",pkgCache::State::Purge},
331 {}};
332 if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
f55a958f
AL
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
6c139d6e
AL
343 WordList FlagList[] = {{"ok",pkgCache::State::Ok},
344 {"reinstreq",pkgCache::State::ReInstReq},
345 {"hold",pkgCache::State::HoldInst},
b2e465d6
AL
346 {"hold-reinstreq",pkgCache::State::HoldReInstReq},
347 {}};
348 if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
f55a958f
AL
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
6c139d6e
AL
359 WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
360 {"unpacked",pkgCache::State::UnPacked},
361 {"half-configured",pkgCache::State::HalfConfigured},
362 {"installed",pkgCache::State::Installed},
6c139d6e
AL
363 {"half-installed",pkgCache::State::HalfInstalled},
364 {"config-files",pkgCache::State::ConfigFiles},
9d06bc80
MV
365 {"triggers-awaited",pkgCache::State::TriggersAwaited},
366 {"triggers-pending",pkgCache::State::TriggersPending},
6c139d6e 367 {"post-inst-failed",pkgCache::State::HalfConfigured},
b2e465d6
AL
368 {"removal-failed",pkgCache::State::HalfInstalled},
369 {}};
370 if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
f55a958f
AL
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. */
6c139d6e
AL
377 if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
378 Pkg->CurrentState == pkgCache::State::ConfigFiles))
f55a958f
AL
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
dcb79bae
AL
386 return true;
387}
a1826878 388
b2e465d6
AL
389const 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
a1826878
AL
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. */
dcb79bae
AL
452const char *debListParser::ParseDepends(const char *Start,const char *Stop,
453 string &Package,string &Ver,
41c81fd8
DK
454 unsigned int &Op, bool const &ParseArchFlags,
455 bool const &StripMultiArch)
dcb79bae
AL
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);
41c81fd8
DK
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
dcb79bae
AL
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;
b2e465d6 492 I = ConvertRelation(I,Op);
dcb79bae
AL
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
02f000a9
AL
501 // Skip trailing whitespace
502 const char *End = I;
503 for (; End > Start && isspace(End[-1]); End--);
504
171c75f1 505 Ver.assign(Start,End-Start);
dcb79bae
AL
506 I++;
507 }
508 else
509 {
171c75f1 510 Ver.clear();
6c139d6e 511 Op = pkgCache::Dep::NoOp;
dcb79bae
AL
512 }
513
514 // Skip whitespace
515 for (;I != Stop && isspace(*I) != 0; I++);
b2e465d6
AL
516
517 if (ParseArchFlags == true)
518 {
519 string arch = _config->Find("APT::Architecture");
9e10ad8a 520
b2e465d6
AL
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;
9e10ad8a 531 bool NegArch = false;
b2e465d6
AL
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;
9e10ad8a
AL
540
541 if (*I == '!')
542 {
543 NegArch = true;
544 I++;
545 }
546
3e18cc75 547 if (stringcmp(arch,I,End) == 0)
b2e465d6
AL
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 }
9e10ad8a
AL
558
559 if (NegArch)
560 Found = !Found;
b2e465d6 561
9e10ad8a 562 if (Found == false)
b2e465d6
AL
563 Package = ""; /* not for this arch */
564 }
565
566 // Skip whitespace
567 for (;I != Stop && isspace(*I) != 0; I++);
568 }
569
dcb79bae 570 if (I != Stop && *I == '|')
6c139d6e 571 Op |= pkgCache::Dep::Or;
dcb79bae
AL
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. */
587bool 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;
5bf15716 596 string const pkgArch = Ver.Arch();
dcb79bae
AL
597 string Version;
598 unsigned int Op;
599
8efa2a3b 600 while (1)
dcb79bae 601 {
8efa2a3b 602 Start = ParseDepends(Start,Stop,Package,Version,Op);
dcb79bae
AL
603 if (Start == 0)
604 return _error->Error("Problem parsing dependency %s",Tag);
8efa2a3b 605
5bf15716 606 if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
dcb79bae 607 return false;
8efa2a3b
AL
608 if (Start == Stop)
609 break;
dcb79bae
AL
610 }
611 return true;
612}
613 /*}}}*/
614// ListParser::ParseProvides - Parse the provides list /*{{{*/
615// ---------------------------------------------------------------------
616/* */
617bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
618{
619 const char *Start;
620 const char *Stop;
67e0766f 621 if (Section.Find("Provides",Start,Stop) == true)
dcb79bae 622 {
67e0766f
DK
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;
b63380b0 642 }
67e0766f 643 }
4d174dc8
DK
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 }
dcb79bae 650
67e0766f
DK
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;
dcb79bae 665 }
67e0766f 666
f55a958f
AL
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 */
b2e465d6 673bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
f55a958f 674{
b2e465d6 675 for (unsigned int C = 0; List[C].Str != 0; C++)
f55a958f
AL
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// ---------------------------------------------------------------------
0149949b 688/* This has to be carefull to only process the correct architecture */
f55a958f
AL
689bool debListParser::Step()
690{
dcb79bae 691 iOffset = Tags.Offset();
0149949b 692 while (Tags.Step(Section) == true)
ddc1d8d0
AL
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 */
5dd4c8b8
DK
697 string const Architecture = Section.FindS("Architecture");
698 if (Architecture.empty() == true)
0149949b 699 return true;
9c14e3d6 700
5dd4c8b8
DK
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;
0149949b 710
5dd4c8b8
DK
711 if (Architecture == "all")
712 return true;
713 }
dcb79bae
AL
714
715 iOffset = Tags.Offset();
0149949b
AL
716 }
717 return false;
f55a958f
AL
718}
719 /*}}}*/
b0b4efb9
AL
720// ListParser::LoadReleaseInfo - Load the release information /*{{{*/
721// ---------------------------------------------------------------------
722/* */
723bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
f2152f03 724 FileFd &File, string component)
b0b4efb9 725{
b3d44315 726 pkgTagFile Tags(&File, File.Size() + 256); // XXX
b0b4efb9
AL
727 pkgTagSection Section;
728 if (Tags.Step(Section) == false)
729 return false;
730
5bf15716
DK
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);
f2152f03
MV
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
b0b4efb9
AL
739 const char *Start;
740 const char *Stop;
b3d44315 741 if (Section.Find("Suite",Start,Stop) == true)
b0b4efb9
AL
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);
efc487fb
DK
749 if (Section.Find("Codename",Start,Stop) == true)
750 FileI->Codename = WriteUniqString(Start,Stop - Start);
b0b4efb9
AL
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);
0dbb95d8 755
3c124dde
AL
756 if (Section.FindFlag("NotAutomatic",FileI->Flags,
757 pkgCache::Flag::NotAutomatic) == false)
0dbb95d8 758 _error->Warning("Bad NotAutomatic flag");
f2152f03 759
b0b4efb9
AL
760 return !_error->PendingError();
761}
762 /*}}}*/
b2e465d6
AL
763// ListParser::GetPrio - Convert the priority from a string /*{{{*/
764// ---------------------------------------------------------------------
765/* */
766unsigned 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 /*}}}*/