diff options
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire.cc | 8 | ||||
-rw-r--r-- | apt-pkg/algorithms.cc | 130 | ||||
-rw-r--r-- | apt-pkg/cachefilter-patterns.h | 1 | ||||
-rw-r--r-- | apt-pkg/cacheset.cc | 112 | ||||
-rw-r--r-- | apt-pkg/contrib/arfile.cc | 11 | ||||
-rw-r--r-- | apt-pkg/contrib/extracttar.cc | 60 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 45 | ||||
-rw-r--r-- | apt-pkg/contrib/srvrec.cc | 17 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 11 | ||||
-rw-r--r-- | apt-pkg/deb/debsystem.cc | 9 | ||||
-rw-r--r-- | apt-pkg/deb/debsystem.h | 1 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 14 | ||||
-rw-r--r-- | apt-pkg/depcache.cc | 653 | ||||
-rw-r--r-- | apt-pkg/depcache.h | 13 | ||||
-rw-r--r-- | apt-pkg/edsp.cc | 34 | ||||
-rw-r--r-- | apt-pkg/init.cc | 8 | ||||
-rw-r--r-- | apt-pkg/pkgcache.cc | 3 | ||||
-rw-r--r-- | apt-pkg/tagfile-keys.list | 1 | ||||
-rw-r--r-- | apt-pkg/tagfile-order.c | 3 |
19 files changed, 721 insertions, 413 deletions
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index fffe76f46..1cffc0463 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -105,18 +105,18 @@ static bool SetupAPTPartialDirectory(std::string const &grand, std::string const { // chown the partial dir if(chown(partial.c_str(), pw->pw_uid, gr->gr_gid) != 0) - _error->WarningE("SetupAPTPartialDirectory", "chown to %s:root of directory %s failed", SandboxUser.c_str(), partial.c_str()); + _error->WarningE("SetupAPTPartialDirectory", "chown to %s:%s of directory %s failed", SandboxUser.c_str(), ROOT_GROUP, partial.c_str()); } } if (chmod(partial.c_str(), mode) != 0) - _error->WarningE("SetupAPTPartialDirectory", "chmod 0700 of directory %s failed", partial.c_str()); + _error->WarningE("SetupAPTPartialDirectory", "chmod 0%03o of directory %s failed", mode, partial.c_str()); } else if (chmod(partial.c_str(), mode) != 0) { // if we haven't created the dir and aren't root, it is kinda expected that chmod doesn't work if (partialExists == false) - _error->WarningE("SetupAPTPartialDirectory", "chmod 0700 of directory %s failed", partial.c_str()); + _error->WarningE("SetupAPTPartialDirectory", "chmod 0%03o of directory %s failed", mode, partial.c_str()); } _error->PushToStack(); @@ -1474,5 +1474,5 @@ pkgAcquire::UriIterator::UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), C } pkgAcquire::UriIterator::~UriIterator() {} -pkgAcquire::MethodConfig::~MethodConfig() {} +pkgAcquire::MethodConfig::~MethodConfig() { delete d; } pkgAcquireStatus::~pkgAcquireStatus() {} diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index f2977b9af..cd09a6944 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -58,6 +58,8 @@ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache), string Jnk = "SIMULATE"; for (decltype(PackageCount) I = 0; I != PackageCount; ++I) FileNames[I] = Jnk; + + Cache->CheckConsistency("simulate"); } /*}}}*/ // Simulate::~Simulate - Destructor /*{{{*/ @@ -515,18 +517,37 @@ void pkgProblemResolver::MakeScores() Score += PrioInstalledAndNotObsolete; // propagate score points along dependencies - for (pkgCache::DepIterator D = InstVer.DependsList(); D.end() == false; ++D) + for (pkgCache::DepIterator D = InstVer.DependsList(); not D.end(); ++D) { if (DepMap[D->Type] == 0) continue; pkgCache::PkgIterator const T = D.TargetPkg(); - if (D->Version != 0) + if (not D.IsIgnorable(T)) + { + if (D->Version != 0) + { + pkgCache::VerIterator const IV = Cache[T].InstVerIter(Cache); + if (IV.end() || not D.IsSatisfied(IV)) + continue; + } + Scores[T->ID] += DepMap[D->Type]; + } + + std::vector<map_id_t> providers; + for (auto Prv = T.ProvidesList(); not Prv.end(); ++Prv) { - pkgCache::VerIterator const IV = Cache[T].InstVerIter(Cache); - if (IV.end() == true || D.IsSatisfied(IV) == false) + if (D.IsIgnorable(Prv)) continue; + auto const PV = Prv.OwnerVer(); + auto const PP = PV.ParentPkg(); + if (PV != Cache[PP].InstVerIter(Cache) || not D.IsSatisfied(Prv)) + continue; + providers.push_back(PP->ID); } - Scores[T->ID] += DepMap[D->Type]; + std::sort(providers.begin(), providers.end()); + providers.erase(std::unique(providers.begin(), providers.end()), providers.end()); + for (auto const prv : providers) + Scores[prv] += DepMap[D->Type]; } } @@ -562,13 +583,25 @@ void pkgProblemResolver::MakeScores() provide important packages extremely important */ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) { - for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; ++P) + auto const transfer = abs(Scores[I->ID] - OldScores[I->ID]); + if (transfer == 0) + continue; + + std::vector<map_id_t> providers; + for (auto Prv = I.ProvidesList(); not Prv.end(); ++Prv) { - // Only do it once per package - if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer) + if (Prv.IsMultiArchImplicit()) + continue; + auto const PV = Prv.OwnerVer(); + auto const PP = PV.ParentPkg(); + if (PV != Cache[PP].InstVerIter(Cache)) continue; - Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]); + providers.push_back(PP->ID); } + std::sort(providers.begin(), providers.end()); + providers.erase(std::unique(providers.begin(), providers.end()), providers.end()); + for (auto const prv : providers) + Scores[prv] += transfer; } /* Protected things are pushed really high up. This number should put them @@ -599,7 +632,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) Flags[Pkg->ID] &= ~Upgradable; bool WasKept = Cache[Pkg].Keep(); - Cache.MarkInstall(Pkg, false, 0, false); + if (not Cache.MarkInstall(Pkg, false, 0, false)) + return false; // This must be a virtual package or something like that. if (Cache[Pkg].InstVerIter(Cache).end() == true) @@ -633,7 +667,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) // Do not change protected packages PkgIterator P = Start.SmartTargetPkg(); - if ((Flags[P->ID] & Protected) == Protected) + if (Cache[P].Protect()) { if (Debug == true) clog << " Reinst Failed because of protected " << P.FullName(false) << endl; @@ -720,6 +754,9 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { pkgDepCache::ActionGroup group(Cache); + if (Debug) + Cache.CheckConsistency("resolve start"); + // Record which packages are marked for install bool Again = false; do @@ -787,8 +824,9 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) changing a breaks c) */ bool Change = true; bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true); + int const MaxCounter = _config->FindI("pkgProblemResolver::MaxCounter", 20); std::vector<PackageKill> KillList; - for (int Counter = 0; Counter != 10 && Change == true; Counter++) + for (int Counter = 0; Counter < MaxCounter && Change; ++Counter) { Change = false; for (pkgCache::Package **K = PList.get(); K != PEnd; K++) @@ -800,7 +838,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) if (Cache[I].CandidateVer != Cache[I].InstallVer && I->CurrentVer != 0 && Cache[I].InstallVer != 0 && (Flags[I->ID] & PreInstalled) != 0 && - (Flags[I->ID] & Protected) == 0 && + not Cache[I].Protect() && (Flags[I->ID] & ReInstateTried) == 0) { if (Debug == true) @@ -835,7 +873,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) pkgCache::DepIterator End; size_t OldSize = 0; - KillList.resize(0); + KillList.clear(); enum {OrRemove,OrKeep} OrOp = OrRemove; for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); @@ -849,7 +887,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { if (OrOp == OrRemove) { - if ((Flags[I->ID] & Protected) != Protected) + if (not Cache[I].Protect()) { if (Debug == true) clog << " Or group remove for " << I.FullName(false) << endl; @@ -903,7 +941,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) targets then we keep the package and bail. This is necessary if a package has a dep on another package that can't be found */ std::unique_ptr<pkgCache::Version *[]> VList(Start.AllTargets()); - if (VList[0] == 0 && (Flags[I->ID] & Protected) != Protected && + if (VList[0] == 0 && not Cache[I].Protect() && Start.IsNegative() == false && Cache[I].NowBroken() == false) { @@ -950,7 +988,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) End.IsNegative() == false)) { // Try a little harder to fix protected packages.. - if ((Flags[I->ID] & Protected) == Protected) + if (Cache[I].Protect()) { if (DoUpgrade(Pkg) == true) { @@ -1037,7 +1075,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } // Skip adding to the kill list if it is protected - if ((Flags[Pkg->ID] & Protected) != 0) + if (Cache[Pkg].Protect() && Cache[Pkg].Mode != pkgDepCache::ModeDelete) continue; if (Debug == true) @@ -1053,7 +1091,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) // Hm, nothing can possibly satisfy this dep. Nuke it. if (VList[0] == 0 && Start.IsNegative() == false && - (Flags[I->ID] & Protected) != Protected) + not Cache[I].Protect()) { bool Installed = Cache[I].Install(); Cache.MarkKeep(I); @@ -1093,33 +1131,38 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) // Apply the kill list now if (Cache[I].InstallVer != 0) { - for (auto J = KillList.begin(); J != KillList.end(); J++) + for (auto const &J : KillList) { - Change = true; - if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0) + bool foundSomething = false; + if ((Cache[J.Dep] & pkgDepCache::DepGNow) == 0) { - if (J->Dep.IsNegative() == true) + if (J.Dep.IsNegative() && Cache.MarkDelete(J.Pkg, false, 0, false)) { - if (Debug == true) - clog << " Fixing " << I.FullName(false) << " via remove of " << J->Pkg.FullName(false) << endl; - Cache.MarkDelete(J->Pkg, false, 0, false); + if (Debug) + std::clog << " Fixing " << I.FullName(false) << " via remove of " << J.Pkg.FullName(false) << '\n'; + foundSomething = true; } } - else + else if (Cache.MarkKeep(J.Pkg, false, false)) { - if (Debug == true) - clog << " Fixing " << I.FullName(false) << " via keep of " << J->Pkg.FullName(false) << endl; - Cache.MarkKeep(J->Pkg, false, false); + if (Debug) + std::clog << " Fixing " << I.FullName(false) << " via keep of " << J.Pkg.FullName(false) << '\n'; + foundSomething = true; } - if (Counter > 1) + if (not foundSomething || Counter > 1) { - if (Scores[I->ID] > Scores[J->Pkg->ID]) - Scores[J->Pkg->ID] = Scores[I->ID]; - } - } + if (Scores[I->ID] > Scores[J.Pkg->ID]) + { + Scores[J.Pkg->ID] = Scores[I->ID]; + Change = true; + } + } + if (foundSomething) + Change = true; + } } - } + } } if (Debug == true) @@ -1133,7 +1176,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { if (Cache[I].InstBroken() == false) continue; - if ((Flags[I->ID] & Protected) != Protected) + if (not Cache[I].Protect()) return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.")); } return _error->Error(_("Unable to correct problems, you have held broken packages.")); @@ -1151,6 +1194,8 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } } + if (Debug) + Cache.CheckConsistency("resolve done"); return true; } @@ -1210,6 +1255,9 @@ bool pkgProblemResolver::ResolveByKeepInternal() { pkgDepCache::ActionGroup group(Cache); + if (Debug) + Cache.CheckConsistency("keep start"); + MakeScores(); /* We have to order the packages so that the broken fixing pass @@ -1253,7 +1301,7 @@ bool pkgProblemResolver::ResolveByKeepInternal() /* Keep the package. If this works then great, otherwise we have to be significantly more aggressive and manipulate its dependencies */ - if ((Flags[I->ID] & Protected) == 0) + if (not Cache[I].Protect()) { if (Debug == true) clog << "Keeping package " << I.FullName(false) << endl; @@ -1301,7 +1349,7 @@ bool pkgProblemResolver::ResolveByKeepInternal() Pkg->CurrentVer == 0) continue; - if ((Flags[I->ID] & Protected) == 0) + if (not Cache[I].Protect()) { if (Debug == true) clog << " Keeping Package " << Pkg.FullName(false) << " due to " << Start.DepType() << endl; @@ -1340,6 +1388,10 @@ bool pkgProblemResolver::ResolveByKeepInternal() } delete[] PList; + + if (Debug) + Cache.CheckConsistency("keep done"); + return true; } /*}}}*/ diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 093364ff1..d64bc4ccf 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -48,6 +48,7 @@ struct APT_PUBLIC PatternTreeParser virtual std::ostream &render(std::ostream &os) { return os; }; std::nullptr_t error(std::string message); + virtual ~Node() = default; }; struct Error : public std::exception diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 3967ba980..565a2b298 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -583,74 +583,54 @@ bool VersionContainerInterface::FromDependency(VersionContainerInterface * const CacheSetHelper &helper) { bool found = false; - switch(selector) { - case CacheSetHelper::ALL: - { - pkgCache::PkgIterator const T = D.TargetPkg(); - for (pkgCache::VerIterator Ver = T.VersionList(); Ver.end() == false; ++Ver) + auto const insertVersion = [&](pkgCache::PkgIterator const &TP, pkgCache::VerIterator const &TV) { + if (not TV.end() && not D.IsIgnorable(TP) && D.IsSatisfied(TV)) { - if (D.IsSatisfied(Ver) == true) - { - vci->insert(Ver); - found = true; - } - for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + vci->insert(TV); + found = true; + } + }; + pkgCache::PkgIterator const T = D.TargetPkg(); + auto const insertAllTargetVersions = [&](auto const &getTargetVersion) { + insertVersion(T, getTargetVersion(T)); + for (auto Prv = T.ProvidesList(); not Prv.end(); ++Prv) + { + if (D.IsIgnorable(Prv)) + continue; + auto const OP = Prv.OwnerPkg(); + auto const TV = getTargetVersion(OP); + if (Prv.OwnerVer() == TV && D.IsSatisfied(Prv)) { - pkgCache::VerIterator const V = Prv.OwnerVer(); - if (unlikely(V.end() == true) || D.IsSatisfied(Prv) == false) - continue; - vci->insert(V); + vci->insert(TV); found = true; } } return found; - } + }; + switch(selector) { + case CacheSetHelper::ALL: + for (auto Ver = T.VersionList(); not Ver.end(); ++Ver) + { + insertVersion(T, Ver); + for (pkgCache::PrvIterator Prv = T.ProvidesList(); not Prv.end(); ++Prv) + if (not D.IsIgnorable(Prv)) + { + vci->insert(Prv.OwnerVer()); + found = true; + } + } + return found; case CacheSetHelper::CANDANDINST: - { found = FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper); found &= FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper); return found; - } case CacheSetHelper::CANDIDATE: - { - pkgCache::PkgIterator const T = D.TargetPkg(); - pkgCache::VerIterator const Cand = Cache[T].CandidateVerIter(Cache); - if (Cand.end() == false && D.IsSatisfied(Cand) == true) - { - vci->insert(Cand); - found = true; - } - for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) - { - pkgCache::VerIterator const V = Prv.OwnerVer(); - pkgCache::VerIterator const Cand = Cache[Prv.OwnerPkg()].CandidateVerIter(Cache); - if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) - continue; - vci->insert(Cand); - found = true; - } - return found; - } + // skip looking if we have already cached that we will find nothing + if (((Cache[D] & pkgDepCache::DepCVer) == 0) != D.IsNegative()) + return found; + return insertAllTargetVersions([&](pkgCache::PkgIterator const &OP) { return Cache[OP].CandidateVerIter(Cache); }); case CacheSetHelper::INSTALLED: - { - pkgCache::PkgIterator const T = D.TargetPkg(); - pkgCache::VerIterator const Cand = T.CurrentVer(); - if (Cand.end() == false && D.IsSatisfied(Cand) == true) - { - vci->insert(Cand); - found = true; - } - for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) - { - pkgCache::VerIterator const V = Prv.OwnerVer(); - pkgCache::VerIterator const Cand = Prv.OwnerPkg().CurrentVer(); - if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) - continue; - vci->insert(Cand); - found = true; - } - return found; - } + return insertAllTargetVersions([&](pkgCache::PkgIterator const &OP) { return OP.CurrentVer(); }); case CacheSetHelper::CANDINST: return FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper) || FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper); @@ -658,25 +638,7 @@ bool VersionContainerInterface::FromDependency(VersionContainerInterface * const return FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper) || FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper); case CacheSetHelper::NEWEST: - { - pkgCache::PkgIterator const T = D.TargetPkg(); - pkgCache::VerIterator const Cand = T.VersionList(); - if (Cand.end() == false && D.IsSatisfied(Cand) == true) - { - vci->insert(Cand); - found = true; - } - for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) - { - pkgCache::VerIterator const V = Prv.OwnerVer(); - pkgCache::VerIterator const Cand = Prv.OwnerPkg().VersionList(); - if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) - continue; - vci->insert(Cand); - found = true; - } - return found; - } + return insertAllTargetVersions([&](pkgCache::PkgIterator const &OP) { return OP.VersionList(); }); case CacheSetHelper::RELEASE: case CacheSetHelper::VERSIONNUMBER: // both make no sense here, so always false diff --git a/apt-pkg/contrib/arfile.cc b/apt-pkg/contrib/arfile.cc index 3fc3afedb..5cb43c690 100644 --- a/apt-pkg/contrib/arfile.cc +++ b/apt-pkg/contrib/arfile.cc @@ -92,7 +92,7 @@ bool ARArchive::LoadHeaders() StrToNum(Head.Size,Memb->Size,sizeof(Head.Size)) == false) { delete Memb; - return _error->Error(_("Invalid archive member header %s"), Head.Name); + return _error->Error(_("Invalid archive member header")); } // Check for an extra long name string @@ -119,7 +119,14 @@ bool ARArchive::LoadHeaders() else { unsigned int I = sizeof(Head.Name) - 1; - for (; Head.Name[I] == ' ' || Head.Name[I] == '/'; I--); + for (; Head.Name[I] == ' ' || Head.Name[I] == '/'; I--) + { + if (I == 0) + { + delete Memb; + return _error->Error(_("Invalid archive member header")); + } + } Memb->Name = std::string(Head.Name,I+1); } diff --git a/apt-pkg/contrib/extracttar.cc b/apt-pkg/contrib/extracttar.cc index 9bb0a55c0..1616c9f12 100644 --- a/apt-pkg/contrib/extracttar.cc +++ b/apt-pkg/contrib/extracttar.cc @@ -254,53 +254,53 @@ bool ExtractTar::Go(pkgDirStream &Stream) default: BadRecord = true; - _error->Warning(_("Unknown TAR header type %u, member %s"),(unsigned)Tar->LinkFlag,Tar->Name); + _error->Warning(_("Unknown TAR header type %u"), (unsigned)Tar->LinkFlag); break; } - + int Fd = -1; - if (BadRecord == false) - if (Stream.DoItem(Itm,Fd) == false) + if (not BadRecord && not Stream.DoItem(Itm, Fd)) + return false; + + if (Fd == -1 || Fd < -2 || BadRecord) + { + if (Itm.Size > 0 && not InFd.Skip(((Itm.Size + (sizeof(Block) - 1)) / sizeof(Block)) * sizeof(Block))) return false; - - // Copy the file over the FD - unsigned long long Size = Itm.Size; - while (Size != 0) + } + else if (Itm.Size != 0) { + // Copy the file over the FD + auto Size = Itm.Size; unsigned char Junk[32*1024]; - unsigned long Read = min(Size, (unsigned long long)sizeof(Junk)); - if (InFd.Read(Junk,((Read+511)/512)*512) == false) - return false; - - if (BadRecord == false) + do { + auto const Read = std::min<unsigned long long>(Size, sizeof(Junk)); + if (not InFd.Read(Junk, ((Read + (sizeof(Block) - 1)) / sizeof(Block)) * sizeof(Block))) + return false; + if (Fd > 0) { - if (write(Fd,Junk,Read) != (signed)Read) - return Stream.Fail(Itm,Fd); + if (not FileFd::Write(Fd, Junk, Read)) + return Stream.Fail(Itm, Fd); } - else + // An Fd of -2 means to send to a special processing function + else if (Fd == -2) { - /* An Fd of -2 means to send to a special processing - function */ - if (Fd == -2) - if (Stream.Process(Itm,Junk,Read,Itm.Size - Size) == false) - return Stream.Fail(Itm,Fd); + if (not Stream.Process(Itm, Junk, Read, Itm.Size - Size)) + return Stream.Fail(Itm, Fd); } - } - - Size -= Read; + + Size -= Read; + } while (Size != 0); } - + // And finish up - if (BadRecord == false) - if (Stream.FinishedFile(Itm,Fd) == false) - return false; - + if (not BadRecord && not Stream.FinishedFile(Itm, Fd)) + return false; LastLongName.erase(); LastLongLink.erase(); } - + return Done(); } /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 045dbe17d..e91c1acc3 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -3150,30 +3150,49 @@ FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink, FileFd * co } FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink, FileFd * const TmpFd, bool Buffered) { - char fn[512]; - FileFd * const Fd = TmpFd == nullptr ? new FileFd() : TmpFd; - + std::string fn; std::string const tempdir = GetTempDir(); - snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", - tempdir.c_str(), Prefix.c_str()); - int const fd = mkstemp(fn); + int fd = -1; +#ifdef O_TMPFILE if (ImmediateUnlink) - unlink(fn); + fd = open(tempdir.c_str(), O_RDWR|O_TMPFILE|O_EXCL|O_CLOEXEC, 0600); if (fd < 0) +#endif { - _error->Errno("GetTempFile",_("Unable to mkstemp %s"), fn); - if (TmpFd == nullptr) - delete Fd; + auto const suffix = Prefix.find(".XXXXXX."); + std::vector<char> buffer(tempdir.length() + 1 + Prefix.length() + (suffix == std::string::npos ? 7 : 0) + 1, '\0'); + if (suffix != std::string::npos) + { + if (snprintf(buffer.data(), buffer.size(), "%s/%s", tempdir.c_str(), Prefix.c_str()) > 0) + { + ssize_t const suffixlen = (buffer.size() - 1) - (tempdir.length() + 1 + suffix + 7); + if (likely(suffixlen > 0)) + fd = mkstemps(buffer.data(), suffixlen); + } + } + else + { + if (snprintf(buffer.data(), buffer.size(), "%s/%s.XXXXXX", tempdir.c_str(), Prefix.c_str()) > 0) + fd = mkstemp(buffer.data()); + } + fn.assign(buffer.data(), buffer.size() - 1); + if (ImmediateUnlink && fd != -1) + unlink(fn.c_str()); + } + if (fd < 0) + { + _error->Errno("GetTempFile",_("Unable to mkstemp %s"), fn.c_str()); return nullptr; } - if (!Fd->OpenDescriptor(fd, FileFd::ReadWrite | (Buffered ? FileFd::BufferedWrite : 0), FileFd::None, true)) + FileFd * const Fd = TmpFd == nullptr ? new FileFd() : TmpFd; + if (not Fd->OpenDescriptor(fd, FileFd::ReadWrite | (Buffered ? FileFd::BufferedWrite : 0), FileFd::None, true)) { - _error->Errno("GetTempFile",_("Unable to write to %s"),fn); + _error->Errno("GetTempFile",_("Unable to write to %s"),fn.c_str()); if (TmpFd == nullptr) delete Fd; return nullptr; } - if (ImmediateUnlink == false) + if (not ImmediateUnlink) Fd->SetFileName(fn); return Fd; } diff --git a/apt-pkg/contrib/srvrec.cc b/apt-pkg/contrib/srvrec.cc index 7d9bf116e..4ca208273 100644 --- a/apt-pkg/contrib/srvrec.cc +++ b/apt-pkg/contrib/srvrec.cc @@ -137,17 +137,12 @@ bool GetSrvRecords(std::string name, std::vector<SrvRec> &Result) // sort them by priority std::stable_sort(Result.begin(), Result.end()); - for(std::vector<SrvRec>::iterator I = Result.begin(); - I != Result.end(); ++I) - { - if (_config->FindB("Debug::Acquire::SrvRecs", false) == true) - { - std::cerr << "SrvRecs: got " << I->target - << " prio: " << I->priority - << " weight: " << I->weight - << std::endl; - } - } + if (_config->FindB("Debug::Acquire::SrvRecs", false)) + for(auto const &R : Result) + std::cerr << "SrvRecs: got " << R.target + << " prio: " << R.priority + << " weight: " << R.weight + << '\n'; return true; } diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index ab957a01a..240946529 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -318,6 +318,8 @@ bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg, return false; if (Section.FindFlag(pkgTagSection::Key::Important,Pkg->Flags,pkgCache::Flag::Important) == false) return false; + if (Section.FindFlag(pkgTagSection::Key::Protected, Pkg->Flags, pkgCache::Flag::Important) == false) + return false; if (std::find(forceEssential.begin(), forceEssential.end(), Pkg.Name()) != forceEssential.end()) { @@ -1018,12 +1020,11 @@ debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile) bool debDebFileParser::UsePackage(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) { - bool res = debListParser::UsePackage(Pkg, Ver); - // we use the full file path as a provides so that the file is found - // by its name - if(NewProvides(Ver, DebFile, Pkg.Cache()->NativeArch(), Ver.VerStr(), 0) == false) + if (not debListParser::UsePackage(Pkg, Ver)) return false; - return res; + // we use the full file path as a provides so that the file is found by its name + // using the MultiArchImplicit flag for this is a bit of a stretch + return NewProvides(Ver, DebFile, Pkg.Cache()->NativeArch(), Ver.VerStr(), pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific); } debListParser::~debListParser() {} diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc index 6904879b6..eac43c3b7 100644 --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@ -270,7 +270,7 @@ static std::string getDpkgStatusLocation(Configuration const &Cnf) { Configuration PathCnf; PathCnf.Set("Dir", Cnf.Find("Dir", "/")); PathCnf.Set("Dir::State::status", "status"); - auto const cnfstatedir = Cnf.Find("Dir::State", STATE_DIR + 1); + auto const cnfstatedir = Cnf.Find("Dir::State", &STATE_DIR[1]); // if the state dir ends in apt, replace it with dpkg - // for the default this gives us the same as the fallback below. // This can't be a ../dpkg as that would play bad with symlinks @@ -466,8 +466,13 @@ pid_t debSystem::ExecDpkg(std::vector<std::string> const &sArgs, int * const inp /*}}}*/ bool debSystem::MultiArchSupported() const /*{{{*/ { + return AssertFeature("multi-arch"); +} + /*}}}*/ +bool debSystem::AssertFeature(std::string const &feature) /*{{{*/ +{ std::vector<std::string> Args = GetDpkgBaseCommand(); - Args.push_back("--assert-multi-arch"); + Args.push_back("--assert-" + feature); pid_t const dpkgAssertMultiArch = ExecDpkg(Args, nullptr, nullptr, true); if (dpkgAssertMultiArch > 0) { diff --git a/apt-pkg/deb/debsystem.h b/apt-pkg/deb/debsystem.h index 2e5a8550c..b3d241512 100644 --- a/apt-pkg/deb/debsystem.h +++ b/apt-pkg/deb/debsystem.h @@ -45,6 +45,7 @@ class debSystem : public pkgSystem APT_HIDDEN static void DpkgChrootDirectory(); APT_HIDDEN static pid_t ExecDpkg(std::vector<std::string> const &sArgs, int * const inputFd, int * const outputFd, bool const DiscardOutput); bool MultiArchSupported() const override; + static bool AssertFeature(std::string const &Feature); std::vector<std::string> ArchitecturesSupported() const override; bool LockInner(OpProgress *const Progress, int timeoutSec) override; diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index ef73881c8..c496538cc 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1416,6 +1416,15 @@ static bool ItemIsEssential(pkgDPkgPM::Item const &I) return true; return (I.Pkg->Flags & pkgCache::Flag::Essential) != 0; } +static bool ItemIsProtected(pkgDPkgPM::Item const &I) +{ + static auto const cachegen = _config->Find("pkgCacheGen::Protected"); + if (cachegen == "none" || cachegen == "native") + return true; + if (unlikely(I.Pkg.end())) + return true; + return (I.Pkg->Flags & pkgCache::Flag::Important) != 0; +} bool pkgDPkgPM::ExpandPendingCalls(std::vector<Item> &List, pkgDepCache &Cache) { { @@ -1712,6 +1721,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) OpenLog(); bool dpkgMultiArch = _system->MultiArchSupported(); + bool dpkgProtectedField = debSystem::AssertFeature("protected-field"); // start pty magic before the loop StartPtyMagic(); @@ -1780,6 +1790,10 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { ADDARGC("--force-remove-essential"); } + if (dpkgProtectedField && std::any_of(I, J, ItemIsProtected)) + { + ADDARGC("--force-remove-protected"); + } ADDARGC("--remove"); break; diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 7730aaf5b..817d9de3c 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -118,6 +118,88 @@ pkgDepCache::~pkgDepCache() delete delLocalPolicy; } /*}}}*/ +bool pkgDepCache::CheckConsistency(char const *const msgtag) /*{{{*/ +{ + auto const OrigPkgState = PkgState; + auto const OrigDepState = DepState; + + PkgState = new StateCache[Head().PackageCount]; + DepState = new unsigned char[Head().DependsCount]; + memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount); + memset(DepState,0,sizeof(*DepState)*Head().DependsCount); + + auto const origUsrSize = iUsrSize; + auto const origDownloadSize = iDownloadSize; + auto const origInstCount = iInstCount; + auto const origDelCount = iDelCount; + auto const origKeepCount = iKeepCount; + auto const origBrokenCount = iBrokenCount; + auto const origPolicyBrokenCount = iPolicyBrokenCount; + auto const origBadCount = iBadCount; + + for (PkgIterator I = PkgBegin(); not I.end(); ++I) + { + auto &State = PkgState[I->ID]; + auto const &OrigState = OrigPkgState[I->ID]; + State.iFlags = OrigState.iFlags; + + State.CandidateVer = OrigState.CandidateVer; + State.InstallVer = OrigState.InstallVer; + State.Mode = OrigState.Mode; + State.Update(I,*this); + State.Status = OrigState.Status; + } + PerformDependencyPass(nullptr); + + _error->PushToStack(); +#define APT_CONSISTENCY_CHECK(VAR,STR) \ + if (orig##VAR != i##VAR) \ + _error->Warning("Internal Inconsistency in pkgDepCache: " #VAR " " STR " vs " STR " (%s)", i##VAR, orig##VAR, msgtag) + APT_CONSISTENCY_CHECK(UsrSize, "%lld"); + APT_CONSISTENCY_CHECK(DownloadSize, "%lld"); + APT_CONSISTENCY_CHECK(InstCount, "%lu"); + APT_CONSISTENCY_CHECK(DelCount, "%lu"); + APT_CONSISTENCY_CHECK(KeepCount, "%lu"); + APT_CONSISTENCY_CHECK(BrokenCount, "%lu"); + APT_CONSISTENCY_CHECK(PolicyBrokenCount, "%lu"); + APT_CONSISTENCY_CHECK(BadCount, "%lu"); +#undef APT_CONSISTENCY_CHECK + + for (PkgIterator P = PkgBegin(); not P.end(); ++P) + { + auto const &State = PkgState[P->ID]; + auto const &OrigState = OrigPkgState[P->ID]; + if (State.Status != OrigState.Status) + _error->Warning("Internal Inconsistency in pkgDepCache: Status of %s is %d vs %d (%s)", P.FullName().c_str(), State.Status, OrigState.Status, msgtag); + if (State.NowBroken() != OrigState.NowBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Now broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast<int>(State.DepState), static_cast<int>(OrigState.DepState), msgtag); + if (State.NowPolicyBroken() != OrigState.NowPolicyBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Now policy broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast<int>(State.DepState), static_cast<int>(OrigState.DepState), msgtag); + if (State.InstBroken() != OrigState.InstBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Install broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast<int>(State.DepState), static_cast<int>(OrigState.DepState), msgtag); + if (State.InstPolicyBroken() != OrigState.InstPolicyBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Install broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast<int>(State.DepState), static_cast<int>(OrigState.DepState), msgtag); + } + + auto inconsistent = _error->PendingError(); + _error->MergeWithStack(); + + delete[] PkgState; + delete[] DepState; + PkgState = OrigPkgState; + DepState = OrigDepState; + iUsrSize = origUsrSize; + iDownloadSize = origDownloadSize; + iInstCount = origInstCount; + iDelCount = origDelCount; + iKeepCount = origKeepCount; + iBrokenCount = origBrokenCount; + iPolicyBrokenCount = origPolicyBrokenCount; + iBadCount = origBadCount; + + return not inconsistent; +} + /*}}}*/ // DepCache::Init - Generate the initial extra structures. /*{{{*/ // --------------------------------------------------------------------- /* This allocats the extension buffers and initializes them. */ @@ -655,8 +737,8 @@ void pkgDepCache::UpdateVerState(PkgIterator const &Pkg) // --------------------------------------------------------------------- /* This will figure out the state of all the packages and all the dependencies based on the current policy. */ -void pkgDepCache::Update(OpProgress * const Prog) -{ +void pkgDepCache::PerformDependencyPass(OpProgress * const Prog) +{ iUsrSize = 0; iDownloadSize = 0; iInstCount = 0; @@ -666,7 +748,6 @@ void pkgDepCache::Update(OpProgress * const Prog) iPolicyBrokenCount = 0; iBadCount = 0; - // Perform the depends pass int Done = 0; for (PkgIterator I = PkgBegin(); I.end() != true; ++I, ++Done) { @@ -699,10 +780,12 @@ void pkgDepCache::Update(OpProgress * const Prog) UpdateVerState(I); AddStates(I); } - if (Prog != 0) Prog->Progress(Done); - +} +void pkgDepCache::Update(OpProgress * const Prog) +{ + PerformDependencyPass(Prog); readStateFile(Prog); } /*}}}*/ @@ -744,25 +827,85 @@ void pkgDepCache::Update(PkgIterator const &Pkg) Update(Pkg.RevDependsList()); // Update the provides map for the current ver - if (Pkg->CurrentVer != 0) - for (PrvIterator P = Pkg.CurrentVer().ProvidesList(); - P.end() != true; ++P) + auto const CurVer = Pkg.CurrentVer(); + if (not CurVer.end()) + for (PrvIterator P = CurVer.ProvidesList(); not P.end(); ++P) Update(P.ParentPkg().RevDependsList()); // Update the provides map for the candidate ver - if (PkgState[Pkg->ID].CandidateVer != 0) - for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList(); - P.end() != true; ++P) + auto const CandVer = PkgState[Pkg->ID].CandidateVerIter(*this); + if (not CandVer.end() && CandVer != CurVer) + for (PrvIterator P = CandVer.ProvidesList(); not P.end(); ++P) Update(P.ParentPkg().RevDependsList()); } /*}}}*/ +// DepCache::IsModeChangeOk - check if it is ok to change the mode /*{{{*/ +// --------------------------------------------------------------------- +/* this is used by all Mark methods on the very first line to check sanity + and prevents mode changes for packages on hold for example. + If you want to check Mode specific stuff you can use the virtual public + Is<Mode>Ok methods instead */ +static char const* PrintMode(char const mode) +{ + switch (mode) + { + case pkgDepCache::ModeInstall: return "Install"; + case pkgDepCache::ModeKeep: return "Keep"; + case pkgDepCache::ModeDelete: return "Delete"; + case pkgDepCache::ModeGarbage: return "Garbage"; + default: return "UNKNOWN"; + } +} +static bool IsModeChangeOk(pkgDepCache &Cache, pkgDepCache::ModeList const mode, pkgCache::PkgIterator const &Pkg, + unsigned long const Depth, bool const FromUser, bool const DebugMarker) +{ + // we are not trying to hard… + if (unlikely(Depth > 100)) + return false; + + // general sanity + if (unlikely(Pkg.end() == true || Pkg->VersionList == 0)) + return false; + + // the user is always right + if (FromUser == true) + return true; + + auto &P = Cache[Pkg]; + // not changing the mode is obviously also fine as we might want to call + // e.g. MarkInstall multiple times with different arguments for the same package + if (P.Mode == mode) + return true; + + // if previous state was set by user only user can reset it + if ((P.iFlags & pkgDepCache::Protected) == pkgDepCache::Protected) + { + if (unlikely(DebugMarker == true)) + std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode) + << " of " << APT::PrettyPkg(&Cache, Pkg) << " as its mode (" << PrintMode(P.Mode) + << ") is protected" << std::endl; + return false; + } + // enforce dpkg holds + else if (mode != pkgDepCache::ModeKeep && Pkg->SelectedState == pkgCache::State::Hold && + _config->FindB("APT::Ignore-Hold",false) == false) + { + if (unlikely(DebugMarker == true)) + std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode) + << " of " << APT::PrettyPkg(&Cache, Pkg) << std::endl; + return false; + } + + return true; +} + /*}}}*/ // DepCache::MarkKeep - Put the package in the keep state /*{{{*/ // --------------------------------------------------------------------- /* */ bool pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser, unsigned long Depth) { - if (IsModeChangeOk(ModeKeep, Pkg, Depth, FromUser) == false) + if (not IsModeChangeOk(*this, ModeKeep, Pkg, Depth, FromUser, DebugMarker)) return false; /* Reject an attempt to keep a non-source broken installed package, those @@ -822,7 +965,7 @@ bool pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser, bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, unsigned long Depth, bool FromUser) { - if (IsModeChangeOk(ModeDelete, Pkg, Depth, FromUser) == false) + if (not IsModeChangeOk(*this, ModeDelete, Pkg, Depth, FromUser, DebugMarker)) return false; StateCache &P = PkgState[Pkg->ID]; @@ -921,75 +1064,18 @@ bool pkgDepCache::IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg, return true; } /*}}}*/ -// DepCache::IsModeChangeOk - check if it is ok to change the mode /*{{{*/ -// --------------------------------------------------------------------- -/* this is used by all Mark methods on the very first line to check sanity - and prevents mode changes for packages on hold for example. - If you want to check Mode specific stuff you can use the virtual public - Is<Mode>Ok methods instead */ -static char const* PrintMode(char const mode) -{ - switch (mode) - { - case pkgDepCache::ModeInstall: return "Install"; - case pkgDepCache::ModeKeep: return "Keep"; - case pkgDepCache::ModeDelete: return "Delete"; - case pkgDepCache::ModeGarbage: return "Garbage"; - default: return "UNKNOWN"; - } -} -bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, - unsigned long const Depth, bool const FromUser) -{ - // we are not trying to hard… - if (unlikely(Depth > 100)) - return false; - - // general sanity - if (unlikely(Pkg.end() == true || Pkg->VersionList == 0)) - return false; - - // the user is always right - if (FromUser == true) - return true; - - StateCache &P = PkgState[Pkg->ID]; - // not changing the mode is obviously also fine as we might want to call - // e.g. MarkInstall multiple times with different arguments for the same package - if (P.Mode == mode) - return true; - - // if previous state was set by user only user can reset it - if ((P.iFlags & Protected) == Protected) - { - if (unlikely(DebugMarker == true)) - std::clog << OutputInDepth(Depth) << "Ignore Mark" << PrintMode(mode) - << " of " << APT::PrettyPkg(this, Pkg) << " as its mode (" << PrintMode(P.Mode) - << ") is protected" << std::endl; - return false; - } - // enforce dpkg holds - else if (mode != ModeKeep && Pkg->SelectedState == pkgCache::State::Hold && - _config->FindB("APT::Ignore-Hold",false) == false) - { - if (unlikely(DebugMarker == true)) - std::clog << OutputInDepth(Depth) << "Hold prevents Mark" << PrintMode(mode) - << " of " << APT::PrettyPkg(this, Pkg) << std::endl; - return false; - } - - return true; -} - /*}}}*/ struct CompareProviders /*{{{*/ { + pkgDepCache const &Cache; pkgCache::PkgIterator const Pkg; - explicit CompareProviders(pkgCache::DepIterator const &Dep) : Pkg(Dep.TargetPkg()) {}; - //bool operator() (APT::VersionList::iterator const &AV, APT::VersionList::iterator const &BV) + explicit CompareProviders(pkgDepCache const &pCache, pkgCache::DepIterator const &Dep) : Cache{pCache}, Pkg{Dep.TargetPkg()} {} bool operator() (pkgCache::VerIterator const &AV, pkgCache::VerIterator const &BV) { pkgCache::PkgIterator const A = AV.ParentPkg(); pkgCache::PkgIterator const B = BV.ParentPkg(); + // Deal with protected first as if they don't work we usually have a problem + if (Cache[A].Protect() != Cache[B].Protect()) + return Cache[A].Protect(); // Prefer MA:same packages if other architectures for it are installed if ((AV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same || (BV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) @@ -1068,10 +1154,13 @@ struct CompareProviders /*{{{*/ } }; /*}}}*/ -bool pkgDepCache::MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, bool FromUser) /*{{{*/ +bool pkgDepCache::MarkInstall_StateChange(pkgCache::PkgIterator const &Pkg, bool AutoInst, bool FromUser) /*{{{*/ { - StateCache &P = PkgState[Pkg->ID]; - P.iFlags &= ~AutoKept; + auto &P = (*this)[Pkg]; + if (P.Protect() && P.InstallVer == P.CandidateVer) + return true; + + P.iFlags &= ~pkgDepCache::AutoKept; /* Target the candidate version and remove the autoflag. We reset the autoflag below if this was called recursively. Otherwise the user @@ -1079,7 +1168,7 @@ bool pkgDepCache::MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, RemoveSizes(Pkg); RemoveStates(Pkg); - P.Mode = ModeInstall; + P.Mode = pkgDepCache::ModeInstall; P.InstallVer = P.CandidateVer; if(FromUser) @@ -1088,16 +1177,16 @@ bool pkgDepCache::MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, // but only if its not marked by the autoremover (aptitude depend on this behavior) // or if we do automatic installation (aptitude never does it) if(P.Status == 2 || (Pkg->CurrentVer != 0 && (AutoInst == true || P.Marked == false))) - P.Flags &= ~Flag::Auto; + P.Flags &= ~pkgCache::Flag::Auto; } else { // Set it to auto if this is a new install. if(P.Status == 2) - P.Flags |= Flag::Auto; + P.Flags |= pkgCache::Flag::Auto; } - if (P.CandidateVer == (Version *)Pkg.CurrentVer()) - P.Mode = ModeKeep; + if (P.CandidateVer == (pkgCache::Version *)Pkg.CurrentVer()) + P.Mode = pkgDepCache::ModeKeep; AddStates(Pkg); Update(Pkg); @@ -1105,8 +1194,37 @@ bool pkgDepCache::MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, return true; } /*}}}*/ -bool pkgDepCache::MarkInstall_CollectDependencies(pkgCache::VerIterator const &PV, std::vector<pkgCache::DepIterator> &toInstall, std::vector<pkgCache::DepIterator> &toRemove) /*{{{*/ +static bool MarkInstall_DiscardCandidate(pkgDepCache &Cache, pkgCache::PkgIterator const &Pkg) /*{{{*/ { + auto &State = Cache[Pkg]; + State.CandidateVer = State.InstallVer; + auto const oldStatus = State.Status; + State.Update(Pkg, Cache); + State.Status = oldStatus; + return true; +} + /*}}}*/ +bool pkgDepCache::MarkInstall_DiscardInstall(pkgCache::PkgIterator const &Pkg) /*{{{*/ +{ + StateCache &State = PkgState[Pkg->ID]; + if (State.Mode == ModeKeep && State.InstallVer == State.CandidateVer && State.CandidateVer == Pkg.CurrentVer()) + return true; + RemoveSizes(Pkg); + RemoveStates(Pkg); + if (Pkg->CurrentVer != 0) + State.InstallVer = Pkg.CurrentVer(); + else + State.InstallVer = nullptr; + State.Mode = ModeKeep; + AddStates(Pkg); + Update(Pkg); + AddSizes(Pkg); + return MarkInstall_DiscardCandidate(*this, Pkg); +} + /*}}}*/ +static bool MarkInstall_CollectDependencies(pkgDepCache const &Cache, pkgCache::VerIterator const &PV, std::vector<pkgCache::DepIterator> &toInstall, std::vector<pkgCache::DepIterator> &toRemove) /*{{{*/ +{ + auto const propagateProctected = Cache[PV.ParentPkg()].Protect(); for (auto Dep = PV.DependsList(); not Dep.end();) { auto const Start = Dep; @@ -1114,17 +1232,17 @@ bool pkgDepCache::MarkInstall_CollectDependencies(pkgCache::VerIterator const &P bool foundSolution = false; for (bool LastOR = true; not Dep.end() && LastOR; ++Dep) { - LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or; - if ((DepState[Dep->ID] & DepInstall) == DepInstall) + LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + if ((Cache[Dep] & pkgDepCache::DepInstall) == pkgDepCache::DepInstall) foundSolution = true; } - if (foundSolution) + if (foundSolution && not propagateProctected) continue; /* Check if this dep should be consider for install. (Pre-)Depends, Conflicts and Breaks for sure. Recommends & Suggests depending on configuration */ - if (not IsImportantDep(Start)) + if (not Cache.IsImportantDep(Start)) continue; if (Start.IsNegative()) @@ -1138,74 +1256,190 @@ bool pkgDepCache::MarkInstall_CollectDependencies(pkgCache::VerIterator const &P return true; } /*}}}*/ -bool pkgDepCache::MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerIterator const &PV, unsigned long Depth, std::vector<pkgCache::DepIterator> &toRemove, APT::PackageVector &toUpgrade) /*{{{*/ +static APT::VersionVector getAllPossibleSolutions(pkgDepCache &Cache, pkgCache::DepIterator Start, pkgCache::DepIterator const &End, APT::CacheSetHelper::VerSelector const selector, bool const sorted) /*{{{*/ { - /* Negative dependencies have no or-group - If the dependency isn't versioned, we try if an upgrade might solve the problem. - Otherwise we remove the offender if needed */ - for (auto const &D : toRemove) + pkgCacheFile CacheFile{&Cache}; + APT::VersionVector toUpgrade, toNewInstall; + do { - std::unique_ptr<Version *[]> List(D.AllTargets()); - pkgCache::PkgIterator TrgPkg = D.TargetPkg(); - for (Version **I = List.get(); *I != 0; I++) + APT::VersionVector verlist = APT::VersionVector::FromDependency(CacheFile, Start, selector); + if (not sorted) { - VerIterator Ver(*this, *I); - PkgIterator Pkg = Ver.ParentPkg(); + std::move(verlist.begin(), verlist.end(), std::back_inserter(toUpgrade)); + continue; + } + std::sort(verlist.begin(), verlist.end(), CompareProviders{Cache, Start}); + for (auto &&Ver : verlist) + { + auto P = Ver.ParentPkg(); + if (P->CurrentVer != 0) + toUpgrade.emplace_back(std::move(Ver)); + else + toNewInstall.emplace_back(std::move(Ver)); + } + } while (Start++ != End); + if (toUpgrade.empty()) + toUpgrade = std::move(toNewInstall); + else + std::move(toNewInstall.begin(), toNewInstall.end(), std::back_inserter(toUpgrade)); - /* The List includes all packages providing this dependency, - even providers which are not installed, so skip them. */ - if (PkgState[Pkg->ID].InstallVer == 0) - continue; + if (not sorted) + std::sort(toUpgrade.begin(), toUpgrade.end(), [](pkgCache::VerIterator const &A, pkgCache::VerIterator const &B) { return A->ID < B->ID; }); + toUpgrade.erase(std::unique(toUpgrade.begin(), toUpgrade.end()), toUpgrade.end()); - // Ignore negative dependencies on versions that are not going to get installed - if (PkgState[Pkg->ID].InstallVer != *I) - continue; + if (not End.IsNegative()) + toUpgrade.erase(std::remove_if(toUpgrade.begin(), toUpgrade.end(), [&Cache](pkgCache::VerIterator const &V) { + auto const P = V.ParentPkg(); + auto const &State = Cache[P]; + return State.Protect() && (State.Delete() || (State.Keep() && P->CurrentVer == 0)); + }), + toUpgrade.end()); + + return toUpgrade; +} + /*}}}*/ +static bool MarkInstall_MarkDeleteForNotUpgradeable(pkgDepCache &Cache, bool const DebugAutoInstall, pkgCache::VerIterator const &PV, unsigned long const Depth, pkgCache::PkgIterator const &Pkg, bool const propagateProctected, APT::PackageVector &delayedRemove)/*{{{*/ +{ + auto &State = Cache[Pkg]; + if (not propagateProctected) + { + if (State.Delete()) + return true; + if(DebugAutoInstall) + std::clog << OutputInDepth(Depth) << " Delayed Removing: " << Pkg.FullName() << " as upgrade is not an option for " << PV.ParentPkg().FullName() << " (" << PV.VerStr() << ")\n"; + if (not IsModeChangeOk(Cache, pkgDepCache::ModeDelete, Pkg, Depth, false, DebugAutoInstall) || + not Cache.IsDeleteOk(Pkg, false, Depth, false)) + return false; + delayedRemove.push_back(Pkg); + return true; + } - if ((D->Version != 0 || TrgPkg != Pkg) && - PkgState[Pkg->ID].CandidateVer != PkgState[Pkg->ID].InstallVer && - PkgState[Pkg->ID].CandidateVer != *I) + if (not State.Delete()) + { + if(DebugAutoInstall) + std::clog << OutputInDepth(Depth) << " Removing: " << Pkg.FullName() << " as upgrade is not an option for " << PV.ParentPkg().FullName() << " (" << PV.VerStr() << ")\n"; + if (not Cache.MarkDelete(Pkg, false, Depth + 1, false)) + return false; + } + MarkInstall_DiscardCandidate(Cache, Pkg); + Cache.MarkProtected(Pkg); + return true; +} + /*}}}*/ +static bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgDepCache &Cache, bool const DebugAutoInstall, pkgCache::VerIterator const &PV, unsigned long Depth, std::vector<pkgCache::DepIterator> &toRemove, APT::PackageVector &toUpgrade, APT::PackageVector &delayedRemove, bool const propagateProctected, bool const FromUser) /*{{{*/ +{ + /* Negative dependencies have no or-group + If the candidate is effected try to keep current and discard candidate + If the current is effected try upgrading to candidate or remove it */ + bool failedToRemoveSomething = false; + APT::PackageVector badCandidate; + for (auto const &D : toRemove) + { + for (auto const &Ver : getAllPossibleSolutions(Cache, D, D, APT::CacheSetHelper::CANDIDATE, true)) + { + auto const Pkg = Ver.ParentPkg(); + auto &State = Cache[Pkg]; + if (State.CandidateVer != Ver) + continue; + if (Pkg.CurrentVer() != Ver) + { + if (State.Install() && not Cache.MarkKeep(Pkg, false, false, Depth)) + { + failedToRemoveSomething = true; + if (not propagateProctected && not FromUser) + break; + } + else if (propagateProctected) + { + MarkInstall_DiscardCandidate(Cache, Pkg); + if (Pkg->CurrentVer == 0) + Cache.MarkProtected(Pkg); + } + else + badCandidate.push_back(Pkg); + } + else if (not MarkInstall_MarkDeleteForNotUpgradeable(Cache, DebugAutoInstall, PV, Depth, Pkg, propagateProctected, delayedRemove)) + { + failedToRemoveSomething = true; + if (not propagateProctected && not FromUser) + break; + } + } + if (failedToRemoveSomething && not propagateProctected && not FromUser) + break; + for (auto const &Ver : getAllPossibleSolutions(Cache, D, D, APT::CacheSetHelper::INSTALLED, true)) + { + auto const Pkg = Ver.ParentPkg(); + auto &State = Cache[Pkg]; + if (State.CandidateVer != Ver && State.CandidateVer != nullptr && + std::find(badCandidate.cbegin(), badCandidate.cend(), Pkg) == badCandidate.end()) toUpgrade.push_back(Pkg); - else + else if (State.CandidateVer == Pkg.CurrentVer()) + ; // already done in the first loop above + else if (not MarkInstall_MarkDeleteForNotUpgradeable(Cache, DebugAutoInstall, PV, Depth, Pkg, propagateProctected, delayedRemove)) { - if(DebugAutoInstall == true) - std::clog << OutputInDepth(Depth) << " Removing: " << Pkg.Name() << " as upgrade is not an option for " << PV.ParentPkg().FullName() << "(" << PV.VerStr() << ")\n"; - if (not MarkDelete(Pkg, false, Depth + 1, false)) - return false; - if (PkgState[PV.ParentPkg()->ID].Protect()) - MarkProtected(Pkg); + failedToRemoveSomething = true; + if (not propagateProctected && not FromUser) + break; } } + if (failedToRemoveSomething && not propagateProctected && not FromUser) + break; } toRemove.clear(); - return true; + return not failedToRemoveSomething; } /*}}}*/ -bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(bool const propagateProctected, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade) /*{{{*/ +static bool MarkInstall_UpgradeOrRemoveConflicts(pkgDepCache &Cache, bool const DebugAutoInstall, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade, bool const propagateProctected, bool const FromUser) /*{{{*/ { + bool failedToRemoveSomething = false; for (auto const &InstPkg : toUpgrade) - if (not MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps)) + if (not Cache[InstPkg].Install() && not Cache.MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps)) { if (DebugAutoInstall) std::clog << OutputInDepth(Depth) << " Removing: " << InstPkg.FullName() << " as upgrade is not possible\n"; - if (not MarkDelete(InstPkg, false, Depth + 1, false)) - return false; - if (propagateProctected) - MarkProtected(InstPkg); + if (not Cache.MarkDelete(InstPkg, false, Depth + 1, false)) + { + failedToRemoveSomething = true; + if (not propagateProctected && not FromUser) + break; + } + else if (propagateProctected) + Cache.MarkProtected(InstPkg); } toUpgrade.clear(); - return true; + return not failedToRemoveSomething; } /*}}}*/ -bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto, bool const propagateProctected) /*{{{*/ +static bool MarkInstall_InstallDependencies(pkgDepCache &Cache, bool const DebugAutoInstall, bool const DebugMarker, pkgCache::PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto, bool const propagateProctected, bool const FromUser) /*{{{*/ { - auto const IsSatisfiedByInstalled = [&](auto const D) { return (DepState[D.ID] & DepInstall) == DepInstall; }; + auto const IsSatisfiedByInstalled = [&](auto &D) { return (Cache[pkgCache::DepIterator{Cache, &D}] & pkgDepCache::DepInstall) == pkgDepCache::DepInstall; }; + bool failedToInstallSomething = false; for (auto &&Dep : toInstall) { - pkgDepCache::DepIterator Start, End; + auto const Copy = Dep; + pkgCache::DepIterator Start, End; Dep.GlobOr(Start, End); - if (std::any_of(Start, Dep, IsSatisfiedByInstalled)) + bool foundSolution = std::any_of(Start, Dep, IsSatisfiedByInstalled); + if (foundSolution && not propagateProctected) continue; bool const IsCriticalDep = Start.IsCritical(); + if (foundSolution) + { + // try propagating protected to this satisfied dependency + if (not IsCriticalDep) + continue; + auto const possibleSolutions = getAllPossibleSolutions(Cache, Start, End, APT::CacheSetHelper::CANDANDINST, false); + if (possibleSolutions.size() != 1) + continue; + auto const InstPkg = possibleSolutions.begin().ParentPkg(); + if (Cache[InstPkg].Protect()) + continue; + Cache.MarkProtected(InstPkg); + if (not Cache.MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps)) + failedToInstallSomething = true; + continue; + } /* Check if any ImportantDep() (but not Critical) were added * since we installed the package. Also check for deps that @@ -1218,21 +1452,21 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign { bool isNewImportantDep = true; bool isPreviouslySatisfiedImportantDep = false; - for (DepIterator D = Pkg.CurrentVer().DependsList(); D.end() != true; ++D) + for (pkgCache::DepIterator D = Pkg.CurrentVer().DependsList(); D.end() != true; ++D) { //FIXME: Should we handle or-group better here? // We do not check if the package we look for is part of the same or-group // we might find while searching, but could that really be a problem? - if (D.IsCritical() || not IsImportantDep(D) || + if (D.IsCritical() || not Cache.IsImportantDep(D) || Start.TargetPkg() != D.TargetPkg()) continue; isNewImportantDep = false; - while ((D->CompareOp & Dep::Or) != 0) + while ((D->CompareOp & pkgCache::Dep::Or) != 0) ++D; - isPreviouslySatisfiedImportantDep = (((*this)[D] & DepGNow) != 0); + isPreviouslySatisfiedImportantDep = ((Cache[D] & pkgDepCache::DepGNow) != 0); if (isPreviouslySatisfiedImportantDep) break; } @@ -1258,41 +1492,22 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign } } - pkgCacheFile CacheFile{this}; - APT::PackageVector toUpgrade, toNewInstall; - do - { - if ((DepState[Start->ID] & DepCVer) != DepCVer) - continue; - - APT::VersionVector verlist = APT::VersionVector::FromDependency(CacheFile, Start, APT::CacheSetHelper::CANDIDATE); - std::sort(verlist.begin(), verlist.end(), CompareProviders{Start}); - for (auto const &Ver : verlist) - { - auto P = Ver.ParentPkg(); - if (P->CurrentVer != 0) - toUpgrade.emplace_back(std::move(P)); - else - toNewInstall.emplace_back(std::move(P)); - } - } while (Start++ != End); - - std::move(toNewInstall.begin(), toNewInstall.end(), std::back_inserter(toUpgrade)); - bool foundSolution = false; - for (auto const &InstPkg : toUpgrade) + auto const possibleSolutions = getAllPossibleSolutions(Cache, Start, End, APT::CacheSetHelper::CANDIDATE, true); + for (auto const &InstVer : possibleSolutions) { - if (PkgState[InstPkg->ID].CandidateVer == nullptr || PkgState[InstPkg->ID].CandidateVer == InstPkg.CurrentVer()) + auto const InstPkg = InstVer.ParentPkg(); + if (Cache[InstPkg].CandidateVer != InstVer) continue; if (DebugAutoInstall) std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.FullName() << " as " << End.DepType() << " of " << Pkg.FullName() << '\n'; - if (propagateProctected && IsCriticalDep && toUpgrade.size() == 1) + if (propagateProctected && IsCriticalDep && possibleSolutions.size() == 1) { - if (not MarkInstall(InstPkg, false, Depth + 1, false, ForceImportantDeps)) + if (not Cache.MarkInstall(InstPkg, false, Depth + 1, false, ForceImportantDeps)) continue; - MarkProtected(InstPkg); + Cache.MarkProtected(InstPkg); } - if (not MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps)) + if (not Cache.MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps)) continue; if (toMoveAuto != nullptr && InstPkg->CurrentVer == 0) @@ -1301,28 +1516,17 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign foundSolution = true; break; } + if (DebugMarker && not foundSolution) + std::clog << OutputInDepth(Depth+1) << APT::PrettyDep(&Cache, Copy) << " can't be satisfied! (dep)\n"; if (not foundSolution && IsCriticalDep) { - if (not propagateProctected) - { - StateCache &State = PkgState[Pkg->ID]; - RemoveSizes(Pkg); - RemoveStates(Pkg); - if (Pkg->CurrentVer != 0) - State.InstallVer = State.CandidateVer = Pkg.CurrentVer(); - else - State.InstallVer = State.CandidateVer = nullptr; - State.Mode = ModeKeep; - State.Update(Pkg, *this); - AddStates(Pkg); - Update(Pkg); - AddSizes(Pkg); - } - return false; + failedToInstallSomething = true; + if (not propagateProctected && not FromUser) + break; } } toInstall.clear(); - return true; + return not failedToInstallSomething; } /*}}}*/ // DepCache::MarkInstall - Put the package in the install state /*{{{*/ @@ -1330,52 +1534,65 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, unsigned long Depth, bool FromUser, bool ForceImportantDeps) { - if (IsModeChangeOk(ModeInstall, Pkg, Depth, FromUser) == false) + StateCache &P = PkgState[Pkg->ID]; + if (P.Protect() && P.Keep() && P.CandidateVer != nullptr && P.CandidateVer == Pkg.CurrentVer()) + ; // we are here to mark our dependencies as protected, no state is changed + else if (not IsModeChangeOk(*this, ModeInstall, Pkg, Depth, FromUser, DebugMarker)) return false; - StateCache &P = PkgState[Pkg->ID]; // See if there is even any possible installation candidate if (P.CandidateVer == 0) return false; - /* Check that it is not already marked for install and that it can be - installed */ - if ((not P.InstPolicyBroken() && not P.InstBroken()) && - (P.Mode == ModeInstall || - P.CandidateVer == (Version *)Pkg.CurrentVer())) + // Check that it is not already marked for install and that it can be installed + if (not P.Protect() && not P.InstPolicyBroken() && not P.InstBroken()) { - if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0) - return MarkKeep(Pkg, false, FromUser, Depth + 1); - return true; + if (P.CandidateVer == Pkg.CurrentVer()) + { + if (P.InstallVer == 0) + return MarkKeep(Pkg, false, FromUser, Depth + 1); + return true; + } + else if (P.Mode == ModeInstall) + return true; } // check if we are allowed to install the package if (not IsInstallOk(Pkg, AutoInst, Depth, FromUser)) return false; + ActionGroup group(*this); + if (FromUser && not MarkInstall_StateChange(Pkg, AutoInst, FromUser)) + return false; + bool const AutoSolve = AutoInst && _config->Find("APT::Solver", "internal") == "internal"; + bool const failEarly = not P.Protect() && not FromUser; + bool hasFailed = false; std::vector<pkgCache::DepIterator> toInstall, toRemove; - APT::PackageVector toUpgrade; + APT::PackageVector toUpgrade, delayedRemove; if (AutoSolve) { VerIterator const PV = P.CandidateVerIter(*this); if (unlikely(PV.end())) return false; - if (not MarkInstall_CollectDependencies(PV, toInstall, toRemove)) + if (not MarkInstall_CollectDependencies(*this, PV, toInstall, toRemove)) return false; - if (not MarkInstall_RemoveConflictsIfNotUpgradeable(PV, Depth, toRemove, toUpgrade)) - return false; + if (not MarkInstall_RemoveConflictsIfNotUpgradeable(*this, DebugAutoInstall, PV, Depth, toRemove, toUpgrade, delayedRemove, P.Protect(), FromUser)) + { + if (failEarly) + return false; + hasFailed = true; + } } - ActionGroup group(*this); - if (not MarkInstall_StateChange(Pkg, AutoInst, FromUser)) + if (not FromUser && not MarkInstall_StateChange(Pkg, AutoInst, FromUser)) return false; if (not AutoSolve) - return true; + return not hasFailed; if (DebugMarker) std::clog << OutputInDepth(Depth) << "MarkInstall " << APT::PrettyPkg(this, Pkg) << " FU=" << FromUser << '\n'; @@ -1399,8 +1616,15 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, operator bool() noexcept { return already; } } propagateProctected{PkgState[Pkg->ID]}; - if (not MarkInstall_UpgradeOrRemoveConflicts(propagateProctected, Depth, ForceImportantDeps, toUpgrade)) - return false; + if (not MarkInstall_UpgradeOrRemoveConflicts(*this, DebugAutoInstall, Depth, ForceImportantDeps, toUpgrade, propagateProctected, FromUser)) + { + if (failEarly) + { + MarkInstall_DiscardInstall(Pkg); + return false; + } + hasFailed = true; + } bool const MoveAutoBitToDependencies = [&]() { VerIterator const PV = P.InstVerIter(*this); @@ -1419,8 +1643,29 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, }(); APT::PackageVector toMoveAuto; - if (not MarkInstall_InstallDependencies(Pkg, Depth, ForceImportantDeps, toInstall, MoveAutoBitToDependencies ? &toMoveAuto : nullptr, propagateProctected)) - return false; + if (not MarkInstall_InstallDependencies(*this, DebugAutoInstall, DebugMarker, Pkg, Depth, ForceImportantDeps, toInstall, + MoveAutoBitToDependencies ? &toMoveAuto : nullptr, propagateProctected, FromUser)) + { + if (failEarly) + { + MarkInstall_DiscardInstall(Pkg); + return false; + } + hasFailed = true; + } + + for (auto const &R : delayedRemove) + { + if (not MarkDelete(R, false, Depth, false)) + { + if (failEarly) + { + MarkInstall_DiscardInstall(Pkg); + return false; + } + hasFailed = true; + } + } if (MoveAutoBitToDependencies) { @@ -1435,7 +1680,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, MarkAuto(InstPkg, false); } } - return true; + return not hasFailed; } /*}}}*/ // DepCache::IsInstallOk - check if it is ok to install this package /*{{{*/ @@ -1810,22 +2055,24 @@ void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache) { // Some info VerIterator Ver = CandidateVerIter(Cache); - + // Use a null string or the version string if (Ver.end() == true) CandVersion = ""; else CandVersion = Ver.VerStr(); - + // Find the current version - CurVersion = ""; if (Pkg->CurrentVer != 0) CurVersion = Pkg.CurrentVer().VerStr(); + else + CurVersion = ""; // Figure out if its up or down or equal - Status = Ver.CompareVer(Pkg.CurrentVer()); if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0) - Status = 2; + Status = 2; + else + Status = Ver.CompareVer(Pkg.CurrentVer()); } /*}}}*/ // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/ @@ -1975,7 +2222,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) reason = "Required"; else if (userFunc.InRootSet(P)) reason = "Blacklisted [APT::NeverAutoRemove]"; - else if (IsModeChangeOk(ModeGarbage, P, 0, false) == false) + else if (not IsModeChangeOk(*this, ModeGarbage, P, 0, false, DebugMarker)) reason = "Hold"; else continue; diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 1579fedbe..78f88ba2f 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -368,6 +368,7 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];}; inline StateCache &operator [](PkgIterator const &I) const {return PkgState[I->ID];}; inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];}; + inline unsigned char const &operator [](DepIterator const &I) const {return DepState[I->ID];}; /** \return A function identifying packages in the root set other * than manually installed packages and essential packages, or \b @@ -501,6 +502,8 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace pkgDepCache(pkgCache * const Cache,Policy * const Plcy = 0); virtual ~pkgDepCache(); + bool CheckConsistency(char const *const msgtag = ""); + protected: // methods call by IsInstallOk bool IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, @@ -515,14 +518,10 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace private: void * const d; - APT_HIDDEN bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, - unsigned long const Depth, bool const FromUser); - APT_HIDDEN bool MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, bool FromUser); - APT_HIDDEN bool MarkInstall_CollectDependencies(pkgCache::VerIterator const &PV, std::vector<pkgCache::DepIterator> &toInstall, std::vector<pkgCache::DepIterator> &toRemove); - APT_HIDDEN bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerIterator const &PV, unsigned long Depth, std::vector<pkgCache::DepIterator> &toRemove, APT::PackageVector &toUpgrade); - APT_HIDDEN bool MarkInstall_UpgradeOrRemoveConflicts(bool const propagateProtected, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade); - APT_HIDDEN bool MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto, bool const propagateProtected); + APT_HIDDEN bool MarkInstall_DiscardInstall(PkgIterator const &Pkg); + + APT_HIDDEN void PerformDependencyPass(OpProgress * const Prog); }; #endif diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index fe6f55dcb..7e3993be4 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -29,8 +29,10 @@ #include <sys/stat.h> #include <unistd.h> +#include <algorithm> #include <array> #include <limits> +#include <sstream> #include <string> #include <apti18n.h> @@ -119,19 +121,25 @@ static bool WriteScenarioDependency(FileFd &output, pkgCache::VerIterator const for (size_t i = 1; i < dependencies.size(); ++i) if (dependencies[i].empty() == false) WriteOkay(Okay, output, "\n", DepMap[i], ": ", dependencies[i]); - string provides; - for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv) + std::vector<std::string> provides; + for (auto Prv = Ver.ProvidesList(); not Prv.end(); ++Prv) { - if (Prv.IsMultiArchImplicit() == true) + if (Prv.IsMultiArchImplicit()) continue; - if (provides.empty() == false) - provides.append(", "); - provides.append(Prv.Name()); + std::string provide = Prv.Name(); if (Prv->ProvideVersion != 0) - provides.append(" (= ").append(Prv.ProvideVersion()).append(")"); + provide.append(" (= ").append(Prv.ProvideVersion()).append(")"); + if ((Ver->MultiArch & pkgCache::Version::Foreign) != 0 && std::find(provides.cbegin(), provides.cend(), provide) != provides.cend()) + continue; + provides.emplace_back(std::move(provide)); + } + if (not provides.empty()) + { + std::ostringstream out; + std::copy(provides.begin(), provides.end() - 1, std::ostream_iterator<std::string>(out, ", ")); + out << provides.back(); + WriteOkay(Okay, output, "\nProvides: ", out.str()); } - if (provides.empty() == false) - WriteOkay(Okay, output, "\nProvides: ", provides); return WriteOkay(Okay, output, "\n"); } /*}}}*/ @@ -262,7 +270,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress *Progres for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false && likely(Okay); ++Pkg) { std::string const arch = Pkg.Arch(); - if (std::find(archs.begin(), archs.end(), arch) == archs.end()) + if (Pkg->CurrentVer == 0 && std::find(archs.begin(), archs.end(), arch) == archs.end()) continue; for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false && likely(Okay); ++Ver, ++p) { @@ -335,9 +343,8 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FileFd &output, } bool Okay = WriteOkay(output, "Request: EDSP 0.5\n"); - const char *arch = _config->Find("APT::Architecture").c_str(); std::vector<string> archs = APT::Configuration::getArchitectures(); - WriteOkay(Okay, output, "Architecture: ", arch, "\n", + WriteOkay(Okay, output, "Architecture: ", _config->Find("APT::Architecture").c_str(), "\n", "Architectures:"); for (std::vector<string>::const_iterator a = archs.begin(); a != archs.end(); ++a) WriteOkay(Okay, output, " ", *a); @@ -858,9 +865,8 @@ bool EIPP::WriteRequest(pkgDepCache &Cache, FileFd &output, /*{{{*/ } bool Okay = WriteOkay(output, "Request: EIPP 0.1\n"); - const char *arch = _config->Find("APT::Architecture").c_str(); std::vector<string> archs = APT::Configuration::getArchitectures(); - WriteOkay(Okay, output, "Architecture: ", arch, "\n", + WriteOkay(Okay, output, "Architecture: ", _config->Find("APT::Architecture").c_str(), "\n", "Architectures:"); for (std::vector<string>::const_iterator a = archs.begin(); a != archs.end(); ++a) WriteOkay(Okay, output, " ", *a); diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index a619368ec..b9d9b15d2 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -134,18 +134,18 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.CndSet("Dir","/"); // State - Cnf.CndSet("Dir::State", STATE_DIR + 1); + Cnf.CndSet("Dir::State", &STATE_DIR[1]); Cnf.CndSet("Dir::State::lists","lists/"); Cnf.CndSet("Dir::State::cdroms","cdroms.list"); // Cache - Cnf.CndSet("Dir::Cache", CACHE_DIR + 1); + Cnf.CndSet("Dir::Cache", &CACHE_DIR[1]); Cnf.CndSet("Dir::Cache::archives","archives/"); Cnf.CndSet("Dir::Cache::srcpkgcache","srcpkgcache.bin"); Cnf.CndSet("Dir::Cache::pkgcache","pkgcache.bin"); // Configuration - Cnf.CndSet("Dir::Etc", CONF_DIR + 1); + Cnf.CndSet("Dir::Etc", &CONF_DIR[1]); Cnf.CndSet("Dir::Etc::sourcelist","sources.list"); Cnf.CndSet("Dir::Etc::sourceparts","sources.list.d"); Cnf.CndSet("Dir::Etc::main","apt.conf"); @@ -162,7 +162,7 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.CndSet("Dir::Media::MountPath","/media/apt"); // State - Cnf.CndSet("Dir::Log", LOG_DIR + 1); + Cnf.CndSet("Dir::Log", &LOG_DIR[1]); Cnf.CndSet("Dir::Log::Terminal","term.log"); Cnf.CndSet("Dir::Log::History","history.log"); Cnf.CndSet("Dir::Log::Planner","eipp.log.xz"); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 02448a073..7eb5ab10b 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -214,8 +214,6 @@ map_id_t pkgCache::sHash(StringView Str) const return Hash % HeaderP->GetHashTableSize(); } -#if defined(HAVE_FMV_SSE42_AND_CRC32) - #ifdef HAVE_FMV_SSE42_AND_CRC32 __attribute__((target("sse4.2"))) static uint32_t hash32(uint32_t crc32, const unsigned char *input, size_t size) { @@ -253,7 +251,6 @@ __attribute__((target("sse4.2"))) static uint32_t hash32(uint32_t crc32, const u crc32 ^= 0xffffffffU; return crc32; } -#endif __attribute__((target("default"))) #endif diff --git a/apt-pkg/tagfile-keys.list b/apt-pkg/tagfile-keys.list index a979a404b..a16bc686a 100644 --- a/apt-pkg/tagfile-keys.list +++ b/apt-pkg/tagfile-keys.list @@ -48,6 +48,7 @@ Package-Revision Package-Type Pre-Depends Priority +Protected Provides Recommended Recommends diff --git a/apt-pkg/tagfile-order.c b/apt-pkg/tagfile-order.c index 4c2068c00..bb199b32e 100644 --- a/apt-pkg/tagfile-order.c +++ b/apt-pkg/tagfile-order.c @@ -11,7 +11,7 @@ static const char *iTFRewritePackageOrder[] = { "Architecture", "Subarchitecture", // Used only by d-i "Version", - "Revision", // Obsolete (warning in dpkg) + "Revision", // Obsolete (warning in dpkg) "Package-Revision", // Obsolete (warning in dpkg) "Package_Revision", // Obsolete (warning in dpkg) "Kernel-Version", // Used only by d-i @@ -23,6 +23,7 @@ static const char *iTFRewritePackageOrder[] = { "Priority", "Class", // dpkg nickname for Priority "Build-Essential", + "Protected", "Essential", "Installer-Menu-Item", // Used only by d-i "Section", |