]> git.saurik.com Git - apt.git/blame - apt-pkg/deb/deblistparser.cc
Merge branch 'feature/gnupglimit' into debian/experimental
[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>
424ff669 18#include <apt-pkg/cachefilter.h>
45df0ad2 19#include <apt-pkg/aptconfiguration.h>
cdcc6d34 20#include <apt-pkg/strutl.h>
472ff00e 21#include <apt-pkg/fileutl.h>
204fbdcc 22#include <apt-pkg/crc-16.h>
a52f938b 23#include <apt-pkg/md5.h>
453b82a3
DK
24#include <apt-pkg/mmap.h>
25#include <apt-pkg/pkgcache.h>
26#include <apt-pkg/cacheiterators.h>
27#include <apt-pkg/tagfile.h>
5c0d3668 28#include <apt-pkg/macros.h>
9c14e3d6 29
453b82a3
DK
30#include <stddef.h>
31#include <string.h>
32#include <algorithm>
33#include <string>
34#include <vector>
e7b470ee 35#include <ctype.h>
f55a958f
AL
36 /*}}}*/
37
8f3ba4e8
DK
38using std::string;
39
84de0cea
MV
40static debListParser::WordList PrioList[] = {
41 {"required",pkgCache::State::Required},
42 {"important",pkgCache::State::Important},
43 {"standard",pkgCache::State::Standard},
44 {"optional",pkgCache::State::Optional},
45 {"extra",pkgCache::State::Extra},
67c3067f 46 {NULL, 0}};
b2e465d6 47
f55a958f
AL
48// ListParser::debListParser - Constructor /*{{{*/
49// ---------------------------------------------------------------------
5dd4c8b8
DK
50/* Provide an architecture and only this one and "all" will be accepted
51 in Step(), if no Architecture is given we will accept every arch
52 we would accept in general with checkArchitecture() */
53debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
54 Arch(Arch) {
33dd02e3
DK
55 if (Arch == "native")
56 this->Arch = _config->Find("APT::Architecture");
dcfa253f
DK
57 Architectures = APT::Configuration::getArchitectures();
58 MultiArchEnabled = Architectures.size() > 1;
0149949b
AL
59}
60 /*}}}*/
f55a958f
AL
61// ListParser::Package - Return the package name /*{{{*/
62// ---------------------------------------------------------------------
63/* This is to return the name of the package this section describes */
5bf15716 64string debListParser::Package() {
33dd02e3
DK
65 string const Result = Section.FindS("Package");
66 if(unlikely(Result.empty() == true))
67 _error->Error("Encountered a section with no Package: header");
68 return Result;
5bf15716
DK
69}
70 /*}}}*/
71// ListParser::Architecture - Return the package arch /*{{{*/
72// ---------------------------------------------------------------------
28166356 73/* This will return the Architecture of the package this section describes */
5bf15716 74string debListParser::Architecture() {
99a2ea5a 75 return Section.FindS("Architecture");
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 /*}}}*/
e33dbfe5 95unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/
0149949b 96{
e33dbfe5 97 unsigned char MA;
28166356 98 string const MultiArch = Section.FindS("Multi-Arch");
19fb04e8 99 if (MultiArch.empty() == true || MultiArch == "no")
e33dbfe5 100 MA = pkgCache::Version::None;
28166356 101 else if (MultiArch == "same") {
ca238ede 102 if (ArchitectureAll() == true)
25396fb0 103 {
e33dbfe5
DK
104 if (showErrors == true)
105 _error->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
106 Section.FindS("Package").c_str());
107 MA = pkgCache::Version::None;
25396fb0 108 }
28166356 109 else
e33dbfe5 110 MA = pkgCache::Version::Same;
28166356
DK
111 }
112 else if (MultiArch == "foreign")
e33dbfe5 113 MA = pkgCache::Version::Foreign;
28166356 114 else if (MultiArch == "allowed")
e33dbfe5 115 MA = pkgCache::Version::Allowed;
28166356
DK
116 else
117 {
e33dbfe5
DK
118 if (showErrors == true)
119 _error->Warning("Unknown Multi-Arch type '%s' for package '%s'",
120 MultiArch.c_str(), Section.FindS("Package").c_str());
121 MA = pkgCache::Version::None;
25396fb0
DK
122 }
123
ca238ede 124 if (ArchitectureAll() == true)
e33dbfe5 125 MA |= pkgCache::Version::All;
ca238ede 126
e33dbfe5
DK
127 return MA;
128}
129 /*}}}*/
130// ListParser::NewVersion - Fill in the version structure /*{{{*/
131// ---------------------------------------------------------------------
132/* */
133bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
134{
78a5476f
DK
135 const char *Start;
136 const char *Stop;
137
e33dbfe5 138 // Parse the section
78a5476f
DK
139 if (Section.Find("Section",Start,Stop) == true)
140 {
141 map_stringitem_t const idx = StoreString(pkgCacheGenerator::SECTION, Start, Stop - Start);
142 Ver->Section = idx;
143 }
144
e33dbfe5 145 Ver->MultiArch = ParseMultiArch(true);
0149949b 146 // Archive Size
e2c66de5 147 Ver->Size = Section.FindULL("Size");
0149949b 148 // Unpacked Size (in K)
e2c66de5 149 Ver->InstalledSize = Section.FindULL("Installed-Size");
0149949b
AL
150 Ver->InstalledSize *= 1024;
151
152 // Priority
0149949b 153 if (Section.Find("Priority",Start,Stop) == true)
78a5476f 154 {
b2e465d6 155 if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
421c8d10 156 Ver->Priority = pkgCache::State::Extra;
0149949b 157 }
dcb79bae 158
6c139d6e 159 if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
dcb79bae 160 return false;
8efa2a3b 161 if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
dcb79bae 162 return false;
6c139d6e 163 if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
dcb79bae 164 return false;
6c139d6e 165 if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
dcb79bae 166 return false;
6c139d6e 167 if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
dcb79bae 168 return false;
308c7d30
IJ
169 if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
170 return false;
f55ece0e 171 if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
dcb79bae 172 return false;
f8ae7e8b 173 if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false)
174 return false;
dcb79bae 175
b2e465d6
AL
176 // Obsolete.
177 if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
178 return false;
179
dcb79bae
AL
180 if (ParseProvides(Ver) == false)
181 return false;
0149949b 182
f55a958f
AL
183 return true;
184}
185 /*}}}*/
a52f938b
OS
186// ListParser::Description - Return the description string /*{{{*/
187// ---------------------------------------------------------------------
188/* This is to return the string describing the package in debian
189 form. If this returns the blank string then the entry is assumed to
190 only describe package properties */
ffe3c68e 191string debListParser::Description(std::string const &lang)
a52f938b 192{
45df0ad2 193 if (lang.empty())
a52f938b
OS
194 return Section.FindS("Description");
195 else
45df0ad2 196 return Section.FindS(string("Description-").append(lang).c_str());
a52f938b 197}
ffe3c68e
DK
198 /*}}}*/
199// ListParser::AvailableDescriptionLanguages /*{{{*/
200std::vector<std::string> debListParser::AvailableDescriptionLanguages()
a52f938b 201{
ffe3c68e
DK
202 std::vector<std::string> const understood = APT::Configuration::getLanguages();
203 std::vector<std::string> avail;
204 if (Section.Exists("Description") == true)
205 avail.push_back("");
206 for (std::vector<std::string>::const_iterator lang = understood.begin(); lang != understood.end(); ++lang)
207 {
208 std::string const tagname = "Description-" + *lang;
209 if (Section.Exists(tagname.c_str()) == true)
210 avail.push_back(*lang);
211 }
212 return avail;
a52f938b 213}
ffe3c68e
DK
214 /*}}}*/
215// ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/
a52f938b 216// ---------------------------------------------------------------------
770c32ec
MV
217/* This is to return the md5 string to allow the check if it is the right
218 description. If no Description-md5 is found in the section it will be
219 calculated.
220 */
a52f938b
OS
221MD5SumValue debListParser::Description_md5()
222{
fc691496
DK
223 string const value = Section.FindS("Description-md5");
224 if (value.empty() == true)
770c32ec 225 {
ffe3c68e 226 std::string const desc = Description("") + "\n";
99359751
DK
227 if (desc == "\n")
228 return MD5SumValue();
229
a52f938b 230 MD5Summation md5;
99359751 231 md5.Add(desc.c_str());
a52f938b 232 return md5.Result();
fc691496
DK
233 }
234 else if (likely(value.size() == 32))
235 {
236 if (likely(value.find_first_not_of("0123456789abcdefABCDEF") == string::npos))
237 return MD5SumValue(value);
238 _error->Error("Malformed Description-md5 line; includes invalid character '%s'", value.c_str());
239 return MD5SumValue();
240 }
241 _error->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value.size(), value.c_str());
242 return MD5SumValue();
a52f938b
OS
243}
244 /*}}}*/
f55a958f
AL
245// ListParser::UsePackage - Update a package structure /*{{{*/
246// ---------------------------------------------------------------------
247/* This is called to update the package with any new information
248 that might be found in the section */
32b9a14c
DK
249bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
250 pkgCache::VerIterator &Ver)
f55a958f 251{
5dd4c8b8 252 string const static myArch = _config->Find("APT::Architecture");
e5a91f7e
DK
253 // Possible values are: "all", "native", "installed" and "none"
254 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
255 string const static essential = _config->Find("pkgCacheGen::Essential", "all");
256 if (essential == "all" ||
257 (essential == "native" && Pkg->Arch != 0 && myArch == Pkg.Arch()))
5dd4c8b8
DK
258 if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
259 return false;
138d4b3d 260 if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
f55a958f 261 return false;
138d4b3d
AL
262
263 if (strcmp(Pkg.Name(),"apt") == 0)
a552f37e
DK
264 {
265 if ((essential == "native" && Pkg->Arch != 0 && myArch == Pkg.Arch()) ||
266 essential == "all")
267 Pkg->Flags |= pkgCache::Flag::Essential | pkgCache::Flag::Important;
268 else
269 Pkg->Flags |= pkgCache::Flag::Important;
270 }
271
f55a958f
AL
272 if (ParseStatus(Pkg,Ver) == false)
273 return false;
274 return true;
275}
276 /*}}}*/
204fbdcc
AL
277// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
278// ---------------------------------------------------------------------
279/* */
280unsigned short debListParser::VersionHash()
281{
282 const char *Sections[] ={"Installed-Size",
283 "Depends",
284 "Pre-Depends",
f78439bf
AL
285// "Suggests",
286// "Recommends",
204fbdcc 287 "Conflicts",
308c7d30 288 "Breaks",
204fbdcc
AL
289 "Replaces",0};
290 unsigned long Result = INIT_FCS;
418a471f 291 char S[1024];
d9682cf8 292 for (const char * const *I = Sections; *I != 0; ++I)
204fbdcc
AL
293 {
294 const char *Start;
295 const char *End;
296 if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
297 continue;
298
299 /* Strip out any spaces from the text, this undoes dpkgs reformatting
421c8d10
AL
300 of certain fields. dpkg also has the rather interesting notion of
301 reformatting depends operators < -> <= */
470a5c38 302 char *J = S;
d9682cf8 303 for (; Start != End; ++Start)
421c8d10 304 {
d9682cf8
DK
305 if (isspace(*Start) != 0)
306 continue;
307 *J++ = tolower_ascii(*Start);
308
309 if ((*Start == '<' || *Start == '>') && Start[1] != *Start && Start[1] != '=')
470a5c38 310 *J++ = '=';
421c8d10 311 }
418a471f 312
470a5c38 313 Result = AddCRC16(Result,S,J - S);
204fbdcc
AL
314 }
315
316 return Result;
317}
318 /*}}}*/
dcb79bae 319// ListParser::ParseStatus - Parse the status field /*{{{*/
f55a958f
AL
320// ---------------------------------------------------------------------
321/* Status lines are of the form,
322 Status: want flag status
323 want = unknown, install, hold, deinstall, purge
324 flag = ok, reinstreq, hold, hold-reinstreq
a005475e 325 status = not-installed, unpacked, half-configured,
f55a958f
AL
326 half-installed, config-files, post-inst-failed,
327 removal-failed, installed
328
329 Some of the above are obsolete (I think?) flag = hold-* and
330 status = post-inst-failed, removal-failed at least.
331 */
32b9a14c
DK
332bool debListParser::ParseStatus(pkgCache::PkgIterator &Pkg,
333 pkgCache::VerIterator &Ver)
f55a958f
AL
334{
335 const char *Start;
336 const char *Stop;
337 if (Section.Find("Status",Start,Stop) == false)
338 return true;
6bc703c2
DK
339
340 // UsePackage() is responsible for setting the flag in the default case
341 bool const static essential = _config->Find("pkgCacheGen::Essential", "") == "installed";
342 if (essential == true &&
343 Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
344 return false;
345
f55a958f
AL
346 // Isolate the first word
347 const char *I = Start;
348 for(; I < Stop && *I != ' '; I++);
349 if (I >= Stop || *I != ' ')
350 return _error->Error("Malformed Status line");
351
352 // Process the want field
6c139d6e
AL
353 WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
354 {"install",pkgCache::State::Install},
355 {"hold",pkgCache::State::Hold},
356 {"deinstall",pkgCache::State::DeInstall},
b2e465d6 357 {"purge",pkgCache::State::Purge},
67c3067f 358 {NULL, 0}};
b2e465d6 359 if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
f55a958f
AL
360 return _error->Error("Malformed 1st word in the Status line");
361
362 // Isloate the next word
363 I++;
364 Start = I;
365 for(; I < Stop && *I != ' '; I++);
366 if (I >= Stop || *I != ' ')
367 return _error->Error("Malformed status line, no 2nd word");
368
369 // Process the flag field
6c139d6e
AL
370 WordList FlagList[] = {{"ok",pkgCache::State::Ok},
371 {"reinstreq",pkgCache::State::ReInstReq},
372 {"hold",pkgCache::State::HoldInst},
b2e465d6 373 {"hold-reinstreq",pkgCache::State::HoldReInstReq},
67c3067f 374 {NULL, 0}};
b2e465d6 375 if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
f55a958f
AL
376 return _error->Error("Malformed 2nd word in the Status line");
377
378 // Isloate the last word
379 I++;
380 Start = I;
381 for(; I < Stop && *I != ' '; I++);
382 if (I != Stop)
383 return _error->Error("Malformed Status line, no 3rd word");
384
385 // Process the flag field
6c139d6e
AL
386 WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
387 {"unpacked",pkgCache::State::UnPacked},
388 {"half-configured",pkgCache::State::HalfConfigured},
389 {"installed",pkgCache::State::Installed},
6c139d6e
AL
390 {"half-installed",pkgCache::State::HalfInstalled},
391 {"config-files",pkgCache::State::ConfigFiles},
9d06bc80
MV
392 {"triggers-awaited",pkgCache::State::TriggersAwaited},
393 {"triggers-pending",pkgCache::State::TriggersPending},
6c139d6e 394 {"post-inst-failed",pkgCache::State::HalfConfigured},
b2e465d6 395 {"removal-failed",pkgCache::State::HalfInstalled},
67c3067f 396 {NULL, 0}};
b2e465d6 397 if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
f55a958f
AL
398 return _error->Error("Malformed 3rd word in the Status line");
399
400 /* A Status line marks the package as indicating the current
401 version as well. Only if it is actually installed.. Otherwise
402 the interesting dpkg handling of the status file creates bogus
403 entries. */
6c139d6e
AL
404 if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
405 Pkg->CurrentState == pkgCache::State::ConfigFiles))
f55a958f
AL
406 {
407 if (Ver.end() == true)
408 _error->Warning("Encountered status field in a non-version description");
409 else
410 Pkg->CurrentVer = Ver.Index();
411 }
412
dcb79bae
AL
413 return true;
414}
a1826878 415
b2e465d6
AL
416const char *debListParser::ConvertRelation(const char *I,unsigned int &Op)
417{
418 // Determine the operator
419 switch (*I)
420 {
421 case '<':
422 I++;
423 if (*I == '=')
424 {
425 I++;
426 Op = pkgCache::Dep::LessEq;
427 break;
428 }
429
430 if (*I == '<')
431 {
432 I++;
433 Op = pkgCache::Dep::Less;
434 break;
435 }
436
437 // < is the same as <= and << is really Cs < for some reason
438 Op = pkgCache::Dep::LessEq;
439 break;
440
441 case '>':
442 I++;
443 if (*I == '=')
444 {
445 I++;
446 Op = pkgCache::Dep::GreaterEq;
447 break;
448 }
449
450 if (*I == '>')
451 {
452 I++;
453 Op = pkgCache::Dep::Greater;
454 break;
455 }
456
457 // > is the same as >= and >> is really Cs > for some reason
458 Op = pkgCache::Dep::GreaterEq;
459 break;
460
461 case '=':
462 Op = pkgCache::Dep::Equals;
463 I++;
464 break;
465
466 // HACK around bad package definitions
467 default:
468 Op = pkgCache::Dep::Equals;
469 break;
470 }
471 return I;
472}
a1826878
AL
473 /*}}}*/
474// ListParser::ParseDepends - Parse a dependency element /*{{{*/
475// ---------------------------------------------------------------------
476/* This parses the dependency elements out of a standard string in place,
477 bit by bit. */
565ded7b
JS
478const char *debListParser::ParseDepends(const char *Start,const char *Stop,
479 std::string &Package,std::string &Ver,unsigned int &Op)
480 { return ParseDepends(Start, Stop, Package, Ver, Op, false, true, false); }
481const char *debListParser::ParseDepends(const char *Start,const char *Stop,
482 std::string &Package,std::string &Ver,unsigned int &Op,
483 bool const &ParseArchFlags)
484 { return ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, true, false); }
485const char *debListParser::ParseDepends(const char *Start,const char *Stop,
486 std::string &Package,std::string &Ver,unsigned int &Op,
487 bool const &ParseArchFlags, bool const &StripMultiArch)
488 { return ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, StripMultiArch, false); }
dcb79bae
AL
489const char *debListParser::ParseDepends(const char *Start,const char *Stop,
490 string &Package,string &Ver,
41c81fd8 491 unsigned int &Op, bool const &ParseArchFlags,
565ded7b
JS
492 bool const &StripMultiArch,
493 bool const &ParseRestrictionsList)
dcb79bae
AL
494{
495 // Strip off leading space
565ded7b 496 for (;Start != Stop && isspace(*Start) != 0; ++Start);
dcb79bae
AL
497
498 // Parse off the package name
499 const char *I = Start;
500 for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
565ded7b
JS
501 *I != ',' && *I != '|' && *I != '[' && *I != ']' &&
502 *I != '<' && *I != '>'; ++I);
dcb79bae
AL
503
504 // Malformed, no '('
505 if (I != Stop && *I == ')')
506 return 0;
507
508 if (I == Start)
509 return 0;
510
511 // Stash the package name
512 Package.assign(Start,I - Start);
41c81fd8
DK
513
514 // We don't want to confuse library users which can't handle MultiArch
550f6493 515 string const arch = _config->Find("APT::Architecture");
41c81fd8
DK
516 if (StripMultiArch == true) {
517 size_t const found = Package.rfind(':');
550f6493
DK
518 if (found != string::npos &&
519 (strcmp(Package.c_str() + found, ":any") == 0 ||
520 strcmp(Package.c_str() + found, ":native") == 0 ||
521 strcmp(Package.c_str() + found + 1, arch.c_str()) == 0))
41c81fd8
DK
522 Package = Package.substr(0,found);
523 }
524
dcb79bae
AL
525 // Skip white space to the '('
526 for (;I != Stop && isspace(*I) != 0 ; I++);
527
528 // Parse a version
529 if (I != Stop && *I == '(')
530 {
531 // Skip the '('
532 for (I++; I != Stop && isspace(*I) != 0 ; I++);
533 if (I + 3 >= Stop)
534 return 0;
b2e465d6 535 I = ConvertRelation(I,Op);
dcb79bae
AL
536
537 // Skip whitespace
538 for (;I != Stop && isspace(*I) != 0; I++);
539 Start = I;
404528bd
DK
540 I = (const char*) memchr(I, ')', Stop - I);
541 if (I == NULL || Start == I)
542 return 0;
dcb79bae 543
02f000a9
AL
544 // Skip trailing whitespace
545 const char *End = I;
546 for (; End > Start && isspace(End[-1]); End--);
547
171c75f1 548 Ver.assign(Start,End-Start);
dcb79bae
AL
549 I++;
550 }
551 else
552 {
171c75f1 553 Ver.clear();
6c139d6e 554 Op = pkgCache::Dep::NoOp;
dcb79bae
AL
555 }
556
557 // Skip whitespace
558 for (;I != Stop && isspace(*I) != 0; I++);
b2e465d6
AL
559
560 if (ParseArchFlags == true)
561 {
424ff669 562 APT::CacheFilter::PackageArchitectureMatchesSpecification matchesArch(arch, false);
9e10ad8a 563
b2e465d6
AL
564 // Parse an architecture
565 if (I != Stop && *I == '[')
566 {
cd9694bf 567 ++I;
b2e465d6 568 // malformed
cd9694bf
DK
569 if (unlikely(I == Stop))
570 return 0;
571
572 const char *End = I;
573 bool Found = false;
574 bool NegArch = false;
575 while (I != Stop)
b2e465d6 576 {
cd9694bf
DK
577 // look for whitespace or ending ']'
578 for (;End != Stop && !isspace(*End) && *End != ']'; ++End);
579
580 if (unlikely(End == Stop))
b2e465d6 581 return 0;
9e10ad8a
AL
582
583 if (*I == '!')
cd9694bf 584 {
9e10ad8a 585 NegArch = true;
cd9694bf
DK
586 ++I;
587 }
9e10ad8a 588
424ff669
DK
589 std::string arch(I, End);
590 if (arch.empty() == false && matchesArch(arch.c_str()) == true)
cd9694bf 591 {
424ff669 592 Found = true;
cd9694bf
DK
593 if (I[-1] != '!')
594 NegArch = false;
595 // we found a match, so fast-forward to the end of the wildcards
596 for (; End != Stop && *End != ']'; ++End);
597 }
598
b2e465d6
AL
599 if (*End++ == ']') {
600 I = End;
601 break;
602 }
cd9694bf 603
b2e465d6
AL
604 I = End;
605 for (;I != Stop && isspace(*I) != 0; I++);
cd9694bf 606 }
9e10ad8a 607
cd9694bf 608 if (NegArch == true)
9e10ad8a 609 Found = !Found;
cd9694bf
DK
610
611 if (Found == false)
b2e465d6
AL
612 Package = ""; /* not for this arch */
613 }
cd9694bf 614
b2e465d6
AL
615 // Skip whitespace
616 for (;I != Stop && isspace(*I) != 0; I++);
617 }
618
565ded7b
JS
619 if (ParseRestrictionsList == true)
620 {
621 // Parse a restrictions list
622 if (I != Stop && *I == '<')
623 {
624 ++I;
625 // malformed
626 if (unlikely(I == Stop))
627 return 0;
628
ce7f128c 629 std::vector<string> const profiles = APT::Configuration::getBuildProfiles();
565ded7b
JS
630
631 const char *End = I;
632 bool Found = false;
633 bool NegRestriction = false;
634 while (I != Stop)
635 {
636 // look for whitespace or ending '>'
637 for (;End != Stop && !isspace(*End) && *End != '>'; ++End);
638
639 if (unlikely(End == Stop))
640 return 0;
641
642 if (*I == '!')
643 {
644 NegRestriction = true;
645 ++I;
646 }
647
648 std::string restriction(I, End);
649
650 std::string prefix = "profile.";
651 // only support for "profile" prefix, ignore others
652 if (restriction.size() > prefix.size() &&
653 restriction.substr(0, prefix.size()) == prefix)
654 {
655 // get the name of the profile
656 restriction = restriction.substr(prefix.size());
657
658 if (restriction.empty() == false && profiles.empty() == false &&
659 std::find(profiles.begin(), profiles.end(), restriction) != profiles.end())
660 {
661 Found = true;
662 if (I[-1] != '!')
663 NegRestriction = false;
664 // we found a match, so fast-forward to the end of the wildcards
665 for (; End != Stop && *End != '>'; ++End);
666 }
667 }
668
669 if (*End++ == '>') {
670 I = End;
671 break;
672 }
673
674 I = End;
675 for (;I != Stop && isspace(*I) != 0; I++);
676 }
677
678 if (NegRestriction == true)
679 Found = !Found;
680
681 if (Found == false)
682 Package = ""; /* not for this restriction */
683 }
684
685 // Skip whitespace
686 for (;I != Stop && isspace(*I) != 0; I++);
687 }
688
dcb79bae 689 if (I != Stop && *I == '|')
6c139d6e 690 Op |= pkgCache::Dep::Or;
dcb79bae
AL
691
692 if (I == Stop || *I == ',' || *I == '|')
693 {
694 if (I != Stop)
695 for (I++; I != Stop && isspace(*I) != 0; I++);
696 return I;
697 }
698
699 return 0;
700}
701 /*}}}*/
702// ListParser::ParseDepends - Parse a dependency list /*{{{*/
703// ---------------------------------------------------------------------
704/* This is the higher level depends parser. It takes a tag and generates
705 a complete depends tree for the given version. */
32b9a14c 706bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
dcb79bae
AL
707 const char *Tag,unsigned int Type)
708{
709 const char *Start;
710 const char *Stop;
711 if (Section.Find(Tag,Start,Stop) == false)
712 return true;
306eacf6 713
28166356 714 string const pkgArch = Ver.Arch();
dcb79bae 715
8efa2a3b 716 while (1)
dcb79bae 717 {
0f485ee5
TG
718 string Package;
719 string Version;
720 unsigned int Op;
721
565ded7b 722 Start = ParseDepends(Start, Stop, Package, Version, Op, false, false, false);
dcb79bae
AL
723 if (Start == 0)
724 return _error->Error("Problem parsing dependency %s",Tag);
0f485ee5 725 size_t const found = Package.rfind(':');
306eacf6 726
cef094c2
DK
727 // If negative is unspecific it needs to apply on all architectures
728 if (MultiArchEnabled == true && found == string::npos &&
306eacf6
DK
729 (Type == pkgCache::Dep::Conflicts ||
730 Type == pkgCache::Dep::DpkgBreaks ||
731 Type == pkgCache::Dep::Replaces))
732 {
dcfa253f
DK
733 for (std::vector<std::string>::const_iterator a = Architectures.begin();
734 a != Architectures.end(); ++a)
306eacf6
DK
735 if (NewDepends(Ver,Package,*a,Version,Op,Type) == false)
736 return false;
c919ad6e
DK
737 if (NewDepends(Ver,Package,"none",Version,Op,Type) == false)
738 return false;
306eacf6 739 }
0f485ee5
TG
740 else if (MultiArchEnabled == true && found != string::npos &&
741 strcmp(Package.c_str() + found, ":any") != 0)
742 {
743 string Arch = Package.substr(found+1, string::npos);
744 Package = Package.substr(0, found);
745 // Such dependencies are not supposed to be accepted …
746 // … but this is probably the best thing to do.
747 if (Arch == "native")
748 Arch = _config->Find("APT::Architecture");
749 if (NewDepends(Ver,Package,Arch,Version,Op,Type) == false)
750 return false;
751 }
c919ad6e
DK
752 else
753 {
754 if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
755 return false;
756 if ((Type == pkgCache::Dep::Conflicts ||
757 Type == pkgCache::Dep::DpkgBreaks ||
758 Type == pkgCache::Dep::Replaces) &&
759 NewDepends(Ver, Package,
760 (pkgArch != "none") ? "none" : _config->Find("APT::Architecture"),
761 Version,Op,Type) == false)
762 return false;
763 }
8efa2a3b
AL
764 if (Start == Stop)
765 break;
dcb79bae
AL
766 }
767 return true;
768}
769 /*}}}*/
770// ListParser::ParseProvides - Parse the provides list /*{{{*/
771// ---------------------------------------------------------------------
772/* */
32b9a14c 773bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
dcb79bae
AL
774{
775 const char *Start;
776 const char *Stop;
67e0766f 777 if (Section.Find("Provides",Start,Stop) == true)
dcb79bae 778 {
67e0766f
DK
779 string Package;
780 string Version;
28166356 781 string const Arch = Ver.Arch();
67e0766f
DK
782 unsigned int Op;
783
784 while (1)
785 {
786 Start = ParseDepends(Start,Stop,Package,Version,Op);
787 if (Start == 0)
788 return _error->Error("Problem parsing Provides line");
40faab46
DK
789 if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) {
790 _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str());
04340db3
DK
791 } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
792 if (NewProvidesAllArch(Ver, Package, Version) == false)
793 return false;
67e0766f
DK
794 } else {
795 if (NewProvides(Ver, Package, Arch, Version) == false)
796 return false;
797 }
798
799 if (Start == Stop)
800 break;
b63380b0 801 }
67e0766f 802 }
dcb79bae 803
b4140ecf 804 if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
4d174dc8
DK
805 {
806 string const Package = string(Ver.ParentPkg().Name()).append(":").append("any");
60dcec6d 807 return NewProvidesAllArch(Ver, Package, Ver.VerStr());
dcb79bae 808 }
894d672e 809 else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
60dcec6d 810 return NewProvidesAllArch(Ver, Ver.ParentPkg().Name(), Ver.VerStr());
dcb79bae 811
60dcec6d
DK
812 return true;
813}
814 /*}}}*/
815// ListParser::NewProvides - add provides for all architectures /*{{{*/
816bool debListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package,
817 string const &Version) {
dcfa253f
DK
818 for (std::vector<string>::const_iterator a = Architectures.begin();
819 a != Architectures.end(); ++a)
67e0766f
DK
820 {
821 if (NewProvides(Ver, Package, *a, Version) == false)
822 return false;
dcb79bae 823 }
f55a958f
AL
824 return true;
825}
826 /*}}}*/
827// ListParser::GrabWord - Matches a word and returns /*{{{*/
828// ---------------------------------------------------------------------
829/* Looks for a word in a list of words - for ParseStatus */
b2e465d6 830bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
f55a958f 831{
b2e465d6 832 for (unsigned int C = 0; List[C].Str != 0; C++)
f55a958f
AL
833 {
834 if (strcasecmp(Word.c_str(),List[C].Str) == 0)
835 {
836 Out = List[C].Val;
837 return true;
838 }
839 }
840 return false;
841}
842 /*}}}*/
843// ListParser::Step - Move to the next section in the file /*{{{*/
844// ---------------------------------------------------------------------
1e3f4083 845/* This has to be careful to only process the correct architecture */
f55a958f
AL
846bool debListParser::Step()
847{
dcb79bae 848 iOffset = Tags.Offset();
0149949b 849 while (Tags.Step(Section) == true)
ddc1d8d0
AL
850 {
851 /* See if this is the correct Architecture, if it isn't then we
852 drop the whole section. A missing arch tag only happens (in theory)
853 inside the Status file, so that is a positive return */
5dd4c8b8 854 string const Architecture = Section.FindS("Architecture");
9c14e3d6 855
dd13742e 856 if (Arch.empty() == true || Arch == "any" || MultiArchEnabled == false)
5dd4c8b8
DK
857 {
858 if (APT::Configuration::checkArchitecture(Architecture) == true)
859 return true;
c919ad6e
DK
860 /* parse version stanzas without an architecture only in the status file
861 (and as misfortune bycatch flat-archives) */
862 if ((Arch.empty() == true || Arch == "any") && Architecture.empty() == true)
863 return true;
5dd4c8b8
DK
864 }
865 else
866 {
867 if (Architecture == Arch)
868 return true;
0149949b 869
28166356 870 if (Architecture == "all" && Arch == _config->Find("APT::Architecture"))
5dd4c8b8
DK
871 return true;
872 }
dcb79bae
AL
873
874 iOffset = Tags.Offset();
0149949b
AL
875 }
876 return false;
f55a958f
AL
877}
878 /*}}}*/
b0b4efb9
AL
879// ListParser::LoadReleaseInfo - Load the release information /*{{{*/
880// ---------------------------------------------------------------------
881/* */
32b9a14c 882bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
f2152f03 883 FileFd &File, string component)
b0b4efb9 884{
f2152f03
MV
885 // apt-secure does no longer download individual (per-section) Release
886 // file. to provide Component pinning we use the section name now
78a5476f 887 map_stringitem_t const storage = StoreString(pkgCacheGenerator::MIXED, component);
2b803d40 888 FileI->Component = storage;
f2152f03 889
233d79a5 890 pkgTagFile TagFile(&File, File.Size());
e9737c7f
DK
891 pkgTagSection Section;
892 if (_error->PendingError() == true || TagFile.Step(Section) == false)
fe0f7911
DK
893 return false;
894
e9737c7f 895 std::string data;
78a5476f 896 #define APT_INRELEASE(TYPE, TAG, STORE) \
e9737c7f
DK
897 data = Section.FindS(TAG); \
898 if (data.empty() == false) \
899 { \
78a5476f 900 map_stringitem_t const storage = StoreString(pkgCacheGenerator::TYPE, data); \
e9737c7f 901 STORE = storage; \
fe0f7911 902 }
78a5476f
DK
903 APT_INRELEASE(MIXED, "Suite", FileI->Archive)
904 APT_INRELEASE(MIXED, "Component", FileI->Component)
905 APT_INRELEASE(VERSION, "Version", FileI->Version)
906 APT_INRELEASE(MIXED, "Origin", FileI->Origin)
907 APT_INRELEASE(MIXED, "Codename", FileI->Codename)
908 APT_INRELEASE(MIXED, "Label", FileI->Label)
e9737c7f
DK
909 #undef APT_INRELEASE
910 Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic);
911 Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades);
f2152f03 912
b0b4efb9
AL
913 return !_error->PendingError();
914}
915 /*}}}*/
b2e465d6
AL
916// ListParser::GetPrio - Convert the priority from a string /*{{{*/
917// ---------------------------------------------------------------------
918/* */
919unsigned char debListParser::GetPrio(string Str)
920{
921 unsigned char Out;
922 if (GrabWord(Str,PrioList,Out) == false)
923 Out = pkgCache::State::Extra;
924
925 return Out;
926}
927 /*}}}*/
68134bda
DK
928#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
929bool debListParser::SameVersion(unsigned short const Hash, /*{{{*/
930 pkgCache::VerIterator const &Ver)
931{
932 if (pkgCacheGenerator::ListParser::SameVersion(Hash, Ver) == false)
933 return false;
934 // status file has no (Download)Size, but all others are fair game
935 // status file is parsed last, so the first version we encounter is
936 // probably also the version we have downloaded
937 unsigned long long const Size = Section.FindULL("Size");
938 if (Size != 0 && Size != Ver->Size)
939 return false;
940 // available everywhere, but easier to check here than to include in VersionHash
941 unsigned char MultiArch = ParseMultiArch(false);
942 if (MultiArch != Ver->MultiArch)
943 return false;
944 // for all practical proposes (we can check): same version
945 return true;
946}
947 /*}}}*/
948#endif
0d29b9d4
MV
949
950
951debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile)
952 : debListParser(File, ""), DebFile(DebFile)
953{
954}
955
956bool debDebFileParser::UsePackage(pkgCache::PkgIterator &Pkg,
957 pkgCache::VerIterator &Ver)
958{
959 bool res = debListParser::UsePackage(Pkg, Ver);
960 // we use the full file path as a provides so that the file is found
961 // by its name
962 if(NewProvidesAllArch(Ver, DebFile, Ver.VerStr()) == false)
963 return false;
964 return res;
965}
966
967
968