that are due to be installed. */
bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
{
+ bool result = true;
+
Configuration::Item const *Opts = _config->Tree(Cnf);
if (Opts == 0 || Opts->Child == 0)
return true;
Opts = Opts->Child;
+
+ sighandler_t old_sigpipe = signal(SIGPIPE, SIG_IGN);
unsigned int Count = 1;
for (; Opts != 0; Opts = Opts->Next, Count++)
if (Opts->Value.empty() == true)
continue;
+ if(_config->FindB("Debug::RunScripts", false) == true)
+ std::clog << "Running external script with list of all .deb file: '"
+ << Opts->Value << "'" << std::endl;
+
// Determine the protocol version
string OptSec = Opts->Value;
string::size_type Pos;
std::set<int> KeepFDs;
MergeKeepFdsFromConfiguration(KeepFDs);
int Pipes[2];
- if (pipe(Pipes) != 0)
- return _error->Errno("pipe","Failed to create IPC pipe to subprocess");
+ if (pipe(Pipes) != 0) {
+ result = _error->Errno("pipe","Failed to create IPC pipe to subprocess");
+ break;
+ }
if (InfoFD != (unsigned)Pipes[0])
SetCloseExec(Pipes[0],true);
else
}
close(Pipes[0]);
FILE *F = fdopen(Pipes[1],"w");
- if (F == 0)
- return _error->Errno("fdopen","Faild to open new FD");
+ if (F == 0) {
+ result = _error->Errno("fdopen","Faild to open new FD");
+ break;
+ }
// Feed it the filenames.
if (Version <= 1)
fclose(F);
// Clean up the sub process
- if (ExecWait(Process,Opts->Value.c_str()) == false)
- return _error->Error("Failure running script %s",Opts->Value.c_str());
+ if (ExecWait(Process,Opts->Value.c_str()) == false) {
+ result = _error->Error("Failure running script %s",Opts->Value.c_str());
+ break;
+ }
}
+ signal(SIGPIPE, old_sigpipe);
- return true;
+ return result;
}
/*}}}*/
// DPkgPM::DoStdin - Read stdin and pass to slave pty /*{{{*/
'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
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",
{
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;
}
// 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 = "";
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;
}
}
/*}}}*/
}
// setup the pty and stuff
- struct winsize win;
+ struct winsize win;
- // if tcgetattr does not return zero there was a error
- // and we do not do any pty magic
+ // if tcgetattr for both stdin/stdout returns 0 (no error)
+ // we do the pty magic
_error->PushToStack();
- if (tcgetattr(STDOUT_FILENO, &d->tt) == 0)
+ if (tcgetattr(STDIN_FILENO, &d->tt) == 0 &&
+ tcgetattr(STDOUT_FILENO, &d->tt) == 0)
{
- if (ioctl(1, TIOCGWINSZ, (char *)&win) < 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)
if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO))
{
- int Flags,dummy;
+ int Flags;
+ int dummy = 0;
if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
_exit(100);
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;
// 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)
{