summaryrefslogtreecommitdiff
path: root/apt-pkg/deb/dpkgpm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/deb/dpkgpm.cc')
-rw-r--r--apt-pkg/deb/dpkgpm.cc170
1 files changed, 117 insertions, 53 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 5fbd1801a..751e1fbe9 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -26,7 +26,6 @@
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
-#include <string.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
@@ -46,6 +45,21 @@
using namespace std;
+class pkgDPkgPMPrivate
+{
+public:
+ pkgDPkgPMPrivate() : dpkgbuf_pos(0), term_out(NULL), history_out(NULL)
+ {
+ }
+ bool stdin_is_dev_null;
+ // the buffer we use for the dpkg status-fd reading
+ char dpkgbuf[1024];
+ int dpkgbuf_pos;
+ FILE *term_out;
+ FILE *history_out;
+ string dpkg_error;
+};
+
namespace
{
// Maps the dpkg "processing" info to human readable names. Entry 0
@@ -110,9 +124,9 @@ ionice(int PID)
// ---------------------------------------------------------------------
/* */
pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache)
- : pkgPackageManager(Cache), dpkgbuf_pos(0),
- term_out(NULL), history_out(NULL), PackagesDone(0), PackagesTotal(0)
+ : pkgPackageManager(Cache), PackagesDone(0), PackagesTotal(0)
{
+ d = new pkgDPkgPMPrivate();
}
/*}}}*/
// DPkgPM::pkgDPkgPM - Destructor /*{{{*/
@@ -120,6 +134,7 @@ pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache)
/* */
pkgDPkgPM::~pkgDPkgPM()
{
+ delete d;
}
/*}}}*/
// DPkgPM::Install - Install a package /*{{{*/
@@ -376,7 +391,7 @@ void pkgDPkgPM::DoStdin(int master)
if (len)
write(master, input_buf, len);
else
- stdin_is_dev_null = true;
+ d->stdin_is_dev_null = true;
}
/*}}}*/
// DPkgPM::DoTerminalPty - Read the terminal pty and write log /*{{{*/
@@ -401,8 +416,8 @@ void pkgDPkgPM::DoTerminalPty(int master)
if(len <= 0)
return;
write(1, term_buf, len);
- if(term_out)
- fwrite(term_buf, len, sizeof(char), term_out);
+ if(d->term_out)
+ fwrite(term_buf, len, sizeof(char), d->term_out);
}
/*}}}*/
// DPkgPM::ProcessDpkgStatusBuf /*{{{*/
@@ -606,14 +621,14 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
char *p, *q;
int len;
- len=read(statusfd, &dpkgbuf[dpkgbuf_pos], sizeof(dpkgbuf)-dpkgbuf_pos);
- dpkgbuf_pos += len;
+ len=read(statusfd, &d->dpkgbuf[d->dpkgbuf_pos], sizeof(d->dpkgbuf)-d->dpkgbuf_pos);
+ d->dpkgbuf_pos += len;
if(len <= 0)
return;
// process line by line if we have a buffer
- p = q = dpkgbuf;
- while((q=(char*)memchr(p, '\n', dpkgbuf+dpkgbuf_pos-p)) != NULL)
+ p = q = d->dpkgbuf;
+ while((q=(char*)memchr(p, '\n', d->dpkgbuf+d->dpkgbuf_pos-p)) != NULL)
{
*q = 0;
ProcessDpkgStatusLine(OutStatusFd, p);
@@ -621,8 +636,8 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
}
// now move the unprocessed bits (after the final \n that is now a 0x0)
- // to the start and update dpkgbuf_pos
- p = (char*)memrchr(dpkgbuf, 0, dpkgbuf_pos);
+ // to the start and update d->dpkgbuf_pos
+ p = (char*)memrchr(d->dpkgbuf, 0, d->dpkgbuf_pos);
if(p == NULL)
return;
@@ -630,8 +645,8 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
p++;
// move the unprocessed tail to the start and update pos
- memmove(dpkgbuf, p, p-dpkgbuf);
- dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
+ memmove(d->dpkgbuf, p, p-d->dpkgbuf);
+ d->dpkgbuf_pos = d->dpkgbuf+d->dpkgbuf_pos-p;
}
/*}}}*/
// DPkgPM::WriteHistoryTag /*{{{*/
@@ -643,7 +658,7 @@ void pkgDPkgPM::WriteHistoryTag(string const &tag, string value)
// poor mans rstrip(", ")
if (value[length-2] == ',' && value[length-1] == ' ')
value.erase(length - 2, 2);
- fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
+ fprintf(d->history_out, "%s: %s\n", tag.c_str(), value.c_str());
} /*}}}*/
// DPkgPM::OpenLog /*{{{*/
bool pkgDPkgPM::OpenLog()
@@ -664,11 +679,11 @@ bool pkgDPkgPM::OpenLog()
_config->Find("Dir::Log::Terminal"));
if (!logfile_name.empty())
{
- term_out = fopen(logfile_name.c_str(),"a");
- if (term_out == NULL)
+ d->term_out = fopen(logfile_name.c_str(),"a");
+ if (d->term_out == NULL)
return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str());
- setvbuf(term_out, NULL, _IONBF, 0);
- SetCloseExec(fileno(term_out), true);
+ setvbuf(d->term_out, NULL, _IONBF, 0);
+ SetCloseExec(fileno(d->term_out), true);
struct passwd *pw;
struct group *gr;
pw = getpwnam("root");
@@ -676,7 +691,7 @@ bool pkgDPkgPM::OpenLog()
if (pw != NULL && gr != NULL)
chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid);
chmod(logfile_name.c_str(), 0644);
- fprintf(term_out, "\nLog started: %s\n", timestr);
+ fprintf(d->term_out, "\nLog started: %s\n", timestr);
}
// write your history
@@ -684,11 +699,11 @@ bool pkgDPkgPM::OpenLog()
_config->Find("Dir::Log::History"));
if (!history_name.empty())
{
- history_out = fopen(history_name.c_str(),"a");
- if (history_out == NULL)
+ d->history_out = fopen(history_name.c_str(),"a");
+ if (d->history_out == NULL)
return _error->WarningE("OpenLog", _("Could not open file '%s'"), history_name.c_str());
chmod(history_name.c_str(), 0644);
- fprintf(history_out, "\nStart-Date: %s\n", timestr);
+ fprintf(d->history_out, "\nStart-Date: %s\n", timestr);
string remove, purge, install, reinstall, upgrade, downgrade;
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
@@ -729,7 +744,7 @@ bool pkgDPkgPM::OpenLog()
WriteHistoryTag("Downgrade",downgrade);
WriteHistoryTag("Remove",remove);
WriteHistoryTag("Purge",purge);
- fflush(history_out);
+ fflush(d->history_out);
}
return true;
@@ -743,16 +758,16 @@ bool pkgDPkgPM::CloseLog()
struct tm *tmp = localtime(&t);
strftime(timestr, sizeof(timestr), "%F %T", tmp);
- if(term_out)
+ if(d->term_out)
{
- fprintf(term_out, "Log ended: ");
- fprintf(term_out, "%s", timestr);
- fprintf(term_out, "\n");
- fclose(term_out);
+ fprintf(d->term_out, "Log ended: ");
+ fprintf(d->term_out, "%s", timestr);
+ fprintf(d->term_out, "\n");
+ fclose(d->term_out);
}
- term_out = NULL;
+ d->term_out = NULL;
- if(history_out)
+ if(d->history_out)
{
if (disappearedPkgs.empty() == false)
{
@@ -769,12 +784,12 @@ bool pkgDPkgPM::CloseLog()
}
WriteHistoryTag("Disappeared", disappear);
}
- if (dpkg_error.empty() == false)
- fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
- fprintf(history_out, "End-Date: %s\n", timestr);
- fclose(history_out);
+ if (d->dpkg_error.empty() == false)
+ fprintf(d->history_out, "Error: %s\n", d->dpkg_error.c_str());
+ fprintf(d->history_out, "End-Date: %s\n", timestr);
+ fclose(d->history_out);
}
- history_out = NULL;
+ d->history_out = NULL;
return true;
}
@@ -882,7 +897,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
}
}
- stdin_is_dev_null = false;
+ d->stdin_is_dev_null = false;
// create log
OpenLog();
@@ -1082,8 +1097,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
const char *s = _("Can not write log, openpty() "
"failed (/dev/pts not mounted?)\n");
fprintf(stderr, "%s",s);
- if(term_out)
- fprintf(term_out, "%s",s);
+ if(d->term_out)
+ fprintf(d->term_out, "%s",s);
master = slave = -1;
} else {
struct termios rtt;
@@ -1213,7 +1228,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
// wait for input or output here
FD_ZERO(&rfds);
- if (master >= 0 && !stdin_is_dev_null)
+ if (master >= 0 && !d->stdin_is_dev_null)
FD_SET(0, &rfds);
FD_SET(_dpkgin, &rfds);
if(master >= 0)
@@ -1267,14 +1282,14 @@ bool pkgDPkgPM::Go(int OutStatusFd)
RunScripts("DPkg::Post-Invoke");
if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
- strprintf(dpkg_error, "Sub-process %s received a segmentation fault.",Args[0]);
+ strprintf(d->dpkg_error, "Sub-process %s received a segmentation fault.",Args[0]);
else if (WIFEXITED(Status) != 0)
- strprintf(dpkg_error, "Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
+ strprintf(d->dpkg_error, "Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
else
- strprintf(dpkg_error, "Sub-process %s exited unexpectedly",Args[0]);
+ strprintf(d->dpkg_error, "Sub-process %s exited unexpectedly",Args[0]);
- if(dpkg_error.size() > 0)
- _error->Error("%s", dpkg_error.c_str());
+ if(d->dpkg_error.size() > 0)
+ _error->Error("%s", d->dpkg_error.c_str());
if(stopOnError)
{
@@ -1326,7 +1341,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
string::size_type pos;
FILE *report;
- if (_config->FindB("Dpkg::ApportFailureReport", false) == false)
+ if (_config->FindB("Dpkg::ApportFailureReport", true) == false)
{
std::clog << "configured to not write apport reports" << std::endl;
return;
@@ -1353,18 +1368,49 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
}
// do not report out-of-memory failures
- if(strstr(errormsg, strerror(ENOMEM)) != NULL) {
+ if(strstr(errormsg, strerror(ENOMEM)) != NULL ||
+ strstr(errormsg, "failed to allocate memory") != NULL) {
std::clog << _("No apport report written because the error message indicates a out of memory error") << std::endl;
return;
}
- // do not report dpkg I/O errors
- // XXX - this message is localized, but this only matches the English version. This is better than nothing.
- if(strstr(errormsg, "short read in buffer_copy (")) {
- std::clog << _("No apport report written because the error message indicates a dpkg I/O error") << std::endl;
+ // do not report bugs regarding inaccessible local files
+ if(strstr(errormsg, strerror(ENOENT)) != NULL ||
+ strstr(errormsg, "cannot access archive") != NULL) {
+ std::clog << _("No apport report written because the error message indicates an issue on the local system") << std::endl;
return;
}
+ // do not report errors encountered when decompressing packages
+ if(strstr(errormsg, "--fsys-tarfile returned error exit status 2") != NULL) {
+ std::clog << _("No apport report written because the error message indicates an issue on the local system") << std::endl;
+ return;
+ }
+
+ // 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"));
+
+ for (vector<string>::iterator I = io_errors.begin(); I != io_errors.end(); I++)
+ {
+ vector<string> list = VectorizeString(dgettext("dpkg", (*I).c_str()), '%');
+ if (list.size() > 1) {
+ // we need to split %s, VectorizeString only allows char so we need
+ // to kill the "s" manually
+ if (list[1].size() > 1) {
+ list[1].erase(0, 1);
+ if(strstr(errormsg, list[0].c_str()) &&
+ strstr(errormsg, list[1].c_str())) {
+ std::clog << _("No apport report written because the error message indicates a dpkg I/O error") << std::endl;
+ return;
+ }
+ }
+ }
+ }
+
// get the pkgname and reportfile
pkgname = flNotDir(pkgpath);
pos = pkgname.find('_');
@@ -1438,8 +1484,8 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
fprintf(report, "ErrorMessage:\n %s\n", errormsg);
// ensure that the log is flushed
- if(term_out)
- fflush(term_out);
+ if(d->term_out)
+ fflush(d->term_out);
// attach terminal log it if we have it
string logfile_name = _config->FindFile("Dir::Log::Terminal");
@@ -1454,6 +1500,24 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
{
while( fgets(buf, sizeof(buf), log) != NULL)
fprintf(report, " %s", buf);
+ fprintf(report, " \n");
+ fclose(log);
+ }
+ }
+
+ // attach history log it if we have it
+ string histfile_name = _config->FindFile("Dir::Log::History");
+ if (!histfile_name.empty())
+ {
+ FILE *log = NULL;
+ char buf[1024];
+
+ fprintf(report, "DpkgHistoryLog:\n");
+ log = fopen(histfile_name.c_str(),"r");
+ if(log != NULL)
+ {
+ while( fgets(buf, sizeof(buf), log) != NULL)
+ fprintf(report, " %s", buf);
fclose(log);
}
}