Ensure that for each all package at least one pseudopackage is installed
[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>
5c0d3668 20#include <apt-pkg/macros.h>
9c14e3d6 21
e7b470ee 22#include <ctype.h>
f55a958f
AL
23 /*}}}*/
24
b2e465d6
AL
25static 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
f55a958f
AL
32// ListParser::debListParser - Constructor /*{{{*/
33// ---------------------------------------------------------------------
5dd4c8b8
DK
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() */
37debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
38 Arch(Arch) {
39 if (Arch == "native")
40 this->Arch = _config->Find("APT::Architecture");
0149949b
AL
41}
42 /*}}}*/
f55a958f
AL
43// ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
44// ---------------------------------------------------------------------
45/* */
46unsigned 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 /*}}}*/
f55a958f
AL
55// ListParser::Package - Return the package name /*{{{*/
56// ---------------------------------------------------------------------
57/* This is to return the name of the package this section describes */
5bf15716
DK
58string 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
5dd4c8b8 69 Packages file parsed here. */
5bf15716
DK
70string debListParser::Architecture() {
71 string const Result = Section.FindS("Architecture");
5dd4c8b8
DK
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 }
5bf15716 82 return Result;
f55a958f
AL
83}
84 /*}}}*/
857e9c13
DK
85// ListParser::ArchitectureAll /*{{{*/
86// ---------------------------------------------------------------------
87/* */
88bool debListParser::ArchitectureAll() {
89 return Section.FindS("Architecture") == "all";
f55a958f
AL
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 */
97string debListParser::Version()
98{
b0b4efb9 99 return Section.FindS("Version");
f55a958f
AL
100}
101 /*}}}*/
f55a958f
AL
102// ListParser::NewVersion - Fill in the version structure /*{{{*/
103// ---------------------------------------------------------------------
104/* */
105bool debListParser::NewVersion(pkgCache::VerIterator Ver)
0149949b
AL
106{
107 // Parse the section
b35d2f5f 108 Ver->Section = UniqFindTagWrite("Section");
5bf15716 109
25396fb0
DK
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
0149949b 134 // Archive Size
b0b4efb9 135 Ver->Size = (unsigned)Section.FindI("Size");
0149949b
AL
136
137 // Unpacked Size (in K)
b0b4efb9 138 Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
0149949b
AL
139 Ver->InstalledSize *= 1024;
140
141 // Priority
142 const char *Start;
143 const char *Stop;
144 if (Section.Find("Priority",Start,Stop) == true)
b2e465d6
AL
145 {
146 if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
421c8d10 147 Ver->Priority = pkgCache::State::Extra;
0149949b 148 }
dcb79bae 149
803ea2a8
DK
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. */
ee60a634 158 bool const static multiArch = APT::Configuration::getArchitectures().size() > 1;
803ea2a8
DK
159 if (strcmp(Ver.Arch(true),"all") == 0)
160 return true;
ee60a634 161 else if (multiArch == true)
803ea2a8
DK
162 {
163 // our pseudo packages have no size to not confuse the fetcher
164 Ver->Size = 0;
165 Ver->InstalledSize = 0;
166 }
167 }
168
6c139d6e 169 if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
dcb79bae 170 return false;
8efa2a3b 171 if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
dcb79bae 172 return false;
6c139d6e 173 if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
dcb79bae 174 return false;
6c139d6e 175 if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
dcb79bae 176 return false;
6c139d6e 177 if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
dcb79bae 178 return false;
308c7d30
IJ
179 if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
180 return false;
f55ece0e 181 if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
dcb79bae 182 return false;
f8ae7e8b 183 if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false)
184 return false;
dcb79bae 185
b2e465d6
AL
186 // Obsolete.
187 if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
188 return false;
189
dcb79bae
AL
190 if (ParseProvides(Ver) == false)
191 return false;
0149949b 192
f55a958f
AL
193 return true;
194}
195 /*}}}*/
a52f938b
OS
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 */
201string debListParser::Description()
202{
45df0ad2
DK
203 string const lang = DescriptionLanguage();
204 if (lang.empty())
a52f938b
OS
205 return Section.FindS("Description");
206 else
45df0ad2 207 return Section.FindS(string("Description-").append(lang).c_str());
a52f938b
OS
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. */
215string debListParser::DescriptionLanguage()
216{
45df0ad2
DK
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 "";
a52f938b
OS
227}
228 /*}}}*/
229// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
230// ---------------------------------------------------------------------
770c32ec
MV
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 */
a52f938b
OS
235MD5SumValue debListParser::Description_md5()
236{
237 string value = Section.FindS("Description-md5");
238
770c32ec
MV
239 if (value.empty())
240 {
a52f938b
OS
241 MD5Summation md5;
242 md5.Add((Description() + "\n").c_str());
243 return md5.Result();
244 } else
245 return MD5SumValue(value);
246}
247 /*}}}*/
f55a958f
AL
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 */
252bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
253 pkgCache::VerIterator Ver)
254{
255 if (Pkg->Section == 0)
b35d2f5f 256 Pkg->Section = UniqFindTagWrite("Section");
5dd4c8b8
DK
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;
138d4b3d 263 if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
f55a958f 264 return false;
138d4b3d
AL
265
266 if (strcmp(Pkg.Name(),"apt") == 0)
267 Pkg->Flags |= pkgCache::Flag::Important;
268
f55a958f
AL
269 if (ParseStatus(Pkg,Ver) == false)
270 return false;
271 return true;
272}
273 /*}}}*/
204fbdcc
AL
274// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
275// ---------------------------------------------------------------------
276/* */
277unsigned short debListParser::VersionHash()
278{
279 const char *Sections[] ={"Installed-Size",
280 "Depends",
281 "Pre-Depends",
f78439bf
AL
282// "Suggests",
283// "Recommends",
204fbdcc 284 "Conflicts",
308c7d30 285 "Breaks",
204fbdcc
AL
286 "Replaces",0};
287 unsigned long Result = INIT_FCS;
418a471f 288 char S[1024];
204fbdcc
AL
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
421c8d10
AL
297 of certain fields. dpkg also has the rather interesting notion of
298 reformatting depends operators < -> <= */
204fbdcc
AL
299 char *I = S;
300 for (; Start != End; Start++)
421c8d10 301 {
204fbdcc 302 if (isspace(*Start) == 0)
4e86942a 303 *I++ = tolower_ascii(*Start);
421c8d10
AL
304 if (*Start == '<' && Start[1] != '<' && Start[1] != '=')
305 *I++ = '=';
306 if (*Start == '>' && Start[1] != '>' && Start[1] != '=')
307 *I++ = '=';
308 }
418a471f 309
204fbdcc
AL
310 Result = AddCRC16(Result,S,I - S);
311 }
312
313 return Result;
314}
315 /*}}}*/
dcb79bae 316// ListParser::ParseStatus - Parse the status field /*{{{*/
f55a958f
AL
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
a005475e 322 status = not-installed, unpacked, half-configured,
f55a958f
AL
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 */
329bool 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
6c139d6e
AL
344 WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
345 {"install",pkgCache::State::Install},
346 {"hold",pkgCache::State::Hold},
347 {"deinstall",pkgCache::State::DeInstall},
b2e465d6
AL
348 {"purge",pkgCache::State::Purge},
349 {}};
350 if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
f55a958f
AL
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
6c139d6e
AL
361 WordList FlagList[] = {{"ok",pkgCache::State::Ok},
362 {"reinstreq",pkgCache::State::ReInstReq},
363 {"hold",pkgCache::State::HoldInst},
b2e465d6
AL
364 {"hold-reinstreq",pkgCache::State::HoldReInstReq},
365 {}};
366 if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
f55a958f
AL
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
6c139d6e
AL
377 WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
378 {"unpacked",pkgCache::State::UnPacked},
379 {"half-configured",pkgCache::State::HalfConfigured},
380 {"installed",pkgCache::State::Installed},
6c139d6e
AL
381 {"half-installed",pkgCache::State::HalfInstalled},
382 {"config-files",pkgCache::State::ConfigFiles},
9d06bc80
MV
383 {"triggers-awaited",pkgCache::State::TriggersAwaited},
384 {"triggers-pending",pkgCache::State::TriggersPending},
6c139d6e 385 {"post-inst-failed",pkgCache::State::HalfConfigured},
b2e465d6
AL
386 {"removal-failed",pkgCache::State::HalfInstalled},
387 {}};
388 if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
f55a958f
AL
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. */
6c139d6e
AL
395 if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
396 Pkg->CurrentState == pkgCache::State::ConfigFiles))
f55a958f
AL
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
dcb79bae
AL
404 return true;
405}
a1826878 406
b2e465d6
AL
407const 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
a1826878
AL
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. */
dcb79bae
AL
470const char *debListParser::ParseDepends(const char *Start,const char *Stop,
471 string &Package,string &Ver,
41c81fd8
DK
472 unsigned int &Op, bool const &ParseArchFlags,
473 bool const &StripMultiArch)
dcb79bae
AL
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);
41c81fd8
DK
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
dcb79bae
AL
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;
b2e465d6 510 I = ConvertRelation(I,Op);
dcb79bae
AL
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
02f000a9
AL
519 // Skip trailing whitespace
520 const char *End = I;
521 for (; End > Start && isspace(End[-1]); End--);
522
171c75f1 523 Ver.assign(Start,End-Start);
dcb79bae
AL
524 I++;
525 }
526 else
527 {
171c75f1 528 Ver.clear();
6c139d6e 529 Op = pkgCache::Dep::NoOp;
dcb79bae
AL
530 }
531
532 // Skip whitespace
533 for (;I != Stop && isspace(*I) != 0; I++);
b2e465d6
AL
534
535 if (ParseArchFlags == true)
536 {
537 string arch = _config->Find("APT::Architecture");
9e10ad8a 538
b2e465d6
AL
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;
9e10ad8a 549 bool NegArch = false;
b2e465d6
AL
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;
9e10ad8a
AL
558
559 if (*I == '!')
560 {
561 NegArch = true;
562 I++;
563 }
564
3e18cc75 565 if (stringcmp(arch,I,End) == 0)
b2e465d6
AL
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 }
9e10ad8a
AL
576
577 if (NegArch)
578 Found = !Found;
b2e465d6 579
9e10ad8a 580 if (Found == false)
b2e465d6
AL
581 Package = ""; /* not for this arch */
582 }
583
584 // Skip whitespace
585 for (;I != Stop && isspace(*I) != 0; I++);
586 }
587
dcb79bae 588 if (I != Stop && *I == '|')
6c139d6e 589 Op |= pkgCache::Dep::Or;
dcb79bae
AL
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. */
605bool 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;
803ea2a8 614 string const pkgArch = Ver.Arch(true);
dcb79bae
AL
615 string Version;
616 unsigned int Op;
617
8efa2a3b 618 while (1)
dcb79bae 619 {
8efa2a3b 620 Start = ParseDepends(Start,Stop,Package,Version,Op);
dcb79bae
AL
621 if (Start == 0)
622 return _error->Error("Problem parsing dependency %s",Tag);
8efa2a3b 623
5bf15716 624 if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
dcb79bae 625 return false;
8efa2a3b
AL
626 if (Start == Stop)
627 break;
dcb79bae
AL
628 }
629 return true;
630}
631 /*}}}*/
632// ListParser::ParseProvides - Parse the provides list /*{{{*/
633// ---------------------------------------------------------------------
634/* */
635bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
636{
637 const char *Start;
638 const char *Stop;
67e0766f 639 if (Section.Find("Provides",Start,Stop) == true)
dcb79bae 640 {
67e0766f
DK
641 string Package;
642 string Version;
803ea2a8 643 string const Arch = Ver.Arch(true);
67e0766f
DK
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;
b63380b0 660 }
67e0766f 661 }
dcb79bae 662
4d174dc8
DK
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());
dcb79bae 667 }
dcb79bae 668
67e0766f
DK
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;
dcb79bae 683 }
67e0766f 684
f55a958f
AL
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 */
b2e465d6 691bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
f55a958f 692{
b2e465d6 693 for (unsigned int C = 0; List[C].Str != 0; C++)
f55a958f
AL
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// ---------------------------------------------------------------------
0149949b 706/* This has to be carefull to only process the correct architecture */
f55a958f
AL
707bool debListParser::Step()
708{
dcb79bae 709 iOffset = Tags.Offset();
0149949b 710 while (Tags.Step(Section) == true)
ddc1d8d0
AL
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 */
5dd4c8b8
DK
715 string const Architecture = Section.FindS("Architecture");
716 if (Architecture.empty() == true)
0149949b 717 return true;
9c14e3d6 718
5dd4c8b8
DK
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;
0149949b 728
5dd4c8b8
DK
729 if (Architecture == "all")
730 return true;
731 }
dcb79bae
AL
732
733 iOffset = Tags.Offset();
0149949b
AL
734 }
735 return false;
f55a958f
AL
736}
737 /*}}}*/
b0b4efb9
AL
738// ListParser::LoadReleaseInfo - Load the release information /*{{{*/
739// ---------------------------------------------------------------------
740/* */
741bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
f2152f03 742 FileFd &File, string component)
b0b4efb9 743{
b3d44315 744 pkgTagFile Tags(&File, File.Size() + 256); // XXX
b0b4efb9
AL
745 pkgTagSection Section;
746 if (Tags.Step(Section) == false)
747 return false;
748
5bf15716
DK
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);
f2152f03
MV
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
b0b4efb9
AL
757 const char *Start;
758 const char *Stop;
b3d44315 759 if (Section.Find("Suite",Start,Stop) == true)
b0b4efb9
AL
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);
efc487fb
DK
767 if (Section.Find("Codename",Start,Stop) == true)
768 FileI->Codename = WriteUniqString(Start,Stop - Start);
b0b4efb9
AL
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);
0dbb95d8 773
3c124dde
AL
774 if (Section.FindFlag("NotAutomatic",FileI->Flags,
775 pkgCache::Flag::NotAutomatic) == false)
0dbb95d8 776 _error->Warning("Bad NotAutomatic flag");
f2152f03 777
b0b4efb9
AL
778 return !_error->PendingError();
779}
780 /*}}}*/
b2e465d6
AL
781// ListParser::GetPrio - Convert the priority from a string /*{{{*/
782// ---------------------------------------------------------------------
783/* */
784unsigned 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 /*}}}*/