diff options
Diffstat (limited to 'apt-pkg/deb/dpkgpm.cc')
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 102 |
1 files changed, 57 insertions, 45 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 790019b98..f83b368cd 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -102,8 +102,8 @@ APT_PURE static unsigned int EnvironmentSize() /*{{{*/ class pkgDPkgPMPrivate /*{{{*/ { public: - pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), - term_out(NULL), history_out(NULL), + pkgDPkgPMPrivate() : stdin_is_dev_null(false), status_fd_reached_end_of_file(false), + dpkgbuf_pos(0), term_out(NULL), history_out(NULL), progress(NULL), tt_is_valid(false), master(-1), slave(NULL), protect_slave_from_dying(-1), direct_stdin(false) @@ -114,6 +114,7 @@ public: { } bool stdin_is_dev_null; + bool status_fd_reached_end_of_file; // the buffer we use for the dpkg status-fd reading char dpkgbuf[1024]; size_t dpkgbuf_pos; @@ -141,12 +142,12 @@ namespace // Maps the dpkg "processing" info to human readable names. Entry 0 // of each array is the key, entry 1 is the value. const std::pair<const char *, const char *> PackageProcessingOps[] = { - std::make_pair("install", N_("Installing %s")), + std::make_pair("install", N_("Preparing %s")), // we don't care for the difference - std::make_pair("upgrade", N_("Installing %s")), - std::make_pair("configure", N_("Configuring %s")), - std::make_pair("remove", N_("Removing %s")), - std::make_pair("purge", N_("Completely removing %s")), + std::make_pair("upgrade", N_("Preparing %s")), + std::make_pair("configure", N_("Preparing to configure %s")), + std::make_pair("remove", N_("Preparing for removal of %s")), + std::make_pair("purge", N_("Preparing to completely remove %s")), std::make_pair("disappear", N_("Noting disappearance of %s")), std::make_pair("trigproc", N_("Running post-installation trigger %s")) }; @@ -958,11 +959,19 @@ void pkgDPkgPM::handleCrossUpgradeAction(string const &pkgname) /*{{{*/ // DPkgPM::DoDpkgStatusFd /*{{{*/ void pkgDPkgPM::DoDpkgStatusFd(int statusfd) { - ssize_t const len = read(statusfd, &d->dpkgbuf[d->dpkgbuf_pos], - (sizeof(d->dpkgbuf)/sizeof(d->dpkgbuf[0])) - d->dpkgbuf_pos); - if(len <= 0) - return; - d->dpkgbuf_pos += (len / sizeof(d->dpkgbuf[0])); + auto const remainingBuffer = (sizeof(d->dpkgbuf) / sizeof(d->dpkgbuf[0])) - d->dpkgbuf_pos; + if (likely(remainingBuffer > 0) && d->status_fd_reached_end_of_file == false) + { + auto const len = read(statusfd, &d->dpkgbuf[d->dpkgbuf_pos], remainingBuffer); + if (len < 0) + return; + else if (len == 0 && d->dpkgbuf_pos == 0) + { + d->status_fd_reached_end_of_file = true; + return; + } + d->dpkgbuf_pos += (len / sizeof(d->dpkgbuf[0])); + } // process line by line from the buffer char *p = d->dpkgbuf, *q = nullptr; @@ -1145,30 +1154,26 @@ void pkgDPkgPM::BuildPackagesProgressMap() { // map the dpkg states to the operations that are performed // (this is sorted in the same way as Item::Ops) - static const std::array<std::array<DpkgState, 3>, 4> DpkgStatesOpMap = {{ + static const std::array<std::array<DpkgState, 2>, 4> DpkgStatesOpMap = {{ // Install operation {{ - {"half-installed", N_("Preparing %s")}, - {"unpacked", N_("Unpacking %s") }, - {nullptr, nullptr} + {"half-installed", N_("Unpacking %s")}, + {"unpacked", N_("Installing %s") }, }}, // Configure operation {{ - {"unpacked",N_("Preparing to configure %s") }, {"half-configured", N_("Configuring %s") }, { "installed", N_("Installed %s")}, }}, // Remove operation {{ - {"half-configured", N_("Preparing for removal of %s")}, + {"half-configured", N_("Removing %s")}, {"half-installed", N_("Removing %s")}, - {"config-files", N_("Removed %s")}, }}, // Purge operation {{ - {"config-files", N_("Preparing to completely remove %s")}, + {"config-files", N_("Completely removing %s")}, {"not-installed", N_("Completely removed %s")}, - {nullptr, nullptr} }}, }}; static_assert(Item::Purge == 3, "Enum item has unexpected index for mapping array"); @@ -1184,21 +1189,16 @@ void pkgDPkgPM::BuildPackagesProgressMap() string const name = I.Pkg.FullName(); PackageOpsDone[name] = 0; - auto AddToPackageOps = std::back_inserter(PackageOps[name]); - if (I.Op == Item::Purge && I.Pkg->CurrentVer != 0) - { - // purging a package which is installed first passes through remove states - auto const DpkgOps = DpkgStatesOpMap[Item::Remove]; - std::copy(DpkgOps.begin(), DpkgOps.end(), AddToPackageOps); + auto AddToPackageOps = [&](decltype(I.Op) const Op) { + auto const DpkgOps = DpkgStatesOpMap[Op]; + std::copy(DpkgOps.begin(), DpkgOps.end(), std::back_inserter(PackageOps[name])); PackagesTotal += DpkgOps.size(); - } - auto const DpkgOps = DpkgStatesOpMap[I.Op]; - std::copy_if(DpkgOps.begin(), DpkgOps.end(), AddToPackageOps, [&](DpkgState const &state) { - if (state.state == nullptr) - return false; - ++PackagesTotal; - return true; - }); + }; + // purging a package which is installed first passes through remove states + if (I.Op == Item::Purge && I.Pkg->CurrentVer != 0) + AddToPackageOps(Item::Remove); + AddToPackageOps(I.Op); + if ((I.Op == Item::Remove || I.Op == Item::Purge) && I.Pkg->CurrentVer != 0) { if (I.Pkg->CurrentState == pkgCache::State::UnPacked || @@ -1622,9 +1622,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) approvedStates.Remove(*Ver); Purges.erase(Ver); auto && RemOp = PackageOps[C.first->Pkg.FullName()]; - if (RemOp.size() == 5) + if (RemOp.size() == 4) { - RemOp.erase(std::next(RemOp.begin(), 3), RemOp.end()); + RemOp.erase(std::next(RemOp.begin(), 2), RemOp.end()); PackagesTotal -= 2; } else @@ -2022,6 +2022,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) // we read from dpkg here int const _dpkgin = fd[0]; close(fd[1]); // close the write end of the pipe + d->status_fd_reached_end_of_file = false; // apply ionice if (_config->FindB("DPkg::UseIoNice", false) == true) @@ -2041,14 +2042,24 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) int Status = 0; int res; bool waitpid_failure = false; - while ((res=waitpid(Child,&Status, WNOHANG)) != Child) { - if(res < 0) { - // error handling, waitpid returned -1 - if (errno == EINTR) - continue; - waitpid_failure = true; - break; + bool dpkg_finished = false; + do + { + if (dpkg_finished == false) + { + if ((res = waitpid(Child, &Status, WNOHANG)) == Child) + dpkg_finished = true; + else if (res < 0) + { + // error handling, waitpid returned -1 + if (errno == EINTR) + continue; + waitpid_failure = true; + break; + } } + if (dpkg_finished && d->status_fd_reached_end_of_file) + break; // wait for input or output here FD_ZERO(&rfds); @@ -2078,7 +2089,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) DoStdin(d->master); if(FD_ISSET(_dpkgin, &rfds)) DoDpkgStatusFd(_dpkgin); - } + + } while (true); close(_dpkgin); // Restore sig int/quit |