From 7546c8da99ade7b6e1bd6aaa9d026f61400214d1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 11 Jul 2013 23:09:47 +0200 Subject: Add DPkgPM::Progress for terminal install progress --- apt-pkg/deb/dpkgpm.cc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index fb0473535..3fb80d158 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -620,6 +620,9 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << (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) @@ -860,6 +863,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. @@ -1274,7 +1289,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); } Child = ExecFork(); - + // This is the child if (Child == 0) { -- cgit v1.2.3-70-g09d2 From cd4ee27de851910dd84067c45d487c5460641913 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 7 Sep 2013 13:30:48 +0200 Subject: fix multiarch status-fd progress calculation --- apt-pkg/deb/dpkgpm.cc | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3c1013761..d935eb07d 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -512,7 +512,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) /* dpkg sends strings like this: - 'status: : ' + 'status: : ' + 'status: :: ' 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 +528,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 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 iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, @@ -578,14 +586,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 +595,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) @@ -1035,7 +1035,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) { -- cgit v1.2.3-70-g09d2 From a38e023c9d5a237ccae1755966adc7c0bbdb9d7e Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 2 Oct 2013 10:15:28 +0200 Subject: make dpkg progress slightly nicer --- apt-pkg/deb/dpkgpm.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d935eb07d..a5097a04f 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -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 @@ -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; } /*}}}*/ /*{{{*/ @@ -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")); -- cgit v1.2.3-70-g09d2 From af6b41692b21a7fd1561d9ad4b3e4407ab93246f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 7 Oct 2013 10:26:50 +0200 Subject: add -o DpkgPM::Progress-Fancy for better dpkg progress output on vt100+ terminals --- apt-pkg/deb/dpkgpm.cc | 88 +++++++++++++++++++++++++++++++++++++++++++++------ apt-pkg/deb/dpkgpm.h | 2 ++ 2 files changed, 81 insertions(+), 9 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a5097a04f..4eb373fb7 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -54,9 +54,15 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0) + last_reported_progress(0.0), nr_terminal_rows(0), + fancy_progress_output(false) { dpkgbuf[0] = '\0'; + if(_config->FindB("DpkgPM::Progress-Fancy", false)) + { + fancy_progress_output = true; + _config->Set("DpkgPM::Progress", true); + } } bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading @@ -67,6 +73,8 @@ public: string dpkg_error; float last_reported_progress; + int nr_terminal_rows; + bool fancy_progress_output; }; namespace @@ -892,10 +900,37 @@ void pkgDPkgPM::SendTerminalProgress(float percentage) if(percentage < (d->last_reported_progress + reporting_steps)) return; - // FIXME: use colors too - std::cout << "\r\n" - << "Progress: [" << std::setw(3) << int(percentage) << "%]" - << "\r\n"; + std::string progress_str; + strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + if (d->fancy_progress_output) + { + int row = d->nr_terminal_rows; + + static string save_cursor = "\033[s"; + static string restore_cursor = "\033[u"; + + static string set_bg_color = "\033[42m"; // green + static string set_fg_color = "\033[30m"; // black + + static string restore_bg = "\033[49m"; + static string restore_fg = "\033[39m"; + + std::cout << save_cursor + // move cursor position to last row + << "\033[" << row << ";0f" + << set_bg_color + << set_fg_color + << progress_str + << restore_cursor + << restore_bg + << restore_fg; + } + else + { + std::cout << progress_str << "\r\n"; + } + std::flush(std::cout); + d->last_reported_progress = percentage; } /*}}}*/ @@ -920,6 +955,29 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, return retval; } /*}}}*/ + +void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) +{ + if(!d->fancy_progress_output) + return; + + // scroll down a bit to avoid visual glitch when the screen + // area shrinks by one row + std::cout << "\n\n"; + + // save cursor + std::cout << "\033[s"; + + // set scroll region (this will place the cursor in the top left) + std::cout << "\033[1;" << nr_rows - 1 << "r"; + + // restore cursor but ensure its inside the scrolling area + std::cout << "\033[u"; + static const char *move_cursor_up = "\033[1A"; + std::cout << move_cursor_up; + std::flush(std::cout); +} + // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -1276,7 +1334,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) _error->PushToStack(); if (tcgetattr(STDOUT_FILENO, &tt) == 0) { - ioctl(0, TIOCGWINSZ, (char *)&win); + ioctl(1, TIOCGWINSZ, (char *)&win); + d->nr_terminal_rows = win.ws_row; if (openpty(&master, &slave, NULL, &tt, &win) < 0) { _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); @@ -1318,11 +1377,12 @@ bool pkgDPkgPM::Go(int OutStatusFd) << endl; FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); } + Child = ExecFork(); - // This is the child if (Child == 0) { + if(slave >= 0 && master >= 0) { setsid(); @@ -1339,7 +1399,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0) _exit(100); - + if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO)) { int Flags,dummy; @@ -1355,6 +1415,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } + SetupTerminalScrollArea(d->nr_terminal_rows); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1449,6 +1510,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); + // reset scroll area + SetupTerminalScrollArea(d->nr_terminal_rows); + if(d->fancy_progress_output) + { + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; + } + if(master >= 0) { tcsetattr(0, TCSAFLUSH, &tt); @@ -1488,7 +1558,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) // 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")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 29901a204..3b8d36623 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -84,6 +84,8 @@ class pkgDPkgPM : public pkgPackageManager bool SendPkgsInfo(FILE * const F, unsigned int const &Version); void WriteHistoryTag(std::string const &tag, std::string value); + // Terminal progress + void SetupTerminalScrollArea(int nr_scrolled_rows); void SendTerminalProgress(float percentage); // apport integration -- cgit v1.2.3-70-g09d2 From 1c6089d72ddf59875fae4f281f023abba0d4fda0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 7 Oct 2013 13:37:28 +0200 Subject: use Dpkg::Progress-Fancy to be consitent with Dpkg::Progress --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 4eb373fb7..a116db9cf 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -58,7 +58,7 @@ public: fancy_progress_output(false) { dpkgbuf[0] = '\0'; - if(_config->FindB("DpkgPM::Progress-Fancy", false)) + if(_config->FindB("Dpkg::Progress-Fancy", false) == true) { fancy_progress_output = true; _config->Set("DpkgPM::Progress", true); -- cgit v1.2.3-70-g09d2 From 28e3b6f6f822a640aec35a41d5e99a97cfa1e9b1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 7 Oct 2013 13:46:30 +0200 Subject: fix off-by-one error in pkgDPkgPM::SetupTerminalScrollArea() --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a116db9cf..7d8c9b4e0 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -963,7 +963,7 @@ void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) // scroll down a bit to avoid visual glitch when the screen // area shrinks by one row - std::cout << "\n\n"; + std::cout << "\n"; // save cursor std::cout << "\033[s"; -- cgit v1.2.3-70-g09d2 From 77fdc2a4de43144432ef9e74058634e94e45ef65 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 8 Oct 2013 21:48:14 +0200 Subject: apt-pkg/deb/dpkgpm.cc: fix off-by-one in SetupTerminalScrollArea reset --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 7d8c9b4e0..b4d812d26 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1511,7 +1511,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); // reset scroll area - SetupTerminalScrollArea(d->nr_terminal_rows); + SetupTerminalScrollArea(d->nr_terminal_rows + 1); if(d->fancy_progress_output) { // override the progress line (sledgehammer) -- cgit v1.2.3-70-g09d2 From 31f97d7b862ccf3de93b30a15f24d76e806031a3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 11 Oct 2013 19:27:23 +0200 Subject: first iteration of install progress refactor --- apt-pkg/deb/dpkgpm.cc | 111 +++++++++-------------------------------------- apt-pkg/deb/dpkgpm.h | 1 + apt-pkg/iprogress.cc | 111 +++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/iprogress.h | 59 +++++++++++++++++++++++++ apt-pkg/makefile | 4 +- apt-pkg/packagemanager.h | 1 + 6 files changed, 194 insertions(+), 93 deletions(-) create mode 100644 apt-pkg/iprogress.cc create mode 100644 apt-pkg/iprogress.h (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4d812d26..cd4f5c31e 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -54,16 +55,21 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0), nr_terminal_rows(0), - fancy_progress_output(false) + last_reported_progress(0.0) { dpkgbuf[0] = '\0'; - if(_config->FindB("Dpkg::Progress-Fancy", false) == true) - { - fancy_progress_output = true; - _config->Set("DpkgPM::Progress", true); - } + if(_config->FindB("DpkgPM::Progress-Fancy", false) == true) + progress = new APT::Progress::PackageManagerFancy(); + else if (_config->FindB("DpkgPM::Progress", false) == true) + progress = new APT::Progress::PackageManagerText(); + else + progress = new APT::Progress::PackageManager(); } + ~pkgDPkgPMPrivate() + { + delete progress; + } + bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading char dpkgbuf[1024]; @@ -73,8 +79,7 @@ public: string dpkg_error; float last_reported_progress; - int nr_terminal_rows; - bool fancy_progress_output; + APT::Progress::PackageManager *progress; }; namespace @@ -644,8 +649,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << s << endl; - if(_config->FindB("DPkgPM::Progress", false) == true) - SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); + d->progress->StatusChanged(pkg, PackagesDone, PackagesTotal); if(OutStatusFd > 0) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); @@ -889,52 +893,6 @@ bool pkgDPkgPM::CloseLog() return true; } /*}}}*/ -// DPkgPM::SendTerminalProgress /*{{{*/ -// --------------------------------------------------------------------- -/* Send progress info to the terminal - */ -void pkgDPkgPM::SendTerminalProgress(float percentage) -{ - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - - if(percentage < (d->last_reported_progress + reporting_steps)) - return; - - std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); - if (d->fancy_progress_output) - { - int row = d->nr_terminal_rows; - - static string save_cursor = "\033[s"; - static string restore_cursor = "\033[u"; - - static string set_bg_color = "\033[42m"; // green - static string set_fg_color = "\033[30m"; // black - - static string restore_bg = "\033[49m"; - static string restore_fg = "\033[39m"; - - std::cout << save_cursor - // move cursor position to last row - << "\033[" << row << ";0f" - << set_bg_color - << set_fg_color - << progress_str - << restore_cursor - << restore_bg - << restore_fg; - } - else - { - std::cout << progress_str << "\r\n"; - } - std::flush(std::cout); - - d->last_reported_progress = percentage; -} - /*}}}*/ -/*{{{*/ // 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 @@ -956,27 +914,6 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, } /*}}}*/ -void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) -{ - if(!d->fancy_progress_output) - return; - - // scroll down a bit to avoid visual glitch when the screen - // area shrinks by one row - std::cout << "\n"; - - // save cursor - std::cout << "\033[s"; - - // set scroll region (this will place the cursor in the top left) - std::cout << "\033[1;" << nr_rows - 1 << "r"; - - // restore cursor but ensure its inside the scrolling area - std::cout << "\033[u"; - static const char *move_cursor_up = "\033[1A"; - std::cout << move_cursor_up; - std::flush(std::cout); -} // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- @@ -1334,8 +1271,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) _error->PushToStack(); if (tcgetattr(STDOUT_FILENO, &tt) == 0) { - ioctl(1, TIOCGWINSZ, (char *)&win); - d->nr_terminal_rows = win.ws_row; + ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win); if (openpty(&master, &slave, NULL, &tt, &win) < 0) { _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); @@ -1415,7 +1351,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } - SetupTerminalScrollArea(d->nr_terminal_rows); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1424,6 +1359,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) cerr << "Could not exec dpkg!" << endl; _exit(100); } + d->progress->Started(); // apply ionice if (_config->FindB("DPkg::UseIoNice", false) == true) @@ -1510,14 +1446,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); - // reset scroll area - SetupTerminalScrollArea(d->nr_terminal_rows + 1); - if(d->fancy_progress_output) - { - // override the progress line (sledgehammer) - static const char* clear_screen_below_cursor = "\033[J"; - std::cout << clear_screen_below_cursor; - } + // tell the progress + d->progress->Finished(); if(master >= 0) { @@ -1556,8 +1486,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) CloseLog(); // dpkg is done at this point - if(_config->FindB("DPkgPM::Progress", false) == true) - SendTerminalProgress(100); + d->progress->StatusChanged("", PackagesDone, PackagesTotal); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 3b8d36623..53e352d4e 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -23,6 +23,7 @@ using std::map; class pkgDPkgPMPrivate; + class pkgDPkgPM : public pkgPackageManager { private: diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc new file mode 100644 index 000000000..4de8c0492 --- /dev/null +++ b/apt-pkg/iprogress.cc @@ -0,0 +1,111 @@ +#include +#include + +#include +#include + +namespace APT { +namespace Progress { + +static void SetupTerminalScrollArea(int nr_rows) +{ + // scroll down a bit to avoid visual glitch when the screen + // area shrinks by one row + std::cout << "\n"; + + // save cursor + std::cout << "\033[s"; + + // set scroll region (this will place the cursor in the top left) + std::cout << "\033[1;" << nr_rows - 1 << "r"; + + // restore cursor but ensure its inside the scrolling area + std::cout << "\033[u"; + static const char *move_cursor_up = "\033[1A"; + std::cout << move_cursor_up; + std::flush(std::cout); +} + +PackageManagerFancy::PackageManagerFancy() + : nr_terminal_rows(-1) +{ + struct winsize win; + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0) + { + nr_terminal_rows = win.ws_row; + } +} + +void PackageManagerFancy::Started() +{ + SetupTerminalScrollArea(nr_terminal_rows); +} + +void PackageManagerFancy::Finished() +{ + SetupTerminalScrollArea(nr_terminal_rows + 1); + + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; +} + +void PackageManagerFancy::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + float percentage = StepsDone/(float)TotalSteps * 100.0; + + if(percentage < (last_reported_progress + reporting_steps)) + return; + + std::string progress_str; + strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + + int row = nr_terminal_rows; + + static string save_cursor = "\033[s"; + static string restore_cursor = "\033[u"; + + static string set_bg_color = "\033[42m"; // green + static string set_fg_color = "\033[30m"; // black + + static string restore_bg = "\033[49m"; + static string restore_fg = "\033[39m"; + + std::cout << save_cursor + // move cursor position to last row + << "\033[" << row << ";0f" + << set_bg_color + << set_fg_color + << progress_str + << restore_cursor + << restore_bg + << restore_fg; + std::flush(std::cout); + last_reported_progress = percentage; +} + +void PackageManagerText::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + float percentage = StepsDone/(float)TotalSteps * 100.0; + + if(percentage < (last_reported_progress + reporting_steps)) + return; + + std::string progress_str; + strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + + std::cout << progress_str << "\r\n"; + std::flush(std::cout); + + last_reported_progress = percentage; +} + + +}; // namespace progress +}; // namespace apt diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h new file mode 100644 index 000000000..14fc89bff --- /dev/null +++ b/apt-pkg/iprogress.h @@ -0,0 +1,59 @@ +#ifndef PKGLIB_IPROGRESS_H +#define PKGLIB_IPROGRSS_H + + +#include + +namespace APT { +namespace Progress { + + + class PackageManager + { + private: + /** \brief dpointer placeholder */ + void *d; + + public: + virtual ~PackageManager() {}; + + virtual void Started() {}; + virtual void Finished() {}; + + virtual void StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) {}; + }; + + class PackageManagerFancy : public PackageManager + { + protected: + int last_reported_progress; + int nr_terminal_rows; + public: + PackageManagerFancy(); + virtual void Started(); + virtual void Finished(); + virtual void StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps); + }; + + class PackageManagerText : public PackageManager + { + protected: + int last_reported_progress; + + public: + PackageManagerText() : last_reported_progress(0) {}; + virtual void StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps); + + }; + + +}; // namespace Progress +}; // namespace APT + +#endif diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 59729faf5..e69b5ce7f 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -43,7 +43,7 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \ srcrecords.cc cachefile.cc versionmatch.cc policy.cc \ pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \ indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \ - aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc + aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc iprogress.cc HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ orderlist.h sourcelist.h packagemanager.h tagfile.h \ init.h pkgcache.h version.h progress.h pkgrecords.h \ @@ -51,7 +51,7 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \ clean.h srcrecords.h cachefile.h versionmatch.h policy.h \ pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \ vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \ - cachefilter.h cacheset.h edsp.h + cachefilter.h cacheset.h edsp.h iprogress.h # Source code for the debian specific components # In theory the deb headers do not need to be exported.. diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 1a6a9f01c..4956e816f 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -39,6 +39,7 @@ class pkgDepCache; class pkgSourceList; class pkgOrderList; class pkgRecords; + class pkgPackageManager : protected pkgCache::Namespace { public: -- cgit v1.2.3-70-g09d2 From f28eef6df2a9fd2befedacf8ccd6248e5b3618db Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 11 Oct 2013 22:05:38 +0200 Subject: add missing _() around the new "Progress" string --- apt-pkg/deb/dpkgpm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4d812d26..c29d21574 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -901,7 +901,7 @@ void pkgDPkgPM::SendTerminalProgress(float percentage) return; std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); if (d->fancy_progress_output) { int row = d->nr_terminal_rows; -- cgit v1.2.3-70-g09d2 From 6c5ae8ed079e01082f606614641b19b7c08893ad Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 11 Oct 2013 22:48:22 +0200 Subject: move common code into PackageManager::StatusChanged() --- apt-pkg/deb/dpkgpm.cc | 5 +++-- apt-pkg/iprogress.cc | 43 +++++++++++++++++++++++++------------------ apt-pkg/iprogress.h | 19 ++++++++++--------- 3 files changed, 38 insertions(+), 29 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index cd4f5c31e..35adb91f6 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -58,9 +58,10 @@ public: last_reported_progress(0.0) { dpkgbuf[0] = '\0'; - if(_config->FindB("DpkgPM::Progress-Fancy", false) == true) + if(_config->FindB("Dpkg::Progress-Fancy", false) == true) progress = new APT::Progress::PackageManagerFancy(); - else if (_config->FindB("DpkgPM::Progress", false) == true) + else if (_config->FindB("Dpkg::Progress", + _config->FindB("DpkgPM::Progress", false)) == true) progress = new APT::Progress::PackageManagerText(); else progress = new APT::Progress::PackageManager(); diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 68a2c7207..398059051 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -7,6 +8,20 @@ namespace APT { namespace Progress { +bool PackageManager::StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps) +{ + int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); + percentage = StepsDone/(float)TotalSteps * 100.0; + strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage); + + if(percentage < (last_reported_progress + reporting_steps)) + return false; + + return true; +} + void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { // scroll down a bit to avoid visual glitch when the screen @@ -55,18 +70,12 @@ void PackageManagerFancy::Finished() } } -void PackageManagerFancy::StatusChanged(std::string PackageName, +bool PackageManagerFancy::StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps) { - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - float percentage = StepsDone/(float)TotalSteps * 100.0; - - if(percentage < (last_reported_progress + reporting_steps)) - return; - - std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + return false; int row = nr_terminal_rows; @@ -90,25 +99,23 @@ void PackageManagerFancy::StatusChanged(std::string PackageName, << restore_fg; std::flush(std::cout); last_reported_progress = percentage; + + return true; } -void PackageManagerText::StatusChanged(std::string PackageName, +bool PackageManagerText::StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps) { - int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); - float percentage = StepsDone/(float)TotalSteps * 100.0; - - if(percentage < (last_reported_progress + reporting_steps)) - return; - - std::string progress_str; - strprintf(progress_str, "Progress: [%3i%%]", (int)percentage); + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + return false; std::cout << progress_str << "\r\n"; std::flush(std::cout); last_reported_progress = percentage; + + return true; } diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index f097e0943..5f1655ab9 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -14,21 +14,26 @@ namespace Progress { /** \brief dpointer placeholder */ void *d; + protected: + std::string progress_str; + float percentage; + int last_reported_progress; + public: + PackageManager() : percentage(0.0), last_reported_progress(0) {}; virtual ~PackageManager() {}; virtual void Started() {}; virtual void Finished() {}; - virtual void StatusChanged(std::string PackageName, + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps) {}; + unsigned int TotalSteps); }; class PackageManagerFancy : public PackageManager { protected: - int last_reported_progress; int nr_terminal_rows; void SetupTerminalScrollArea(int nr_rows); @@ -36,19 +41,15 @@ namespace Progress { PackageManagerFancy(); virtual void Started(); virtual void Finished(); - virtual void StatusChanged(std::string PackageName, + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps); }; class PackageManagerText : public PackageManager { - protected: - int last_reported_progress; - public: - PackageManagerText() : last_reported_progress(0) {}; - virtual void StatusChanged(std::string PackageName, + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps); -- cgit v1.2.3-70-g09d2 From e6ad8031b774af9bdd5d460d9983450bb5a03d0d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 13 Oct 2013 15:05:04 +0200 Subject: move the status-fd progress reporting out of the pkgDPkgPM class, at this point, breaks ABI/API, lets see what we can do about this --- apt-pkg/deb/dpkgpm.cc | 99 ++++++++++-------------------------------- apt-pkg/deb/dpkgpm.h | 7 +-- apt-pkg/iprogress.cc | 95 +++++++++++++++++++++++++++++++++++++--- apt-pkg/iprogress.h | 56 ++++++++++++++++++++---- apt-pkg/packagemanager.cc | 14 +++--- apt-pkg/packagemanager.h | 18 ++++++-- apt-private/private-install.cc | 24 +++++++++- 7 files changed, 211 insertions(+), 102 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 35adb91f6..0c3be4ce5 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -55,20 +55,12 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0) + last_reported_progress(0.0), progress(NULL) { dpkgbuf[0] = '\0'; - if(_config->FindB("Dpkg::Progress-Fancy", false) == true) - progress = new APT::Progress::PackageManagerFancy(); - else if (_config->FindB("Dpkg::Progress", - _config->FindB("DpkgPM::Progress", false)) == true) - progress = new APT::Progress::PackageManagerText(); - else - progress = new APT::Progress::PackageManager(); } ~pkgDPkgPMPrivate() { - delete progress; } bool stdin_is_dev_null; @@ -519,11 +511,9 @@ void pkgDPkgPM::DoTerminalPty(int master) // --------------------------------------------------------------------- /* */ -void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) +void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false); - // the status we output - ostringstream status; if (Debug == true) std::clog << "got from dpkg '" << line << "'" << std::endl; @@ -573,7 +563,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // 'processing: action: pkg' if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) { - char s[200]; const char* const pkg_or_trigger = list[2].c_str(); action = list[1].c_str(); const std::pair * const iter = @@ -586,17 +575,11 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::clog << "ignoring unknown action: " << action << std::endl; return; } - snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger); - - status << "pmstatus:" << pkg_or_trigger - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + std::string pkg_action; + strprintf(pkg_action, _(iter->second), pkg_or_trigger); + d->progress->StatusChanged(pkg_or_trigger, PackagesDone, PackagesTotal, + pkg_action); if (strncmp(action, "disappear", strlen("disappear")) == 0) handleDisappearAction(pkg_or_trigger); return; @@ -604,28 +587,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if(strncmp(action,"error",strlen("error")) == 0) { - status << "pmerror:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + d->progress->Error(list[1], PackagesDone, PackagesTotal, list[3]); pkgFailures++; WriteApportReport(list[1].c_str(), list[3].c_str()); return; } else if(strncmp(action,"conffile",strlen("conffile")) == 0) { - status << "pmconffile:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, + list[3]); return; } @@ -638,24 +608,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) { // only read the translation if there is actually a next // action - const char *translation = _(states[PackageOpsDone[pkg]].str); - char s[200]; - snprintf(s, sizeof(s), translation, pkg); + std::string translation; + strprintf(translation, _(states[PackageOpsDone[pkg]].str), pkg); // we moved from one dpkg state to a new one, report that PackageOpsDone[pkg]++; PackagesDone++; - // build the status str - status << "pmstatus:" << pkg - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s - << endl; - d->progress->StatusChanged(pkg, PackagesDone, PackagesTotal); - - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; + // and send to the progress + d->progress->StatusChanged(pkg, PackagesDone, PackagesTotal, + translation); } if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << pkg @@ -713,7 +674,7 @@ void pkgDPkgPM::handleDisappearAction(string const &pkgname) // --------------------------------------------------------------------- /* */ -void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd) +void pkgDPkgPM::DoDpkgStatusFd(int statusfd) { char *p, *q; int len; @@ -728,7 +689,7 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd) while((q=(char*)memchr(p, '\n', d->dpkgbuf+d->dpkgbuf_pos-p)) != NULL) { *q = 0; - ProcessDpkgStatusLine(OutStatusFd, p); + ProcessDpkgStatusLine(p); p=q+1; // continue with next line } @@ -920,14 +881,15 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, // --------------------------------------------------------------------- /* This globs the operations and calls dpkg * - * If it is called with "OutStatusFd" set to a valid file descriptor - * apt will report the install progress over this fd. It maps the - * dpkg states a package goes through to human readable (and i10n-able) + * 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 + * through to human readable (and i10n-able) * names and calculates a percentage for each step. */ -bool pkgDPkgPM::Go(int OutStatusFd) +bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { pkgPackageManager::SigINTStop = false; + d->progress = progress; // Generate the base argument list for dpkg std::vector Args; @@ -1304,16 +1266,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) // Fork dpkg pid_t Child; - _config->Set("APT::Keep-Fds::",fd[1]); - // send status information that we are about to fork dpkg - if(OutStatusFd > 0) { - ostringstream status; - status << "pmstatus:dpkg-exec:" - << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << _("Running dpkg") - << endl; - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - } + d->progress->Started(); Child = ExecFork(); // This is the child @@ -1360,15 +1313,11 @@ bool pkgDPkgPM::Go(int OutStatusFd) cerr << "Could not exec dpkg!" << endl; _exit(100); } - d->progress->Started(); // apply ionice if (_config->FindB("DPkg::UseIoNice", false) == true) ionice(Child); - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds",fd[1]); - // Wait for dpkg int Status = 0; @@ -1437,7 +1386,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(master >= 0 && FD_ISSET(0, &rfds)) DoStdin(master); if(FD_ISSET(_dpkgin, &rfds)) - DoDpkgStatusFd(_dpkgin, OutStatusFd); + DoDpkgStatusFd(_dpkgin); } close(_dpkgin); @@ -1487,7 +1436,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) CloseLog(); // dpkg is done at this point - d->progress->StatusChanged("", PackagesDone, PackagesTotal); + d->progress->StatusChanged("", PackagesDone, PackagesTotal, ""); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 53e352d4e..1f4bbafc7 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -99,14 +99,15 @@ class pkgDPkgPM : public pkgPackageManager // input processing void DoStdin(int master); void DoTerminalPty(int master); - void DoDpkgStatusFd(int statusfd, int OutStatusFd); - void ProcessDpkgStatusLine(int OutStatusFd, char *line); + void DoDpkgStatusFd(int statusfd); + void ProcessDpkgStatusLine(char *line); // The Actuall installation implementation virtual bool Install(PkgIterator Pkg,std::string File); virtual bool Configure(PkgIterator Pkg); virtual bool Remove(PkgIterator Pkg,bool Purge = false); - virtual bool Go(int StatusFd=-1); + + virtual bool Go(APT::Progress::PackageManager *progress); virtual void Reset(); public: diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 398059051..6c5d33d4a 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -1,16 +1,22 @@ +#include +#include #include #include + #include #include #include +#include + namespace APT { namespace Progress { bool PackageManager::StatusChanged(std::string PackageName, - unsigned int StepsDone, - unsigned int TotalSteps) + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction) { int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1); percentage = StepsDone/(float)TotalSteps * 100.0; @@ -22,6 +28,80 @@ bool PackageManager::StatusChanged(std::string PackageName, return true; } +PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) +{ + OutStatusFd = progress_fd; +} + +void PackageManagerProgressFd::Started() +{ + _config->Set("APT::Keep-Fds::", OutStatusFd); + + // send status information that we are about to fork dpkg + if(OutStatusFd > 0) { + std::ostringstream status; + status << "pmstatus:dpkg-exec:" + << (StepsDone/float(StepsTotal)*100.0) + << ":" << _("Running dpkg") + << std::endl; + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + } +} + +void PackageManagerProgressFd::Finished() +{ + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds", OutStatusFd); +} + +void PackageManagerProgressFd::Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) +{ + std::ostringstream status; + status << "pmerror:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ErrorMessage + << std::endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); +} + +void PackageManagerProgressFd::ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) +{ + std::ostringstream status; + status << "pmconffile:" << PackageName + << ":" << (StepsDone/float(TotalSteps)*100.0) + << ":" << ConfMessage + << std::endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); +} + + +bool PackageManagerProgressFd::StatusChanged(std::string PackageName, + unsigned int xStepsDone, + unsigned int xTotalSteps, + std::string pkg_action) +{ + StepsDone = xStepsDone; + StepsTotal = xTotalSteps; + + // build the status str + std::ostringstream status; + status << "pmstatus:" << PackageName + << ":" << (StepsDone/float(StepsTotal)*100.0) + << ":" << pkg_action + << std::endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + return true; +} + void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows) { // scroll down a bit to avoid visual glitch when the screen @@ -72,9 +152,11 @@ void PackageManagerFancy::Finished() bool PackageManagerFancy::StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps) + unsigned int TotalSteps, + std::string HumanReadableAction) { - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, + HumanReadableAction)) return false; int row = nr_terminal_rows; @@ -105,9 +187,10 @@ bool PackageManagerFancy::StatusChanged(std::string PackageName, bool PackageManagerText::StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps) + unsigned int TotalSteps, + std::string HumanReadableAction) { - if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps)) + if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction)) return false; std::cout << progress_str << "\r\n"; diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 5f1655ab9..6519e9445 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -1,13 +1,13 @@ #ifndef PKGLIB_IPROGRESS_H -#define PKGLIB_IPROGRSS_H +#define PKGLIB_IPROGRESS_H +#include +#include -#include namespace APT { namespace Progress { - class PackageManager { private: @@ -20,15 +20,54 @@ namespace Progress { int last_reported_progress; public: - PackageManager() : percentage(0.0), last_reported_progress(0) {}; + PackageManager() + : percentage(0.0), last_reported_progress(0) {}; virtual ~PackageManager() {}; virtual void Started() {}; virtual void Finished() {}; + + virtual pid_t fork() {return fork(); }; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps); + unsigned int TotalSteps, + std::string HumanReadableAction) ; + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage) {}; + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage) {}; + }; + + class PackageManagerProgressFd : public PackageManager + { + protected: + int OutStatusFd; + int StepsDone; + int StepsTotal; + + public: + PackageManagerProgressFd(int progress_fd); + virtual void Started(); + virtual void Finished(); + + virtual bool StatusChanged(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string HumanReadableAction); + virtual void Error(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ErrorMessage); + virtual void ConffilePrompt(std::string PackageName, + unsigned int StepsDone, + unsigned int TotalSteps, + std::string ConfMessage); + }; class PackageManagerFancy : public PackageManager @@ -43,7 +82,8 @@ namespace Progress { virtual void Finished(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps); + unsigned int TotalSteps, + std::string HumanReadableAction); }; class PackageManagerText : public PackageManager @@ -51,8 +91,8 @@ namespace Progress { public: virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, - unsigned int TotalSteps); - + unsigned int TotalSteps, + std::string HumanReadableAction); }; diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 8c0d2e855..32bc5284e 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1032,28 +1032,32 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() // PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/ // --------------------------------------------------------------------- pkgPackageManager::OrderResult -pkgPackageManager::DoInstallPostFork(int statusFd) +pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) { +// FIXME: port to new structure +#if 0 if(statusFd > 0) // FIXME: use SetCloseExec here once it taught about throwing // exceptions instead of doing _exit(100) on failure fcntl(statusFd,F_SETFD,FD_CLOEXEC); - bool goResult = Go(statusFd); +#endif + bool goResult = Go(progress); if(goResult == false) return Failed; return Res; }; - + /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ -pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) +pkgPackageManager::OrderResult +pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) { if(DoInstallPreFork() == Failed) return Failed; - return DoInstallPostFork(statusFd); + return DoInstallPostFork(progress); } /*}}}*/ diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 4956e816f..5c15ac0e4 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -24,6 +24,7 @@ #define PKGLIB_PACKAGEMANAGER_H #include +#include #include #include @@ -40,6 +41,7 @@ class pkgSourceList; class pkgOrderList; class pkgRecords; + class pkgPackageManager : protected pkgCache::Namespace { public: @@ -84,7 +86,7 @@ class pkgPackageManager : protected pkgCache::Namespace virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;}; virtual bool Configure(PkgIterator /*Pkg*/) {return false;}; virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;}; - virtual bool Go(int statusFd=-1) {return true;}; + virtual bool Go(APT::Progress::PackageManager *progress) {return true;}; virtual void Reset() {}; // the result of the operation @@ -97,7 +99,17 @@ class pkgPackageManager : protected pkgCache::Namespace pkgRecords *Recs); // Do the installation - OrderResult DoInstall(int statusFd=-1); + OrderResult DoInstall(APT::Progress::PackageManager *progress); + + // compat + OrderResult DoInstall(int statusFd=-1) { + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + OrderResult res = DoInstall(progress); + delete progress; + return res; + } + // stuff that needs to be done before the fork() of a library that // uses apt @@ -107,7 +119,7 @@ class pkgPackageManager : protected pkgCache::Namespace }; // stuff that needs to be done after the fork - OrderResult DoInstallPostFork(int statusFd=-1); + OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); bool FixMissing(); /** \brief returns all packages dpkg let disappear */ diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 643a6b370..d1066c869 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -104,7 +105,11 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) { pkgSimulate PM(Cache); int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd); + APT::Progress::PackageManager *progress = NULL; + if (status_fd > 0) + progress = new APT::Progress::PackageManagerProgressFd(status_fd); + pkgPackageManager::OrderResult Res = PM.DoInstall(progress); + delete progress; if (Res == pkgPackageManager::Failed) return false; if (Res != pkgPackageManager::Completed) @@ -332,8 +337,23 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) } _system->UnLock(); + + // FIXME: make this a factory + // select the right progress int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd); + APT::Progress::PackageManager *progress = NULL; + if (status_fd > 0) + progress = new APT::Progress::PackageManagerProgressFd(status_fd); + else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) + progress = new APT::Progress::PackageManagerFancy(); + else if (_config->FindB("Dpkg::Progress", + _config->FindB("DpkgPM::Progress", false)) == true) + progress = new APT::Progress::PackageManagerText(); + else + progress = new APT::Progress::PackageManager(); + pkgPackageManager::OrderResult Res = PM->DoInstall(progress); + delete progress; + if (Res == pkgPackageManager::Failed || _error->PendingError() == true) return false; if (Res == pkgPackageManager::Completed) -- cgit v1.2.3-70-g09d2 From ca5b257835578d98145becbc3d97505394a7726c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 13 Oct 2013 15:10:53 +0200 Subject: add APT::Progress::PackageManager::Pulse() --- apt-pkg/deb/dpkgpm.cc | 5 +++-- apt-pkg/iprogress.h | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 0c3be4ce5..d617a3c0c 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1364,13 +1364,14 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) FD_SET(_dpkgin, &rfds); if(master >= 0) FD_SET(master, &rfds); - tv.tv_sec = 1; - tv.tv_nsec = 0; + tv.tv_sec = 0; + tv.tv_nsec = d->progress->GetPulseInterval(); select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &original_sigmask); if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &original_sigmask); + d->progress->Pulse(); if (select_ret == 0) continue; else if (select_ret < 0 && errno == EINTR) diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 6519e9445..04520ffe8 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -28,7 +28,12 @@ namespace Progress { virtual void Finished() {}; virtual pid_t fork() {return fork(); }; - + + virtual void Pulse() {}; + virtual long GetPulseInterval() { + return 500000; + }; + virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, -- cgit v1.2.3-70-g09d2 From a22fdebf63a42026e4350ebd069512c797bc2a5b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 14 Oct 2013 07:52:21 +0200 Subject: rename APT::Progress::Packagemanager Started->Start, Finished->Stop to match pkgAcquireStatus --- apt-pkg/deb/dpkgpm.cc | 10 ++++------ apt-pkg/iprogress.cc | 8 ++++---- apt-pkg/iprogress.h | 13 ++++++------- 3 files changed, 14 insertions(+), 17 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d617a3c0c..36d8c829a 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1264,11 +1264,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) _error->DumpErrors(std::cerr); _error->RevertToStack(); - // Fork dpkg - pid_t Child; - d->progress->Started(); - - Child = ExecFork(); + // Tell the progress that its starting and fork dpkg + d->progress->Start(); + pid_t Child = ExecFork(); // This is the child if (Child == 0) { @@ -1398,7 +1396,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) signal(SIGHUP,old_SIGHUP); // tell the progress - d->progress->Finished(); + d->progress->Stop(); if(master >= 0) { diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 7d1cc6341..7de190da0 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -40,7 +40,7 @@ void PackageManagerProgressFd::WriteToStatusFd(std::string s) FileFd::Write(OutStatusFd, s.c_str(), s.size()); } -void PackageManagerProgressFd::Started() +void PackageManagerProgressFd::Start() { _config->Set("APT::Keep-Fds::", OutStatusFd); @@ -53,7 +53,7 @@ void PackageManagerProgressFd::Started() WriteToStatusFd(status.str()); } -void PackageManagerProgressFd::Finished() +void PackageManagerProgressFd::Stop() { // clear the Keep-Fd again _config->Clear("APT::Keep-Fds", OutStatusFd); @@ -134,13 +134,13 @@ PackageManagerFancy::PackageManagerFancy() } } -void PackageManagerFancy::Started() +void PackageManagerFancy::Start() { if (nr_terminal_rows > 0) SetupTerminalScrollArea(nr_terminal_rows); } -void PackageManagerFancy::Finished() +void PackageManagerFancy::Stop() { if (nr_terminal_rows > 0) { diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index 5584b3940..ccf154279 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -24,8 +24,8 @@ namespace Progress { : percentage(0.0), last_reported_progress(0) {}; virtual ~PackageManager() {}; - virtual void Started() {}; - virtual void Finished() {}; + virtual void Start() {}; + virtual void Stop() {}; virtual pid_t fork() {return fork(); }; @@ -59,9 +59,8 @@ namespace Progress { public: PackageManagerProgressFd(int progress_fd); - // FIXME: rename to Start/Stop to match the pkgAcquireStatus - virtual void Started(); - virtual void Finished(); + virtual void Start(); + virtual void Stop(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, @@ -86,8 +85,8 @@ namespace Progress { public: PackageManagerFancy(); - virtual void Started(); - virtual void Finished(); + virtual void Start(); + virtual void Stop(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, -- cgit v1.2.3-70-g09d2 From 5e9458e285af11c7fa4308add10d250e3546c8bf Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 14 Oct 2013 08:42:48 +0200 Subject: re-add APT::Keep-Fds:: for the dpkg status-fd in dpkgpm.cc as we always need this --- apt-pkg/deb/dpkgpm.cc | 6 ++++++ apt-pkg/iprogress.cc | 9 +++++++-- apt-pkg/packagemanager.cc | 18 +++++------------- apt-private/private-install.cc | 3 +++ 4 files changed, 21 insertions(+), 15 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 36d8c829a..fbb5e4c96 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1264,6 +1264,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) _error->DumpErrors(std::cerr); _error->RevertToStack(); + // this is the dpkg status-fd, we need to keep it + _config->Set("APT::Keep-Fds::",fd[1]); + // Tell the progress that its starting and fork dpkg d->progress->Start(); pid_t Child = ExecFork(); @@ -1316,6 +1319,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (_config->FindB("DPkg::UseIoNice", false) == true) ionice(Child); + // clear the Keep-Fd again + _config->Clear("APT::Keep-Fds",fd[1]); + // Wait for dpkg int Status = 0; diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 7de190da0..bed991d68 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -8,7 +8,7 @@ #include #include #include - +#include namespace APT { namespace Progress { @@ -42,7 +42,12 @@ void PackageManagerProgressFd::WriteToStatusFd(std::string s) void PackageManagerProgressFd::Start() { - _config->Set("APT::Keep-Fds::", OutStatusFd); + if(OutStatusFd <= 0) + return; + + // FIXME: use SetCloseExec here once it taught about throwing + // exceptions instead of doing _exit(100) on failure + fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); // send status information that we are about to fork dpkg std::ostringstream status; diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 32bc5284e..3690a64c3 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -26,7 +26,6 @@ #include #include -#include #include /*}}}*/ @@ -1034,18 +1033,11 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() pkgPackageManager::OrderResult pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) { -// FIXME: port to new structure -#if 0 - if(statusFd > 0) - // FIXME: use SetCloseExec here once it taught about throwing - // exceptions instead of doing _exit(100) on failure - fcntl(statusFd,F_SETFD,FD_CLOEXEC); -#endif - bool goResult = Go(progress); - if(goResult == false) - return Failed; - - return Res; + bool goResult = Go(progress); + if(goResult == false) + return Failed; + + return Res; }; /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index d1066c869..8d72faecc 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -104,12 +104,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) if (_config->FindB("APT::Get::Simulate") == true) { pkgSimulate PM(Cache); + int status_fd = _config->FindI("APT::Status-Fd",-1); APT::Progress::PackageManager *progress = NULL; if (status_fd > 0) progress = new APT::Progress::PackageManagerProgressFd(status_fd); pkgPackageManager::OrderResult Res = PM.DoInstall(progress); delete progress; + if (Res == pkgPackageManager::Failed) return false; if (Res != pkgPackageManager::Completed) @@ -341,6 +343,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) // FIXME: make this a factory // select the right progress int status_fd = _config->FindI("APT::Status-Fd",-1); + APT::Progress::PackageManager *progress = NULL; if (status_fd > 0) progress = new APT::Progress::PackageManagerProgressFd(status_fd); -- cgit v1.2.3-70-g09d2 From 7794a6880e74446075d9cae19525829ada5b0d91 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 13 Oct 2013 19:33:09 +0200 Subject: fix progress-segfault in case of dpkg errors/prompts Errors and conffile prompts have a fourth information piece, which the "old" code access which isn't provided by the "new" one. This isn't checking if the messages are really well-formed, so it could still segfault on misformed messages, but this code needs more work anyway, so one step at a time. Closes: 726047 --- apt-pkg/deb/dpkgpm.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index c29d21574..1fbeabbdc 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -546,8 +546,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // 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 list = StringSplit(line, ": ", 3); - if(list.size() != 3) + std::vector list = StringSplit(line, ": ", 4); + if(list.size() < 3) { if (Debug == true) std::clog << "ignoring line: not enough ':'" << std::endl; -- cgit v1.2.3-70-g09d2 From fd6417a6026401f95af82608e12b4a9d105b090f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 15 Oct 2013 15:39:59 +0200 Subject: fix logic for finding what package dpkg means in the --status-fd and only send out short packagenames --- apt-pkg/deb/dpkgpm.cc | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4d812d26..61d8eec02 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -557,11 +557,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::string pkgname = list[1]; if (pkgname.find(":") == std::string::npos) { - string const nativeArch = _config->Find("APT::Architecture"); - pkgname = pkgname + ":" + nativeArch; + // 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 + pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); + 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; + } + } + } } const char* const pkg = pkgname.c_str(); const char* action = list[2].c_str(); + + std::string short_pkgname = StringSplit(pkgname, ":")[0]; // 'processing' from dpkg looks like // 'processing: action: pkg' @@ -640,7 +655,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) PackageOpsDone[pkg]++; PackagesDone++; // build the status str - status << "pmstatus:" << pkg + status << "pmstatus:" << short_pkgname << ":" << (PackagesDone/float(PackagesTotal)*100.0) << ":" << s << endl; @@ -653,7 +668,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::clog << "send: '" << status.str() << "'" << endl; } if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << pkg + std::clog << "(parsed from dpkg) pkg: " << short_pkgname << " action: " << action << endl; } /*}}}*/ -- cgit v1.2.3-70-g09d2 From 42c1513b712818823e0a136c949f0d93c46907d7 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 15 Oct 2013 18:07:44 +0200 Subject: tests, do not send pkgname with arch via the status-fd --- apt-pkg/deb/dpkgpm.cc | 2 +- test/integration/framework | 10 ++- test/integration/test-apt-progress-fd | 71 ++++++++++++++++++++++ test/integration/test-apt-progress-fd-error | 22 +++++++ .../test-apt-progress-fd-error-postinst | 22 +++++++ 5 files changed, 125 insertions(+), 2 deletions(-) create mode 100755 test/integration/test-apt-progress-fd create mode 100755 test/integration/test-apt-progress-fd-error create mode 100755 test/integration/test-apt-progress-fd-error-postinst (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d18900b9c..fe38bf697 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -649,7 +649,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // action const char *translation = _(states[PackageOpsDone[pkg]].str); char s[200]; - snprintf(s, sizeof(s), translation, pkg); + snprintf(s, sizeof(s), translation, short_pkgname.c_str()); // we moved from one dpkg state to a new one, report that PackageOpsDone[pkg]++; diff --git a/test/integration/framework b/test/integration/framework index d899bb574..0f57d0259 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -335,6 +335,7 @@ buildsimplenativepackage() { local SECTION="${7:-others}" local PRIORITY="${8:-optional}" + local FILE_TREE="$9" local DISTSECTION if [ "$SECTION" = "$(echo "$SECTION" | cut -d'/' -f 2)" ]; then DISTSECTION="main" @@ -391,9 +392,16 @@ Package: $NAME" >> ${BUILDDIR}/debian/control mkdir -p ${BUILDDIR}/debian/tmp/DEBIAN ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME} ${BUILDDIR}/debian/tmp/usr/bin cp ${BUILDDIR}/debian/copyright ${BUILDDIR}/debian/changelog ${BUILDDIR}/FEATURES ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME} cp ${BUILDDIR}/${NAME} ${BUILDDIR}/debian/tmp/usr/bin/${NAME}-${arch} + if [ -n "$FILE_TREE" ]; then + cp -ar "$FILE_TREE" ${BUILDDIR}/debian/tmp + fi + if [ -n "$POSTINST" ]; then + echo "$POSTINST" > ${BUILDDIR}/debian/tmp/DEBIAN/postinst + chmod +x ${BUILDDIR}/debian/tmp/DEBIAN/postinst + fi + (cd ${BUILDDIR}; dpkg-gencontrol -DArchitecture=$arch) (cd ${BUILDDIR}/debian/tmp; md5sum $(find usr/ -type f) > DEBIAN/md5sums) - dpkg-deb --build ${BUILDDIR}/debian/tmp ${BUILDDIR}/.. 2> /dev/null > /dev/null echo "pool/${NAME}_${VERSION}_${arch}.deb" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.pkglist done diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd new file mode 100755 index 000000000..5f73c8f8c --- /dev/null +++ b/test/integration/test-apt-progress-fd @@ -0,0 +1,71 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' 'i386' + +buildsimplenativepackage 'testing' 'amd64' '0.1' 'stable' +buildsimplenativepackage 'testing' 'amd64' '0.8.15' 'stable' +buildsimplenativepackage 'testing2' 'amd64,i386' '0.8.15' 'stable' +setupaptarchive + +# install native +exec 3> apt-progress.log +testsuccess aptget install testing=0.1 -y -o APT::Status-Fd=3 +testequal "dlstatus:1:0:Retrieving file 1 of 1 +dlstatus:1:0:Retrieving file 1 of 1 +pmstatus:dpkg-exec:0:Running dpkg +pmstatus:testing:0:Installing testing +pmstatus:testing:20:Preparing testing +pmstatus:testing:40:Unpacking testing +pmstatus:testing:60:Preparing to configure testing +pmstatus:dpkg-exec:60:Running dpkg +pmstatus:testing:60:Configuring testing +pmstatus:testing:80:Configuring testing +pmstatus:testing:100:Installed testing" cat apt-progress.log + +# upgrade +exec 3> apt-progress.log +testsuccess aptget install testing=0.8.15 -y -o APT::Status-Fd=3 +testequal "dlstatus:1:0:Retrieving file 1 of 1 +dlstatus:1:0:Retrieving file 1 of 1 +pmstatus:dpkg-exec:0:Running dpkg +pmstatus:testing:20:Preparing testing +pmstatus:testing:40:Unpacking testing +pmstatus:testing:60:Preparing to configure testing +pmstatus:dpkg-exec:60:Running dpkg +pmstatus:testing:60:Configuring testing +pmstatus:testing:80:Configuring testing +pmstatus:testing:100:Installed testing" cat apt-progress.log + +# and remove +exec 3> apt-progress.log +testsuccess aptget remove testing -y -o APT::Status-Fd=3 +testequal "pmstatus:dpkg-exec:0:Running dpkg +pmstatus:testing:0:Removing testing +pmstatus:testing:33.3333:Preparing for removal of testing +pmstatus:testing:66.6667:Removing testing +pmstatus:testing:100:Removed testing" cat apt-progress.log + + +# install non-native and ensure we get proper progress info +exec 3> apt-progress.log +testsuccess aptget install testing2:i386 -y -o APT::Status-Fd=3 + +# and compare +testequal "dlstatus:1:0:Retrieving file 1 of 1 +dlstatus:1:0:Retrieving file 1 of 1 +pmstatus:dpkg-exec:0:Running dpkg +pmstatus:testing2:0:Installing testing2 +pmstatus:testing2:20:Preparing testing2 +pmstatus:testing2:40:Unpacking testing2 +pmstatus:testing2:60:Preparing to configure testing2 +pmstatus:dpkg-exec:60:Running dpkg +pmstatus:testing2:60:Configuring testing2 +pmstatus:testing2:80:Configuring testing2 +pmstatus:testing2:100:Installed testing2" cat apt-progress.log + +rm -f apt-progress*.log \ No newline at end of file diff --git a/test/integration/test-apt-progress-fd-error b/test/integration/test-apt-progress-fd-error new file mode 100755 index 000000000..0cd59410e --- /dev/null +++ b/test/integration/test-apt-progress-fd-error @@ -0,0 +1,22 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' 'i386' + +mkdir -p usr/bin +touch usr/bin/file-conflict + +buildsimplenativepackage 'foo1' 'amd64,i386' '0.8.15' 'stable' '' 'pkg with file conflicts' '' '' 'usr/' +buildsimplenativepackage 'foo2' 'amd64,i386' '0.8.15' 'stable' '' 'pkg with file conflicts' '' '' 'usr/' + +setupaptarchive + +exec 3> apt-progress.log +testfailure aptget install foo1 foo2 -y -o APT::Status-Fd=3 +msgtest "Ensure correct error message" +grep -q "aptarchive/pool/foo2_0.8.15_amd64.deb :40:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log && msgpass || msgfail + diff --git a/test/integration/test-apt-progress-fd-error-postinst b/test/integration/test-apt-progress-fd-error-postinst new file mode 100755 index 000000000..0b6e70212 --- /dev/null +++ b/test/integration/test-apt-progress-fd-error-postinst @@ -0,0 +1,22 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' 'i386' + +mkdir -p DEBIAN/ +echo "#!/bin/sh\nexit 1" > DEBIAN/postinst +chmod 755 DEBIAN/postinst + +buildsimplenativepackage 'postinst-error' 'amd64,i386' '0.8.15' 'stable' '' 'pkg with posinst error' '' '' './DEBIAN' + +setupaptarchive + +exec 3> apt-progress.log +testfailure aptget install postinst-error -y -o APT::Status-Fd=3 +msgtest "Ensure correct error message for postinst error" +grep -q "pmerror:postinst-error :80:subprocess installed post-installation script returned error exit status 2" apt-progress.log && msgpass || msgfail + -- cgit v1.2.3-70-g09d2 From c420fe0096985234e861aaafc2b9908b6259a1bb Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 17 Oct 2013 07:47:15 +0200 Subject: fix broken clean when apt was finished and ensure that terminal progress is updated when a new dpkg-loop is entered in dpkgpm.cc --- apt-pkg/deb/dpkgpm.cc | 28 +++++++++++++++++++--------- apt-pkg/deb/dpkgpm.h | 1 + 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index fe38bf697..f870fab93 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -993,6 +993,20 @@ void pkgDPkgPM::SetupTerminalScrollArea(int nr_rows) std::flush(std::cout); } +void pkgDPkgPM::CleanupTerminal() +{ + // reset scroll area + SetupTerminalScrollArea(d->nr_terminal_rows + 1); + if(d->fancy_progress_output) + { + // override the progress line (sledgehammer) + static const char* clear_screen_below_cursor = "\033[J"; + std::cout << clear_screen_below_cursor; + std::flush(std::cout); + } +} + + // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -1430,7 +1444,9 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } + // setup terminal SetupTerminalScrollArea(d->nr_terminal_rows); + SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1525,15 +1541,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGHUP,old_SIGHUP); - // reset scroll area - SetupTerminalScrollArea(d->nr_terminal_rows + 1); - if(d->fancy_progress_output) - { - // override the progress line (sledgehammer) - static const char* clear_screen_below_cursor = "\033[J"; - std::cout << clear_screen_below_cursor; - } - if(master >= 0) { tcsetattr(0, TCSAFLUSH, &tt); @@ -1564,6 +1571,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(stopOnError) { CloseLog(); + CleanupTerminal(); return false; } } @@ -1574,6 +1582,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(_config->FindB("DPkgPM::Progress", false) == true) SendTerminalProgress(100); + CleanupTerminal(); + if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 3b8d36623..1a58e1af5 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -87,6 +87,7 @@ class pkgDPkgPM : public pkgPackageManager // Terminal progress void SetupTerminalScrollArea(int nr_scrolled_rows); void SendTerminalProgress(float percentage); + void CleanupTerminal(); // apport integration void WriteApportReport(const char *pkgpath, const char *errormsg); -- cgit v1.2.3-70-g09d2 From 7c016f6e107ba55d7b55870166273ce63c4ecb65 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 17 Oct 2013 08:18:09 +0200 Subject: ensure that short-name -> long-name detection for dpkg-status works for reinstalls too --- apt-pkg/deb/dpkgpm.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 1b234c0ed..19de44001 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -561,7 +561,9 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) pkgCache::PkgIterator P = Grp.PackageList(); for (; P.end() != true; P = Grp.NextPkg(P)) { - if(Cache[P].Mode != pkgDepCache::ModeKeep) + if(Cache[P].Install() || Cache[P].ReInstall() || + Cache[P].Upgrade() || Cache[P].Downgrade() || + Cache[P].Delete() || Cache[P].Purge()) { pkgname = P.FullName(); break; @@ -569,6 +571,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) } } } + const char* const pkg = pkgname.c_str(); const char* action = list[2].c_str(); -- cgit v1.2.3-70-g09d2 From dd640f3cece45693b57b49d90ba7cc4134577070 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 08:02:29 +0200 Subject: cleanup --- apt-pkg/deb/dpkgpm.cc | 104 +++++++++++++++++++++++----------- apt-pkg/deb/dpkgpm.h | 3 +- apt-pkg/iprogress.cc | 2 +- test/integration/test-apt-progress-fd | 46 +++++++-------- 4 files changed, 97 insertions(+), 58 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 19de44001..7fba04a30 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -507,6 +507,34 @@ void pkgDPkgPM::DoTerminalPty(int master) fwrite(term_buf, len, sizeof(char), d->term_out); } /*}}}*/ + +std::string pkgDPkgPM::ExpandShortPackageName(pkgDepCache &Cache, + const std::string &short_pkgname) +{ + if (short_pkgname.find(":") != string::npos) + return short_pkgname; + + std::string pkgname = short_pkgname; + // 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 + pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); + if (Grp.end() == false) + { + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if(Cache[P].Install() || Cache[P].ReInstall() || + Cache[P].Upgrade() || Cache[P].Downgrade() || + Cache[P].Delete() || Cache[P].Purge()) + { + pkgname = P.FullName(); + return pkgname; + } + } + } + return pkgname; +} + // DPkgPM::ProcessDpkgStatusBuf /*{{{*/ // --------------------------------------------------------------------- /* @@ -549,32 +577,35 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) std::clog << "ignoring line: not enough ':'" << std::endl; return; } - // 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) + + if (list[0] != "processing" && list[0] != "status") { - // 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 - pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); - if (Grp.end() == false) - { - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if(Cache[P].Install() || Cache[P].ReInstall() || - Cache[P].Upgrade() || Cache[P].Downgrade() || - Cache[P].Delete() || Cache[P].Purge()) - { - pkgname = P.FullName(); - break; - } - } - } + if (Debug == true) + std::clog << "ignoring line: unknown prefix '" << list[0] << "'" + << std::endl; + return; + } + + std::string prefix = list[0]; + std::string pkgname; + std::string action; + if (prefix == "processing") + { + action = list[1]; + pkgname = list[2]; + if (action != "install" && action != "configure" && + action != "remove" && action != "purge" && + action != "disappear") + return; + } else if (prefix == "status") { + pkgname = list[1]; + action = list[2]; } + // dpkg does not always send out the architecture so we need to guess + // it here + pkgname = ExpandShortPackageName(Cache, pkgname); const char* const pkg = pkgname.c_str(); - const char* action = list[2].c_str(); - std::string short_pkgname = StringSplit(pkgname, ":")[0]; std::string i18n_pkgname = short_pkgname; if (pkgname.find(":") != string::npos) @@ -587,48 +618,52 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // 'processing: action: pkg' if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) { - const char* const pkg_or_trigger = list[2].c_str(); - action = list[1].c_str(); const std::pair * const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, - MatchProcessingOp(action)); + MatchProcessingOp(action.c_str())); if(iter == PackageProcessingOpsEnd) { if (Debug == true) std::clog << "ignoring unknown action: " << action << std::endl; return; } + std::string pkg_action; - strprintf(pkg_action, _(iter->second), pkg_or_trigger); + strprintf(pkg_action, _(iter->second), short_pkgname.c_str()); - d->progress->StatusChanged(pkg_or_trigger, PackagesDone, PackagesTotal, + d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, pkg_action); - if (strncmp(action, "disappear", strlen("disappear")) == 0) - handleDisappearAction(pkg_or_trigger); + + if (strncmp(action.c_str(), "disappear", strlen("disappear")) == 0) + handleDisappearAction(pkgname); return; } - if(strncmp(action,"error",strlen("error")) == 0) + // FIXME: fix indent once this goes into debian/sid + if(strncmp(prefix.c_str(), "status", strlen("processing")) == 0) + { + + if(strncmp(action.c_str(),"error",strlen("error")) == 0) { d->progress->Error(list[1], PackagesDone, PackagesTotal, list[3]); pkgFailures++; WriteApportReport(list[1].c_str(), list[3].c_str()); return; } - else if(strncmp(action,"conffile",strlen("conffile")) == 0) + else if(strncmp(action.c_str(),"conffile",strlen("conffile")) == 0) { d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, list[3]); return; - } + } else { vector 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 && (strcmp(action, next_action) == 0)) + if(next_action && (strcmp(action.c_str(), next_action) == 0)) { // only read the translation if there is actually a next // action @@ -644,9 +679,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, translation); } + if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << pkgname << " action: " << action << endl; + } + } } /*}}}*/ // DPkgPM::handleDisappearAction /*{{{*/ diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 302507105..922631ba8 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -84,11 +84,12 @@ class pkgDPkgPM : public pkgPackageManager __deprecated bool SendV2Pkgs(FILE *F); bool SendPkgsInfo(FILE * const F, unsigned int const &Version); void WriteHistoryTag(std::string const &tag, std::string value); + std::string ExpandShortPackageName(pkgDepCache &Cache, + const std::string &short_pkgname); // Terminal progress void SetupTerminalScrollArea(int nr_scrolled_rows); void SendTerminalProgress(float percentage); - void CleanupTerminal(); // apport integration void WriteApportReport(const char *pkgpath, const char *errormsg); diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index bed991d68..318d626d4 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -101,7 +101,7 @@ bool PackageManagerProgressFd::StatusChanged(std::string PackageName, // build the status str std::ostringstream status; - status << "pmstatus:" << PackageName + status << "pmstatus:" << StringSplit(PackageName, ":")[0] << ":" << (StepsDone/float(StepsTotal)*100.0) << ":" << pkg_action << std::endl; diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index 5f73c8f8c..cdf8d4a23 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -18,14 +18,14 @@ testsuccess aptget install testing=0.1 -y -o APT::Status-Fd=3 testequal "dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing:0:Installing testing -pmstatus:testing:20:Preparing testing -pmstatus:testing:40:Unpacking testing +pmstatus:testing:0:Installing testing (amd64) +pmstatus:testing:20:Preparing testing (amd64) +pmstatus:testing:40:Unpacking testing (amd64) pmstatus:testing:60:Preparing to configure testing pmstatus:dpkg-exec:60:Running dpkg -pmstatus:testing:60:Configuring testing -pmstatus:testing:80:Configuring testing -pmstatus:testing:100:Installed testing" cat apt-progress.log +pmstatus:testing:60:Configuring testing (amd64) +pmstatus:testing:80:Configuring testing (amd64) +pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log # upgrade exec 3> apt-progress.log @@ -33,22 +33,22 @@ testsuccess aptget install testing=0.8.15 -y -o APT::Status-Fd=3 testequal "dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing:20:Preparing testing -pmstatus:testing:40:Unpacking testing +pmstatus:testing:20:Preparing testing (amd64) +pmstatus:testing:40:Unpacking testing (amd64) pmstatus:testing:60:Preparing to configure testing pmstatus:dpkg-exec:60:Running dpkg -pmstatus:testing:60:Configuring testing -pmstatus:testing:80:Configuring testing -pmstatus:testing:100:Installed testing" cat apt-progress.log +pmstatus:testing:60:Configuring testing (amd64) +pmstatus:testing:80:Configuring testing (amd64) +pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log # and remove exec 3> apt-progress.log testsuccess aptget remove testing -y -o APT::Status-Fd=3 testequal "pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing:0:Removing testing -pmstatus:testing:33.3333:Preparing for removal of testing -pmstatus:testing:66.6667:Removing testing -pmstatus:testing:100:Removed testing" cat apt-progress.log +pmstatus:testing:0:Removing testing (amd64) +pmstatus:testing:33.3333:Preparing for removal of testing (amd64) +pmstatus:testing:66.6667:Removing testing (amd64) +pmstatus:testing:100:Removed testing (amd64)" cat apt-progress.log # install non-native and ensure we get proper progress info @@ -59,13 +59,13 @@ testsuccess aptget install testing2:i386 -y -o APT::Status-Fd=3 testequal "dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg -pmstatus:testing2:0:Installing testing2 -pmstatus:testing2:20:Preparing testing2 -pmstatus:testing2:40:Unpacking testing2 -pmstatus:testing2:60:Preparing to configure testing2 +pmstatus:testing2:0:Installing testing2 (i386) +pmstatus:testing2:20:Preparing testing2 (i386) +pmstatus:testing2:40:Unpacking testing2 (i386) +pmstatus:testing2:60:Preparing to configure testing2 (i386) pmstatus:dpkg-exec:60:Running dpkg -pmstatus:testing2:60:Configuring testing2 -pmstatus:testing2:80:Configuring testing2 -pmstatus:testing2:100:Installed testing2" cat apt-progress.log +pmstatus:testing2:60:Configuring testing2 (i386) +pmstatus:testing2:80:Configuring testing2 (i386) +pmstatus:testing2:100:Installed testing2 (i386)" cat apt-progress.log -rm -f apt-progress*.log \ No newline at end of file +rm -f apt-progress*.log -- cgit v1.2.3-70-g09d2 From 2842f8f3e31fbec8c53ce40f15ff0c76f021f030 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 08:10:29 +0200 Subject: add APT::String::Strip(), start cleanup of ProcessDpkgStatusLine --- apt-pkg/contrib/strutl.cc | 17 ++++++++++++++++- apt-pkg/contrib/strutl.h | 7 +++++++ apt-pkg/deb/dpkgpm.cc | 33 ++++++++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 6 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 77e48962c..9f794927d 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -36,7 +36,22 @@ using namespace std; /*}}}*/ - +// Strip - Remove white space from the front and back of a string /*{{{*/ +// --------------------------------------------------------------------- +namespace APT { + namespace String { +std::string Strip(const std::string &s) +{ + size_t start = s.find_first_not_of(" \t\n"); + // only whitespace + if (start == string::npos) + return ""; + size_t end = s.find_last_not_of(" \t\n"); + return s.substr(start, end-start+1); +} +} +} + /*}}}*/ // UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/ // --------------------------------------------------------------------- /* This is handy to use before display some information for enduser */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index b42e06491..c8fc317c0 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -33,6 +33,13 @@ using std::vector; using std::ostream; #endif +namespace APT { + namespace String { + std::string Strip(const std::string &s); + }; +}; + + bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest); char *_strstrip(char *String); char *_strrstrip(char *String); // right strip only diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index f870fab93..c5d40c033 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -540,6 +540,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) 'processing: trigproc: trigger' */ + // we need to split on ": " (note the appended space) as the ':' is // part of the pkgname:arch information that dpkg sends // @@ -553,8 +554,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::clog << "ignoring line: not enough ':'" << std::endl; return; } + + std::string prefix = APT::String::Strip(list[0]); + std::string pkgname; + std::string action_str; + if (prefix == "processing") + { + pkgname = APT::String::Strip(list[2]); + action_str = APT::String::Strip(list[1]); + } + else if (prefix == "status") + { + pkgname = APT::String::Strip(list[1]); + action_str = APT::String::Strip(list[2]); + } else { + if (Debug == true) + std::clog << "unknown prefix '" << prefix << "'" << std::endl; + return; + } + // 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) { // find the package in the group that is in a touched by dpkg @@ -574,13 +593,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) } } const char* const pkg = pkgname.c_str(); - const char* action = list[2].c_str(); - + const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; // 'processing' from dpkg looks like // 'processing: action: pkg' - if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) + if(prefix == "processing") { char s[200]; const char* const pkg_or_trigger = list[2].c_str(); @@ -609,7 +627,11 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (strncmp(action, "disappear", strlen("disappear")) == 0) handleDisappearAction(pkg_or_trigger); return; - } + } + + // FIXME: fix indent once the progress-refactor branch is merged + if (prefix == "status") + { if(strncmp(action,"error",strlen("error")) == 0) { @@ -670,6 +692,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << short_pkgname << " action: " << action << endl; + } } /*}}}*/ // DPkgPM::handleDisappearAction /*{{{*/ -- cgit v1.2.3-70-g09d2 From 11ef54810d6241b6d2433d27099b43763dabaee3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 08:32:36 +0200 Subject: reshuffle dpkgpm.cc code a bit more --- apt-pkg/deb/dpkgpm.cc | 68 +++++++++++++++++------------ test/integration/test-apt-progress-fd-error | 2 +- 2 files changed, 41 insertions(+), 29 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index c5d40c033..41885e6e8 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -555,6 +555,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } + // build the (prefix, pkgname, action) tuple, position of this + // is different for "processing" or "status" messages std::string prefix = APT::String::Strip(list[0]); std::string pkgname; std::string action_str; @@ -573,6 +575,38 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } + // FIXME: fix indent once the progress-refactor branch is merged + if (prefix == "status") + { + + if(action_str == "error") + { + status << "pmerror:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + pkgFailures++; + WriteApportReport(list[1].c_str(), list[3].c_str()); + return; + } + else if(action_str == "conffile") + { + status << "pmconffile:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + return; + } + } + // dpkg does not send always send "pkgname:arch" so we add it here if needed if (pkgname.find(":") == std::string::npos) { @@ -595,6 +629,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) const char* const pkg = pkgname.c_str(); const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; + std::string arch = ""; + if (pkgname.find(":") != string::npos) + arch = StringSplit(pkgname, ":")[1]; + std::string i18n_pkgname = pkgname; + if (arch.size() != 0) + strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), arch.c_str()); // 'processing' from dpkg looks like // 'processing: action: pkg' @@ -629,37 +669,9 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } - // FIXME: fix indent once the progress-refactor branch is merged if (prefix == "status") { - if(strncmp(action,"error",strlen("error")) == 0) - { - status << "pmerror:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); - return; - } - else if(strncmp(action,"conffile",strlen("conffile")) == 0) - { - status << "pmconffile:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - return; - } - vector const &states = PackageOps[pkg]; const char *next_action = NULL; if(PackageOpsDone[pkg] < states.size()) diff --git a/test/integration/test-apt-progress-fd-error b/test/integration/test-apt-progress-fd-error index 0cd59410e..96d66371a 100755 --- a/test/integration/test-apt-progress-fd-error +++ b/test/integration/test-apt-progress-fd-error @@ -18,5 +18,5 @@ setupaptarchive exec 3> apt-progress.log testfailure aptget install foo1 foo2 -y -o APT::Status-Fd=3 msgtest "Ensure correct error message" -grep -q "aptarchive/pool/foo2_0.8.15_amd64.deb :40:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log && msgpass || msgfail +grep -q "aptarchive/pool/foo2_0.8.15_amd64.deb :40:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log && msgpass || (cat apt-progress.log && msgfail) -- cgit v1.2.3-70-g09d2 From 27ede340880968cad79b5cc675f283480eb046f4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 09:28:08 +0200 Subject: reshuffle the pkgDPkgPM::ProcessDpkgStatusLine() some more to make it more robust --- apt-pkg/deb/dpkgpm.cc | 168 +++++++++++++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 77 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 41885e6e8..b5d314165 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -516,29 +516,15 @@ void pkgDPkgPM::DoTerminalPty(int master) void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) { bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false); - // the status we output - ostringstream status; - if (Debug == true) std::clog << "got from dpkg '" << line << "'" << std::endl; - /* dpkg sends strings like this: 'status: : ' 'status: :: ' - 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 - 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited - Newer versions of dpkg sent also: - 'processing: install: pkg' - 'processing: configure: pkg' - 'processing: remove: pkg' - 'processing: purge: pkg' - 'processing: disappear: pkg' - 'processing: trigproc: trigger' - + 'processing: {install,configure,remove,purge,disappear,trigproc}: pkg' + 'processing: {install,configure,remove,purge,disappear,trigproc}: trigger' */ // we need to split on ": " (note the appended space) as the ':' is @@ -560,11 +546,30 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) std::string prefix = APT::String::Strip(list[0]); std::string pkgname; std::string action_str; + ostringstream status; + + // "processing" has the form "processing: action: pkg or trigger" + // with action = ["install", "configure", "remove", "purge", "disappear", + // "trigproc"] if (prefix == "processing") { pkgname = APT::String::Strip(list[2]); action_str = APT::String::Strip(list[1]); + + // this is what we support in the processing stage + if(action_str != "install" && action_str != "configure" && + action_str != "remove" && action_str != "purge" && + action_str != "purge") + { + if (Debug == true) + std::clog << "ignoring processing action: '" << action_str + << "'" << std::endl; + return; + } } + // "status" has the form: "status: pkg: state" + // with state in ["half-installed", "unpacked", "half-configured", + // "installed", "config-files", "not-installed"] else if (prefix == "status") { pkgname = APT::String::Strip(list[1]); @@ -575,38 +580,47 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) return; } - // FIXME: fix indent once the progress-refactor branch is merged - if (prefix == "status") - { - if(action_str == "error") - { - status << "pmerror:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); - return; - } - else if(action_str == "conffile") + /* handle the special cases first: + + 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 + 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited + */ + if (prefix == "status") { - status << "pmconffile:" << list[1] - << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << list[3] - << endl; - if(OutStatusFd > 0) - FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); - if (Debug == true) - std::clog << "send: '" << status.str() << "'" << endl; - return; - } + if(action_str == "error") + { + status << "pmerror:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + pkgFailures++; + WriteApportReport(list[1].c_str(), list[3].c_str()); + return; + } + else if(action_str == "conffile") + { + status << "pmconffile:" << list[1] + << ":" << (PackagesDone/float(PackagesTotal)*100.0) + << ":" << list[3] + << endl; + if(OutStatusFd > 0) + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); + if (Debug == true) + std::clog << "send: '" << status.str() << "'" << endl; + 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 if (pkgname.find(":") == std::string::npos) { @@ -626,6 +640,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) } } } + const char* const pkg = pkgname.c_str(); const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; @@ -671,39 +686,38 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (prefix == "status") { - - vector 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 && (strcmp(action, next_action) == 0)) - { - // only read the translation if there is actually a next - // action - const char *translation = _(states[PackageOpsDone[pkg]].str); - char s[200]; - snprintf(s, sizeof(s), translation, short_pkgname.c_str()); - - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; - // build the status str - status << "pmstatus:" << short_pkgname - << ":" << (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) - std::clog << "send: '" << status.str() << "'" << endl; - } - if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << short_pkgname - << " action: " << action << endl; + vector 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 && (strcmp(action, next_action) == 0)) + { + // only read the translation if there is actually a next + // action + const char *translation = _(states[PackageOpsDone[pkg]].str); + char s[200]; + snprintf(s, sizeof(s), translation, short_pkgname.c_str()); + + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + PackagesDone++; + // build the status str + status << "pmstatus:" << short_pkgname + << ":" << (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) + std::clog << "send: '" << status.str() << "'" << endl; + } + if (Debug == true) + std::clog << "(parsed from dpkg) pkg: " << short_pkgname + << " action: " << action << endl; } } /*}}}*/ -- cgit v1.2.3-70-g09d2 From fa300ed15fc5a1d9e146c85d45f0a88b1d7f96bf Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 09:40:05 +0200 Subject: use std::string instead of char* in pkgDPkgPM::ProcessDpkgStatusLine() --- apt-pkg/deb/dpkgpm.cc | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b5d314165..0ebd9f28b 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -545,7 +545,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // is different for "processing" or "status" messages std::string prefix = APT::String::Strip(list[0]); std::string pkgname; - std::string action_str; + std::string action; ostringstream status; // "processing" has the form "processing: action: pkg or trigger" @@ -554,15 +554,14 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if (prefix == "processing") { pkgname = APT::String::Strip(list[2]); - action_str = APT::String::Strip(list[1]); + action = APT::String::Strip(list[1]); // this is what we support in the processing stage - if(action_str != "install" && action_str != "configure" && - action_str != "remove" && action_str != "purge" && - action_str != "purge") + if(action != "install" && action != "configure" && + action != "remove" && action != "purge" && action != "purge") { if (Debug == true) - std::clog << "ignoring processing action: '" << action_str + std::clog << "ignoring processing action: '" << action << "'" << std::endl; return; } @@ -573,7 +572,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) else if (prefix == "status") { pkgname = APT::String::Strip(list[1]); - action_str = APT::String::Strip(list[2]); + action = APT::String::Strip(list[2]); } else { if (Debug == true) std::clog << "unknown prefix '" << prefix << "'" << std::endl; @@ -590,7 +589,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) */ if (prefix == "status") { - if(action_str == "error") + if(action == "error") { status << "pmerror:" << list[1] << ":" << (PackagesDone/float(PackagesTotal)*100.0) @@ -604,7 +603,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) WriteApportReport(list[1].c_str(), list[3].c_str()); return; } - else if(action_str == "conffile") + else if(action == "conffile") { status << "pmconffile:" << list[1] << ":" << (PackagesDone/float(PackagesTotal)*100.0) @@ -621,7 +620,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // 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 send 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 @@ -642,7 +642,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) } const char* const pkg = pkgname.c_str(); - const char* action = action_str.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; std::string arch = ""; if (pkgname.find(":") != string::npos) @@ -655,32 +654,33 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // 'processing: action: pkg' if(prefix == "processing") { - char s[200]; - const char* const pkg_or_trigger = list[2].c_str(); - action = list[1].c_str(); const std::pair * const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, - MatchProcessingOp(action)); + MatchProcessingOp(action.c_str())); if(iter == PackageProcessingOpsEnd) { if (Debug == true) std::clog << "ignoring unknown action: " << action << std::endl; return; } - snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger); + std::string msg; + strprintf(msg, _(iter->second), short_pkgname.c_str()); - status << "pmstatus:" << pkg_or_trigger + status << "pmstatus:" << short_pkgname << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s + << ":" << msg << endl; if(OutStatusFd > 0) FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; - if (strncmp(action, "disappear", strlen("disappear")) == 0) - handleDisappearAction(pkg_or_trigger); + // FIXME: this needs a muliarch testcase + // FIXME2: is "pkgname" here reliable with dpkg only sending us + // short pkgnames? + if (action == "disappear") + handleDisappearAction(pkgname); return; } @@ -691,13 +691,13 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) if(PackageOpsDone[pkg] < states.size()) next_action = states[PackageOpsDone[pkg]].state; // check if the package moved to the next dpkg state - if(next_action && (strcmp(action, next_action) == 0)) + if(next_action && (action == next_action)) { // only read the translation if there is actually a next // action const char *translation = _(states[PackageOpsDone[pkg]].str); - char s[200]; - snprintf(s, sizeof(s), translation, short_pkgname.c_str()); + std::string msg; + strprintf(msg, translation, short_pkgname.c_str()); // we moved from one dpkg state to a new one, report that PackageOpsDone[pkg]++; @@ -705,7 +705,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) // build the status str status << "pmstatus:" << short_pkgname << ":" << (PackagesDone/float(PackagesTotal)*100.0) - << ":" << s + << ":" << msg << endl; if(_config->FindB("DPkgPM::Progress", false) == true) SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); -- cgit v1.2.3-70-g09d2 From 34d6563ef47b455b69a7bc9ad0838902bb911dea Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 15:56:06 +0200 Subject: merged debian/sid --- apt-pkg/deb/dpkgpm.cc | 257 +++++++++++++++++++++++++------------------------- 1 file changed, 127 insertions(+), 130 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 7fba04a30..b5f858022 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -55,14 +55,13 @@ class pkgDPkgPMPrivate public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), - last_reported_progress(0.0), progress(NULL) + progress(NULL) { dpkgbuf[0] = '\0'; } ~pkgDPkgPMPrivate() { } - bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading char dpkgbuf[1024]; @@ -70,8 +69,6 @@ public: FILE *term_out; FILE *history_out; string dpkg_error; - - float last_reported_progress; APT::Progress::PackageManager *progress; }; @@ -507,34 +504,6 @@ void pkgDPkgPM::DoTerminalPty(int master) fwrite(term_buf, len, sizeof(char), d->term_out); } /*}}}*/ - -std::string pkgDPkgPM::ExpandShortPackageName(pkgDepCache &Cache, - const std::string &short_pkgname) -{ - if (short_pkgname.find(":") != string::npos) - return short_pkgname; - - std::string pkgname = short_pkgname; - // 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 - pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); - if (Grp.end() == false) - { - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if(Cache[P].Install() || Cache[P].ReInstall() || - Cache[P].Upgrade() || Cache[P].Downgrade() || - Cache[P].Delete() || Cache[P].Purge()) - { - pkgname = P.FullName(); - return pkgname; - } - } - } - return pkgname; -} - // DPkgPM::ProcessDpkgStatusBuf /*{{{*/ // --------------------------------------------------------------------- /* @@ -542,28 +511,17 @@ std::string pkgDPkgPM::ExpandShortPackageName(pkgDepCache &Cache, void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false); - if (Debug == true) std::clog << "got from dpkg '" << line << "'" << std::endl; - /* dpkg sends strings like this: 'status: : ' 'status: :: ' - 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 - 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited - Newer versions of dpkg sent also: - 'processing: install: pkg' - 'processing: configure: pkg' - 'processing: remove: pkg' - 'processing: purge: pkg' - 'processing: disappear: pkg' - 'processing: trigproc: trigger' - + 'processing: {install,configure,remove,purge,disappear,trigproc}: pkg' + 'processing: {install,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 // @@ -578,45 +536,106 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) return; } - if (list[0] != "processing" && list[0] != "status") + // build the (prefix, pkgname, action) tuple, position of this + // is different for "processing" or "status" messages + std::string prefix = APT::String::Strip(list[0]); + std::string pkgname; + std::string action; + ostringstream status; + + // "processing" has the form "processing: action: pkg or trigger" + // with action = ["install", "configure", "remove", "purge", "disappear", + // "trigproc"] + if (prefix == "processing") + { + pkgname = APT::String::Strip(list[2]); + action = APT::String::Strip(list[1]); + + // this is what we support in the processing stage + if(action != "install" && action != "configure" && + action != "remove" && action != "purge" && action != "purge") + { + if (Debug == true) + std::clog << "ignoring processing action: '" << action + << "'" << std::endl; + return; + } + } + // "status" has the form: "status: pkg: state" + // with state in ["half-installed", "unpacked", "half-configured", + // "installed", "config-files", "not-installed"] + else if (prefix == "status") { + pkgname = APT::String::Strip(list[1]); + action = APT::String::Strip(list[2]); + } else { if (Debug == true) - std::clog << "ignoring line: unknown prefix '" << list[0] << "'" - << std::endl; + std::clog << "unknown prefix '" << prefix << "'" << std::endl; return; } - std::string prefix = list[0]; - std::string pkgname; - std::string action; - if (prefix == "processing") + + /* handle the special cases first: + + 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 + 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited + */ + if (prefix == "status") { - action = list[1]; - pkgname = list[2]; - if (action != "install" && action != "configure" && - action != "remove" && action != "purge" && - action != "disappear") + if(action == "error") + { + d->progress->Error(list[1], PackagesDone, PackagesTotal, + list[3]); + pkgFailures++; + WriteApportReport(list[1].c_str(), list[3].c_str()); + return; + } + else if(action == "conffile") + { + d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, + list[3]); return; - } else if (prefix == "status") { - pkgname = list[1]; - action = list[2]; + } } - // dpkg does not always send out the architecture so we need to guess - // it here - pkgname = ExpandShortPackageName(Cache, pkgname); + // 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 + 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 + pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname); + 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; + } + } + } + } + const char* const pkg = pkgname.c_str(); std::string short_pkgname = StringSplit(pkgname, ":")[0]; - std::string i18n_pkgname = short_pkgname; + std::string arch = ""; if (pkgname.find(":") != string::npos) - { - strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), - StringSplit(pkgname, ":")[1].c_str()); - } + arch = StringSplit(pkgname, ":")[1]; + std::string i18n_pkgname = pkgname; + if (arch.size() != 0) + strprintf(i18n_pkgname, "%s (%s)", short_pkgname.c_str(), arch.c_str()); // 'processing' from dpkg looks like // 'processing: action: pkg' - if(strncmp(list[0].c_str(), "processing", strlen("processing")) == 0) + if(prefix == "processing") { const std::pair * const iter = std::find_if(PackageProcessingOpsBegin, @@ -628,62 +647,41 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) std::clog << "ignoring unknown action: " << action << std::endl; return; } - - std::string pkg_action; - strprintf(pkg_action, _(iter->second), short_pkgname.c_str()); - - d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, - pkg_action); - - if (strncmp(action.c_str(), "disappear", strlen("disappear")) == 0) + std::string msg; + strprintf(msg, _(iter->second), i18n_pkgname.c_str()); + d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); + + // FIXME: this needs a muliarch testcase + // FIXME2: is "pkgname" here reliable with dpkg only sending us + // short pkgnames? + if (action == "disappear") handleDisappearAction(pkgname); return; - } - - // FIXME: fix indent once this goes into debian/sid - if(strncmp(prefix.c_str(), "status", strlen("processing")) == 0) - { - - if(strncmp(action.c_str(),"error",strlen("error")) == 0) - { - d->progress->Error(list[1], PackagesDone, PackagesTotal, list[3]); - pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); - return; - } - else if(strncmp(action.c_str(),"conffile",strlen("conffile")) == 0) - { - d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, - list[3]); - return; - } else { + } - vector 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 && (strcmp(action.c_str(), next_action) == 0)) + if (prefix == "status") { - // only read the translation if there is actually a next - // action - std::string translation; - strprintf(translation, _(states[PackageOpsDone[pkg]].str), - i18n_pkgname.c_str()); - - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; - - // and send to the progress - d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, - translation); - } - - if (Debug == true) - std::clog << "(parsed from dpkg) pkg: " << pkgname - << " action: " << action << endl; - } + vector 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; + strprintf(msg, translation, i18n_pkgname.c_str()); + d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); + + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + PackagesDone++; + } + if (Debug == true) + std::clog << "(parsed from dpkg) pkg: " << short_pkgname + << " action: " << action << endl; } } /*}}}*/ @@ -919,6 +917,8 @@ 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 @@ -938,18 +938,16 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, sigprocmask(SIG_SETMASK, &origmask, 0); return retval; } -/*}}}*/ - - + /*}}}*/ // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* 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 * through to human readable (and i10n-able) * names and calculates a percentage for each step. -*/ + */ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { pkgPackageManager::SigINTStop = false; @@ -1331,7 +1329,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) // this is the dpkg status-fd, we need to keep it _config->Set("APT::Keep-Fds::",fd[1]); - // Tell the progress that its starting and fork dpkg + // Tell the progress that its starting and fork dpkg // FIXME: this is called once per dpkg run which is *too often* d->progress->Start(); @@ -1372,7 +1370,6 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } - /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ putenv((char *)"DPKG_NO_TSTP=yes"); @@ -1441,6 +1438,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv, &original_sigmask); + d->progress->Pulse(); if (select_ret == 0) @@ -1509,7 +1507,6 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) d->progress->StatusChanged("", PackagesDone, PackagesTotal, ""); d->progress->Stop(); - if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); -- cgit v1.2.3-70-g09d2 From 65dbd5a1a32f63dae81c8b5814cd246f1154c38d Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 18 Oct 2013 18:26:56 +0200 Subject: re-add missing APT::String::Strip --- apt-pkg/contrib/strutl.cc | 17 ++++++++++++++++- apt-pkg/contrib/strutl.h | 7 +++++++ apt-pkg/deb/dpkgpm.cc | 7 ++++--- apt-pkg/iprogress.cc | 8 ++++++++ apt-pkg/iprogress.h | 2 +- test/integration/test-apt-progress-fd | 1 - 6 files changed, 36 insertions(+), 6 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 77e48962c..9f794927d 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -36,7 +36,22 @@ using namespace std; /*}}}*/ - +// Strip - Remove white space from the front and back of a string /*{{{*/ +// --------------------------------------------------------------------- +namespace APT { + namespace String { +std::string Strip(const std::string &s) +{ + size_t start = s.find_first_not_of(" \t\n"); + // only whitespace + if (start == string::npos) + return ""; + size_t end = s.find_last_not_of(" \t\n"); + return s.substr(start, end-start+1); +} +} +} + /*}}}*/ // UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/ // --------------------------------------------------------------------- /* This is handy to use before display some information for enduser */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index b42e06491..c8fc317c0 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -33,6 +33,13 @@ using std::vector; using std::ostream; #endif +namespace APT { + namespace String { + std::string Strip(const std::string &s); + }; +}; + + bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest); char *_strstrip(char *String); char *_strrstrip(char *String); // right strip only diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b5f858022..5f1849b53 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -668,6 +668,10 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // check if the package moved to the next dpkg state if(next_action && (action == next_action)) { + // we moved from one dpkg state to a new one, report that + PackageOpsDone[pkg]++; + PackagesDone++; + // only read the translation if there is actually a next // action const char *translation = _(states[PackageOpsDone[pkg]].str); @@ -675,9 +679,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) strprintf(msg, translation, i18n_pkgname.c_str()); d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg); - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; } if (Debug == true) std::clog << "(parsed from dpkg) pkg: " << short_pkgname diff --git a/apt-pkg/iprogress.cc b/apt-pkg/iprogress.cc index 318d626d4..daa7695e2 100644 --- a/apt-pkg/iprogress.cc +++ b/apt-pkg/iprogress.cc @@ -29,6 +29,7 @@ bool PackageManager::StatusChanged(std::string PackageName, } PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) + : StepsDone(0), StepsTotal(1) { OutStatusFd = progress_fd; } @@ -106,6 +107,13 @@ bool PackageManagerProgressFd::StatusChanged(std::string PackageName, << ":" << pkg_action << std::endl; WriteToStatusFd(status.str()); + + if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true) + std::cerr << "progress: " << PackageName << " " << xStepsDone + << " " << xTotalSteps << " " << pkg_action + << std::endl; + + return true; } diff --git a/apt-pkg/iprogress.h b/apt-pkg/iprogress.h index ccf154279..42fa89be4 100644 --- a/apt-pkg/iprogress.h +++ b/apt-pkg/iprogress.h @@ -21,7 +21,7 @@ namespace Progress { public: PackageManager() - : percentage(0.0), last_reported_progress(0) {}; + : percentage(0.0), last_reported_progress(-1) {}; virtual ~PackageManager() {}; virtual void Start() {}; diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index cdf8d4a23..97bb25848 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -50,7 +50,6 @@ pmstatus:testing:33.3333:Preparing for removal of testing (amd64) pmstatus:testing:66.6667:Removing testing (amd64) pmstatus:testing:100:Removed testing (amd64)" cat apt-progress.log - # install non-native and ensure we get proper progress info exec 3> apt-progress.log testsuccess aptget install testing2:i386 -y -o APT::Status-Fd=3 -- cgit v1.2.3-70-g09d2 From d274520ee8d174aa9f062f2fbb2c4d117a121dd8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 21 Oct 2013 21:24:32 +0200 Subject: fix apt output ordering and update test to match the new human friendly messages that include the architecture --- apt-pkg/deb/dpkgpm.cc | 10 +++++----- test/integration/test-apt-progress-fd | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 5f1849b53..a61f08d91 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -668,14 +668,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // check if the package moved to the next dpkg state if(next_action && (action == next_action)) { - // we moved from one dpkg state to a new one, report that - PackageOpsDone[pkg]++; - PackagesDone++; - // 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); @@ -1505,7 +1506,6 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) CloseLog(); // dpkg is done at this point - d->progress->StatusChanged("", PackagesDone, PackagesTotal, ""); d->progress->Stop(); if (pkgPackageManager::SigINTStop) diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index 97bb25848..9d250e949 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -21,7 +21,7 @@ pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) pmstatus:testing:20:Preparing testing (amd64) pmstatus:testing:40:Unpacking testing (amd64) -pmstatus:testing:60:Preparing to configure testing +pmstatus:testing:60:Preparing to configure testing (amd64) pmstatus:dpkg-exec:60:Running dpkg pmstatus:testing:60:Configuring testing (amd64) pmstatus:testing:80:Configuring testing (amd64) @@ -35,7 +35,7 @@ dlstatus:1:0:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:20:Preparing testing (amd64) pmstatus:testing:40:Unpacking testing (amd64) -pmstatus:testing:60:Preparing to configure testing +pmstatus:testing:60:Preparing to configure testing (amd64) pmstatus:dpkg-exec:60:Running dpkg pmstatus:testing:60:Configuring testing (amd64) pmstatus:testing:80:Configuring testing (amd64) -- cgit v1.2.3-70-g09d2 From 3b1b0f2900347ef2836c7ee4cc3ee20c6cdcb621 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 21 Oct 2013 21:42:16 +0200 Subject: restore binary compatiblity with the pkgPackageManager interface --- apt-pkg/deb/dpkgpm.cc | 3 +- apt-pkg/packagemanager.cc | 25 +++++++++++++ apt-pkg/packagemanager.h | 18 +++++----- test/integration/test-apt-progress-fd-deb822 | 54 ++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 test/integration/test-apt-progress-fd-deb822 (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a61f08d91..adc94f05c 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,7 +19,8 @@ #include #include #include -#include + +#include #include #include diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 3690a64c3..a2079a2e4 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1027,6 +1027,18 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Completed; } +// PM::DoInstallPostFork - compat /*{{{*/ +// --------------------------------------------------------------------- + /*}}}*/ +pkgPackageManager::OrderResult +pkgPackageManager::DoInstallPostFork(int statusFd) +{ + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + pkgPackageManager::OrderResult res = DoInstallPostFork(progress); + delete progress; + return res; + } /*}}}*/ // PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/ // --------------------------------------------------------------------- @@ -1042,6 +1054,19 @@ pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- +/* compat */ +pkgPackageManager::OrderResult +pkgPackageManager::DoInstall(int statusFd) +{ + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + OrderResult res = DoInstall(progress); + delete progress; + return res; + } + /*}}}*/ +// PM::DoInstall - Does the installation /*{{{*/ +// --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ pkgPackageManager::OrderResult diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 5c15ac0e4..dcd12f979 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -23,8 +23,10 @@ #ifndef PKGLIB_PACKAGEMANAGER_H #define PKGLIB_PACKAGEMANAGER_H +#include #include -#include + +#include #include #include @@ -100,16 +102,8 @@ class pkgPackageManager : protected pkgCache::Namespace // Do the installation OrderResult DoInstall(APT::Progress::PackageManager *progress); - // compat - OrderResult DoInstall(int statusFd=-1) { - APT::Progress::PackageManager *progress = new - APT::Progress::PackageManagerProgressFd(statusFd); - OrderResult res = DoInstall(progress); - delete progress; - return res; - } - + __deprecated OrderResult DoInstall(int statusFd=-1); // stuff that needs to be done before the fork() of a library that // uses apt @@ -120,6 +114,10 @@ class pkgPackageManager : protected pkgCache::Namespace // stuff that needs to be done after the fork OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); + // compat + __deprecated OrderResult DoInstallPostFork(int statusFd=-1); + + // ? bool FixMissing(); /** \brief returns all packages dpkg let disappear */ diff --git a/test/integration/test-apt-progress-fd-deb822 b/test/integration/test-apt-progress-fd-deb822 new file mode 100644 index 000000000..0a7be0cd8 --- /dev/null +++ b/test/integration/test-apt-progress-fd-deb822 @@ -0,0 +1,54 @@ + +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' 'i386' + +buildsimplenativepackage 'testing' 'amd64' '0.1' 'stable' +buildsimplenativepackage 'testing' 'all' '0.8.15' 'stable' +buildsimplenativepackage 'testing2' 'amd64,i386' '0.8.15' 'stable' +setupaptarchive + +# install native +exec 3> apt-progress.log +testsuccess aptget install testing=0.1 -y -o APT::Status-deb822-Fd=3 +testequal "# and compare +testequal "percent:0 +message: Running dpkg + +package: testing2 +percent: 0 +message: Installing testing2 (i386) + +package: testing2 +percent: 20 +message: Preparing testing2 (i386) + +package: testing2 +percent: 40 +message: Unpacking testing2 (i386) + +package: testing2 +percent: 60 +message: Preparing to configure testing2 (i386) + +percent: 60 +message: Running dpkg + +package: testing2 +percent: 60 +message: Configuring testing2 (i386) + +package: testing2 +percent: 80 +message: Configuring testing2 (i386) + +package: testing2 +percent: 100 +message: Installed testing2 (i386)" cat apt-progress.log + + +rm -f apt-progress*.log -- cgit v1.2.3-70-g09d2 From af36becc889122909d677c267bc5325fb73b6151 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 19:02:01 +0200 Subject: fix install-progress location --- apt-pkg/deb/dpkgpm.cc | 3 +-- apt-pkg/install-progress.cc | 3 +-- apt-pkg/packagemanager.h | 3 +-- apt-private/private-install.cc | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index adc94f05c..c98ff3e04 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -19,8 +19,7 @@ #include #include #include - -#include +#include #include #include diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 1d15228c2..9d0d4e3f1 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -1,8 +1,7 @@ #include #include #include - -#include +#include #include diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index dcd12f979..8ffac2f13 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -25,8 +25,7 @@ #include #include - -#include +#include #include #include diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 1d2acee6c..d9d46dba0 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -23,8 +23,7 @@ #include #include #include - -#include +#include #include #include -- cgit v1.2.3-70-g09d2 From 1f467276115ddc43b766dbd1107eb2fb315dc747 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 21:15:55 +0200 Subject: use Pkg.FullName() in disappearedPkgs and remove duplicated check --- apt-pkg/deb/dpkgpm.cc | 13 ++----------- test/integration/test-disappearing-packages | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index c98ff3e04..889b62afa 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -550,16 +550,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { pkgname = APT::String::Strip(list[2]); action = APT::String::Strip(list[1]); - - // this is what we support in the processing stage - if(action != "install" && action != "configure" && - action != "remove" && action != "purge" && action != "purge") - { - if (Debug == true) - std::clog << "ignoring processing action: '" << action - << "'" << std::endl; - return; - } } // "status" has the form: "status: pkg: state" // with state in ["half-installed", "unpacked", "half-configured", @@ -696,6 +686,7 @@ void pkgDPkgPM::handleDisappearAction(string const &pkgname) pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname); if (unlikely(Pkg.end() == true)) return; + // the disappeared package was auto-installed - nothing to do if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) return; @@ -1218,7 +1209,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { if((*I).Pkg.end() == true) continue; - if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.Name()) != disappearedPkgs.end()) + if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.FullName()) != disappearedPkgs.end()) continue; // We keep this here to allow "smooth" transitions from e.g. multiarch dpkg/ubuntu to dpkg/debian if (dpkgMultiArch == false && (I->Pkg.Arch() == nativeArch || diff --git a/test/integration/test-disappearing-packages b/test/integration/test-disappearing-packages index 09dbf7014..3b1e1bd7c 100755 --- a/test/integration/test-disappearing-packages +++ b/test/integration/test-disappearing-packages @@ -40,7 +40,7 @@ echo "The following package disappeared from your system as all files have been overwritten by other packages: old-pkg Note: This is done automatically and on purpose by dpkg." > $COMPAREFILE -$CMD 2>&1 | tail -n 4 | diff $COMPAREFILE - && msgpass || msgfail +$CMD 2>&1 | tail -n 4 | diff -u $COMPAREFILE - && msgpass || msgfail rm $COMPAREFILE sed -i rootdir/var/log/apt/history.log -e '/^Commandline: / d' -e '/^Start-Date: / d' -e '/^End-Date: / d' -e "s#:$(getarchitecture 'native') #:native #" -- cgit v1.2.3-70-g09d2 From b4017ba767e15dc06c73915efaf36409ee099bf2 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 22 Oct 2013 21:53:49 +0200 Subject: fix failing ./test/integration/test-disappearing-packages (thanks Donkult!) --- apt-pkg/deb/dpkgpm.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 889b62afa..1a02115ba 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -680,13 +680,13 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) // DPkgPM::handleDisappearAction /*{{{*/ void pkgDPkgPM::handleDisappearAction(string const &pkgname) { - // record the package name for display and stuff later - disappearedPkgs.insert(pkgname); - pkgCache::PkgIterator Pkg = Cache.FindPkg(pkgname); if (unlikely(Pkg.end() == true)) return; + // record the package name for display and stuff later + disappearedPkgs.insert(Pkg.FullName(true)); + // the disappeared package was auto-installed - nothing to do if ((Cache[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) return; @@ -1209,7 +1209,7 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) { if((*I).Pkg.end() == true) continue; - if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.FullName()) != disappearedPkgs.end()) + if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.FullName(true)) != disappearedPkgs.end()) continue; // We keep this here to allow "smooth" transitions from e.g. multiarch dpkg/ubuntu to dpkg/debian if (dpkgMultiArch == false && (I->Pkg.Arch() == nativeArch || -- cgit v1.2.3-70-g09d2 From a18456a58a9ad2fe33f7fbd202533a115712df96 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 24 Oct 2013 08:31:50 +0200 Subject: make the main loop a while() instead of a for() as I find this (much) easier to read this way) --- apt-pkg/deb/dpkgpm.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 1a02115ba..56358ae87 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1087,8 +1087,9 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) dpkgMultiArch = true; } - // this loop is runs once per operation - for (vector::const_iterator I = List.begin(); I != List.end();) + // go over each item + vector::const_iterator I = List.begin(); + while (I != List.end()) { // Do all actions with the same Op in one run vector::const_iterator J = I; -- cgit v1.2.3-70-g09d2 From 6fad3c240c18dff339d934f2e3bd41c93c417f89 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 25 Oct 2013 15:43:28 +0200 Subject: extract getDpkgExecutable() and DPkgPM::BuildPackagesProgressMap() out of the monster long pkgDPkgPM::Go() --- apt-pkg/deb/dpkgpm.cc | 136 +++++++++++++++++++++++++++----------------------- apt-pkg/deb/dpkgpm.h | 3 ++ 2 files changed, 77 insertions(+), 62 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 56358ae87..98fb7581a 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -132,6 +132,20 @@ ionice(int PID) return ExecWait(Process, "ionice"); } +static std::string getDpkgExecutable() +{ + string Tmp = _config->Find("Dir::Bin::dpkg","dpkg"); + string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/"); + size_t dpkgChrootLen = dpkgChrootDir.length(); + if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0) + { + if (dpkgChrootDir[dpkgChrootLen - 1] == '/') + --dpkgChrootLen; + Tmp = Tmp.substr(dpkgChrootLen); + } + return Tmp; +} + // dpkgChrootDirectory - chrooting for dpkg if needed /*{{{*/ static void dpkgChrootDirectory() { @@ -932,6 +946,60 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, return retval; } /*}}}*/ + +// DPkgPM::BuildPackagesProgressMap /*{{{*/ +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 struct DpkgState DpkgStatesOpMap[][7] = { + // Install operation + { + {"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} + }, + }; + + // init the PackageOps map, go over the list of packages that + // that will be [installed|configured|removed|purged] and add + // them to the PackageOps map (the dpkg states it goes through) + // and the PackageOpsTranslations (human readable strings) + for (vector::const_iterator I = List.begin(); I != List.end(); ++I) + { + if((*I).Pkg.end() == true) + continue; + + string const name = (*I).Pkg.FullName(); + PackageOpsDone[name] = 0; + for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; ++i) + { + PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]); + PackagesTotal++; + } + } +} + /*}}}*/ // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -947,21 +1015,11 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) d->progress = progress; // Generate the base argument list for dpkg - std::vector Args; unsigned long StartSize = 0; - string Tmp = _config->Find("Dir::Bin::dpkg","dpkg"); - { - string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/"); - size_t dpkgChrootLen = dpkgChrootDir.length(); - if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0) - { - if (dpkgChrootDir[dpkgChrootLen - 1] == '/') - --dpkgChrootLen; - Tmp = Tmp.substr(dpkgChrootLen); - } - } - Args.push_back(Tmp.c_str()); - StartSize += Tmp.length(); + std::vector Args; + std::string DpkgExecutable = getDpkgExecutable(); + Args.push_back(DpkgExecutable.c_str()); + StartSize += DpkgExecutable.length(); // Stick in any custom dpkg options Configuration::Item const *Opts = _config->Tree("DPkg::Options"); @@ -1018,54 +1076,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true) List.push_back(Item(Item::ConfigurePending, PkgIterator())); - // map the dpkg states to the operations that are performed - // (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") }, - {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} - }, - }; - - // init the PackageOps map, go over the list of packages that - // that will be [installed|configured|removed|purged] and add - // them to the PackageOps map (the dpkg states it goes through) - // and the PackageOpsTranslations (human readable strings) - for (vector::const_iterator I = List.begin(); I != List.end(); ++I) - { - if((*I).Pkg.end() == true) - continue; - - string const name = (*I).Pkg.FullName(); - PackageOpsDone[name] = 0; - for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; ++i) - { - PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]); - PackagesTotal++; - } - } + // for the progress + BuildPackagesProgressMap(); d->stdin_is_dev_null = false; diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 922631ba8..5f00eee5d 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -97,6 +97,9 @@ class pkgDPkgPM : public pkgPackageManager // dpkg log bool OpenLog(); bool CloseLog(); + + // helper + void BuildPackagesProgressMap(); // input processing void DoStdin(int master); -- cgit v1.2.3-70-g09d2 From c3045b79796b611858e9f8b44127a70d6043cea0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 07:36:47 +0100 Subject: move pty stuff into its own function --- apt-pkg/deb/dpkgpm.cc | 173 +++++++++++++++++++++++++++----------------------- apt-pkg/deb/dpkgpm.h | 3 + 2 files changed, 97 insertions(+), 79 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 0ebd9f28b..ddfc7c04e 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -55,7 +55,7 @@ public: pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), term_out(NULL), history_out(NULL), last_reported_progress(0.0), nr_terminal_rows(0), - fancy_progress_output(false) + fancy_progress_output(false), master(-1), slave(-1) { dpkgbuf[0] = '\0'; if(_config->FindB("Dpkg::Progress-Fancy", false) == true) @@ -63,6 +63,7 @@ public: fancy_progress_output = true; _config->Set("DpkgPM::Progress", true); } + } bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading @@ -75,6 +76,16 @@ public: float last_reported_progress; int nr_terminal_rows; bool fancy_progress_output; + + // pty stuff + struct termios tt; + int master; + int slave; + + // signals + sigset_t sigmask; + sigset_t original_sigmask; + }; namespace @@ -1055,6 +1066,61 @@ void pkgDPkgPM::CleanupTerminal() } } +void pkgDPkgPM::StartPtyMagic() +{ + // setup the pty and stuff + struct winsize win; + + // if tcgetattr does not return zero there was a error + // and we do not do any pty magic + _error->PushToStack(); + if (tcgetattr(STDOUT_FILENO, &d->tt) == 0) + { + ioctl(1, TIOCGWINSZ, (char *)&win); + d->nr_terminal_rows = win.ws_row; + if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0) + { + _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); + d->master = d->slave = -1; + } else { + struct termios rtt; + rtt = d->tt; + cfmakeraw(&rtt); + rtt.c_lflag &= ~ECHO; + rtt.c_lflag |= ISIG; + // block SIGTTOU during tcsetattr to prevent a hang if + // the process is a member of the background process group + // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html + sigemptyset(&d->sigmask); + sigaddset(&d->sigmask, SIGTTOU); + sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask); + tcsetattr(0, TCSAFLUSH, &rtt); + sigprocmask(SIG_SETMASK, &d->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(); + + // setup terminal + SetupTerminalScrollArea(d->nr_terminal_rows); +} + +void pkgDPkgPM::StopPtyMagic() +{ + if(d->slave > 0) + close(d->slave); + if(d->master >= 0) + { + tcsetattr(0, TCSAFLUSH, &d->tt); + close(d->master); + } +} // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- @@ -1121,8 +1187,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) fd_set rfds; struct timespec tv; - sigset_t sigmask; - sigset_t original_sigmask; unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024); unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024); @@ -1210,8 +1274,12 @@ bool pkgDPkgPM::Go(int OutStatusFd) dpkgMultiArch = true; } - // this loop is runs once per operation - for (vector::const_iterator I = List.begin(); I != List.end();) + // start pty magic before the loop + StartPtyMagic(); + + // this loop is runs once per dpkg operation + vector::const_iterator I = List.begin(); + while (I != List.end()) { // Do all actions with the same Op in one run vector::const_iterator J = I; @@ -1402,47 +1470,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) // ignore SIGHUP as well (debian #463030) sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN); - struct termios tt; - struct winsize win; - int master = -1; - int slave = -1; - - // if tcgetattr does not return zero there was a error - // and we do not do any pty magic - _error->PushToStack(); - if (tcgetattr(STDOUT_FILENO, &tt) == 0) - { - ioctl(1, TIOCGWINSZ, (char *)&win); - d->nr_terminal_rows = win.ws_row; - if (openpty(&master, &slave, NULL, &tt, &win) < 0) - { - _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); - master = slave = -1; - } else { - struct termios rtt; - rtt = tt; - cfmakeraw(&rtt); - rtt.c_lflag &= ~ECHO; - rtt.c_lflag |= ISIG; - // block SIGTTOU during tcsetattr to prevent a hang if - // the process is a member of the background process group - // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGTTOU); - sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask); - tcsetattr(0, TCSAFLUSH, &rtt); - 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]); @@ -1461,15 +1488,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (Child == 0) { - if(slave >= 0 && master >= 0) + if(d->slave >= 0 && d->master >= 0) { setsid(); - ioctl(slave, TIOCSCTTY, 0); - close(master); - dup2(slave, 0); - dup2(slave, 1); - dup2(slave, 2); - close(slave); + ioctl(d->slave, TIOCSCTTY, 0); + close(d->master); + dup2(d->slave, 0); + dup2(d->slave, 1); + dup2(d->slave, 2); + close(d->slave); } close(fd[0]); // close the read end of the pipe @@ -1493,9 +1520,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0) _exit(100); } - // setup terminal - SetupTerminalScrollArea(d->nr_terminal_rows); - SendTerminalProgress(PackagesDone/float(PackagesTotal)*100.0); /* No Job Control Stop Env is a magic dpkg var that prevents it from using sigstop */ @@ -1519,12 +1543,9 @@ bool pkgDPkgPM::Go(int OutStatusFd) int const _dpkgin = fd[0]; close(fd[1]); // close the write end of the pipe - if(slave > 0) - close(slave); - // setups fds - sigemptyset(&sigmask); - sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask); + sigemptyset(&d->sigmask); + sigprocmask(SIG_BLOCK,&d->sigmask,&d->original_sigmask); /* free vectors (and therefore memory) as we don't need the included data anymore */ for (std::vector::const_iterator p = Packages.begin(); @@ -1553,18 +1574,18 @@ bool pkgDPkgPM::Go(int OutStatusFd) // wait for input or output here FD_ZERO(&rfds); - if (master >= 0 && !d->stdin_is_dev_null) + if (d->master >= 0 && !d->stdin_is_dev_null) FD_SET(0, &rfds); FD_SET(_dpkgin, &rfds); - if(master >= 0) - FD_SET(master, &rfds); + if(d->master >= 0) + FD_SET(d->master, &rfds); tv.tv_sec = 1; tv.tv_nsec = 0; - select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, - &tv, &original_sigmask); + 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(master, _dpkgin)+1, &rfds, NULL, - NULL, &tv, &original_sigmask); + select_ret = racy_pselect(max(d->master, _dpkgin)+1, &rfds, NULL, + NULL, &tv, &d->original_sigmask); if (select_ret == 0) continue; else if (select_ret < 0 && errno == EINTR) @@ -1575,10 +1596,10 @@ bool pkgDPkgPM::Go(int OutStatusFd) continue; } - if(master >= 0 && FD_ISSET(master, &rfds)) - DoTerminalPty(master); - if(master >= 0 && FD_ISSET(0, &rfds)) - DoStdin(master); + if(d->master >= 0 && FD_ISSET(d->master, &rfds)) + DoTerminalPty(d->master); + if(d->master >= 0 && FD_ISSET(0, &rfds)) + DoStdin(d->master); if(FD_ISSET(_dpkgin, &rfds)) DoDpkgStatusFd(_dpkgin, OutStatusFd); } @@ -1589,13 +1610,6 @@ bool pkgDPkgPM::Go(int OutStatusFd) signal(SIGINT,old_SIGINT); signal(SIGHUP,old_SIGHUP); - - if(master >= 0) - { - tcsetattr(0, TCSAFLUSH, &tt); - close(master); - } - // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) { @@ -1632,6 +1646,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) SendTerminalProgress(100); CleanupTerminal(); + StopPtyMagic(); if (pkgPackageManager::SigINTStop) _error->Warning(_("Operation was interrupted before it could finish")); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 1a58e1af5..5551b4383 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -95,6 +95,9 @@ class pkgDPkgPM : public pkgPackageManager // dpkg log bool OpenLog(); bool CloseLog(); + + void StartPtyMagic(); + void StopPtyMagic(); // input processing void DoStdin(int master); -- cgit v1.2.3-70-g09d2 From bd5f39b34cc0e8cebbe9103f569d4d903e75bd2b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 08:23:12 +0100 Subject: restore ABI and prepare next ABI via #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) --- apt-pkg/deb/dpkgpm.cc | 17 +++++++++++++++++ apt-pkg/deb/dpkgpm.h | 7 +++++++ apt-pkg/install-progress.cc | 22 ++++++++++++++++++++++ apt-pkg/install-progress.h | 3 +++ apt-pkg/packagemanager.cc | 36 ++++++++++++++++++++++++++++++------ apt-pkg/packagemanager.h | 15 ++++++++++++++- apt-private/private-install.cc | 35 +++++++++++++---------------------- 7 files changed, 106 insertions(+), 29 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 98fb7581a..b252c02eb 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1000,6 +1000,19 @@ void pkgDPkgPM::BuildPackagesProgressMap() } } /*}}}*/ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) +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 GoNoABIBreak(progress); +} +#endif + // DPkgPM::Go - Run the sequence /*{{{*/ // --------------------------------------------------------------------- /* This globs the operations and calls dpkg @@ -1009,7 +1022,11 @@ void pkgDPkgPM::BuildPackagesProgressMap() * through to human readable (and i10n-able) * names and calculates a percentage for each step. */ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) +#else +bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) +#endif { pkgPackageManager::SigINTStop = false; d->progress = progress; diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 5f00eee5d..4494bbae3 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -15,6 +15,7 @@ #include #include #include +#include #ifndef APT_8_CLEANER_HEADERS using std::vector; @@ -112,7 +113,13 @@ class pkgDPkgPM : public pkgPackageManager virtual bool Configure(PkgIterator Pkg); virtual bool Remove(PkgIterator Pkg,bool Purge = false); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) virtual bool Go(APT::Progress::PackageManager *progress); +#else + virtual bool Go(int StatusFd=-1); + bool GoNoABIBreak(APT::Progress::PackageManager *progress); +#endif + virtual void Reset(); public: diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 9d0d4e3f1..a9146f27d 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -13,6 +13,28 @@ namespace APT { namespace Progress { +PackageManager* PackageManagerProgressFactory() +{ + // select the right progress + int status_fd = _config->FindI("APT::Status-Fd", -1); + int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1); + + APT::Progress::PackageManager *progress = NULL; + if (status_deb822_fd > 0) + progress = new APT::Progress::PackageManagerProgressDeb822Fd( + status_deb822_fd); + else if (status_fd > 0) + progress = new APT::Progress::PackageManagerProgressFd(status_fd); + else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) + progress = new APT::Progress::PackageManagerFancy(); + else if (_config->FindB("Dpkg::Progress", + _config->FindB("DpkgPM::Progress", false)) == true) + progress = new APT::Progress::PackageManagerText(); + else + progress = new APT::Progress::PackageManager(); + return progress; +} + bool PackageManager::StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 9c31eac92..050954bb5 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -8,6 +8,9 @@ namespace APT { namespace Progress { + class PackageManager; + PackageManager* PackageManagerProgressFactory(); + class PackageManager { private: diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index a2079a2e4..3fdd9b637 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1030,15 +1030,16 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() // PM::DoInstallPostFork - compat /*{{{*/ // --------------------------------------------------------------------- /*}}}*/ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) pkgPackageManager::OrderResult pkgPackageManager::DoInstallPostFork(int statusFd) { - APT::Progress::PackageManager *progress = new - APT::Progress::PackageManagerProgressFd(statusFd); - pkgPackageManager::OrderResult res = DoInstallPostFork(progress); - delete progress; - return res; - } + APT::Progress::PackageManager *progress = new + APT::Progress::PackageManagerProgressFd(statusFd); + pkgPackageManager::OrderResult res = DoInstallPostFork(progress); + delete progress; + return res; +} /*}}}*/ // PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/ // --------------------------------------------------------------------- @@ -1051,10 +1052,22 @@ pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress) return Res; }; +#else +pkgPackageManager::OrderResult +pkgPackageManager::DoInstallPostFork(int statusFd) +{ + bool goResult = Go(statusFd); + if(goResult == false) + return Failed; + + return Res; +} +#endif /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* compat */ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) { @@ -1064,11 +1077,21 @@ pkgPackageManager::DoInstall(int statusFd) delete progress; return res; } +#else +pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) +{ + if(DoInstallPreFork() == Failed) + return Failed; + + return DoInstallPostFork(statusFd); +} +#endif /*}}}*/ // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) pkgPackageManager::OrderResult pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) { @@ -1077,4 +1100,5 @@ pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress) return DoInstallPostFork(progress); } +#endif /*}}}*/ diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 8ffac2f13..a5c58e4a7 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,12 @@ class pkgPackageManager : protected pkgCache::Namespace virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;}; virtual bool Configure(PkgIterator /*Pkg*/) {return false;}; virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;}; +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) virtual bool Go(APT::Progress::PackageManager *progress) {return true;}; +#else + virtual bool Go(int StatusFd=-1) {return true;}; +#endif + virtual void Reset() {}; // the result of the operation @@ -100,9 +106,13 @@ class pkgPackageManager : protected pkgCache::Namespace pkgRecords *Recs); // Do the installation +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) OrderResult DoInstall(APT::Progress::PackageManager *progress); // compat __deprecated OrderResult DoInstall(int statusFd=-1); +#else + OrderResult DoInstall(int statusFd=-1); +#endif // stuff that needs to be done before the fork() of a library that // uses apt @@ -110,11 +120,14 @@ class pkgPackageManager : protected pkgCache::Namespace Res = OrderInstall(); return Res; }; - +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) // stuff that needs to be done after the fork OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress); // compat __deprecated OrderResult DoInstallPostFork(int statusFd=-1); +#else + OrderResult DoInstallPostFork(int statusFd=-1); +#endif // ? bool FixMissing(); diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index d9d46dba0..3adb00b23 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -105,12 +106,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) { pkgSimulate PM(Cache); - int status_fd = _config->FindI("APT::Status-Fd",-1); - APT::Progress::PackageManager *progress = NULL; - if (status_fd > 0) - progress = new APT::Progress::PackageManagerProgressFd(status_fd); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory(); pkgPackageManager::OrderResult Res = PM.DoInstall(progress); delete progress; +#else + int status_fd = _config->FindI("APT::Status-Fd",-1); + pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd); +#endif if (Res == pkgPackageManager::Failed) return false; @@ -340,26 +343,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) _system->UnLock(); - // FIXME: make this a factory - // select the right progress - int status_fd = _config->FindI("APT::Status-Fd", -1); - int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1); - - APT::Progress::PackageManager *progress = NULL; - if (status_deb822_fd > 0) - progress = new APT::Progress::PackageManagerProgressDeb822Fd( - status_deb822_fd); - else if (status_fd > 0) - progress = new APT::Progress::PackageManagerProgressFd(status_fd); - else if(_config->FindB("Dpkg::Progress-Fancy", false) == true) - progress = new APT::Progress::PackageManagerFancy(); - else if (_config->FindB("Dpkg::Progress", - _config->FindB("DpkgPM::Progress", false)) == true) - progress = new APT::Progress::PackageManagerText(); - else - progress = new APT::Progress::PackageManager(); +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) + APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory(); pkgPackageManager::OrderResult Res = PM->DoInstall(progress); delete progress; +#else + int status_fd = _config->FindI("APT::Status-Fd", -1); + pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd); +#endif if (Res == pkgPackageManager::Failed || _error->PendingError() == true) return false; -- cgit v1.2.3-70-g09d2 From e45c4617e496b49f8d7225546a751022f246a2f3 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Oct 2013 22:55:38 +0100 Subject: add new pid_t ExecFork(std::set KeepFDs) to get rid of the super ugly APT::Keep-Fds hack and also add a new PackageManagerProgressFd::StartDpkg() progress state --- apt-pkg/contrib/fileutl.cc | 33 +++++++++++++++++++-------------- apt-pkg/contrib/fileutl.h | 2 ++ apt-pkg/deb/dpkgpm.cc | 26 ++++++++++++++------------ apt-pkg/install-progress.cc | 6 +----- apt-pkg/install-progress.h | 8 +++++++- 5 files changed, 43 insertions(+), 32 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0261119ba..2347ef140 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -766,6 +766,25 @@ bool WaitFd(int Fd,bool write,unsigned long timeout) child, it fixes up the important signals and nukes all of the fds, otherwise acts like normal fork. */ pid_t ExecFork() +{ + set KeepFDs; + + Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds"); + if (Opts != 0 && Opts->Child != 0) + { + Opts = Opts->Child; + for (; Opts != 0; Opts = Opts->Next) + { + if (Opts->Value.empty() == true) + continue; + int fd = atoi(Opts->Value.c_str()); + KeepFDs.insert(fd); + } + } + return ExecFork(KeepFDs); +} + +pid_t ExecFork(std::set KeepFDs) { // Fork off the process pid_t Process = fork(); @@ -786,20 +805,6 @@ pid_t ExecFork() signal(SIGCONT,SIG_DFL); signal(SIGTSTP,SIG_DFL); - set KeepFDs; - Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds"); - if (Opts != 0 && Opts->Child != 0) - { - Opts = Opts->Child; - for (; Opts != 0; Opts = Opts->Next) - { - if (Opts->Value.empty() == true) - continue; - int fd = atoi(Opts->Value.c_str()); - KeepFDs.insert(fd); - } - } - // Close all of our FDs - just in case for (int K = 3; K != 40; K++) { diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index decd64d9d..63a999c30 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -26,6 +26,7 @@ #include #include +#include #include @@ -182,6 +183,7 @@ void SetCloseExec(int Fd,bool Close); void SetNonBlock(int Fd,bool Block); bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0); pid_t ExecFork(); +pid_t ExecFork(std::set keep_fds); bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); // File string manipulators diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index d1b11098c..26d79dbb1 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -416,17 +416,20 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) unsigned int InfoFD = _config->FindI(OptSec + "::InfoFD", STDIN_FILENO); // Create the pipes + std::set KeepFDs; int Pipes[2]; if (pipe(Pipes) != 0) return _error->Errno("pipe","Failed to create IPC pipe to subprocess"); if (InfoFD != (unsigned)Pipes[0]) SetCloseExec(Pipes[0],true); else - _config->Set("APT::Keep-Fds::", Pipes[0]); + KeepFDs.insert(Pipes[0]); + + SetCloseExec(Pipes[1],true); // Purified Fork for running the script - pid_t Process = ExecFork(); + pid_t Process = ExecFork(KeepFDs); if (Process == 0) { // Setup the FDs @@ -448,8 +451,6 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) 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) @@ -1375,11 +1376,14 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) // ignore SIGHUP as well (debian #463030) sighandler_t old_SIGHUP = signal(SIGHUP,SIG_IGN); - pid_t Child = ExecFork(); - // This is the child + // now run dpkg + d->progress->StartDpkg(); + std::set KeepFDs; + KeepFDs.insert(fd[1]); + pid_t Child = ExecFork(KeepFDs); if (Child == 0) { - + // This is the child if(d->slave >= 0 && d->master >= 0) { setsid(); @@ -1425,9 +1429,6 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) if (_config->FindB("DPkg::UseIoNice", false) == true) ionice(Child); - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds",fd[1]); - // Wait for dpkg int Status = 0; @@ -1471,13 +1472,14 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) FD_SET(_dpkgin, &rfds); if(d->master >= 0) FD_SET(d->master, &rfds); - tv.tv_sec = 1; - tv.tv_nsec = 0; + tv.tv_sec = 0; + tv.tv_nsec = d->progress->GetPulseInterval(); 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) diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index a9146f27d..79660b29e 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -63,7 +63,7 @@ void PackageManagerProgressFd::WriteToStatusFd(std::string s) FileFd::Write(OutStatusFd, s.c_str(), s.size()); } -void PackageManagerProgressFd::Start() +void PackageManagerProgressFd::StartDpkg() { if(OutStatusFd <= 0) return; @@ -83,8 +83,6 @@ void PackageManagerProgressFd::Start() void PackageManagerProgressFd::Stop() { - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); } void PackageManagerProgressFd::Error(std::string PackageName, @@ -168,8 +166,6 @@ void PackageManagerProgressDeb822Fd::Start() void PackageManagerProgressDeb822Fd::Stop() { - // clear the Keep-Fd again - _config->Clear("APT::Keep-Fds", OutStatusFd); } void PackageManagerProgressDeb822Fd::Error(std::string PackageName, diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 050954bb5..5291039d8 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -27,9 +27,15 @@ namespace Progress { : percentage(0.0), last_reported_progress(-1) {}; virtual ~PackageManager() {}; + /* Global Start/Stop */ virtual void Start() {}; virtual void Stop() {}; + /* When dpkg is invoked (may happen multiple times for each + * install/remove block + */ + virtual void StartDpkg() {}; + virtual pid_t fork() {return fork(); }; virtual void Pulse() {}; @@ -62,7 +68,7 @@ namespace Progress { public: PackageManagerProgressFd(int progress_fd); - virtual void Start(); + virtual void StartDpkg(); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, -- cgit v1.2.3-70-g09d2 From 96ae6de5d3d5ae31100079c78fffc5ebc4a0b81c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 28 Nov 2013 17:08:53 +0100 Subject: fix regression that APT::Keep-Fds is not honored (closes: #730490) --- apt-pkg/contrib/fileutl.cc | 26 ++++++++++++++++++-------- apt-pkg/contrib/fileutl.h | 1 + apt-pkg/deb/dpkgpm.cc | 2 ++ debian/changelog | 3 ++- 4 files changed, 23 insertions(+), 9 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index d2be276c7..3a6bdfe2e 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -760,16 +760,13 @@ bool WaitFd(int Fd,bool write,unsigned long timeout) return true; } /*}}}*/ -// ExecFork - Magical fork that sanitizes the context before execing /*{{{*/ +// MergeKeepFdsFromConfiguration - Merge APT::Keep-Fds configuration /*{{{*/ // --------------------------------------------------------------------- -/* This is used if you want to cleanse the environment for the forked - child, it fixes up the important signals and nukes all of the fds, - otherwise acts like normal fork. */ -pid_t ExecFork() +/* This is used to merge the APT::Keep-Fds with the provided KeepFDs + * set. + */ +void MergeKeepFdsFromConfiguration(std::set &KeepFDs) { - set KeepFDs; - - // FIXME: remove looking at APT::Keep-Fds eventually, its a hack Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds"); if (Opts != 0 && Opts->Child != 0) { @@ -782,6 +779,19 @@ pid_t ExecFork() KeepFDs.insert(fd); } } +} + /*}}}*/ +// ExecFork - Magical fork that sanitizes the context before execing /*{{{*/ +// --------------------------------------------------------------------- +/* This is used if you want to cleanse the environment for the forked + child, it fixes up the important signals and nukes all of the fds, + otherwise acts like normal fork. */ +pid_t ExecFork() +{ + set KeepFDs; + // we need to merge the Keep-Fds as external tools like + // debconf-apt-progress use it + MergeKeepFdsFromConfiguration(KeepFDs); return ExecFork(KeepFDs); } diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 63a999c30..e9a9aab28 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -184,6 +184,7 @@ void SetNonBlock(int Fd,bool Block); bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0); pid_t ExecFork(); pid_t ExecFork(std::set keep_fds); +void MergeKeepFdsFromConfiguration(std::set &keep_fds); bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); // File string manipulators diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 26d79dbb1..01c6242dc 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -417,6 +417,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) // Create the pipes std::set KeepFDs; + MergeKeepFdsFromConfiguration(KeepFDs); int Pipes[2]; if (pipe(Pipes) != 0) return _error->Errno("pipe","Failed to create IPC pipe to subprocess"); @@ -1380,6 +1381,7 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) d->progress->StartDpkg(); std::set KeepFDs; KeepFDs.insert(fd[1]); + MergeKeepFdsFromConfiguration(KeepFDs); pid_t Child = ExecFork(KeepFDs); if (Child == 0) { diff --git a/debian/changelog b/debian/changelog index 7447628db..92b9635dd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,8 +2,9 @@ apt (0.9.13.1) unstable; urgency=low [ Colin Watson ] * fix "apt-get --purge build-dep" (closes: #720597) + * fix regression that APT::Keep-Fds is not honored (closes: #730490) - -- Michael Vogt Thu, 28 Nov 2013 16:49:31 +0100 + -- Michael Vogt Thu, 28 Nov 2013 16:49:31 +0100 apt (0.9.13) unstable; urgency=low -- cgit v1.2.3-70-g09d2 From 804d195655c48a448d576b2b196d18c2c816e824 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 29 Nov 2013 20:08:56 +0100 Subject: reset terminal on error (closes: #730795) --- apt-pkg/deb/dpkgpm.cc | 1 + debian/changelog | 1 + 2 files changed, 2 insertions(+) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 01c6242dc..49396c1c7 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1530,6 +1530,7 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) if(stopOnError) { CloseLog(); + StopPtyMagic(); d->progress->Stop(); return false; } diff --git a/debian/changelog b/debian/changelog index 505a690f6..5522f4c4e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,7 @@ apt (0.9.13.1) UNRELEASED; urgency=low * merge mvo/feature/short-list * merge mvo/feature/edit-sources * fix segfault in pkgDepCache::SetCandidateRelease() (closes: #709560) + * reset terminal on error (closes: #730795) -- Michael Vogt Thu, 28 Nov 2013 20:02:39 +0100 -- cgit v1.2.3-70-g09d2 From 0cd4e696306af28f98c0f810ed18b052919205c8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 29 Nov 2013 20:17:20 +0100 Subject: fix apport report writing (LP: #1254499) --- apt-pkg/deb/dpkgpm.cc | 2 +- debian/changelog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 49396c1c7..14333c3e7 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -201,7 +201,7 @@ pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) // --------------------------------------------------------------------- /* */ pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) - : pkgPackageManager(Cache), PackagesDone(0), PackagesTotal(0) + : pkgPackageManager(Cache), pkgFailures(0), PackagesDone(0), PackagesTotal(0) { d = new pkgDPkgPMPrivate(); } diff --git a/debian/changelog b/debian/changelog index 5522f4c4e..65a8f4242 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,7 @@ apt (0.9.13.1) UNRELEASED; urgency=low * merge mvo/feature/edit-sources * fix segfault in pkgDepCache::SetCandidateRelease() (closes: #709560) * reset terminal on error (closes: #730795) + * fix apport report writing (LP: #1254499) -- Michael Vogt Thu, 28 Nov 2013 20:02:39 +0100 -- cgit v1.2.3-70-g09d2 From 581b556830ba17dc8a9d3edb858a4fd8c1d2fb58 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 30 Nov 2013 13:10:33 +0100 Subject: merge ubuntus apport reporting changes to reduce diff apport reporting is still disabled by default, but it is available in Debian/experimental at the moment and a diff is not a good idea anyway. --- apt-pkg/deb/dpkgpm.cc | 59 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 14333c3e7..b4bfd1400 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1622,18 +1622,49 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) } // do not report out-of-memory failures - if(strstr(errormsg, strerror(ENOMEM)) != NULL) { + 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; return; } - // do not report dpkg I/O errors - // XXX - this message is localized, but this only matches the English version. This is better than nothing. - if(strstr(errormsg, "short read in buffer_copy (")) { - std::clog << _("No apport report written because the error message indicates a dpkg I/O error") << std::endl; + // do not report bugs regarding inaccessible local files + if(strstr(errormsg, strerror(ENOENT)) != NULL || + strstr(errormsg, "cannot access archive") != NULL) { + std::clog << _("No apport report written because the error message indicates an issue on the local system") << std::endl; return; } + // do not report errors encountered when decompressing packages + if(strstr(errormsg, "--fsys-tarfile returned error exit status 2") != NULL) { + std::clog << _("No apport report written because the error message indicates an issue on the local system") << 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 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")); + + for (vector::iterator I = io_errors.begin(); I != io_errors.end(); I++) + { + vector list = VectorizeString(dgettext("dpkg", (*I).c_str()), '%'); + if (list.size() > 1) { + // we need to split %s, VectorizeString only allows char so we need + // to kill the "s" manually + if (list[1].size() > 1) { + list[1].erase(0, 1); + 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; + } + } + } + } + // get the pkgname and reportfile pkgname = flNotDir(pkgpath); pos = pkgname.find('_'); @@ -1721,6 +1752,24 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) if(log != NULL) { char buf[1024]; + while( fgets(buf, sizeof(buf), log) != NULL) + fprintf(report, " %s", buf); + fprintf(report, " \n"); + fclose(log); + } + } + + // attach history log it if we have it + string histfile_name = _config->FindFile("Dir::Log::History"); + if (!histfile_name.empty()) + { + FILE *log = NULL; + char buf[1024]; + + fprintf(report, "DpkgHistoryLog:\n"); + log = fopen(histfile_name.c_str(),"r"); + if(log != NULL) + { while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); fclose(log); -- cgit v1.2.3-70-g09d2 From c23e6cd58242470daad78ddad85285f9cd7aed0f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 12 Dec 2013 15:11:01 +0100 Subject: Fix conffile prompt regression (LP: #1260297) This fixes a regression in the conffile prompt for the progress-fd and adds a testcase to ensure this does not regress again. --- apt-pkg/deb/dpkgpm.cc | 10 ++++-- apt-pkg/install-progress.cc | 2 +- test/integration/test-apt-progress-fd-conffile | 43 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100755 test/integration/test-apt-progress-fd-conffile (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4bfd1400..0d73733d5 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -44,6 +44,7 @@ #include #include #include +#include #include /*}}}*/ @@ -596,7 +597,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) 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 - 'status: conffile-prompt: conffile : 'current-conffile' 'new-conffile' useredited distedited + 'status:/etc/compiz.conf/compiz.conf : conffile-prompt: 'current-conffile' 'new-conffile' useredited distedited */ if (prefix == "status") { @@ -608,7 +609,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) WriteApportReport(list[1].c_str(), list[3].c_str()); return; } - else if(action == "conffile") + else if(action == "conffile-prompt") { d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, list[3]); @@ -1036,7 +1037,10 @@ void pkgDPkgPM::StartPtyMagic() if (tcgetattr(STDOUT_FILENO, &d->tt) == 0) { ioctl(1, TIOCGWINSZ, (char *)&win); - if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0) + if (_config->FindB("Dpkg::Use-Pty", true) == false) + { + d->master = d->slave = -1; + } else if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0) { _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); d->master = d->slave = -1; diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index b82b7efde..0caf62b61 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -9,7 +9,7 @@ #include #include #include - +#include namespace APT { namespace Progress { diff --git a/test/integration/test-apt-progress-fd-conffile b/test/integration/test-apt-progress-fd-conffile new file mode 100755 index 000000000..0b42b1b2f --- /dev/null +++ b/test/integration/test-apt-progress-fd-conffile @@ -0,0 +1,43 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'native' + +# old conffile +setupsimplenativepackage 'compiz-core' 'native' '1.0' 'unstable' +BUILDDIR='incoming/compiz-core-1.0' +mkdir -p ${BUILDDIR}/debian/compiz-core/etc +echo 'foo=bar;' > ${BUILDDIR}/compiz.conf +echo 'compiz.conf /etc/compiz.conf' >> ${BUILDDIR}/debian/install +buildpackage "$BUILDDIR" 'unstable' 'main' 'native' +rm -rf "$BUILDDIR" + +# new conffile +setupsimplenativepackage 'compiz-core' 'native' '2.0' 'unstable' +BUILDDIR='incoming/compiz-core-2.0' +mkdir -p ${BUILDDIR}/debian/compiz-core/etc +echo 'foo2=bar2;' > ${BUILDDIR}/compiz.conf +echo 'compiz.conf /etc/compiz.conf' >> ${BUILDDIR}/debian/install +buildpackage "$BUILDDIR" 'unstable' 'main' 'native' +rm -rf "$BUILDDIR" + +setupaptarchive + +testsuccess aptget install compiz-core=1.0 + +# fake conffile change +echo "meep" >> rootdir/etc/compiz.conf/compiz.conf + +# install +exec 3> apt-progress.log +echo n | aptget install compiz-core=2.0 -o APT::Status-Fd=3 -o Dpkg::Use-Pty=false + +# and ensure there is a conffile message in the file +msgtest "Conffile prompt in apt-progress.log" +grep -q "pmconffile:/etc/compiz.conf/compiz.conf" apt-progress.log && msgpass || (cat apt-progress.log && msgfail) + +cat apt-progress.log \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 4754718a4461ebff89f5b49c385a007b4197bcff Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sun, 22 Dec 2013 14:38:39 +0100 Subject: first proof-of-concept for a fix for #731738 --- apt-pkg/deb/dpkgpm.cc | 2 +- apt-pkg/install-progress.cc | 9 ++++++++- apt-pkg/install-progress.h | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4bfd1400..b9f839e82 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1182,7 +1182,7 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) StartPtyMagic(); // Tell the progress that its starting and fork dpkg - d->progress->Start(); + d->progress->Start(d->master); // this loop is runs once per dpkg operation vector::const_iterator I = List.begin(); diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index b82b7efde..2215fb1f5 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -273,11 +273,18 @@ void PackageManagerFancy::HandleSIGWINCH(int) SetupTerminalScrollArea(nr_terminal_rows); } -void PackageManagerFancy::Start() +void PackageManagerFancy::Start(int child_pty) { int nr_terminal_rows = GetNumberTerminalRows(); if (nr_terminal_rows > 0) + { SetupTerminalScrollArea(nr_terminal_rows); + // *cough* + struct winsize win; + ioctl(child_pty, TIOCGWINSZ, (char *)&win); + win.ws_row = nr_terminal_rows - 1; + ioctl(child_pty, TIOCSWINSZ, (char *)&win); + } } void PackageManagerFancy::Stop() diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 4b7590983..010be82fd 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -28,7 +28,7 @@ namespace Progress { virtual ~PackageManager() {}; /* Global Start/Stop */ - virtual void Start() {}; + virtual void Start(int child_pty=-1) {}; virtual void Stop() {}; /* When dpkg is invoked (may happen multiple times for each @@ -125,7 +125,7 @@ namespace Progress { public: PackageManagerFancy(); ~PackageManagerFancy(); - virtual void Start(); + virtual void Start(int child_pty=-1); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, -- cgit v1.2.3-70-g09d2 From 9ce3cfc9309c55cc01018c88c1ca82779fd74431 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 16 Jan 2014 22:19:49 +0100 Subject: correct some style/performance/warnings from cppcheck The most "visible" change is from utime to utimensat/futimens as the first one isn't part of POSIX anymore. Reported-By: cppcheck Git-Dch: Ignore --- apt-inst/dirstream.cc | 20 +++++++--------- apt-pkg/contrib/fileutl.cc | 2 +- apt-pkg/contrib/gpgv.cc | 5 ++-- apt-pkg/contrib/hashes.cc | 5 ++-- apt-pkg/contrib/hashsum.cc | 7 +++--- apt-pkg/deb/dpkgpm.cc | 9 +++---- apt-pkg/install-progress.cc | 2 +- apt-private/private-list.cc | 12 +++++----- apt-private/private-search.cc | 8 +++---- ftparchive/multicompress.cc | 10 ++++---- methods/connect.cc | 6 ++--- methods/copy.cc | 18 +++++++------- methods/ftp.cc | 49 +++++++++++++++++++++------------------ methods/gzip.cc | 26 +++++++++++---------- methods/http.cc | 4 +--- methods/https.cc | 10 ++++---- methods/https.h | 2 +- methods/mirror.cc | 8 +++---- methods/rsh.cc | 36 ++++++++++++++-------------- methods/server.cc | 25 ++++++++++---------- methods/server.h | 2 +- test/interactive-helper/rpmver.cc | 9 ++++--- 22 files changed, 133 insertions(+), 142 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-inst/dirstream.cc b/apt-inst/dirstream.cc index 65d1aa188..b62bdcae1 100644 --- a/apt-inst/dirstream.cc +++ b/apt-inst/dirstream.cc @@ -20,7 +20,6 @@ #include #include #include -#include #include #include /*}}}*/ @@ -93,19 +92,18 @@ bool pkgDirStream::FinishedFile(Item &Itm,int Fd) { if (Fd < 0) return true; - - if (close(Fd) != 0) - return _error->Errno("close",_("Failed to close file %s"),Itm.Name); /* Set the modification times. The only way it can fail is if someone has futzed with our file, which is intolerable :> */ - struct utimbuf Time; - Time.actime = Itm.MTime; - Time.modtime = Itm.MTime; - if (utime(Itm.Name,&Time) != 0) - _error->Errno("utime",_("Failed to close file %s"),Itm.Name); - - return true; + struct timespec times[2]; + times[0].tv_sec = times[1].tv_sec = Itm.MTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + if (futimens(Fd, times) != 0) + _error->Errno("futimens", "Failed to set modification time for %s",Itm.Name); + + if (close(Fd) != 0) + return _error->Errno("close",_("Failed to close file %s"),Itm.Name); + return true; } /*}}}*/ // DirStream::Fail - Failed processing a file /*{{{*/ diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index efbf7aaf4..1c8acd513 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -319,7 +319,7 @@ bool CreateDirectory(string const &Parent, string const &Path) return false; // we are not going to create directories "into the blue" - if (Path.find(Parent, 0) != 0) + if (Path.compare(0, Parent.length(), Parent) != 0) return false; vector const dirs = VectorizeString(Path.substr(Parent.size()), '/'); diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index 0a469dd7a..9de227062 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -260,8 +260,7 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, char *buf = NULL; size_t buf_size = 0; - ssize_t line_len = 0; - while ((line_len = getline(&buf, &buf_size, in)) != -1) + while (getline(&buf, &buf_size, in) != -1) { _strrstrip(buf); if (found_message_start == false) @@ -355,7 +354,7 @@ bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &Me return _error->Error("Couldn't open temporary file to work with %s", ClearSignedFileName.c_str()); _error->PushToStack(); - bool const splitDone = SplitClearSignedFile(ClearSignedFileName.c_str(), &MessageFile, NULL, NULL); + bool const splitDone = SplitClearSignedFile(ClearSignedFileName, &MessageFile, NULL, NULL); bool const errorDone = _error->PendingError(); _error->MergeWithStack(); if (splitDone == false) diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index b4c768db9..890573d9c 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -129,13 +129,12 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512) { unsigned char Buf[64*64]; - ssize_t Res = 0; - int ToEOF = (Size == 0); + bool const ToEOF = (Size == 0); while (Size != 0 || ToEOF) { unsigned long long n = sizeof(Buf); if (!ToEOF) n = std::min(Size, n); - Res = read(Fd,Buf,n); + ssize_t const Res = read(Fd,Buf,n); if (Res < 0 || (!ToEOF && Res != (ssize_t) n)) // error, or short read return false; if (ToEOF && Res == 0) // EOF diff --git a/apt-pkg/contrib/hashsum.cc b/apt-pkg/contrib/hashsum.cc index 289e43aa4..d02177724 100644 --- a/apt-pkg/contrib/hashsum.cc +++ b/apt-pkg/contrib/hashsum.cc @@ -9,13 +9,12 @@ /* */ bool SummationImplementation::AddFD(int const Fd, unsigned long long Size) { unsigned char Buf[64 * 64]; - ssize_t Res = 0; - int ToEOF = (Size == 0); + bool const ToEOF = (Size == 0); while (Size != 0 || ToEOF) { unsigned long long n = sizeof(Buf); if (!ToEOF) n = std::min(Size, n); - Res = read(Fd, Buf, n); + ssize_t const Res = read(Fd, Buf, n); if (Res < 0 || (!ToEOF && Res != (ssize_t) n)) // error, or short read return false; if (ToEOF && Res == 0) // EOF @@ -27,7 +26,7 @@ bool SummationImplementation::AddFD(int const Fd, unsigned long long Size) { } bool SummationImplementation::AddFD(FileFd &Fd, unsigned long long Size) { unsigned char Buf[64 * 64]; - bool ToEOF = (Size == 0); + bool const ToEOF = (Size == 0); while (Size != 0 || ToEOF) { unsigned long long n = sizeof(Buf); diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 14ce133cf..1967d5d26 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -568,7 +568,6 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) std::string prefix = APT::String::Strip(list[0]); std::string pkgname; std::string action; - ostringstream status; // "processing" has the form "processing: action: pkg or trigger" // with action = ["install", "configure", "remove", "purge", "disappear", @@ -1652,7 +1651,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) 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")); - for (vector::iterator I = io_errors.begin(); I != io_errors.end(); I++) + for (vector::iterator I = io_errors.begin(); I != io_errors.end(); ++I) { vector list = VectorizeString(dgettext("dpkg", (*I).c_str()), '%'); if (list.size() > 1) { @@ -1767,13 +1766,11 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) string histfile_name = _config->FindFile("Dir::Log::History"); if (!histfile_name.empty()) { - FILE *log = NULL; - char buf[1024]; - fprintf(report, "DpkgHistoryLog:\n"); - log = fopen(histfile_name.c_str(),"r"); + FILE* log = fopen(histfile_name.c_str(),"r"); if(log != NULL) { + char buf[1024]; while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); fclose(log); diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index fe065da4f..a3a4cc0e1 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -242,7 +242,7 @@ PackageManagerFancy::~PackageManagerFancy() void PackageManagerFancy::staticSIGWINCH(int signum) { std::vector::const_iterator I; - for(I = instances.begin(); I != instances.end(); I++) + for(I = instances.begin(); I != instances.end(); ++I) (*I)->HandleSIGWINCH(signum); } diff --git a/apt-private/private-list.cc b/apt-private/private-list.cc index a02ebf02d..898ee7222 100644 --- a/apt-private/private-list.cc +++ b/apt-private/private-list.cc @@ -61,7 +61,7 @@ class PackageNameMatcher : public Matcher /*{{{*/ public: PackageNameMatcher(const char **patterns) { - for(int i=0; patterns[i] != NULL; i++) + for(int i=0; patterns[i] != NULL; ++i) { std::string pattern = patterns[i]; #ifdef PACKAGE_MATCHER_ABI_COMPAT @@ -79,12 +79,12 @@ class PackageNameMatcher : public Matcher /*{{{*/ } virtual ~PackageNameMatcher() { - for(J=filters.begin(); J != filters.end(); J++) + for(J=filters.begin(); J != filters.end(); ++J) delete *J; } virtual bool operator () (const pkgCache::PkgIterator &P) { - for(J=filters.begin(); J != filters.end(); J++) + for(J=filters.begin(); J != filters.end(); ++J) { APT::CacheFilter::PackageMatcher *cachefilter = *J; if((*cachefilter)(P)) @@ -104,7 +104,7 @@ void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ std::ostream &outs) { for (pkgCache::VerIterator Ver = P.VersionList(); - Ver.end() == false; Ver++) + Ver.end() == false; ++Ver) ListSingleVersion(CacheFile, records, Ver, outs); } /*}}}*/ @@ -142,7 +142,7 @@ bool List(CommandLine &Cmd) Cache->Head().PackageCount, _("Listing")); GetLocalitySortedVersionSet(CacheFile, bag, matcher, progress); - for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); V++) + for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); ++V) { std::stringstream outs; if(_config->FindB("APT::Cmd::All-Versions", false) == true) @@ -159,7 +159,7 @@ bool List(CommandLine &Cmd) // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status) // output the sorted map - for (K = output_map.begin(); K != output_map.end(); K++) + for (K = output_map.begin(); K != output_map.end(); ++K) std::cout << (*K).second << std::endl; diff --git a/apt-private/private-search.cc b/apt-private/private-search.cc index ff4140fa7..ade12353a 100644 --- a/apt-private/private-search.cc +++ b/apt-private/private-search.cc @@ -61,18 +61,18 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ progress.OverallProgress(50, 100, 50, _("Full Text Search")); progress.SubProgress(bag.size()); int Done = 0; - for ( ;V != bag.end(); V++) + for ( ;V != bag.end(); ++V) { if (Done%500 == 0) progress.Progress(Done); - Done++; + ++Done; int i; pkgCache::DescIterator Desc = V.TranslatedDescription(); pkgRecords::Parser &parser = records.Lookup(Desc.FileList()); bool all_found = true; - for(i=0; patterns[i] != NULL; i++) + for(i=0; patterns[i] != NULL; ++i) { // FIXME: use regexp instead of simple find() const char *pattern = patterns[i]; @@ -93,7 +93,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status) // output the sorted map - for (K = output_map.begin(); K != output_map.end(); K++) + for (K = output_map.begin(); K != output_map.end(); ++K) std::cout << (*K).second << std::endl; return true; diff --git a/ftparchive/multicompress.cc b/ftparchive/multicompress.cc index 1fea589e2..265fb1a80 100644 --- a/ftparchive/multicompress.cc +++ b/ftparchive/multicompress.cc @@ -21,9 +21,9 @@ #include #include +#include #include #include -#include #include #include @@ -234,14 +234,12 @@ bool MultiCompress::Finalize(unsigned long long &OutSize) else { // Update the mtime if necessary - if (UpdateMTime > 0 && + if (UpdateMTime > 0 && (Now - St.st_mtime > (signed)UpdateMTime || St.st_mtime > Now)) { - struct utimbuf Buf; - Buf.actime = Buf.modtime = Now; - utime(I->Output.c_str(),&Buf); + utimensat(AT_FDCWD, I->Output.c_str(), NULL, AT_SYMLINK_NOFOLLOW); Changed = true; - } + } } // Force the file permissions diff --git a/methods/connect.cc b/methods/connect.cc index fc7a72ee9..d9c9a1dd4 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -142,9 +142,9 @@ bool Connect(std::string Host,int Port,const char *Service,int DefPort,int &Fd, // Convert the port name/number char ServStr[300]; if (Port != 0) - snprintf(ServStr,sizeof(ServStr),"%u",Port); + snprintf(ServStr,sizeof(ServStr),"%i", Port); else - snprintf(ServStr,sizeof(ServStr),"%s",Service); + snprintf(ServStr,sizeof(ServStr),"%s", Service); /* We used a cached address record.. Yes this is against the spec but the way we have setup our rotating dns suggests that this is more @@ -190,7 +190,7 @@ bool Connect(std::string Host,int Port,const char *Service,int DefPort,int &Fd, { if (DefPort != 0) { - snprintf(ServStr,sizeof(ServStr),"%u",DefPort); + snprintf(ServStr, sizeof(ServStr), "%i", DefPort); DefPort = 0; continue; } diff --git a/methods/copy.cc b/methods/copy.cc index e81d0022b..744cc2b51 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -18,7 +18,6 @@ #include #include -#include #include #include /*}}}*/ @@ -71,18 +70,19 @@ bool CopyMethod::Fetch(FetchItem *Itm) } From.Close(); - To.Close(); - + // Transfer the modification times - struct utimbuf TimeBuf; - TimeBuf.actime = Buf.st_atime; - TimeBuf.modtime = Buf.st_mtime; - if (utime(Itm->DestFile.c_str(),&TimeBuf) != 0) + struct timespec times[2]; + times[0].tv_sec = Buf.st_atime; + times[1].tv_sec = Buf.st_mtime; + times[0].tv_nsec = times[1].tv_nsec = 0; + if (futimens(To.Fd(), times) != 0) { To.OpFail(); - return _error->Errno("utime",_("Failed to set modification time")); + return _error->Errno("futimens",_("Failed to set modification time")); } - + To.Close(); + Hashes Hash; FileFd Fd(Res.Filename, FileFd::ReadOnly); Hash.AddFD(Fd); diff --git a/methods/ftp.cc b/methods/ftp.cc index 979adca62..2d05364d5 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -953,14 +952,16 @@ void FtpMethod::SigTerm(int) { if (FailFd == -1) _exit(100); - close(FailFd); - + // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(FailFile.c_str(),&UBuf); - + struct timespec times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(FailFd, times); + + close(FailFd); + _exit(100); } /*}}}*/ @@ -1059,13 +1060,14 @@ bool FtpMethod::Fetch(FetchItem *Itm) if (Server->Get(File,Fd,Res.ResumePoint,Hash,Missing) == false) { Fd.Close(); - + // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(FailFile.c_str(),&UBuf); - + struct timespec times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(FailFd, times); + // If the file is missing we hard fail and delete the destfile // otherwise transient fail if (Missing == true) { @@ -1077,20 +1079,21 @@ bool FtpMethod::Fetch(FetchItem *Itm) } Res.Size = Fd.Size(); + + // Timestamp + struct timespec times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(Fd.Fd(), times); + FailFd = -1; } - + Res.LastModified = FailTime; Res.TakeHashes(Hash); - - // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(Queue->DestFile.c_str(),&UBuf); - FailFd = -1; URIDone(Res); - + return true; } /*}}}*/ diff --git a/methods/gzip.cc b/methods/gzip.cc index 48c8e9892..f1edb353b 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -94,32 +93,35 @@ bool GzipMethod::Fetch(FetchItem *Itm) } From.Close(); - To.Close(); - + if (Failed == true) return false; - + // Transfer the modification times struct stat Buf; if (stat(Path.c_str(),&Buf) != 0) return _error->Errno("stat",_("Failed to stat")); - struct utimbuf TimeBuf; - TimeBuf.actime = Buf.st_atime; - TimeBuf.modtime = Buf.st_mtime; - if (utime(Itm->DestFile.c_str(),&TimeBuf) != 0) - return _error->Errno("utime",_("Failed to set modification time")); + struct timespec times[2]; + times[0].tv_sec = Buf.st_atime; + times[1].tv_sec = Buf.st_mtime; + times[0].tv_nsec = times[1].tv_nsec = 0; + if (futimens(To.Fd(), times) != 0) + { + To.OpFail(); + return _error->Errno("futimens",_("Failed to set modification time")); + } + Res.Size = To.FileSize(); + To.Close(); if (stat(Itm->DestFile.c_str(),&Buf) != 0) return _error->Errno("stat",_("Failed to stat")); - + // Return a Done response Res.LastModified = Buf.st_mtime; - Res.Size = Buf.st_size; Res.TakeHashes(Hash); URIDone(Res); - return true; } /*}}}*/ diff --git a/methods/http.cc b/methods/http.cc index b22b61efc..e1390afcb 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -97,8 +97,6 @@ void CircleBuf::Reset() is non-blocking.. */ bool CircleBuf::Read(int Fd) { - unsigned long long BwReadMax; - while (1) { // Woops, buffer is full @@ -106,7 +104,7 @@ bool CircleBuf::Read(int Fd) return true; // what's left to read in this tick - BwReadMax = CircleBuf::BwReadLimit/BW_HZ; + unsigned long long const BwReadMax = CircleBuf::BwReadLimit/BW_HZ; if(CircleBuf::BwReadLimit) { struct timeval now; diff --git a/methods/https.cc b/methods/https.cc index 2a562434b..e16e36339 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -405,10 +404,11 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_getinfo(curl, CURLINFO_FILETIME, &Res.LastModified); if (Res.LastModified != -1) { - struct utimbuf UBuf; - UBuf.actime = Res.LastModified; - UBuf.modtime = Res.LastModified; - utime(File->Name().c_str(),&UBuf); + struct timespec times[2]; + times[0].tv_sec = Res.LastModified; + times[1].tv_sec = Res.LastModified; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(File->Fd(), times); } else Res.LastModified = resultStat.st_mtime; diff --git a/methods/https.h b/methods/https.h index 8632d6d02..89a89d19c 100644 --- a/methods/https.h +++ b/methods/https.h @@ -65,7 +65,7 @@ class HttpsMethod : public pkgAcqMethod public: FileFd *File; - HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig) + HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), File(NULL) { File = 0; curl = curl_easy_init(); diff --git a/methods/mirror.cc b/methods/mirror.cc index 854366318..83ef0d133 100644 --- a/methods/mirror.cc +++ b/methods/mirror.cc @@ -114,7 +114,7 @@ bool MirrorMethod::Clean(string Dir) for(I=list.begin(); I != list.end(); ++I) { string uri = (*I)->GetURI(); - if(uri.find("mirror://") != 0) + if(uri.compare(0, strlen("mirror://"), "mirror://") != 0) continue; string BaseUri = uri.substr(0,uri.size()-1); if (URItoFileName(BaseUri) == Dir->d_name) @@ -198,9 +198,9 @@ bool MirrorMethod::RandomizeMirrorFile(string mirror_file) // "stable" on the same machine. this is to avoid running into out-of-sync // issues (i.e. Release/Release.gpg different on each mirror) struct utsname buf; - int seed=1, i; + int seed=1; if(uname(&buf) == 0) { - for(i=0,seed=1; buf.nodename[i] != 0; i++) { + for(int i=0,seed=1; buf.nodename[i] != 0; ++i) { seed = seed * 31 + buf.nodename[i]; } } @@ -306,7 +306,7 @@ bool MirrorMethod::InitMirrors() if (s.size() == 0) continue; // ignore non http lines - if (s.find("http://") != 0) + if (s.compare(0, strlen("http://"), "http://") != 0) continue; AllMirrors.push_back(s); diff --git a/methods/rsh.cc b/methods/rsh.cc index d76dca6ef..a441220bf 100644 --- a/methods/rsh.cc +++ b/methods/rsh.cc @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -395,13 +394,14 @@ void RSHMethod::SigTerm(int sig) { if (FailFd == -1) _exit(100); - close(FailFd); - // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(FailFile.c_str(),&UBuf); + // Transfer the modification times + struct timespec times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(FailFd, times); + close(FailFd); _exit(100); } @@ -488,10 +488,11 @@ bool RSHMethod::Fetch(FetchItem *Itm) Fd.Close(); // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(FailFile.c_str(),&UBuf); + struct timespec times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(FailFd, times); // If the file is missing we hard fail otherwise transient fail if (Missing == true) @@ -501,18 +502,17 @@ bool RSHMethod::Fetch(FetchItem *Itm) } Res.Size = Fd.Size(); + struct timespec times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(Fd.Fd(), times); + FailFd = -1; } Res.LastModified = FailTime; Res.TakeHashes(Hash); - // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(Queue->DestFile.c_str(),&UBuf); - FailFd = -1; - URIDone(Res); return true; diff --git a/methods/server.cc b/methods/server.cc index a2128441c..e12c23c07 100644 --- a/methods/server.cc +++ b/methods/server.cc @@ -17,9 +17,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -368,14 +368,14 @@ void ServerMethod::SigTerm(int) { if (FailFd == -1) _exit(100); + + struct timespec times[2]; + times[0].tv_sec = FailTime; + times[1].tv_sec = FailTime; + times[0].tv_nsec = times[1].tv_nsec = 0; + futimens(FailFd, times); close(FailFd); - - // Timestamp - struct utimbuf UBuf; - UBuf.actime = FailTime; - UBuf.modtime = FailTime; - utime(FailFile.c_str(),&UBuf); - + _exit(100); } /*}}}*/ @@ -539,11 +539,10 @@ int ServerMethod::Loop() File = 0; // Timestamp - struct utimbuf UBuf; - time(&UBuf.actime); - UBuf.actime = Server->Date; - UBuf.modtime = Server->Date; - utime(Queue->DestFile.c_str(),&UBuf); + struct timespec times[2]; + times[0].tv_sec = times[1].tv_sec = Server->Date; + times[0].tv_nsec = times[1].tv_nsec = 0; + utimensat(AT_FDCWD, Queue->DestFile.c_str(), times, AT_SYMLINK_NOFOLLOW); // Send status to APT if (Result == true) diff --git a/methods/server.h b/methods/server.h index 4dc6a1f2f..2b81e6173 100644 --- a/methods/server.h +++ b/methods/server.h @@ -137,7 +137,7 @@ class ServerMethod : public pkgAcqMethod virtual ServerState * CreateServerState(URI uri) = 0; virtual void RotateDNS() = 0; - ServerMethod(const char *Ver,unsigned long Flags = 0) : pkgAcqMethod(Ver, Flags), PipelineDepth(0), AllowRedirect(false), Debug(false) {}; + ServerMethod(const char *Ver,unsigned long Flags = 0) : pkgAcqMethod(Ver, Flags), Server(NULL), File(NULL), PipelineDepth(0), AllowRedirect(false), Debug(false) {}; virtual ~ServerMethod() {}; }; diff --git a/test/interactive-helper/rpmver.cc b/test/interactive-helper/rpmver.cc index 9fc807de8..15c96cbbe 100644 --- a/test/interactive-helper/rpmver.cc +++ b/test/interactive-helper/rpmver.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include #define xisdigit(x) isdigit(x) @@ -12,10 +13,8 @@ using namespace std; int rpmvercmp(const char * a, const char * b) { - char oldch1, oldch2; char * str1, * str2; char * one, * two; - int rc; int isnum; /* easy comparison to see if versions are identical */ @@ -53,9 +52,9 @@ int rpmvercmp(const char * a, const char * b) /* save character at the end of the alpha or numeric segment */ /* so that they can be restored after the comparison */ - oldch1 = *str1; + char oldch1 = *str1; *str1 = '\0'; - oldch2 = *str2; + char oldch2 = *str2; *str2 = '\0'; /* take care of the case where the two version segments are */ @@ -81,7 +80,7 @@ int rpmvercmp(const char * a, const char * b) /* segments are alpha or if they are numeric. don't return */ /* if they are equal because there might be more segments to */ /* compare */ - rc = strcmp(one, two); + int rc = strcmp(one, two); if (rc) return rc; /* restore character that was replaced by null above */ -- cgit v1.2.3-70-g09d2 From 1700c3cfb902f3f61fa4d9269523467fcceaaf58 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 18 Jan 2014 23:42:51 +0100 Subject: do not ignore ioctl(TIOCSCTTY) errors Show a proper error message when a ioctl() in dpkgpm.cc fails. Also simply StartPtyMagic() a bit. --- apt-pkg/deb/dpkgpm.cc | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'apt-pkg/deb/dpkgpm.cc') diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 14ce133cf..506ebf620 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1028,6 +1028,12 @@ bool pkgDPkgPM::Go(int StatusFd) void pkgDPkgPM::StartPtyMagic() { + if (_config->FindB("Dpkg::Use-Pty", true) == false) + { + d->master = d->slave = -1; + return; + } + // setup the pty and stuff struct winsize win; @@ -1036,10 +1042,9 @@ void pkgDPkgPM::StartPtyMagic() _error->PushToStack(); if (tcgetattr(STDOUT_FILENO, &d->tt) == 0) { - ioctl(1, TIOCGWINSZ, (char *)&win); - if (_config->FindB("Dpkg::Use-Pty", true) == false) + if (ioctl(1, TIOCGWINSZ, (char *)&win) < 0) { - d->master = d->slave = -1; + _error->Errno("ioctl", _("ioctl(TIOCGWINSZ) failed")); } else if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0) { _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); @@ -1393,12 +1398,17 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) if(d->slave >= 0 && d->master >= 0) { setsid(); - ioctl(d->slave, TIOCSCTTY, 0); - close(d->master); - dup2(d->slave, 0); - dup2(d->slave, 1); - dup2(d->slave, 2); - close(d->slave); + int res = ioctl(d->slave, TIOCSCTTY, 0); + if (res < 0) { + std::cerr << "ioctl(TIOCSCTTY) failed for fd: " + << d->slave << std::endl; + } else { + close(d->master); + dup2(d->slave, 0); + dup2(d->slave, 1); + dup2(d->slave, 2); + close(d->slave); + } } close(fd[0]); // close the read end of the pipe -- cgit v1.2.3-70-g09d2