summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc46
-rw-r--r--apt-pkg/acquire-item.h11
-rw-r--r--apt-pkg/acquire.cc3
-rw-r--r--apt-pkg/cachefile.cc3
-rw-r--r--apt-pkg/cachefilter.h1
-rw-r--r--apt-pkg/clean.cc5
-rw-r--r--apt-pkg/contrib/proxy.cc82
-rw-r--r--apt-pkg/contrib/proxy.h16
-rw-r--r--apt-pkg/contrib/strutl.cc54
-rw-r--r--apt-pkg/deb/deblistparser.cc14
-rw-r--r--apt-pkg/deb/dpkgpm.cc251
-rw-r--r--apt-pkg/deb/dpkgpm.h1
-rw-r--r--apt-pkg/depcache.cc3
-rw-r--r--apt-pkg/edsp.cc7
-rw-r--r--apt-pkg/packagemanager.cc49
-rw-r--r--apt-pkg/upgrade.cc6
16 files changed, 395 insertions, 157 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 0178456a8..6cb9b012a 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -356,7 +356,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
Desc.URI = URI + ".diff/Index";
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
- DestFile += URItoFileName(URI) + string(".DiffIndex");
+ DestFile += URItoFileName(Desc.URI);
if(Debug)
std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
@@ -392,7 +392,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
string pkgAcqDiffIndex::Custom600Headers()
{
string Final = _config->FindDir("Dir::State::lists");
- Final += URItoFileName(RealURI) + string(".IndexDiff");
+ Final += URItoFileName(Desc.URI);
if(Debug)
std::clog << "Custom600Header-IMS: " << Final << std::endl;
@@ -932,8 +932,6 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
}
CompressionExtension = comprExt;
- Verify = true;
-
Init(URI, URIDesc, ShortDesc);
}
pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
@@ -957,13 +955,6 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
if (CompressionExtension.empty() == false)
CompressionExtension.erase(CompressionExtension.end()-1);
- // only verify non-optional targets, see acquire-item.h for a FIXME
- // to make this more flexible
- if (Target->IsOptional())
- Verify = false;
- else
- Verify = true;
-
Init(Target->URI, Target->Description, Target->ShortDesc);
}
/*}}}*/
@@ -1056,23 +1047,24 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
return;
}
- /* Verify the index file for correctness (all indexes must
- * have a Package field) (LP: #346386) (Closes: #627642) */
- if (Verify == true)
+ // FIXME: this can go away once we only ever download stuff that
+ // has a valid hash and we never do GET based probing
+ //
+ /* Always verify the index file for correctness (all indexes must
+ * have a Package field) (LP: #346386) (Closes: #627642)
+ */
+ FileFd fd(DestFile, FileFd::ReadOnly);
+ // Only test for correctness if the file is not empty (empty is ok)
+ if (fd.FileSize() > 0)
{
- FileFd fd(DestFile, FileFd::ReadOnly);
- // Only test for correctness if the file is not empty (empty is ok)
- if (fd.FileSize() > 0)
- {
- pkgTagSection sec;
- pkgTagFile tag(&fd);
-
- // all our current indexes have a field 'Package' in each section
- if (_error->PendingError() == true || tag.Step(sec) == false || sec.Exists("Package") == false)
- {
- RenameOnError(InvalidFormat);
- return;
- }
+ pkgTagSection sec;
+ pkgTagFile tag(&fd);
+
+ // all our current indexes have a field 'Package' in each section
+ if (_error->PendingError() == true || tag.Step(sec) == false || sec.Exists("Package") == false)
+ {
+ RenameOnError(InvalidFormat);
+ return;
}
}
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index f48d2a0d7..06537bf2c 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -685,15 +685,8 @@ class pkgAcqIndex : public pkgAcquire::Item
*/
bool Erase;
- /** \brief Verify for correctness by checking if a "Package"
- * tag is found in the index. This can be set to
- * false for optional index targets
- *
- */
- // FIXME: instead of a bool it should use a verify string that will
- // then be used in the pkgAcqIndex::Done method to ensure that
- // the downloaded file contains the expected tag
- bool Verify;
+ // Unused, used to be used to verify that "Packages: " header was there
+ bool __DELME_ON_NEXT_ABI_BREAK_Verify;
/** \brief The download request that is currently being
* processed.
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index a187a00ae..057bc24cd 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -486,6 +486,9 @@ bool pkgAcquire::Clean(string Dir)
if (DirectoryExists(Dir) == false)
return true;
+ if(Dir == "/")
+ return _error->Error(_("Clean of %s is not supported"), Dir.c_str());
+
DIR *D = opendir(Dir.c_str());
if (D == 0)
return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc
index 0fd40106f..ea3d45480 100644
--- a/apt-pkg/cachefile.cc
+++ b/apt-pkg/cachefile.cc
@@ -143,6 +143,9 @@ bool pkgCacheFile::BuildDepCache(OpProgress *Progress)
if (DCache != NULL)
return true;
+ if (BuildPolicy(Progress) == false)
+ return false;
+
DCache = new pkgDepCache(Cache,Policy);
if (_error->PendingError() == true)
return false;
diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h
index 49d2855f5..6d10d1163 100644
--- a/apt-pkg/cachefilter.h
+++ b/apt-pkg/cachefilter.h
@@ -73,6 +73,7 @@ public:
bool operator() (pkgCache::VerIterator const &Ver);
~PackageArchitectureMatchesSpecification();
};
+ /*}}}*/
#else
diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc
index 0ee3b765d..37128e9aa 100644
--- a/apt-pkg/clean.cc
+++ b/apt-pkg/clean.cc
@@ -34,7 +34,10 @@
bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache)
{
bool CleanInstalled = _config->FindB("APT::Clean-Installed",true);
-
+
+ if(Dir == "/")
+ return _error->Error(_("Clean of %s is not supported"), Dir.c_str());
+
DIR *D = opendir(Dir.c_str());
if (D == 0)
return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
diff --git a/apt-pkg/contrib/proxy.cc b/apt-pkg/contrib/proxy.cc
new file mode 100644
index 000000000..b58db8478
--- /dev/null
+++ b/apt-pkg/contrib/proxy.cc
@@ -0,0 +1,82 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+/* ######################################################################
+
+ Proxy - Proxy releated functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include<apt-pkg/configuration.h>
+#include<apt-pkg/error.h>
+#include<apt-pkg/fileutl.h>
+#include<apt-pkg/strutl.h>
+
+#include<iostream>
+#include <unistd.h>
+
+#include "proxy.h"
+
+
+// AutoDetectProxy - auto detect proxy /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool AutoDetectProxy(URI &URL)
+{
+ // we support both http/https debug options
+ bool Debug = _config->FindB("Debug::Acquire::"+URL.Access,false);
+
+ // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old
+ // name without the dash ("-")
+ std::string AutoDetectProxyCmd = _config->Find("Acquire::"+URL.Access+"::Proxy-Auto-Detect",
+ _config->Find("Acquire::"+URL.Access+"::ProxyAutoDetect"));
+
+ if (AutoDetectProxyCmd.empty())
+ return true;
+
+ if (Debug)
+ std::clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << std::endl;
+
+ int Pipes[2] = {-1,-1};
+ if (pipe(Pipes) != 0)
+ return _error->Errno("pipe", "Failed to create Pipe");
+
+ pid_t Process = ExecFork();
+ if (Process == 0)
+ {
+ close(Pipes[0]);
+ dup2(Pipes[1],STDOUT_FILENO);
+ SetCloseExec(STDOUT_FILENO,false);
+
+ std::string foo = URL;
+ const char *Args[4];
+ Args[0] = AutoDetectProxyCmd.c_str();
+ Args[1] = foo.c_str();
+ Args[2] = 0;
+ execv(Args[0],(char **)Args);
+ std::cerr << "Failed to exec method " << Args[0] << std::endl;
+ _exit(100);
+ }
+ char buf[512];
+ int InFd = Pipes[0];
+ close(Pipes[1]);
+ int res = read(InFd, buf, sizeof(buf)-1);
+ ExecWait(Process, "ProxyAutoDetect", true);
+
+ if (res < 0)
+ return _error->Errno("read", "Failed to read");
+ if (res == 0)
+ return _error->Warning("ProxyAutoDetect returned no data");
+
+ // add trailing \0
+ buf[res] = 0;
+
+ if (Debug)
+ std::clog << "auto detect command returned: '" << buf << "'" << std::endl;
+
+ if (strstr(buf, URL.Access.c_str()) == buf)
+ _config->Set("Acquire::"+URL.Access+"::proxy::"+URL.Host, _strstrip(buf));
+
+ return true;
+}
+ /*}}}*/
diff --git a/apt-pkg/contrib/proxy.h b/apt-pkg/contrib/proxy.h
new file mode 100644
index 000000000..2cbcd07b4
--- /dev/null
+++ b/apt-pkg/contrib/proxy.h
@@ -0,0 +1,16 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+/* ######################################################################
+
+ Proxy - Proxy operations
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef PKGLIB_PROXY_H
+#define PKGLIB_PROXY_H
+
+class URI;
+bool AutoDetectProxy(URI &URL);
+
+
+#endif
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index 2100ee47b..87f57a30e 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -45,14 +45,26 @@ using namespace std;
// ---------------------------------------------------------------------
namespace APT {
namespace String {
-std::string Strip(const std::string &s)
+std::string Strip(const std::string &str)
{
- size_t start = s.find_first_not_of(" \t\n");
- // only whitespace
- if (start == string::npos)
+ // ensure we have at least one character
+ if (str.empty() == true)
+ return str;
+
+ char const * const s = str.c_str();
+ size_t start = 0;
+ for (; isspace(s[start]) != 0; ++start)
+ ; // find the first not-space
+
+ // string contains only whitespaces
+ if (s[start] == '\0')
return "";
- size_t end = s.find_last_not_of(" \t\n");
- return s.substr(start, end-start+1);
+
+ size_t end = str.length() - 1;
+ for (; isspace(s[end]) != 0; --end)
+ ; // find the last not-space
+
+ return str.substr(start, end - start + 1);
}
bool Endswith(const std::string &s, const std::string &end)
@@ -434,23 +446,30 @@ string TimeToStr(unsigned long Sec)
/* This replaces all occurrences of Subst with Contents in Str. */
string SubstVar(const string &Str,const string &Subst,const string &Contents)
{
+ if (Subst.empty() == true)
+ return Str;
+
string::size_type Pos = 0;
string::size_type OldPos = 0;
string Temp;
-
- while (OldPos < Str.length() &&
+
+ while (OldPos < Str.length() &&
(Pos = Str.find(Subst,OldPos)) != string::npos)
{
- Temp += string(Str,OldPos,Pos) + Contents;
- OldPos = Pos + Subst.length();
+ if (OldPos != Pos)
+ Temp.append(Str, OldPos, Pos - OldPos);
+ if (Contents.empty() == false)
+ Temp.append(Contents);
+ OldPos = Pos + Subst.length();
}
-
+
if (OldPos == 0)
return Str;
-
+
+ if (OldPos >= Str.length())
+ return Temp;
return Temp + string(Str,OldPos);
}
-
string SubstVar(string Str,const struct SubstVar *Vars)
{
for (; Vars->Subst != 0; Vars++)
@@ -697,9 +716,12 @@ string LookupTag(const string &Message,const char *Tag,const char *Default)
then returns the result. Several varients on true/false are checked. */
int StringToBool(const string &Text,int Default)
{
- char *End;
- int Res = strtol(Text.c_str(),&End,0);
- if (End != Text.c_str() && Res >= 0 && Res <= 1)
+ char *ParseEnd;
+ int Res = strtol(Text.c_str(),&ParseEnd,0);
+ // ensure that the entire string was converted by strtol to avoid
+ // failures on "apt-cache show -a 0ad" where the "0" is converted
+ const char *TextEnd = Text.c_str()+Text.size();
+ if (ParseEnd == TextEnd && Res >= 0 && Res <= 1)
return Res;
// Check for positives
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index a1bcfb710..7d4fd52cf 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -108,7 +108,7 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/
{
unsigned char MA;
string const MultiArch = Section.FindS("Multi-Arch");
- if (MultiArch.empty() == true)
+ if (MultiArch.empty() == true || MultiArch == "no")
MA = pkgCache::Version::None;
else if (MultiArch == "same") {
if (ArchitectureAll() == true)
@@ -145,7 +145,8 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/
bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
{
// Parse the section
- Ver->Section = UniqFindTagWrite("Section");
+ unsigned long const idxSection = UniqFindTagWrite("Section");
+ Ver->Section = idxSection;
Ver->MultiArch = ParseMultiArch(true);
// Archive Size
Ver->Size = Section.FindULL("Size");
@@ -260,7 +261,10 @@ bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
pkgCache::VerIterator &Ver)
{
if (Pkg->Section == 0)
- Pkg->Section = UniqFindTagWrite("Section");
+ {
+ unsigned long const idxSection = UniqFindTagWrite("Section");
+ Pkg->Section = idxSection;
+ }
string const static myArch = _config->Find("APT::Architecture");
// Possible values are: "all", "native", "installed" and "none"
@@ -799,8 +803,8 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
Start = ParseDepends(Start,Stop,Package,Version,Op);
if (Start == 0)
return _error->Error("Problem parsing Provides line");
- if (Op != pkgCache::Dep::NoOp) {
- _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str());
+ if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) {
+ _error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str());
} else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
if (NewProvidesAllArch(Ver, Package, Version) == false)
return false;
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 613a4de9f..04a13a86c 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -59,8 +59,8 @@ class pkgDPkgPMPrivate
{
public:
pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
- term_out(NULL), history_out(NULL),
- progress(NULL), master(-1), slave(-1)
+ term_out(NULL), history_out(NULL),
+ progress(NULL), master(-1), slave(NULL)
{
dpkgbuf[0] = '\0';
}
@@ -77,9 +77,9 @@ public:
APT::Progress::PackageManager *progress;
// pty stuff
- struct termios tt;
+ struct termios tt;
int master;
- int slave;
+ char * slave;
// signals
sigset_t sigmask;
@@ -510,7 +510,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
return result;
}
/*}}}*/
-// DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/
+// DPkgPM::DoStdin - Read stdin and pass to master pty /*{{{*/
// ---------------------------------------------------------------------
/*
*/
@@ -564,8 +564,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
'status: <pkg>: <pkg qstate>'
'status: <pkg>:<arch>: <pkg qstate>'
- 'processing: {install,configure,remove,purge,disappear,trigproc}: pkg'
- 'processing: {install,configure,remove,purge,disappear,trigproc}: trigger'
+ 'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: pkg'
+ 'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: trigger'
*/
// we need to split on ": " (note the appended space) as the ':' is
@@ -589,12 +589,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
std::string action;
// "processing" has the form "processing: action: pkg or trigger"
- // with action = ["install", "configure", "remove", "purge", "disappear",
- // "trigproc"]
+ // with action = ["install", "upgrade", "configure", "remove", "purge",
+ // "disappear", "trigproc"]
if (prefix == "processing")
{
pkgname = APT::String::Strip(list[2]);
action = APT::String::Strip(list[1]);
+ // we don't care for the difference (as dpkg doesn't really either)
+ if (action == "upgrade")
+ action = "install";
}
// "status" has the form: "status: pkg: state"
// with state in ["half-installed", "unpacked", "half-configured",
@@ -621,15 +624,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
{
if(action == "error")
{
- d->progress->Error(list[1], PackagesDone, PackagesTotal,
+ d->progress->Error(pkgname, PackagesDone, PackagesTotal,
list[3]);
pkgFailures++;
- WriteApportReport(list[1].c_str(), list[3].c_str());
+ WriteApportReport(pkgname.c_str(), list[3].c_str());
return;
}
else if(action == "conffile-prompt")
{
- d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal,
+ d->progress->ConffilePrompt(pkgname, PackagesDone, PackagesTotal,
list[3]);
return;
}
@@ -638,27 +641,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
// at this point we know that we should have a valid pkgname, so build all
// the info from it
- // dpkg does not send always send "pkgname:arch" so we add it here
- // if needed
+ // dpkg does not always send "pkgname:arch" so we add it here if needed
if (pkgname.find(":") == std::string::npos)
{
- // find the package in the group that is in a touched by dpkg
- // if there are multiple dpkg will send us a full pkgname:arch
+ // find the package in the group that is touched by dpkg
+ // if there are multiple pkgs dpkg would send us a full pkgname:arch
pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname);
- if (Grp.end() == false)
+ if (Grp.end() == false)
{
- pkgCache::PkgIterator P = Grp.PackageList();
- for (; P.end() != true; P = Grp.NextPkg(P))
- {
- if(Cache[P].Mode != pkgDepCache::ModeKeep)
- {
- pkgname = P.FullName();
- break;
- }
- }
+ pkgCache::PkgIterator P = Grp.PackageList();
+ for (; P.end() != true; P = Grp.NextPkg(P))
+ {
+ if(Cache[P].Keep() == false || Cache[P].ReInstall() == true)
+ {
+ pkgname = P.FullName();
+ break;
+ }
+ }
}
}
-
+
const char* const pkg = pkgname.c_str();
std::string short_pkgname = StringSplit(pkgname, ":")[0];
std::string arch = "";
@@ -697,28 +699,29 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
if (prefix == "status")
{
vector<struct DpkgState> const &states = PackageOps[pkg];
- const char *next_action = NULL;
if(PackageOpsDone[pkg] < states.size())
- next_action = states[PackageOpsDone[pkg]].state;
- // check if the package moved to the next dpkg state
- if(next_action && (action == next_action))
{
- // only read the translation if there is actually a next
- // action
- const char *translation = _(states[PackageOpsDone[pkg]].str);
- std::string msg;
-
- // we moved from one dpkg state to a new one, report that
- PackageOpsDone[pkg]++;
- PackagesDone++;
-
- strprintf(msg, translation, i18n_pkgname.c_str());
- d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
-
+ char const * const next_action = states[PackageOpsDone[pkg]].state;
+ if (next_action && Debug == true)
+ std::clog << "(parsed from dpkg) pkg: " << short_pkgname
+ << " action: " << action << " (expected: '" << next_action << "' "
+ << PackageOpsDone[pkg] << " of " << states.size() << ")" << endl;
+
+ // check if the package moved to the next dpkg state
+ if(next_action && (action == next_action))
+ {
+ // only read the translation if there is actually a next action
+ char const * const translation = _(states[PackageOpsDone[pkg]].str);
+
+ // we moved from one dpkg state to a new one, report that
+ ++PackageOpsDone[pkg];
+ ++PackagesDone;
+
+ std::string msg;
+ strprintf(msg, translation, i18n_pkgname.c_str());
+ d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
+ }
}
- if (Debug == true)
- std::clog << "(parsed from dpkg) pkg: " << short_pkgname
- << " action: " << action << endl;
}
}
/*}}}*/
@@ -1048,60 +1051,127 @@ void pkgDPkgPM::StartPtyMagic()
{
if (_config->FindB("Dpkg::Use-Pty", true) == false)
{
- d->master = d->slave = -1;
+ d->master = -1;
+ if (d->slave != NULL)
+ free(d->slave);
+ d->slave = NULL;
return;
}
- // setup the pty and stuff
- struct winsize win;
-
+ _error->PushToStack();
// if tcgetattr for both stdin/stdout returns 0 (no error)
// we do the pty magic
- _error->PushToStack();
- if (tcgetattr(STDIN_FILENO, &d->tt) == 0 &&
- tcgetattr(STDOUT_FILENO, &d->tt) == 0)
+ if (tcgetattr(STDOUT_FILENO, &d->tt) == 0 &&
+ tcgetattr(STDIN_FILENO, &d->tt) == 0)
{
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) < 0)
- {
- _error->Errno("ioctl", _("ioctl(TIOCGWINSZ) failed"));
- } else if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0)
- {
- _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
- d->master = d->slave = -1;
- } else {
- struct termios rtt;
- rtt = d->tt;
- cfmakeraw(&rtt);
- rtt.c_lflag &= ~ECHO;
- rtt.c_lflag |= ISIG;
+ d->master = posix_openpt(O_RDWR | O_NOCTTY);
+ if (d->master == -1)
+ _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+ else if (unlockpt(d->master) == -1)
+ {
+ _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master);
+ close(d->master);
+ d->master = -1;
+ }
+ else
+ {
+ char const * const slave_name = ptsname(d->master);
+ if (slave_name == NULL)
+ {
+ _error->Errno("unlockpt", "Getting name for slave of master fd %d failed!", d->master);
+ close(d->master);
+ d->master = -1;
+ }
+ else
+ {
+ d->slave = strdup(slave_name);
+ if (d->slave == NULL)
+ {
+ _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master);
+ close(d->master);
+ d->master = -1;
+ }
+ struct winsize win;
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0)
+ _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!");
+ if (ioctl(d->master, TIOCSWINSZ, &win) < 0)
+ _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master);
+ if (tcsetattr(d->master, TCSANOW, &d->tt) == -1)
+ _error->Errno("tcsetattr", "Setting in Start via TCSANOW for master fd %d failed!", d->master);
+
+ struct termios raw_tt;
+ raw_tt = d->tt;
+ cfmakeraw(&raw_tt);
+ raw_tt.c_lflag &= ~ECHO;
+ raw_tt.c_lflag |= ISIG;
// block SIGTTOU during tcsetattr to prevent a hang if
// the process is a member of the background process group
// http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
sigemptyset(&d->sigmask);
sigaddset(&d->sigmask, SIGTTOU);
sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask);
- tcsetattr(0, TCSAFLUSH, &rtt);
- sigprocmask(SIG_SETMASK, &d->original_sigmask, 0);
- }
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_tt) == -1)
+ _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdout failed!");
+ sigprocmask(SIG_SETMASK, &d->original_sigmask, NULL);
+ }
}
- // complain only if stdout is either a terminal (but still failed) or is an invalid
+ }
+ else
+ {
+ // complain only if stdout is either a terminal (but still failed) or is an invalid
// descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
- else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
- _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+ if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
+ _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+ }
- if (_error->PendingError() == true)
- _error->DumpErrors(std::cerr);
- _error->RevertToStack();
+ if (_error->PendingError() == true)
+ {
+ if (d->master != -1)
+ {
+ close(d->master);
+ d->master = -1;
+ }
+ _error->DumpErrors(std::cerr);
+ }
+ _error->RevertToStack();
}
+void pkgDPkgPM::SetupSlavePtyMagic()
+{
+ if(d->master == -1)
+ return;
+
+ if (close(d->master) == -1)
+ _error->FatalE("close", "Closing master %d in child failed!", d->master);
+ if (setsid() == -1)
+ _error->FatalE("setsid", "Starting a new session for child failed!");
+
+ int const slaveFd = open(d->slave, O_RDWR);
+ if (slaveFd == -1)
+ _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+
+ if (ioctl(slaveFd, TIOCSCTTY, 0) < 0)
+ _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd);
+ else
+ {
+ for (unsigned short i = 0; i < 3; ++i)
+ if (dup2(slaveFd, i) == -1)
+ _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i);
+ if (tcsetattr(0, TCSANOW, &d->tt) < 0)
+ _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd);
+ }
+}
void pkgDPkgPM::StopPtyMagic()
{
- if(d->slave > 0)
- close(d->slave);
+ if (d->slave != NULL)
+ free(d->slave);
+ d->slave = NULL;
if(d->master >= 0)
{
- tcsetattr(0, TCSAFLUSH, &d->tt);
+ if (tcsetattr(0, TCSAFLUSH, &d->tt) == -1)
+ _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!");
close(d->master);
+ d->master = -1;
}
}
@@ -1413,22 +1483,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress)
pid_t Child = ExecFork(KeepFDs);
if (Child == 0)
{
- // This is the child
- if(d->slave >= 0 && d->master >= 0)
- {
- setsid();
- int res = ioctl(d->slave, TIOCSCTTY, 0);
- if (res < 0) {
- std::cerr << "ioctl(TIOCSCTTY) failed for fd: "
- << d->slave << std::endl;
- } else {
- close(d->master);
- dup2(d->slave, 0);
- dup2(d->slave, 1);
- dup2(d->slave, 2);
- close(d->slave);
- }
- }
+ // This is the child
+ SetupSlavePtyMagic();
close(fd[0]); // close the read end of the pipe
dpkgChrootDirectory();
@@ -1668,9 +1724,10 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
// do not report dpkg I/O errors, this is a format string, so we compare
// the prefix and the suffix of the error with the dpkg error message
vector<string> io_errors;
- io_errors.push_back(string("failed to read on buffer copy for %s"));
- io_errors.push_back(string("failed in write on buffer copy for %s"));
- io_errors.push_back(string("short read on buffer copy for %s"));
+ io_errors.push_back(string("failed to read"));
+ io_errors.push_back(string("failed to write"));
+ io_errors.push_back(string("failed to seek"));
+ io_errors.push_back(string("unexpected end of file or stream"));
for (vector<string>::iterator I = io_errors.begin(); I != io_errors.end(); ++I)
{
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index 859c74b46..2c1805015 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -110,6 +110,7 @@ class pkgDPkgPM : public pkgPackageManager
// helper
void BuildPackagesProgressMap();
void StartPtyMagic();
+ void SetupSlavePtyMagic();
void StopPtyMagic();
// input processing
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index c25672d1c..42e31396b 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -663,10 +663,11 @@ void pkgDepCache::Update(OpProgress *Prog)
{
iUsrSize = 0;
iDownloadSize = 0;
- iDelCount = 0;
iInstCount = 0;
+ iDelCount = 0;
iKeepCount = 0;
iBrokenCount = 0;
+ iPolicyBrokenCount = 0;
iBadCount = 0;
// Perform the depends pass
diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc
index 6d1b68c23..0d0418e06 100644
--- a/apt-pkg/edsp.cc
+++ b/apt-pkg/edsp.cc
@@ -26,6 +26,7 @@
#include <time.h>
#include <unistd.h>
#include <stdio.h>
+#include <algorithm>
#include <iostream>
#include <vector>
#include <limits>
@@ -50,7 +51,12 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
if (Progress != NULL)
Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
unsigned long p = 0;
+ std::vector<std::string> archs = APT::Configuration::getArchitectures();
for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
+ {
+ std::string const arch = Pkg.Arch();
+ if (std::find(archs.begin(), archs.end(), arch) == archs.end())
+ continue;
for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p)
{
WriteScenarioVersion(Cache, output, Pkg, Ver);
@@ -59,6 +65,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
if (Progress != NULL && p % 100 == 0)
Progress->Progress(p);
}
+ }
return true;
}
/*}}}*/
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index 393f836f7..249542c68 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -372,6 +372,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
std::list<DepIterator> needConfigure;
do
{
+ // Check each dependency and see if anything needs to be done
+ // so that it can be configured
Changed = false;
for (DepIterator D = instVer.DependsList(); D.end() == false; )
{
@@ -383,7 +385,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
continue;
Bad = true;
- // Check for dependencies that have not been unpacked, probably due to loops.
+ // the first pass checks if we its all good, i.e. if we have
+ // to do anything at all
for (DepIterator Cur = Start; true; ++Cur)
{
SPtrArray<Version *> VList = Cur.AllTargets();
@@ -412,6 +415,47 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
Bad = false;
}
+ }
+
+ if (Cur == End || Bad == false)
+ break;
+ }
+
+ // this dependency is in a good state, so we can stop
+ if (Bad == false)
+ {
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Found ok dep " << D.TargetPkg() << std::endl;
+ continue;
+ }
+
+ // Check for dependencies that have not been unpacked,
+ // probably due to loops.
+ for (DepIterator Cur = Start; true; ++Cur)
+ {
+ SPtrArray<Version *> VList = Cur.AllTargets();
+
+ for (Version **I = VList; *I != 0; ++I)
+ {
+ VerIterator Ver(Cache,*I);
+ PkgIterator DepPkg = Ver.ParentPkg();
+
+ // Check if the current version of the package is available and will satisfy this dependency
+ if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true &&
+ List->IsFlag(DepPkg,pkgOrderList::Removed) == false &&
+ DepPkg.State() == PkgIterator::NeedsNothing)
+ continue;
+
+ // Check if the version that is going to be installed will satisfy the dependency
+ if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
+ continue;
+
+ if (PkgLoop == true)
+ {
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
+ Bad = false;
+ }
else
{
if (Debug)
@@ -419,6 +463,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
return false;
}
+ // at this point we either unpacked a Dep or we are in a loop,
+ // no need to unpack a second one
break;
}
@@ -435,6 +481,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str());
} while (Changed == true);
+ // now go over anything that needs configuring
Bad = false, Changed = false, i = 0;
do
{
diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc
index 7926845c2..29b11937b 100644
--- a/apt-pkg/upgrade.cc
+++ b/apt-pkg/upgrade.cc
@@ -143,6 +143,12 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache)
*/
static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache)
{
+ std::string const solver = _config->Find("APT::Solver", "internal");
+ if (solver != "internal") {
+ OpTextProgress Prog(*_config);
+ return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
+ }
+
pkgDepCache::ActionGroup group(Cache);
pkgProblemResolver Fix(&Cache);