diff options
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 129 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.h | 14 | ||||
-rw-r--r-- | apt-pkg/deb/debindexfile.cc | 13 | ||||
-rw-r--r-- | apt-pkg/deb/debrecords.cc | 2 | ||||
-rw-r--r-- | apt-pkg/deb/debsrcrecords.h | 2 | ||||
-rw-r--r-- | cmdline/apt-cache.cc | 2 | ||||
-rw-r--r-- | methods/gzip.cc | 2 | ||||
-rw-r--r-- | methods/rred.cc | 2 |
8 files changed, 135 insertions, 31 deletions
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index d5e7192e3..1cb3fab1e 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/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> @@ -725,6 +726,11 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned Close(); 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; #define if_FLAGGED_SET(FLAG, MODE) if ((Mode & FLAG) == FLAG) fileflags |= MODE 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); #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) { Flags |= Replace; @@ -757,18 +827,27 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned 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,18 +867,34 @@ bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool A Close(); 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, Compress) == false) + { + if (AutoClose) + close (iFd); + return _error->Errno("gzdopen",_("Could not open file descriptor %d"), Fd); } this->FileName = ""; 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 /*{{{*/ // --------------------------------------------------------------------- diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index fa8f92272..59a9d97e3 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -61,7 +61,7 @@ class FileFd ReadOnlyGzip, 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) { @@ -94,7 +94,7 @@ class FileFd } 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); }; 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), 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,bool) : iFd(Fd), Flags(0), gz(NULL) {}; virtual ~FileFd(); + + private: + bool OpenInternDescriptor(OpenMode Mode, CompressMode Compress); }; bool RunScripts(const char *Cnf); diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 27c1f7f32..d9c448598 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/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 */ _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 +288,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 +305,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,6 +319,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const // Store the IMS information pkgCache::PkgFileIterator File = Gen.GetCurFile(); pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File); + // FIXME: Get this info from FileFd instead struct stat St; if (fstat(Pkg.Fd(),&St) != 0) 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 */ _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 +510,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; @@ -590,7 +591,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); diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 1afa7b74d..184c07c33 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/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) { diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index 4c8d03224..5d2a67f4f 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/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(); }; diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 65d7b0ccd..1cd5080cc 100644 --- a/cmdline/apt-cache.cc +++ b/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 diff --git a/methods/gzip.cc b/methods/gzip.cc index a51497948..6ab6548ef 100644 --- a/methods/gzip.cc +++ b/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")); diff --git a/methods/rred.cc b/methods/rred.cc index ef00fcaa3..56ad8220b 100644 --- a/methods/rred.cc +++ b/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 // 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) |