summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire.cc8
-rw-r--r--apt-pkg/algorithms.cc130
-rw-r--r--apt-pkg/cachefilter-patterns.h1
-rw-r--r--apt-pkg/cacheset.cc112
-rw-r--r--apt-pkg/contrib/arfile.cc11
-rw-r--r--apt-pkg/contrib/extracttar.cc60
-rw-r--r--apt-pkg/contrib/fileutl.cc45
-rw-r--r--apt-pkg/contrib/srvrec.cc17
-rw-r--r--apt-pkg/deb/deblistparser.cc11
-rw-r--r--apt-pkg/deb/debsystem.cc9
-rw-r--r--apt-pkg/deb/debsystem.h1
-rw-r--r--apt-pkg/deb/dpkgpm.cc14
-rw-r--r--apt-pkg/depcache.cc653
-rw-r--r--apt-pkg/depcache.h13
-rw-r--r--apt-pkg/edsp.cc34
-rw-r--r--apt-pkg/init.cc8
-rw-r--r--apt-pkg/pkgcache.cc3
-rw-r--r--apt-pkg/tagfile-keys.list1
-rw-r--r--apt-pkg/tagfile-order.c3
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",