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