diff options
Diffstat (limited to 'apt-pkg/deb')
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 208 |
1 files changed, 86 insertions, 122 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index f8855526c..b0237aa9a 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1,10 +1,9 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: dpkgpm.cc,v 1.28 2004/01/27 02:25:01 mdz Exp $ /* ###################################################################### DPKG Package Manager - Provide an interface to dpkg - + ##################################################################### */ /*}}}*/ // Includes /*{{{*/ @@ -56,8 +55,7 @@ using namespace std; -APT_PURE static string -AptHistoryRequestingUser() +APT_PURE static string AptHistoryRequestingUser() /*{{{*/ { const char* EnvKeys[]{"SUDO_UID", "PKEXEC_UID", "PACKAGEKIT_CALLER_UID"}; @@ -80,9 +78,8 @@ AptHistoryRequestingUser() } return ""; } - -APT_PURE static unsigned int -EnvironmentSize() + /*}}}*/ +APT_PURE static unsigned int EnvironmentSize() /*{{{*/ { unsigned int size = 0; char **envp = environ; @@ -92,8 +89,8 @@ EnvironmentSize() return size; } - -class pkgDPkgPMPrivate + /*}}}*/ +class pkgDPkgPMPrivate /*{{{*/ { public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), @@ -129,7 +126,7 @@ public: bool direct_stdin; }; - + /*}}}*/ namespace { // Maps the dpkg "processing" info to human readable names. Entry 0 @@ -165,13 +162,10 @@ namespace }; } -/* helper function to ionice the given PID - - there is no C header for ionice yet - just the syscall interface - so we use the binary from util-linux -*/ -static bool -ionice(int PID) +// ionice - helper function to ionice the given PID /*{{{*/ +/* there is no C header for ionice yet - just the syscall interface + so we use the binary from util-linux */ +static bool ionice(int PID) { if (!FileExists("/usr/bin/ionice")) return false; @@ -189,13 +183,13 @@ ionice(int PID) } return ExecWait(Process, "ionice"); } - + /*}}}*/ // FindNowVersion - Helper to find a Version in "now" state /*{{{*/ // --------------------------------------------------------------------- -/* This is helpful when a package is no longer installed but has residual +/* This is helpful when a package is no longer installed but has residual * config files */ -static +static pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) { pkgCache::VerIterator Ver; @@ -275,7 +269,7 @@ bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge) { if (Pkg.end() == true) return false; - + if (Purge == true) List.push_back(Item(Item::Purge,Pkg)); else @@ -316,14 +310,14 @@ bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version) Top = Top->Child; continue; } - + while (Top != 0 && Top->Next == 0) Top = Top->Parent; if (Top != 0) Top = Top->Next; - } + } fprintf(F,"\n"); - + // Write out the package actions in order. for (vector<Item>::iterator I = List.begin(); I != List.end(); ++I) { @@ -331,7 +325,7 @@ bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version) continue; pkgDepCache::StateCache &S = Cache[I->Pkg]; - + fprintf(F,"%s ",I->Pkg.Name()); // Current version which we are going to replace @@ -386,13 +380,13 @@ bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version) fprintf(F,"**ERROR**\n"); else fprintf(F,"%s\n",I->File.c_str()); - } + } else if (I->Op == Item::Configure) fprintf(F,"**CONFIGURE**\n"); else if (I->Op == Item::Remove || I->Op == Item::Purge) fprintf(F,"**REMOVE**\n"); - + if (ferror(F) != 0) return false; } @@ -414,7 +408,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) Opts = Opts->Child; sighandler_t old_sigpipe = signal(SIGPIPE, SIG_IGN); - + unsigned int Count = 1; for (; Opts != 0; Opts = Opts->Next, Count++) { @@ -431,10 +425,10 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) if ((Pos = OptSec.find(' ')) == string::npos || Pos == 0) Pos = OptSec.length(); OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos); - + unsigned int Version = _config->FindI(OptSec+"::Version",1); unsigned int InfoFD = _config->FindI(OptSec + "::InfoFD", STDIN_FILENO); - + // Create the pipes std::set<int> KeepFDs; MergeKeepFdsFromConfiguration(KeepFDs); @@ -480,7 +474,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) result = _error->Errno("fdopen","Failed to open new FD"); break; } - + // Feed it the filenames. if (Version <= 1) { @@ -493,7 +487,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) // No errors here.. if (I->File[0] != '/') continue; - + /* Feed the filename of each package that is pending install into the pipe. */ fprintf(F,"%s\n",I->File.c_str()); @@ -505,7 +499,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) SendPkgsInfo(F, Version); fclose(F); - + // Clean up the sub process if (ExecWait(Process,Opts->Value.c_str()) == false) { result = _error->Error("Failure running script %s",Opts->Value.c_str()); @@ -549,18 +543,15 @@ void pkgDPkgPM::DoTerminalPty(int master) struct timespec sleepfor = { 0, 500000000 }; nanosleep(&sleepfor, NULL); return; - } - if(len <= 0) + } + if(len <= 0) return; FileFd::Write(1, term_buf, len); if(d->term_out) fwrite(term_buf, len, sizeof(char), d->term_out); } /*}}}*/ -// DPkgPM::ProcessDpkgStatusBuf /*{{{*/ -// --------------------------------------------------------------------- -/* - */ +// DPkgPM::ProcessDpkgStatusBuf /*{{{*/ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false); @@ -570,14 +561,14 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) /* dpkg sends strings like this: 'status: <pkg>: <pkg qstate>' 'status: <pkg>:<arch>: <pkg qstate>' - + '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 // 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 @@ -696,12 +687,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); // FIXME: this needs a muliarch testcase - // FIXME2: is "pkgname" here reliable with dpkg only sending us + // FIXME2: is "pkgname" here reliable with dpkg only sending us // short pkgnames? if (action == "disappear") handleDisappearAction(pkgname); return; - } + } if (prefix == "status") { @@ -914,7 +905,7 @@ bool pkgDPkgPM::OpenLog() WriteHistoryTag("Purge",purge); fflush(d->history_out); } - + return true; } /*}}}*/ @@ -963,28 +954,6 @@ bool pkgDPkgPM::CloseLog() return true; } /*}}}*/ - /*}}}*/ -/*{{{*/ -// This implements a racy version of pselect for those architectures -// that don't have a working implementation. -// FIXME: Probably can be removed on Lenny+1 -static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, const struct timespec *timeout, - const sigset_t *sigmask) -{ - sigset_t origmask; - struct timeval tv; - int retval; - - tv.tv_sec = timeout->tv_sec; - tv.tv_usec = timeout->tv_nsec/1000; - - sigprocmask(SIG_SETMASK, sigmask, &origmask); - retval = select(nfds, readfds, writefds, exceptfds, &tv); - sigprocmask(SIG_SETMASK, &origmask, 0); - return retval; -} - /*}}}*/ // DPkgPM::BuildPackagesProgressMap /*{{{*/ void pkgDPkgPM::BuildPackagesProgressMap() @@ -993,27 +962,27 @@ void pkgDPkgPM::BuildPackagesProgressMap() // (this is sorted in the same way as Item::Ops) static const struct DpkgState DpkgStatesOpMap[][7] = { // Install operation - { - {"half-installed", N_("Preparing %s")}, - {"unpacked", N_("Unpacking %s") }, + { + {"half-installed", N_("Preparing %s")}, + {"unpacked", N_("Unpacking %s") }, {NULL, NULL} }, // Configure operation - { + { {"unpacked",N_("Preparing to configure %s") }, {"half-configured", N_("Configuring %s") }, { "installed", N_("Installed %s")}, {NULL, NULL} }, // Remove operation - { + { {"half-configured", N_("Preparing for removal of %s")}, {"half-installed", N_("Removing %s")}, {"config-files", N_("Removed %s")}, {NULL, NULL} }, // Purge operation - { + { {"config-files", N_("Preparing to completely remove %s")}, {"not-installed", N_("Completely removed %s")}, {NULL, NULL} @@ -1045,18 +1014,18 @@ void pkgDPkgPM::BuildPackagesProgressMap() ++PackagesTotal; } /*}}}*/ -bool pkgDPkgPM::Go(int StatusFd) +bool pkgDPkgPM::Go(int StatusFd) /*{{{*/ { APT::Progress::PackageManager *progress = NULL; if (StatusFd == -1) progress = APT::Progress::PackageManagerProgressFactory(); else progress = new APT::Progress::PackageManagerProgressFd(StatusFd); - + return Go(progress); } - -void pkgDPkgPM::StartPtyMagic() + /*}}}*/ +void pkgDPkgPM::StartPtyMagic() /*{{{*/ { if (_config->FindB("Dpkg::Use-Pty", true) == false) { @@ -1154,7 +1123,8 @@ void pkgDPkgPM::StartPtyMagic() } _error->RevertToStack(); } -void pkgDPkgPM::SetupSlavePtyMagic() + /*}}}*/ +void pkgDPkgPM::SetupSlavePtyMagic() /*{{{*/ { if(d->master == -1 || d->slave == NULL) return; @@ -1186,7 +1156,8 @@ void pkgDPkgPM::SetupSlavePtyMagic() if (slaveFd != -1) close(slaveFd); } -void pkgDPkgPM::StopPtyMagic() + /*}}}*/ +void pkgDPkgPM::StopPtyMagic() /*{{{*/ { if (d->slave != NULL) free(d->slave); @@ -1196,7 +1167,7 @@ void pkgDPkgPM::StopPtyMagic() close(d->protect_slave_from_dying); d->protect_slave_from_dying = -1; } - if(d->master >= 0) + if(d->master >= 0) { if (d->tt_is_valid == true && tcsetattr(STDIN_FILENO, TCSAFLUSH, &d->tt) == -1) _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!"); @@ -1207,7 +1178,7 @@ void pkgDPkgPM::StopPtyMagic() // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- -/* This globs the operations and calls dpkg +/* This globs the operations and calls dpkg * * If it is called with a progress object apt will report the install * progress to this object. It maps the dpkg states a package goes @@ -1277,7 +1248,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) // start pty magic before the loop StartPtyMagic(); - // Tell the progress that its starting and fork dpkg + // Tell the progress that its starting and fork dpkg d->progress->Start(d->master); // this loop is runs once per dpkg operation @@ -1331,13 +1302,13 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) ADDARGC("--force-remove-essential"); ADDARGC("--remove"); break; - + case Item::Purge: ADDARGC("--force-depends"); ADDARGC("--force-remove-essential"); ADDARGC("--purge"); break; - + case Item::Configure: ADDARGC("--configure"); break; @@ -1424,7 +1395,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) #undef ADDARG J = I; - + if (_config->FindB("Debug::pkgDPkgPM",false) == true) { for (std::vector<const char *>::const_iterator a = Args.begin(); @@ -1443,18 +1414,17 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) clog << flush; cerr << flush; - /* Mask off sig int/quit. We do this because dpkg also does when + /* Mask off sig int/quit. We do this because dpkg also does when it forks scripts. What happens is that when you hit ctrl-c it sends - it to all processes in the group. Since dpkg ignores the signal + it to all processes in the group. Since dpkg ignores the signal it doesn't die but we do! So we must also ignore it */ sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN); sighandler_t old_SIGINT = signal(SIGINT,SigINT); - + // Check here for any SIGINT - if (pkgPackageManager::SigINTStop && (Op == Item::Remove || Op == Item::Purge || Op == Item::Install)) + if (pkgPackageManager::SigINTStop && (Op == Item::Remove || Op == Item::Purge || Op == Item::Install)) break; - - + // ignore SIGHUP as well (debian #463030) sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN); @@ -1481,13 +1451,13 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) int dummy = 0; if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0) _exit(100); - + // Discard everything in stdin before forking dpkg if (fcntl(STDIN_FILENO,F_SETFL,Flags | O_NONBLOCK) < 0) _exit(100); - + while (read(STDIN_FILENO,&dummy,1) == 1); - + if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } @@ -1502,19 +1472,16 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) execvp(Args[0], (char**) &Args[0]); cerr << "Could not exec dpkg!" << endl; _exit(100); - } - - // apply ionice - if (_config->FindB("DPkg::UseIoNice", false) == true) - ionice(Child); - - // Wait for dpkg - int Status = 0; + } // we read from dpkg here int const _dpkgin = fd[0]; close(fd[1]); // close the write end of the pipe + // apply ionice + if (_config->FindB("DPkg::UseIoNice", false) == true) + ionice(Child); + // setups fds sigemptyset(&d->sigmask); sigprocmask(SIG_BLOCK,&d->sigmask,&d->original_sigmask); @@ -1526,8 +1493,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) Packages.clear(); // the result of the waitpid call + int Status = 0; int res; - int select_ret; bool waitpid_failure = false; while ((res=waitpid(Child,&Status, WNOHANG)) != Child) { if(res < 0) { @@ -1547,22 +1514,19 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) FD_SET(d->master, &rfds); tv.tv_sec = 0; tv.tv_nsec = d->progress->GetPulseInterval(); - select_ret = pselect(max(d->master, _dpkgin)+1, &rfds, NULL, NULL, + auto const select_ret = pselect(max(d->master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &d->original_sigmask); - if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) - select_ret = racy_pselect(max(d->master, _dpkgin)+1, &rfds, NULL, - NULL, &tv, &d->original_sigmask); d->progress->Pulse(); - if (select_ret == 0) - continue; - else if (select_ret < 0 && errno == EINTR) - continue; - else if (select_ret < 0) - { - perror("select() returned error"); - continue; - } - + if (select_ret == 0) + continue; + else if (select_ret < 0 && errno == EINTR) + continue; + else if (select_ret < 0) + { + perror("select() returned error"); + continue; + } + if(d->master >= 0 && FD_ISSET(d->master, &rfds)) DoTerminalPty(d->master); if(d->master >= 0 && FD_ISSET(0, &rfds)) @@ -1645,7 +1609,7 @@ void SigINT(int /*sig*/) { // pkgDpkgPM::Reset - Dump the contents of the command list /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgDPkgPM::Reset() +void pkgDPkgPM::Reset() { List.erase(List.begin(),List.end()); } @@ -1653,7 +1617,7 @@ void pkgDPkgPM::Reset() // pkgDpkgPM::WriteApportReport - write out error report pkg failure /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) +void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) { // If apport doesn't exist or isn't installed do nothing // This e.g. prevents messages in 'universes' without apport @@ -1678,20 +1642,20 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) return; } - // check if its not a follow up error + // check if its not a follow up error const char *needle = dgettext("dpkg", "dependency problems - leaving unconfigured"); if(strstr(errormsg, needle) != NULL) { std::clog << _("No apport report written because the error message indicates its a followup error from a previous failure.") << std::endl; return; } - // do not report disk-full failures + // do not report disk-full failures if(strstr(errormsg, strerror(ENOSPC)) != NULL) { std::clog << _("No apport report written because the error message indicates a disk full error") << std::endl; return; } - // do not report out-of-memory failures + // do not report out-of-memory failures 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; @@ -1727,7 +1691,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) // to kill the "s" manually if (list[1].size() > 1) { list[1].erase(0, 1); - if(strstr(errormsg, list[0].c_str()) && + 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; |