X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/4d174dc84ea184b5afa81abb3b94e2ef3380ece8..43fb90dcd5d3f8887c1903073ad21a53847974ba:/apt-pkg/deb/deblistparser.cc?ds=sidebyside diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 3726a6a04..1b3bfd6ae 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -17,10 +17,10 @@ #include #include #include +#include +#include #include - -#include /*}}}*/ static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Important}, @@ -37,8 +37,10 @@ static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Impor we would accept in general with checkArchitecture() */ debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File), Arch(Arch) { - if (Arch == "native") - this->Arch = _config->Find("APT::Architecture"); + if (Arch == "native") + this->Arch = _config->Find("APT::Architecture"); + Architectures = APT::Configuration::getArchitectures(); + MultiArchEnabled = Architectures.size() > 1; } /*}}}*/ // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ @@ -57,10 +59,10 @@ unsigned long debListParser::UniqFindTagWrite(const char *Tag) // --------------------------------------------------------------------- /* This is to return the name of the package this section describes */ string debListParser::Package() { - string const Result = Section.FindS("Package"); - if(unlikely(Result.empty() == true)) - _error->Error("Encountered a section with no Package: header"); - return Result; + string const Result = Section.FindS("Package"); + if(unlikely(Result.empty() == true)) + _error->Error("Encountered a section with no Package: header"); + return Result; } /*}}}*/ // ListParser::Architecture - Return the package arch /*{{{*/ @@ -69,25 +71,26 @@ string debListParser::Package() { Note that architecture "all" packages will get the architecture of the Packages file parsed here. */ string debListParser::Architecture() { - string const Result = Section.FindS("Architecture"); - if (Result.empty() == true || Result == "all") { - if (Arch.empty() == true) - /* FIXME: this is a problem for installed arch all - packages as we don't know from which arch this - package was installed - and therefore which - dependency this package resolves. */ - return _config->Find("APT::Architecture"); - else - return Arch; - } - return Result; + string const Result = Section.FindS("Architecture"); + if (Result.empty() == true || Result == "all") + { + if (Arch.empty() == true) + /* FIXME: this is a problem for installed arch all + packages as we don't know from which arch this + package was installed - and therefore which + dependency this package resolves. */ + return _config->Find("APT::Architecture"); + else + return Arch; + } + return Result; } /*}}}*/ // ListParser::ArchitectureAll /*{{{*/ // --------------------------------------------------------------------- /* */ bool debListParser::ArchitectureAll() { - return Section.FindS("Architecture") == "all"; + return Section.FindS("Architecture") == "all"; } /*}}}*/ // ListParser::Version - Return the version string /*{{{*/ @@ -103,7 +106,7 @@ string debListParser::Version() // ListParser::NewVersion - Fill in the version structure /*{{{*/ // --------------------------------------------------------------------- /* */ -bool debListParser::NewVersion(pkgCache::VerIterator Ver) +bool debListParser::NewVersion(pkgCache::VerIterator &Ver) { // Parse the section Ver->Section = UniqFindTagWrite("Section"); @@ -133,10 +136,9 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) } // Archive Size - Ver->Size = (unsigned)Section.FindI("Size"); - + Ver->Size = Section.FindULL("Size"); // Unpacked Size (in K) - Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size"); + Ver->InstalledSize = Section.FindULL("Installed-Size"); Ver->InstalledSize *= 1024; // Priority @@ -148,6 +150,24 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) Ver->Priority = pkgCache::State::Extra; } + if (Ver->MultiArch == pkgCache::Version::All) + { + /* We maintain a "pseudo" arch=all package for architecture all versions + on which these versions can depend on. This pseudo package is many used + for downloading/installing: The other pseudo-packages will degenerate + to a NOP in the download/install step - this package will ensure that + it is downloaded only one time and installed only one time -- even if + the architecture bound versions coming in and out on regular basis. */ + if (strcmp(Ver.Arch(true),"all") == 0) + return true; + else if (MultiArchEnabled == true) + { + // our pseudo packages have no size to not confuse the fetcher + Ver->Size = 0; + Ver->InstalledSize = 0; + } + } + if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false) return false; if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false) @@ -231,15 +251,19 @@ MD5SumValue debListParser::Description_md5() // --------------------------------------------------------------------- /* This is called to update the package with any new information that might be found in the section */ -bool debListParser::UsePackage(pkgCache::PkgIterator Pkg, - pkgCache::VerIterator Ver) +bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver) { if (Pkg->Section == 0) Pkg->Section = UniqFindTagWrite("Section"); - // Packages which are not from "our" arch doesn't get the essential flag + // Packages which are not from the "native" arch doesn't get the essential flag + // in the default "native" mode - it is also possible to mark "all" or "none". + // The "installed" mode is handled by ParseStatus(), See #544481 and friends. string const static myArch = _config->Find("APT::Architecture"); - if (Pkg->Arch != 0 && myArch == Pkg.Arch()) + string const static essential = _config->Find("pkgCacheGen::Essential", "native"); + if ((essential == "native" && Pkg->Arch != 0 && myArch == Pkg.Arch()) || + essential == "all") if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false) return false; if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false) @@ -308,14 +332,20 @@ unsigned short debListParser::VersionHash() Some of the above are obsolete (I think?) flag = hold-* and status = post-inst-failed, removal-failed at least. */ -bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg, - pkgCache::VerIterator Ver) +bool debListParser::ParseStatus(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver) { const char *Start; const char *Stop; if (Section.Find("Status",Start,Stop) == false) return true; - + + // UsePackage() is responsible for setting the flag in the default case + bool const static essential = _config->Find("pkgCacheGen::Essential", "") == "installed"; + if (essential == true && + Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false) + return false; + // Isolate the first word const char *I = Start; for(; I < Stop && *I != ' '; I++); @@ -444,6 +474,21 @@ const char *debListParser::ConvertRelation(const char *I,unsigned int &Op) return I; } +/* + * CompleteArch: + * + * The complete architecture, consisting of -. + */ +static string CompleteArch(std::string& arch) { + if (arch == "armel") return "linux-arm"; + if (arch == "armhf") return "linux-arm"; + if (arch == "lpia") return "linux-i386"; + if (arch == "powerpcspe") return "linux-powerpc"; + if (arch == "uclibc-linux-armel") return "linux-arm"; + if (arch == "uclinux-armel") return "uclinux-arm"; + + return (arch.find("-") != string::npos) ? arch : "linux-" + arch; +} /*}}}*/ // ListParser::ParseDepends - Parse a dependency element /*{{{*/ // --------------------------------------------------------------------- @@ -517,6 +562,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, if (ParseArchFlags == true) { string arch = _config->Find("APT::Architecture"); + string completeArch = CompleteArch(arch); // Parse an architecture if (I != Stop && *I == '[') @@ -544,8 +590,13 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, I++; } - if (stringcmp(arch,I,End) == 0) + if (stringcmp(arch,I,End) == 0) { Found = true; + } else { + std::string wildcard = SubstVar(string(I, End), "any", "*"); + if (fnmatch(wildcard.c_str(), completeArch.c_str(), 0) == 0) + Found = true; + } if (*End++ == ']') { I = End; @@ -584,16 +635,16 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, // --------------------------------------------------------------------- /* This is the higher level depends parser. It takes a tag and generates a complete depends tree for the given version. */ -bool debListParser::ParseDepends(pkgCache::VerIterator Ver, +bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, const char *Tag,unsigned int Type) { const char *Start; const char *Stop; if (Section.Find(Tag,Start,Stop) == false) return true; - + string Package; - string const pkgArch = Ver.Arch(); + string const pkgArch = Ver.Arch(true); string Version; unsigned int Op; @@ -602,8 +653,18 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, Start = ParseDepends(Start,Stop,Package,Version,Op); if (Start == 0) return _error->Error("Problem parsing dependency %s",Tag); - - if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) + + if (MultiArchEnabled == true && + (Type == pkgCache::Dep::Conflicts || + Type == pkgCache::Dep::DpkgBreaks || + Type == pkgCache::Dep::Replaces)) + { + for (std::vector::const_iterator a = Architectures.begin(); + a != Architectures.end(); ++a) + if (NewDepends(Ver,Package,*a,Version,Op,Type) == false) + return false; + } + else if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) return false; if (Start == Stop) break; @@ -614,7 +675,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver, // ListParser::ParseProvides - Parse the provides list /*{{{*/ // --------------------------------------------------------------------- /* */ -bool debListParser::ParseProvides(pkgCache::VerIterator Ver) +bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) { const char *Start; const char *Stop; @@ -622,7 +683,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) { string Package; string Version; - string const Arch = Ver.Arch(); + string const Arch = Ver.Arch(true); unsigned int Op; while (1) @@ -651,14 +712,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) if (Ver->MultiArch != pkgCache::Version::Foreign) return true; - std::vector const archs = APT::Configuration::getArchitectures(); - if (archs.size() <= 1) + if (MultiArchEnabled == false) return true; string const Package = Ver.ParentPkg().Name(); string const Version = Ver.VerStr(); - for (std::vector::const_iterator a = archs.begin(); - a != archs.end(); ++a) + for (std::vector::const_iterator a = Architectures.begin(); + a != Architectures.end(); ++a) { if (NewProvides(Ver, Package, *a, Version) == false) return false; @@ -698,7 +758,7 @@ bool debListParser::Step() if (Architecture.empty() == true) return true; - if (Arch.empty() == true) + if (Arch.empty() == true || Arch == "any" || MultiArchEnabled == false) { if (APT::Configuration::checkArchitecture(Architecture) == true) return true; @@ -720,7 +780,7 @@ bool debListParser::Step() // ListParser::LoadReleaseInfo - Load the release information /*{{{*/ // --------------------------------------------------------------------- /* */ -bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, +bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, FileFd &File, string component) { pkgTagFile Tags(&File, File.Size() + 256); // XXX @@ -756,6 +816,12 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, if (Section.FindFlag("NotAutomatic",FileI->Flags, pkgCache::Flag::NotAutomatic) == false) _error->Warning("Bad NotAutomatic flag"); + if (Section.FindFlag("ButAutomaticUpgrades",FileI->Flags, + pkgCache::Flag::ButAutomaticUpgrades) == false) + _error->Warning("Bad ButAutomaticUpgrades flag"); + // overrule the NotAutomatic setting if needed as they are both present for compatibility + else if ((FileI->Flags & pkgCache::Flag::ButAutomaticUpgrades) == pkgCache::Flag::ButAutomaticUpgrades) + FileI->Flags &= ~pkgCache::Flag::NotAutomatic; return !_error->PendingError(); }