]>
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                                                        /*{{{*/ 
  15 #include <apt-pkg/deblistparser.h> 
  16 #include <apt-pkg/error.h> 
  17 #include <apt-pkg/configuration.h> 
  18 #include <apt-pkg/aptconfiguration.h> 
  19 #include <apt-pkg/strutl.h> 
  20 #include <apt-pkg/fileutl.h> 
  21 #include <apt-pkg/crc-16.h> 
  22 #include <apt-pkg/md5.h> 
  23 #include <apt-pkg/macros.h> 
  31 static debListParser::WordList PrioList
[] = {{"important",pkgCache::State::Important
}, 
  32                        {"required",pkgCache::State::Required
}, 
  33                        {"standard",pkgCache::State::Standard
}, 
  34                        {"optional",pkgCache::State::Optional
}, 
  35                        {"extra",pkgCache::State::Extra
}, 
  38 // ListParser::debListParser - Constructor                              /*{{{*/ 
  39 // --------------------------------------------------------------------- 
  40 /* Provide an architecture and only this one and "all" will be accepted 
  41    in Step(), if no Architecture is given we will accept every arch 
  42    we would accept in general with checkArchitecture() */ 
  43 debListParser::debListParser(FileFd 
*File
, string 
const &Arch
) : Tags(File
), 
  46       this->Arch 
= _config
->Find("APT::Architecture"); 
  47    Architectures 
= APT::Configuration::getArchitectures(); 
  48    MultiArchEnabled 
= Architectures
.size() > 1; 
  51 // ListParser::UniqFindTagWrite - Find the tag and write a unq string   /*{{{*/ 
  52 // --------------------------------------------------------------------- 
  54 unsigned long debListParser::UniqFindTagWrite(const char *Tag
) 
  58    if (Section
.Find(Tag
,Start
,Stop
) == false) 
  60    return WriteUniqString(Start
,Stop 
- Start
); 
  63 // ListParser::Package - Return the package name                        /*{{{*/ 
  64 // --------------------------------------------------------------------- 
  65 /* This is to return the name of the package this section describes */ 
  66 string 
debListParser::Package() { 
  67    string 
const Result 
= Section
.FindS("Package"); 
  68    if(unlikely(Result
.empty() == true)) 
  69       _error
->Error("Encountered a section with no Package: header"); 
  73 // ListParser::Architecture - Return the package arch                   /*{{{*/ 
  74 // --------------------------------------------------------------------- 
  75 /* This will return the Architecture of the package this section describes */ 
  76 string 
debListParser::Architecture() { 
  77    return Section
.FindS("Architecture"); 
  80 // ListParser::ArchitectureAll                                          /*{{{*/ 
  81 // --------------------------------------------------------------------- 
  83 bool debListParser::ArchitectureAll() { 
  84    return Section
.FindS("Architecture") == "all"; 
  87 // ListParser::Version - Return the version string                      /*{{{*/ 
  88 // --------------------------------------------------------------------- 
  89 /* This is to return the string describing the version in debian form, 
  90    epoch:upstream-release. If this returns the blank string then the  
  91    entry is assumed to only describe package properties */ 
  92 string 
debListParser::Version() 
  94    return Section
.FindS("Version"); 
  97 // ListParser::NewVersion - Fill in the version structure               /*{{{*/ 
  98 // --------------------------------------------------------------------- 
 100 bool debListParser::NewVersion(pkgCache::VerIterator 
&Ver
) 
 103    Ver
->Section 
= UniqFindTagWrite("Section"); 
 106    string 
const MultiArch 
= Section
.FindS("Multi-Arch"); 
 107    if (MultiArch
.empty() == true) 
 108       Ver
->MultiArch 
= pkgCache::Version::None
; 
 109    else if (MultiArch 
== "same") { 
 111       if (ArchitectureAll() == true) 
 113          /* Arch all packages can't be Multi-Arch: same */ 
 114          _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same", 
 115                         Section
.FindS("Package").c_str()); 
 116          Ver
->MultiArch 
= pkgCache::Version::None
; 
 119          Ver
->MultiArch 
= pkgCache::Version::Same
; 
 121    else if (MultiArch 
== "foreign") 
 122       Ver
->MultiArch 
= pkgCache::Version::Foreign
; 
 123    else if (MultiArch 
== "allowed") 
 124       Ver
->MultiArch 
= pkgCache::Version::Allowed
; 
 127       _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'", 
 128                         MultiArch
.c_str(), Section
.FindS("Package").c_str()); 
 129       Ver
->MultiArch 
= pkgCache::Version::None
; 
 132    if (ArchitectureAll() == true) 
 133       Ver
->MultiArch 
|= pkgCache::Version::All
; 
 136    Ver
->Size 
= Section
.FindULL("Size"); 
 137    // Unpacked Size (in K) 
 138    Ver
->InstalledSize 
= Section
.FindULL("Installed-Size"); 
 139    Ver
->InstalledSize 
*= 1024; 
 144    if (Section
.Find("Priority",Start
,Stop
) == true) 
 146       if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false) 
 147          Ver
->Priority 
= pkgCache::State::Extra
; 
 150    if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false) 
 152    if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false) 
 154    if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false) 
 156    if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false) 
 158    if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false) 
 160    if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false) 
 162    if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false) 
 164    if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false) 
 168    if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false) 
 171    if (ParseProvides(Ver
) == false) 
 177 // ListParser::Description - Return the description string              /*{{{*/ 
 178 // --------------------------------------------------------------------- 
 179 /* This is to return the string describing the package in debian 
 180    form. If this returns the blank string then the entry is assumed to 
 181    only describe package properties */ 
 182 string 
debListParser::Description() 
 184    string 
const lang 
= DescriptionLanguage(); 
 186       return Section
.FindS("Description"); 
 188       return Section
.FindS(string("Description-").append(lang
).c_str()); 
 191 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/ 
 192 // --------------------------------------------------------------------- 
 193 /* This is to return the string describing the language of 
 194    description. If this returns the blank string then the entry is 
 195    assumed to describe original description. */ 
 196 string 
debListParser::DescriptionLanguage() 
 198    if (Section
.FindS("Description").empty() == false) 
 201    std::vector
<string
> const lang 
= APT::Configuration::getLanguages(true); 
 202    for (std::vector
<string
>::const_iterator l 
= lang
.begin(); 
 203         l 
!= lang
.end(); ++l
) 
 204       if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false) 
 210 // ListParser::Description - Return the description_md5 MD5SumValue     /*{{{*/ 
 211 // --------------------------------------------------------------------- 
 212 /* This is to return the md5 string to allow the check if it is the right 
 213    description. If no Description-md5 is found in the section it will be 
 216 MD5SumValue 
debListParser::Description_md5() 
 218    string value 
= Section
.FindS("Description-md5"); 
 223       md5
.Add((Description() + "\n").c_str()); 
 226       return MD5SumValue(value
); 
 229 // ListParser::UsePackage - Update a package structure                  /*{{{*/ 
 230 // --------------------------------------------------------------------- 
 231 /* This is called to update the package with any new information  
 232    that might be found in the section */ 
 233 bool debListParser::UsePackage(pkgCache::PkgIterator 
&Pkg
, 
 234                                pkgCache::VerIterator 
&Ver
) 
 236    if (Pkg
->Section 
== 0) 
 237       Pkg
->Section 
= UniqFindTagWrite("Section"); 
 239    // Packages which are not from the "native" arch doesn't get the essential flag 
 240    // in the default "native" mode - it is also possible to mark "all" or "none". 
 241    // The "installed" mode is handled by ParseStatus(), See #544481 and friends. 
 242    string 
const static myArch 
= _config
->Find("APT::Architecture"); 
 243    string 
const static essential 
= _config
->Find("pkgCacheGen::Essential", "native"); 
 244    if ((essential 
== "native" && Pkg
->Arch 
!= 0 && myArch 
== Pkg
.Arch()) || 
 246       if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false) 
 248    if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false) 
 251    if (strcmp(Pkg
.Name(),"apt") == 0) 
 252       Pkg
->Flags 
|= pkgCache::Flag::Essential 
| pkgCache::Flag::Important
; 
 254    if (ParseStatus(Pkg
,Ver
) == false) 
 259 // ListParser::VersionHash - Compute a unique hash for this version     /*{{{*/ 
 260 // --------------------------------------------------------------------- 
 262 unsigned short debListParser::VersionHash() 
 264    const char *Sections
[] ={"Installed-Size", 
 272    unsigned long Result 
= INIT_FCS
; 
 274    for (const char **I 
= Sections
; *I 
!= 0; I
++) 
 278       if (Section
.Find(*I
,Start
,End
) == false || End 
- Start 
>= (signed)sizeof(S
)) 
 281       /* Strip out any spaces from the text, this undoes dpkgs reformatting 
 282          of certain fields. dpkg also has the rather interesting notion of 
 283          reformatting depends operators < -> <= */ 
 285       for (; Start 
!= End
; Start
++) 
 287          if (isspace(*Start
) == 0) 
 288             *J
++ = tolower_ascii(*Start
); 
 289          if (*Start 
== '<' && Start
[1] != '<' && Start
[1] != '=') 
 291          if (*Start 
== '>' && Start
[1] != '>' && Start
[1] != '=') 
 295       Result 
= AddCRC16(Result
,S
,J 
- S
); 
 301 // ListParser::ParseStatus - Parse the status field                     /*{{{*/ 
 302 // --------------------------------------------------------------------- 
 303 /* Status lines are of the form, 
 304      Status: want flag status 
 305    want = unknown, install, hold, deinstall, purge 
 306    flag = ok, reinstreq, hold, hold-reinstreq 
 307    status = not-installed, unpacked, half-configured, 
 308             half-installed, config-files, post-inst-failed,  
 309             removal-failed, installed 
 311    Some of the above are obsolete (I think?) flag = hold-* and  
 312    status = post-inst-failed, removal-failed at least. 
 314 bool debListParser::ParseStatus(pkgCache::PkgIterator 
&Pkg
, 
 315                                 pkgCache::VerIterator 
&Ver
) 
 319    if (Section
.Find("Status",Start
,Stop
) == false) 
 322    // UsePackage() is responsible for setting the flag in the default case 
 323    bool const static essential 
= _config
->Find("pkgCacheGen::Essential", "") == "installed"; 
 324    if (essential 
== true && 
 325        Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false) 
 328    // Isolate the first word 
 329    const char *I 
= Start
; 
 330    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 331    if (I 
>= Stop 
|| *I 
!= ' ') 
 332       return _error
->Error("Malformed Status line"); 
 334    // Process the want field 
 335    WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
}, 
 336                           {"install",pkgCache::State::Install
}, 
 337                           {"hold",pkgCache::State::Hold
}, 
 338                           {"deinstall",pkgCache::State::DeInstall
}, 
 339                           {"purge",pkgCache::State::Purge
}, 
 341    if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false) 
 342       return _error
->Error("Malformed 1st word in the Status line"); 
 344    // Isloate the next word 
 347    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 348    if (I 
>= Stop 
|| *I 
!= ' ') 
 349       return _error
->Error("Malformed status line, no 2nd word"); 
 351    // Process the flag field 
 352    WordList FlagList
[] = {{"ok",pkgCache::State::Ok
}, 
 353                           {"reinstreq",pkgCache::State::ReInstReq
}, 
 354                           {"hold",pkgCache::State::HoldInst
}, 
 355                           {"hold-reinstreq",pkgCache::State::HoldReInstReq
}, 
 357    if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false) 
 358       return _error
->Error("Malformed 2nd word in the Status line"); 
 360    // Isloate the last word 
 363    for(; I 
< Stop 
&& *I 
!= ' '; I
++); 
 365       return _error
->Error("Malformed Status line, no 3rd word"); 
 367    // Process the flag field 
 368    WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
}, 
 369                             {"unpacked",pkgCache::State::UnPacked
}, 
 370                             {"half-configured",pkgCache::State::HalfConfigured
}, 
 371                             {"installed",pkgCache::State::Installed
}, 
 372                             {"half-installed",pkgCache::State::HalfInstalled
}, 
 373                             {"config-files",pkgCache::State::ConfigFiles
}, 
 374                             {"triggers-awaited",pkgCache::State::TriggersAwaited
}, 
 375                             {"triggers-pending",pkgCache::State::TriggersPending
}, 
 376                             {"post-inst-failed",pkgCache::State::HalfConfigured
}, 
 377                             {"removal-failed",pkgCache::State::HalfInstalled
}, 
 379    if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false) 
 380       return _error
->Error("Malformed 3rd word in the Status line"); 
 382    /* A Status line marks the package as indicating the current 
 383       version as well. Only if it is actually installed.. Otherwise 
 384       the interesting dpkg handling of the status file creates bogus  
 386    if (!(Pkg
->CurrentState 
== pkgCache::State::NotInstalled 
|| 
 387          Pkg
->CurrentState 
== pkgCache::State::ConfigFiles
)) 
 389       if (Ver
.end() == true) 
 390          _error
->Warning("Encountered status field in a non-version description"); 
 392          Pkg
->CurrentVer 
= Ver
.Index(); 
 398 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
) 
 400    // Determine the operator 
 408          Op 
= pkgCache::Dep::LessEq
; 
 415          Op 
= pkgCache::Dep::Less
; 
 419       // < is the same as <= and << is really Cs < for some reason 
 420       Op 
= pkgCache::Dep::LessEq
; 
 428          Op 
= pkgCache::Dep::GreaterEq
; 
 435          Op 
= pkgCache::Dep::Greater
; 
 439       // > is the same as >= and >> is really Cs > for some reason 
 440       Op 
= pkgCache::Dep::GreaterEq
; 
 444       Op 
= pkgCache::Dep::Equals
; 
 448       // HACK around bad package definitions 
 450       Op 
= pkgCache::Dep::Equals
; 
 459  * The complete architecture, consisting of <kernel>-<cpu>. 
 461 static string 
CompleteArch(std::string 
const &arch
) { 
 462     if (arch 
== "armel")              return "linux-arm"; 
 463     if (arch 
== "armhf")              return "linux-arm"; 
 464     if (arch 
== "lpia")               return "linux-i386"; 
 465     if (arch 
== "powerpcspe")         return "linux-powerpc"; 
 466     if (arch 
== "uclibc-linux-armel") return "linux-arm"; 
 467     if (arch 
== "uclinux-armel")      return "uclinux-arm"; 
 469     return (arch
.find("-") != string::npos
) ? arch 
: "linux-" + arch
; 
 472 // ListParser::ParseDepends - Parse a dependency element                /*{{{*/ 
 473 // --------------------------------------------------------------------- 
 474 /* This parses the dependency elements out of a standard string in place, 
 476 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
, 
 477                                         string 
&Package
,string 
&Ver
, 
 478                                         unsigned int &Op
, bool const &ParseArchFlags
, 
 479                                         bool const &StripMultiArch
) 
 481    // Strip off leading space 
 482    for (;Start 
!= Stop 
&& isspace(*Start
) != 0; Start
++); 
 484    // Parse off the package name 
 485    const char *I 
= Start
; 
 486    for (;I 
!= Stop 
&& isspace(*I
) == 0 && *I 
!= '(' && *I 
!= ')' && 
 487         *I 
!= ',' && *I 
!= '|' && *I 
!= '[' && *I 
!= ']'; I
++); 
 490    if (I 
!= Stop 
&& *I 
== ')') 
 496    // Stash the package name 
 497    Package
.assign(Start
,I 
- Start
); 
 499    // We don't want to confuse library users which can't handle MultiArch 
 500    string 
const arch 
= _config
->Find("APT::Architecture"); 
 501    if (StripMultiArch 
== true) { 
 502       size_t const found 
= Package
.rfind(':'); 
 503       if (found 
!= string::npos 
&& 
 504           (strcmp(Package
.c_str() + found
, ":any") == 0 || 
 505            strcmp(Package
.c_str() + found
, ":native") == 0 || 
 506            strcmp(Package
.c_str() + found 
+ 1, arch
.c_str()) == 0)) 
 507          Package 
= Package
.substr(0,found
); 
 510    // Skip white space to the '(' 
 511    for (;I 
!= Stop 
&& isspace(*I
) != 0 ; I
++); 
 514    if (I 
!= Stop 
&& *I 
== '(') 
 517       for (I
++; I 
!= Stop 
&& isspace(*I
) != 0 ; I
++); 
 520       I 
= ConvertRelation(I
,Op
); 
 523       for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 525       I 
= (const char*) memchr(I
, ')', Stop 
- I
); 
 526       if (I 
== NULL 
|| Start 
== I
) 
 529       // Skip trailing whitespace 
 531       for (; End 
> Start 
&& isspace(End
[-1]); End
--); 
 533       Ver
.assign(Start
,End
-Start
); 
 539       Op 
= pkgCache::Dep::NoOp
; 
 543    for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 545    if (ParseArchFlags 
== true) 
 547       string completeArch 
= CompleteArch(arch
); 
 549       // Parse an architecture 
 550       if (I 
!= Stop 
&& *I 
== '[') 
 559          bool NegArch 
= false; 
 562             // look for whitespace or ending ']' 
 563             while (End 
!= Stop 
&& !isspace(*End
) && *End 
!= ']')  
 575             if (stringcmp(arch
,I
,End
) == 0) { 
 578                std::string wildcard 
= SubstVar(string(I
, End
), "any", "*"); 
 579                if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0) 
 589             for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 596             Package 
= ""; /* not for this arch */ 
 600       for (;I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 603    if (I 
!= Stop 
&& *I 
== '|') 
 604       Op 
|= pkgCache::Dep::Or
; 
 606    if (I 
== Stop 
|| *I 
== ',' || *I 
== '|') 
 609          for (I
++; I 
!= Stop 
&& isspace(*I
) != 0; I
++); 
 616 // ListParser::ParseDepends - Parse a dependency list                   /*{{{*/ 
 617 // --------------------------------------------------------------------- 
 618 /* This is the higher level depends parser. It takes a tag and generates 
 619    a complete depends tree for the given version. */ 
 620 bool debListParser::ParseDepends(pkgCache::VerIterator 
&Ver
, 
 621                                  const char *Tag
,unsigned int Type
) 
 625    if (Section
.Find(Tag
,Start
,Stop
) == false) 
 629    string 
const pkgArch 
= Ver
.Arch(); 
 635       Start 
= ParseDepends(Start
,Stop
,Package
,Version
,Op
,false,!MultiArchEnabled
); 
 637          return _error
->Error("Problem parsing dependency %s",Tag
); 
 639       if (MultiArchEnabled 
== true && 
 640           (Type 
== pkgCache::Dep::Conflicts 
|| 
 641            Type 
== pkgCache::Dep::DpkgBreaks 
|| 
 642            Type 
== pkgCache::Dep::Replaces
)) 
 644          for (std::vector
<std::string
>::const_iterator a 
= Architectures
.begin(); 
 645               a 
!= Architectures
.end(); ++a
) 
 646             if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false) 
 649       else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false) 
 657 // ListParser::ParseProvides - Parse the provides list                  /*{{{*/ 
 658 // --------------------------------------------------------------------- 
 660 bool debListParser::ParseProvides(pkgCache::VerIterator 
&Ver
) 
 664    if (Section
.Find("Provides",Start
,Stop
) == true) 
 668       string 
const Arch 
= Ver
.Arch(); 
 673          Start 
= ParseDepends(Start
,Stop
,Package
,Version
,Op
); 
 675             return _error
->Error("Problem parsing Provides line"); 
 676          if (Op 
!= pkgCache::Dep::NoOp
) { 
 677             _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str()); 
 678          } else if ((Ver
->MultiArch 
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) { 
 679             if (NewProvidesAllArch(Ver
, Package
, Version
) == false) 
 682             if (NewProvides(Ver
, Package
, Arch
, Version
) == false) 
 691    if (MultiArchEnabled 
== false) 
 693    else if ((Ver
->MultiArch 
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
) 
 695       string 
const Package 
= string(Ver
.ParentPkg().Name()).append(":").append("any"); 
 696       return NewProvidesAllArch(Ver
, Package
, Ver
.VerStr()); 
 698    else if ((Ver
->MultiArch 
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
) 
 699       return NewProvidesAllArch(Ver
, Ver
.ParentPkg().Name(), Ver
.VerStr()); 
 704 // ListParser::NewProvides - add provides for all architectures         /*{{{*/ 
 705 bool debListParser::NewProvidesAllArch(pkgCache::VerIterator 
&Ver
, string 
const &Package
, 
 706                                 string 
const &Version
) { 
 707    for (std::vector
<string
>::const_iterator a 
= Architectures
.begin(); 
 708         a 
!= Architectures
.end(); ++a
) 
 710       if (NewProvides(Ver
, Package
, *a
, Version
) == false) 
 716 // ListParser::GrabWord - Matches a word and returns                    /*{{{*/ 
 717 // --------------------------------------------------------------------- 
 718 /* Looks for a word in a list of words - for ParseStatus */ 
 719 bool debListParser::GrabWord(string Word
,WordList 
*List
,unsigned char &Out
) 
 721    for (unsigned int C 
= 0; List
[C
].Str 
!= 0; C
++) 
 723       if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0) 
 732 // ListParser::Step - Move to the next section in the file              /*{{{*/ 
 733 // --------------------------------------------------------------------- 
 734 /* This has to be carefull to only process the correct architecture */ 
 735 bool debListParser::Step() 
 737    iOffset 
= Tags
.Offset(); 
 738    while (Tags
.Step(Section
) == true) 
 740       /* See if this is the correct Architecture, if it isn't then we 
 741          drop the whole section. A missing arch tag only happens (in theory) 
 742          inside the Status file, so that is a positive return */ 
 743       string 
const Architecture 
= Section
.FindS("Architecture"); 
 744       if (Architecture
.empty() == true) 
 747       if (Arch
.empty() == true || Arch 
== "any" || MultiArchEnabled 
== false) 
 749          if (APT::Configuration::checkArchitecture(Architecture
) == true) 
 754          if (Architecture 
== Arch
) 
 757          if (Architecture 
== "all" && Arch 
== _config
->Find("APT::Architecture")) 
 761       iOffset 
= Tags
.Offset(); 
 766 // ListParser::LoadReleaseInfo - Load the release information           /*{{{*/ 
 767 // --------------------------------------------------------------------- 
 769 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator 
&FileI
, 
 770                                     FileFd 
&File
, string component
) 
 772    // apt-secure does no longer download individual (per-section) Release 
 773    // file. to provide Component pinning we use the section name now 
 774    FileI
->Component 
= WriteUniqString(component
); 
 776    // FIXME: Code depends on the fact that Release files aren't compressed 
 777    FILE* release 
= fdopen(dup(File
.Fd()), "r"); 
 782    bool gpgClose 
= false; 
 783    while (fgets(buffer
, sizeof(buffer
), release
) != NULL
) 
 788       for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
) 
 791       if (buffer
[len
] == '\0') 
 794       // only evalute the first GPG section 
 795       if (strncmp("-----", buffer
, 5) == 0) 
 797          if (gpgClose 
== true) 
 803       // seperate the tag from the data 
 804       const char* dataStart 
= strchr(buffer 
+ len
, ':'); 
 805       if (dataStart 
== NULL
) 
 807       len 
= dataStart 
- buffer
; 
 808       for (++dataStart
; *dataStart 
== ' '; ++dataStart
) 
 811       const char* dataEnd 
= (const char*)rawmemchr(dataStart
, '\0'); 
 812       // The last char should be a newline, but we can never be sure: #633350 
 813       const char* lineEnd 
= dataEnd
; 
 814       for (--lineEnd
; *lineEnd 
== '\r' || *lineEnd 
== '\n'; --lineEnd
) 
 819       // which datastorage need to be updated 
 820       enum { Suite
, Component
, Version
, Origin
, Codename
, Label
, None 
} writeTo 
= None
; 
 821       if (buffer
[0] == ' ') 
 823       #define APT_PARSER_WRITETO(X) else if (strncmp(#X, buffer, len) == 0) writeTo = X; 
 824       APT_PARSER_WRITETO(Suite
) 
 825       APT_PARSER_WRITETO(Component
) 
 826       APT_PARSER_WRITETO(Version
) 
 827       APT_PARSER_WRITETO(Origin
) 
 828       APT_PARSER_WRITETO(Codename
) 
 829       APT_PARSER_WRITETO(Label
) 
 830       #undef APT_PARSER_WRITETO 
 831       #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \ 
 832          pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd); 
 833       APT_PARSER_FLAGIT(NotAutomatic
) 
 834       APT_PARSER_FLAGIT(ButAutomaticUpgrades
) 
 835       #undef APT_PARSER_FLAGIT 
 837       // load all data from the line and save it 
 840          data
.append(dataStart
, dataEnd
); 
 841       if (sizeof(buffer
) - 1 == (dataEnd 
- buffer
)) 
 843          while (fgets(buffer
, sizeof(buffer
), release
) != NULL
) 
 847             if (strlen(buffer
) != sizeof(buffer
) - 1) 
 853          // remove spaces and stuff from the end of the data line 
 854          for (std::string::reverse_iterator s 
= data
.rbegin(); 
 855               s 
!= data
.rend(); ++s
) 
 857             if (*s 
!= '\r' && *s 
!= '\n' && *s 
!= ' ') 
 862          case Suite
: FileI
->Archive 
= WriteUniqString(data
); break; 
 863          case Component
: FileI
->Component 
= WriteUniqString(data
); break; 
 864          case Version
: FileI
->Version 
= WriteUniqString(data
); break; 
 865          case Origin
: FileI
->Origin 
= WriteUniqString(data
); break; 
 866          case Codename
: FileI
->Codename 
= WriteUniqString(data
); break; 
 867          case Label
: FileI
->Label 
= WriteUniqString(data
); break; 
 874    return !_error
->PendingError(); 
 877 // ListParser::GetPrio - Convert the priority from a string             /*{{{*/ 
 878 // --------------------------------------------------------------------- 
 880 unsigned char debListParser::GetPrio(string Str
) 
 883    if (GrabWord(Str
,PrioList
,Out
) == false) 
 884       Out 
= pkgCache::State::Extra
;