1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $ 
   4 /* ###################################################################### 
   6    Package Cache Generator - Generator for the cache structure. 
   8    This builds the cache structure from the abstract package list parser.  
  10    ##################################################################### */ 
  12 // Include Files                                                        /*{{{*/ 
  15 #include <apt-pkg/deblistparser.h> 
  16 #include <apt-pkg/error.h> 
  17 #include <apt-pkg/configuration.h> 
  18 #include <apt-pkg/cachefilter.h> 
  19 #include <apt-pkg/aptconfiguration.h> 
  20 #include <apt-pkg/strutl.h> 
  21 #include <apt-pkg/fileutl.h> 
  22 #include <apt-pkg/crc-16.h> 
  23 #include <apt-pkg/md5.h> 
  24 #include <apt-pkg/mmap.h> 
  25 #include <apt-pkg/pkgcache.h> 
  26 #include <apt-pkg/cacheiterators.h> 
  27 #include <apt-pkg/tagfile.h> 
  28 #include <apt-pkg/macros.h> 
  40 static 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
}, 
  48 // ListParser::debListParser - Constructor                              /*{{{*/ 
  49 // --------------------------------------------------------------------- 
  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() */ 
  53 debListParser::debListParser(FileFd 
*File
, string 
const &Arch
) : Tags(File
), 
  56       this->Arch 
= _config
->Find("APT::Architecture"); 
  57    Architectures 
= APT::Configuration::getArchitectures(); 
  58    MultiArchEnabled 
= Architectures
.size() > 1; 
  61 // ListParser::Package - Return the package name                        /*{{{*/ 
  62 // --------------------------------------------------------------------- 
  63 /* This is to return the name of the package this section describes */ 
  64 string 
debListParser::Package() { 
  65    string 
const Result 
= Section
.FindS("Package"); 
  66    if(unlikely(Result
.empty() == true)) 
  67       _error
->Error("Encountered a section with no Package: header"); 
  71 // ListParser::Architecture - Return the package arch                   /*{{{*/ 
  72 // --------------------------------------------------------------------- 
  73 /* This will return the Architecture of the package this section describes */ 
  74 string 
debListParser::Architecture() { 
  75    return Section
.FindS("Architecture"); 
  78 // ListParser::ArchitectureAll                                          /*{{{*/ 
  79 // --------------------------------------------------------------------- 
  81 bool debListParser::ArchitectureAll() { 
  82    return Section
.FindS("Architecture") == "all"; 
  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 */ 
  90 string 
debListParser::Version() 
  92    return Section
.FindS("Version"); 
  95 unsigned char debListParser::ParseMultiArch(bool const showErrors
)      /*{{{*/ 
  98    string 
const MultiArch 
= Section
.FindS("Multi-Arch"); 
  99    if (MultiArch
.empty() == true || MultiArch 
== "no") 
 100       MA 
= pkgCache::Version::None
; 
 101    else if (MultiArch 
== "same") { 
 102       if (ArchitectureAll() == true) 
 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
; 
 110          MA 
= pkgCache::Version::Same
; 
 112    else if (MultiArch 
== "foreign") 
 113       MA 
= pkgCache::Version::Foreign
; 
 114    else if (MultiArch 
== "allowed") 
 115       MA 
= pkgCache::Version::Allowed
; 
 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
; 
 124    if (ArchitectureAll() == true) 
 125       MA 
|= pkgCache::Version::All
; 
 130 // ListParser::NewVersion - Fill in the version structure               /*{{{*/ 
 131 // --------------------------------------------------------------------- 
 133 bool debListParser::NewVersion(pkgCache::VerIterator 
&Ver
) 
 139    if (Section
.Find("Section",Start
,Stop
) == true) 
 141       map_stringitem_t 
const idx 
= StoreString(pkgCacheGenerator::SECTION
, Start
, Stop 
- Start
); 
 144    // Parse the source package name 
 145    pkgCache::GrpIterator 
const G 
= Ver
.ParentPkg().Group(); 
 146    Ver
->SourcePkgName 
= G
->Name
; 
 147    Ver
->SourceVerStr 
= Ver
->VerStr
; 
 148    if (Section
.Find("Source",Start
,Stop
) == true) 
 150       const char * const Space 
= (const char * const) memchr(Start
, ' ', Stop 
- Start
); 
 151       pkgCache::VerIterator V
; 
 156          const char * const Open 
= (const char * const) memchr(Space
, '(', Stop 
- Space
); 
 157          if (likely(Open 
!= NULL
)) 
 159             const char * const Close 
= (const char * const) memchr(Open
, ')', Stop 
- Open
); 
 160             if (likely(Close 
!= NULL
)) 
 162                std::string 
const version(Open 
+ 1, (Close 
- Open
) - 1); 
 163                if (version 
!= Ver
.VerStr()) 
 165                   map_stringitem_t 
const idx 
= StoreString(pkgCacheGenerator::VERSION
, version
); 
 166                   Ver
->SourceVerStr 
= idx
; 
 172       std::string 
const pkgname(Start
, Stop 
- Start
); 
 173       if (pkgname 
!= G
.Name()) 
 175          for (pkgCache::PkgIterator P 
= G
.PackageList(); P
.end() == false; P 
= G
.NextPkg(P
)) 
 177             for (V 
= P
.VersionList(); V
.end() == false; ++V
) 
 179                if (pkgname 
== V
.SourcePkgName()) 
 181                   Ver
->SourcePkgName 
= V
->SourcePkgName
; 
 185             if (V
.end() == false) 
 190             map_stringitem_t 
const idx 
= StoreString(pkgCacheGenerator::PKGNAME
, pkgname
); 
 191             Ver
->SourcePkgName 
= idx
; 
 196    Ver
->MultiArch 
= ParseMultiArch(true); 
 198    Ver
->Size 
= Section
.FindULL("Size"); 
 199    // Unpacked Size (in K) 
 200    Ver
->InstalledSize 
= Section
.FindULL("Installed-Size"); 
 201    Ver
->InstalledSize 
*= 1024; 
 204    if (Section
.Find("Priority",Start
,Stop
) == true) 
 206       if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false) 
 207          Ver
->Priority 
= pkgCache::State::Extra
; 
 210    if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false) 
 212    if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false) 
 214    if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false) 
 216    if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false) 
 218    if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false) 
 220    if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false) 
 222    if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false) 
 224    if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false) 
 228    if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false) 
 231    if (ParseProvides(Ver
) == false) 
 237 // ListParser::Description - Return the description string              /*{{{*/ 
 238 // --------------------------------------------------------------------- 
 239 /* This is to return the string describing the package in debian 
 240    form. If this returns the blank string then the entry is assumed to 
 241    only describe package properties */ 
 242 string 
debListParser::Description(std::string 
const &lang
) 
 245       return Section
.FindS("Description"); 
 247       return Section
.FindS(string("Description-").append(lang
).c_str()); 
 250 // ListParser::AvailableDescriptionLanguages                            /*{{{*/ 
 251 std::vector
<std::string
> debListParser::AvailableDescriptionLanguages() 
 253    std::vector
<std::string
> const understood 
= APT::Configuration::getLanguages(); 
 254    std::vector
<std::string
> avail
; 
 255    if (Section
.Exists("Description") == true) 
 257    for (std::vector
<std::string
>::const_iterator lang 
= understood
.begin(); lang 
!= understood
.end(); ++lang
) 
 259       std::string 
const tagname 
= "Description-" + *lang
; 
 260       if (Section
.Exists(tagname
.c_str()) == true) 
 261          avail
.push_back(*lang
); 
 266 // ListParser::Description_md5 - Return the description_md5 MD5SumValue /*{{{*/ 
 267 // --------------------------------------------------------------------- 
 268 /* This is to return the md5 string to allow the check if it is the right 
 269    description. If no Description-md5 is found in the section it will be 
 272 MD5SumValue 
debListParser::Description_md5() 
 274    string 
const value 
= Section
.FindS("Description-md5"); 
 275    if (value
.empty() == true) 
 277       std::string 
const desc 
= Description("") + "\n"; 
 279          return MD5SumValue(); 
 282       md5
.Add(desc
.c_str()); 
 285    else if (likely(value
.size() == 32)) 
 287       if (likely(value
.find_first_not_of("0123456789abcdefABCDEF") == string::npos
)) 
 288          return MD5SumValue(value
); 
 289       _error
->Error("Malformed Description-md5 line; includes invalid character '%s'", value
.c_str()); 
 290       return MD5SumValue(); 
 292    _error
->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value
.size(), value
.c_str()); 
 293    return MD5SumValue(); 
 296 // ListParser::UsePackage - Update a package structure                  /*{{{*/ 
 297 // --------------------------------------------------------------------- 
 298 /* This is called to update the package with any new information  
 299    that might be found in the section */ 
 300 bool debListParser::UsePackage(pkgCache::PkgIterator 
&Pkg
, 
 301                                pkgCache::VerIterator 
&Ver
) 
 303    string 
const static myArch 
= _config
->Find("APT::Architecture"); 
 304    // Possible values are: "all", "native", "installed" and "none" 
 305    // The "installed" mode is handled by ParseStatus(), See #544481 and friends. 
 306    string 
const static essential 
= _config
->Find("pkgCacheGen::Essential", "all"); 
 307    if (essential 
== "all" || 
 308        (essential 
== "native" && Pkg
->Arch 
!= 0 && myArch 
== Pkg
.Arch())) 
 309       if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false) 
 311    if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false) 
 314    if (strcmp(Pkg
.Name(),"apt") == 0) 
 316       if ((essential 
== "native" && Pkg
->Arch 
!= 0 && myArch 
== Pkg
.Arch()) || 
 318          Pkg
->Flags 
|= pkgCache::Flag::Essential 
| pkgCache::Flag::Important
; 
 320          Pkg
->Flags 
|= pkgCache::Flag::Important
; 
 323    if (ParseStatus(Pkg
,Ver
) == false) 
 328 // ListParser::VersionHash - Compute a unique hash for this version     /*{{{*/ 
 329 // --------------------------------------------------------------------- 
 331 unsigned short debListParser::VersionHash() 
 333    const char *Sections
[] ={"Installed-Size", 
 341    unsigned long Result 
= INIT_FCS
; 
 343    for (const char * const *I 
= Sections
; *I 
!= 0; ++I
) 
 347       if (Section
.Find(*I
,Start
,End
) == false || End 
- Start 
>= (signed)sizeof(S
)) 
 350       /* Strip out any spaces from the text, this undoes dpkgs reformatting 
 351          of certain fields. dpkg also has the rather interesting notion of 
 352          reformatting depends operators < -> <= */ 
 354       for (; Start 
!= End
; ++Start
) 
 356          if (isspace(*Start
) != 0) 
 358          *J
++ = tolower_ascii(*Start
); 
 360          if ((*Start 
== '<' || *Start 
== '>') && Start
[1] != *Start 
&& Start
[1] != '=') 
 364       Result 
= AddCRC16(Result
,S
,J 
- S
); 
 370 // ListParser::ParseStatus - Parse the status field                     /*{{{*/ 
 371 // --------------------------------------------------------------------- 
 372 /* Status lines are of the form, 
 373      Status: want flag status 
 374    want = unknown, install, hold, deinstall, purge 
 375    flag = ok, reinstreq, hold, hold-reinstreq 
 376    status = not-installed, unpacked, half-configured, 
 377             half-installed, config-files, post-inst-failed,  
 378             removal-failed, installed 
 380    Some of the above are obsolete (I think?) flag = hold-* and  
 381    status = post-inst-failed, removal-failed at least. 
 383 bool debListParser::ParseStatus(pkgCache::PkgIterator 
&Pkg
, 
 384                                 pkgCache::VerIterator 
&Ver
) 
 388    if (Section
.Find("Status",Start
,Stop
) == false) 
 391    // UsePackage() is responsible for setting the flag in the default case 
 392    bool const static essential 
= _config
->Find("pkgCacheGen::Essential", "") == "installed"; 
 393    if (essential 
== true && 
 394        Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false) 
 397    // Isolate the first word 
 398    const char *I 
= Start
; 
 399    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 400    if (I 
>= Stop 
|| *I 
!= ' ') 
 401       return _error
->Error("Malformed Status line"); 
 403    // Process the want field 
 404    WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
}, 
 405                           {"install",pkgCache::State::Install
}, 
 406                           {"hold",pkgCache::State::Hold
}, 
 407                           {"deinstall",pkgCache::State::DeInstall
}, 
 408                           {"purge",pkgCache::State::Purge
}, 
 410    if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false) 
 411       return _error
->Error("Malformed 1st word in the Status line"); 
 413    // Isloate the next word 
 416    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 417    if (I 
>= Stop 
|| *I 
!= ' ') 
 418       return _error
->Error("Malformed status line, no 2nd word"); 
 420    // Process the flag field 
 421    WordList FlagList
[] = {{"ok",pkgCache::State::Ok
}, 
 422                           {"reinstreq",pkgCache::State::ReInstReq
}, 
 423                           {"hold",pkgCache::State::HoldInst
}, 
 424                           {"hold-reinstreq",pkgCache::State::HoldReInstReq
}, 
 426    if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false) 
 427       return _error
->Error("Malformed 2nd word in the Status line"); 
 429    // Isloate the last word 
 432    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 434       return _error
->Error("Malformed Status line, no 3rd word"); 
 436    // Process the flag field 
 437    WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
}, 
 438                             {"unpacked",pkgCache::State::UnPacked
}, 
 439                             {"half-configured",pkgCache::State::HalfConfigured
}, 
 440                             {"installed",pkgCache::State::Installed
}, 
 441                             {"half-installed",pkgCache::State::HalfInstalled
}, 
 442                             {"config-files",pkgCache::State::ConfigFiles
}, 
 443                             {"triggers-awaited",pkgCache::State::TriggersAwaited
}, 
 444                             {"triggers-pending",pkgCache::State::TriggersPending
}, 
 445                             {"post-inst-failed",pkgCache::State::HalfConfigured
}, 
 446                             {"removal-failed",pkgCache::State::HalfInstalled
}, 
 448    if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false) 
 449       return _error
->Error("Malformed 3rd word in the Status line"); 
 451    /* A Status line marks the package as indicating the current 
 452       version as well. Only if it is actually installed.. Otherwise 
 453       the interesting dpkg handling of the status file creates bogus  
 455    if (!(Pkg
->CurrentState 
== pkgCache::State::NotInstalled 
|| 
 456          Pkg
->CurrentState 
== pkgCache::State::ConfigFiles
)) 
 458       if (Ver
.end() == true) 
 459          _error
->Warning("Encountered status field in a non-version description"); 
 461          Pkg
->CurrentVer 
= Ver
.Index(); 
 467 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
) 
 469    // Determine the operator 
 477          Op 
= pkgCache::Dep::LessEq
; 
 484          Op 
= pkgCache::Dep::Less
; 
 488       // < is the same as <= and << is really Cs < for some reason 
 489       Op 
= pkgCache::Dep::LessEq
; 
 497          Op 
= pkgCache::Dep::GreaterEq
; 
 504          Op 
= pkgCache::Dep::Greater
; 
 508       // > is the same as >= and >> is really Cs > for some reason 
 509       Op 
= pkgCache::Dep::GreaterEq
; 
 513       Op 
= pkgCache::Dep::Equals
; 
 517       // HACK around bad package definitions 
 519       Op 
= pkgCache::Dep::Equals
; 
 525 // ListParser::ParseDepends - Parse a dependency element                /*{{{*/ 
 526 // --------------------------------------------------------------------- 
 527 /* This parses the dependency elements out of a standard string in place, 
 529 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
, 
 530                std::string 
&Package
,std::string 
&Ver
,unsigned int &Op
) 
 531    { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, false, true, false); } 
 532 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
, 
 533                std::string 
&Package
,std::string 
&Ver
,unsigned int &Op
, 
 534                bool const &ParseArchFlags
) 
 535    { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, true, false); } 
 536 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
, 
 537                std::string 
&Package
,std::string 
&Ver
,unsigned int &Op
, 
 538                bool const &ParseArchFlags
, bool const &StripMultiArch
) 
 539    { return ParseDepends(Start
, Stop
, Package
, Ver
, Op
, ParseArchFlags
, StripMultiArch
, false); } 
 540 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
, 
 541                                         string 
&Package
,string 
&Ver
, 
 542                                         unsigned int &Op
, bool const &ParseArchFlags
, 
 543                                         bool const &StripMultiArch
, 
 544                                         bool const &ParseRestrictionsList
) 
 546    // Strip off leading space 
 547    for (;Start 
!= Stop 
&& isspace(*Start
) != 0; ++Start
); 
 549    // Parse off the package name 
 550    const char *I 
= Start
; 
 551    for (;I 
!= Stop 
&& isspace(*I
) == 0 && *I 
!= '(' && *I 
!= ')' && 
 552         *I 
!= ',' && *I 
!= '|' && *I 
!= '[' && *I 
!= ']' && 
 553         *I 
!= '<' && *I 
!= '>'; ++I
); 
 556    if (I 
!= Stop 
&& *I 
== ')') 
 562    // Stash the package name 
 563    Package
.assign(Start
,I 
- Start
); 
 565    // We don't want to confuse library users which can't handle MultiArch 
 566    string 
const arch 
= _config
->Find("APT::Architecture"); 
 567    if (StripMultiArch 
== true) { 
 568       size_t const found 
= Package
.rfind(':'); 
 569       if (found 
!= string::npos 
&& 
 570           (strcmp(Package
.c_str() + found
, ":any") == 0 || 
 571            strcmp(Package
.c_str() + found
, ":native") == 0 || 
 572            strcmp(Package
.c_str() + found 
+ 1, arch
.c_str()) == 0)) 
 573          Package 
= Package
.substr(0,found
); 
 576    // Skip white space to the '(' 
 577    for (;I 
!= Stop 
&& isspace(*I
) != 0 ; I
++); 
 580    if (I 
!= Stop 
&& *I 
== '(') 
 583       for (I
++; I 
!= Stop 
&& isspace(*I
) != 0 ; I
++); 
 586       I 
= ConvertRelation(I
,Op
); 
 589       for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 591       I 
= (const char*) memchr(I
, ')', Stop 
- I
); 
 592       if (I 
== NULL 
|| Start 
== I
) 
 595       // Skip trailing whitespace 
 597       for (; End 
> Start 
&& isspace(End
[-1]); End
--); 
 599       Ver
.assign(Start
,End
-Start
); 
 605       Op 
= pkgCache::Dep::NoOp
; 
 609    for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 611    if (ParseArchFlags 
== true) 
 613       APT::CacheFilter::PackageArchitectureMatchesSpecification 
matchesArch(arch
, false); 
 615       // Parse an architecture 
 616       if (I 
!= Stop 
&& *I 
== '[') 
 620          if (unlikely(I 
== Stop
)) 
 625          bool NegArch 
= false; 
 628             // look for whitespace or ending ']' 
 629             for (;End 
!= Stop 
&& !isspace(*End
) && *End 
!= ']'; ++End
); 
 631             if (unlikely(End 
== Stop
)) 
 640             std::string 
arch(I
, End
); 
 641             if (arch
.empty() == false && matchesArch(arch
.c_str()) == true) 
 646                // we found a match, so fast-forward to the end of the wildcards 
 647                for (; End 
!= Stop 
&& *End 
!= ']'; ++End
); 
 656             for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 663             Package 
= ""; /* not for this arch */ 
 667       for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 670    if (ParseRestrictionsList 
== true) 
 672       // Parse a restrictions list 
 673       if (I 
!= Stop 
&& *I 
== '<') 
 677          if (unlikely(I 
== Stop
)) 
 680          std::vector
<string
> const profiles 
= APT::Configuration::getBuildProfiles(); 
 684          bool NegRestriction 
= false; 
 687             // look for whitespace or ending '>' 
 688             for (;End 
!= Stop 
&& !isspace(*End
) && *End 
!= '>'; ++End
); 
 690             if (unlikely(End 
== Stop
)) 
 695                NegRestriction 
= true; 
 699             std::string 
restriction(I
, End
); 
 701             std::string prefix 
= "profile."; 
 702             // only support for "profile" prefix, ignore others 
 703             if (restriction
.size() > prefix
.size() && 
 704                   restriction
.substr(0, prefix
.size()) == prefix
) 
 706                // get the name of the profile 
 707                restriction 
= restriction
.substr(prefix
.size()); 
 709                if (restriction
.empty() == false && profiles
.empty() == false && 
 710                      std::find(profiles
.begin(), profiles
.end(), restriction
) != profiles
.end()) 
 714                      NegRestriction 
= false; 
 715                   // we found a match, so fast-forward to the end of the wildcards 
 716                   for (; End 
!= Stop 
&& *End 
!= '>'; ++End
); 
 726             for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 729          if (NegRestriction 
== true) 
 733             Package 
= ""; /* not for this restriction */ 
 737       for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 740    if (I 
!= Stop 
&& *I 
== '|') 
 741       Op 
|= pkgCache::Dep::Or
; 
 743    if (I 
== Stop 
|| *I 
== ',' || *I 
== '|') 
 746          for (I
++; I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 753 // ListParser::ParseDepends - Parse a dependency list                   /*{{{*/ 
 754 // --------------------------------------------------------------------- 
 755 /* This is the higher level depends parser. It takes a tag and generates 
 756    a complete depends tree for the given version. */ 
 757 bool debListParser::ParseDepends(pkgCache::VerIterator 
&Ver
, 
 758                                  const char *Tag
,unsigned int Type
) 
 762    if (Section
.Find(Tag
,Start
,Stop
) == false) 
 765    string 
const pkgArch 
= Ver
.Arch(); 
 773       Start 
= ParseDepends(Start
, Stop
, Package
, Version
, Op
, false, false, false); 
 775          return _error
->Error("Problem parsing dependency %s",Tag
); 
 776       size_t const found 
= Package
.rfind(':'); 
 778       // If negative is unspecific it needs to apply on all architectures 
 779       if (MultiArchEnabled 
== true && found 
== string::npos 
&& 
 780           (Type 
== pkgCache::Dep::Conflicts 
|| 
 781            Type 
== pkgCache::Dep::DpkgBreaks 
|| 
 782            Type 
== pkgCache::Dep::Replaces
)) 
 784          for (std::vector
<std::string
>::const_iterator a 
= Architectures
.begin(); 
 785               a 
!= Architectures
.end(); ++a
) 
 786             if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false) 
 788          if (NewDepends(Ver
,Package
,"none",Version
,Op
,Type
) == false) 
 791       else if (MultiArchEnabled 
== true && found 
!= string::npos 
&& 
 792                strcmp(Package
.c_str() + found
, ":any") != 0) 
 794          string Arch 
= Package
.substr(found
+1, string::npos
); 
 795          Package 
= Package
.substr(0, found
); 
 796          // Such dependencies are not supposed to be accepted … 
 797          // … but this is probably the best thing to do. 
 798          if (Arch 
== "native") 
 799             Arch 
= _config
->Find("APT::Architecture"); 
 800          if (NewDepends(Ver
,Package
,Arch
,Version
,Op
,Type
) == false) 
 805          if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false) 
 807          if ((Type 
== pkgCache::Dep::Conflicts 
|| 
 808               Type 
== pkgCache::Dep::DpkgBreaks 
|| 
 809               Type 
== pkgCache::Dep::Replaces
) && 
 810              NewDepends(Ver
, Package
, 
 811                         (pkgArch 
!= "none") ? "none" : _config
->Find("APT::Architecture"), 
 812                         Version
,Op
,Type
) == false) 
 821 // ListParser::ParseProvides - Parse the provides list                  /*{{{*/ 
 822 // --------------------------------------------------------------------- 
 824 bool debListParser::ParseProvides(pkgCache::VerIterator 
&Ver
) 
 828    if (Section
.Find("Provides",Start
,Stop
) == true) 
 832       string 
const Arch 
= Ver
.Arch(); 
 837          Start 
= ParseDepends(Start
,Stop
,Package
,Version
,Op
); 
 839             return _error
->Error("Problem parsing Provides line"); 
 840          if (Op 
!= pkgCache::Dep::NoOp 
&& Op 
!= pkgCache::Dep::Equals
) { 
 841             _error
->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package
.c_str()); 
 842          } else if ((Ver
->MultiArch 
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) { 
 843             if (NewProvidesAllArch(Ver
, Package
, Version
) == false) 
 846             if (NewProvides(Ver
, Package
, Arch
, Version
) == false) 
 855    if ((Ver
->MultiArch 
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
) 
 857       string 
const Package 
= string(Ver
.ParentPkg().Name()).append(":").append("any"); 
 858       return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr()); 
 860    else if ((Ver
->MultiArch 
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) 
 861       return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr()); 
 866 // ListParser::NewProvides - add provides for all architectures         /*{{{*/ 
 867 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator 
&Ver
, string 
const &Package
, 
 868                                 string 
const &Version
) { 
 869    for (std::vector
<string
>::const_iterator a 
= Architectures
.begin(); 
 870         a 
!= Architectures
.end(); ++a
) 
 872       if (NewProvides(Ver
, Package
, *a
, Version
) == false) 
 878 // ListParser::GrabWord - Matches a word and returns                    /*{{{*/ 
 879 // --------------------------------------------------------------------- 
 880 /* Looks for a word in a list of words - for ParseStatus */ 
 881 bool debListParser::GrabWord(string Word
,WordList 
*List
,unsigned char &Out
) 
 883    for (unsigned int C 
= 0; List
[C
].Str 
!= 0; C
++) 
 885       if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0) 
 894 // ListParser::Step - Move to the next section in the file              /*{{{*/ 
 895 // --------------------------------------------------------------------- 
 896 /* This has to be careful to only process the correct architecture */ 
 897 bool debListParser::Step() 
 899    iOffset 
= Tags
.Offset(); 
 900    while (Tags
.Step(Section
) == true) 
 902       /* See if this is the correct Architecture, if it isn't then we 
 903          drop the whole section. A missing arch tag only happens (in theory) 
 904          inside the Status file, so that is a positive return */ 
 905       string 
const Architecture 
= Section
.FindS("Architecture"); 
 907       if (Arch
.empty() == true || Arch 
== "any" || MultiArchEnabled 
== false) 
 909          if (APT::Configuration::checkArchitecture(Architecture
) == true) 
 911          /* parse version stanzas without an architecture only in the status file 
 912             (and as misfortune bycatch flat-archives) */ 
 913          if ((Arch
.empty() == true || Arch 
== "any") && Architecture
.empty() == true) 
 918          if (Architecture 
== Arch
) 
 921          if (Architecture 
== "all" && Arch 
== _config
->Find("APT::Architecture")) 
 925       iOffset 
= Tags
.Offset(); 
 930 // ListParser::LoadReleaseInfo - Load the release information           /*{{{*/ 
 931 // --------------------------------------------------------------------- 
 933 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator 
&FileI
, 
 934                                     FileFd 
&File
, string component
) 
 936    // apt-secure does no longer download individual (per-section) Release 
 937    // file. to provide Component pinning we use the section name now 
 938    map_stringitem_t 
const storage 
= StoreString(pkgCacheGenerator::MIXED
, component
); 
 939    FileI
->Component 
= storage
; 
 941    pkgTagFile 
TagFile(&File
, File
.Size()); 
 942    pkgTagSection Section
; 
 943    if (_error
->PendingError() == true || TagFile
.Step(Section
) == false) 
 947    #define APT_INRELEASE(TYPE, TAG, STORE) \ 
 948    data = Section.FindS(TAG); \ 
 949    if (data.empty() == false) \ 
 951       map_stringitem_t const storage = StoreString(pkgCacheGenerator::TYPE, data); \ 
 954    APT_INRELEASE(MIXED
, "Suite", FileI
->Archive
) 
 955    APT_INRELEASE(MIXED
, "Component", FileI
->Component
) 
 956    APT_INRELEASE(VERSION
, "Version", FileI
->Version
) 
 957    APT_INRELEASE(MIXED
, "Origin", FileI
->Origin
) 
 958    APT_INRELEASE(MIXED
, "Codename", FileI
->Codename
) 
 959    APT_INRELEASE(MIXED
, "Label", FileI
->Label
) 
 961    Section
.FindFlag("NotAutomatic", FileI
->Flags
, pkgCache::Flag::NotAutomatic
); 
 962    Section
.FindFlag("ButAutomaticUpgrades", FileI
->Flags
, pkgCache::Flag::ButAutomaticUpgrades
); 
 964    return !_error
->PendingError(); 
 967 // ListParser::GetPrio - Convert the priority from a string             /*{{{*/ 
 968 // --------------------------------------------------------------------- 
 970 unsigned char debListParser::GetPrio(string Str
) 
 973    if (GrabWord(Str
,PrioList
,Out
) == false) 
 974       Out 
= pkgCache::State::Extra
; 
 979 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) 
 980 bool debListParser::SameVersion(unsigned short const Hash
,              /*{{{*/ 
 981       pkgCache::VerIterator 
const &Ver
) 
 983    if (pkgCacheGenerator::ListParser::SameVersion(Hash
, Ver
) == false) 
 985    // status file has no (Download)Size, but all others are fair game 
 986    // status file is parsed last, so the first version we encounter is 
 987    // probably also the version we have downloaded 
 988    unsigned long long const Size 
= Section
.FindULL("Size"); 
 989    if (Size 
!= 0 && Size 
!= Ver
->Size
) 
 991    // available everywhere, but easier to check here than to include in VersionHash 
 992    unsigned char MultiArch 
= ParseMultiArch(false); 
 993    if (MultiArch 
!= Ver
->MultiArch
) 
 995    // for all practical proposes (we can check): same version 
1002 debDebFileParser::debDebFileParser(FileFd 
*File
, std::string 
const &DebFile
) 
1003    : debListParser(File
, ""), DebFile(DebFile
) 
1007 bool debDebFileParser::UsePackage(pkgCache::PkgIterator 
&Pkg
, 
1008                                   pkgCache::VerIterator 
&Ver
) 
1010    bool res 
= debListParser::UsePackage(Pkg
, Ver
); 
1011    // we use the full file path as a provides so that the file is found 
1013    if(NewProvidesAllArch(Ver
, DebFile
, Ver
.VerStr()) == false)