From d8cb4aa44573aca621110fda47d72bd682c0e3f4 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Tue, 3 Jul 2007 21:38:32 +0200
Subject: * first (raw and ineffient) implementation

---
 apt-pkg/deb/dpkgpm.cc | 77 +++++++++++++++++++++++++++++++++++++++++++++++----
 apt-pkg/makefile      |  2 +-
 cmdline/makefile      |  2 +-
 3 files changed, 73 insertions(+), 8 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index e5506d3bf..9ca519acd 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -25,6 +25,11 @@
 #include <sstream>
 #include <map>
 
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <pty.h>
+
 #include <config.h>
 #include <apti18n.h>
 									/*}}}*/
@@ -516,7 +521,24 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 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);
-	
+
+      struct	termios tt;
+      struct	winsize win;
+      int	master;
+      int	slave;
+
+      tcgetattr(0, &tt);
+      ioctl(0, TIOCGWINSZ, (char *)&win);
+      if (openpty(&master, &slave, NULL, &tt, &win) < 0) {
+	 fprintf(stderr, _("openpty failed\n"));
+      }
+
+      struct termios rtt;
+      rtt = tt;
+      cfmakeraw(&rtt);
+      rtt.c_lflag &= ~ECHO;
+      tcsetattr(0, TCSAFLUSH, &rtt);
+
        // Fork dpkg
       pid_t Child;
       _config->Set("APT::Keep-Fds::",fd[1]);
@@ -525,8 +547,16 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       // This is the child
       if (Child == 0)
       {
+	 setsid();
+	 ioctl(slave, TIOCSCTTY, 0);
+	 close(master);
+	 dup2(slave, 0);
+	 dup2(slave, 1);
+	 dup2(slave, 2);
+	 close(slave);
+
 	 close(fd[0]); // close the read end of the pipe
-	 
+
 	 if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
 	    _exit(100);
 	 
@@ -545,7 +575,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	    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("DPKG_NO_TSTP=yes");
@@ -567,11 +598,19 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
       // the read buffers for the communication with dpkg
       char line[1024] = {0,};
+      
       char buf[2] = {0,0};
+      char term_buf[2] = {0,0};
+      char input_buf[2] = {0,0};
       
       // the result of the waitpid call
       int res;
-
+      close(slave);
+      fcntl(0, F_SETFL, O_NONBLOCK);
+      fcntl(master, F_SETFL, O_NONBLOCK);
+      FILE *term_out = fopen("/var/log/dpkg-out.log","a");
+      chmod("/var/log/dpkg-out.log", 0600);
+      
       while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
 	 if(res < 0) {
 	    // FIXME: move this to a function or something, looks ugly here
@@ -585,18 +624,41 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	    signal(SIGINT,old_SIGINT);
 	    return _error->Errno("waitpid","Couldn't wait for subprocess");
 	 }
+
+	 // wait for input or output here
+	 
+	 // FIXME: use select() instead of the rubish below
 	 
 	 // read a single char, make sure that the read can't block 
 	 // (otherwise we may leave zombies)
+         int term_len = read(master, term_buf, 1);
+	 int input_len = read(0, input_buf, 1);
          int len = read(_dpkgin, buf, 1);
 
-	 // nothing to read, wait a bit for more
+	 // see if we have any input that needs to go to the 
+	 // master pty
+	 if(input_len > 0) 
+	    write(master, input_buf, 1);
+
+	 // see if we have any output that needs to be echoed
+	 // and written to the log
+	 if(term_len > 0) 
+	 {
+	    do
+	    {
+	       fwrite(term_buf, 1, 1, term_out);
+	       write(1, term_buf, 1);
+	    } while(read(master, term_buf, 1) > 0);
+	    term_buf[0] = 0;
+	 }
+
+	 // nothing to read from dpkg , wait a bit for more
 	 if(len <= 0)
 	 {
 	    usleep(1000);
 	    continue;
 	 }
-	 
+
 	 // sanity check (should never happen)
 	 if(strlen(line) >= sizeof(line)-10)
 	 {
@@ -702,10 +764,13 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 line[0]=0;
       }
       close(_dpkgin);
+      fclose(term_out);
 
       // Restore sig int/quit
       signal(SIGQUIT,old_SIGQUIT);
       signal(SIGINT,old_SIGINT);
+
+      tcsetattr(0, TCSAFLUSH, &tt);
        
       // Check for an error code.
       if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
diff --git a/apt-pkg/makefile b/apt-pkg/makefile
index df9954f67..8dd50b8c2 100644
--- a/apt-pkg/makefile
+++ b/apt-pkg/makefile
@@ -15,7 +15,7 @@ LIBRARY=apt-pkg
 LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
 MAJOR=4.4
 MINOR=0
-SLIBS=$(PTHREADLIB) $(INTLLIBS)
+SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil
 APT_DOMAIN:=libapt-pkg$(MAJOR)
 
 # Source code for the contributed non-core things
diff --git a/cmdline/makefile b/cmdline/makefile
index 49035be44..5820c2e0f 100644
--- a/cmdline/makefile
+++ b/cmdline/makefile
@@ -14,7 +14,7 @@ include $(PROGRAM_H)
 
 # The apt-get program
 PROGRAM=apt-get
-SLIBS = -lapt-pkg
+SLIBS = -lapt-pkg -lutil
 LIB_MAKES = apt-pkg/makefile
 SOURCE = apt-get.cc acqprogress.cc
 include $(PROGRAM_H)
-- 
cgit v1.2.3


From 090c6566327b0549e74ca50ed8aaae1a898407b2 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Sun, 15 Jul 2007 10:30:30 +0100
Subject: apt-pkg/deb/dpkgpm.cc: - use select() to check for new data

---
 apt-pkg/deb/dpkgpm.cc | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 9ca519acd..d024f8a35 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -17,6 +17,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <fcntl.h>
+#include <sys/select.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <signal.h>
@@ -529,7 +530,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
       tcgetattr(0, &tt);
       ioctl(0, TIOCGWINSZ, (char *)&win);
-      if (openpty(&master, &slave, NULL, &tt, &win) < 0) {
+      if (openpty(&master, &slave, NULL, &tt, &win) < 0) 
+      {
 	 fprintf(stderr, _("openpty failed\n"));
       }
 
@@ -608,9 +610,17 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       close(slave);
       fcntl(0, F_SETFL, O_NONBLOCK);
       fcntl(master, F_SETFL, O_NONBLOCK);
+      // FIXME: make this a apt config option and add a logrotate file
       FILE *term_out = fopen("/var/log/dpkg-out.log","a");
       chmod("/var/log/dpkg-out.log", 0600);
-      
+
+      fd_set rfds;
+      struct timeval tv;
+      int select_ret;
+      FD_ZERO(&rfds);
+      FD_SET(0, &rfds); 
+      FD_SET(_dpkgin, &rfds);
+      FD_SET(master, &rfds);
       while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
 	 if(res < 0) {
 	    // FIXME: move this to a function or something, looks ugly here
@@ -626,9 +636,14 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 }
 
 	 // wait for input or output here
-	 
-	 // FIXME: use select() instead of the rubish below
-	 
+	 tv.tv_sec = 1;
+	 tv.tv_usec = 0;
+	 select_ret = select(max(master, _dpkgin)+1, &rfds, NULL, &rfds, &tv);
+	 if (select_ret < 0)
+	    std::cerr << "Error in select()" << std::endl;
+	 else if (select_ret == 0)
+	    continue;
+
 	 // read a single char, make sure that the read can't block 
 	 // (otherwise we may leave zombies)
          int term_len = read(master, term_buf, 1);
-- 
cgit v1.2.3


From ceabc520928a2eadce005b4f6bcf1f1e703d6b49 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Sun, 15 Jul 2007 11:11:04 +0100
Subject: apt-pkg/deb/dpkgpm.{cc,h}: - move the terminal and stdin reading into
 its own functions

---
 apt-pkg/deb/dpkgpm.cc | 61 ++++++++++++++++++++++++++++++++-------------------
 apt-pkg/deb/dpkgpm.h  |  5 +++++
 2 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index d024f8a35..be61be43b 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -329,7 +329,40 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 
    return true;
 }
+
+									/*}}}*/
+// DPkgPM::DoStdin - Read stdin and pass to slave pty			/*{{{*/
+// ---------------------------------------------------------------------
+/*
+*/
+void pkgDPkgPM::DoStdin(int master)
+{
+   char input_buf[2] = {0,0}; 
+  while(read(0, input_buf, 1) > 0)
+      write(master, input_buf, 1);
+}
 									/*}}}*/
+// DPkgPM::DoTerminalPty - Read the terminal pty and write log		/*{{{*/
+// ---------------------------------------------------------------------
+/*
+ * read the terminal pty and write log
+ */
+void pkgDPkgPM::DoTerminalPty(int master, FILE *term_out)
+{
+   char term_buf[2] = {0,0};
+
+   // read a single char, make sure that the read can't block 
+   // (otherwise we may leave zombies)
+   do
+   {
+      fwrite(term_buf, 1, 1, term_out);
+      write(1, term_buf, 1);
+   } while(read(master, term_buf, 1) > 0);
+}
+									/*}}}*/
+
+
+
 // DPkgPM::Go - Run the sequence					/*{{{*/
 // ---------------------------------------------------------------------
 /* This globs the operations and calls dpkg 
@@ -528,6 +561,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       int	master;
       int	slave;
 
+      // FIXME: setup sensible signal handling (*ick*)
       tcgetattr(0, &tt);
       ioctl(0, TIOCGWINSZ, (char *)&win);
       if (openpty(&master, &slave, NULL, &tt, &win) < 0) 
@@ -602,8 +636,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       char line[1024] = {0,};
       
       char buf[2] = {0,0};
-      char term_buf[2] = {0,0};
-      char input_buf[2] = {0,0};
       
       // the result of the waitpid call
       int res;
@@ -644,28 +676,11 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 else if (select_ret == 0)
 	    continue;
 
-	 // read a single char, make sure that the read can't block 
-	 // (otherwise we may leave zombies)
-         int term_len = read(master, term_buf, 1);
-	 int input_len = read(0, input_buf, 1);
-         int len = read(_dpkgin, buf, 1);
+	 DoStdin(master);
+	 DoTerminalPty(master, term_out);
+	 //DoDpkgStatusFd();
 
-	 // see if we have any input that needs to go to the 
-	 // master pty
-	 if(input_len > 0) 
-	    write(master, input_buf, 1);
-
-	 // see if we have any output that needs to be echoed
-	 // and written to the log
-	 if(term_len > 0) 
-	 {
-	    do
-	    {
-	       fwrite(term_buf, 1, 1, term_out);
-	       write(1, term_buf, 1);
-	    } while(read(master, term_buf, 1) > 0);
-	    term_buf[0] = 0;
-	 }
+	 int len = read(_dpkgin, buf, 1);
 
 	 // nothing to read from dpkg , wait a bit for more
 	 if(len <= 0)
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index 7da729904..a1466878d 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -44,6 +44,11 @@ class pkgDPkgPM : public pkgPackageManager
    bool RunScriptsWithPkgs(const char *Cnf);
    bool SendV2Pkgs(FILE *F);
 
+   // input processing
+   void DoStdin(int master);
+   void DoTerminalPty(int master, FILE *out);
+   //   void DoDpkgStatusFd();
+
    // The Actuall installation implementation
    virtual bool Install(PkgIterator Pkg,string File);
    virtual bool Configure(PkgIterator Pkg);
-- 
cgit v1.2.3


From 7fdafa0f344e236aeaeaa67708dbb70e10a80d98 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Sun, 15 Jul 2007 15:42:15 +0100
Subject: apt-pkg/deb/dpkgpm.cc: - unbreak progress reporting, make code nicer

---
 apt-pkg/deb/dpkgpm.cc | 211 +++++++++++++++++++++++++-------------------------
 1 file changed, 104 insertions(+), 107 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index be61be43b..0d5e2b415 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -338,7 +338,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 void pkgDPkgPM::DoStdin(int master)
 {
    char input_buf[2] = {0,0}; 
-  while(read(0, input_buf, 1) > 0)
+   while(read(0, input_buf, 1) > 0)
       write(master, input_buf, 1);
 }
 									/*}}}*/
@@ -353,11 +353,11 @@ void pkgDPkgPM::DoTerminalPty(int master, FILE *term_out)
 
    // read a single char, make sure that the read can't block 
    // (otherwise we may leave zombies)
-   do
+   while(read(master, term_buf, 1) > 0)
    {
       fwrite(term_buf, 1, 1, term_out);
       write(1, term_buf, 1);
-   } while(read(master, term_buf, 1) > 0);
+   } 
 }
 									/*}}}*/
 
@@ -634,7 +634,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
       // the read buffers for the communication with dpkg
       char line[1024] = {0,};
-      
       char buf[2] = {0,0};
       
       // the result of the waitpid call
@@ -670,7 +669,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 // wait for input or output here
 	 tv.tv_sec = 1;
 	 tv.tv_usec = 0;
-	 select_ret = select(max(master, _dpkgin)+1, &rfds, NULL, &rfds, &tv);
+	 select_ret = select(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv);
 	 if (select_ret < 0)
 	    std::cerr << "Error in select()" << std::endl;
 	 else if (select_ret == 0)
@@ -680,118 +679,116 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 DoTerminalPty(master, term_out);
 	 //DoDpkgStatusFd();
 
-	 int len = read(_dpkgin, buf, 1);
-
-	 // nothing to read from dpkg , wait a bit for more
-	 if(len <= 0)
+	 while(true)
 	 {
-	    usleep(1000);
-	    continue;
-	 }
+	    if(read(_dpkgin, buf, 1) <= 0)
+	       break;
 
-	 // 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;
+	    // sanity check (should never happen)
+	    if(strlen(line) >= sizeof(line)-10)
+	    {
+	       _error->Error("got a overlong line from dpkg: '%s'",line);
+	       line[0]=0;
+	       continue;
+	    }
+	    // 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;
+	    if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+	       std::clog << "got from dpkg '" << line << "'" << std::endl;
 
-	 // the status we output
-	 ostringstream status;
+	    // 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
+	    /* 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[5];
-	 //        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]));
-	 char *pkg = list[1];
-	 char *action = _strstrip(list[2]);
-	 if( pkg == NULL || action == NULL) 
-	 {
-	    if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
-	       std::clog << "ignoring line: not enough ':'" << std::endl;
-	    // reset the line buffer
-	    line[0]=0;
-	    continue;
-	 }
+	    */
+	    char* list[5];
+	    //        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]));
+	    char *pkg = list[1];
+	    char *action = _strstrip(list[2]);
+	    if( pkg == NULL || action == NULL) 
+	    {
+	       if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+		  std::clog << "ignoring line: not enough ':'" << std::endl;
+	       // reset the line buffer
+	       line[0]=0;
+	       continue;
+	    }
 
-	 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;
-	 }
+	    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;
+	    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;
+	    }
+	    if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) 
+	       std::clog << "(parsed from dpkg) pkg: " << pkg 
+			 << " action: " << action << endl;
 
-	 // reset the line buffer
-	 line[0]=0;
+	    // reset the line buffer
+	    line[0]=0;
+	 }
       }
       close(_dpkgin);
       fclose(term_out);
-- 
cgit v1.2.3


From 97efd303643092950042d4f66854c2c1238fa274 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Sun, 15 Jul 2007 17:38:22 +0100
Subject: apt-pkg/deb/dpkgpm.cc: - write current time to log

---
 apt-pkg/deb/dpkgpm.cc | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 0d5e2b415..6270e49f3 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -590,7 +590,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 dup2(slave, 1);
 	 dup2(slave, 2);
 	 close(slave);
-
 	 close(fd[0]); // close the read end of the pipe
 
 	 if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
@@ -641,10 +640,20 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       close(slave);
       fcntl(0, F_SETFL, O_NONBLOCK);
       fcntl(master, F_SETFL, O_NONBLOCK);
+
       // FIXME: make this a apt config option and add a logrotate file
       FILE *term_out = fopen("/var/log/dpkg-out.log","a");
       chmod("/var/log/dpkg-out.log", 0600);
-
+      // output current time
+      char outstr[200];
+      time_t t = time(NULL);
+      struct tm *tmp = localtime(&t);
+      strftime(outstr, sizeof(outstr), "%F  %T", tmp);
+      fprintf(term_out, "Log started: ");
+      fprintf(term_out, outstr);
+      fprintf(term_out, "\n");
+
+      // setups fds
       fd_set rfds;
       struct timeval tv;
       int select_ret;
@@ -677,8 +686,9 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
 	 DoStdin(master);
 	 DoTerminalPty(master, term_out);
-	 //DoDpkgStatusFd();
 
+	 // FIXME: move this into its own function too
+	 //DoDpkgStatusFd();
 	 while(true)
 	 {
 	    if(read(_dpkgin, buf, 1) <= 0)
-- 
cgit v1.2.3


From 955a6ddb8f3bcfadebee5694511661e71980b991 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Mon, 16 Jul 2007 09:19:45 +0100
Subject: apt-pkg/deb/dpkgpm.cc: - run  DoStdin(), DoTerminalPty() calls only
 if their FD is in the   returned set after select()

---
 apt-pkg/deb/dpkgpm.cc | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 6270e49f3..e78f2dc1c 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -337,9 +337,9 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 */
 void pkgDPkgPM::DoStdin(int master)
 {
-   char input_buf[2] = {0,0}; 
-   while(read(0, input_buf, 1) > 0)
-      write(master, input_buf, 1);
+   char input_buf[256] = {0,}; 
+   int len = read(0, input_buf, sizeof(input_buf));
+   write(master, input_buf, len);
 }
 									/*}}}*/
 // DPkgPM::DoTerminalPty - Read the terminal pty and write log		/*{{{*/
@@ -349,15 +349,13 @@ void pkgDPkgPM::DoStdin(int master)
  */
 void pkgDPkgPM::DoTerminalPty(int master, FILE *term_out)
 {
-   char term_buf[2] = {0,0};
+   char term_buf[1024] = {0,};
 
-   // read a single char, make sure that the read can't block 
-   // (otherwise we may leave zombies)
-   while(read(master, term_buf, 1) > 0)
-   {
-      fwrite(term_buf, 1, 1, term_out);
-      write(1, term_buf, 1);
-   } 
+   int len=read(master, term_buf, sizeof(term_buf));
+   if(len <= 0)
+      return;
+   fwrite(term_buf, len, sizeof(char), term_out);
+   write(1, term_buf, len);
 }
 									/*}}}*/
 
@@ -638,9 +636,10 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       // the result of the waitpid call
       int res;
       close(slave);
+#if 0
       fcntl(0, F_SETFL, O_NONBLOCK);
       fcntl(master, F_SETFL, O_NONBLOCK);
-
+#endif
       // FIXME: make this a apt config option and add a logrotate file
       FILE *term_out = fopen("/var/log/dpkg-out.log","a");
       chmod("/var/log/dpkg-out.log", 0600);
@@ -657,10 +656,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       fd_set rfds;
       struct timeval tv;
       int select_ret;
-      FD_ZERO(&rfds);
-      FD_SET(0, &rfds); 
-      FD_SET(_dpkgin, &rfds);
-      FD_SET(master, &rfds);
       while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
 	 if(res < 0) {
 	    // FIXME: move this to a function or something, looks ugly here
@@ -676,6 +671,10 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 }
 
 	 // wait for input or output here
+	 FD_ZERO(&rfds);
+	 FD_SET(0, &rfds); 
+	 FD_SET(_dpkgin, &rfds);
+	 FD_SET(master, &rfds);
 	 tv.tv_sec = 1;
 	 tv.tv_usec = 0;
 	 select_ret = select(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv);
@@ -684,11 +683,14 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 else if (select_ret == 0)
 	    continue;
 
-	 DoStdin(master);
-	 DoTerminalPty(master, term_out);
+	 if(FD_ISSET(master, &rfds))
+	    DoTerminalPty(master, term_out);
+	 if(FD_ISSET(0, &rfds))
+	    DoStdin(master);
 
 	 // FIXME: move this into its own function too
 	 //DoDpkgStatusFd();
+	 if(FD_ISSET(_dpkgin, &rfds))
 	 while(true)
 	 {
 	    if(read(_dpkgin, buf, 1) <= 0)
-- 
cgit v1.2.3


From 6191b008773fc4f0476d4c8f485d146dab13cccd Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Thu, 19 Jul 2007 00:22:42 +0100
Subject: apt-pkg/deb/dpkgpm.{cc,h}: - move make dpkgstatus processing into
 DoDpkgStatusFd()   and ProcessDpkgStatusLine() [the later is a stub for now]

---
 apt-pkg/deb/dpkgpm.cc | 62 +++++++++++++++++++++++++++++++++++++++++----------
 apt-pkg/deb/dpkgpm.h  |  8 ++++++-
 2 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 46a2aaa6a..949ae1c3f 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -40,7 +40,7 @@ using namespace std;
 // DPkgPM::pkgDPkgPM - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache)
+pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache), dpkgbuf_pos(0)
 {
 }
 									/*}}}*/
@@ -358,7 +358,52 @@ void pkgDPkgPM::DoTerminalPty(int master, FILE *term_out)
    write(1, term_buf, len);
 }
 									/*}}}*/
+// DPkgPM::ProcessDpkgStatusBuf                                        	/*{{{*/
+// ---------------------------------------------------------------------
+/*
+ */
+void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
+{
+   std::cerr << "got line: '" << line << "'" << std::endl;
+}
+
+// DPkgPM::DoDpkgStatusFd                                           	/*{{{*/
+// ---------------------------------------------------------------------
+/*
+ */
+void pkgDPkgPM::DoDpkgStatusFd(int statusfd)
+{
+   char *p, *q;
+   int len;
+
+   len=read(statusfd, &dpkgbuf[dpkgbuf_pos], sizeof(dpkgbuf)-dpkgbuf_pos);
+   dpkgbuf_pos += len;
+   if(len <= 0)
+      return;
 
+   // process line by line if we have a buffer
+   p = q = dpkgbuf;
+   while((q=(char*)memchr(p, '\n', dpkgbuf+dpkgbuf_pos-p)) != NULL)
+   {
+      *q = 0;
+      ProcessDpkgStatusLine(p);
+      p=q+1; // continue with next line
+   }
+
+   // now move the unprocessed bits (after the final \n that is now a 0x0) 
+   // to the start and update dpkgbuf_pos
+   p = (char*)memrchr(dpkgbuf, 0, dpkgbuf_pos);
+   if(p == NULL)
+      return;
+
+   // we are interessted in the first char *after* 0x0
+   p++;
+
+   // move the unprocessed tail to the start and update pos
+   memmove(dpkgbuf, p, p-dpkgbuf);
+   dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
+}
+									/*}}}*/
 
 
 // DPkgPM::Go - Run the sequence					/*{{{*/
@@ -626,20 +671,15 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
       // 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;
       close(slave);
-#if 0
-      fcntl(0, F_SETFL, O_NONBLOCK);
-      fcntl(master, F_SETFL, O_NONBLOCK);
-#endif
+
       // FIXME: make this a apt config option and add a logrotate file
       FILE *term_out = fopen("/var/log/dpkg-out.log","a");
       chmod("/var/log/dpkg-out.log", 0600);
@@ -688,12 +728,9 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 if(FD_ISSET(0, &rfds))
 	    DoStdin(master);
 
-	 // FIXME: move this into its own function too
-	 // FIXME2: do not use non-blocking read here, 
-	 //         read/process as much data as possible 
-	 //         Yin one run
-	 //DoDpkgStatusFd();
 	 if(FD_ISSET(_dpkgin, &rfds))
+	    DoDpkgStatusFd(_dpkgin);
+#if 0
 	 while(true)
 	 {
 	    if(read(_dpkgin, buf, 1) <= 0)
@@ -804,6 +841,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	    // reset the line buffer
 	    line[0]=0;
 	 }
+#endif
       }
       close(_dpkgin);
       fclose(term_out);
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index a1466878d..f47cd0bd8 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -18,6 +18,10 @@ using std::vector;
 
 class pkgDPkgPM : public pkgPackageManager
 {
+   private:
+   int dpkgbuf_pos;
+   char dpkgbuf[1024];
+
    protected:
 
    // used for progress reporting
@@ -47,7 +51,9 @@ class pkgDPkgPM : public pkgPackageManager
    // input processing
    void DoStdin(int master);
    void DoTerminalPty(int master, FILE *out);
-   //   void DoDpkgStatusFd();
+   void DoDpkgStatusFd(int statusfd);
+   void ProcessDpkgStatusLine(char *line);
+
 
    // The Actuall installation implementation
    virtual bool Install(PkgIterator Pkg,string File);
-- 
cgit v1.2.3


From 09fa2df2f4717ac956210d43e3f3465d6ef5b82b Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Thu, 19 Jul 2007 00:56:22 +0100
Subject: apt-pkg/deb/dpkgpm.{cc,h}: - move output processing
 ProcessDpkgStatusLine() and out of the   Go() method (yeah!) - things start
 to look more tidy now

---
 apt-pkg/deb/dpkgpm.cc | 224 +++++++++++++++++++++-----------------------------
 apt-pkg/deb/dpkgpm.h  |  31 +++++--
 2 files changed, 117 insertions(+), 138 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 949ae1c3f..bef35ab4c 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -37,10 +37,13 @@
 
 using namespace std;
 
+
+
 // DPkgPM::pkgDPkgPM - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache), dpkgbuf_pos(0)
+pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) 
+   : pkgPackageManager(Cache), dpkgbuf_pos(0), Total(0), Done(0)
 {
 }
 									/*}}}*/
@@ -362,16 +365,100 @@ void pkgDPkgPM::DoTerminalPty(int master, FILE *term_out)
 // ---------------------------------------------------------------------
 /*
  */
-void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
+void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 {
-   std::cerr << "got line: '" << line << "'" << std::endl;
+   // the status we output
+   ostringstream status;
+
+   if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+      std::clog << "got from dpkg '" << line << "'" << std::endl;
+
+
+   /* 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[5];
+   //        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]));
+   char *pkg = list[1];
+   char *action = _strstrip(list[2]);
+   if( pkg == NULL || action == NULL) 
+   {
+      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+	 std::clog << "ignoring line: not enough ':'" << std::endl;
+      return;
+   }
+
+   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());
+      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+	 std::clog << "send: '" << status.str() << "'" << endl;
+      return;
+   }
+   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());
+      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+	 std::clog << "send: '" << status.str() << "'" << endl;
+      return;
+   }
+
+   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;
 }
 
 // DPkgPM::DoDpkgStatusFd                                           	/*{{{*/
 // ---------------------------------------------------------------------
 /*
  */
-void pkgDPkgPM::DoDpkgStatusFd(int statusfd)
+void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
 {
    char *p, *q;
    int len;
@@ -386,7 +473,7 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd)
    while((q=(char*)memchr(p, '\n', dpkgbuf+dpkgbuf_pos-p)) != NULL)
    {
       *q = 0;
-      ProcessDpkgStatusLine(p);
+      ProcessDpkgStatusLine(OutStatusFd, p);
       p=q+1; // continue with next line
    }
 
@@ -426,9 +513,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
    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] = {
@@ -460,15 +544,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       },
    };
 
-   // 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)
@@ -727,121 +802,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	    DoTerminalPty(master, term_out);
 	 if(FD_ISSET(0, &rfds))
 	    DoStdin(master);
-
 	 if(FD_ISSET(_dpkgin, &rfds))
-	    DoDpkgStatusFd(_dpkgin);
-#if 0
-	 while(true)
-	 {
-	    if(read(_dpkgin, buf, 1) <= 0)
-	       break;
-
-	    // sanity check (should never happen)
-	    if(strlen(line) >= sizeof(line)-10)
-	    {
-	       _error->Error("got a overlong line from dpkg: '%s'",line);
-	       line[0]=0;
-	       continue;
-	    }
-	    // 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[5];
-	    //        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]));
-	    char *pkg = list[1];
-	    char *action = _strstrip(list[2]);
-	    if( pkg == NULL || action == NULL) 
-	    {
-	       if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
-		  std::clog << "ignoring line: not enough ':'" << std::endl;
-	       // reset the line buffer
-	       line[0]=0;
-	       continue;
-	    }
-
-	    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;
-
-	    // reset the line buffer
-	    line[0]=0;
-	 }
-#endif
+	    DoDpkgStatusFd(_dpkgin, OutStatusFd);
       }
       close(_dpkgin);
       fclose(term_out);
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index f47cd0bd8..c7792aba4 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -12,25 +12,42 @@
 
 #include <apt-pkg/packagemanager.h>
 #include <vector>
+#include <map>
 #include <stdio.h>
 
 using std::vector;
+using std::map;
+
 
 class pkgDPkgPM : public pkgPackageManager
 {
    private:
-   int dpkgbuf_pos;
-   char dpkgbuf[1024];
 
-   protected:
+   // the buffer we use for the dpkg status-fd reading
+   char dpkgbuf[1024];
+   int dpkgbuf_pos;
 
-   // used for progress reporting
+   // progress reporting
    struct DpkgState 
    {
       const char *state;     // the dpkg state (e.g. "unpack")
       const char *str;       // the human readable translation of the state
    };
-   
+
+   // 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;
+   // progress reporting
+   int Done;
+   int Total;
+
+   protected:
+  
    struct Item
    {
       enum Ops {Install, Configure, Remove, Purge} Op;
@@ -51,8 +68,8 @@ class pkgDPkgPM : public pkgPackageManager
    // input processing
    void DoStdin(int master);
    void DoTerminalPty(int master, FILE *out);
-   void DoDpkgStatusFd(int statusfd);
-   void ProcessDpkgStatusLine(char *line);
+   void DoDpkgStatusFd(int statusfd, int OutStatusFd);
+   void ProcessDpkgStatusLine(int OutStatusFd, char *line);
 
 
    // The Actuall installation implementation
-- 
cgit v1.2.3


From ff56e98015b17c73a3f1aacf3deef5ec4ef4e21b Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Thu, 19 Jul 2007 10:37:05 +0100
Subject: apt-pkg/deb/dpkgpm.{cc,h} - a bit cleanup - move the log date to the
 right place - write log to dir::log::name apt-pkg/init.cc: - init
 dir::log::name "/var/log/apt/term.log" debian/apt.dirs: - create
 /var/log/apt/ doc/examples/configure-index: - add new dir::log::name to the
 index

---
 apt-pkg/deb/dpkgpm.cc        | 48 ++++++++++++++++++++++++++------------------
 apt-pkg/deb/dpkgpm.h         |  9 ++++-----
 apt-pkg/init.cc              |  4 ++++
 debian/apt.dirs              |  1 +
 doc/examples/configure-index |  5 +++++
 5 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index bef35ab4c..8cb076edd 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -43,7 +43,7 @@ using namespace std;
 // ---------------------------------------------------------------------
 /* */
 pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) 
-   : pkgPackageManager(Cache), dpkgbuf_pos(0), Total(0), Done(0)
+   : pkgPackageManager(Cache), dpkgbuf_pos(0), PackagesTotal(0), PackagesDone(0)
 {
 }
 									/*}}}*/
@@ -401,7 +401,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
    if(strncmp(action,"error",strlen("error")) == 0)
    {
       status << "pmerror:" << list[1]
-	     << ":"  << (Done/float(Total)*100.0) 
+	     << ":"  << (PackagesDone/float(PackagesTotal)*100.0) 
 	     << ":" << list[3]
 	     << endl;
       if(OutStatusFd > 0)
@@ -413,7 +413,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
    if(strncmp(action,"conffile",strlen("conffile")) == 0)
    {
       status << "pmconffile:" << list[1]
-	     << ":"  << (Done/float(Total)*100.0) 
+	     << ":"  << (PackagesDone/float(PackagesTotal)*100.0) 
 	     << ":" << list[3]
 	     << endl;
       if(OutStatusFd > 0)
@@ -438,10 +438,10 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 
       // we moved from one dpkg state to a new one, report that
       PackageOpsDone[pkg]++;
-      Done++;
+      PackagesDone++;
       // build the status str
       status << "pmstatus:" << pkg 
-	     << ":"  << (Done/float(Total)*100.0) 
+	     << ":"  << (PackagesDone/float(PackagesTotal)*100.0) 
 	     << ":" << s
 	     << endl;
       if(OutStatusFd > 0)
@@ -555,10 +555,27 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL;  i++) 
       {
 	 PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]);
-	 Total++;
+	 PackagesTotal++;
       }
    }   
 
+   // create log
+   string logdir = _config->FindDir("Dir::Log");
+   if(not FileExists(logdir))
+      return _error->Error(_("Directory '%s' missing"), logdir.c_str());
+   string logfile_name = flCombine(logdir,
+				   _config->Find("Dir::Log::Name"));
+   FILE *term_out = fopen(logfile_name.c_str(),"a");
+   chmod(logfile_name.c_str(), 0600);
+   // output current time
+   char outstr[200];
+   time_t t = time(NULL);
+   struct tm *tmp = localtime(&t);
+   strftime(outstr, sizeof(outstr), "%F  %T", tmp);
+   fprintf(term_out, "Log started: ");
+   fprintf(term_out, outstr);
+   fprintf(term_out, "\n");
+
    // this loop is runs once per operation
    for (vector<Item>::iterator I = List.begin(); I != List.end();)
    {
@@ -755,18 +772,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       int res;
       close(slave);
 
-      // FIXME: make this a apt config option and add a logrotate file
-      FILE *term_out = fopen("/var/log/dpkg-out.log","a");
-      chmod("/var/log/dpkg-out.log", 0600);
-      // output current time
-      char outstr[200];
-      time_t t = time(NULL);
-      struct tm *tmp = localtime(&t);
-      strftime(outstr, sizeof(outstr), "%F  %T", tmp);
-      fprintf(term_out, "Log started: ");
-      fprintf(term_out, outstr);
-      fprintf(term_out, "\n");
-
       // setups fds
       fd_set rfds;
       struct timeval tv;
@@ -806,7 +811,6 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	    DoDpkgStatusFd(_dpkgin, OutStatusFd);
       }
       close(_dpkgin);
-      fclose(term_out);
 
       // Restore sig int/quit
       signal(SIGQUIT,old_SIGQUIT);
@@ -832,10 +836,14 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 else 
 	    _error->Error("Sub-process %s exited unexpectedly",Args[0]);
 
-	 if(stopOnError)
+	 if(stopOnError) 
+	 {
+	    fclose(term_out);
 	    return false;
+	 }
       }      
    }
+   fclose(term_out);
 
    if (RunScripts("DPkg::Post-Invoke") == false)
       return false;
diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h
index c7792aba4..c552b20c9 100644
--- a/apt-pkg/deb/dpkgpm.h
+++ b/apt-pkg/deb/dpkgpm.h
@@ -27,6 +27,8 @@ class pkgDPkgPM : public pkgPackageManager
    char dpkgbuf[1024];
    int dpkgbuf_pos;
 
+   protected:
+
    // progress reporting
    struct DpkgState 
    {
@@ -43,10 +45,8 @@ class pkgDPkgPM : public pkgPackageManager
    // going to be install is already in state "half-installed")
    map<string,int> PackageOpsDone;
    // progress reporting
-   int Done;
-   int Total;
-
-   protected:
+   int PackagesDone;
+   int PackagesTotal;
   
    struct Item
    {
@@ -71,7 +71,6 @@ class pkgDPkgPM : public pkgPackageManager
    void DoDpkgStatusFd(int statusfd, int OutStatusFd);
    void ProcessDpkgStatusLine(int OutStatusFd, char *line);
 
-
    // The Actuall installation implementation
    virtual bool Install(PkgIterator Pkg,string File);
    virtual bool Configure(PkgIterator Pkg);
diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc
index 2f15486d9..2617603ec 100644
--- a/apt-pkg/init.cc
+++ b/apt-pkg/init.cc
@@ -74,6 +74,10 @@ bool pkgInitConfig(Configuration &Cnf)
    Cnf.Set("Dir::Etc::parts","apt.conf.d");
    Cnf.Set("Dir::Etc::preferences","preferences");
    Cnf.Set("Dir::Bin::methods","/usr/lib/apt/methods");
+
+   // State   
+   Cnf.Set("Dir::Log","var/log/apt");
+   Cnf.Set("Dir::Log::Name","term.log");
    
    bool Res = true;
    
diff --git a/debian/apt.dirs b/debian/apt.dirs
index 1543e8bb1..26bb0683c 100644
--- a/debian/apt.dirs
+++ b/debian/apt.dirs
@@ -7,4 +7,5 @@ etc/apt/sources.list.d
 var/cache/apt/archives/partial
 var/lib/apt/lists/partial
 var/lib/apt/periodic
+var/log/apt
 usr/share/bug/apt
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index d0aad1e3d..0bf407a4d 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -227,6 +227,11 @@ Dir "/"
      apt-get "/usr/bin/apt-get";
      apt-cache "/usr/bin/apt-cache";
   };
+
+  // Location of the logfile
+  Log "var/log/apt" {
+	Name "term.log";
+  };
 };
 
 // Things that effect the APT dselect method
-- 
cgit v1.2.3


From b574dd1fac99ba71b1d0adf0aa164100fcf0cb91 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Thu, 19 Jul 2007 10:46:47 +0100
Subject: add logrotate support

---
 debian/apt.dirs      | 1 +
 debian/apt.logrotate | 8 ++++++++
 debian/rules         | 1 +
 3 files changed, 10 insertions(+)
 create mode 100644 debian/apt.logrotate

diff --git a/debian/apt.dirs b/debian/apt.dirs
index 26bb0683c..8ce9b175a 100644
--- a/debian/apt.dirs
+++ b/debian/apt.dirs
@@ -4,6 +4,7 @@ usr/lib/dpkg/methods/apt
 etc/apt
 etc/apt/apt.conf.d
 etc/apt/sources.list.d
+etc/logrotate.d
 var/cache/apt/archives/partial
 var/lib/apt/lists/partial
 var/lib/apt/periodic
diff --git a/debian/apt.logrotate b/debian/apt.logrotate
new file mode 100644
index 000000000..3e924d383
--- /dev/null
+++ b/debian/apt.logrotate
@@ -0,0 +1,8 @@
+/var/log/apt/term.log {
+  rotate 6
+  monthly
+  compress
+  missingok
+  notifempty
+}
+
diff --git a/debian/rules b/debian/rules
index 3ebecfba4..dfee44fde 100755
--- a/debian/rules
+++ b/debian/rules
@@ -209,6 +209,7 @@ apt: build debian/shlibs.local
 	cp -r $(BLD)/locale debian/$@/usr/share/
 
 	cp debian/bugscript debian/$@/usr/share/bug/apt/script
+	cp debian/apt.logrotate debian/$@/etc/logrorate.d/apt
 
 	cp share/debian-archive.gpg debian/$@/usr/share/$@
 	cp debian/apt.conf.autoremove debian/$@/etc/apt/apt.conf.d/01autoremove
-- 
cgit v1.2.3


From 495e5cb25443e6606c0d02891e1f6610983e88cd Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Thu, 26 Jul 2007 19:18:11 +0200
Subject: * implement sha256/sha1/md5 checking with proper backward
 compatibility   and fallback

---
 apt-pkg/acquire-item.cc     | 127 +++++++++++++++++++-------------------------
 apt-pkg/acquire-item.h      |  75 +++++++++++++-------------
 apt-pkg/contrib/hashes.cc   |  84 +++++++++++++++++++++++++++++
 apt-pkg/contrib/hashes.h    |  27 ++++++++++
 apt-pkg/deb/debmetaindex.cc |   2 +-
 apt-pkg/deb/debrecords.cc   |   8 +++
 apt-pkg/deb/debrecords.h    |   1 +
 apt-pkg/indexcopy.cc        |  13 ++---
 apt-pkg/indexrecords.cc     |  48 +++++++++--------
 apt-pkg/indexrecords.h      |   3 +-
 apt-pkg/pkgrecords.h        |   1 +
 apt-pkg/tagfile.h           |   4 +-
 cmdline/apt-get.cc          |   6 +--
 13 files changed, 252 insertions(+), 147 deletions(-)

diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 6d71b6ea3..6d3bc25f3 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -95,7 +95,7 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long Size)
 // Acquire::Item::Done - Item downloaded OK				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgAcquire::Item::Done(string Message,unsigned long Size,string,
+void pkgAcquire::Item::Done(string Message,unsigned long Size,string Hash,
 			    pkgAcquire::MethodConfig *Cnf)
 {
    // We just downloaded something..
@@ -142,8 +142,9 @@ void pkgAcquire::Item::Rename(string From,string To)
  */
 pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
 				 string URI,string URIDesc,string ShortDesc,
-				 string ExpectedMD5)
-   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc)
+				 HashString ExpectedHash)
+   : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
+     Description(URIDesc)
 {
    
    Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
@@ -271,11 +272,11 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
       if(found) 
       {
 	 // queue the diffs
-	 unsigned int last_space = Description.rfind(" ");
+	 string::size_type last_space = Description.rfind(" ");
 	 if(last_space != string::npos)
 	    Description.erase(last_space, Description.size()-last_space);
 	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
-			      ExpectedMD5, available_patches);
+			      ExpectedHash, available_patches);
 	 Complete = false;
 	 Status = StatDone;
 	 Dequeue();
@@ -298,7 +299,7 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 		<< "Falling back to normal index file aquire" << std::endl;
 
    new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc, 
-		   ExpectedMD5);
+		   ExpectedHash);
 
    Complete = false;
    Status = StatDone;
@@ -344,8 +345,9 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
  */
 pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
 				   string URI,string URIDesc,string ShortDesc,
-				   string ExpectedMD5, vector<DiffInfo> diffs)
-   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), 
+				   HashString ExpectedMD5, 
+				   vector<DiffInfo> diffs)
+   : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash), 
      available_patches(diffs)
 {
    
@@ -378,7 +380,7 @@ void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
 		<< "Falling back to normal index file aquire" << std::endl;
    new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, 
-		   ExpectedMD5);
+		   ExpectedHash);
    Finish();
 }
 
@@ -393,14 +395,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone)
       DestFile = _config->FindDir("Dir::State::lists");
       DestFile += URItoFileName(RealURI);
 
-      // do the final md5sum checking
-      MD5Summation sum;
-      FileFd Fd(DestFile, FileFd::ReadOnly);
-      sum.AddFD(Fd.Fd(), Fd.Size());
-      Fd.Close();
-      string MD5 = (string)sum.Result();
-
-      if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+      if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
       {
 	 Status = StatAuthError;
 	 ErrorText = _("MD5Sum mismatch");
@@ -542,7 +537,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
       // see if there is more to download
       if(available_patches.size() > 0) {
 	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
-			      ExpectedMD5, available_patches);
+			      ExpectedHash, available_patches);
 	 return Finish();
       } else 
 	 return Finish(true);
@@ -556,8 +551,8 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
    instantiated to fetch the revision file */   
 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
 			 string URI,string URIDesc,string ShortDesc,
-			 string ExpectedMD5, string comprExt)
-   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
+			 HashString ExpectedHash, string comprExt)
+   : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash)
 {
    Decompression = false;
    Erase = false;
@@ -608,7 +603,7 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 
       // retry with a gzip one 
       new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc, 
-		      ExpectedMD5, string(".gz"));
+		      ExpectedHash, string(".gz"));
       Status = StatDone;
       Complete = false;
       Dequeue();
@@ -633,29 +628,20 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    to the uncompressed version of the file. If this is so the file
    is copied into the partial directory. In all other cases the file
    is decompressed with a gzip uri. */
-void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
 		       pkgAcquire::MethodConfig *Cfg)
 {
-   Item::Done(Message,Size,MD5,Cfg);
+   Item::Done(Message,Size,Hash,Cfg);
 
    if (Decompression == true)
    {
       if (_config->FindB("Debug::pkgAcquire::Auth", false))
       {
-         std::cerr << std::endl << RealURI << ": Computed MD5: " << MD5;
-         std::cerr << "  Expected MD5: " << ExpectedMD5 << std::endl;
+         std::cerr << std::endl << RealURI << ": Computed Hash: " << Hash;
+         std::cerr << "  Expected Hash: " << ExpectedHash.toStr() << std::endl;
       }
 
-      if (MD5.empty())
-      {
-         MD5Summation sum;
-         FileFd Fd(DestFile, FileFd::ReadOnly);
-         sum.AddFD(Fd.Fd(), Fd.Size());
-         Fd.Close();
-         MD5 = (string)sum.Result();
-      }
-
-      if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+      if (!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
       {
          Status = StatAuthError;
          ErrorText = _("MD5Sum mismatch");
@@ -737,8 +723,8 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
 // ---------------------------------------------------------------------
 /* The Translation file is added to the queue */
 pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
-			    string URI,string URIDesc,string ShortDesc) :
-                      pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, "", "")
+			    string URI,string URIDesc,string ShortDesc) 
+  : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
 {
 }
 
@@ -915,10 +901,10 @@ string pkgAcqMetaIndex::Custom600Headers()
    return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
 
-void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,
 			   pkgAcquire::MethodConfig *Cfg)
 {
-   Item::Done(Message,Size,MD5,Cfg);
+   Item::Done(Message,Size,Hash,Cfg);
 
    // MetaIndexes are done in two passes: one to download the
    // metaindex with an appropriate method, and a second to verify it
@@ -1036,7 +1022,7 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
         Target != IndexTargets->end();
         Target++)
    {
-      string ExpectedIndexMD5;
+      HashString ExpectedIndexHash;
       if (verify)
       {
          const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
@@ -1047,16 +1033,16 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
                + (*Target)->MetaKey + " in Meta-index file (malformed Release file?)";
             return;
          }
-         ExpectedIndexMD5 = Record->MD5Hash;
+         ExpectedIndexHash = Record->Hash;
          if (_config->FindB("Debug::pkgAcquire::Auth", false))
          {
             std::cerr << "Queueing: " << (*Target)->URI << std::endl;
-            std::cerr << "Expected MD5: " << ExpectedIndexMD5 << std::endl;
+            std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
          }
-         if (ExpectedIndexMD5.empty())
+         if (ExpectedIndexHash.empty())
          {
             Status = StatAuthError;
-            ErrorText = "Unable to find MD5 sum for "
+            ErrorText = "Unable to find hash sum for "
                + (*Target)->MetaKey + " in Meta-index file";
             return;
          }
@@ -1066,10 +1052,10 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
       // on the users option)
       if(_config->FindB("Acquire::PDiffs",true) == true) 
 	 new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
-			     (*Target)->ShortDesc, ExpectedIndexMD5);
+			     (*Target)->ShortDesc, ExpectedIndexHash);
       else 
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
-			    (*Target)->ShortDesc, ExpectedIndexMD5);
+			    (*Target)->ShortDesc, ExpectedIndexHash);
    }
 }
 
@@ -1309,7 +1295,12 @@ bool pkgAcqArchive::QueueNext()
 	 return false;
       
       string PkgFile = Parse.FileName();
-      MD5 = Parse.MD5Hash();
+      if(Parse.SHA256Hash() != "")
+	 hash = HashString("SHA256", Parse.SHA256Hash());
+      else if (Parse.SHA1Hash() != "")
+	 hash = HashString("SHA1", Parse.SHA1Hash());
+      else 
+	 hash = HashString("MD5Sum", Parse.MD5Hash());
       if (PkgFile.empty() == true)
 	 return _error->Error(_("The package index files are corrupted. No Filename: "
 			      "field for package %s."),
@@ -1389,10 +1380,10 @@ bool pkgAcqArchive::QueueNext()
 // AcqArchive::Done - Finished fetching					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash,
+void pkgAcqArchive::Done(string Message,unsigned long Size,string CalcHash,
 			 pkgAcquire::MethodConfig *Cfg)
 {
-   Item::Done(Message,Size,Md5Hash,Cfg);
+   Item::Done(Message,Size,CalcHash,Cfg);
    
    // Check the size
    if (Size != Version->Size)
@@ -1402,17 +1393,14 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash,
       return;
    }
    
-   // Check the md5
-   if (Md5Hash.empty() == false && MD5.empty() == false)
+   // Check the hash
+   if(!hash.VerifyFile(DestFile))
    {
-      if (Md5Hash != MD5)
-      {
-	 Status = StatError;
-	 ErrorText = _("MD5Sum mismatch");
-	 if(FileExists(DestFile))
-	    Rename(DestFile,DestFile + ".FAILED");
-	 return;
-      }
+      Status = StatError;
+      ErrorText = _("MD5Sum mismatch");
+      if(FileExists(DestFile))
+	 Rename(DestFile,DestFile + ".FAILED");
+      return;
    }
 
    // Grab the output filename
@@ -1507,7 +1495,7 @@ void pkgAcqArchive::Finished()
 pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
 		       unsigned long Size,string Dsc,string ShortDesc,
 		       const string &DestDir, const string &DestFilename) :
-                       Item(Owner), Md5Hash(MD5)
+                       Item(Owner), hash(MD5)
 {
    Retries = _config->FindI("Acquire::Retries",0);
    
@@ -1544,23 +1532,20 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
 // AcqFile::Done - Item downloaded OK					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgAcqFile::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqFile::Done(string Message,unsigned long Size,string CalcHash,
 		      pkgAcquire::MethodConfig *Cnf)
 {
+   Item::Done(Message,Size,CalcHash,Cnf);
+
    // Check the md5
-   if (Md5Hash.empty() == false && MD5.empty() == false)
+   if(!hash.VerifyFile(DestFile))
    {
-      if (Md5Hash != MD5)
-      {
-	 Status = StatError;
-	 ErrorText = "MD5Sum mismatch";
-	 Rename(DestFile,DestFile + ".FAILED");
-	 return;
-      }
+      Status = StatError;
+      ErrorText = "MD5Sum mismatch";
+      Rename(DestFile,DestFile + ".FAILED");
+      return;
    }
    
-   Item::Done(Message,Size,MD5,Cnf);
-
    string FileName = LookupTag(Message,"Filename");
    if (FileName.empty() == true)
    {
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index f5272ed86..08b75c6d2 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -12,7 +12,7 @@
    Three item classes are provided to provide functionality for
    downloading of Index, Translation and Packages files.
    
-   A Archive class is provided for downloading .deb files. It does Md5
+   A Archive class is provided for downloading .deb files. It does Hash
    checking and source location as well as a retry algorithm.
    
    ##################################################################### */
@@ -26,7 +26,7 @@
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/indexrecords.h>
-
+#include <apt-pkg/hashes.h>
 
 /** \addtogroup acquire
  *  @{
@@ -187,12 +187,12 @@ class pkgAcquire::Item
     *  \param Message Data from the acquire method.  Use LookupTag()
     *  to parse it.
     *  \param Size The size of the object that was fetched.
-    *  \param Md5Hash The MD5Sum of the object that was fetched.
+    *  \param Hash The HashSum of the object that was fetched.
     *  \param Cnf The method via which the object was fetched.
     *
     *  \sa pkgAcqMethod
     */
-   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+   virtual void Done(string Message,unsigned long Size,string Hash,
 		     pkgAcquire::MethodConfig *Cnf);
 
    /** \brief Invoked when the worker starts to fetch this object.
@@ -230,12 +230,12 @@ class pkgAcquire::Item
    /** \brief Invoked by the worker when the download is completely done. */
    virtual void Finished() {};
    
-   /** \brief MD5Sum.
+   /** \brief HashSum 
     *
-    *  \return the MD5Sum of this object, if applicable; otherwise, an
+    *  \return the HashSum of this object, if applicable; otherwise, an
     *  empty string.
     */
-   virtual string MD5Sum() {return string();};
+   virtual string HashSum() {return string();};
 
    /** \return the acquire process with which this item is associated. */
    pkgAcquire *GetOwner() {return Owner;};
@@ -297,10 +297,10 @@ class pkgAcqDiffIndex : public pkgAcquire::Item
     */
    string RealURI;
 
-   /** \brief The MD5Sum that the real index file should have after
+   /** \brief The Hash that the real index file should have after
     *  all patches have been applied.
     */
-   string ExpectedMD5;
+   HashString ExpectedHash;
 
    /** \brief The index file which will be patched to generate the new
     *  file.
@@ -343,10 +343,10 @@ class pkgAcqDiffIndex : public pkgAcquire::Item
     *
     *  \param ShortDesc A short description of the list file to download.
     *
-    *  \param ExpectedMD5 The list file's MD5 signature.
+    *  \param ExpectedHash The list file's MD5 signature.
     */
    pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc,
-		   string ShortDesc, string ExpectedMD5);
+		   string ShortDesc, HashString ExpectedHash);
 };
 
 /** \brief An item that is responsible for fetching all the patches
@@ -379,7 +379,7 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item
     *  finishes downloading.
     *
     *  Dequeues the item and checks the resulting file's md5sum
-    *  against ExpectedMD5 after the last patch was applied.
+    *  against ExpectedHash after the last patch was applied.
     *  There is no need to check the md5/sha1 after a "normal" 
     *  patch because QueueNextDiff() will check the sha1 later.
     *
@@ -405,10 +405,10 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item
     */
    string RealURI;
 
-   /** \brief The MD5Sum of the package index file that is being
+   /** \brief The HashSum of the package index file that is being
     *  reconstructed.
     */
-   string ExpectedMD5;
+   HashString ExpectedHash;
 
    /** A description of the file being downloaded. */
    string Description;
@@ -465,7 +465,7 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item
     *
     *  \param ShortDesc A brief description of this item.
     *
-    *  \param ExpectedMD5 The expected md5sum of the completely
+    *  \param ExpectedHash The expected md5sum of the completely
     *  reconstructed package index file; the index file will be tested
     *  against this value when it is entirely reconstructed.
     *
@@ -474,7 +474,7 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item
     *  that depends on it.
     */
    pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc,
-		    string ShortDesc, string ExpectedMD5,
+		    string ShortDesc, HashString ExpectedHash,
 		    vector<DiffInfo> diffs=vector<DiffInfo>());
 };
 
@@ -507,8 +507,8 @@ class pkgAcqIndex : public pkgAcquire::Item
     */
    string RealURI;
 
-   /** \brief The expected md5sum of the decompressed index file. */
-   string ExpectedMD5;
+   /** \brief The expected hashsum of the decompressed index file. */
+   HashString ExpectedHash;
 
    /** \brief The compression-related file extension that is being
     *  added to the downloaded file (e.g., ".gz" or ".bz2").
@@ -535,14 +535,14 @@ class pkgAcqIndex : public pkgAcquire::Item
     *
     *  \param ShortDesc A brief description of this index file.
     *
-    *  \param ExpectedMD5 The expected md5sum of this index file.
+    *  \param ExpectedHash The expected hashsum of this index file.
     *
     *  \param compressExt The compression-related extension with which
     *  this index file should be downloaded, or "" to autodetect
     *  (".bz2" is used if bzip2 is installed, ".gz" otherwise).
     */
    pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
-	       string ShortDesc, string ExpectedMD5, string compressExt="");
+	       string ShortDesc, HashString ExpectedHash, string compressExt="");
 };
 
 /** \brief An acquire item that is responsible for fetching a
@@ -569,7 +569,7 @@ class pkgAcqIndexTrans : public pkgAcqIndex
     *
     *  \param ShortDesc A brief description of this index file.
     *
-    *  \param ExpectedMD5 The expected md5sum of this index file.
+    *  \param ExpectedHash The expected hashsum of this index file.
     *
     *  \param compressExt The compression-related extension with which
     *  this index file should be downloaded, or "" to autodetect
@@ -661,9 +661,9 @@ class pkgAcqMetaSig : public pkgAcquire::Item
  *
  *  Once the download and verification are complete, the downloads of
  *  the individual index files are queued up using pkgAcqDiffIndex.
- *  If the meta-index file had a valid signature, the expected md5sums
+ *  If the meta-index file had a valid signature, the expected hashsums
  *  of the index files will be the md5sums listed in the meta-index;
- *  otherwise, the expected md5sums will be "" (causing the
+ *  otherwise, the expected hashsums will be "" (causing the
  *  authentication of the index files to be bypassed).
  */
 class pkgAcqMetaIndex : public pkgAcquire::Item
@@ -727,11 +727,11 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
 
    /** \brief Starts downloading the individual index files.
     *
-    *  \param verify If \b true, only indices whose expected md5sum
+    *  \param verify If \b true, only indices whose expected hashsum
     *  can be determined from the meta-index will be downloaded, and
-    *  the md5sums of indices will be checked (reporting
+    *  the hashsums of indices will be checked (reporting
     *  #StatAuthError if there is a mismatch).  If verify is \b false,
-    *  no md5sum checking will be performed.
+    *  no hashsum checking will be performed.
     */
    void QueueIndexes(bool verify);
    
@@ -739,7 +739,7 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
    
    // Specialized action members
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+   virtual void Done(string Message,unsigned long Size, string Hash,
 		     pkgAcquire::MethodConfig *Cnf);
    virtual string Custom600Headers();
    virtual string DescURI() {return RealURI; };
@@ -776,8 +776,8 @@ class pkgAcqArchive : public pkgAcquire::Item
     */
    pkgRecords *Recs;
 
-   /** \brief The md5sum of this package. */
-   string MD5;
+   /** \brief The hashsum of this package. */
+   HashString hash;
 
    /** \brief A location in which the actual filename of the package
     *  should be stored.
@@ -805,13 +805,12 @@ class pkgAcqArchive : public pkgAcquire::Item
    public:
    
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+   virtual void Done(string Message,unsigned long Size,string Hash,
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual string MD5Sum() {return MD5;};
    virtual string DescURI() {return Desc.URI;};
    virtual string ShortDesc() {return Desc.ShortDesc;};
    virtual void Finished();
-
+   virtual string HashSum() {return hash.toStr(); };
    virtual bool IsTrusted();
    
    /** \brief Create a new pkgAcqArchive.
@@ -848,8 +847,8 @@ class pkgAcqFile : public pkgAcquire::Item
    /** \brief The currently active download process. */
    pkgAcquire::ItemDesc Desc;
 
-   /** \brief The md5sum of the file to download, if it is known. */
-   string Md5Hash;
+   /** \brief The hashsum of the file to download, if it is known. */
+   HashString hash;
 
    /** \brief How many times to retry the download, set from
     *  Acquire::Retries.
@@ -860,9 +859,9 @@ class pkgAcqFile : public pkgAcquire::Item
    
    // Specialized action members
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
-   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+   virtual void Done(string Message,unsigned long Size,string CalcHash,
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual string MD5Sum() {return Md5Hash;};
+   virtual string HashSum() {return hash.toStr(); };
    virtual string DescURI() {return Desc.URI;};
 
    /** \brief Create a new pkgAcqFile object.
@@ -872,7 +871,7 @@ class pkgAcqFile : public pkgAcquire::Item
     *
     *  \param URI The URI to download.
     *
-    *  \param MD5 The md5sum of the file to download, if it is known;
+    *  \param Hash The hashsum of the file to download, if it is known;
     *  otherwise "".
     *
     *  \param Size The size of the file to download, if it is known;
@@ -894,7 +893,7 @@ class pkgAcqFile : public pkgAcquire::Item
     * is the absolute name to which the file should be downloaded.
     */
 
-   pkgAcqFile(pkgAcquire *Owner, string URI, string MD5, unsigned long Size,
+   pkgAcqFile(pkgAcquire *Owner, string URI, string Hash, unsigned long Size,
 	      string Desc, string ShortDesc,
 	      const string &DestDir="", const string &DestFilename="");
 };
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index b725e9418..da714f997 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -12,11 +12,95 @@
 									/*}}}*/
 // Include Files							/*{{{*/
 #include <apt-pkg/hashes.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/configuration.h>
     
 #include <unistd.h>    
 #include <system.h>    
+#include <string>
+#include <iostream>
 									/*}}}*/
 
+const char* HashString::_SupportedHashes[] = 
+{
+   "SHA256", "SHA1", "MD5Sum", NULL
+};
+
+HashString::HashString()
+{
+}
+
+HashString::HashString(string Type, string Hash) : Type(Type), Hash(Hash)
+{
+}
+
+HashString::HashString(string StringedHash)
+{
+   // legacy: md5sum without "MD5Sum:" prefix
+   if (StringedHash.find(":") == string::npos && StringedHash.size() == 32)
+   {
+      Type = "MD5Sum";
+      Hash = StringedHash;
+      return;
+   }
+   string::size_type pos = StringedHash.find(":");
+   Type = StringedHash.substr(0,pos-1);
+   Hash = StringedHash.substr(pos+1, StringedHash.size() - pos);
+
+   if(_config->FindB("Debug::Hashes",false) == true)
+      std::clog << "HashString(string): " << Type << " : " << Hash << std::endl;
+}
+
+
+bool HashString::VerifyFile(string filename) const
+{
+   FileFd fd;
+   MD5Summation MD5;
+   SHA1Summation SHA1;
+   SHA256Summation SHA256;
+   string fileHash;
+
+   FileFd Fd(filename, FileFd::ReadOnly);
+   if(Type == "MD5Sum") 
+   {
+      MD5.AddFD(Fd.Fd(), Fd.Size());
+      fileHash = (string)MD5.Result();
+   } 
+   else if (Type == "SHA1")
+   {
+      SHA1.AddFD(Fd.Fd(), Fd.Size());
+      fileHash = (string)SHA1.Result();
+   } 
+   else if (Type == "SHA256") 
+   {
+      SHA256.AddFD(Fd.Fd(), Fd.Size());
+      fileHash = (string)SHA256.Result();
+   }
+   Fd.Close();
+
+   if(_config->FindB("Debug::Hashes",false) == true)
+      std::clog << "HashString::VerifyFile: got: " << fileHash << " expected: " << toStr() << std::endl;
+
+   return (fileHash == Hash);
+}
+
+const char** HashString::SupportedHashes()
+{
+   return _SupportedHashes;
+}
+
+bool HashString::empty() const
+{
+   return (Type.empty() || Hash.empty());
+}
+
+
+string HashString::toStr() const
+{
+   return Type+string(":")+Hash;
+}
+
+
 // Hashes::AddFD - Add the contents of the FD				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index b09ea9f6b..86c0eb2ad 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -19,8 +19,35 @@
 #include <apt-pkg/sha256.h>
 
 #include <algorithm>
+#include <vector>
 
 using std::min;
+using std::vector;
+
+// helper class that contains hash function name
+// and hash
+class HashString
+{
+ protected:
+   string Type;
+   string Hash;
+   static const char * _SupportedHashes[10];
+
+ public:
+   HashString(string Type, string Hash);
+   HashString(string StringedHashString);  // init from str as "type:hash"
+   HashString();
+
+   // verify the given filename against the currently loaded hash
+   bool VerifyFile(string filename) const;
+
+   // helper
+   string toStr() const;                    // convert to str as "type:hash"
+   bool empty() const;
+
+   // return the list of hashes we support
+   static const char** SupportedHashes();
+};
 
 class Hashes
 {
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index 73b2dda49..94995798f 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -144,7 +144,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
       vector <struct IndexTarget *> *targets = ComputeIndexTargets();
       for (vector <struct IndexTarget*>::const_iterator Target = targets->begin(); Target != targets->end(); Target++) {
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
-			 (*Target)->ShortDesc, "");
+			 (*Target)->ShortDesc, HashString());
       }
    }
    new pkgAcqMetaSig(Owner, MetaIndexURI("Release.gpg"),
diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc
index 8a5b6e215..3d3d7de0a 100644
--- a/apt-pkg/deb/debrecords.cc
+++ b/apt-pkg/deb/debrecords.cc
@@ -67,6 +67,14 @@ string debRecordParser::SHA1Hash()
    return Section.FindS("SHA1");
 }
 									/*}}}*/
+// RecordParser::SHA1Hash - Return the archive hash			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string debRecordParser::SHA256Hash()
+{
+   return Section.FindS("SHA256");
+}
+									/*}}}*/
 // RecordParser::Maintainer - Return the maintainer email		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h
index df21931a8..ab244b6dd 100644
--- a/apt-pkg/deb/debrecords.h
+++ b/apt-pkg/deb/debrecords.h
@@ -35,6 +35,7 @@ class debRecordParser : public pkgRecords::Parser
    virtual string FileName();
    virtual string MD5Hash();
    virtual string SHA1Hash();
+   virtual string SHA256Hash();
    virtual string SourcePkg();
    virtual string SourceVer();
    
diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc
index c9dded134..b30777d8d 100644
--- a/apt-pkg/indexcopy.cc
+++ b/apt-pkg/indexcopy.cc
@@ -528,23 +528,16 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
       return false;
    }
 
-   MD5Summation sum;
-   FileFd Fd(prefix+file, FileFd::ReadOnly);
-   sum.AddFD(Fd.Fd(), Fd.Size());
-   Fd.Close();
-   string MD5 = (string)sum.Result();
-   
-   if (Record->MD5Hash != MD5)
+   if (!Record->Hash.VerifyFile(prefix+file))
    {
-      _error->Warning("MD5 mismatch for: %s",file.c_str());
+      _error->Warning("Hash mismatch for: %s",file.c_str());
       return false;
    }
 
    if(_config->FindB("Debug::aptcdrom",false)) 
    {
       cout << "File: " << prefix+file << endl;
-      cout << "Expected MD5sum: " << Record->MD5Hash << endl;
-      cout << "got: " << MD5 << endl << endl;
+      cout << "Expected Hash " << Record->Hash.toStr() << endl;
    }
 
    return true;
diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc
index 396e1591f..502f454a8 100644
--- a/apt-pkg/indexrecords.cc
+++ b/apt-pkg/indexrecords.cc
@@ -50,32 +50,38 @@ bool indexRecords::Load(const string Filename)
 
    const char *Start, *End;
    Section.Get (Start, End, 0);
+
    Suite = Section.FindS("Suite");
    Dist = Section.FindS("Codename");
-//    if (Dist.empty())
-//    {
-//       ErrorText = _(("No Codename entry in Release file " + Filename).c_str());
-//       return false;
-//    }
-   if (!Section.Find("MD5Sum", Start, End))
+
+   int i;
+   for (i=0;HashString::SupportedHashes()[i] != NULL; i++)
    {
-      ErrorText = _(("No MD5Sum entry in Release file " + Filename).c_str());
-      return false;
+      if (!Section.Find(HashString::SupportedHashes()[i], Start, End))
+	 continue;
+
+      string Name;
+      string Hash;
+      size_t Size;
+      while (Start < End)
+      {
+	 if (!parseSumData(Start, End, Name, Hash, Size))
+	    return false;
+	 indexRecords::checkSum *Sum = new indexRecords::checkSum;
+	 Sum->MetaKeyFilename = Name;
+	 Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);
+	 Sum->Size = Size;
+	 Entries[Name] = Sum;
+      }
+      break;
    }
-   string Name;
-   string MD5Hash;
-   size_t Size;
-   while (Start < End)
+
+   if(HashString::SupportedHashes()[i] == NULL)
    {
-      if (!parseSumData(Start, End, Name, MD5Hash, Size))
-	 return false;
-      indexRecords::checkSum *Sum = new indexRecords::checkSum;
-      Sum->MetaKeyFilename = Name;
-      Sum->MD5Hash = MD5Hash;
-      Sum->Size = Size;
-      Entries[Name] = Sum;
-   }
-   
+      ErrorText = _(("No Hash entry in Release file " + Filename).c_str());
+      return false;
+   }  
+
    string Strdate = Section.FindS("Date"); // FIXME: verify this somehow?
    return true;
 }
diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h
index ac0df470c..468d2bd0f 100644
--- a/apt-pkg/indexrecords.h
+++ b/apt-pkg/indexrecords.h
@@ -8,6 +8,7 @@
 
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/fileutl.h>
+#include <apt-pkg/hashes.h>
 
 #include <map>
 #include <vector>
@@ -45,7 +46,7 @@ class indexRecords
 struct indexRecords::checkSum
 {
    string MetaKeyFilename;
-   string MD5Hash;
+   HashString Hash;
    size_t Size;      
 };
 
diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h
index 7b9f51a50..f3bf7b6a1 100644
--- a/apt-pkg/pkgrecords.h
+++ b/apt-pkg/pkgrecords.h
@@ -57,6 +57,7 @@ class pkgRecords::Parser
    virtual string FileName() {return string();};
    virtual string MD5Hash() {return string();};
    virtual string SHA1Hash() {return string();};
+   virtual string SHA256Hash() {return string();};
    virtual string SourcePkg() {return string();};
    virtual string SourceVer() {return string();};
 
diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h
index 05c6aa701..6536932dd 100644
--- a/apt-pkg/tagfile.h
+++ b/apt-pkg/tagfile.h
@@ -30,8 +30,8 @@ class pkgTagSection
    const char *Stop;
    
    // We have a limit of 256 tags per section.
-   unsigned short Indexes[256];
-   unsigned short AlphaIndexes[0x100];
+   unsigned int Indexes[256];
+   unsigned int AlphaIndexes[0x100];
    
    unsigned int TagCount;
      
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index df0414076..fb1bb248e 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -918,7 +918,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); I++)
 	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
-	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
       return true;
    }
 
@@ -1359,7 +1359,7 @@ bool DoUpdate(CommandLine &CmdL)
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); I++)
 	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
-	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
       return true;
    }
 
@@ -2211,7 +2211,7 @@ bool DoSource(CommandLine &CmdL)
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); I++)
 	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
-	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
       return true;
    }
    
-- 
cgit v1.2.3


From 5d0d7fae8775dbc2c042bc203e544c79b852b680 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Mon, 30 Jul 2007 16:51:58 +0200
Subject: * apt-pkg/acquire-method.{cc,h}:   - transfert sha256 sum between
 libapt and method too

---
 apt-pkg/acquire-method.cc | 6 ++++++
 apt-pkg/acquire-method.h  | 1 +
 2 files changed, 7 insertions(+)

diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc
index 3360a8eae..7dee7d3e7 100644
--- a/apt-pkg/acquire-method.cc
+++ b/apt-pkg/acquire-method.cc
@@ -179,6 +179,8 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
       End += snprintf(End,sizeof(S)-50 - (End - S),"MD5-Hash: %s\n",Res.MD5Sum.c_str());
    if (Res.SHA1Sum.empty() == false)
       End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash: %s\n",Res.SHA1Sum.c_str());
+   if (Res.SHA256Sum.empty() == false)
+      End += snprintf(End,sizeof(S)-50 - (End - S),"SHA256-Hash: %s\n",Res.SHA256Sum.c_str());
    if (Res.GPGVOutput.size() > 0)
       End += snprintf(End,sizeof(S)-50 - (End - S),"GPGVOutput:\n");     
    for (vector<string>::iterator I = Res.GPGVOutput.begin();
@@ -211,6 +213,9 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
       if (Alt->SHA1Sum.empty() == false)
 	 End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-SHA1-Hash: %s\n",
 			 Alt->SHA1Sum.c_str());
+      if (Alt->SHA256Sum.empty() == false)
+	 End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-SHA256-Hash: %s\n",
+			 Alt->SHA256Sum.c_str());
       
       if (Alt->IMSHit == true)
 	 strcat(End,"Alt-IMS-Hit: true\n");
@@ -455,5 +460,6 @@ void pkgAcqMethod::FetchResult::TakeHashes(Hashes &Hash)
 {
    MD5Sum = Hash.MD5.Result();
    SHA1Sum = Hash.SHA1.Result();
+   SHA256Sum = Hash.SHA256.Result();
 }
 									/*}}}*/
diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h
index 0fd846f54..e02eab018 100644
--- a/apt-pkg/acquire-method.h
+++ b/apt-pkg/acquire-method.h
@@ -43,6 +43,7 @@ class pkgAcqMethod
    {
       string MD5Sum;
       string SHA1Sum;
+      string SHA256Sum;
       vector<string> GPGVOutput;
       time_t LastModified;
       bool IMSHit;
-- 
cgit v1.2.3


From 9498d18252a848b06f281434c173cece967ebbf6 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Mon, 30 Jul 2007 16:53:02 +0200
Subject: * apt-pkg/acquire-item.cc:   - md5sum -> hashsum

---
 apt-pkg/acquire-item.cc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 6d3bc25f3..a7132ce1d 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -644,7 +644,7 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
       if (!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
       {
          Status = StatAuthError;
-         ErrorText = _("MD5Sum mismatch");
+         ErrorText = _("Hash Sum mismatch");
          Rename(DestFile,DestFile + ".FAILED");
          return;
       }
@@ -1397,7 +1397,7 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string CalcHash,
    if(!hash.VerifyFile(DestFile))
    {
       Status = StatError;
-      ErrorText = _("MD5Sum mismatch");
+      ErrorText = _("Hash Sum mismatch");
       if(FileExists(DestFile))
 	 Rename(DestFile,DestFile + ".FAILED");
       return;
@@ -1541,7 +1541,7 @@ void pkgAcqFile::Done(string Message,unsigned long Size,string CalcHash,
    if(!hash.VerifyFile(DestFile))
    {
       Status = StatError;
-      ErrorText = "MD5Sum mismatch";
+      ErrorText = "Hash Sum mismatch";
       Rename(DestFile,DestFile + ".FAILED");
       return;
    }
-- 
cgit v1.2.3


From 8a8feb29265b3dfc27f82072563a641a7976752a Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Mon, 30 Jul 2007 17:47:05 +0200
Subject: * apt-pkg/acquire-item.{cc,h}:   - rename "hash" into ExpectedHash in
 pkgAcqFile, pkgAcqIndex   - add missing HashSum() call to class pkgAcqIndex  
 - use the data provided by acquire-method (and send via the    
 {SHA256,SHA1,MD5Sum}-Hash tag when comparing the hash, this     avoids
 calculating the hash twice (just like old libapt) *
 apt-pkg/acquire-method.cc:   - send MD5Sum-Hash tag to libapt to be
 consistant with     HashString::SupportedHashes() *
 apt-pkg/acquire-worker.cc:   - check with "Owner->HashSum().HashType()" what
 hash the frontend     is expecting and pass it to pkgAcquireItem::Done() in
 the new     HashString format   - add some debugging output *
 apt-pkg/contrib/hashes.cc:   - fix off-by-one error when constructing a
 HashString from a single     input string * apt-pkg/contrib/hashes.h:   - add
 "HashType()" method * apt-pkg/init.h, apt-pkg/makefile, methods/makefile:   -
 break ABI

---
 apt-pkg/acquire-item.cc   | 18 +++++++++---------
 apt-pkg/acquire-item.h    |  9 +++++----
 apt-pkg/acquire-method.cc |  3 +++
 apt-pkg/acquire-worker.cc | 17 ++++++++++++++++-
 apt-pkg/contrib/hashes.cc |  2 +-
 apt-pkg/contrib/hashes.h  |  3 +++
 apt-pkg/init.h            |  2 +-
 apt-pkg/makefile          |  2 +-
 methods/makefile          |  2 +-
 9 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index a7132ce1d..c48502bb9 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -641,7 +641,7 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
          std::cerr << "  Expected Hash: " << ExpectedHash.toStr() << std::endl;
       }
 
-      if (!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
+      if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash)
       {
          Status = StatAuthError;
          ErrorText = _("Hash Sum mismatch");
@@ -1296,11 +1296,11 @@ bool pkgAcqArchive::QueueNext()
       
       string PkgFile = Parse.FileName();
       if(Parse.SHA256Hash() != "")
-	 hash = HashString("SHA256", Parse.SHA256Hash());
+	 ExpectedHash = HashString("SHA256", Parse.SHA256Hash());
       else if (Parse.SHA1Hash() != "")
-	 hash = HashString("SHA1", Parse.SHA1Hash());
+	 ExpectedHash = HashString("SHA1", Parse.SHA1Hash());
       else 
-	 hash = HashString("MD5Sum", Parse.MD5Hash());
+	 ExpectedHash = HashString("MD5Sum", Parse.MD5Hash());
       if (PkgFile.empty() == true)
 	 return _error->Error(_("The package index files are corrupted. No Filename: "
 			      "field for package %s."),
@@ -1394,7 +1394,7 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string CalcHash,
    }
    
    // Check the hash
-   if(!hash.VerifyFile(DestFile))
+   if(ExpectedHash.toStr() != CalcHash)
    {
       Status = StatError;
       ErrorText = _("Hash Sum mismatch");
@@ -1492,10 +1492,10 @@ void pkgAcqArchive::Finished()
 // AcqFile::pkgAcqFile - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* The file is added to the queue */
-pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
+pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
 		       unsigned long Size,string Dsc,string ShortDesc,
 		       const string &DestDir, const string &DestFilename) :
-                       Item(Owner), hash(MD5)
+                       Item(Owner), ExpectedHash(Hash)
 {
    Retries = _config->FindI("Acquire::Retries",0);
    
@@ -1537,8 +1537,8 @@ void pkgAcqFile::Done(string Message,unsigned long Size,string CalcHash,
 {
    Item::Done(Message,Size,CalcHash,Cnf);
 
-   // Check the md5
-   if(!hash.VerifyFile(DestFile))
+   // Check the hash
+   if(ExpectedHash.toStr() != CalcHash)
    {
       Status = StatError;
       ErrorText = "Hash Sum mismatch";
diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h
index 08b75c6d2..edd910230 100644
--- a/apt-pkg/acquire-item.h
+++ b/apt-pkg/acquire-item.h
@@ -523,6 +523,7 @@ class pkgAcqIndex : public pkgAcquire::Item
 		     pkgAcquire::MethodConfig *Cnf);
    virtual string Custom600Headers();
    virtual string DescURI() {return RealURI + CompressionExtension;};
+   virtual string HashSum() {return ExpectedHash.toStr(); };
 
    /** \brief Create a pkgAcqIndex.
     *
@@ -777,7 +778,7 @@ class pkgAcqArchive : public pkgAcquire::Item
    pkgRecords *Recs;
 
    /** \brief The hashsum of this package. */
-   HashString hash;
+   HashString ExpectedHash;
 
    /** \brief A location in which the actual filename of the package
     *  should be stored.
@@ -810,7 +811,7 @@ class pkgAcqArchive : public pkgAcquire::Item
    virtual string DescURI() {return Desc.URI;};
    virtual string ShortDesc() {return Desc.ShortDesc;};
    virtual void Finished();
-   virtual string HashSum() {return hash.toStr(); };
+   virtual string HashSum() {return ExpectedHash.toStr(); };
    virtual bool IsTrusted();
    
    /** \brief Create a new pkgAcqArchive.
@@ -848,7 +849,7 @@ class pkgAcqFile : public pkgAcquire::Item
    pkgAcquire::ItemDesc Desc;
 
    /** \brief The hashsum of the file to download, if it is known. */
-   HashString hash;
+   HashString ExpectedHash;
 
    /** \brief How many times to retry the download, set from
     *  Acquire::Retries.
@@ -861,8 +862,8 @@ class pkgAcqFile : public pkgAcquire::Item
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Done(string Message,unsigned long Size,string CalcHash,
 		     pkgAcquire::MethodConfig *Cnf);
-   virtual string HashSum() {return hash.toStr(); };
    virtual string DescURI() {return Desc.URI;};
+   virtual string HashSum() {return ExpectedHash.toStr(); };
 
    /** \brief Create a new pkgAcqFile object.
     *
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc
index 7dee7d3e7..bc29417f7 100644
--- a/apt-pkg/acquire-method.cc
+++ b/apt-pkg/acquire-method.cc
@@ -176,7 +176,10 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
 		      TimeRFC1123(Res.LastModified).c_str());
 
    if (Res.MD5Sum.empty() == false)
+   {
       End += snprintf(End,sizeof(S)-50 - (End - S),"MD5-Hash: %s\n",Res.MD5Sum.c_str());
+      End += snprintf(End,sizeof(S)-50 - (End - S),"MD5Sum-Hash: %s\n",Res.MD5Sum.c_str());
+   }
    if (Res.SHA1Sum.empty() == false)
       End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash: %s\n",Res.SHA1Sum.c_str());
    if (Res.SHA256Sum.empty() == false)
diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc
index 25d40ef54..460f59961 100644
--- a/apt-pkg/acquire-worker.cc
+++ b/apt-pkg/acquire-worker.cc
@@ -267,8 +267,23 @@ bool pkgAcquire::Worker::RunMessages()
 	       _error->Warning("Bizarre Error - File size is not what the server reported %s %lu",
 			       LookupTag(Message,"Size","0").c_str(),TotalSize);
 
+	    // see if there is a hash to verify
+	    string RecivedHash;
+	    HashString expectedHash(Owner->HashSum());
+	    if(!expectedHash.empty()) 
+	    {
+	       string hashTag = expectedHash.HashType()+"-Hash";
+	       RecivedHash = expectedHash.HashType() + ":" + LookupTag(Message, hashTag.c_str());
+	       if(_config->FindB("Debug::pkgAcquire::Auth", false) == true)
+	       {
+		  clog << "201 URI Done: " << Owner->DescURI() << endl
+		       << "RecivedHash: " << RecivedHash << endl
+		       << "ExpectedHash: " << expectedHash.toStr() 
+		       << endl << endl;
+	       }
+	    }
 	    Owner->Done(Message,atoi(LookupTag(Message,"Size","0").c_str()),
-			LookupTag(Message,"MD5-Hash"),Config);
+			RecivedHash.c_str(), Config);
 	    ItemDone();
 	    
 	    // Log that we are done
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index da714f997..fcc2f887c 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -44,7 +44,7 @@ HashString::HashString(string StringedHash)
       return;
    }
    string::size_type pos = StringedHash.find(":");
-   Type = StringedHash.substr(0,pos-1);
+   Type = StringedHash.substr(0,pos);
    Hash = StringedHash.substr(pos+1, StringedHash.size() - pos);
 
    if(_config->FindB("Debug::Hashes",false) == true)
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index 86c0eb2ad..93e7b25d9 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -38,6 +38,9 @@ class HashString
    HashString(string StringedHashString);  // init from str as "type:hash"
    HashString();
 
+   // get hash type used
+   string HashType() { return Type; };
+
    // verify the given filename against the currently loaded hash
    bool VerifyFile(string filename) const;
 
diff --git a/apt-pkg/init.h b/apt-pkg/init.h
index bc0e55036..801c7cfd0 100644
--- a/apt-pkg/init.h
+++ b/apt-pkg/init.h
@@ -18,7 +18,7 @@
 
 // See the makefile
 #define APT_PKG_MAJOR 4
-#define APT_PKG_MINOR 4
+#define APT_PKG_MINOR 5
 #define APT_PKG_RELEASE 0
     
 extern const char *pkgVersion;
diff --git a/apt-pkg/makefile b/apt-pkg/makefile
index df9954f67..78c24fe83 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=4.4
+MAJOR=4.5
 MINOR=0
 SLIBS=$(PTHREADLIB) $(INTLLIBS)
 APT_DOMAIN:=libapt-pkg$(MAJOR)
diff --git a/methods/makefile b/methods/makefile
index f178cbbea..16900116a 100644
--- a/methods/makefile
+++ b/methods/makefile
@@ -7,7 +7,7 @@ include ../buildlib/defaults.mak
 BIN := $(BIN)/methods
 
 # FIXME..
-LIB_APT_PKG_MAJOR = 4.4
+LIB_APT_PKG_MAJOR = 4.5
 APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR)
 
 # The file method
-- 
cgit v1.2.3


From 2c941d896911dca364b3d38dc593f3bf6847f3e5 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Tue, 31 Jul 2007 12:11:54 +0200
Subject: * apt-pkg/acquire-item.cc:   - only verify checksum in pkgAcqFile if
 we actually have one

---
 apt-pkg/acquire-item.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index c48502bb9..6e7c75032 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -1538,7 +1538,7 @@ void pkgAcqFile::Done(string Message,unsigned long Size,string CalcHash,
    Item::Done(Message,Size,CalcHash,Cnf);
 
    // Check the hash
-   if(ExpectedHash.toStr() != CalcHash)
+   if(!ExpectedHash.empty() && ExpectedHash.toStr() != CalcHash)
    {
       Status = StatError;
       ErrorText = "Hash Sum mismatch";
-- 
cgit v1.2.3


From 57539d9e0512081f18267d125d9d1257b238e7c9 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Thu, 2 Aug 2007 11:56:54 +0200
Subject: * apt-inst/contrib/extracttar.cc:   - fix fd leak for zero size files

---
 apt-inst/contrib/extracttar.cc | 2 +-
 debian/changelog               | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/apt-inst/contrib/extracttar.cc b/apt-inst/contrib/extracttar.cc
index 8a535967f..68c871a5d 100644
--- a/apt-inst/contrib/extracttar.cc
+++ b/apt-inst/contrib/extracttar.cc
@@ -332,7 +332,7 @@ bool ExtractTar::Go(pkgDirStream &Stream)
       }
       
       // And finish up
-      if (Itm.Size != 0 && BadRecord == false)
+      if (Itm.Size >= 0 && BadRecord == false)
 	 if (Stream.FinishedFile(Itm,Fd) == false)
 	    return false;
       
diff --git a/debian/changelog b/debian/changelog
index 873df1693..d7f844f5c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+apt (0.7.7) UNRELEASED; urgency=low
+
+  * apt-inst/contrib/extracttar.cc:
+    - fix fd leak for zero size files 
+
+ -- Michael Vogt <michael.vogt@ubuntu.com>  Thu, 02 Aug 2007 11:55:54 +0200
+
 apt (0.7.6) unstable; urgency=low
 
   * Applied patch from Aurelien Jarno <aurel32@debian.org> to fix wrong
-- 
cgit v1.2.3


From 4c49961112370b869c3c7db61793bb899c709c09 Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Thu, 2 Aug 2007 19:23:41 +0200
Subject: * methods/https.cc:   - only send i-m-s if last-modified is > 0   -
 instead of resume send a range: if-range: custom header   - merge 304
 detection patch from thom may (thanks!) * apt-pkg/acquire-item.cc:   - remove
 empty files on i-m-s hits from partial/

---
 apt-pkg/acquire-item.cc | 20 +++++++++++++-------
 methods/https.cc        | 28 ++++++++++++++++++++--------
 2 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 8ec4ba2c0..bc6d8cead 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -263,8 +263,10 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
    {
       // The files timestamp matches
       if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
+      {
+	 unlink(FileName.c_str());
 	 return;
-
+      }
       Decompression = true;
       Local = true;
       DestFile += ".decomp";
@@ -283,7 +285,10 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
    
    // The files timestamp matches
    if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+   {
+      unlink(FileName.c_str());
       return;
+   }
 
    if (FileName == DestFile)
       Erase = true;
@@ -520,18 +525,19 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)
 
    // see if the download was a IMSHit
    IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
-
    Complete = true;
 
    string FinalFile = _config->FindDir("Dir::State::lists");
    FinalFile += URItoFileName(RealURI);
 
-   // The files timestamp matches
-   if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == false)
-   {
-      // Move it into position
+   // If we get a IMS hit we can remove the empty file in partial
+   // othersie we move the file in place
+   if (IMSHit)
+      unlink(DestFile.c_str());
+   else
       Rename(DestFile,FinalFile);
-   }
+
+   chmod(FinalFile.c_str(),0644);
    DestFile = FinalFile;
 }
 
diff --git a/methods/https.cc b/methods/https.cc
index b758e4ab3..7a6148d14 100644
--- a/methods/https.cc
+++ b/methods/https.cc
@@ -108,6 +108,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
    struct stat SBuf;
    struct curl_slist *headers=NULL;  
    char curl_errorstr[CURL_ERROR_SIZE];
+   long curl_responsecode;
 
    // TODO:
    //       - http::Timeout
@@ -160,8 +161,11 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
 
    // set time values
-   curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
-   curl_easy_setopt(curl, CURLOPT_TIMEVALUE, Itm->LastModified);
+   if(Itm->LastModified > 0)
+   {
+      curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+      curl_easy_setopt(curl, CURLOPT_TIMEVALUE, Itm->LastModified);
+   }
 
    // speed limit
    int dlLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024;
@@ -179,8 +183,14 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
 
    // In this case we send an if-range query with a range header
-  if (stat(Itm->DestFile.c_str(),&SBuf) >= 0 && SBuf.st_size > 0)
-     curl_easy_setopt(curl, CURLOPT_RESUME_FROM, (long)SBuf.st_size);
+   if (stat(Itm->DestFile.c_str(),&SBuf) >= 0 && SBuf.st_size > 0)
+   {
+      char Buf[1000];
+      sprintf(Buf,"Range: bytes=%li-\r\nIf-Range: %s\r\n",
+	      (long)SBuf.st_size - 1,
+	      TimeRFC1123(SBuf.st_mtime).c_str());
+      headers = curl_slist_append(headers, Buf);
+   }
 
    // go for it - if the file exists, append on it
    File = new FileFd(Itm->DestFile, FileFd::WriteAny);
@@ -191,14 +201,17 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
 
    // get it!
    CURLcode success = curl_easy_perform(curl);
-
+   curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &curl_responsecode);
 
    // cleanup
-   if(success != 0) {
+   if(success != 0) 
+   {
+      unlink(File->Name().c_str());
       _error->Error(curl_errorstr);
       Fail();
       return true;
    }
+   File->Close();
 
    if (Res.Size == 0)
       Res.Size = File->Size();
@@ -211,7 +224,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
       Res.Filename = File->Name();
       Res.LastModified = Buf.st_mtime;
       Res.IMSHit = false;
-      if (Itm->LastModified != 0 && Buf.st_mtime >= Itm->LastModified)
+      if (curl_responsecode == 304)
       {
 	 Res.IMSHit = true;
 	 Res.LastModified = Itm->LastModified;
@@ -228,7 +241,6 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
    URIDone(Res);
 
    // cleanup
-   File->Close();
    Res.Size = 0;
    delete File;
    curl_slist_free_all(headers);
-- 
cgit v1.2.3


From a1e9299a9485a219f3a1e3736b1cec21aa24577f Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Fri, 3 Aug 2007 00:56:57 +0200
Subject: debian/changelog: updated credits

---
 debian/changelog | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/debian/changelog b/debian/changelog
index d7f844f5c..75db9cc72 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,7 +1,8 @@
 apt (0.7.7) UNRELEASED; urgency=low
 
   * apt-inst/contrib/extracttar.cc:
-    - fix fd leak for zero size files 
+    - fix fd leak for zero size files (thanks to Bill Broadley for
+      reporting this bug)
 
  -- Michael Vogt <michael.vogt@ubuntu.com>  Thu, 02 Aug 2007 11:55:54 +0200
 
-- 
cgit v1.2.3


From 8da1f029b7544202da68100b22a2901809bf07af Mon Sep 17 00:00:00 2001
From: Michael Vogt <michael.vogt@ubuntu.com>
Date: Fri, 3 Aug 2007 11:21:19 +0200
Subject: * doc/examples/configure-index:   - updated Dir::Log::Terminal *
 apt-pkg/deb/dpkgpm.cc:   - make the terminal log optional   - rename
 Dir::Log::Name to Dir::Log::Terminal

---
 apt-pkg/deb/dpkgpm.cc        | 29 +++++++++++++++++------------
 doc/examples/configure-index |  2 +-
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc
index 8cb076edd..aa840f85e 100644
--- a/apt-pkg/deb/dpkgpm.cc
+++ b/apt-pkg/deb/dpkgpm.cc
@@ -357,8 +357,9 @@ void pkgDPkgPM::DoTerminalPty(int master, FILE *term_out)
    int len=read(master, term_buf, sizeof(term_buf));
    if(len <= 0)
       return;
-   fwrite(term_buf, len, sizeof(char), term_out);
    write(1, term_buf, len);
+   if(term_out)
+      fwrite(term_buf, len, sizeof(char), term_out);
 }
 									/*}}}*/
 // DPkgPM::ProcessDpkgStatusBuf                                        	/*{{{*/
@@ -564,17 +565,21 @@ bool pkgDPkgPM::Go(int OutStatusFd)
    if(not FileExists(logdir))
       return _error->Error(_("Directory '%s' missing"), logdir.c_str());
    string logfile_name = flCombine(logdir,
-				   _config->Find("Dir::Log::Name"));
-   FILE *term_out = fopen(logfile_name.c_str(),"a");
-   chmod(logfile_name.c_str(), 0600);
-   // output current time
-   char outstr[200];
-   time_t t = time(NULL);
-   struct tm *tmp = localtime(&t);
-   strftime(outstr, sizeof(outstr), "%F  %T", tmp);
-   fprintf(term_out, "Log started: ");
-   fprintf(term_out, outstr);
-   fprintf(term_out, "\n");
+				   _config->Find("Dir::Log::Terminal"));
+   FILE *term_out = NULL;
+   if (!logfile_name.empty())
+   {
+      term_out = fopen(logfile_name.c_str(),"a");
+      chmod(logfile_name.c_str(), 0600);
+      // output current time
+      char outstr[200];
+      time_t t = time(NULL);
+      struct tm *tmp = localtime(&t);
+      strftime(outstr, sizeof(outstr), "%F  %T", tmp);
+      fprintf(term_out, "\nLog started: ");
+      fprintf(term_out, outstr);
+      fprintf(term_out, "\n");
+   }
 
    // this loop is runs once per operation
    for (vector<Item>::iterator I = List.begin(); I != List.end();)
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index 0bf407a4d..4c730795d 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -230,7 +230,7 @@ Dir "/"
 
   // Location of the logfile
   Log "var/log/apt" {
-	Name "term.log";
+	Terminal "term.log";
   };
 };
 
-- 
cgit v1.2.3