Просмотр исходного кода

merged from lp:~donkult/apt/experimental

Michael Vogt лет назад: 14
Родитель
Сommit
27da8141d2
72 измененных файлов с 1117 добавлено и 524 удалено
  1. 3 0
      apt-inst/contrib/arfile.h
  2. 6 0
      apt-inst/contrib/extracttar.h
  3. 4 0
      apt-inst/database.h
  4. 4 0
      apt-inst/deb/debfile.h
  5. 8 0
      apt-pkg/acquire-item.h
  6. 5 0
      apt-pkg/acquire-method.h
  7. 5 0
      apt-pkg/acquire.h
  8. 5 0
      apt-pkg/algorithms.h
  9. 6 0
      apt-pkg/cachefile.h
  10. 4 0
      apt-pkg/cacheset.h
  11. 85 73
      apt-pkg/cdrom.cc
  12. 5 0
      apt-pkg/cdrom.h
  13. 4 0
      apt-pkg/contrib/cdromutl.h
  14. 4 0
      apt-pkg/contrib/cmndline.h
  15. 4 0
      apt-pkg/contrib/configuration.h
  16. 432 74
      apt-pkg/contrib/fileutl.cc
  17. 59 12
      apt-pkg/contrib/fileutl.h
  18. 6 0
      apt-pkg/contrib/hashes.h
  19. 5 0
      apt-pkg/contrib/hashsum_template.h
  20. 5 0
      apt-pkg/contrib/md5.h
  21. 20 2
      apt-pkg/contrib/mmap.cc
  22. 5 0
      apt-pkg/contrib/mmap.h
  23. 4 0
      apt-pkg/contrib/netrc.h
  24. 4 0
      apt-pkg/contrib/progress.h
  25. 5 0
      apt-pkg/contrib/sha1.h
  26. 6 0
      apt-pkg/contrib/strutl.h
  27. 14 18
      apt-pkg/deb/debindexfile.cc
  28. 1 0
      apt-pkg/deb/deblistparser.cc
  29. 4 0
      apt-pkg/deb/deblistparser.h
  30. 4 0
      apt-pkg/deb/debmetaindex.h
  31. 1 1
      apt-pkg/deb/debrecords.cc
  32. 4 0
      apt-pkg/deb/debrecords.h
  33. 1 1
      apt-pkg/deb/debsrcrecords.h
  34. 5 0
      apt-pkg/deb/dpkgpm.h
  35. 5 0
      apt-pkg/depcache.h
  36. 5 0
      apt-pkg/edsp.h
  37. 4 7
      apt-pkg/edsp/edspindexfile.cc
  38. 4 0
      apt-pkg/edsp/edspindexfile.h
  39. 6 0
      apt-pkg/edsp/edsplistparser.h
  40. 59 116
      apt-pkg/indexcopy.cc
  41. 5 0
      apt-pkg/indexcopy.h
  42. 4 0
      apt-pkg/indexfile.h
  43. 4 0
      apt-pkg/indexrecords.h
  44. 5 0
      apt-pkg/init.h
  45. 7 0
      apt-pkg/metaindex.h
  46. 5 0
      apt-pkg/packagemanager.h
  47. 4 1
      apt-pkg/pkgcache.h
  48. 9 7
      apt-pkg/pkgcachegen.cc
  49. 4 0
      apt-pkg/pkgsystem.h
  50. 4 0
      apt-pkg/policy.h
  51. 15 13
      apt-pkg/sourcelist.h
  52. 4 4
      apt-pkg/srcrecords.cc
  53. 5 0
      apt-pkg/srcrecords.h
  54. 4 0
      apt-pkg/tagfile.h
  55. 4 0
      apt-pkg/vendor.h
  56. 7 0
      apt-pkg/vendorlist.h
  57. 4 0
      apt-pkg/version.h
  58. 4 0
      apt-pkg/versionmatch.h
  59. 2 0
      buildlib/config.h.in
  60. 1 1
      cmdline/apt-cache.cc
  61. 16 0
      cmdline/apt-config.cc
  62. 6 4
      cmdline/apt-extracttemplates.h
  63. 14 12
      debian/changelog
  64. 13 127
      ftparchive/multicompress.cc
  65. 1 5
      ftparchive/multicompress.h
  66. 8 15
      ftparchive/writer.cc
  67. 1 1
      methods/gzip.cc
  68. 15 29
      methods/rred.cc
  69. 1 1
      test/integration/framework
  70. 86 0
      test/libapt/cdromfindpackages_test.cc
  71. 6 0
      test/libapt/makefile
  72. 29 0
      test/libapt/run-tests

+ 3 - 0
apt-inst/contrib/arfile.h

@@ -17,6 +17,9 @@
 
 
 #include <string>
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/fileutl.h>
+#endif
 
 class FileFd;
 

+ 6 - 0
apt-inst/contrib/extracttar.h

@@ -18,6 +18,12 @@
 
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/dirstream.h>
+#include <algorithm>
+using std::min;
+#endif
+
 class pkgDirStream;
 
 class ExtractTar

+ 4 - 0
apt-inst/database.h

@@ -25,6 +25,10 @@
 
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/filelist.h>
+#endif
+
 class pkgFLCache;
 class OpProgress;
 

+ 4 - 0
apt-inst/deb/debfile.h

@@ -29,6 +29,10 @@
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/pkgcache.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/database.h>
+#endif
+
 class FileFd;
 class pkgDataBase;
 

+ 8 - 0
apt-pkg/acquire-item.h

@@ -25,6 +25,14 @@
 #include <apt-pkg/weakptr.h>
 #include <apt-pkg/pkgcache.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/indexfile.h>
+#include <apt-pkg/vendor.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/indexrecords.h>
+#endif
+
 /** \addtogroup acquire
  *  @{
  *

+ 5 - 0
apt-pkg/acquire-method.h

@@ -25,6 +25,11 @@
 #include <string>
 #include <vector>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/strutl.h>
+#endif
+
 class Hashes;
 class pkgAcqMethod
 {

+ 5 - 0
apt-pkg/acquire.h

@@ -75,6 +75,11 @@
 #include <sys/time.h>
 #include <unistd.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::vector;
+using std::string;
+#endif
+
 class pkgAcquireStatus;
 
 /** \brief The core download scheduler.					{{{

+ 5 - 0
apt-pkg/algorithms.h

@@ -36,6 +36,11 @@
 
 #include <iostream>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/acquire.h>
+using std::ostream;
+#endif
+
 class pkgAcquireStatus;
 
 class pkgSimulate : public pkgPackageManager				/*{{{*/

+ 6 - 0
apt-pkg/cachefile.h

@@ -20,6 +20,12 @@
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/macros.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/acquire.h>
+#include <apt-pkg/policy.h>
+#include <apt-pkg/sourcelist.h>
+#endif
+
 class pkgPolicy;
 class pkgSourceList;
 class OpProgress;

+ 4 - 0
apt-pkg/cacheset.h

@@ -20,6 +20,10 @@
 
 #include <apt-pkg/error.h>
 #include <apt-pkg/pkgcache.h>
+
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/cachefile.h>
+#endif
 									/*}}}*/
 
 class pkgCacheFile;

+ 85 - 73
apt-pkg/cdrom.cc

@@ -58,23 +58,21 @@ bool pkgCdrom::FindPackages(string CD,
       return _error->Errno("chdir","Unable to change to %s",CD.c_str());
 
    // Look for a .disk subdirectory
-   struct stat Buf;
-   if (stat(".disk",&Buf) == 0)
+   if (DirectoryExists(".disk") == true)
    {
       if (InfoDir.empty() == true)
 	 InfoDir = CD + ".disk/";
    }
 
    // Don't look into directories that have been marked to ingore.
-   if (stat(".aptignr",&Buf) == 0)
+   if (RealFileExists(".aptignr") == true)
       return true;
 
-
    /* Check _first_ for a signature file as apt-cdrom assumes that all files
       under a Packages/Source file are in control of that file and stops 
       the scanning
    */
-   if (stat("Release.gpg",&Buf) == 0)
+   if (RealFileExists("Release.gpg") == true || RealFileExists("InRelease") == true)
    {
       SigList.push_back(CD);
    }
@@ -82,66 +80,69 @@ bool pkgCdrom::FindPackages(string CD,
    /* Aha! We found some package files. We assume that everything under 
       this dir is controlled by those package files so we don't look down
       anymore */
-    std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-    types.push_back("");
-    for (std::vector<std::string>::const_iterator t = types.begin();
-         t != types.end(); ++t)
-    {
-       std::string filename = std::string("Packages");
-       if ((*t).size() > 0)
-          filename.append("."+*t);
-       if (stat(filename.c_str(), &Buf) == 0)
-       {
-          List.push_back(CD);
-      
-          // Continue down if thorough is given
-          if (_config->FindB("APT::CDROM::Thorough",false) == false)
-             return true;
-          break;
-       }
-    }
-    for (std::vector<std::string>::const_iterator t = types.begin();
-         t != types.end(); ++t)
-    {
-       std::string filename = std::string("Sources");
-       if ((*t).size() > 0)
-          filename.append("."+*t);
-       {
-          SList.push_back(CD);
-      
-          // Continue down if thorough is given
-          if (_config->FindB("APT::CDROM::Thorough",false) == false)
-             return true;
-          break;
-       }
-    }
+   std::vector<APT::Configuration::Compressor> const compressor = APT::Configuration::getCompressors();
+   for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
+	c != compressor.end(); ++c)
+   {
+      if (RealFileExists(std::string("Packages").append(c->Extension).c_str()) == false)
+	 continue;
+
+      if (_config->FindB("Debug::aptcdrom",false) == true)
+	 std::clog << "Found Packages in " << CD << std::endl;
+      List.push_back(CD);
 
-   // see if we find translatin indexes
-   if (stat("i18n",&Buf) == 0)
+      // Continue down if thorough is given
+      if (_config->FindB("APT::CDROM::Thorough",false) == false)
+	 return true;
+      break;
+   }
+   for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
+	c != compressor.end(); ++c)
+   {
+      if (RealFileExists(std::string("Sources").append(c->Extension).c_str()) == false)
+	 continue;
+
+      if (_config->FindB("Debug::aptcdrom",false) == true)
+	 std::clog << "Found Sources in " << CD << std::endl;
+      SList.push_back(CD);
+
+      // Continue down if thorough is given
+      if (_config->FindB("APT::CDROM::Thorough",false) == false)
+	 return true;
+      break;
+   }
+
+   // see if we find translation indices
+   if (DirectoryExists("i18n") == true)
    {
       D = opendir("i18n");
       for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
       {
-	 if(strstr(Dir->d_name,"Translation") != NULL) 
+	 if(strncmp(Dir->d_name, "Translation-", strlen("Translation-")) != 0)
+	    continue;
+	 string file = Dir->d_name;
+	 for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
+	      c != compressor.end(); ++c)
 	 {
-	    if (_config->FindB("Debug::aptcdrom",false) == true)
-	       std::clog << "found translations: " << Dir->d_name << "\n";
-	    string file = Dir->d_name;
-            for (std::vector<std::string>::const_iterator t = types.begin();
-                 t != types.end(); ++t)
-            {
-               std::string needle = "." + *t;
-               if(file.substr(file.size()-needle.size()) == needle)
-                  file = file.substr(0, file.size()-needle.size());
-               TransList.push_back(CD+"i18n/"+ file);
-               break;
-            }
+	    string fileext = flExtension(file);
+	    if (file == fileext)
+	       fileext.clear();
+	    else if (fileext.empty() == false)
+	       fileext = "." + fileext;
+
+	    if (c->Extension == fileext)
+	    {
+	       if (_config->FindB("Debug::aptcdrom",false) == true)
+		  std::clog << "Found translation " << Dir->d_name << " in " << CD << "i18n/" << std::endl;
+	       file.erase(file.size() - fileext.size());
+	       TransList.push_back(CD + "i18n/" + file);
+	       break;
+	    }
 	 }
       }
       closedir(D);
    }
 
-   
    D = opendir(".");
    if (D == 0)
       return _error->Errno("opendir","Unable to read %s",CD.c_str());
@@ -276,38 +277,43 @@ bool pkgCdrom::DropBinaryArch(vector<string> &List)
 /* Here we go and stat every file that we found and strip dup inodes. */
 bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
 {
+   bool couldFindAllFiles = true;
    // Get a list of all the inodes
    ino_t *Inodes = new ino_t[List.size()];
-   for (unsigned int I = 0; I != List.size(); I++)
+   for (unsigned int I = 0; I != List.size(); ++I)
    {
       struct stat Buf;
-      std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-      types.push_back("");
-      for (std::vector<std::string>::const_iterator t = types.begin();
-           t != types.end(); ++t)
+      bool found = false;
+
+      std::vector<APT::Configuration::Compressor> const compressor = APT::Configuration::getCompressors();
+      for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
+	   c != compressor.end(); ++c)
       {
-         std::string filename = List[I] + Name;
-         if ((*t).size() > 0)
-            filename.append("." + *t);
+	 std::string filename = std::string(List[I]).append(Name).append(c->Extension);
          if (stat(filename.c_str(), &Buf) != 0)
-            _error->Errno("stat","Failed to stat %s%s",List[I].c_str(),
-                          Name);
-         Inodes[I] = Buf.st_ino;
+	    continue;
+	 Inodes[I] = Buf.st_ino;
+	 found = true;
+	 break;
+      }
+
+      if (found == false)
+      {
+	 _error->Errno("stat","Failed to stat %s%s",List[I].c_str(), Name);
+	 couldFindAllFiles = false;
+	 Inodes[I] = 0;
       }
    }
-   
-   if (_error->PendingError() == true) {
-      delete[] Inodes;
-      return false;
-   }
-   
+
    // Look for dups
    for (unsigned int I = 0; I != List.size(); I++)
    {
+      if (Inodes[I] == 0)
+	 continue;
       for (unsigned int J = I+1; J < List.size(); J++)
       {
 	 // No match
-	 if (Inodes[J] != Inodes[I])
+	 if (Inodes[J] == 0 || Inodes[J] != Inodes[I])
 	    continue;
 	 
 	 // We score the two paths.. and erase one
@@ -333,7 +339,7 @@ bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
 	 List.erase(List.begin()+I);
    }
    
-   return true;
+   return couldFindAllFiles;
 }
 									/*}}}*/
 // ReduceSourceList - Takes the path list and reduces it		/*{{{*/
@@ -712,7 +718,13 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
    DropBinaryArch(List);
    DropRepeats(List,"Packages");
    DropRepeats(SourceList,"Sources");
+   // FIXME: We ignore stat() errors here as we usually have only one of those in use
+   // This has little potencial to drop 'valid' stat() errors as we know that one of these
+   // files need to exist, but it would be better if we would check it here
+   _error->PushToStack();
    DropRepeats(SigList,"Release.gpg");
+   DropRepeats(SigList,"InRelease");
+   _error->RevertToStack();
    DropRepeats(TransList,"");
    if(log != NULL) {
       msg.str("");

+ 5 - 0
apt-pkg/cdrom.h

@@ -4,6 +4,11 @@
 #include<string>
 #include<vector>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/init.h>
+using namespace std;
+#endif
+
 class Configuration;
 class OpProgress;
 

+ 4 - 0
apt-pkg/contrib/cdromutl.h

@@ -12,6 +12,10 @@
 
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 // mount cdrom, DeviceName (e.g. /dev/sr0) is optional
 bool MountCdrom(std::string Path, std::string DeviceName="");
 bool UnmountCdrom(std::string Path);

+ 4 - 0
apt-pkg/contrib/cmndline.h

@@ -44,6 +44,10 @@
 #ifndef PKGLIB_CMNDLINE_H
 #define PKGLIB_CMNDLINE_H
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/configuration.h>
+#endif
+
 class Configuration;
 
 class CommandLine

+ 4 - 0
apt-pkg/contrib/configuration.h

@@ -34,6 +34,10 @@
 #include <vector>
 #include <iostream>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 class Configuration
 {
    public:

+ 432 - 74
apt-pkg/contrib/fileutl.cc

@@ -24,6 +24,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sptr.h>
+#include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
 
 #include <cstdlib>
@@ -43,6 +44,16 @@
 #include <set>
 #include <algorithm>
 
+// FIXME: Compressor Fds have some speed disadvantages and are a bit buggy currently,
+// so while the current implementation satisfies the testcases it is not a real option
+// to disable it for now
+#define APT_USE_ZLIB 1
+#if APT_USE_ZLIB
+#include <zlib.h>
+#else
+#pragma message "Usage of zlib is DISABLED!"
+#endif
+
 #ifdef WORDS_BIGENDIAN
 #include <inttypes.h>
 #endif
@@ -52,6 +63,21 @@
 
 using namespace std;
 
+class FileFdPrivate {
+	public:
+#if APT_USE_ZLIB
+	gzFile gz;
+#else
+	void* gz;
+#endif
+	int compressed_fd;
+	pid_t compressor_pid;
+	bool pipe;
+	APT::Configuration::Compressor compressor;
+	unsigned int openmode;
+	FileFdPrivate() : gz(NULL), compressed_fd(-1), compressor_pid(-1), pipe(false) {};
+};
+
 // RunScripts - Run a set of scripts from a configuration subtree	/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -718,84 +744,287 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap)
 // FileFd::Open - Open a file						/*{{{*/
 // ---------------------------------------------------------------------
 /* The most commonly used open mode combinations are given with Mode */
-bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms)
+bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, unsigned long const Perms)
 {
-   Close();
-   Flags = AutoClose;
-   switch (Mode)
+   if (Mode == ReadOnlyGzip)
+      return Open(FileName, ReadOnly, Gzip, Perms);
+
+   if (Compress == Auto && (Mode & WriteOnly) == WriteOnly)
+      return _error->Error("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str());
+
+   // FIXME: Denote inbuilt compressors somehow - as we don't need to have the binaries for them
+   std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
+   std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
+   if (Compress == Auto)
    {
-      case ReadOnly:
-      iFd = open(FileName.c_str(),O_RDONLY);
-      break;
-
-      case ReadOnlyGzip:
-      iFd = open(FileName.c_str(),O_RDONLY);
-      if (iFd > 0) {
-	 gz = gzdopen (iFd, "r");
-	 if (gz == NULL) {
-	     close (iFd);
-	     iFd = -1;
-	 }
-      }
-      break;
-      
-      case WriteAtomic:
+      for (; compressor != compressors.end(); ++compressor)
       {
-	 Flags |= Replace;
-	 char *name = strdup((FileName + ".XXXXXX").c_str());
-	 TemporaryFileName = string(mktemp(name));
-	 iFd = open(TemporaryFileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
-	 free(name);
+	 std::string file = std::string(FileName).append(compressor->Extension);
+	 if (FileExists(file) == false)
+	    continue;
+	 FileName = file;
 	 break;
       }
-
-      case WriteEmpty:
+   }
+   else if (Compress == Extension)
+   {
+      std::string::size_type const found = FileName.find_last_of('.');
+      std::string ext;
+      if (found != std::string::npos)
       {
-      	 struct stat Buf;
-	 if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
-	    unlink(FileName.c_str());
-	 iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
-	 break;
+	 ext = FileName.substr(found);
+	 if (ext == ".new" || ext == ".bak")
+	 {
+	    std::string::size_type const found2 = FileName.find_last_of('.', found - 1);
+	    if (found2 != std::string::npos)
+	       ext = FileName.substr(found2, found - found2);
+	    else
+	       ext.clear();
+	 }
       }
-      
-      case WriteExists:
-      iFd = open(FileName.c_str(),O_RDWR);
-      break;
+      for (; compressor != compressors.end(); ++compressor)
+	 if (ext == compressor->Extension)
+	    break;
+      // no matching extension - assume uncompressed (imagine files like 'example.org_Packages')
+      if (compressor == compressors.end())
+	 for (compressor = compressors.begin(); compressor != compressors.end(); ++compressor)
+	    if (compressor->Name == ".")
+	       break;
+   }
+   else
+   {
+      std::string name;
+      switch (Compress)
+      {
+      case None: name = "."; break;
+      case Gzip: name = "gzip"; break;
+      case Bzip2: name = "bzip2"; break;
+      case Lzma: name = "lzma"; break;
+      case Xz: name = "xz"; break;
+      case Auto:
+      case Extension:
+	 // Unreachable
+	 return _error->Error("Opening File %s in None, Auto or Extension should be already handled?!?", FileName.c_str());
+      }
+      for (; compressor != compressors.end(); ++compressor)
+	 if (compressor->Name == name)
+	    break;
+      if (compressor == compressors.end())
+	 return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
+   }
 
-      case WriteAny:
-      iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms);
-      break;      
+   if (compressor == compressors.end())
+      return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str());
+   return Open(FileName, Mode, *compressor, Perms);
+}
+bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms)
+{
+   Close();
+   d = new FileFdPrivate;
+   d->openmode = Mode;
+   Flags = AutoClose;
+
+   if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0)
+      return _error->Error("ReadOnly mode for %s doesn't accept additional flags!", FileName.c_str());
+   if ((Mode & ReadWrite) == 0)
+      return _error->Error("No openmode provided in FileFd::Open for %s", FileName.c_str());
 
-      case WriteTemp:
+   if ((Mode & Atomic) == Atomic)
+   {
+      Flags |= Replace;
+      char *name = strdup((FileName + ".XXXXXX").c_str());
+      TemporaryFileName = string(mktemp(name));
+      free(name);
+   }
+   else if ((Mode & (Exclusive | Create)) == (Exclusive | Create))
+   {
+      // for atomic, this will be done by rename in Close()
       unlink(FileName.c_str());
-      iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms);
-      break;
-   }  
+   }
+   if ((Mode & Empty) == Empty)
+   {
+      struct stat Buf;
+      if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
+	 unlink(FileName.c_str());
+   }
+
+   int fileflags = 0;
+   #define if_FLAGGED_SET(FLAG, MODE) if ((Mode & FLAG) == FLAG) fileflags |= MODE
+   if_FLAGGED_SET(ReadWrite, O_RDWR);
+   else if_FLAGGED_SET(ReadOnly, O_RDONLY);
+   else if_FLAGGED_SET(WriteOnly, O_WRONLY);
+
+   if_FLAGGED_SET(Create, O_CREAT);
+   if_FLAGGED_SET(Empty, O_TRUNC);
+   if_FLAGGED_SET(Exclusive, O_EXCL);
+   else if_FLAGGED_SET(Atomic, O_EXCL);
+   #undef if_FLAGGED_SET
+
+   if (TemporaryFileName.empty() == false)
+      iFd = open(TemporaryFileName.c_str(), fileflags, Perms);
+   else
+      iFd = open(FileName.c_str(), fileflags, Perms);
+
+   if (iFd == -1 || OpenInternDescriptor(Mode, compressor) == false)
+   {
+      if (iFd != -1)
+      {
+	 close (iFd);
+	 iFd = -1;
+      }
+      return _error->Errno("open",_("Could not open file %s"), FileName.c_str());
+   }
 
-   if (iFd < 0)
-      return _error->Errno("open",_("Could not open file %s"),FileName.c_str());
-   
    this->FileName = FileName;
    SetCloseExec(iFd,true);
    return true;
 }
+									/*}}}*/
+// FileFd::OpenDescriptor - Open a filedescriptor			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose)
+{
+   std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
+   std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
+   std::string name;
+   switch (Compress)
+   {
+   case None: name = "."; break;
+   case Gzip: name = "gzip"; break;
+   case Bzip2: name = "bzip2"; break;
+   case Lzma: name = "lzma"; break;
+   case Xz: name = "xz"; break;
+   case Auto:
+   case Extension:
+      return _error->Error("Opening Fd %d in Auto or Extension compression mode is not supported", Fd);
+   }
+   for (; compressor != compressors.end(); ++compressor)
+      if (compressor->Name == name)
+	 break;
+   if (compressor == compressors.end())
+      return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
 
-bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose)
+   return OpenDescriptor(Fd, Mode, *compressor, AutoClose);
+}
+bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose)
 {
    Close();
+   d = new FileFdPrivate;
+   d->openmode = Mode;
    Flags = (AutoClose) ? FileFd::AutoClose : 0;
    iFd = Fd;
-   if (Mode == ReadOnlyGzip) {
-      gz = gzdopen (iFd, "r");
-      if (gz == NULL) {
-	 if (AutoClose)
-	    close (iFd);
-	 return _error->Errno("gzdopen",_("Could not open file descriptor %d"),
-			      Fd);
-      }
+   if (OpenInternDescriptor(Mode, compressor) == false)
+   {
+      if (AutoClose)
+	 close (iFd);
+      return _error->Errno("gzdopen",_("Could not open file descriptor %d"), Fd);
    }
    this->FileName = "";
    return true;
+}
+bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor)
+{
+   d->compressor = compressor;
+   if (compressor.Name == "." || compressor.Binary.empty() == true)
+      return true;
+#if APT_USE_ZLIB
+   else if (compressor.Name == "gzip")
+   {
+      if ((Mode & ReadWrite) == ReadWrite)
+	 d->gz = gzdopen(iFd, "r+");
+      else if ((Mode & WriteOnly) == WriteOnly)
+	 d->gz = gzdopen(iFd, "w");
+      else
+	 d->gz = gzdopen (iFd, "r");
+      if (d->gz == NULL)
+	 return false;
+      Flags |= Compressed;
+      return true;
+   }
+#endif
+
+   if ((Mode & ReadWrite) == ReadWrite)
+      return _error->Error("ReadWrite mode is not supported for file %s", FileName.c_str());
+
+   bool const Comp = (Mode & WriteOnly) == WriteOnly;
+   // Handle 'decompression' of empty files
+   if (Comp == false)
+   {
+      struct stat Buf;
+      fstat(iFd, &Buf);
+      if (Buf.st_size == 0 && S_ISFIFO(Buf.st_mode) == false)
+	 return true;
+
+      // We don't need the file open - instead let the compressor open it
+      // as he properly knows better how to efficiently read from 'his' file
+      if (FileName.empty() == false)
+	 close(iFd);
+   }
+
+   // Create a data pipe
+   int Pipe[2] = {-1,-1};
+   if (pipe(Pipe) != 0)
+      return _error->Errno("pipe",_("Failed to create subprocess IPC"));
+   for (int J = 0; J != 2; J++)
+      SetCloseExec(Pipe[J],true);
+
+   d->compressed_fd = iFd;
+   d->pipe = true;
+
+   if (Comp == true)
+      iFd = Pipe[1];
+   else
+      iFd = Pipe[0];
+
+   // The child..
+   d->compressor_pid = ExecFork();
+   if (d->compressor_pid == 0)
+   {
+      if (Comp == true)
+      {
+	 dup2(d->compressed_fd,STDOUT_FILENO);
+	 dup2(Pipe[0],STDIN_FILENO);
+      }
+      else
+      {
+	 if (FileName.empty() == true)
+	    dup2(d->compressed_fd,STDIN_FILENO);
+	 dup2(Pipe[1],STDOUT_FILENO);
+      }
+
+      SetCloseExec(STDOUT_FILENO,false);
+      SetCloseExec(STDIN_FILENO,false);
+
+      std::vector<char const*> Args;
+      Args.push_back(compressor.Binary.c_str());
+      std::vector<std::string> const * const addArgs =
+		(Comp == true) ? &(compressor.CompressArgs) : &(compressor.UncompressArgs);
+      for (std::vector<std::string>::const_iterator a = addArgs->begin();
+	   a != addArgs->end(); ++a)
+	 Args.push_back(a->c_str());
+      if (Comp == false && FileName.empty() == false)
+      {
+	 Args.push_back("--stdout");
+	 if (TemporaryFileName.empty() == false)
+	    Args.push_back(TemporaryFileName.c_str());
+	 else
+	    Args.push_back(FileName.c_str());
+      }
+      Args.push_back(NULL);
+
+      execvp(Args[0],(char **)&Args[0]);
+      cerr << _("Failed to exec compressor ") << Args[0] << endl;
+      _exit(100);
+   }
+   if (Comp == true)
+      close(Pipe[0]);
+   else
+      close(Pipe[1]);
+   if (Comp == true || FileName.empty() == true)
+      close(d->compressed_fd);
+
+   return true;
 }
 									/*}}}*/
 // FileFd::~File - Closes the file					/*{{{*/
@@ -817,12 +1046,14 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
    errno = 0;
    if (Actual != 0)
       *Actual = 0;
-   
+   *((char *)To) = '\0';
    do
    {
-      if (gz != NULL)
-         Res = gzread(gz,To,Size);
+#if APT_USE_ZLIB
+      if (d->gz != NULL)
+         Res = gzread(d->gz,To,Size);
       else
+#endif
          Res = read(iFd,To,Size);
       if (Res < 0 && errno == EINTR)
 	 continue;
@@ -853,6 +1084,31 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
    return _error->Error(_("read, still have %llu to read but none left"), Size);
 }
 									/*}}}*/
+// FileFd::ReadLine - Read a complete line from the file		/*{{{*/
+// ---------------------------------------------------------------------
+/* Beware: This method can be quiet slow for big buffers on UNcompressed
+   files because of the naive implementation! */
+char* FileFd::ReadLine(char *To, unsigned long long const Size)
+{
+   *To = '\0';
+#if APT_USE_ZLIB
+   if (d->gz != NULL)
+      return gzgets(d->gz, To, Size);
+#endif
+
+   unsigned long long read = 0;
+   if (Read(To, Size, &read) == false)
+      return NULL;
+   char* c = To;
+   for (; *c != '\n' && *c != '\0' && read != 0; --read, ++c)
+      ; // find the end of the line
+   if (*c != '\0')
+      *c = '\0';
+   if (read != 0)
+      Seek(Tell() - read);
+   return To;
+}
+									/*}}}*/
 // FileFd::Write - Write to the file					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -862,9 +1118,11 @@ bool FileFd::Write(const void *From,unsigned long long Size)
    errno = 0;
    do
    {
-      if (gz != NULL)
-         Res = gzwrite(gz,From,Size);
+#if APT_USE_ZLIB
+      if (d->gz != NULL)
+         Res = gzwrite(d->gz,From,Size);
       else
+#endif
          Res = write(iFd,From,Size);
       if (Res < 0 && errno == EINTR)
 	 continue;
@@ -891,10 +1149,38 @@ bool FileFd::Write(const void *From,unsigned long long Size)
 /* */
 bool FileFd::Seek(unsigned long long To)
 {
+   if (d->pipe == true)
+   {
+      if ((d->openmode & ReadOnly) != ReadOnly)
+	 return _error->Error("Reopen is only implemented for read-only files!");
+      close(iFd);
+      iFd = 0;
+      if (TemporaryFileName.empty() == false)
+	 iFd = open(TemporaryFileName.c_str(), O_RDONLY);
+      else if (FileName.empty() == false)
+	 iFd = open(FileName.c_str(), O_RDONLY);
+      else
+      {
+	 if (d->compressed_fd > 0)
+	    if (lseek(d->compressed_fd, 0, SEEK_SET) != 0)
+	       iFd = d->compressed_fd;
+	 if (iFd <= 0)
+	    return _error->Error("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!");
+      }
+
+      if (OpenInternDescriptor(d->openmode, d->compressor) == false)
+	 return _error->Error("Seek on file %s because it couldn't be reopened", FileName.c_str());
+
+      if (To != 0)
+	 return Skip(To);
+      return true;
+   }
    int res;
-   if (gz)
-      res = gzseek(gz,To,SEEK_SET);
+#if APT_USE_ZLIB
+   if (d->gz)
+      res = gzseek(d->gz,To,SEEK_SET);
    else
+#endif
       res = lseek(iFd,To,SEEK_SET);
    if (res != (signed)To)
    {
@@ -911,9 +1197,11 @@ bool FileFd::Seek(unsigned long long To)
 bool FileFd::Skip(unsigned long long Over)
 {
    int res;
-   if (gz)
-      res = gzseek(gz,Over,SEEK_CUR);
+#if APT_USE_ZLIB
+   if (d->gz != NULL)
+      res = gzseek(d->gz,Over,SEEK_CUR);
    else
+#endif
       res = lseek(iFd,Over,SEEK_CUR);
    if (res < 0)
    {
@@ -929,7 +1217,7 @@ bool FileFd::Skip(unsigned long long Over)
 /* */
 bool FileFd::Truncate(unsigned long long To)
 {
-   if (gz)
+   if (d->gz != NULL)
    {
       Flags |= Fail;
       return _error->Error("Truncating gzipped files is not implemented (%s)", FileName.c_str());
@@ -949,9 +1237,11 @@ bool FileFd::Truncate(unsigned long long To)
 unsigned long long FileFd::Tell()
 {
    off_t Res;
-   if (gz)
-     Res = gztell(gz);
+#if APT_USE_ZLIB
+   if (d->gz != NULL)
+     Res = gztell(d->gz);
    else
+#endif
      Res = lseek(iFd,0,SEEK_CUR);
    if (Res == (off_t)-1)
       _error->Errno("lseek","Failed to determine the current file position");
@@ -964,9 +1254,19 @@ unsigned long long FileFd::Tell()
 unsigned long long FileFd::FileSize()
 {
    struct stat Buf;
-
-   if (fstat(iFd,&Buf) != 0)
+   if (d->pipe == false && fstat(iFd,&Buf) != 0)
       return _error->Errno("fstat","Unable to determine the file size");
+
+   // for compressor pipes st_size is undefined and at 'best' zero
+   if (d->pipe == true || S_ISFIFO(Buf.st_mode))
+   {
+      // we set it here, too, as we get the info here for free
+      // in theory the Open-methods should take care of it already
+      d->pipe = true;
+      if (stat(FileName.c_str(), &Buf) != 0)
+	 return _error->Errno("stat","Unable to determine the file size");
+   }
+
    return Buf.st_size;
 }
 									/*}}}*/
@@ -977,10 +1277,25 @@ unsigned long long FileFd::Size()
 {
    unsigned long long size = FileSize();
 
+   // for compressor pipes st_size is undefined and at 'best' zero,
+   // so we 'read' the content and 'seek' back - see there
+   if (d->pipe == true)
+   {
+      // FIXME: If we have read first and then FileSize() the report is wrong
+      size = 0;
+      char ignore[1000];
+      unsigned long long read = 0;
+      do {
+	 Read(ignore, sizeof(ignore), &read);
+	 size += read;
+      } while(read != 0);
+      Seek(0);
+   }
+#if APT_USE_ZLIB
    // only check gzsize if we are actually a gzip file, just checking for
-   // "gz" is not sufficient as uncompressed files will be opened with
+   // "gz" is not sufficient as uncompressed files could be opened with
    // gzopen in "direct" mode as well
-   if (gz && !gzdirect(gz) && size > 0)
+   else if (d->gz && !gzdirect(d->gz) && size > 0)
    {
        /* unfortunately zlib.h doesn't provide a gzsize(), so we have to do
 	* this ourselves; the original (uncompressed) file size is the last 32
@@ -1004,24 +1319,58 @@ unsigned long long FileFd::Size()
 	   return _error->Errno("lseek","Unable to seek in gzipped file");
        return size;
    }
+#endif
 
    return size;
 }
 									/*}}}*/
+// FileFd::ModificationTime - Return the time of last touch		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+time_t FileFd::ModificationTime()
+{
+   struct stat Buf;
+   if (d->pipe == false && fstat(iFd,&Buf) != 0)
+   {
+      _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
+      return 0;
+   }
+
+   // for compressor pipes st_size is undefined and at 'best' zero
+   if (d->pipe == true || S_ISFIFO(Buf.st_mode))
+   {
+      // we set it here, too, as we get the info here for free
+      // in theory the Open-methods should take care of it already
+      d->pipe = true;
+      if (stat(FileName.c_str(), &Buf) != 0)
+      {
+	 _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
+	 return 0;
+      }
+   }
+
+   return Buf.st_mtime;
+}
+									/*}}}*/
 // FileFd::Close - Close the file if the close flag is set		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 bool FileFd::Close()
 {
+   if (iFd == -1)
+      return true;
+
    bool Res = true;
    if ((Flags & AutoClose) == AutoClose)
    {
-      if (gz != NULL) {
-	 int const e = gzclose(gz);
+#if APT_USE_ZLIB
+      if (d != NULL && d->gz != NULL) {
+	 int const e = gzclose(d->gz);
 	 // gzdopen() on empty files always fails with "buffer error" here, ignore that
 	 if (e != 0 && e != Z_BUF_ERROR)
 	    Res &= _error->Errno("close",_("Problem closing the gzip file %s"), FileName.c_str());
       } else
+#endif
 	 if (iFd > 0 && close(iFd) != 0)
 	    Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str());
    }
@@ -1031,16 +1380,23 @@ bool FileFd::Close()
 	 Res &= _error->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName.c_str(), FileName.c_str());
 
       FileName = TemporaryFileName; // for the unlink() below.
+      TemporaryFileName.clear();
    }
 
    iFd = -1;
-   gz = NULL;
 
    if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail &&
        FileName.empty() == false)
       if (unlink(FileName.c_str()) != 0)
 	 Res &= _error->WarningE("unlnk",_("Problem unlinking the file %s"), FileName.c_str());
 
+   if (d != NULL)
+   {
+      if (d->compressor_pid > 0)
+	 ExecWait(d->compressor_pid, "FileFdCompressor", true);
+      delete d;
+      d = NULL;
+   }
 
    return Res;
 }
@@ -1057,3 +1413,5 @@ bool FileFd::Sync()
    return true;
 }
 									/*}}}*/
+
+gzFile FileFd::gzFd() { return (gzFile) d->gz; }

+ 59 - 12
apt-pkg/contrib/fileutl.h

@@ -22,30 +22,51 @@
 #define PKGLIB_FILEUTL_H
 
 #include <apt-pkg/macros.h>
+#include <apt-pkg/aptconfiguration.h>
 
 #include <string>
 #include <vector>
 
 #include <zlib.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 /* Define this for python-apt */
 #define APT_HAS_GZIP 1
 
+class FileFdPrivate;
 class FileFd
 {
    protected:
    int iFd;
  
    enum LocalFlags {AutoClose = (1<<0),Fail = (1<<1),DelOnFail = (1<<2),
-                    HitEof = (1<<3), Replace = (1<<4) };
+                    HitEof = (1<<3), Replace = (1<<4), Compressed = (1<<5) };
    unsigned long Flags;
    std::string FileName;
    std::string TemporaryFileName;
-   gzFile gz;
 
    public:
-   enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp,ReadOnlyGzip,
-                  WriteAtomic};
+   enum OpenMode {
+	ReadOnly = (1 << 0),
+	WriteOnly = (1 << 1),
+	ReadWrite = ReadOnly | WriteOnly,
+
+	Create = (1 << 2),
+	Exclusive = (1 << 3),
+	Atomic = Exclusive | (1 << 4),
+	Empty = (1 << 5),
+
+	WriteEmpty = ReadWrite | Create | Empty,
+	WriteExists = ReadWrite,
+	WriteAny = ReadWrite | Create,
+	WriteTemp = ReadWrite | Create | Exclusive,
+	ReadOnlyGzip,
+	WriteAtomic = ReadWrite | Create | Atomic
+   };
+   enum CompressMode { Auto = 'A', None = 'N', Extension = 'E', Gzip = 'G', Bzip2 = 'B', Lzma = 'L', Xz = 'X' };
    
    inline bool Read(void *To,unsigned long long Size,bool AllowEof)
    {
@@ -55,6 +76,7 @@ class FileFd
       return Read(To,Size);
    }   
    bool Read(void *To,unsigned long long Size,unsigned long long *Actual = 0);
+   char* ReadLine(char *To, unsigned long long const Size);
    bool Write(const void *From,unsigned long long Size);
    bool Seek(unsigned long long To);
    bool Skip(unsigned long long To);
@@ -62,6 +84,7 @@ class FileFd
    unsigned long long Tell();
    unsigned long long Size();
    unsigned long long FileSize();
+   time_t ModificationTime();
 
    /* You want to use 'unsigned long long' if you are talking about a file
       to be able to support large files (>2 or >4 GB) properly.
@@ -77,30 +100,54 @@ class FileFd
 	return T;
    }
 
-   bool Open(std::string FileName,OpenMode Mode,unsigned long Perms = 0666);
-   bool OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose=false);
+   bool Open(std::string FileName,unsigned int const Mode,CompressMode Compress,unsigned long const Perms = 0666);
+   bool Open(std::string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor,unsigned long const Perms = 0666);
+   inline bool Open(std::string const &FileName,unsigned int const Mode, unsigned long const Perms = 0666) {
+      return Open(FileName, Mode, None, Perms);
+   };
+   bool OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose=false);
+   bool OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose=false);
+   inline bool OpenDescriptor(int Fd, unsigned int const Mode, bool AutoClose=false) {
+      return OpenDescriptor(Fd, Mode, None, AutoClose);
+   };
    bool Close();
    bool Sync();
    
    // Simple manipulators
    inline int Fd() {return iFd;};
    inline void Fd(int fd) {iFd = fd;};
-   inline gzFile gzFd() {return gz;};
+   __deprecated gzFile gzFd();
+
    inline bool IsOpen() {return iFd >= 0;};
    inline bool Failed() {return (Flags & Fail) == Fail;};
    inline void EraseOnFailure() {Flags |= DelOnFail;};
    inline void OpFail() {Flags |= Fail;};
    inline bool Eof() {return (Flags & HitEof) == HitEof;};
+   inline bool IsCompressed() {return (Flags & Compressed) == Compressed;};
    inline std::string &Name() {return FileName;};
    
-   FileFd(std::string FileName,OpenMode Mode,unsigned long Perms = 0666) : iFd(-1), 
-            Flags(0), gz(NULL)
+   FileFd(std::string FileName,unsigned int const Mode,unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL)
    {
-      Open(FileName,Mode,Perms);
+      Open(FileName,Mode, None, Perms);
+   };
+   FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL)
+   {
+      Open(FileName,Mode, Compress, Perms);
+   };
+   FileFd() : iFd(-1), Flags(AutoClose), d(NULL) {};
+   FileFd(int const Fd, unsigned int const Mode = ReadWrite, CompressMode Compress = None) : iFd(-1), Flags(0), d(NULL)
+   {
+      OpenDescriptor(Fd, Mode, Compress);
+   };
+   FileFd(int const Fd, bool const AutoClose) : iFd(-1), Flags(0), d(NULL)
+   {
+      OpenDescriptor(Fd, ReadWrite, None, AutoClose);
    };
-   FileFd(int Fd = -1) : iFd(Fd), Flags(AutoClose), gz(NULL) {};
-   FileFd(int Fd,bool) : iFd(Fd), Flags(0), gz(NULL) {};
    virtual ~FileFd();
+
+   private:
+   FileFdPrivate* d;
+   bool OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor);
 };
 
 bool RunScripts(const char *Cnf);

+ 6 - 0
apt-pkg/contrib/hashes.h

@@ -22,6 +22,12 @@
 #include <vector>
 #include <cstring>
 
+
+#ifndef APT_8_CLEANER_HEADERS
+using std::min;
+using std::vector;
+#endif
+
 // helper class that contains hash function name
 // and hash
 class HashString

+ 5 - 0
apt-pkg/contrib/hashsum_template.h

@@ -15,6 +15,11 @@
 #include <algorithm>
 #include <stdint.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::min;
+#endif
+
 template<int N>
 class HashSumValue
 {

+ 5 - 0
apt-pkg/contrib/md5.h

@@ -31,6 +31,11 @@
 
 #include "hashsum_template.h"
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::min;
+#endif
+
 typedef HashSumValue<128> MD5SumValue;
 
 class MD5Summation : public SummationImplementation

+ 20 - 2
apt-pkg/contrib/mmap.cc

@@ -66,7 +66,7 @@ MMap::~MMap()
 bool MMap::Map(FileFd &Fd)
 {
    iSize = Fd.Size();
-   
+
    // Set the permissions.
    int Prot = PROT_READ;
    int Map = MAP_SHARED;
@@ -77,7 +77,18 @@ bool MMap::Map(FileFd &Fd)
    
    if (iSize == 0)
       return _error->Error(_("Can't mmap an empty file"));
-   
+
+   // We can't mmap compressed fd's directly, so we need to read it completely
+   if (Fd.IsCompressed() == true)
+   {
+      if ((Flags & ReadOnly) != ReadOnly)
+	 return _error->Error("Compressed file %s can only be mapped readonly", Fd.Name().c_str());
+      Base = new unsigned char[iSize];
+      if (Fd.Seek(0L) == false || Fd.Read(Base, iSize) == false)
+	 return false;
+      return true;
+   }
+
    // Map it.
    Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
    if (Base == (void *)-1)
@@ -86,6 +97,13 @@ bool MMap::Map(FileFd &Fd)
       {
 	 // The filesystem doesn't support this particular kind of mmap.
 	 // So we allocate a buffer and read the whole file into it.
+	 if ((Flags & ReadOnly) == ReadOnly)
+	 {
+	    // for readonly, we don't need sync, so make it simple
+	    Base = new unsigned char[iSize];
+	    return Fd.Read(Base, iSize);
+	 }
+	 // FIXME: Writing to compressed fd's ?
 	 int const dupped_fd = dup(Fd.Fd());
 	 if (dupped_fd == -1)
 	    return _error->Errno("mmap", _("Couldn't duplicate file descriptor %i"), Fd.Fd());

+ 5 - 0
apt-pkg/contrib/mmap.h

@@ -28,6 +28,11 @@
 
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/fileutl.h>
+using std::string;
+#endif
+
 class FileFd;
 
 /* This should be a 32 bit type, larger tyes use too much ram and smaller

+ 4 - 0
apt-pkg/contrib/netrc.h

@@ -16,6 +16,10 @@
 
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/strutl.h>
+#endif
+
 #define DOT_CHAR "."
 #define DIR_CHAR "/"
 

+ 4 - 0
apt-pkg/contrib/progress.h

@@ -25,6 +25,10 @@
 #include <string>
 #include <sys/time.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 class Configuration;
 class OpProgress
 {

+ 5 - 0
apt-pkg/contrib/sha1.h

@@ -20,6 +20,11 @@
 
 #include "hashsum_template.h"
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::min;
+#endif
+
 typedef  HashSumValue<160> SHA1SumValue;
 
 class SHA1Summation : public SummationImplementation

+ 6 - 0
apt-pkg/contrib/strutl.h

@@ -27,6 +27,12 @@
 
 #include "macros.h"
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::vector;
+using std::ostream;
+#endif
+
 bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest);
 char *_strstrip(char *String);
 char *_strtabexpand(char *String,size_t Len);

+ 14 - 18
apt-pkg/deb/debindexfile.cc

@@ -26,6 +26,8 @@
 #include <sys/stat.h>
 									/*}}}*/
 
+using std::string;
+
 // SourcesIndex::debSourcesIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -159,7 +161,7 @@ unsigned long debSourcesIndex::Size() const
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    _error->PushToStack();
 
-   FileFd f = FileFd (IndexFile("Sources"), FileFd::ReadOnlyGzip);
+   FileFd f = FileFd (IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension);
    if (!f.Failed())
       size = f.Size();
 
@@ -288,7 +290,7 @@ unsigned long debPackagesIndex::Size() const
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    _error->PushToStack();
 
-   FileFd f = FileFd (IndexFile("Packages"), FileFd::ReadOnlyGzip);
+   FileFd f = FileFd (IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension);
    if (!f.Failed())
       size = f.Size();
 
@@ -305,7 +307,7 @@ unsigned long debPackagesIndex::Size() const
 bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
    string PackageFile = IndexFile("Packages");
-   FileFd Pkg(PackageFile,FileFd::ReadOnlyGzip);
+   FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
    debListParser Parser(&Pkg, Architecture);
 
    if (_error->PendingError() == true)
@@ -319,11 +321,8 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    // Store the IMS information
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
    pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
-   struct stat St;
-   if (fstat(Pkg.Fd(),&St) != 0)
-      return _error->Errno("fstat","Failed to stat");
-   File->Size = St.st_size;
-   File->mtime = St.st_mtime;
+   File->Size = Pkg.FileSize();
+   File->mtime = Pkg.ModificationTime();
    
    if (Gen.MergeList(Parser) == false)
       return _error->Error("Problem with MergeList %s",PackageFile.c_str());
@@ -489,7 +488,7 @@ unsigned long debTranslationsIndex::Size() const
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    _error->PushToStack();
 
-   FileFd f = FileFd (IndexFile(Language), FileFd::ReadOnlyGzip);
+   FileFd f = FileFd (IndexFile(Language), FileFd::ReadOnly, FileFd::Extension);
    if (!f.Failed())
       size = f.Size();
 
@@ -509,7 +508,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    string TranslationFile = IndexFile(Language);
    if (FileExists(TranslationFile))
    {
-     FileFd Trans(TranslationFile,FileFd::ReadOnlyGzip);
+     FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
      debListParser TransParser(&Trans);
      if (_error->PendingError() == true)
        return false;
@@ -521,11 +520,8 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 
      // Store the IMS information
      pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
-     struct stat TransSt;
-     if (fstat(Trans.Fd(),&TransSt) != 0)
-       return _error->Errno("fstat","Failed to stat");
-     TransFile->Size = TransSt.st_size;
-     TransFile->mtime = TransSt.st_mtime;
+     TransFile->Size = Trans.FileSize();
+     TransFile->mtime = Trans.ModificationTime();
    
      if (Gen.MergeList(TransParser) == false)
        return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
@@ -590,7 +586,7 @@ unsigned long debStatusIndex::Size() const
 /* */
 bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
-   FileFd Pkg(File,FileFd::ReadOnlyGzip);
+   FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
    if (_error->PendingError() == true)
       return false;
    debListParser Parser(&Pkg);
@@ -607,8 +603,8 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    struct stat St;
    if (fstat(Pkg.Fd(),&St) != 0)
       return _error->Errno("fstat","Failed to stat");
-   CFile->Size = St.st_size;
-   CFile->mtime = St.st_mtime;
+   CFile->Size = Pkg.FileSize();
+   CFile->mtime = Pkg.ModificationTime();
    CFile->Archive = Gen.WriteUniqString("now");
    
    if (Gen.MergeList(Parser) == false)

+ 1 - 0
apt-pkg/deb/deblistparser.cc

@@ -773,6 +773,7 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
    // file. to provide Component pinning we use the section name now
    FileI->Component = WriteUniqString(component);
 
+   // FIXME: Code depends on the fact that Release files aren't compressed
    FILE* release = fdopen(dup(File.Fd()), "r");
    if (release == NULL)
       return false;

+ 4 - 0
apt-pkg/deb/deblistparser.h

@@ -14,6 +14,10 @@
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/tagfile.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/indexfile.h>
+#endif
+
 class debListParser : public pkgCacheGenerator::ListParser
 {
    public:

+ 4 - 0
apt-pkg/deb/debmetaindex.h

@@ -8,6 +8,10 @@
 #include <string>
 #include <vector>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/sourcelist.h>
+#endif
+
 class debReleaseIndex : public metaIndex {
    public:
 

+ 1 - 1
apt-pkg/deb/debrecords.cc

@@ -25,7 +25,7 @@ using std::string;
 // ---------------------------------------------------------------------
 /* */
 debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : 
-                  File(FileName,FileFd::ReadOnlyGzip), 
+                  File(FileName,FileFd::ReadOnly, FileFd::Extension),
                   Tags(&File, std::max(Cache.Head().MaxVerFileSize, 
 				       Cache.Head().MaxDescFileSize) + 200)
 {

+ 4 - 0
apt-pkg/deb/debrecords.h

@@ -18,6 +18,10 @@
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/fileutl.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/indexfile.h>
+#endif
+
 class debRecordParser : public pkgRecords::Parser
 {
    /** \brief dpointer placeholder (for later in case we need it) */

+ 1 - 1
apt-pkg/deb/debsrcrecords.h

@@ -50,7 +50,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
    virtual bool Files(std::vector<pkgSrcRecords::File> &F);
 
    debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) 
-      : Parser(Index), Fd(File,FileFd::ReadOnlyGzip), Tags(&Fd,102400), 
+      : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400), 
         Buffer(NULL) {}
    virtual ~debSrcRecordParser();
 };

+ 5 - 0
apt-pkg/deb/dpkgpm.h

@@ -15,6 +15,11 @@
 #include <map>
 #include <stdio.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::vector;
+using std::map;
+#endif
+
 class pkgDPkgPMPrivate;
 
 class pkgDPkgPM : public pkgPackageManager

+ 5 - 0
apt-pkg/depcache.h

@@ -46,6 +46,11 @@
 #include <set>
 #include <list>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/progress.h>
+#include <apt-pkg/error.h>
+#endif
+
 class OpProgress;
 
 class pkgDepCache : protected pkgCache::Namespace

+ 5 - 0
apt-pkg/edsp.h

@@ -15,6 +15,11 @@
 #include <list>
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/depcache.h>
+#include <apt-pkg/progress.h>
+#endif
+
 class pkgDepCache;
 class OpProgress;
 

+ 4 - 7
apt-pkg/edsp/edspindexfile.cc

@@ -24,7 +24,7 @@
 // edspIndex::edspIndex - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-edspIndex::edspIndex(string File) : debStatusIndex(File)
+edspIndex::edspIndex(std::string File) : debStatusIndex(File)
 {
 }
 									/*}}}*/
@@ -44,16 +44,13 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 
    if (Prog != NULL)
       Prog->SubProgress(0,File);
-   if (Gen.SelectFile(File,string(),*this) == false)
+   if (Gen.SelectFile(File,std::string(),*this) == false)
       return _error->Error("Problem with SelectFile %s",File.c_str());
 
    // Store the IMS information
    pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
-   struct stat St;
-   if (fstat(Pkg.Fd(),&St) != 0)
-      return _error->Errno("fstat","Failed to stat");
-   CFile->Size = St.st_size;
-   CFile->mtime = St.st_mtime;
+   CFile->Size = Pkg.FileSize();
+   CFile->mtime = Pkg.ModificationTime();
    CFile->Archive = Gen.WriteUniqString("edsp::scenario");
 
    if (Gen.MergeList(Parser) == false)

+ 4 - 0
apt-pkg/edsp/edspindexfile.h

@@ -10,6 +10,10 @@
 
 #include <apt-pkg/debindexfile.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/indexfile.h>
+#endif
+
 class edspIndex : public debStatusIndex
 {
    /** \brief dpointer placeholder (for later in case we need it) */

+ 6 - 0
apt-pkg/edsp/edsplistparser.h

@@ -13,6 +13,12 @@
 
 #include <apt-pkg/deblistparser.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/pkgcachegen.h>
+#include <apt-pkg/indexfile.h>
+#include <apt-pkg/tagfile.h>
+#endif
+
 class FileFd;
 
 class edspListParser : public debListParser

+ 59 - 116
apt-pkg/indexcopy.cc

@@ -16,6 +16,7 @@
 #include <apt-pkg/progress.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
+#include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/indexrecords.h>
@@ -37,8 +38,6 @@
 
 using namespace std;
 
-
-
 // IndexCopy::CopyPackages - Copy the package files from the CD		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -57,15 +56,25 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
    
    // Prepare the progress indicator
    off_t TotalSize = 0;
+   std::vector<APT::Configuration::Compressor> const compressor = APT::Configuration::getCompressors();
    for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
    {
       struct stat Buf;
-      if (stat(string(*I + GetFileName()).c_str(),&Buf) != 0 &&
-	  stat(string(*I + GetFileName() + ".gz").c_str(),&Buf) != 0)
-	 return _error->Errno("stat","Stat failed for %s",
-			      string(*I + GetFileName()).c_str());
+      bool found = false;
+      std::string file = std::string(*I).append(GetFileName());
+      for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
+	   c != compressor.end(); ++c)
+      {
+	 if (stat(std::string(file + c->Extension).c_str(), &Buf) != 0)
+	    continue;
+	 found = true;
+	 break;
+      }
+
+      if (found == false)
+	 return _error->Errno("stat", "Stat failed for %s", file.c_str());
       TotalSize += Buf.st_size;
-   }	
+   }
 
    off_t CurrentSize = 0;
    unsigned int NotFound = 0;
@@ -74,57 +83,11 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
    for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
    {      
       string OrigPath = string(*I,CDROM.length());
-      off_t FileSize = 0;
       
       // Open the package file
-      FileFd Pkg;
-      if (RealFileExists(*I + GetFileName()) == true)
-      {
-	 Pkg.Open(*I + GetFileName(),FileFd::ReadOnly);
-	 FileSize = Pkg.Size();
-      }      
-      else
-      {
-	 FileFd From(*I + GetFileName() + ".gz",FileFd::ReadOnly);
-	 if (_error->PendingError() == true)
-	    return false;
-	 FileSize = From.Size();
-	 
-	 // Get a temp file
-	 FILE *tmp = tmpfile();
-	 if (tmp == 0)
-	    return _error->Errno("tmpfile","Unable to create a tmp file");
-	 Pkg.Fd(dup(fileno(tmp)));
-	 fclose(tmp);
-	 
-	 // Fork gzip
-	 pid_t Process = fork();
-	 if (Process < 0)
-	    return _error->Errno("fork","Couldn't fork gzip");
-	 
-	 // The child
-	 if (Process == 0)
-	 {	    
-	    dup2(From.Fd(),STDIN_FILENO);
-	    dup2(Pkg.Fd(),STDOUT_FILENO);
-	    SetCloseExec(STDIN_FILENO,false);
-	    SetCloseExec(STDOUT_FILENO,false);
-	    
-	    const char *Args[3];
-	    string Tmp =  _config->Find("Dir::bin::gzip","gzip");
-	    Args[0] = Tmp.c_str();
-	    Args[1] = "-d";
-	    Args[2] = 0;
-	    execvp(Args[0],(char **)Args);
-	    exit(100);
-	 }
-	 
-	 // Wait for gzip to finish
-	 if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
-	    return _error->Error("gzip failed, perhaps the disk is full.");
-	 
-	 Pkg.Seek(0);
-      }
+      FileFd Pkg(*I + GetFileName(), FileFd::ReadOnly, FileFd::Extension);
+      off_t const FileSize = Pkg.Size();
+
       pkgTagFile Parser(&Pkg);
       if (_error->PendingError() == true)
 	 return false;
@@ -602,13 +565,19 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
 
       string const releasegpg = *I+"Release.gpg";
       string const release = *I+"Release";
+      string const inrelease = *I+"InRelease";
+      bool useInRelease = true;
 
       // a Release.gpg without a Release should never happen
-      if(RealFileExists(release) == false)
+      if (RealFileExists(inrelease) == true)
+	 ;
+      else if(RealFileExists(release) == false || RealFileExists(releasegpg) == false)
       {
 	 delete MetaIndex;
 	 continue;
       }
+      else
+	 useInRelease = false;
 
       pid_t pid = ExecFork();
       if(pid < 0) {
@@ -616,11 +585,16 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
 	 return false;
       }
       if(pid == 0)
-	 RunGPGV(release, releasegpg);
+      {
+	 if (useInRelease == true)
+	    RunGPGV(inrelease, inrelease);
+	 else
+	    RunGPGV(release, releasegpg);
+      }
 
       if(!ExecWait(pid, "gpgv")) {
 	 _error->Warning("Signature verification failed for: %s",
-			 releasegpg.c_str());
+			 (useInRelease ? inrelease.c_str() : releasegpg.c_str()));
 	 // something went wrong, don't copy the Release.gpg
 	 // FIXME: delete any existing gpg file?
 	 continue;
@@ -650,8 +624,13 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
       delete MetaIndex;
    
       // everything was fine, copy the Release and Release.gpg file
-      CopyMetaIndex(CDROM, Name, prefix, "Release");
-      CopyMetaIndex(CDROM, Name, prefix, "Release.gpg");
+      if (useInRelease == true)
+	 CopyMetaIndex(CDROM, Name, prefix, "InRelease");
+      else
+      {
+	 CopyMetaIndex(CDROM, Name, prefix, "Release");
+	 CopyMetaIndex(CDROM, Name, prefix, "Release.gpg");
+      }
    }   
 
    return true;
@@ -789,15 +768,25 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
    
    // Prepare the progress indicator
    off_t TotalSize = 0;
+   std::vector<APT::Configuration::Compressor> const compressor = APT::Configuration::getCompressors();
    for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
    {
       struct stat Buf;
-      if (stat(string(*I).c_str(),&Buf) != 0 &&
-	  stat(string(*I + ".gz").c_str(),&Buf) != 0)
-	 return _error->Errno("stat","Stat failed for %s",
-			      string(*I).c_str());
+      bool found = false;
+      std::string file = *I;
+      for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
+	   c != compressor.end(); ++c)
+      {
+	 if (stat(std::string(file + c->Extension).c_str(), &Buf) != 0)
+	    continue;
+	 found = true;
+	 break;
+      }
+
+      if (found == false)
+	 return _error->Errno("stat", "Stat failed for %s", file.c_str());
       TotalSize += Buf.st_size;
-   }	
+   }
 
    off_t CurrentSize = 0;
    unsigned int NotFound = 0;
@@ -806,57 +795,11 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
    for (vector<string>::iterator I = List.begin(); I != List.end(); ++I)
    {      
       string OrigPath = string(*I,CDROM.length());
-      off_t FileSize = 0;
-      
+
       // Open the package file
-      FileFd Pkg;
-      if (RealFileExists(*I) == true)
-      {
-	 Pkg.Open(*I,FileFd::ReadOnly);
-	 FileSize = Pkg.Size();
-      }      
-      else
-      {
-	 FileFd From(*I + ".gz",FileFd::ReadOnly);
-	 if (_error->PendingError() == true)
-	    return false;
-	 FileSize = From.Size();
-	 
-	 // Get a temp file
-	 FILE *tmp = tmpfile();
-	 if (tmp == 0)
-	    return _error->Errno("tmpfile","Unable to create a tmp file");
-	 Pkg.Fd(dup(fileno(tmp)));
-	 fclose(tmp);
-	 
-	 // Fork gzip
-	 pid_t Process = fork();
-	 if (Process < 0)
-	    return _error->Errno("fork","Couldn't fork gzip");
-	 
-	 // The child
-	 if (Process == 0)
-	 {	    
-	    dup2(From.Fd(),STDIN_FILENO);
-	    dup2(Pkg.Fd(),STDOUT_FILENO);
-	    SetCloseExec(STDIN_FILENO,false);
-	    SetCloseExec(STDOUT_FILENO,false);
-	    
-	    const char *Args[3];
-	    string Tmp =  _config->Find("Dir::bin::gzip","gzip");
-	    Args[0] = Tmp.c_str();
-	    Args[1] = "-d";
-	    Args[2] = 0;
-	    execvp(Args[0],(char **)Args);
-	    exit(100);
-	 }
-	 
-	 // Wait for gzip to finish
-	 if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
-	    return _error->Error("gzip failed, perhaps the disk is full.");
-	 
-	 Pkg.Seek(0);
-      }
+      FileFd Pkg(*I, FileFd::ReadOnly, FileFd::Extension);
+      off_t const FileSize = Pkg.Size();
+
       pkgTagFile Parser(&Pkg);
       if (_error->PendingError() == true)
 	 return false;

+ 5 - 0
apt-pkg/indexcopy.h

@@ -14,6 +14,11 @@
 #include <string>
 #include <stdio.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::vector;
+#endif
+
 class pkgTagSection;
 class FileFd;
 class indexRecords;

+ 4 - 0
apt-pkg/indexfile.h

@@ -29,6 +29,10 @@
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/macros.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 class pkgAcquire;
 class pkgCacheGenerator;
 class OpProgress;

+ 4 - 0
apt-pkg/indexrecords.h

@@ -13,6 +13,10 @@
 #include <vector>
 #include <ctime>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/fileutl.h>
+#endif
+
 class indexRecords
 {
    bool parseSumData(const char *&Start, const char *End, std::string &Name,

+ 5 - 0
apt-pkg/init.h

@@ -13,6 +13,11 @@
 #ifndef PKGLIB_INIT_H
 #define PKGLIB_INIT_H
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/pkgsystem.h>
+#endif
+
 class pkgSystem;
 class Configuration;
 

+ 7 - 0
apt-pkg/metaindex.h

@@ -6,6 +6,13 @@
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/indexfile.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/srcrecords.h>
+#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/vendor.h>
+using std::string;
+#endif
+
 class pkgAcquire;
 class pkgCacheGenerator;
 class OpProgress;

+ 5 - 0
apt-pkg/packagemanager.h

@@ -29,6 +29,11 @@
 #include <iostream>
 #include <set>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/depcache.h>
+using std::string;
+#endif
+
 class pkgAcquire;
 class pkgDepCache;
 class pkgSourceList;

+ 4 - 1
apt-pkg/pkgcache.h

@@ -74,11 +74,14 @@
 #ifndef PKGLIB_PKGCACHE_H
 #define PKGLIB_PKGCACHE_H
 
-
 #include <string>
 #include <time.h>
 #include <apt-pkg/mmap.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 class pkgVersioningSystem;
 class pkgCache								/*{{{*/
 {

+ 9 - 7
apt-pkg/pkgcachegen.cc

@@ -35,12 +35,14 @@
 
 #include <apti18n.h>
 									/*}}}*/
-typedef vector<pkgIndexFile *>::iterator FileIterator;
+typedef std::vector<pkgIndexFile *>::iterator FileIterator;
 template <typename Iter> std::vector<Iter*> pkgCacheGenerator::Dynamic<Iter>::toReMap;
 
 bool IsDuplicateDescription(pkgCache::DescIterator Desc,
 			    MD5SumValue const &CurMd5, std::string const &CurLang);
 
+using std::string;
+
 // CacheGenerator::pkgCacheGenerator - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* We set the dirty flag and make sure that is written to the disk */
@@ -1221,14 +1223,14 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress
 			MMap **OutMap,bool AllowMem)
 {
    bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
-   
-   vector<pkgIndexFile *> Files;
-   for (vector<metaIndex *>::const_iterator i = List.begin();
+
+   std::vector<pkgIndexFile *> Files;
+   for (std::vector<metaIndex *>::const_iterator i = List.begin();
         i != List.end();
         ++i)
    {
-      vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
-      for (vector<pkgIndexFile *>::const_iterator j = Indexes->begin();
+      std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
+      for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin();
 	   j != Indexes->end();
 	   ++j)
          Files.push_back (*j);
@@ -1418,7 +1420,7 @@ __deprecated bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutM
    { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress, OutMap); }
 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
 {
-   vector<pkgIndexFile *> Files;
+   std::vector<pkgIndexFile *> Files;
    unsigned long EndOfSource = Files.size();
    if (_system->AddStatusFiles(Files) == false)
       return false;

+ 4 - 0
apt-pkg/pkgsystem.h

@@ -41,6 +41,10 @@
 
 #include <vector>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/depcache.h>
+#endif
+
 class pkgDepCache;
 class pkgPackageManager;
 class pkgVersioningSystem;

+ 4 - 0
apt-pkg/policy.h

@@ -38,6 +38,10 @@
 #include <apt-pkg/versionmatch.h>
 #include <vector>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::vector;
+#endif
+
 class pkgPolicy : public pkgDepCache::Policy
 {
    protected:

+ 15 - 13
apt-pkg/sourcelist.h

@@ -32,9 +32,11 @@
 #include <map>
 #include <apt-pkg/pkgcache.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/metaindex.h>
 using std::string;
 using std::vector;
-    
+#endif
 
 class pkgAcquire;
 class pkgIndexFile;
@@ -57,32 +59,32 @@ class pkgSourceList
       const char *Name;
       const char *Label;
 
-      bool FixupURI(string &URI) const;
-      virtual bool ParseLine(vector<metaIndex *> &List,
+      bool FixupURI(std::string &URI) const;
+      virtual bool ParseLine(std::vector<metaIndex *> &List,
 			     const char *Buffer,
-			     unsigned long const &CurLine,string const &File) const;
-      virtual bool CreateItem(vector<metaIndex *> &List,string const &URI,
-			      string const &Dist,string const &Section,
-			      std::map<string, string> const &Options) const = 0;
+			     unsigned long const &CurLine,std::string const &File) const;
+      virtual bool CreateItem(std::vector<metaIndex *> &List,std::string const &URI,
+			      std::string const &Dist,std::string const &Section,
+			      std::map<std::string, std::string> const &Options) const = 0;
       Type();
       virtual ~Type() {};
    };
    
-   typedef vector<metaIndex *>::const_iterator const_iterator;
+   typedef std::vector<metaIndex *>::const_iterator const_iterator;
    
    protected:
 
-   vector<metaIndex *> SrcList;
+   std::vector<metaIndex *> SrcList;
    
    public:
 
    bool ReadMainList();
-   bool Read(string File);
+   bool Read(std::string File);
 
    // CNC:2003-03-03
    void Reset();
-   bool ReadAppend(string File);
-   bool ReadSourceDir(string Dir);
+   bool ReadAppend(std::string File);
+   bool ReadSourceDir(std::string Dir);
    
    // List accessors
    inline const_iterator begin() const {return SrcList.begin();};
@@ -98,7 +100,7 @@ class pkgSourceList
    time_t GetLastModifiedTime();
 
    pkgSourceList();
-   pkgSourceList(string File);
+   pkgSourceList(std::string File);
    ~pkgSourceList();      
 };
 

+ 4 - 4
apt-pkg/srcrecords.cc

@@ -29,8 +29,8 @@ pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : Files(0), Current(0)
 {
    for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); ++I)
    {
-      vector<pkgIndexFile *> *Indexes = (*I)->GetIndexFiles();
-      for (vector<pkgIndexFile *>::const_iterator J = Indexes->begin();
+      std::vector<pkgIndexFile *> *Indexes = (*I)->GetIndexFiles();
+      for (std::vector<pkgIndexFile *>::const_iterator J = Indexes->begin();
 	   J != Indexes->end(); ++J)
       {
          Parser* P = (*J)->CreateSrcParser();
@@ -58,7 +58,7 @@ pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : Files(0), Current(0)
 pkgSrcRecords::~pkgSrcRecords()
 {
    // Blow away all the parser objects
-   for(vector<Parser*>::iterator I = Files.begin(); I != Files.end(); ++I)
+   for(std::vector<Parser*>::iterator I = Files.begin(); I != Files.end(); ++I)
       delete *I;
 }
 									/*}}}*/
@@ -68,7 +68,7 @@ pkgSrcRecords::~pkgSrcRecords()
 bool pkgSrcRecords::Restart()
 {
    Current = Files.begin();
-   for (vector<Parser*>::iterator I = Files.begin();
+   for (std::vector<Parser*>::iterator I = Files.begin();
         I != Files.end(); ++I)
       (*I)->Restart();
    

+ 5 - 0
apt-pkg/srcrecords.h

@@ -17,6 +17,11 @@
 #include <string>
 #include <vector>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::vector;
+#endif
+
 class pkgSourceList;
 class pkgIndexFile;
 class pkgSrcRecords

+ 4 - 0
apt-pkg/tagfile.h

@@ -24,6 +24,10 @@
 
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/fileutl.h>
+#endif
+
 class FileFd;
 
 class pkgTagSection

+ 4 - 0
apt-pkg/vendor.h

@@ -6,6 +6,10 @@
 
 #include <apt-pkg/macros.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 // A class representing a particular software provider.
 class __deprecated Vendor
 {

+ 7 - 0
apt-pkg/vendorlist.h

@@ -17,6 +17,13 @@
 #include <vector>
 #include <apt-pkg/macros.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+#include <apt-pkg/vendor.h>
+#include <apt-pkg/configuration.h>
+using std::string;
+using std::vector;
+#endif
+
 class Vendor;
 class Configuration;
 

+ 4 - 0
apt-pkg/version.h

@@ -23,6 +23,10 @@
 #include <apt-pkg/strutl.h>
 #include <string>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 class pkgVersioningSystem
 {
    public:

+ 4 - 0
apt-pkg/versionmatch.h

@@ -39,6 +39,10 @@
 #include <string>
 #include <apt-pkg/pkgcache.h>
 
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+#endif
+
 class pkgVersionMatch
 {   
    // Version Matching

+ 2 - 0
buildlib/config.h.in

@@ -44,3 +44,5 @@
 
 /* The package name string */
 #undef PACKAGE
+
+#define APT_8_CLEANER_HEADERS

+ 1 - 1
cmdline/apt-cache.cc

@@ -1143,7 +1143,7 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
       return _error->Error(_("Package file %s is out of sync."),I.FileName());
 
    FileFd PkgF;
-   if (PkgF.Open(I.FileName(), FileFd::ReadOnlyGzip) == false)
+   if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false)
       return false;
 
    // Read the record

+ 16 - 0
cmdline/apt-config.cc

@@ -134,6 +134,22 @@ int main(int argc,const char *argv[])					/*{{{*/
    for (std::vector<std::string>::const_iterator a = archs.begin(); a != archs.end(); ++a)
       _config->Set("APT::Architectures::", *a);
 
+   std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
+   _config->Clear("APT::Compressor");
+   string conf = "APT::Compressor::";
+   for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressors.begin(); c != compressors.end(); ++c)
+   {
+      string comp = conf + c->Name + "::";
+      _config->Set(comp + "Name", c->Name);
+      _config->Set(comp + "Extension", c->Extension);
+      _config->Set(comp + "Binary", c->Binary);
+      _config->Set(std::string(comp + "Cost").c_str(), c->Cost);
+      for (std::vector<std::string>::const_iterator a = c->CompressArgs.begin(); a != c->CompressArgs.end(); ++a)
+	 _config->Set(comp + "CompressArg::", *a);
+      for (std::vector<std::string>::const_iterator a = c->UncompressArgs.begin(); a != c->UncompressArgs.end(); ++a)
+	 _config->Set(comp + "UncompressArg::", *a);
+   }
+
    // Match the operation
    CmdL.DispatchArg(Cmds);
    

+ 6 - 4
cmdline/apt-extracttemplates.h

@@ -14,6 +14,8 @@
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/dirstream.h>
 
+#include <string>
+
 class DebFile : public pkgDirStream
 {
 	FileFd File;
@@ -31,11 +33,11 @@ public:
 	bool Go();
 	bool ParseInfo();
 
-	static string GetInstalledVer(const string &package);
+	static std::string GetInstalledVer(const std::string &package);
 
-	string Package;
-	string Version;
-	string DepVer, PreDepVer;
+	std::string Package;
+	std::string Version;
+	std::string DepVer, PreDepVer;
 	unsigned int DepOp, PreDepOp;
 
 	char *Config;

+ 14 - 12
debian/changelog

@@ -3,14 +3,14 @@ apt (0.8.16~exp9) UNRELEASED; urgency=low
   [ Julian Andres Klode ]
   * apt-pkg/cdrom.cc:
     - Accept .bz2, .xz files in addition to .gz files (Closes: #649451)
-  
+
   [ Michael Vogt ]
   * apt-pkg/cdrom.cc:
     - use aptconfiguration to get the supported compression types
   * debian/control:
     - bump debhelper build-dep to debhelper (>= 8.1.3~)
     - set libapt-pkg-dev to multi-arch: same too
- 
+
   [ Colin Watson ]
   * Convert libapt-pkg4.12 and libapt-inst1.4 to Multi-Arch: same.
 
@@ -27,12 +27,22 @@ apt (0.8.16~exp9) UNRELEASED; urgency=low
   * cmdline/apt-get.cc:
     - ignore foreign architectures if we check if a provides has only one
       resolver as it's basically the same for the user, so no need to choose
-  
- -- Julian Andres Klode <jak@debian.org>  Mon, 21 Nov 2011 18:46:36 +0100
+  * cmdline/apt-config.cc:
+    - dump the APT::Compressor settings correctly and completely
+  * apt-pkg/contrib/fileutl.{h,cc}:
+    - implement a ModificationTime method for FileFd
+    - add a ReadLine method
+    - drop the explicit export of gz-compression handling
+  * apt-pkg/cdrom.cc:
+    - support InRelease files on cdrom
+
+ -- David Kalnischkies <kalnischkies@gmail.com>  Sun, 11 Dec 2011 19:34:58 +0100
 
 apt (0.8.16~exp8) experimental; urgency=low
 
   [ David Kalnischkies ]
+  * algorithms.cc:
+    - show a debug why a package was kept by ResolveByKeep()
   * apt-pkg/packagemanager.cc:
     - do not fail on unpacked packages in SmartUnPack, just don't
       shedule them for unpack, but do all checks and configure them
@@ -228,14 +238,6 @@ apt (0.8.16~exp1) experimental; urgency=low
 
  -- Michael Vogt <mvo@debian.org>  Wed, 29 Jun 2011 12:40:31 +0200
 
-apt (1.8.15.9+nmu1) unstable; urgency=low
-
-  [ David Kalnischkies ]
-  * algorithms.cc:
-    - show a debug why a package was kept by ResolveByKeep()
-
- -- David Kalnischkies <kalnischkies@gmail.com>  Mon, 17 Oct 2011 16:36:22 +0200
-
 apt (0.8.15.9) unstable; urgency=low
 
   [ David Kalnischkies ]

+ 13 - 127
ftparchive/multicompress.cc

@@ -16,6 +16,7 @@
 // Include Files							/*{{{*/
 #include <config.h>
 
+#include <apt-pkg/fileutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/md5.h>
@@ -90,7 +91,7 @@ MultiCompress::MultiCompress(string const &Output,string const &Compress,
    /* Open all the temp files now so we can report any errors. File is 
       made unreable to prevent people from touching it during creating. */
    for (Files *I = Outputs; I != 0; I = I->Next)
-      I->TmpFile.Open(I->Output + ".new",FileFd::WriteEmpty,0600);
+      I->TmpFile.Open(I->Output + ".new", FileFd::WriteOnly | FileFd::Create | FileFd::Empty, FileFd::Extension, 0600);
    if (_error->PendingError() == true)
       return;
 
@@ -182,11 +183,6 @@ bool MultiCompress::Start()
       _exit(0);
    };
 
-   /* Tidy up the temp files, we open them in the constructor so as to
-      get proper error reporting. Close them now. */
-   for (Files *I = Outputs; I != 0; I = I->Next)
-      I->TmpFile.Close();
-   
    close(Pipe[0]);
    Input = fdopen(Pipe[1],"w");
    if (Input == 0)
@@ -261,77 +257,10 @@ bool MultiCompress::Finalize(unsigned long long &OutSize)
    return true;
 }
 									/*}}}*/
-// MultiCompress::OpenCompress - Open the compressor			/*{{{*/
-// ---------------------------------------------------------------------
-/* This opens the compressor, either in compress mode or decompress 
-   mode. FileFd is always the compressor input/output file, 
-   OutFd is the created pipe, Input for Compress, Output for Decompress. */
-bool MultiCompress::OpenCompress(APT::Configuration::Compressor const &Prog,
-				 pid_t &Pid,int const &FileFd,int &OutFd,bool const &Comp)
-{
-   Pid = -1;
-   
-   // No compression
-   if (Prog.Binary.empty() == true)
-   {
-      OutFd = dup(FileFd);
-      return true;
-   }
-      
-   // Create a data pipe
-   int Pipe[2] = {-1,-1};
-   if (pipe(Pipe) != 0)
-      return _error->Errno("pipe",_("Failed to create subprocess IPC"));
-   for (int J = 0; J != 2; J++)
-      SetCloseExec(Pipe[J],true);
-
-   if (Comp == true)
-      OutFd = Pipe[1];
-   else
-      OutFd = Pipe[0];
-   
-   // The child..
-   Pid = ExecFork();
-   if (Pid == 0)
-   {
-      if (Comp == true)
-      {
-	 dup2(FileFd,STDOUT_FILENO);
-	 dup2(Pipe[0],STDIN_FILENO);
-      }   
-      else
-      {
-	 dup2(FileFd,STDIN_FILENO);
-	 dup2(Pipe[1],STDOUT_FILENO);
-      }
-      
-      SetCloseExec(STDOUT_FILENO,false);
-      SetCloseExec(STDIN_FILENO,false);
-
-      std::vector<char const*> Args;
-      Args.push_back(Prog.Binary.c_str());
-      std::vector<std::string> const * const addArgs =
-		(Comp == true) ? &(Prog.CompressArgs) : &(Prog.UncompressArgs);
-      for (std::vector<std::string>::const_iterator a = addArgs->begin();
-	   a != addArgs->end(); ++a)
-	 Args.push_back(a->c_str());
-      Args.push_back(NULL);
-
-      execvp(Args[0],(char **)&Args[0]);
-      cerr << _("Failed to exec compressor ") << Args[0] << endl;
-      _exit(100);
-   };      
-   if (Comp == true)
-      close(Pipe[0]);
-   else
-      close(Pipe[1]);
-   return true;
-}
-									/*}}}*/
 // MultiCompress::OpenOld - Open an old file				/*{{{*/
 // ---------------------------------------------------------------------
 /* This opens one of the original output files, possibly decompressing it. */
-bool MultiCompress::OpenOld(int &Fd,pid_t &Proc)
+bool MultiCompress::OpenOld(FileFd &Fd)
 {
    Files *Best = Outputs;
    for (Files *I = Outputs; I != 0; I = I->Next)
@@ -339,29 +268,9 @@ bool MultiCompress::OpenOld(int &Fd,pid_t &Proc)
 	 Best = I;
 
    // Open the file
-   FileFd F(Best->Output,FileFd::ReadOnly);
-   if (_error->PendingError() == true)
-      return false;
-   
-   // Decompress the file so we can read it
-   if (OpenCompress(Best->CompressProg,Proc,F.Fd(),Fd,false) == false)
-      return false;
-   
-   return true;
+   return Fd.Open(Best->Output, FileFd::ReadOnly, FileFd::Extension);
 }
 									/*}}}*/
-// MultiCompress::CloseOld - Close the old file				/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool MultiCompress::CloseOld(int Fd,pid_t Proc)
-{
-   close(Fd);
-   if (Proc != -1)
-      if (ExecWait(Proc,_("decompressor"),false) == false)
-	 return false;
-   return true;
-}   
-									/*}}}*/
 // MultiCompress::Child - The writer child				/*{{{*/
 // ---------------------------------------------------------------------
 /* The child process forks a bunch of compression children and takes 
@@ -371,14 +280,6 @@ bool MultiCompress::CloseOld(int Fd,pid_t Proc)
    is new then the temp files are renamed, otherwise they are erased. */
 bool MultiCompress::Child(int const &FD)
 {
-   // Start the compression children.
-   for (Files *I = Outputs; I != 0; I = I->Next)
-   {
-      if (OpenCompress(I->CompressProg,I->CompressProc,I->TmpFile.Fd(),
-		       I->Fd,true) == false)
-	 return false;      
-   }
-
    /* Okay, now we just feed data from FD to all the other FDs. Also
       stash a hash of the data to use later. */
    SetNonBlock(FD,false);
@@ -398,25 +299,14 @@ bool MultiCompress::Child(int const &FD)
       FileSize += Res;
       for (Files *I = Outputs; I != 0; I = I->Next)
       {
-	 if (write(I->Fd,Buffer,Res) != Res)
+	 if (I->TmpFile.Write(Buffer, Res) == false)
 	 {
 	    _error->Errno("write",_("IO to subprocess/file failed"));
 	    break;
 	 }
       }      
    }   
-   
-   // Close all the writers
-   for (Files *I = Outputs; I != 0; I = I->Next)
-      close(I->Fd);
-   
-   // Wait for the compressors to exit
-   for (Files *I = Outputs; I != 0; I = I->Next)
-   {
-      if (I->CompressProc != -1)
-	 ExecWait(I->CompressProc, I->CompressProg.Binary.c_str(), false);
-   }
-   
+
    if (_error->PendingError() == true)
       return false;
    
@@ -435,31 +325,27 @@ bool MultiCompress::Child(int const &FD)
    // Check the MD5 of the lowest cost entity.
    while (Missing == false)
    {
-      int CompFd = -1;
-      pid_t Proc = -1;
-      if (OpenOld(CompFd,Proc) == false)
+      FileFd CompFd;
+      if (OpenOld(CompFd) == false)
       {
 	 _error->Discard();
 	 break;
       }
-            
+
       // Compute the hash
       MD5Summation OldMD5;
       unsigned long long NewFileSize = 0;
       while (1)
       {
-	 int Res = read(CompFd,Buffer,sizeof(Buffer));
+	 unsigned long long Res = 0;
+	 if (CompFd.Read(Buffer,sizeof(Buffer), &Res) == false)
+	    return _error->Errno("read",_("Failed to read while computing MD5"));
 	 if (Res == 0)
 	    break;
-	 if (Res < 0)
-	    return _error->Errno("read",_("Failed to read while computing MD5"));
 	 NewFileSize += Res;
 	 OldMD5.Add(Buffer,Res);
       }
-      
-      // Tidy the compressor
-      if (CloseOld(CompFd,Proc) == false)
-	 return false;
+      CompFd.Close();
 
       // Check the hash
       if (OldMD5.Result() == MD5.Result() &&

+ 1 - 5
ftparchive/multicompress.h

@@ -34,15 +34,12 @@ class MultiCompress
       FileFd TmpFile;
       pid_t CompressProc;
       time_t OldMTime;
-      int Fd;
    };
    
    Files *Outputs;
    pid_t Outputter;
    mode_t Permissions;
 
-   bool OpenCompress(APT::Configuration::Compressor const &Prog,
-		     pid_t &Pid,int const &FileFd, int &OutFd,bool const &Comp);
    bool Child(int const &Fd);
    bool Start();
    bool Die();
@@ -54,8 +51,7 @@ class MultiCompress
    unsigned long UpdateMTime;
    
    bool Finalize(unsigned long long &OutSize);
-   bool OpenOld(int &Fd,pid_t &Proc);
-   bool CloseOld(int Fd,pid_t Proc);
+   bool OpenOld(FileFd &Fd);
    static bool GetStat(std::string const &Output,std::string const &Compress,struct stat &St);
    
    MultiCompress(std::string const &Output,std::string const &Compress,

+ 8 - 15
ftparchive/writer.cc

@@ -889,22 +889,16 @@ bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompres
    MultiCompress Pkgs(PkgFile,PkgCompress,0,false);
    if (_error->PendingError() == true)
       return false;
-   
+
    // Open the package file
-   int CompFd = -1;
-   pid_t Proc = -1;
-   if (Pkgs.OpenOld(CompFd,Proc) == false)
+   FileFd Fd;
+   if (Pkgs.OpenOld(Fd) == false)
       return false;
-   
-   // No auto-close FD
-   FileFd Fd(CompFd,false);   
+
    pkgTagFile Tags(&Fd);
    if (_error->PendingError() == true)
-   {
-      Pkgs.CloseOld(CompFd,Proc);
       return false;
-   }
-   
+
    // Parse.
    pkgTagSection Section;
    while (Tags.Step(Section) == true)
@@ -926,11 +920,10 @@ bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompres
 	 _error->DumpErrors();
       }
    }
-   
+
    // Tidy the compressor
-   if (Pkgs.CloseOld(CompFd,Proc) == false)
-      return false;
-   
+   Fd.Close();
+
    return true;
 }
 

+ 1 - 1
methods/gzip.cc

@@ -48,7 +48,7 @@ bool GzipMethod::Fetch(FetchItem *Itm)
    URIStart(Res);
    
    // Open the source and destination files
-   FileFd From(Path,FileFd::ReadOnlyGzip);
+   FileFd From(Path,FileFd::ReadOnly, FileFd::Gzip);
 
    if(From.FileSize() == 0)
       return _error->Error(_("Empty files can't be valid archives"));

+ 15 - 29
methods/rred.cc

@@ -37,13 +37,13 @@ class RredMethod : public pkgAcqMethod {
 	// return values
 	enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE, MMAP_FAILED};
 
-	State applyFile(gzFile &ed_cmds, FILE *in_file, FILE *out_file,
+	State applyFile(FileFd &ed_cmds, FILE *in_file, FILE *out_file,
 	             unsigned long &line, char *buffer, Hashes *hash) const;
 	void ignoreLineInFile(FILE *fin, char *buffer) const;
-	void ignoreLineInFile(gzFile &fin, char *buffer) const;
+	void ignoreLineInFile(FileFd &fin, char *buffer) const;
 	void copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines,
 	                            Hashes *hash, char *buffer) const;
-	void copyLinesFromFileToFile(gzFile &fin, FILE *fout, unsigned int lines,
+	void copyLinesFromFileToFile(FileFd &fin, FILE *fout, unsigned int lines,
 	                            Hashes *hash, char *buffer) const;
 
 	State patchFile(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const;
@@ -72,10 +72,10 @@ public:
  *  \param hash the created file for correctness
  *  \return the success State of the ed command executor
  */
-RredMethod::State RredMethod::applyFile(gzFile &ed_cmds, FILE *in_file, FILE *out_file,
+RredMethod::State RredMethod::applyFile(FileFd &ed_cmds, FILE *in_file, FILE *out_file,
 			unsigned long &line, char *buffer, Hashes *hash) const {
 	// get the current command and parse it
-	if (gzgets(ed_cmds, buffer, BUF_SIZE) == NULL) {
+	if (ed_cmds.ReadLine(buffer, BUF_SIZE) == NULL) {
 		if (Debug == true)
 			std::clog << "rred: encounter end of file - we can start patching now." << std::endl;
 		line = 0;
@@ -130,7 +130,7 @@ RredMethod::State RredMethod::applyFile(gzFile &ed_cmds, FILE *in_file, FILE *ou
 	unsigned char mode = *idx;
 
 	// save the current position
-	unsigned const long pos = gztell(ed_cmds);
+	unsigned const long long pos = ed_cmds.Tell();
 
 	// if this is add or change then go to the next full stop
 	unsigned int data_length = 0;
@@ -164,7 +164,7 @@ RredMethod::State RredMethod::applyFile(gzFile &ed_cmds, FILE *in_file, FILE *ou
 
 	// include data from ed script
 	if (mode == MODE_CHANGED || mode == MODE_ADDED) {
-		gzseek(ed_cmds, pos, SEEK_SET);
+		ed_cmds.Seek(pos);
 		copyLinesFromFileToFile(ed_cmds, out_file, data_length, hash, buffer);
 	}
 
@@ -190,11 +190,11 @@ void RredMethod::copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lin
 	}
 }
 										/*}}}*/
-void RredMethod::copyLinesFromFileToFile(gzFile &fin, FILE *fout, unsigned int lines,/*{{{*/
+void RredMethod::copyLinesFromFileToFile(FileFd &fin, FILE *fout, unsigned int lines,/*{{{*/
 					Hashes *hash, char *buffer) const {
 	while (0 < lines--) {
 		do {
-			gzgets(fin, buffer, BUF_SIZE);
+			fin.ReadLine(buffer, BUF_SIZE);
 			size_t const written = fwrite(buffer, 1, strlen(buffer), fout);
 			hash->Add((unsigned char*)buffer, written);
 		} while (strlen(buffer) == (BUF_SIZE - 1) &&
@@ -211,11 +211,11 @@ void RredMethod::ignoreLineInFile(FILE *fin, char *buffer) const {		/*{{{*/
 	}
 }
 										/*}}}*/
-void RredMethod::ignoreLineInFile(gzFile &fin, char *buffer) const {		/*{{{*/
-	gzgets(fin, buffer, BUF_SIZE);
+void RredMethod::ignoreLineInFile(FileFd &fin, char *buffer) const {		/*{{{*/
+	fin.ReadLine(buffer, BUF_SIZE);
 	while (strlen(buffer) == (BUF_SIZE - 1) &&
 	       buffer[BUF_SIZE - 2] != '\n') {
-		gzgets(fin, buffer, BUF_SIZE);
+		fin.ReadLine(buffer, BUF_SIZE);
 		buffer[0] = ' ';
 	}
 }
@@ -224,12 +224,11 @@ RredMethod::State RredMethod::patchFile(FileFd &Patch, FileFd &From,		/*{{{*/
 					FileFd &out_file, Hashes *hash) const {
    char buffer[BUF_SIZE];
    FILE* fFrom = fdopen(From.Fd(), "r");
-   gzFile fPatch = Patch.gzFd();
    FILE* fTo = fdopen(out_file.Fd(), "w");
 
    /* we do a tail recursion to read the commands in the right order */
    unsigned long line = -1; // assign highest possible value
-   State const result = applyFile(fPatch, fFrom, fTo, line, buffer, hash);
+   State const result = applyFile(Patch, fFrom, fTo, line, buffer, hash);
    
    /* read the rest from infile */
    if (result == ED_OK) {
@@ -258,20 +257,7 @@ struct EdCommand {
 RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From,		/*{{{*/
 					FileFd &out_file, Hashes *hash) const {
 #ifdef _POSIX_MAPPED_FILES
-	MMap ed_cmds(MMap::ReadOnly);
-	if (Patch.gzFd() != NULL) {
-		unsigned long long mapSize = Patch.Size();
-		DynamicMMap* dyn = new DynamicMMap(0, mapSize, 0);
-		if (dyn->validData() == false) {
-			delete dyn;
-			return MMAP_FAILED;
-		}
-		dyn->AddSize(mapSize);
-		gzread(Patch.gzFd(), dyn->Data(), mapSize);
-		ed_cmds = *dyn;
-	} else
-		ed_cmds = MMap(Patch, MMap::ReadOnly);
-
+	MMap ed_cmds(Patch, MMap::ReadOnly);
 	MMap in_file(From, MMap::ReadOnly);
 
 	if (ed_cmds.Size() == 0 || in_file.Size() == 0)
@@ -489,7 +475,7 @@ bool RredMethod::Fetch(FetchItem *Itm)						/*{{{*/
    // Open the source and destination files (the d'tor of FileFd will do 
    // the cleanup/closing of the fds)
    FileFd From(Path,FileFd::ReadOnly);
-   FileFd Patch(Path+".ed",FileFd::ReadOnlyGzip);
+   FileFd Patch(Path+".ed",FileFd::ReadOnly, FileFd::Gzip);
    FileFd To(Itm->DestFile,FileFd::WriteAtomic);   
    To.EraseOnFailure();
    if (_error->PendingError() == true)

+ 1 - 1
test/integration/framework

@@ -102,7 +102,7 @@ aptitude() {
 
 addtrap() {
 	CURRENTTRAP="$CURRENTTRAP $1"
-	trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+	trap "$CURRENTTRAP exit;" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
 }
 
 setupenvironment() {

+ 86 - 0
test/libapt/cdromfindpackages_test.cc

@@ -0,0 +1,86 @@
+#include <apt-pkg/cdrom.h>
+#include <apt-pkg/error.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "assert.h"
+
+class Cdrom : public pkgCdrom {
+	public:
+	bool FindPackages(std::string const &CD,
+			  std::vector<std::string> &List,
+			  std::vector<std::string> &SList,
+			  std::vector<std::string> &SigList,
+			  std::vector<std::string> &TransList,
+			  std::string &InfoDir) {
+		bool const result = pkgCdrom::FindPackages(CD, List, SList, SigList, TransList, InfoDir, NULL, 0);
+		std::sort(List.begin(), List.end());
+		std::sort(SList.begin(), SList.end());
+		std::sort(SigList.begin(), SigList.end());
+		std::sort(TransList.begin(), TransList.end());
+		return result;
+	}
+
+	bool DropRepeats(std::vector<std::string> &List, char const *Name) {
+		return pkgCdrom::DropRepeats(List, Name);
+	}
+};
+
+int main(int argc, char const *argv[]) {
+	if (argc != 2) {
+		std::cout << "One parameter expected - given " << argc << std::endl;
+		return 100;
+	}
+
+	Cdrom cd;
+	std::vector<std::string> Packages, Sources, Signatur, Translation;
+	std::string InfoDir;
+	std::string path = argv[1];
+	equals(true, cd.FindPackages(path, Packages, Sources, Signatur, Translation, InfoDir));
+	equals(4, Packages.size());
+	equals(path + "/dists/sid/main/binary-i386/", Packages[0]);
+	equals(path + "/dists/stable/contrib/binary-amd64/", Packages[1]);
+	equals(path + "/dists/stable/main/binary-i386/", Packages[2]);
+	equals(path + "/dists/unstable/main/binary-i386/", Packages[3]);
+	equals(3, Sources.size());
+	equals(path + "/dists/sid/main/source/", Sources[0]);
+	equals(path + "/dists/stable/main/source/", Sources[1]);
+	equals(path + "/dists/unstable/main/source/", Sources[2]);
+	equals(3, Signatur.size());
+	equals(path + "/dists/sid/", Signatur[0]);
+	equals(path + "/dists/stable/", Signatur[1]);
+	equals(path + "/dists/unstable/", Signatur[2]);
+	equals(4, Translation.size());
+	equals(path + "/dists/sid/main/i18n/Translation-de", Translation[0]);
+	equals(path + "/dists/sid/main/i18n/Translation-en", Translation[1]);
+	equals(path + "/dists/unstable/main/i18n/Translation-de", Translation[2]);
+	equals(path + "/dists/unstable/main/i18n/Translation-en", Translation[3]);
+	equals(path + "/.disk/", InfoDir);
+
+	cd.DropRepeats(Packages, "Packages");
+	cd.DropRepeats(Sources, "Sources");
+	_error->PushToStack();
+	cd.DropRepeats(Signatur, "InRelease");
+	cd.DropRepeats(Signatur, "Release.gpg");
+	_error->RevertToStack();
+	_error->DumpErrors();
+	cd.DropRepeats(Translation, "");
+
+	equals(3, Packages.size());
+	equals(path + "/dists/stable/contrib/binary-amd64/", Packages[0]);
+	equals(path + "/dists/stable/main/binary-i386/", Packages[1]);
+	equals(path + "/dists/unstable/main/binary-i386/", Packages[2]);
+	equals(2, Sources.size());
+	equals(path + "/dists/stable/main/source/", Sources[0]);
+	equals(path + "/dists/unstable/main/source/", Sources[1]);
+	equals(2, Signatur.size());
+	equals(path + "/dists/stable/", Signatur[0]);
+	equals(path + "/dists/unstable/", Signatur[1]);
+	equals(2, Translation.size());
+	equals(path + "/dists/unstable/main/i18n/Translation-de", Translation[0]);
+	equals(path + "/dists/unstable/main/i18n/Translation-en", Translation[1]);
+
+	return 0;
+}

+ 6 - 0
test/libapt/makefile

@@ -74,3 +74,9 @@ PROGRAM = Configuration${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = configuration_test.cc
 include $(PROGRAM_H)
+
+# test cdroms core FindPackages
+PROGRAM = CdromFindPackages${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = cdromfindpackages_test.cc
+include $(PROGRAM_H)

+ 29 - 0
test/libapt/run-tests

@@ -75,6 +75,35 @@ do
 		continue
 	elif [ $name = "CompareVersion${EXT}" ]; then
 		tmppath="${DIR}/versions.lst"
+	elif [ $name = "CdromFindPackages${EXT}" ]; then
+		tmppath=$(mktemp -d)
+		mkdir -p "${tmppath}/.disk" "${tmppath}/pool" \
+			"${tmppath}/dists/stable/main/binary-i386" \
+			"${tmppath}/dists/stable/main/source" \
+			"${tmppath}/dists/stable/contrib/binary-amd64" \
+			"${tmppath}/dists/stable/contrib/binary-all" \
+			"${tmppath}/dists/unstable/main/binary-i386" \
+			"${tmppath}/dists/unstable/main/i18n" \
+			"${tmppath}/dists/unstable/main/source" \
+			"${tmppath}/dists/broken/non-free/source"
+		touch "${tmppath}/dists/broken/.aptignr" \
+			"${tmppath}/dists/stable/main/binary-i386/Packages" \
+			"${tmppath}/dists/stable/main/binary-i386/Packages.bz2" \
+			"${tmppath}/dists/stable/main/source/Sources.xz" \
+			"${tmppath}/dists/stable/contrib/binary-amd64/Packages" \
+			"${tmppath}/dists/stable/contrib/binary-amd64/Packages.gz" \
+			"${tmppath}/dists/stable/contrib/binary-all/Packages" \
+			"${tmppath}/dists/unstable/main/binary-i386/Packages.xz" \
+			"${tmppath}/dists/unstable/main/binary-i386/Packages.lzma" \
+			"${tmppath}/dists/unstable/main/i18n/Translation-en" \
+			"${tmppath}/dists/unstable/main/i18n/Translation-de.bz2" \
+			"${tmppath}/dists/unstable/main/source/Sources.xz" \
+			"${tmppath}/dists/broken/non-free/source/Sources.gz" \
+			"${tmppath}/dists/stable/Release.gpg" \
+			"${tmppath}/dists/stable/Release" \
+			"${tmppath}/dists/unstable/InRelease" \
+			"${tmppath}/dists/broken/Release.gpg"
+		ln -s "${tmppath}/dists/unstable" "${tmppath}/dists/sid"
 	fi
 
 	echo -n "Testing with ${NAME} "