Sfoglia il codice sorgente

enable FileFd to guess the compressor based on the filename if requested or
to search for compressed silbings of the given filename and use this guessing
instead of hardcoding Gzip compression

David Kalnischkies 14 anni fa
parent
commit
468720c59f

+ 112 - 17
apt-pkg/contrib/fileutl.cc

@@ -24,6 +24,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
+#include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
 
 
 #include <cstdlib>
 #include <cstdlib>
@@ -725,6 +726,11 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned
    Close();
    Close();
    Flags = AutoClose;
    Flags = AutoClose;
 
 
+   if (Compress == Auto && (Mode & WriteOnly) == WriteOnly)
+      return _error->Error("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str());
+   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());
+
    int fileflags = 0;
    int fileflags = 0;
 #define if_FLAGGED_SET(FLAG, MODE) if ((Mode & FLAG) == FLAG) fileflags |= MODE
 #define if_FLAGGED_SET(FLAG, MODE) if ((Mode & FLAG) == FLAG) fileflags |= MODE
    if_FLAGGED_SET(ReadWrite, O_RDWR);
    if_FLAGGED_SET(ReadWrite, O_RDWR);
@@ -738,6 +744,70 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned
    if_FLAGGED_SET(Empty, O_TRUNC);
    if_FLAGGED_SET(Empty, O_TRUNC);
 #undef if_FLAGGED_SET
 #undef if_FLAGGED_SET
 
 
+   // 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)
+   {
+      Compress = None;
+      for (; compressor != compressors.end(); ++compressor)
+      {
+	 std::string file = std::string(FileName).append(compressor->Extension);
+	 if (FileExists(file) == false)
+	    continue;
+	 FileName = file;
+	 if (compressor->Binary == ".")
+	    Compress = None;
+	 else
+	    Compress = Extension;
+	 break;
+      }
+   }
+   else if (Compress == Extension)
+   {
+      Compress = None;
+      std::string ext = flExtension(FileName);
+      if (ext != FileName)
+      {
+	 ext = "." + ext;
+	 for (; compressor != compressors.end(); ++compressor)
+	    if (ext == compressor->Extension)
+	       break;
+      }
+   }
+   else if (Compress != None)
+   {
+      std::string name;
+      switch (Compress)
+      {
+      case Gzip: name = "gzip"; break;
+      case Bzip2: name = "bzip2"; break;
+      case Lzma: name = "lzma"; break;
+      case Xz: name = "xz"; break;
+      default: return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str());
+      }
+      for (; compressor != compressors.end(); ++compressor)
+	 if (compressor->Name == name)
+	    break;
+      if (compressor == compressors.end() && name != "gzip")
+	 return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
+   }
+
+   // if we have them, use inbuilt compressors instead of forking
+   if (compressor != compressors.end())
+   {
+      if (compressor->Name == "gzip")
+      {
+	 Compress = Gzip;
+	 compressor = compressors.end();
+      }
+      else if (compressor->Name == "." || Compress == None)
+      {
+	 Compress = None;
+	 compressor = compressors.end();
+      }
+   }
+
    if ((Mode & Atomic) == Atomic)
    if ((Mode & Atomic) == Atomic)
    {
    {
       Flags |= Replace;
       Flags |= Replace;
@@ -757,18 +827,27 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned
 	 unlink(FileName.c_str());
 	 unlink(FileName.c_str());
    }
    }
 
 
-   if (TemporaryFileName.empty() == false)
-      iFd = open(TemporaryFileName.c_str(), fileflags, Perms);
-   else
-      iFd = open(FileName.c_str(), fileflags, Perms);
+   if (compressor != compressors.end())
+   {
+      if ((Mode & ReadWrite) == ReadWrite)
+	 _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor->Name.c_str(), FileName.c_str());
 
 
-   if (iFd != -1 && Compress == Gzip)
+      _error->Error("Forking external compressor %s is not implemented for %s", compressor->Name.c_str(), FileName.c_str());
+   }
+   else
    {
    {
-      gz = gzdopen (iFd, "r");
-      if (gz == NULL)
+      if (TemporaryFileName.empty() == false)
+	 iFd = open(TemporaryFileName.c_str(), fileflags, Perms);
+      else
+	 iFd = open(FileName.c_str(), fileflags, Perms);
+
+      if (iFd != -1)
       {
       {
-	 close (iFd);
-	 iFd = -1;
+	 if (OpenInternDescriptor(Mode, Compress) == false)
+	 {
+	    close (iFd);
+	    iFd = -1;
+	 }
       }
       }
    }
    }
 
 
@@ -788,17 +867,33 @@ bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool A
    Close();
    Close();
    Flags = (AutoClose) ? FileFd::AutoClose : 0;
    Flags = (AutoClose) ? FileFd::AutoClose : 0;
    iFd = Fd;
    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, Compress) == false)
+   {
+      if (AutoClose)
+	 close (iFd);
+      return _error->Errno("gzdopen",_("Could not open file descriptor %d"), Fd);
    }
    }
    this->FileName = "";
    this->FileName = "";
    return true;
    return true;
+}
+bool FileFd::OpenInternDescriptor(OpenMode Mode, CompressMode Compress)
+{
+   if (Compress == None)
+      return true;
+   else if (Compress == Gzip)
+   {
+      if ((Mode & ReadWrite) == ReadWrite)
+	 gz = gzdopen(iFd, "r+");
+      else if ((Mode & WriteOnly) == WriteOnly)
+	 gz = gzdopen(iFd, "w");
+      else
+	 gz = gzdopen (iFd, "r");
+      if (gz == NULL)
+	 return false;
+   }
+   else
+      return false;
+   return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FileFd::~File - Closes the file					/*{{{*/
 // FileFd::~File - Closes the file					/*{{{*/

+ 11 - 3
apt-pkg/contrib/fileutl.h

@@ -61,7 +61,7 @@ class FileFd
 	ReadOnlyGzip,
 	ReadOnlyGzip,
 	WriteAtomic = ReadWrite | Create | Atomic
 	WriteAtomic = ReadWrite | Create | Atomic
    };
    };
-   enum CompressMode { Auto, None, Gzip, Bzip2, Lzma, Xz };
+   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)
    inline bool Read(void *To,unsigned long long Size,bool AllowEof)
    {
    {
@@ -94,7 +94,7 @@ class FileFd
    }
    }
 
 
    bool Open(std::string FileName,OpenMode Mode,CompressMode Compress,unsigned long Perms = 0666);
    bool Open(std::string FileName,OpenMode Mode,CompressMode Compress,unsigned long Perms = 0666);
-   inline bool Open(std::string const &FileName,OpenMode Mode,unsigned long Perms = 0666) {
+   inline bool Open(std::string const &FileName,OpenMode Mode, unsigned long Perms = 0666) {
       return Open(FileName, Mode, None, Perms);
       return Open(FileName, Mode, None, Perms);
    };
    };
    bool OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose=false);
    bool OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose=false);
@@ -118,11 +118,19 @@ class FileFd
    FileFd(std::string FileName,OpenMode Mode,unsigned long Perms = 0666) : iFd(-1), 
    FileFd(std::string FileName,OpenMode Mode,unsigned long Perms = 0666) : iFd(-1), 
             Flags(0), gz(NULL)
             Flags(0), gz(NULL)
    {
    {
-      Open(FileName,Mode,Perms);
+      Open(FileName,Mode, None, Perms);
+   };
+   FileFd(std::string FileName,OpenMode Mode, CompressMode Compress, unsigned long Perms = 0666) :
+	    iFd(-1), Flags(0), gz(NULL)
+   {
+      Open(FileName,Mode, Compress, Perms);
    };
    };
    FileFd(int Fd = -1) : iFd(Fd), Flags(AutoClose), gz(NULL) {};
    FileFd(int Fd = -1) : iFd(Fd), Flags(AutoClose), gz(NULL) {};
    FileFd(int Fd,bool) : iFd(Fd), Flags(0), gz(NULL) {};
    FileFd(int Fd,bool) : iFd(Fd), Flags(0), gz(NULL) {};
    virtual ~FileFd();
    virtual ~FileFd();
+
+   private:
+   bool OpenInternDescriptor(OpenMode Mode, CompressMode Compress);
 };
 };
 
 
 bool RunScripts(const char *Cnf);
 bool RunScripts(const char *Cnf);

+ 7 - 6
apt-pkg/deb/debindexfile.cc

@@ -159,7 +159,7 @@ unsigned long debSourcesIndex::Size() const
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    _error->PushToStack();
    _error->PushToStack();
 
 
-   FileFd f = FileFd (IndexFile("Sources"), FileFd::ReadOnlyGzip);
+   FileFd f = FileFd (IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension);
    if (!f.Failed())
    if (!f.Failed())
       size = f.Size();
       size = f.Size();
 
 
@@ -288,7 +288,7 @@ unsigned long debPackagesIndex::Size() const
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    _error->PushToStack();
    _error->PushToStack();
 
 
-   FileFd f = FileFd (IndexFile("Packages"), FileFd::ReadOnlyGzip);
+   FileFd f = FileFd (IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension);
    if (!f.Failed())
    if (!f.Failed())
       size = f.Size();
       size = f.Size();
 
 
@@ -305,7 +305,7 @@ unsigned long debPackagesIndex::Size() const
 bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
 {
 {
    string PackageFile = IndexFile("Packages");
    string PackageFile = IndexFile("Packages");
-   FileFd Pkg(PackageFile,FileFd::ReadOnlyGzip);
+   FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
    debListParser Parser(&Pkg, Architecture);
    debListParser Parser(&Pkg, Architecture);
 
 
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
@@ -319,6 +319,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    // Store the IMS information
    // Store the IMS information
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
    pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
    pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
+   // FIXME: Get this info from FileFd instead
    struct stat St;
    struct stat St;
    if (fstat(Pkg.Fd(),&St) != 0)
    if (fstat(Pkg.Fd(),&St) != 0)
       return _error->Errno("fstat","Failed to stat");
       return _error->Errno("fstat","Failed to stat");
@@ -489,7 +490,7 @@ unsigned long debTranslationsIndex::Size() const
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    /* we need to ignore errors here; if the lists are absent, just return 0 */
    _error->PushToStack();
    _error->PushToStack();
 
 
-   FileFd f = FileFd (IndexFile(Language), FileFd::ReadOnlyGzip);
+   FileFd f = FileFd (IndexFile(Language), FileFd::ReadOnly, FileFd::Extension);
    if (!f.Failed())
    if (!f.Failed())
       size = f.Size();
       size = f.Size();
 
 
@@ -509,7 +510,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
    string TranslationFile = IndexFile(Language);
    string TranslationFile = IndexFile(Language);
    if (FileExists(TranslationFile))
    if (FileExists(TranslationFile))
    {
    {
-     FileFd Trans(TranslationFile,FileFd::ReadOnlyGzip);
+     FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
      debListParser TransParser(&Trans);
      debListParser TransParser(&Trans);
      if (_error->PendingError() == true)
      if (_error->PendingError() == true)
        return false;
        return false;
@@ -590,7 +591,7 @@ unsigned long debStatusIndex::Size() const
 /* */
 /* */
 bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) 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)
    if (_error->PendingError() == true)
       return false;
       return false;
    debListParser Parser(&Pkg);
    debListParser Parser(&Pkg);

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

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

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

@@ -50,7 +50,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
    virtual bool Files(std::vector<pkgSrcRecords::File> &F);
    virtual bool Files(std::vector<pkgSrcRecords::File> &F);
 
 
    debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) 
    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) {}
         Buffer(NULL) {}
    virtual ~debSrcRecordParser();
    virtual ~debSrcRecordParser();
 };
 };

+ 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());
       return _error->Error(_("Package file %s is out of sync."),I.FileName());
 
 
    FileFd PkgF;
    FileFd PkgF;
-   if (PkgF.Open(I.FileName(), FileFd::ReadOnlyGzip) == false)
+   if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false)
       return false;
       return false;
 
 
    // Read the record
    // Read the record

+ 1 - 1
methods/gzip.cc

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

+ 1 - 1
methods/rred.cc

@@ -489,7 +489,7 @@ bool RredMethod::Fetch(FetchItem *Itm)						/*{{{*/
    // Open the source and destination files (the d'tor of FileFd will do 
    // Open the source and destination files (the d'tor of FileFd will do 
    // the cleanup/closing of the fds)
    // the cleanup/closing of the fds)
    FileFd From(Path,FileFd::ReadOnly);
    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);   
    FileFd To(Itm->DestFile,FileFd::WriteAtomic);   
    To.EraseOnFailure();
    To.EraseOnFailure();
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)