|
|
@@ -37,6 +37,7 @@
|
|
|
#include <map>
|
|
|
#include <pwd.h>
|
|
|
#include <grp.h>
|
|
|
+#include <iomanip>
|
|
|
|
|
|
#include <termios.h>
|
|
|
#include <unistd.h>
|
|
|
@@ -52,7 +53,8 @@ class pkgDPkgPMPrivate
|
|
|
{
|
|
|
public:
|
|
|
pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
|
|
|
- term_out(NULL), history_out(NULL)
|
|
|
+ term_out(NULL), history_out(NULL),
|
|
|
+ last_reported_progress(0.0)
|
|
|
{
|
|
|
dpkgbuf[0] = '\0';
|
|
|
}
|
|
|
@@ -63,6 +65,8 @@ public:
|
|
|
FILE *term_out;
|
|
|
FILE *history_out;
|
|
|
string dpkg_error;
|
|
|
+
|
|
|
+ float last_reported_progress;
|
|
|
};
|
|
|
|
|
|
namespace
|
|
|
@@ -512,7 +516,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
|
|
|
|
|
|
|
|
|
/* dpkg sends strings like this:
|
|
|
- 'status: <pkg>: <pkg qstate>'
|
|
|
+ 'status: <pkg>: <pkg qstate>'
|
|
|
+ 'status: <pkg>:<arch>: <pkg qstate>'
|
|
|
errors look like this:
|
|
|
'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data
|
|
|
and conffile-prompt like this
|
|
|
@@ -527,29 +532,36 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
|
|
|
'processing: trigproc: trigger'
|
|
|
|
|
|
*/
|
|
|
- char* list[6];
|
|
|
- // dpkg sends multiline error messages sometimes (see
|
|
|
- // #374195 for a example. we should support this by
|
|
|
- // either patching dpkg to not send multiline over the
|
|
|
- // statusfd or by rewriting the code here to deal with
|
|
|
- // it. for now we just ignore it and not crash
|
|
|
- TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
|
|
|
- if( list[0] == NULL || list[1] == NULL || list[2] == NULL)
|
|
|
+ // we need to split on ": " (note the appended space) as the ':' is
|
|
|
+ // part of the pkgname:arch information that dpkg sends
|
|
|
+ //
|
|
|
+ // A dpkg error message may contain additional ":" (like
|
|
|
+ // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..."
|
|
|
+ // so we need to ensure to not split too much
|
|
|
+ std::vector<std::string> list = StringSplit(line, ": ", 3);
|
|
|
+ if(list.size() != 3)
|
|
|
{
|
|
|
if (Debug == true)
|
|
|
std::clog << "ignoring line: not enough ':'" << std::endl;
|
|
|
return;
|
|
|
}
|
|
|
- const char* const pkg = list[1];
|
|
|
- const char* action = _strstrip(list[2]);
|
|
|
+ // dpkg does not send always send "pkgname:arch" so we add it here if needed
|
|
|
+ std::string pkgname = list[1];
|
|
|
+ if (pkgname.find(":") == std::string::npos)
|
|
|
+ {
|
|
|
+ string const nativeArch = _config->Find("APT::Architecture");
|
|
|
+ pkgname = pkgname + ":" + nativeArch;
|
|
|
+ }
|
|
|
+ const char* const pkg = pkgname.c_str();
|
|
|
+ const char* action = list[2].c_str();
|
|
|
|
|
|
// 'processing' from dpkg looks like
|
|
|
// 'processing: action: pkg'
|
|
|
- if(strncmp(list[0], "processing", strlen("processing")) == 0)
|
|
|
+ if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0)
|
|
|
{
|
|
|
char s[200];
|
|
|
- const char* const pkg_or_trigger = _strstrip(list[2]);
|
|
|
- action = _strstrip( list[1]);
|
|
|
+ const char* const pkg_or_trigger = list[2].c_str();
|
|
|
+ action = list[1].c_str();
|
|
|
const std::pair<const char *, const char *> * const iter =
|
|
|
std::find_if(PackageProcessingOpsBegin,
|
|
|
PackageProcessingOpsEnd,
|
|
|
@@ -578,14 +590,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
|
|
|
|
|
|
if(strncmp(action,"error",strlen("error")) == 0)
|
|
|
{
|
|
|
- // urgs, sometime has ":" in its error string so that we
|
|
|
- // end up with the error message split between list[3]
|
|
|
- // and list[4], e.g. the message:
|
|
|
- // "failed in buffer_write(fd) (10, ret=-1): backend dpkg-deb ..."
|
|
|
- // concat them again
|
|
|
- if( list[4] != NULL )
|
|
|
- list[3][strlen(list[3])] = ':';
|
|
|
-
|
|
|
status << "pmerror:" << list[1]
|
|
|
<< ":" << (PackagesDone/float(PackagesTotal)*100.0)
|
|
|
<< ":" << list[3]
|
|
|
@@ -595,7 +599,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
|
|
|
if (Debug == true)
|
|
|
std::clog << "send: '" << status.str() << "'" << endl;
|
|
|
pkgFailures++;
|
|
|
- WriteApportReport(list[1], list[3]);
|
|
|
+ WriteApportReport(list[1].c_str(), list[3].c_str());
|
|
|
return;
|
|
|
}
|
|
|
else if(strncmp(action,"conffile",strlen("conffile")) == 0)
|
|
|
@@ -883,10 +887,16 @@ bool pkgDPkgPM::CloseLog()
|
|
|
*/
|
|
|
void pkgDPkgPM::SendTerminalProgress(float percentage)
|
|
|
{
|
|
|
+ int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1);
|
|
|
+
|
|
|
+ if(percentage < (d->last_reported_progress + reporting_steps))
|
|
|
+ return;
|
|
|
+
|
|
|
// FIXME: use colors too
|
|
|
std::cout << "\r\n"
|
|
|
- << "Progress: [" << percentage << "%]"
|
|
|
+ << "Progress: [" << std::setw(3) << int(percentage) << "%]"
|
|
|
<< "\r\n";
|
|
|
+ d->last_reported_progress = percentage;
|
|
|
}
|
|
|
/*}}}*/
|
|
|
/*{{{*/
|
|
|
@@ -1035,7 +1045,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
if((*I).Pkg.end() == true)
|
|
|
continue;
|
|
|
|
|
|
- string const name = (*I).Pkg.Name();
|
|
|
+ string const name = (*I).Pkg.FullName();
|
|
|
PackageOpsDone[name] = 0;
|
|
|
for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; ++i)
|
|
|
{
|
|
|
@@ -1444,7 +1454,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
tcsetattr(0, TCSAFLUSH, &tt);
|
|
|
close(master);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Check for an error code.
|
|
|
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
|
|
|
{
|
|
|
@@ -1474,6 +1484,10 @@ bool pkgDPkgPM::Go(int OutStatusFd)
|
|
|
}
|
|
|
}
|
|
|
CloseLog();
|
|
|
+
|
|
|
+ // dpkg is done at this point
|
|
|
+ if(_config->FindB("DPkgPM::Progress", false) == true)
|
|
|
+ SendTerminalProgress(100);
|
|
|
|
|
|
if (pkgPackageManager::SigINTStop)
|
|
|
_error->Warning(_("Operation was interrupted before it could finish"));
|