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