summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2005-08-19 15:30:19 +0000
committerMichael Vogt <michael.vogt@ubuntu.com>2005-08-19 15:30:19 +0000
commit16176b647e76f316ec98f31f6dd806a49d7b8a77 (patch)
tree442d538ff8e0b54ba8ae60fe95733b0dc56a9576 /apt-pkg
parent4a0a786f45a78eb8631c0e2d39d804ab9fdea214 (diff)
* merged with mainline
Patches applied: * andrelop@debian.org/apt--translation--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-79 * andrelop@debian.org/apt--translation--0--patch-1 Sync with Matt version. * andrelop@debian.org/apt--translation--0--patch-2 Update pt_BR translation * andrelop@debian.org/apt--translation--0--patch-3 Sync with bubulle's branch. * apt@packages.debian.org/apt--main--0--patch-88 Change debian/bugscript to use #!/bin/bash (Closes: #313402) * apt@packages.debian.org/apt--main--0--patch-89 Branch for Debian * apt@packages.debian.org/apt--main--0--patch-90 Update version in configure * apt@packages.debian.org/apt--main--0--patch-91 Fix French man page build * apt@packages.debian.org/apt--main--0--patch-92 Add the current Debian archive signing key * apt@packages.debian.org/apt--main--0--patch-93 Merge with mvo * apt@packages.debian.org/apt--main--0--patch-94 Update changelog * apt@packages.debian.org/apt--main--0--patch-95 Merge Christian's branch * apt@packages.debian.org/apt--main--0--patch-96 Update changelog * apt@packages.debian.org/apt--main--0--patch-97 Update priority of apt-utils to important, to match the override file * apt@packages.debian.org/apt--main--0--patch-98 Install only one keyring on each branch (Closes: #316119) * apt@packages.debian.org/apt--main--0--patch-99 Finalize 0.6.39 * apt@packages.debian.org/apt--main--0--patch-100 Use debian.org address in mainline * apt@packages.debian.org/apt--main--0--patch-101 Update pot file * apt@packages.debian.org/apt--main--0--patch-102 Open 0.6.40 * apt@packages.debian.org/apt--main--0--patch-103 Patch from Jordi Mallach to mark some additional strings for translation * apt@packages.debian.org/apt--main--0--patch-104 Updated Catalan translation from Jordi Mallach * apt@packages.debian.org/apt--main--0--patch-105 Merge from bubulle@debian.org--2005/apt--main--0 * apt@packages.debian.org/apt--main--0--patch-106 Restore lost changelog entries * apt@packages.debian.org/apt--main--0--patch-107 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * apt@packages.debian.org/apt--main--0--patch-108 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * apt@packages.debian.org/apt--main--0--patch-109 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * apt@packages.debian.org/apt--main--0--patch-110 Merge michael.vogt@ubuntu.com--2005/apt--progress-reporting--0 * bubulle@debian.org--2005/apt--main--0--patch-82 Fix permissions * bubulle@debian.org--2005/apt--main--0--patch-83 French translation spellchecked * bubulle@debian.org--2005/apt--main--0--patch-84 Spell corrections in German translations * bubulle@debian.org--2005/apt--main--0--patch-85 Correct some file permissions * bubulle@debian.org--2005/apt--main--0--patch-86 Correct Hebrew translation * bubulle@debian.org--2005/apt--main--0--patch-87 Sync Portuguese translation with the POT file * bubulle@debian.org--2005/apt--main--0--patch-88 Updated Danish translation (not yet complete) * bubulle@debian.org--2005/apt--main--0--patch-89 Sync with Andre Luis Lopes and Otavio branches * bubulle@debian.org--2005/apt--main--0--patch-90 Merge with Matt * bubulle@debian.org--2005/apt--main--0--patch-91 Updated Slovak translation * bubulle@debian.org--2005/apt--main--0--patch-92 Add apt-key French man page * bubulle@debian.org--2005/apt--main--0--patch-93 Update Greek translations * bubulle@debian.org--2005/apt--main--0--patch-94 Merge with Matt * bubulle@debian.org--2005/apt--main--0--patch-95 Sync PO files with the POT file/French translation update * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-22 * added myself to uploaders, changelog is signed with mvo@debian.org and in sync with the debian/experimental upload * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-23 * apt-cache show <virtual-pkg> shows all virtual packages instead of nothing (thanks to otavio) * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-24 * changelog updated * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-25 * make pinning on component work again (we just use the section, as apt-0.6 don't use per-section Release files anymore) * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-27 * updated the changelog * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-28 * merged with my apt--fixes--0 branch * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-29 * added a missing OpProgress::Done() in depCache::Init(), removed the show-virtual-packages patch in apt-cache because matt does not like him :/ * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-30 * fix a stupid bug in the depcache::Init() code * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-31 * merged/removed conflicts with apt--main--0 * michael.vogt@ubuntu.com--2005/apt--mvo--0--patch-32 * merged apt--main and make sure that the po files come from apt--main (because they are more recent) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-85 * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-1 * inital proof of concept code, understands what dpkg tells it already * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-2 * progress reporting works now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-3 * added "APT::Status-Fd" variable * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-4 * do i18n now too * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-5 * define N_(x) if it is not defined already * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-6 * PackageManager::DoInstall(int status_fd) added (does not break the ABI) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-7 * merged with apt--fixes--0 to make it build again * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-8 * added support for "error" and "conffile-prompt" messages from dpkg * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-9 merge with main * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-10 * use sizeof() for all snprintf() uses; fix a potential line break problem in the status reading code; changed the N_() to _() calls * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-11 * added APT::KeepFDs configuration list for file descriptors that apt should leave open (needed for various frontends like debconf, synaptic) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-12 * fixed a API breakage * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-13 * doc added, should be releasable now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-14 * merged with apt--main--0 * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-15 * more source comments, added Debug::DpkgPM debug code to inspect the dpkg<->apt communication, broke the abi (ok with matt) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-16 * the progress reporting has it's own "Debug::pkgDPkgProgressReporting" debug variable now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-17 * merged PackageOps and TranslatedPackageOps into a single Map with the new DpkgState struct * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-18 * clear the APT::Keep-Fds configuration when it's no longer needed * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-19 * rewrote the reading from dpkg so that it never blocks * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-20 * merged the two status arrays into one * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-21 * added support for download progress reporting too (for Kamion and base-config) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-22 * ABI break; added Configuration::Clear(string List, {int,string} value) added (to remove a single Value from a list); test/conf_clear.cc added * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-23 * remvoed a debug string * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-24 * soname changed, fixed a bug in the parsing code when dpkg send the same state more than once (at the end) * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-25 * merged with apt@packages.debian.org/apt--main--0, added changelog entry for the 0.6.40.1 upload * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-26 * fix a bug when out-of-order states are send from dpkg * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-27 * changelog update * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-28 * a real changelog entry now * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-29 * changelog finalized * michael.vogt@ubuntu.com--2005/apt--progress-reporting--0--patch-30 * propper (and sane) support for pmerror and pmconffile added
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire.cc21
-rw-r--r--apt-pkg/contrib/configuration.cc45
-rw-r--r--apt-pkg/contrib/configuration.h7
-rw-r--r--apt-pkg/contrib/fileutl.cc24
-rw-r--r--apt-pkg/contrib/fileutl.h2
-rw-r--r--apt-pkg/deb/debindexfile.cc4
-rw-r--r--apt-pkg/deb/deblistparser.cc11
-rw-r--r--apt-pkg/deb/deblistparser.h3
-rw-r--r--apt-pkg/deb/dpkgpm.cc242
-rw-r--r--apt-pkg/deb/dpkgpm.h9
-rw-r--r--apt-pkg/depcache.cc3
-rw-r--r--apt-pkg/init.h2
-rw-r--r--apt-pkg/makefile2
-rw-r--r--apt-pkg/packagemanager.cc4
-rw-r--r--apt-pkg/packagemanager.h2
15 files changed, 337 insertions, 44 deletions
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index 212c8d52b..47655af80 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -26,6 +26,7 @@
#include <apti18n.h>
#include <iostream>
+#include <sstream>
#include <dirent.h>
#include <sys/time.h>
@@ -807,6 +808,26 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
Time = NewTime;
}
+ int fd = _config->FindI("APT::Status-Fd",-1);
+ if(fd > 0)
+ {
+ ostringstream status;
+
+ char msg[200];
+ long i = CurrentItems < TotalItems ? CurrentItems + 1 : CurrentItems;
+ unsigned long ETA =
+ (unsigned long)((TotalBytes - CurrentBytes) / CurrentCPS);
+
+ snprintf(msg,sizeof(msg), _("Downloading file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str());
+
+ // build the status str
+ status << "dlstatus:" << i
+ << ":" << (CurrentBytes/float(TotalBytes)*100.0)
+ << ":" << msg
+ << endl;
+ write(fd, status.str().c_str(), status.str().size());
+ }
+
return true;
}
/*}}}*/
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 69f8d1dca..09e454be9 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -327,15 +327,56 @@ void Configuration::Set(const char *Name,int Value)
Itm->Value = S;
}
/*}}}*/
+// Configuration::Clear - Clear an single value from a list /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Configuration::Clear(string Name, int Value)
+{
+ char S[300];
+ snprintf(S,sizeof(S),"%i",Value);
+ Clear(Name, S);
+}
+ /*}}}*/
+// Configuration::Clear - Clear an single value from a list /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Configuration::Clear(string Name, string Value)
+{
+ Item *Top = Lookup(Name.c_str(),false);
+ if (Top == 0 || Top->Child == 0)
+ return;
+
+ Item *Tmp, *Prev, *I;
+ Prev = I = Top->Child;
+
+ while(I != NULL)
+ {
+ if(I->Value == Value)
+ {
+ Tmp = I;
+ // was first element, point parent to new first element
+ if(Top->Child == Tmp)
+ Top->Child = I->Next;
+ I = I->Next;
+ Prev->Next = I;
+ delete Tmp;
+ } else {
+ Prev = I;
+ I = I->Next;
+ }
+ }
+
+}
+ /*}}}*/
// Configuration::Clear - Clear an entire tree /*{{{*/
// ---------------------------------------------------------------------
/* */
void Configuration::Clear(string Name)
{
Item *Top = Lookup(Name.c_str(),false);
- if (Top == 0)
+ if (Top == 0)
return;
-
+
Top->Value = string();
Item *Stop = Top;
Top = Top->Child;
diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h
index 0ed8f59d3..789bc82cf 100644
--- a/apt-pkg/contrib/configuration.h
+++ b/apt-pkg/contrib/configuration.h
@@ -87,8 +87,13 @@ class Configuration
bool Exists(const char *Name) const;
bool ExistsAny(const char *Name) const;
+ // clear a whole tree
void Clear(string Name);
-
+
+ // remove a certain value from a list (e.g. the list of "APT::Keep-Fds")
+ void Clear(string List, string Value);
+ void Clear(string List, int Value);
+
inline const Item *Tree(const char *Name) const {return Lookup(Name);};
inline void Dump() { Dump(std::clog); };
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 0ce0c9b9d..9fd71728e 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -20,6 +20,7 @@
#include <apt-pkg/fileutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/sptr.h>
+#include <apt-pkg/configuration.h>
#include <apti18n.h>
@@ -32,6 +33,7 @@
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
+#include <set>
/*}}}*/
using namespace std;
@@ -306,7 +308,7 @@ bool WaitFd(int Fd,bool write,unsigned long timeout)
/* 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(int dontCloseThisFd)
+pid_t ExecFork()
{
// Fork off the process
pid_t Process = fork();
@@ -326,11 +328,27 @@ pid_t ExecFork(int dontCloseThisFd)
signal(SIGWINCH,SIG_DFL);
signal(SIGCONT,SIG_DFL);
signal(SIGTSTP,SIG_DFL);
-
+
+ set<int> 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++)
- if(K != dontCloseThisFd)
+ {
+ if(KeepFDs.find(K) == KeepFDs.end())
fcntl(K,F_SETFD,FD_CLOEXEC);
+ }
}
return Process;
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 4716e261e..041aa3309 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -87,7 +87,7 @@ string SafeGetCWD();
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(int dontCloseThisFd=-1);
+pid_t ExecFork();
bool ExecWait(pid_t Pid,const char *Name,bool Reap = false);
// File string manipulators
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index f26265fff..ff8bce85d 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -24,7 +24,7 @@
#include <apt-pkg/strutl.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/debmetaindex.h>
-
+
#include <sys/stat.h>
/*}}}*/
@@ -290,7 +290,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
FileFd Rel(ReleaseFile,FileFd::ReadOnly);
if (_error->PendingError() == true)
return false;
- Parser.LoadReleaseInfo(File,Rel);
+ Parser.LoadReleaseInfo(File,Rel,Section);
}
return true;
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index 96a80582d..25b533773 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -564,13 +564,20 @@ bool debListParser::Step()
// ---------------------------------------------------------------------
/* */
bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
- FileFd &File)
+ FileFd &File, string component)
{
pkgTagFile Tags(&File, File.Size() + 256); // XXX
pkgTagSection Section;
if (Tags.Step(Section) == false)
return false;
+ //mvo: I don't think we need to fill that in (it's unused since apt-0.6)
+ //FileI->Architecture = WriteUniqString(Arch);
+
+ // apt-secure does no longer download individual (per-section) Release
+ // file. to provide Component pinning we use the section name now
+ FileI->Component = WriteUniqString(component);
+
const char *Start;
const char *Stop;
if (Section.Find("Suite",Start,Stop) == true)
@@ -589,7 +596,7 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
if (Section.FindFlag("NotAutomatic",FileI->Flags,
pkgCache::Flag::NotAutomatic) == false)
_error->Warning("Bad NotAutomatic flag");
-
+
return !_error->PendingError();
}
/*}}}*/
diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h
index 9f305211a..3a0e0421b 100644
--- a/apt-pkg/deb/deblistparser.h
+++ b/apt-pkg/deb/deblistparser.h
@@ -55,7 +55,8 @@ class debListParser : public pkgCacheGenerator::ListParser
virtual bool Step();
- bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File);
+ bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File,
+ string section);
static const char *ParseDepends(const char *Start,const char *Stop,
string &Package,string &Ver,unsigned int &Op,
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 61c48dcbb..fe8fbca74 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -25,7 +25,11 @@
#include <signal.h>
#include <errno.h>
#include <stdio.h>
-#include <iostream>
+#include <sstream>
+#include <map>
+
+#include <config.h>
+#include <apti18n.h>
/*}}}*/
using namespace std;
@@ -325,8 +329,14 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
/*}}}*/
// DPkgPM::Go - Run the sequence /*{{{*/
// ---------------------------------------------------------------------
-/* This globs the operations and calls dpkg */
-bool pkgDPkgPM::Go(int status_fd)
+/* 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)
+ * names and calculates a percentage for each step.
+*/
+bool pkgDPkgPM::Go(int OutStatusFd)
{
unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
@@ -336,7 +346,66 @@ bool pkgDPkgPM::Go(int status_fd)
if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
return false;
+
+ // prepare the progress reporting
+ int Done = 0;
+ int Total = 0;
+ // 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[][5] = {
+ // Install operation
+ {
+ {"half-installed", _("Preparing %s")},
+ {"unpacked", _("Unpacking %s") },
+ {NULL, NULL}
+ },
+ // Configure operation
+ {
+ {"unpacked",_("Preparing to configure %s") },
+ {"half-configured", _("Configuring %s") },
+ { "installed", _("Installed %s")},
+ {NULL, NULL}
+ },
+ // Remove operation
+ {
+ {"half-configured", _("Preparing for removal of %s")},
+ {"half-installed", _("Removing %s")},
+ {"config-files", _("Removed %s")},
+ {NULL, NULL}
+ },
+ // Purge operation
+ {
+ {"config-files", _("Preparing for remove with config %s")},
+ {"not-installed", _("Removed with config %s")},
+ {NULL, NULL}
+ },
+ };
+ // the dpkg states that the pkg will run through, the string is
+ // the package, the vector contains the dpkg states that the package
+ // will go through
+ map<string,vector<struct DpkgState> > PackageOps;
+ // the dpkg states that are already done; the string is the package
+ // the int is the state that is already done (e.g. a package that is
+ // going to be install is already in state "half-installed")
+ map<string,int> PackageOpsDone;
+
+ // 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<Item>::iterator I = List.begin(); I != List.end();I++)
+ {
+ string name = (*I).Pkg.Name();
+ PackageOpsDone[name] = 0;
+ for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL; i++)
+ {
+ PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]);
+ Total++;
+ }
+ }
+
+ // this loop is runs once per operation
for (vector<Item>::iterator I = List.begin(); I != List.end();)
{
vector<Item>::iterator J = I;
@@ -367,16 +436,15 @@ bool pkgDPkgPM::Go(int status_fd)
}
}
- // if we got a status_fd argument, we pass it to apt
char status_fd_buf[20];
- if(status_fd > 0)
- {
- Args[n++] = "--status-fd";
- Size += strlen(Args[n-1]);
- snprintf(status_fd_buf,20,"%i",status_fd);
- Args[n++] = status_fd_buf;
- Size += strlen(Args[n-1]);
- }
+ int fd[2];
+ pipe(fd);
+
+ Args[n++] = "--status-fd";
+ Size += strlen(Args[n-1]);
+ snprintf(status_fd_buf,sizeof(status_fd_buf),"%i", fd[1]);
+ Args[n++] = status_fd_buf;
+ Size += strlen(Args[n-1]);
switch (I->Op)
{
@@ -449,17 +517,17 @@ bool pkgDPkgPM::Go(int status_fd)
it doesn't die but we do! So we must also ignore it */
sighandler_t old_SIGQUIT = signal(SIGQUIT,SIG_IGN);
sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
-
- // Fork dpkg
+
+ // Fork dpkg
pid_t Child;
- if(status_fd > 0)
- Child = ExecFork(status_fd);
- else
- Child = ExecFork();
+ _config->Set("APT::Keep-Fds::",fd[1]);
+ Child = ExecFork();
// This is the child
if (Child == 0)
{
+ close(fd[0]); // close the read end of the pipe
+
if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
_exit(100);
@@ -487,19 +555,141 @@ bool pkgDPkgPM::Go(int status_fd)
_exit(100);
}
+ // clear the Keep-Fd again
+ _config->Clear("APT::Keep-Fds",fd[1]);
+
// Wait for dpkg
int Status = 0;
- while (waitpid(Child,&Status,0) != Child)
- {
- if (errno == EINTR)
+
+ // we read from dpkg here
+ int _dpkgin = fd[0];
+ fcntl(_dpkgin, F_SETFL, O_NONBLOCK);
+ close(fd[1]); // close the write end of the pipe
+
+ // the read buffers for the communication with dpkg
+ char line[1024] = {0,};
+ char buf[2] = {0,0};
+
+ // the result of the waitpid call
+ int res;
+
+ while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
+ if(res < 0) {
+ // FIXME: move this to a function or something, looks ugly here
+ // error handling, waitpid returned -1
+ if (errno == EINTR)
+ continue;
+ RunScripts("DPkg::Post-Invoke");
+
+ // Restore sig int/quit
+ signal(SIGQUIT,old_SIGQUIT);
+ signal(SIGINT,old_SIGINT);
+ return _error->Errno("waitpid","Couldn't wait for subprocess");
+ }
+
+ // read a single char, make sure that the read can't block
+ // (otherwise we may leave zombies)
+ int len = read(_dpkgin, buf, 1);
+
+ // nothing to read, wait a bit for more
+ if(len <= 0)
+ {
+ usleep(1000);
continue;
- RunScripts("DPkg::Post-Invoke");
+ }
+
+ // sanity check (should never happen)
+ if(strlen(line) >= sizeof(line)-10)
+ {
+ _error->Error("got a overlong line from dpkg: '%s'",line);
+ line[0]=0;
+ }
+ // append to line, check if we got a complete line
+ strcat(line, buf);
+ if(buf[0] != '\n')
+ continue;
+
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "got from dpkg '" << line << "'" << std::endl;
+
+ // the status we output
+ ostringstream status;
+
+ /* dpkg sends strings like this:
+ 'status: <pkg>: <pkg qstate>'
+ 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
+
+ */
+ char* list[4];
+ TokSplitString(':', line, list, 5);
+ char *pkg = list[1];
+ char *action = _strstrip(list[2]);
+
+ if(strncmp(action,"error",strlen("error")) == 0)
+ {
+ status << "pmerror:" << list[1]
+ << ":" << (Done/float(Total)*100.0)
+ << ":" << list[3]
+ << endl;
+ if(OutStatusFd > 0)
+ write(OutStatusFd, status.str().c_str(), status.str().size());
+ line[0]=0;
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "send: '" << status.str() << "'" << endl;
+ continue;
+ }
+ if(strncmp(action,"conffile",strlen("conffile")) == 0)
+ {
+ status << "pmconffile:" << list[1]
+ << ":" << (Done/float(Total)*100.0)
+ << ":" << list[3]
+ << endl;
+ if(OutStatusFd > 0)
+ write(OutStatusFd, status.str().c_str(), status.str().size());
+ line[0]=0;
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "send: '" << status.str() << "'" << endl;
+ continue;
+ }
+
+ vector<struct DpkgState> &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, pkg);
+
+ // we moved from one dpkg state to a new one, report that
+ PackageOpsDone[pkg]++;
+ Done++;
+ // build the status str
+ status << "pmstatus:" << pkg
+ << ":" << (Done/float(Total)*100.0)
+ << ":" << s
+ << endl;
+ if(OutStatusFd > 0)
+ write(OutStatusFd, status.str().c_str(), status.str().size());
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "send: '" << status.str() << "'" << endl;
+
+ }
+ if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+ std::clog << "(parsed from dpkg) pkg: " << pkg
+ << " action: " << action << endl;
- // Restore sig int/quit
- signal(SIGQUIT,old_SIGQUIT);
- signal(SIGINT,old_SIGINT);
- return _error->Errno("waitpid","Couldn't wait for subprocess");
+ // reset the line buffer
+ line[0]=0;
}
+ close(_dpkgin);
// Restore sig int/quit
signal(SIGQUIT,old_SIGQUIT);
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index b59b9dc93..2ff8a9ac7 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -23,6 +23,13 @@ using std::vector;
class pkgDPkgPM : public pkgPackageManager
{
protected:
+
+ // used for progress reporting
+ struct DpkgState
+ {
+ const char *state; // the dpkg state (e.g. "unpack")
+ const char *str; // the human readable translation of the state
+ };
struct Item
{
@@ -45,7 +52,7 @@ class pkgDPkgPM : public pkgPackageManager
virtual bool Install(PkgIterator Pkg,string File);
virtual bool Configure(PkgIterator Pkg);
virtual bool Remove(PkgIterator Pkg,bool Purge = false);
- virtual bool Go(int status_fd=-1);
+ virtual bool Go(int StatusFd=-1);
virtual void Reset();
public:
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc
index c6bf3185a..dd1c794c9 100644
--- a/apt-pkg/depcache.cc
+++ b/apt-pkg/depcache.cc
@@ -91,6 +91,9 @@ bool pkgDepCache::Init(OpProgress *Prog)
}
Update(Prog);
+
+ if(Prog != 0)
+ Prog->Done();
return true;
}
diff --git a/apt-pkg/init.h b/apt-pkg/init.h
index 74ac3a7ca..8255b406a 100644
--- a/apt-pkg/init.h
+++ b/apt-pkg/init.h
@@ -18,7 +18,7 @@
// See the makefile
#define APT_PKG_MAJOR 3
-#define APT_PKG_MINOR 5
+#define APT_PKG_MINOR 11
#define APT_PKG_RELEASE 0
extern const char *pkgVersion;
diff --git a/apt-pkg/makefile b/apt-pkg/makefile
index 5f48f0f52..0e6aecc65 100644
--- a/apt-pkg/makefile
+++ b/apt-pkg/makefile
@@ -13,7 +13,7 @@ include ../buildlib/defaults.mak
# methods/makefile - FIXME
LIBRARY=apt-pkg
LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
-MAJOR=3.9
+MAJOR=3.11
MINOR=0
SLIBS=$(PTHREADLIB) $(INTLLIBS)
APT_DOMAIN:=libapt-pkg$(MAJOR)
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index a08ccd602..155408bb4 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -631,11 +631,11 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
// ---------------------------------------------------------------------
/* This uses the filenames in FileNames and the information in the
DepCache to perform the installation of packages.*/
-pkgPackageManager::OrderResult pkgPackageManager::DoInstall()
+pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int status_fd)
{
OrderResult Res = OrderInstall();
if (Res != Failed)
- if (Go() == false)
+ if (Go(status_fd) == false)
return Failed;
return Res;
}
diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h
index 43f2c4ace..f64637d03 100644
--- a/apt-pkg/packagemanager.h
+++ b/apt-pkg/packagemanager.h
@@ -76,7 +76,7 @@ class pkgPackageManager : protected pkgCache::Namespace
// Main action members
bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
pkgRecords *Recs);
- OrderResult DoInstall();
+ OrderResult DoInstall(int statusFd=-1);
bool FixMissing();
pkgPackageManager(pkgDepCache *Cache);