]>
git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
   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                                                        /*{{{*/ 
  13 #include <apt-pkg/deblistparser.h> 
  14 #include <apt-pkg/error.h> 
  15 #include <apt-pkg/configuration.h> 
  16 #include <apt-pkg/aptconfiguration.h> 
  17 #include <apt-pkg/strutl.h> 
  18 #include <apt-pkg/crc-16.h> 
  19 #include <apt-pkg/md5.h> 
  20 #include <apt-pkg/macros.h> 
  26 static debListParser::WordList PrioList
[] = {{"important",pkgCache::State::Important
}, 
  27                        {"required",pkgCache::State::Required
}, 
  28                        {"standard",pkgCache::State::Standard
}, 
  29                        {"optional",pkgCache::State::Optional
}, 
  30                        {"extra",pkgCache::State::Extra
}, 
  33 // ListParser::debListParser - Constructor                              /*{{{*/ 
  34 // --------------------------------------------------------------------- 
  35 /* Provide an architecture and only this one and "all" will be accepted 
  36    in Step(), if no Architecture is given we will accept every arch 
  37    we would accept in general with checkArchitecture() */ 
  38 debListParser::debListParser(FileFd 
*File
, string 
const &Arch
) : Tags(File
), 
  41       this->Arch 
= _config
->Find("APT::Architecture"); 
  42    Architectures 
= APT::Configuration::getArchitectures(); 
  43    MultiArchEnabled 
= Architectures
.size() > 1; 
  46 // ListParser::UniqFindTagWrite - Find the tag and write a unq string   /*{{{*/ 
  47 // --------------------------------------------------------------------- 
  49 unsigned long debListParser::UniqFindTagWrite(const char *Tag
) 
  53    if (Section
.Find(Tag
,Start
,Stop
) == false) 
  55    return WriteUniqString(Start
,Stop 
- Start
); 
  58 // ListParser::Package - Return the package name                        /*{{{*/ 
  59 // --------------------------------------------------------------------- 
  60 /* This is to return the name of the package this section describes */ 
  61 string 
debListParser::Package() { 
  62    string 
const Result 
= Section
.FindS("Package"); 
  63    if(unlikely(Result
.empty() == true)) 
  64       _error
->Error("Encountered a section with no Package: header"); 
  68 // ListParser::Architecture - Return the package arch                   /*{{{*/ 
  69 // --------------------------------------------------------------------- 
  70 /* This will return the Architecture of the package this section describes 
  71    Note that architecture "all" packages will get the architecture of the 
  72    Packages file parsed here. */ 
  73 string 
debListParser::Architecture() { 
  74    string 
const Result 
= Section
.FindS("Architecture"); 
  75    if (Result
.empty() == true || Result 
== "all") 
  77       if (Arch
.empty() == true) 
  78          /* FIXME: this is a problem for installed arch all 
  79             packages as we don't know from which arch this 
  80             package was installed - and therefore which 
  81             dependency this package resolves. */ 
  82          return _config
->Find("APT::Architecture"); 
  89 // ListParser::ArchitectureAll                                          /*{{{*/ 
  90 // --------------------------------------------------------------------- 
  92 bool debListParser::ArchitectureAll() { 
  93    return Section
.FindS("Architecture") == "all"; 
  96 // ListParser::Version - Return the version string                      /*{{{*/ 
  97 // --------------------------------------------------------------------- 
  98 /* This is to return the string describing the version in debian form, 
  99    epoch:upstream-release. If this returns the blank string then the  
 100    entry is assumed to only describe package properties */ 
 101 string 
debListParser::Version() 
 103    return Section
.FindS("Version"); 
 106 // ListParser::NewVersion - Fill in the version structure               /*{{{*/ 
 107 // --------------------------------------------------------------------- 
 109 bool debListParser::NewVersion(pkgCache::VerIterator 
&Ver
) 
 112    Ver
->Section 
= UniqFindTagWrite("Section"); 
 115    if (Section
.FindS("Architecture") == "all") 
 116       /* Arch all packages can't have a Multi-Arch field, 
 117          but we need a special treatment for them nonetheless */ 
 118       Ver
->MultiArch 
= pkgCache::Version::All
; 
 121       string 
const MultiArch 
= Section
.FindS("Multi-Arch"); 
 122       if (MultiArch
.empty() == true) 
 123          Ver
->MultiArch 
= pkgCache::Version::None
; 
 124       else if (MultiArch 
== "same") 
 125          Ver
->MultiArch 
= pkgCache::Version::Same
; 
 126       else if (MultiArch 
== "foreign") 
 127          Ver
->MultiArch 
= pkgCache::Version::Foreign
; 
 128       else if (MultiArch 
== "allowed") 
 129          Ver
->MultiArch 
= pkgCache::Version::Allowed
; 
 132          _error
->Warning("Unknown Multi-Arch type »%s« for package »%s«", 
 133                         MultiArch
.c_str(), Section
.FindS("Package").c_str()); 
 134          Ver
->MultiArch 
= pkgCache::Version::None
; 
 139    Ver
->Size 
= Section
.FindULL("Size"); 
 140    // Unpacked Size (in K) 
 141    Ver
->InstalledSize 
= Section
.FindULL("Installed-Size"); 
 142    Ver
->InstalledSize 
*= 1024; 
 147    if (Section
.Find("Priority",Start
,Stop
) == true) 
 149       if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false) 
 150          Ver
->Priority 
= pkgCache::State::Extra
; 
 153    if (Ver
->MultiArch 
== pkgCache::Version::All
) 
 155       /* We maintain a "pseudo" arch=all package for architecture all versions 
 156          on which these versions can depend on. This pseudo package is many used 
 157          for downloading/installing: The other pseudo-packages will degenerate 
 158          to a NOP in the download/install step - this package will ensure that 
 159          it is downloaded only one time and installed only one time -- even if 
 160          the architecture bound versions coming in and out on regular basis. */ 
 161       if (strcmp(Ver
.Arch(true),"all") == 0) 
 163       else if (MultiArchEnabled 
== true) 
 165          // our pseudo packages have no size to not confuse the fetcher 
 167          Ver
->InstalledSize 
= 0; 
 171    if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false) 
 173    if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false) 
 175    if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false) 
 177    if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false) 
 179    if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false) 
 181    if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false) 
 183    if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false) 
 185    if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false) 
 189    if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false) 
 192    if (ParseProvides(Ver
) == false) 
 198 // ListParser::Description - Return the description string              /*{{{*/ 
 199 // --------------------------------------------------------------------- 
 200 /* This is to return the string describing the package in debian 
 201    form. If this returns the blank string then the entry is assumed to 
 202    only describe package properties */ 
 203 string 
debListParser::Description() 
 205    string 
const lang 
= DescriptionLanguage(); 
 207       return Section
.FindS("Description"); 
 209       return Section
.FindS(string("Description-").append(lang
).c_str()); 
 212 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/ 
 213 // --------------------------------------------------------------------- 
 214 /* This is to return the string describing the language of 
 215    description. If this returns the blank string then the entry is 
 216    assumed to describe original description. */ 
 217 string 
debListParser::DescriptionLanguage() 
 219    if (Section
.FindS("Description").empty() == false) 
 222    std::vector
<string
> const lang 
= APT::Configuration::getLanguages(); 
 223    for (std::vector
<string
>::const_iterator l 
= lang
.begin(); 
 224         l 
!= lang
.end(); l
++) 
 225       if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false) 
 231 // ListParser::Description - Return the description_md5 MD5SumValue     /*{{{*/ 
 232 // --------------------------------------------------------------------- 
 233 /* This is to return the md5 string to allow the check if it is the right 
 234    description. If no Description-md5 is found in the section it will be 
 237 MD5SumValue 
debListParser::Description_md5() 
 239    string value 
= Section
.FindS("Description-md5"); 
 244       md5
.Add((Description() + "\n").c_str()); 
 247       return MD5SumValue(value
); 
 250 // ListParser::UsePackage - Update a package structure                  /*{{{*/ 
 251 // --------------------------------------------------------------------- 
 252 /* This is called to update the package with any new information  
 253    that might be found in the section */ 
 254 bool debListParser::UsePackage(pkgCache::PkgIterator 
&Pkg
, 
 255                                pkgCache::VerIterator 
&Ver
) 
 257    if (Pkg
->Section 
== 0) 
 258       Pkg
->Section 
= UniqFindTagWrite("Section"); 
 260    // Packages which are not from the "native" arch doesn't get the essential flag 
 261    // in the default "native" mode - it is also possible to mark "all" or "none". 
 262    // The "installed" mode is handled by ParseStatus(), See #544481 and friends. 
 263    string 
const static myArch 
= _config
->Find("APT::Architecture"); 
 264    string 
const static essential 
= _config
->Find("pkgCacheGen::Essential", "native"); 
 265    if ((essential 
== "native" && Pkg
->Arch 
!= 0 && myArch 
== Pkg
.Arch()) || 
 267       if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false) 
 269    if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false) 
 272    if (strcmp(Pkg
.Name(),"apt") == 0) 
 273       Pkg
->Flags 
|= pkgCache::Flag::Important
; 
 275    if (ParseStatus(Pkg
,Ver
) == false) 
 280 // ListParser::VersionHash - Compute a unique hash for this version     /*{{{*/ 
 281 // --------------------------------------------------------------------- 
 283 unsigned short debListParser::VersionHash() 
 285    const char *Sections
[] ={"Installed-Size", 
 293    unsigned long Result 
= INIT_FCS
; 
 295    for (const char **I 
= Sections
; *I 
!= 0; I
++) 
 299       if (Section
.Find(*I
,Start
,End
) == false || End 
- Start 
>= (signed)sizeof(S
)) 
 302       /* Strip out any spaces from the text, this undoes dpkgs reformatting 
 303          of certain fields. dpkg also has the rather interesting notion of 
 304          reformatting depends operators < -> <= */ 
 306       for (; Start 
!= End
; Start
++) 
 308          if (isspace(*Start
) == 0) 
 309             *I
++ = tolower_ascii(*Start
); 
 310          if (*Start 
== '<' && Start
[1] != '<' && Start
[1] != '=') 
 312          if (*Start 
== '>' && Start
[1] != '>' && Start
[1] != '=') 
 316       Result 
= AddCRC16(Result
,S
,I 
- S
); 
 322 // ListParser::ParseStatus - Parse the status field                     /*{{{*/ 
 323 // --------------------------------------------------------------------- 
 324 /* Status lines are of the form, 
 325      Status: want flag status 
 326    want = unknown, install, hold, deinstall, purge 
 327    flag = ok, reinstreq, hold, hold-reinstreq 
 328    status = not-installed, unpacked, half-configured, 
 329             half-installed, config-files, post-inst-failed,  
 330             removal-failed, installed 
 332    Some of the above are obsolete (I think?) flag = hold-* and  
 333    status = post-inst-failed, removal-failed at least. 
 335 bool debListParser::ParseStatus(pkgCache::PkgIterator 
&Pkg
, 
 336                                 pkgCache::VerIterator 
&Ver
) 
 340    if (Section
.Find("Status",Start
,Stop
) == false) 
 343    // UsePackage() is responsible for setting the flag in the default case 
 344    bool const static essential 
= _config
->Find("pkgCacheGen::Essential", "") == "installed"; 
 345    if (essential 
== true && 
 346        Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false) 
 349    // Isolate the first word 
 350    const char *I 
= Start
; 
 351    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 352    if (I 
>= Stop 
|| *I 
!= ' ') 
 353       return _error
->Error("Malformed Status line"); 
 355    // Process the want field 
 356    WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
}, 
 357                           {"install",pkgCache::State::Install
}, 
 358                           {"hold",pkgCache::State::Hold
}, 
 359                           {"deinstall",pkgCache::State::DeInstall
}, 
 360                           {"purge",pkgCache::State::Purge
}, 
 362    if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false) 
 363       return _error
->Error("Malformed 1st word in the Status line"); 
 365    // Isloate the next word 
 368    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 369    if (I 
>= Stop 
|| *I 
!= ' ') 
 370       return _error
->Error("Malformed status line, no 2nd word"); 
 372    // Process the flag field 
 373    WordList FlagList
[] = {{"ok",pkgCache::State::Ok
}, 
 374                           {"reinstreq",pkgCache::State::ReInstReq
}, 
 375                           {"hold",pkgCache::State::HoldInst
}, 
 376                           {"hold-reinstreq",pkgCache::State::HoldReInstReq
}, 
 378    if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false) 
 379       return _error
->Error("Malformed 2nd word in the Status line"); 
 381    // Isloate the last word 
 384    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 386       return _error
->Error("Malformed Status line, no 3rd word"); 
 388    // Process the flag field 
 389    WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
}, 
 390                             {"unpacked",pkgCache::State::UnPacked
}, 
 391                             {"half-configured",pkgCache::State::HalfConfigured
}, 
 392                             {"installed",pkgCache::State::Installed
}, 
 393                             {"half-installed",pkgCache::State::HalfInstalled
}, 
 394                             {"config-files",pkgCache::State::ConfigFiles
}, 
 395                             {"triggers-awaited",pkgCache::State::TriggersAwaited
}, 
 396                             {"triggers-pending",pkgCache::State::TriggersPending
}, 
 397                             {"post-inst-failed",pkgCache::State::HalfConfigured
}, 
 398                             {"removal-failed",pkgCache::State::HalfInstalled
}, 
 400    if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false) 
 401       return _error
->Error("Malformed 3rd word in the Status line"); 
 403    /* A Status line marks the package as indicating the current 
 404       version as well. Only if it is actually installed.. Otherwise 
 405       the interesting dpkg handling of the status file creates bogus  
 407    if (!(Pkg
->CurrentState 
== pkgCache::State::NotInstalled 
|| 
 408          Pkg
->CurrentState 
== pkgCache::State::ConfigFiles
)) 
 410       if (Ver
.end() == true) 
 411          _error
->Warning("Encountered status field in a non-version description"); 
 413          Pkg
->CurrentVer 
= Ver
.Index(); 
 419 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
) 
 421    // Determine the operator 
 429          Op 
= pkgCache::Dep::LessEq
; 
 436          Op 
= pkgCache::Dep::Less
; 
 440       // < is the same as <= and << is really Cs < for some reason 
 441       Op 
= pkgCache::Dep::LessEq
; 
 449          Op 
= pkgCache::Dep::GreaterEq
; 
 456          Op 
= pkgCache::Dep::Greater
; 
 460       // > is the same as >= and >> is really Cs > for some reason 
 461       Op 
= pkgCache::Dep::GreaterEq
; 
 465       Op 
= pkgCache::Dep::Equals
; 
 469       // HACK around bad package definitions 
 471       Op 
= pkgCache::Dep::Equals
; 
 480  * The complete architecture, consisting of <kernel>-<cpu>. 
 482 static string 
CompleteArch(std::string
& arch
) { 
 483     if (arch 
== "armel")              return "linux-arm"; 
 484     if (arch 
== "lpia")               return "linux-i386"; 
 485     if (arch 
== "powerpcspe")         return "linux-powerpc"; 
 486     if (arch 
== "uclibc-linux-armel") return "linux-arm"; 
 487     if (arch 
== "uclinux-armel")      return "uclinux-arm"; 
 489     return (arch
.find("-") != string::npos
) ? arch 
: "linux-" + arch
; 
 492 // ListParser::ParseDepends - Parse a dependency element                /*{{{*/ 
 493 // --------------------------------------------------------------------- 
 494 /* This parses the dependency elements out of a standard string in place, 
 496 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
, 
 497                                         string 
&Package
,string 
&Ver
, 
 498                                         unsigned int &Op
, bool const &ParseArchFlags
, 
 499                                         bool const &StripMultiArch
) 
 501    // Strip off leading space 
 502    for (;Start 
!= Stop 
&& isspace(*Start
) != 0; Start
++); 
 504    // Parse off the package name 
 505    const char *I 
= Start
; 
 506    for (;I 
!= Stop 
&& isspace(*I
) == 0 && *I 
!= '(' && *I 
!= ')' && 
 507         *I 
!= ',' && *I 
!= '|'; I
++); 
 510    if (I 
!= Stop 
&& *I 
== ')') 
 516    // Stash the package name 
 517    Package
.assign(Start
,I 
- Start
); 
 519    // We don't want to confuse library users which can't handle MultiArch 
 520    if (StripMultiArch 
== true) { 
 521       size_t const found 
= Package
.rfind(':'); 
 522       if (found 
!= string::npos
) 
 523          Package 
= Package
.substr(0,found
); 
 526    // Skip white space to the '(' 
 527    for (;I 
!= Stop 
&& isspace(*I
) != 0 ; I
++); 
 530    if (I 
!= Stop 
&& *I 
== '(') 
 533       for (I
++; I 
!= Stop 
&& isspace(*I
) != 0 ; I
++); 
 536       I 
= ConvertRelation(I
,Op
); 
 539       for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 541       for (;I 
!= Stop 
&& *I 
!= ')'; I
++); 
 542       if (I 
== Stop 
|| Start 
== I
) 
 545       // Skip trailing whitespace 
 547       for (; End 
> Start 
&& isspace(End
[-1]); End
--); 
 549       Ver
.assign(Start
,End
-Start
); 
 555       Op 
= pkgCache::Dep::NoOp
; 
 559    for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 561    if (ParseArchFlags 
== true) 
 563       string arch 
= _config
->Find("APT::Architecture"); 
 564       string completeArch 
= CompleteArch(arch
); 
 566       // Parse an architecture 
 567       if (I 
!= Stop 
&& *I 
== '[') 
 576          bool NegArch 
= false; 
 579             // look for whitespace or ending ']' 
 580             while (End 
!= Stop 
&& !isspace(*End
) && *End 
!= ']')  
 592             if (stringcmp(arch
,I
,End
) == 0) { 
 595                std::string wildcard 
= SubstVar(string(I
, End
), "any", "*"); 
 596                if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0) 
 606             for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 613             Package 
= ""; /* not for this arch */ 
 617       for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 620    if (I 
!= Stop 
&& *I 
== '|') 
 621       Op 
|= pkgCache::Dep::Or
; 
 623    if (I 
== Stop 
|| *I 
== ',' || *I 
== '|') 
 626          for (I
++; I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 633 // ListParser::ParseDepends - Parse a dependency list                   /*{{{*/ 
 634 // --------------------------------------------------------------------- 
 635 /* This is the higher level depends parser. It takes a tag and generates 
 636    a complete depends tree for the given version. */ 
 637 bool debListParser::ParseDepends(pkgCache::VerIterator 
&Ver
, 
 638                                  const char *Tag
,unsigned int Type
) 
 642    if (Section
.Find(Tag
,Start
,Stop
) == false) 
 646    string 
const pkgArch 
= Ver
.Arch(true); 
 652       Start 
= ParseDepends(Start
,Stop
,Package
,Version
,Op
); 
 654          return _error
->Error("Problem parsing dependency %s",Tag
); 
 656       if (MultiArchEnabled 
== true && 
 657           (Type 
== pkgCache::Dep::Conflicts 
|| 
 658            Type 
== pkgCache::Dep::DpkgBreaks 
|| 
 659            Type 
== pkgCache::Dep::Replaces
)) 
 661          for (std::vector
<std::string
>::const_iterator a 
= Architectures
.begin(); 
 662               a 
!= Architectures
.end(); ++a
) 
 663             if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false) 
 666       else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false) 
 674 // ListParser::ParseProvides - Parse the provides list                  /*{{{*/ 
 675 // --------------------------------------------------------------------- 
 677 bool debListParser::ParseProvides(pkgCache::VerIterator 
&Ver
) 
 681    if (Section
.Find("Provides",Start
,Stop
) == true) 
 685       string 
const Arch 
= Ver
.Arch(true); 
 690          Start 
= ParseDepends(Start
,Stop
,Package
,Version
,Op
); 
 692             return _error
->Error("Problem parsing Provides line"); 
 693          if (Op 
!= pkgCache::Dep::NoOp
) { 
 694             _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str()); 
 696             if (NewProvides(Ver
, Package
, Arch
, Version
) == false) 
 705    if (Ver
->MultiArch 
== pkgCache::Version::Allowed
) 
 707       string 
const Package 
= string(Ver
.ParentPkg().Name()).append(":").append("any"); 
 708       NewProvides(Ver
, Package
, "any", Ver
.VerStr()); 
 711    if (Ver
->MultiArch 
!= pkgCache::Version::Foreign
) 
 714    if (MultiArchEnabled 
== false) 
 717    string 
const Package 
= Ver
.ParentPkg().Name(); 
 718    string 
const Version 
= Ver
.VerStr(); 
 719    for (std::vector
<string
>::const_iterator a 
= Architectures
.begin(); 
 720         a 
!= Architectures
.end(); ++a
) 
 722       if (NewProvides(Ver
, Package
, *a
, Version
) == false) 
 729 // ListParser::GrabWord - Matches a word and returns                    /*{{{*/ 
 730 // --------------------------------------------------------------------- 
 731 /* Looks for a word in a list of words - for ParseStatus */ 
 732 bool debListParser::GrabWord(string Word
,WordList 
*List
,unsigned char &Out
) 
 734    for (unsigned int C 
= 0; List
[C
].Str 
!= 0; C
++) 
 736       if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0) 
 745 // ListParser::Step - Move to the next section in the file              /*{{{*/ 
 746 // --------------------------------------------------------------------- 
 747 /* This has to be carefull to only process the correct architecture */ 
 748 bool debListParser::Step() 
 750    iOffset 
= Tags
.Offset(); 
 751    while (Tags
.Step(Section
) == true) 
 753       /* See if this is the correct Architecture, if it isn't then we 
 754          drop the whole section. A missing arch tag only happens (in theory) 
 755          inside the Status file, so that is a positive return */ 
 756       string 
const Architecture 
= Section
.FindS("Architecture"); 
 757       if (Architecture
.empty() == true) 
 760       if (Arch
.empty() == true || MultiArchEnabled 
== false) 
 762          if (APT::Configuration::checkArchitecture(Architecture
) == true) 
 767          if (Architecture 
== Arch
) 
 770          if (Architecture 
== "all") 
 774       iOffset 
= Tags
.Offset(); 
 779 // ListParser::LoadReleaseInfo - Load the release information           /*{{{*/ 
 780 // --------------------------------------------------------------------- 
 782 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator 
&FileI
, 
 783                                     FileFd 
&File
, string component
) 
 785    pkgTagFile 
Tags(&File
, File
.Size() + 256); // XXX 
 786    pkgTagSection Section
; 
 787    if (Tags
.Step(Section
) == false) 
 790    // FIXME: Do we need it now for multi-arch? 
 791    // mvo: I don't think we need to fill that in (it's unused since apt-0.6) 
 792 //    FileI->Architecture = WriteUniqString(Arch); 
 794    // apt-secure does no longer download individual (per-section) Release 
 795    // file. to provide Component pinning we use the section name now 
 796    FileI
->Component 
= WriteUniqString(component
); 
 800    if (Section
.Find("Suite",Start
,Stop
) == true) 
 801       FileI
->Archive 
= WriteUniqString(Start
,Stop 
- Start
); 
 802    if (Section
.Find("Component",Start
,Stop
) == true) 
 803       FileI
->Component 
= WriteUniqString(Start
,Stop 
- Start
); 
 804    if (Section
.Find("Version",Start
,Stop
) == true) 
 805       FileI
->Version 
= WriteUniqString(Start
,Stop 
- Start
); 
 806    if (Section
.Find("Origin",Start
,Stop
) == true) 
 807       FileI
->Origin 
= WriteUniqString(Start
,Stop 
- Start
); 
 808    if (Section
.Find("Codename",Start
,Stop
) == true) 
 809       FileI
->Codename 
= WriteUniqString(Start
,Stop 
- Start
); 
 810    if (Section
.Find("Label",Start
,Stop
) == true) 
 811       FileI
->Label 
= WriteUniqString(Start
,Stop 
- Start
); 
 812    if (Section
.Find("Architecture",Start
,Stop
) == true) 
 813       FileI
->Architecture 
= WriteUniqString(Start
,Stop 
- Start
); 
 815    if (Section
.FindFlag("NotAutomatic",FileI
->Flags
, 
 816                         pkgCache::Flag::NotAutomatic
) == false) 
 817       _error
->Warning("Bad NotAutomatic flag"); 
 819    return !_error
->PendingError(); 
 822 // ListParser::GetPrio - Convert the priority from a string             /*{{{*/ 
 823 // --------------------------------------------------------------------- 
 825 unsigned char debListParser::GetPrio(string Str
) 
 828    if (GrabWord(Str
,PrioList
,Out
) == false) 
 829       Out 
= pkgCache::State::Extra
;