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