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