From: Michael Vogt Date: Wed, 28 Aug 2013 08:59:54 +0000 (+0200) Subject: Merge remote-tracking branch 'mvo/feature/install-progress' into debian/sid X-Git-Tag: 0.9.11.3~5^2~1 X-Git-Url: https://git.saurik.com/apt.git/commitdiff_plain/f68cba9b720bc44aacf6af468836287d9754afea?ds=inline;hp=-c Merge remote-tracking branch 'mvo/feature/install-progress' into debian/sid --- f68cba9b720bc44aacf6af468836287d9754afea diff --combined apt-pkg/deb/dpkgpm.cc index 4b5467eff,3fb80d158..3c1013761 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@@ -134,8 -134,6 +134,8 @@@ static void dpkgChrootDirectory( std::cerr << "Chrooting into " << chrootDir << std::endl; if (chroot(chrootDir.c_str()) != 0) _exit(100); + if (chdir("/") != 0) + _exit(100); } /*}}}*/ @@@ -296,7 -294,7 +296,7 @@@ bool pkgDPkgPM::SendPkgsInfo(FILE * con if (CurVer.end() == true && (I->Op == Item::Remove || I->Op == Item::Purge)) CurVer = FindNowVersion(I->Pkg); - else if (CurVer.end() == true) + if (CurVer.end() == true) { if (Version <= 2) fprintf(F, "- "); @@@ -382,32 -380,24 +382,32 @@@ bool pkgDPkgPM::RunScriptsWithPkgs(cons 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 int Pipes[2]; if (pipe(Pipes) != 0) return _error->Errno("pipe","Failed to create IPC pipe to subprocess"); - SetCloseExec(Pipes[0],true); + if (InfoFD != (unsigned)Pipes[0]) + SetCloseExec(Pipes[0],true); + else + _config->Set("APT::Keep-Fds::", Pipes[0]); SetCloseExec(Pipes[1],true); - + // Purified Fork for running the script - pid_t Process = ExecFork(); + pid_t Process = ExecFork(); if (Process == 0) { // Setup the FDs - dup2(Pipes[0],STDIN_FILENO); + dup2(Pipes[0], InfoFD); SetCloseExec(STDOUT_FILENO,false); - SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDIN_FILENO,false); SetCloseExec(STDERR_FILENO,false); + string hookfd; + strprintf(hookfd, "%d", InfoFD); + setenv("APT_HOOK_INFO_FD", hookfd.c_str(), 1); + dpkgChrootDirectory(); const char *Args[4]; Args[0] = "/bin/sh"; @@@ -417,8 -407,6 +417,8 @@@ execv(Args[0],(char **)Args); _exit(100); } + if (InfoFD == (unsigned)Pipes[0]) + _config->Clear("APT::Keep-Fds", Pipes[0]); close(Pipes[0]); FILE *F = fdopen(Pipes[1],"w"); if (F == 0) @@@ -632,6 -620,9 +632,9 @@@ void pkgDPkgPM::ProcessDpkgStatusLine(i << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << s << endl; + if(_config->FindB("DPkgPM::Progress", false) == true) + SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); + if(OutStatusFd > 0) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) @@@ -761,15 -752,13 +764,15 @@@ bool pkgDPkgPM::OpenLog( return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str()); setvbuf(d->term_out, NULL, _IONBF, 0); SetCloseExec(fileno(d->term_out), true); - struct passwd *pw; - struct group *gr; - pw = getpwnam("root"); - gr = getgrnam("adm"); - if (pw != NULL && gr != NULL) - chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid); - chmod(logfile_name.c_str(), 0640); + if (getuid() == 0) // if we aren't root, we can't chown a file, so don't try it + { + struct passwd *pw = getpwnam("root"); + struct group *gr = getgrnam("adm"); + if (pw != NULL && gr != NULL && chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0) + _error->WarningE("OpenLog", "chown to root:adm of file %s failed", logfile_name.c_str()); + } + if (chmod(logfile_name.c_str(), 0640) != 0) + _error->WarningE("OpenLog", "chmod 0640 of file %s failed", logfile_name.c_str()); fprintf(d->term_out, "\nLog started: %s\n", timestr); } @@@ -874,6 -863,18 +877,18 @@@ bool pkgDPkgPM::CloseLog( return true; } /*}}}*/ + // DPkgPM::SendTerminalProgress /*{{{*/ + // --------------------------------------------------------------------- + /* Send progress info to the terminal + */ + void pkgDPkgPM::SendTerminalProgress(float percentage) + { + // FIXME: use colors too + std::cout << "\r\n" + << "Progress: [" << percentage << "%]" + << "\r\n"; + } + /*}}}*/ /*{{{*/ // This implements a racy version of pselect for those architectures // that don't have a working implementation. @@@ -1248,13 -1249,16 +1263,13 @@@ bool pkgDPkgPM::Go(int OutStatusFd // if tcgetattr does not return zero there was a error // and we do not do any pty magic - if (tcgetattr(0, &tt) == 0) + _error->PushToStack(); + if (tcgetattr(STDOUT_FILENO, &tt) == 0) { ioctl(0, TIOCGWINSZ, (char *)&win); - if (openpty(&master, &slave, NULL, &tt, &win) < 0) + if (openpty(&master, &slave, NULL, &tt, &win) < 0) { - const char *s = _("Can not write log, openpty() " - "failed (/dev/pts not mounted?)\n"); - fprintf(stderr, "%s",s); - if(d->term_out) - fprintf(d->term_out, "%s",s); + _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); master = slave = -1; } else { struct termios rtt; @@@ -1272,15 -1276,6 +1287,15 @@@ sigprocmask(SIG_SETMASK, &original_sigmask, 0); } } + // complain only if stdout is either a terminal (but still failed) or is an invalid + // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. + else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) + _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); + + if (_error->PendingError() == true) + _error->DumpErrors(std::cerr); + _error->RevertToStack(); + // Fork dpkg pid_t Child; _config->Set("APT::Keep-Fds::",fd[1]); @@@ -1294,7 -1289,7 +1309,7 @@@ FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); } Child = ExecFork(); - + // This is the child if (Child == 0) {