From 257e8d668c044fb0e9ad8e4b53afd32e07404831 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 29 Nov 2011 12:14:31 +0100 Subject: split up the OpenMode into OpenMode and CompressionMode and provide ReadOnly, WriteOnly and ReadWrite as flags alongside the additional flags as decompression will be one-way later, but certain parts really depend on Write* openmodes being ReadWrite opens, so we will have to fail for those. --- apt-pkg/contrib/fileutl.cc | 102 +++++++++++++++++++++++---------------------- apt-pkg/contrib/fileutl.h | 30 +++++++++++-- 2 files changed, 79 insertions(+), 53 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 95058cbde..d5e7192e3 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -718,69 +718,72 @@ 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,OpenMode Mode,CompressMode Compress, unsigned long Perms) { + if (Mode == ReadOnlyGzip) + return Open(FileName, ReadOnly, Gzip, Perms); Close(); Flags = AutoClose; - switch (Mode) + + 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); + else return _error->Error("No openmode provided in FileFd::Open for %s", FileName.c_str()); + + if_FLAGGED_SET(Create, O_CREAT); + if_FLAGGED_SET(Exclusive, O_EXCL); + else if_FLAGGED_SET(Atomic, O_EXCL); + if_FLAGGED_SET(Empty, O_TRUNC); +#undef if_FLAGGED_SET + + 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()); + } + if ((Mode & Empty) == Empty) { - case ReadOnly: - iFd = open(FileName.c_str(),O_RDONLY); - break; + struct stat Buf; + if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode)) + unlink(FileName.c_str()); + } - 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: - { - 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); - break; - } + if (TemporaryFileName.empty() == false) + iFd = open(TemporaryFileName.c_str(), fileflags, Perms); + else + iFd = open(FileName.c_str(), fileflags, Perms); - case WriteEmpty: + if (iFd != -1 && Compress == Gzip) + { + gz = gzdopen (iFd, "r"); + if (gz == NULL) { - 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; + close (iFd); + iFd = -1; } - - case WriteExists: - iFd = open(FileName.c_str(),O_RDWR); - break; - - case WriteAny: - iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms); - break; - - case WriteTemp: - unlink(FileName.c_str()); - iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms); - break; - } + } - if (iFd < 0) + if (iFd == -1) return _error->Errno("open",_("Could not open file %s"),FileName.c_str()); - + this->FileName = FileName; SetCloseExec(iFd,true); return true; } - -bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose) + /*}}}*/ +// FileFd::OpenDescriptor - Open a filedescriptor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose) { Close(); Flags = (AutoClose) ? FileFd::AutoClose : 0; @@ -1031,6 +1034,7 @@ 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; diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 0d0451a46..fa8f92272 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -44,8 +44,24 @@ class FileFd 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, None, Gzip, Bzip2, Lzma, Xz }; inline bool Read(void *To,unsigned long long Size,bool AllowEof) { @@ -77,8 +93,14 @@ 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,OpenMode Mode,CompressMode Compress,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); + inline bool OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose=false) { + return OpenDescriptor(Fd, Mode, None, AutoClose); + }; bool Close(); bool Sync(); -- cgit v1.2.3 From 468720c59fcf48b20332cdb7b601b2b0d7cbbfbb Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 10 Dec 2011 19:31:36 +0100 Subject: 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 --- apt-pkg/contrib/fileutl.cc | 129 +++++++++++++++++++++++++++++++++++++++------ apt-pkg/contrib/fileutl.h | 14 +++-- 2 files changed, 123 insertions(+), 20 deletions(-) (limited to 'apt-pkg/contrib') 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 #include #include +#include #include #include @@ -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 const compressors = APT::Configuration::getCompressors(); + std::vector::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,17 +867,33 @@ 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); -- cgit v1.2.3 From 76a763e1f842543a53bc28db681d963d0fc4ae12 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 10 Dec 2011 20:03:49 +0100 Subject: * apt-pkg/contrib/fileutl.{h,cc}: - implement a ModificationTime method for FileFd --- apt-pkg/contrib/fileutl.cc | 14 ++++++++++++++ apt-pkg/contrib/fileutl.h | 1 + 2 files changed, 15 insertions(+) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 1cb3fab1e..83b68e796 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1106,6 +1106,20 @@ unsigned long long FileFd::Size() return size; } /*}}}*/ +// FileFd::ModificationTime - Return the time of last touch /*{{{*/ +// --------------------------------------------------------------------- +/* */ +time_t FileFd::ModificationTime() +{ + struct stat Buf; + if (fstat(iFd,&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 /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 59a9d97e3..8f2d7a0a0 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -78,6 +78,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. -- cgit v1.2.3 From 032bd56ff86166fd4b6a8f69bd9d5d1bc57b886e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 11 Dec 2011 19:46:59 +0100 Subject: - add a ReadLine method - drop the explicit export of gz-compression handling --- apt-pkg/contrib/fileutl.cc | 83 ++++++++++++++++++++++++++++++++++------------ apt-pkg/contrib/fileutl.h | 30 +++++++++++------ apt-pkg/contrib/mmap.cc | 13 +++++++- 3 files changed, 93 insertions(+), 33 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 83b68e796..58cd6dceb 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -44,6 +44,8 @@ #include #include +#include + #ifdef WORDS_BIGENDIAN #include #endif @@ -53,6 +55,12 @@ using namespace std; +class FileFdPrivate { + public: + gzFile gz; + FileFdPrivate() : gz(NULL) {}; +}; + // RunScripts - Run a set of scripts from a configuration subtree /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -719,11 +727,12 @@ 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,CompressMode Compress, unsigned long Perms) +bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned long const Perms) { if (Mode == ReadOnlyGzip) return Open(FileName, ReadOnly, Gzip, Perms); Close(); + d = new FileFdPrivate; Flags = AutoClose; if (Compress == Auto && (Mode & WriteOnly) == WriteOnly) @@ -865,6 +874,7 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose) { Close(); + d = new FileFdPrivate; Flags = (AutoClose) ? FileFd::AutoClose : 0; iFd = Fd; if (OpenInternDescriptor(Mode, Compress) == false) @@ -883,13 +893,14 @@ bool FileFd::OpenInternDescriptor(OpenMode Mode, CompressMode Compress) else if (Compress == Gzip) { if ((Mode & ReadWrite) == ReadWrite) - gz = gzdopen(iFd, "r+"); + d->gz = gzdopen(iFd, "r+"); else if ((Mode & WriteOnly) == WriteOnly) - gz = gzdopen(iFd, "w"); + d->gz = gzdopen(iFd, "w"); else - gz = gzdopen (iFd, "r"); - if (gz == NULL) + d->gz = gzdopen (iFd, "r"); + if (d->gz == NULL) return false; + Flags |= Compressed; } else return false; @@ -918,8 +929,8 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) do { - if (gz != NULL) - Res = gzread(gz,To,Size); + if (d->gz != NULL) + Res = gzread(d->gz,To,Size); else Res = read(iFd,To,Size); if (Res < 0 && errno == EINTR) @@ -951,6 +962,28 @@ 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) +{ + if (d->gz != NULL) + return gzgets(d->gz, To, Size); + + 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 /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -960,8 +993,8 @@ bool FileFd::Write(const void *From,unsigned long long Size) errno = 0; do { - if (gz != NULL) - Res = gzwrite(gz,From,Size); + if (d->gz != NULL) + Res = gzwrite(d->gz,From,Size); else Res = write(iFd,From,Size); if (Res < 0 && errno == EINTR) @@ -990,8 +1023,8 @@ bool FileFd::Write(const void *From,unsigned long long Size) bool FileFd::Seek(unsigned long long To) { int res; - if (gz) - res = gzseek(gz,To,SEEK_SET); + if (d->gz) + res = gzseek(d->gz,To,SEEK_SET); else res = lseek(iFd,To,SEEK_SET); if (res != (signed)To) @@ -1009,8 +1042,8 @@ 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 (d->gz != NULL) + res = gzseek(d->gz,Over,SEEK_CUR); else res = lseek(iFd,Over,SEEK_CUR); if (res < 0) @@ -1027,7 +1060,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()); @@ -1047,8 +1080,8 @@ bool FileFd::Truncate(unsigned long long To) unsigned long long FileFd::Tell() { off_t Res; - if (gz) - Res = gztell(gz); + if (d->gz != NULL) + Res = gztell(d->gz); else Res = lseek(iFd,0,SEEK_CUR); if (Res == (off_t)-1) @@ -1076,9 +1109,9 @@ unsigned long long FileFd::Size() unsigned long long size = FileSize(); // 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) + 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 @@ -1125,11 +1158,14 @@ time_t FileFd::ModificationTime() /* */ bool FileFd::Close() { + if (iFd == -1) + return true; + bool Res = true; if ((Flags & AutoClose) == AutoClose) { - if (gz != NULL) { - int const e = gzclose(gz); + 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()); @@ -1147,13 +1183,17 @@ bool FileFd::Close() } 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) + { + delete d; + d = NULL; + } return Res; } @@ -1170,3 +1210,4 @@ bool FileFd::Sync() return true; } /*}}}*/ +gzFile FileFd::gzFd() {return d->gz;}; diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 8f2d7a0a0..209ca91e7 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -31,17 +31,17 @@ /* 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 { @@ -71,6 +71,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); @@ -94,8 +95,8 @@ class FileFd return T; } - 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) { + bool Open(std::string FileName,OpenMode Mode,CompressMode Compress,unsigned long const Perms = 0666); + inline bool Open(std::string const &FileName,OpenMode Mode, unsigned long const Perms = 0666) { return Open(FileName, Mode, None, Perms); }; bool OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose=false); @@ -108,29 +109,36 @@ class FileFd // 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,OpenMode Mode,unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL) { Open(FileName,Mode, None, Perms); }; - FileFd(std::string FileName,OpenMode Mode, CompressMode Compress, unsigned long Perms = 0666) : - iFd(-1), Flags(0), gz(NULL) + FileFd(std::string FileName,OpenMode Mode, CompressMode Compress, unsigned long Perms = 0666) : iFd(-1), Flags(0), d(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) {}; + FileFd() : iFd(-1), Flags(AutoClose), d(NULL) {}; + FileFd(int const Fd, OpenMode 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); + }; virtual ~FileFd(); private: + FileFdPrivate* d; bool OpenInternDescriptor(OpenMode Mode, CompressMode Compress); }; diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index f76169a92..1fb84b0af 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -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) -- cgit v1.2.3 From 699b209e5122f8fcd85fc4666c9b7020286ab0d0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 13 Dec 2011 00:17:30 +0100 Subject: Allow the FileFd to use an external Compressor to uncompress a given file internally so that it is exported and can be used like a "normal" uncompressed file with FileFd This allows us to hide th zlib usage in the implementation and use gzip instead if we don't have zlib builtin (the same for other compressors). The code includes quiet a few FIXME's so while all tests are working it shouldn't be used just yet outside of libapt as it might break. --- apt-pkg/contrib/fileutl.cc | 302 +++++++++++++++++++++++++++++++++++++++++++-- apt-pkg/contrib/fileutl.h | 10 ++ apt-pkg/contrib/mmap.cc | 9 +- 3 files changed, 309 insertions(+), 12 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 58cd6dceb..727d3ddb5 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -44,7 +44,13 @@ #include #include +// 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 +#ifdef APT_USE_ZLIB #include +#endif #ifdef WORDS_BIGENDIAN #include @@ -57,8 +63,16 @@ using namespace std; class FileFdPrivate { public: +#ifdef APT_USE_ZLIB gzFile gz; - FileFdPrivate() : gz(NULL) {}; +#else + void* gz; +#endif + pid_t compressor_pid; + bool pipe; + APT::Configuration::Compressor compressor; + FileFd::OpenMode openmode; + FileFdPrivate() : gz(NULL), compressor_pid(-1), pipe(false) {}; }; // RunScripts - Run a set of scripts from a configuration subtree /*{{{*/ @@ -724,6 +738,175 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap) } /*}}}*/ +// ExecCompressor - Open a de/compressor pipe /*{{{*/ +// --------------------------------------------------------------------- +/* 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 ExecCompressor(APT::Configuration::Compressor const &Prog, + pid_t *Pid, int const FileFd, int &OutFd, bool const Comp) +{ + if (Pid != NULL) + *Pid = -1; + + // No compression + if (Prog.Binary.empty() == true) + { + OutFd = dup(FileFd); + return true; + } + + // Handle 'decompression' of empty files + if (Comp == false) + { + struct stat Buf; + fstat(FileFd, &Buf); + if (Buf.st_size == 0 && S_ISFIFO(Buf.st_mode) == false) + { + OutFd = 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_t child = ExecFork(); + if (Pid != NULL) + *Pid = child; + if (child == 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 Args; + Args.push_back(Prog.Binary.c_str()); + std::vector const * const addArgs = + (Comp == true) ? &(Prog.CompressArgs) : &(Prog.UncompressArgs); + for (std::vector::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]); + + if (Pid == NULL) + ExecWait(child, Prog.Binary.c_str(), true); + + return true; +} +bool ExecCompressor(APT::Configuration::Compressor const &Prog, + pid_t *Pid, std::string const &FileName, int &OutFd, bool const Comp) +{ + if (Pid != NULL) + *Pid = -1; + + // No compression + if (Prog.Binary.empty() == true) + { + if (Comp == true) + OutFd = open(FileName.c_str(), O_WRONLY, 0666); + else + OutFd = open(FileName.c_str(), O_RDONLY); + return true; + } + + // Handle 'decompression' of empty files + if (Comp == false) + { + struct stat Buf; + stat(FileName.c_str(), &Buf); + if (Buf.st_size == 0) + { + OutFd = open(FileName.c_str(), O_RDONLY); + 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_t child = ExecFork(); + if (Pid != NULL) + *Pid = child; + if (child == 0) + { + if (Comp == true) + { + dup2(Pipe[0],STDIN_FILENO); + SetCloseExec(STDIN_FILENO,false); + } + else + { + dup2(Pipe[1],STDOUT_FILENO); + SetCloseExec(STDOUT_FILENO,false); + } + + std::vector Args; + Args.push_back(Prog.Binary.c_str()); + std::vector const * const addArgs = + (Comp == true) ? &(Prog.CompressArgs) : &(Prog.UncompressArgs); + for (std::vector::const_iterator a = addArgs->begin(); + a != addArgs->end(); ++a) + Args.push_back(a->c_str()); + Args.push_back("--stdout"); + 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 (Pid == NULL) + ExecWait(child, Prog.Binary.c_str(), false); + + return true; +} + /*}}}*/ + // FileFd::Open - Open a file /*{{{*/ // --------------------------------------------------------------------- /* The most commonly used open mode combinations are given with Mode */ @@ -733,6 +916,7 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned return Open(FileName, ReadOnly, Gzip, Perms); Close(); d = new FileFdPrivate; + d->openmode = Mode; Flags = AutoClose; if (Compress == Auto && (Mode & WriteOnly) == WriteOnly) @@ -805,12 +989,15 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned // if we have them, use inbuilt compressors instead of forking if (compressor != compressors.end()) { +#ifdef APT_USE_ZLIB if (compressor->Name == "gzip") { Compress = Gzip; compressor = compressors.end(); } - else if (compressor->Name == "." || Compress == None) + else +#endif + if (compressor->Name == ".") { Compress = None; compressor = compressors.end(); @@ -839,9 +1026,12 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned 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()); + return _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor->Name.c_str(), FileName.c_str()); - _error->Error("Forking external compressor %s is not implemented for %s", compressor->Name.c_str(), FileName.c_str()); + if (ExecCompressor(*compressor, NULL /*d->compressor_pid*/, FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) + return _error->Error("Forking external compressor %s is not implemented for %s", compressor->Name.c_str(), FileName.c_str()); + d->pipe = true; + d->compressor = *compressor; } else { @@ -875,6 +1065,7 @@ bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool A { Close(); d = new FileFdPrivate; + d->openmode = Mode; Flags = (AutoClose) ? FileFd::AutoClose : 0; iFd = Fd; if (OpenInternDescriptor(Mode, Compress) == false) @@ -890,6 +1081,7 @@ bool FileFd::OpenInternDescriptor(OpenMode Mode, CompressMode Compress) { if (Compress == None) return true; +#ifdef APT_USE_ZLIB else if (Compress == Gzip) { if ((Mode & ReadWrite) == ReadWrite) @@ -902,8 +1094,29 @@ bool FileFd::OpenInternDescriptor(OpenMode Mode, CompressMode Compress) return false; Flags |= Compressed; } +#endif else - return false; + { + 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()); + } + std::vector const compressors = APT::Configuration::getCompressors(); + std::vector::const_iterator compressor = compressors.begin(); + for (; compressor != compressors.end(); ++compressor) + if (compressor->Name == name) + break; + if (compressor == compressors.end() || + ExecCompressor(*compressor, NULL /*&(d->compressor_pid)*/, + FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) + return _error->Error("Forking external compressor %s is not implemented for %s", name.c_str(), FileName.c_str()); + d->pipe = true; + } return true; } /*}}}*/ @@ -926,12 +1139,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 { +#ifdef 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; @@ -968,8 +1183,11 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) files because of the naive implementation! */ char* FileFd::ReadLine(char *To, unsigned long long const Size) { + *To = '\0'; +#ifdef 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) @@ -993,9 +1211,11 @@ bool FileFd::Write(const void *From,unsigned long long Size) errno = 0; do { +#ifdef 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; @@ -1022,10 +1242,21 @@ bool FileFd::Write(const void *From,unsigned long long Size) /* */ bool FileFd::Seek(unsigned long long To) { + if (d->pipe == true) + { + // FIXME: What about OpenDescriptor() stuff here? + close(iFd); + bool result = ExecCompressor(d->compressor, NULL, FileName, iFd, (d->openmode & ReadOnly) != ReadOnly); + if (result == true && To != 0) + result &= Skip(To); + return result; + } int res; +#ifdef USE_ZLIB if (d->gz) res = gzseek(d->gz,To,SEEK_SET); else +#endif res = lseek(iFd,To,SEEK_SET); if (res != (signed)To) { @@ -1042,9 +1273,11 @@ bool FileFd::Seek(unsigned long long To) bool FileFd::Skip(unsigned long long Over) { int res; +#ifdef USE_ZLIB if (d->gz != NULL) res = gzseek(d->gz,Over,SEEK_CUR); else +#endif res = lseek(iFd,Over,SEEK_CUR); if (res < 0) { @@ -1080,9 +1313,11 @@ bool FileFd::Truncate(unsigned long long To) unsigned long long FileFd::Tell() { off_t Res; +#ifdef 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"); @@ -1095,9 +1330,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; } /*}}}*/ @@ -1108,10 +1353,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); + } +#ifdef USE_ZLIB // only check gzsize if we are actually a gzip file, just checking for // "gz" is not sufficient as uncompressed files could be opened with // gzopen in "direct" mode as well - if (d->gz && !gzdirect(d->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 @@ -1135,6 +1395,7 @@ unsigned long long FileFd::Size() return _error->Errno("lseek","Unable to seek in gzipped file"); return size; } +#endif return size; } @@ -1145,11 +1406,25 @@ unsigned long long FileFd::Size() time_t FileFd::ModificationTime() { struct stat Buf; - if (fstat(iFd,&Buf) != 0) + 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; } /*}}}*/ @@ -1164,12 +1439,14 @@ bool FileFd::Close() bool Res = true; if ((Flags & AutoClose) == AutoClose) { +#ifdef 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()); } @@ -1191,6 +1468,8 @@ bool FileFd::Close() if (d != NULL) { +// if (d->compressor_pid != -1) +// ExecWait(d->compressor_pid, "FileFdCompressor", true); delete d; d = NULL; } @@ -1210,4 +1489,5 @@ bool FileFd::Sync() return true; } /*}}}*/ -gzFile FileFd::gzFd() {return d->gz;}; + +gzFile FileFd::gzFd() { return (gzFile) d->gz; } diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 209ca91e7..f96dc72dc 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -22,6 +22,7 @@ #define PKGLIB_FILEUTL_H #include +#include #include #include @@ -110,6 +111,7 @@ class FileFd inline int Fd() {return iFd;}; inline void Fd(int fd) {iFd = fd;}; __deprecated gzFile gzFd(); + inline bool IsOpen() {return iFd >= 0;}; inline bool Failed() {return (Flags & Fail) == Fail;}; inline void EraseOnFailure() {Flags |= DelOnFail;}; @@ -170,6 +172,14 @@ bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0); pid_t ExecFork(); bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); +bool ExecCompressor(APT::Configuration::Compressor const &Prog, + pid_t *Pid, int const FileFd, int &OutFd, bool const Comp = true); +inline bool ExecDecompressor(APT::Configuration::Compressor const &Prog, + pid_t *Pid, int const FileFd, int &OutFd) +{ + return ExecCompressor(Prog, Pid, FileFd, OutFd, true); +} + // File string manipulators std::string flNotDir(std::string File); std::string flNotFile(std::string File); diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index 1fb84b0af..a67ab3698 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/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; @@ -97,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()); -- cgit v1.2.3 From a4f6bdc8bd91c7282ae9ac60c44844c6f0058a65 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 13 Dec 2011 00:54:37 +0100 Subject: revert 2184.1.2: do not pollute namespace in headers The breakage is just to big for now, so guard the change with #ifndef APT_8_CLEANER_HEADERS and be nice to library users --- apt-pkg/contrib/cdromutl.h | 4 ++++ apt-pkg/contrib/configuration.h | 4 ++++ apt-pkg/contrib/fileutl.h | 4 ++++ apt-pkg/contrib/hashes.h | 6 ++++++ apt-pkg/contrib/hashsum_template.h | 5 +++++ apt-pkg/contrib/md5.h | 5 +++++ apt-pkg/contrib/mmap.h | 4 ++++ apt-pkg/contrib/progress.h | 4 ++++ apt-pkg/contrib/sha1.h | 5 +++++ apt-pkg/contrib/strutl.h | 6 ++++++ 10 files changed, 47 insertions(+) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/cdromutl.h b/apt-pkg/contrib/cdromutl.h index 2c6afac0f..e94045b5c 100644 --- a/apt-pkg/contrib/cdromutl.h +++ b/apt-pkg/contrib/cdromutl.h @@ -12,6 +12,10 @@ #include +#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); diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index f6f2a3c1d..4c2e75041 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -34,6 +34,10 @@ #include #include +#ifndef APT_8_CLEANER_HEADERS +using std::string; +#endif + class Configuration { public: diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index f96dc72dc..8a986b82b 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -29,6 +29,10 @@ #include +#ifndef APT_8_CLEANER_HEADERS +using std::string; +#endif + /* Define this for python-apt */ #define APT_HAS_GZIP 1 diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 81851dede..b206eccb8 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -22,6 +22,12 @@ #include #include + +#ifndef APT_8_CLEANER_HEADERS +using std::min; +using std::vector; +#endif + // helper class that contains hash function name // and hash class HashString diff --git a/apt-pkg/contrib/hashsum_template.h b/apt-pkg/contrib/hashsum_template.h index 27d192b82..6301ac9d0 100644 --- a/apt-pkg/contrib/hashsum_template.h +++ b/apt-pkg/contrib/hashsum_template.h @@ -15,6 +15,11 @@ #include #include +#ifndef APT_8_CLEANER_HEADERS +using std::string; +using std::min; +#endif + template class HashSumValue { diff --git a/apt-pkg/contrib/md5.h b/apt-pkg/contrib/md5.h index a207da4e4..25631b166 100644 --- a/apt-pkg/contrib/md5.h +++ b/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 diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h index 2ed4a95f8..602de94f8 100644 --- a/apt-pkg/contrib/mmap.h +++ b/apt-pkg/contrib/mmap.h @@ -28,6 +28,10 @@ #include +#ifndef APT_8_CLEANER_HEADERS +using std::string; +#endif + class FileFd; /* This should be a 32 bit type, larger tyes use too much ram and smaller diff --git a/apt-pkg/contrib/progress.h b/apt-pkg/contrib/progress.h index 7635719bc..3a6943aee 100644 --- a/apt-pkg/contrib/progress.h +++ b/apt-pkg/contrib/progress.h @@ -25,6 +25,10 @@ #include #include +#ifndef APT_8_CLEANER_HEADERS +using std::string; +#endif + class Configuration; class OpProgress { diff --git a/apt-pkg/contrib/sha1.h b/apt-pkg/contrib/sha1.h index b4b139a22..a8d55eb13 100644 --- a/apt-pkg/contrib/sha1.h +++ b/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 diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 93f4bef4f..337139d5d 100644 --- a/apt-pkg/contrib/strutl.h +++ b/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); -- cgit v1.2.3 From b9dadc24b9477b466bc8058c765d76c65ecc7125 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 13 Dec 2011 01:22:38 +0100 Subject: revert 2184.1.3: forward declaration instead of headers The breakage is just to big for now, so guard the change with #ifndef APT_8_CLEANER_HEADERS and be nice to library users --- apt-pkg/contrib/cmndline.h | 4 ++++ apt-pkg/contrib/mmap.h | 1 + apt-pkg/contrib/netrc.h | 4 ++++ 3 files changed, 9 insertions(+) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h index b201d9855..9f505fd41 100644 --- a/apt-pkg/contrib/cmndline.h +++ b/apt-pkg/contrib/cmndline.h @@ -44,6 +44,10 @@ #ifndef PKGLIB_CMNDLINE_H #define PKGLIB_CMNDLINE_H +#ifndef APT_8_CLEANER_HEADERS +#include +#endif + class Configuration; class CommandLine diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h index 602de94f8..6bd4a2d86 100644 --- a/apt-pkg/contrib/mmap.h +++ b/apt-pkg/contrib/mmap.h @@ -29,6 +29,7 @@ #include #ifndef APT_8_CLEANER_HEADERS +#include using std::string; #endif diff --git a/apt-pkg/contrib/netrc.h b/apt-pkg/contrib/netrc.h index 7b94eba88..5931d4a42 100644 --- a/apt-pkg/contrib/netrc.h +++ b/apt-pkg/contrib/netrc.h @@ -16,6 +16,10 @@ #include +#ifndef APT_8_CLEANER_HEADERS +#include +#endif + #define DOT_CHAR "." #define DIR_CHAR "/" -- cgit v1.2.3 From 73437844e2f22a17203dac0ba72317769ec54398 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 13 Dec 2011 01:43:28 +0100 Subject: =?UTF-8?q?note=20to=20myself:=20In=20case=20you=20rename=20someth?= =?UTF-8?q?ing,=20make=20sure=20that=20you=20have=20renamed=20it=20everywh?= =?UTF-8?q?ere=20as=20otherwise=20stuff=20"magically"=20starts=20to=20fail?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes commit 2209 as the mixture of #define names generates a lovely compilable but non-functional mixture of gzip usageā€¦ --- apt-pkg/contrib/fileutl.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 727d3ddb5..25ac5275c 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1252,7 +1252,7 @@ bool FileFd::Seek(unsigned long long To) return result; } int res; -#ifdef USE_ZLIB +#ifdef APT_USE_ZLIB if (d->gz) res = gzseek(d->gz,To,SEEK_SET); else @@ -1273,7 +1273,7 @@ bool FileFd::Seek(unsigned long long To) bool FileFd::Skip(unsigned long long Over) { int res; -#ifdef USE_ZLIB +#ifdef APT_USE_ZLIB if (d->gz != NULL) res = gzseek(d->gz,Over,SEEK_CUR); else @@ -1313,7 +1313,7 @@ bool FileFd::Truncate(unsigned long long To) unsigned long long FileFd::Tell() { off_t Res; -#ifdef USE_ZLIB +#ifdef APT_USE_ZLIB if (d->gz != NULL) Res = gztell(d->gz); else @@ -1367,7 +1367,7 @@ unsigned long long FileFd::Size() } while(read != 0); Seek(0); } -#ifdef USE_ZLIB +#ifdef APT_USE_ZLIB // only check gzsize if we are actually a gzip file, just checking for // "gz" is not sufficient as uncompressed files could be opened with // gzopen in "direct" mode as well @@ -1439,7 +1439,7 @@ bool FileFd::Close() bool Res = true; if ((Flags & AutoClose) == AutoClose) { -#ifdef USE_ZLIB +#ifdef 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 -- cgit v1.2.3 From aee1aac6f75906ec73dacffc55e7026002201f98 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 13 Dec 2011 23:48:14 +0100 Subject: allow Open() and OpenDescriptor() to be called with a Compressor --- apt-pkg/contrib/fileutl.cc | 187 +++++++++++++++++++++++---------------------- apt-pkg/contrib/fileutl.h | 4 +- 2 files changed, 98 insertions(+), 93 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 25ac5275c..c2b684089 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -48,7 +48,7 @@ // so while the current implementation satisfies the testcases it is not a real option // to disable it for now #define APT_USE_ZLIB 1 -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB #include #endif @@ -63,7 +63,7 @@ using namespace std; class FileFdPrivate { public: -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB gzFile gz; #else void* gz; @@ -914,95 +914,77 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned { if (Mode == ReadOnlyGzip) return Open(FileName, ReadOnly, Gzip, Perms); - Close(); - d = new FileFdPrivate; - d->openmode = Mode; - 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); - else if_FLAGGED_SET(ReadOnly, O_RDONLY); - else if_FLAGGED_SET(WriteOnly, O_WRONLY); - else return _error->Error("No openmode provided in FileFd::Open for %s", FileName.c_str()); - - if_FLAGGED_SET(Create, O_CREAT); - if_FLAGGED_SET(Exclusive, O_EXCL); - else if_FLAGGED_SET(Atomic, O_EXCL); - 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 const compressors = APT::Configuration::getCompressors(); std::vector::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) - { + if (ext == FileName) + ext.clear(); + else ext = "." + ext; - for (; compressor != compressors.end(); ++compressor) - if (ext == compressor->Extension) + 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 if (Compress != None) + 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; - default: return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str()); + 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() && name != "gzip") + if (compressor == compressors.end()) 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()) - { -#ifdef APT_USE_ZLIB - if (compressor->Name == "gzip") - { - Compress = Gzip; - compressor = compressors.end(); - } - else -#endif - if (compressor->Name == ".") - { - Compress = None; - compressor = compressors.end(); - } - } + 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,OpenMode 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()); if ((Mode & Atomic) == Atomic) { @@ -1023,18 +1005,35 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned unlink(FileName.c_str()); } - if (compressor != compressors.end()) + // if we have them, use inbuilt compressors instead of forking + if (compressor.Name != "." +#if APT_USE_ZLIB + && compressor.Name != "gzip" +#endif + ) { if ((Mode & ReadWrite) == ReadWrite) - return _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor->Name.c_str(), FileName.c_str()); + return _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor.Name.c_str(), FileName.c_str()); - if (ExecCompressor(*compressor, NULL /*d->compressor_pid*/, FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) - return _error->Error("Forking external compressor %s is not implemented for %s", compressor->Name.c_str(), FileName.c_str()); + if (ExecCompressor(compressor, NULL /*d->compressor_pid*/, FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) + return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), FileName.c_str()); d->pipe = true; - d->compressor = *compressor; + d->compressor = compressor; } else { + 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(Exclusive, O_EXCL); + else if_FLAGGED_SET(Atomic, O_EXCL); + if_FLAGGED_SET(Empty, O_TRUNC); + #undef if_FLAGGED_SET + if (TemporaryFileName.empty() == false) iFd = open(TemporaryFileName.c_str(), fileflags, Perms); else @@ -1042,7 +1041,7 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned if (iFd != -1) { - if (OpenInternDescriptor(Mode, Compress) == false) + if (OpenInternDescriptor(Mode, compressor) == false) { close (iFd); iFd = -1; @@ -1062,13 +1061,37 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned // --------------------------------------------------------------------- /* */ bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose) +{ + std::vector const compressors = APT::Configuration::getCompressors(); + std::vector::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()); + + return OpenDescriptor(Fd, Mode, *compressor, AutoClose); +} +bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, APT::Configuration::Compressor const &compressor, bool AutoClose) { Close(); d = new FileFdPrivate; d->openmode = Mode; Flags = (AutoClose) ? FileFd::AutoClose : 0; iFd = Fd; - if (OpenInternDescriptor(Mode, Compress) == false) + if (OpenInternDescriptor(Mode, compressor) == false) { if (AutoClose) close (iFd); @@ -1077,12 +1100,12 @@ bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool A this->FileName = ""; return true; } -bool FileFd::OpenInternDescriptor(OpenMode Mode, CompressMode Compress) +bool FileFd::OpenInternDescriptor(OpenMode Mode, APT::Configuration::Compressor const &compressor) { - if (Compress == None) + if (compressor.Name == ".") return true; -#ifdef APT_USE_ZLIB - else if (Compress == Gzip) +#if APT_USE_ZLIB + else if (compressor.Name == "gzip") { if ((Mode & ReadWrite) == ReadWrite) d->gz = gzdopen(iFd, "r+"); @@ -1096,27 +1119,7 @@ bool FileFd::OpenInternDescriptor(OpenMode Mode, CompressMode Compress) } #endif else - { - 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()); - } - std::vector const compressors = APT::Configuration::getCompressors(); - std::vector::const_iterator compressor = compressors.begin(); - for (; compressor != compressors.end(); ++compressor) - if (compressor->Name == name) - break; - if (compressor == compressors.end() || - ExecCompressor(*compressor, NULL /*&(d->compressor_pid)*/, - FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) - return _error->Error("Forking external compressor %s is not implemented for %s", name.c_str(), FileName.c_str()); - d->pipe = true; - } + return _error->Error("Can't find a match for specified compressor %s for file %s", compressor.Name.c_str(), FileName.c_str()); return true; } /*}}}*/ @@ -1142,7 +1145,7 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) *((char *)To) = '\0'; do { -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB if (d->gz != NULL) Res = gzread(d->gz,To,Size); else @@ -1184,7 +1187,7 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) char* FileFd::ReadLine(char *To, unsigned long long const Size) { *To = '\0'; -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB if (d->gz != NULL) return gzgets(d->gz, To, Size); #endif @@ -1211,7 +1214,7 @@ bool FileFd::Write(const void *From,unsigned long long Size) errno = 0; do { -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB if (d->gz != NULL) Res = gzwrite(d->gz,From,Size); else @@ -1252,7 +1255,7 @@ bool FileFd::Seek(unsigned long long To) return result; } int res; -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB if (d->gz) res = gzseek(d->gz,To,SEEK_SET); else @@ -1273,7 +1276,7 @@ bool FileFd::Seek(unsigned long long To) bool FileFd::Skip(unsigned long long Over) { int res; -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB if (d->gz != NULL) res = gzseek(d->gz,Over,SEEK_CUR); else @@ -1313,7 +1316,7 @@ bool FileFd::Truncate(unsigned long long To) unsigned long long FileFd::Tell() { off_t Res; -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB if (d->gz != NULL) Res = gztell(d->gz); else @@ -1367,7 +1370,7 @@ unsigned long long FileFd::Size() } while(read != 0); Seek(0); } -#ifdef APT_USE_ZLIB +#if APT_USE_ZLIB // only check gzsize if we are actually a gzip file, just checking for // "gz" is not sufficient as uncompressed files could be opened with // gzopen in "direct" mode as well @@ -1439,7 +1442,7 @@ bool FileFd::Close() bool Res = true; if ((Flags & AutoClose) == AutoClose) { -#ifdef APT_USE_ZLIB +#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 diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 8a986b82b..51277290e 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -101,10 +101,12 @@ class FileFd } bool Open(std::string FileName,OpenMode Mode,CompressMode Compress,unsigned long const Perms = 0666); + bool Open(std::string FileName,OpenMode Mode,APT::Configuration::Compressor const &compressor,unsigned long const Perms = 0666); inline bool Open(std::string const &FileName,OpenMode Mode, unsigned long const Perms = 0666) { return Open(FileName, Mode, None, Perms); }; bool OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose=false); + bool OpenDescriptor(int Fd, OpenMode Mode, APT::Configuration::Compressor const &compressor, bool AutoClose=false); inline bool OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose=false) { return OpenDescriptor(Fd, Mode, None, AutoClose); }; @@ -145,7 +147,7 @@ class FileFd private: FileFdPrivate* d; - bool OpenInternDescriptor(OpenMode Mode, CompressMode Compress); + bool OpenInternDescriptor(OpenMode Mode, APT::Configuration::Compressor const &compressor); }; bool RunScripts(const char *Cnf); -- cgit v1.2.3 From 52b47296f61ec3ca1075bbfb44982f5caa541e7c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 14 Dec 2011 22:11:43 +0100 Subject: use FileFd instead of forking the compression childs by hand --- apt-pkg/contrib/fileutl.cc | 90 +++++++++++++++++++++++++++++++++++----------- apt-pkg/contrib/fileutl.h | 20 +++++------ 2 files changed, 80 insertions(+), 30 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index c2b684089..60396fc3d 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -50,6 +50,8 @@ #define APT_USE_ZLIB 1 #if APT_USE_ZLIB #include +#else +#warning "Usage of zlib is DISABLED!" #endif #ifdef WORDS_BIGENDIAN @@ -71,7 +73,7 @@ class FileFdPrivate { pid_t compressor_pid; bool pipe; APT::Configuration::Compressor compressor; - FileFd::OpenMode openmode; + unsigned int openmode; FileFdPrivate() : gz(NULL), compressor_pid(-1), pipe(false) {}; }; @@ -858,8 +860,13 @@ bool ExecCompressor(APT::Configuration::Compressor const &Prog, for (int J = 0; J != 2; J++) SetCloseExec(Pipe[J],true); + int FileFd = -1; if (Comp == true) + { OutFd = Pipe[1]; + // FIXME: we should handle openmode and permission from Open() here + FileFd = open(FileName.c_str(), O_WRONLY, 0666); + } else OutFd = Pipe[0]; @@ -872,13 +879,14 @@ bool ExecCompressor(APT::Configuration::Compressor const &Prog, if (Comp == true) { dup2(Pipe[0],STDIN_FILENO); + dup2(FileFd,STDOUT_FILENO); SetCloseExec(STDIN_FILENO,false); } else { dup2(Pipe[1],STDOUT_FILENO); - SetCloseExec(STDOUT_FILENO,false); } + SetCloseExec(STDOUT_FILENO,false); std::vector Args; Args.push_back(Prog.Binary.c_str()); @@ -887,8 +895,11 @@ bool ExecCompressor(APT::Configuration::Compressor const &Prog, for (std::vector::const_iterator a = addArgs->begin(); a != addArgs->end(); ++a) Args.push_back(a->c_str()); - Args.push_back("--stdout"); - Args.push_back(FileName.c_str()); + if (Comp == false) + { + Args.push_back("--stdout"); + Args.push_back(FileName.c_str()); + } Args.push_back(NULL); execvp(Args[0],(char **)&Args[0]); @@ -896,7 +907,10 @@ bool ExecCompressor(APT::Configuration::Compressor const &Prog, _exit(100); } if (Comp == true) + { close(Pipe[0]); + close(FileFd); + } else close(Pipe[1]); @@ -910,7 +924,7 @@ bool ExecCompressor(APT::Configuration::Compressor const &Prog, // FileFd::Open - Open a file /*{{{*/ // --------------------------------------------------------------------- /* The most commonly used open mode combinations are given with Mode */ -bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned long const Perms) +bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, unsigned long const Perms) { if (Mode == ReadOnlyGzip) return Open(FileName, ReadOnly, Gzip, Perms); @@ -934,11 +948,20 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned } else if (Compress == Extension) { - std::string ext = flExtension(FileName); - if (ext == FileName) - ext.clear(); - else - ext = "." + ext; + std::string::size_type const found = FileName.find_last_of('.'); + std::string ext; + if (found != std::string::npos) + { + 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(); + } + } for (; compressor != compressors.end(); ++compressor) if (ext == compressor->Extension) break; @@ -960,8 +983,8 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned 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()); + // 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) @@ -974,7 +997,7 @@ bool FileFd::Open(string FileName,OpenMode Mode,CompressMode Compress, unsigned 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,OpenMode Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms) +bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms) { Close(); d = new FileFdPrivate; @@ -1015,8 +1038,35 @@ bool FileFd::Open(string FileName,OpenMode Mode,APT::Configuration::Compressor c if ((Mode & ReadWrite) == ReadWrite) return _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor.Name.c_str(), FileName.c_str()); - if (ExecCompressor(compressor, NULL /*d->compressor_pid*/, FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) - return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), FileName.c_str()); + if ((Mode & (WriteOnly | Create)) == (WriteOnly | Create)) + { + if (TemporaryFileName.empty() == false) + { + if (RealFileExists(TemporaryFileName) == false) + { + iFd = open(TemporaryFileName.c_str(), O_WRONLY | O_CREAT, Perms); + close(iFd); + iFd = -1; + } + } + else if (RealFileExists(FileName) == false) + { + iFd = open(FileName.c_str(), O_WRONLY | O_CREAT, Perms); + close(iFd); + iFd = -1; + } + } + + if (TemporaryFileName.empty() == false) + { + if (ExecCompressor(compressor, &(d->compressor_pid), TemporaryFileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) + return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), TemporaryFileName.c_str()); + } + else + { + if (ExecCompressor(compressor, &(d->compressor_pid), FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) + return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), FileName.c_str()); + } d->pipe = true; d->compressor = compressor; } @@ -1060,7 +1110,7 @@ bool FileFd::Open(string FileName,OpenMode Mode,APT::Configuration::Compressor c // FileFd::OpenDescriptor - Open a filedescriptor /*{{{*/ // --------------------------------------------------------------------- /* */ -bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool AutoClose) +bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose) { std::vector const compressors = APT::Configuration::getCompressors(); std::vector::const_iterator compressor = compressors.begin(); @@ -1084,7 +1134,7 @@ bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, CompressMode Compress, bool A return OpenDescriptor(Fd, Mode, *compressor, AutoClose); } -bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, APT::Configuration::Compressor const &compressor, bool AutoClose) +bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose) { Close(); d = new FileFdPrivate; @@ -1100,7 +1150,7 @@ bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, APT::Configuration::Compresso this->FileName = ""; return true; } -bool FileFd::OpenInternDescriptor(OpenMode Mode, APT::Configuration::Compressor const &compressor) +bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor) { if (compressor.Name == ".") return true; @@ -1471,8 +1521,8 @@ bool FileFd::Close() if (d != NULL) { -// if (d->compressor_pid != -1) -// ExecWait(d->compressor_pid, "FileFdCompressor", true); + if (d->compressor_pid != -1) + ExecWait(d->compressor_pid, "FileFdCompressor", true); delete d; d = NULL; } diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 51277290e..f14f97b69 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -100,14 +100,14 @@ class FileFd return T; } - bool Open(std::string FileName,OpenMode Mode,CompressMode Compress,unsigned long const Perms = 0666); - bool Open(std::string FileName,OpenMode Mode,APT::Configuration::Compressor const &compressor,unsigned long const Perms = 0666); - inline bool Open(std::string const &FileName,OpenMode Mode, unsigned long const Perms = 0666) { + 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, OpenMode Mode, CompressMode Compress, bool AutoClose=false); - bool OpenDescriptor(int Fd, OpenMode Mode, APT::Configuration::Compressor const &compressor, bool AutoClose=false); - inline bool OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose=false) { + 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(); @@ -126,16 +126,16 @@ class FileFd 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), d(NULL) + FileFd(std::string FileName,unsigned int const Mode,unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL) { Open(FileName,Mode, None, Perms); }; - FileFd(std::string FileName,OpenMode Mode, CompressMode Compress, unsigned long Perms = 0666) : iFd(-1), Flags(0), d(NULL) + 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, OpenMode Mode = ReadWrite, CompressMode Compress = None) : iFd(-1), Flags(0), d(NULL) + FileFd(int const Fd, unsigned int const Mode = ReadWrite, CompressMode Compress = None) : iFd(-1), Flags(0), d(NULL) { OpenDescriptor(Fd, Mode, Compress); }; @@ -147,7 +147,7 @@ class FileFd private: FileFdPrivate* d; - bool OpenInternDescriptor(OpenMode Mode, APT::Configuration::Compressor const &compressor); + bool OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor); }; bool RunScripts(const char *Cnf); -- cgit v1.2.3 From 561f860a385087ea4d863f01cb5e0e050a5e360f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 15 Dec 2011 23:38:38 +0100 Subject: refactor compressor calling so that we don't (need to) export ExecCompressor anymore and therefore are also able to drop quiet a bit of duplicated code --- apt-pkg/contrib/fileutl.cc | 376 +++++++++++++++------------------------------ apt-pkg/contrib/fileutl.h | 8 - 2 files changed, 120 insertions(+), 264 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 60396fc3d..44486905f 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -51,7 +51,7 @@ #if APT_USE_ZLIB #include #else -#warning "Usage of zlib is DISABLED!" +#pragma message "Usage of zlib is DISABLED!" #endif #ifdef WORDS_BIGENDIAN @@ -70,11 +70,12 @@ class FileFdPrivate { #else void* gz; #endif + int compressed_fd; pid_t compressor_pid; bool pipe; APT::Configuration::Compressor compressor; unsigned int openmode; - FileFdPrivate() : gz(NULL), compressor_pid(-1), pipe(false) {}; + FileFdPrivate() : gz(NULL), compressed_fd(-1), compressor_pid(-1), pipe(false) {}; }; // RunScripts - Run a set of scripts from a configuration subtree /*{{{*/ @@ -740,187 +741,6 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap) } /*}}}*/ -// ExecCompressor - Open a de/compressor pipe /*{{{*/ -// --------------------------------------------------------------------- -/* 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 ExecCompressor(APT::Configuration::Compressor const &Prog, - pid_t *Pid, int const FileFd, int &OutFd, bool const Comp) -{ - if (Pid != NULL) - *Pid = -1; - - // No compression - if (Prog.Binary.empty() == true) - { - OutFd = dup(FileFd); - return true; - } - - // Handle 'decompression' of empty files - if (Comp == false) - { - struct stat Buf; - fstat(FileFd, &Buf); - if (Buf.st_size == 0 && S_ISFIFO(Buf.st_mode) == false) - { - OutFd = 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_t child = ExecFork(); - if (Pid != NULL) - *Pid = child; - if (child == 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 Args; - Args.push_back(Prog.Binary.c_str()); - std::vector const * const addArgs = - (Comp == true) ? &(Prog.CompressArgs) : &(Prog.UncompressArgs); - for (std::vector::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]); - - if (Pid == NULL) - ExecWait(child, Prog.Binary.c_str(), true); - - return true; -} -bool ExecCompressor(APT::Configuration::Compressor const &Prog, - pid_t *Pid, std::string const &FileName, int &OutFd, bool const Comp) -{ - if (Pid != NULL) - *Pid = -1; - - // No compression - if (Prog.Binary.empty() == true) - { - if (Comp == true) - OutFd = open(FileName.c_str(), O_WRONLY, 0666); - else - OutFd = open(FileName.c_str(), O_RDONLY); - return true; - } - - // Handle 'decompression' of empty files - if (Comp == false) - { - struct stat Buf; - stat(FileName.c_str(), &Buf); - if (Buf.st_size == 0) - { - OutFd = open(FileName.c_str(), O_RDONLY); - 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); - - int FileFd = -1; - if (Comp == true) - { - OutFd = Pipe[1]; - // FIXME: we should handle openmode and permission from Open() here - FileFd = open(FileName.c_str(), O_WRONLY, 0666); - } - else - OutFd = Pipe[0]; - - // The child.. - pid_t child = ExecFork(); - if (Pid != NULL) - *Pid = child; - if (child == 0) - { - if (Comp == true) - { - dup2(Pipe[0],STDIN_FILENO); - dup2(FileFd,STDOUT_FILENO); - SetCloseExec(STDIN_FILENO,false); - } - else - { - dup2(Pipe[1],STDOUT_FILENO); - } - SetCloseExec(STDOUT_FILENO,false); - - std::vector Args; - Args.push_back(Prog.Binary.c_str()); - std::vector const * const addArgs = - (Comp == true) ? &(Prog.CompressArgs) : &(Prog.UncompressArgs); - for (std::vector::const_iterator a = addArgs->begin(); - a != addArgs->end(); ++a) - Args.push_back(a->c_str()); - if (Comp == false) - { - Args.push_back("--stdout"); - 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]); - close(FileFd); - } - else - close(Pipe[1]); - - if (Pid == NULL) - ExecWait(child, Prog.Binary.c_str(), false); - - return true; -} - /*}}}*/ - // FileFd::Open - Open a file /*{{{*/ // --------------------------------------------------------------------- /* The most commonly used open mode combinations are given with Mode */ @@ -1028,80 +848,33 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co unlink(FileName.c_str()); } - // if we have them, use inbuilt compressors instead of forking - if (compressor.Name != "." -#if APT_USE_ZLIB - && compressor.Name != "gzip" -#endif - ) - { - if ((Mode & ReadWrite) == ReadWrite) - return _error->Error("External compressors like %s do not support readwrite mode for file %s", compressor.Name.c_str(), 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 ((Mode & (WriteOnly | Create)) == (WriteOnly | Create)) - { - if (TemporaryFileName.empty() == false) - { - if (RealFileExists(TemporaryFileName) == false) - { - iFd = open(TemporaryFileName.c_str(), O_WRONLY | O_CREAT, Perms); - close(iFd); - iFd = -1; - } - } - else if (RealFileExists(FileName) == false) - { - iFd = open(FileName.c_str(), O_WRONLY | O_CREAT, Perms); - close(iFd); - iFd = -1; - } - } + 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) - { - if (ExecCompressor(compressor, &(d->compressor_pid), TemporaryFileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) - return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), TemporaryFileName.c_str()); - } - else - { - if (ExecCompressor(compressor, &(d->compressor_pid), FileName, iFd, ((Mode & ReadOnly) != ReadOnly)) == false) - return _error->Error("Forking external compressor %s is not implemented for %s", compressor.Name.c_str(), FileName.c_str()); - } - d->pipe = true; - d->compressor = compressor; - } + if (TemporaryFileName.empty() == false) + iFd = open(TemporaryFileName.c_str(), fileflags, Perms); else - { - 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(Exclusive, O_EXCL); - else if_FLAGGED_SET(Atomic, O_EXCL); - if_FLAGGED_SET(Empty, O_TRUNC); - #undef if_FLAGGED_SET - - if (TemporaryFileName.empty() == false) - iFd = open(TemporaryFileName.c_str(), fileflags, Perms); - else - iFd = open(FileName.c_str(), fileflags, Perms); + iFd = open(FileName.c_str(), fileflags, Perms); + if (iFd == -1 || OpenInternDescriptor(Mode, compressor) == false) + { if (iFd != -1) { - if (OpenInternDescriptor(Mode, compressor) == false) - { - close (iFd); - iFd = -1; - } + close (iFd); + iFd = -1; } + return _error->Errno("open",_("Could not open file %s"), FileName.c_str()); } - if (iFd == -1) - return _error->Errno("open",_("Could not open file %s"),FileName.c_str()); - this->FileName = FileName; SetCloseExec(iFd,true); return true; @@ -1152,7 +925,8 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration: } bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor) { - if (compressor.Name == ".") + d->compressor = compressor; + if (compressor.Name == "." || compressor.Binary.empty() == true) return true; #if APT_USE_ZLIB else if (compressor.Name == "gzip") @@ -1166,10 +940,90 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C 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 Args; + Args.push_back(compressor.Binary.c_str()); + std::vector const * const addArgs = + (Comp == true) ? &(compressor.CompressArgs) : &(compressor.UncompressArgs); + for (std::vector::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 - return _error->Error("Can't find a match for specified compressor %s for file %s", compressor.Name.c_str(), FileName.c_str()); + close(Pipe[1]); + if (Comp == true || FileName.empty() == true) + close(d->compressed_fd); + return true; } /*}}}*/ @@ -1297,12 +1151,22 @@ bool FileFd::Seek(unsigned long long To) { if (d->pipe == true) { - // FIXME: What about OpenDescriptor() stuff here? + if ((d->openmode & ReadOnly) != ReadOnly) + return _error->Error("Reopen is only implemented for read-only files!"); close(iFd); - bool result = ExecCompressor(d->compressor, NULL, FileName, iFd, (d->openmode & ReadOnly) != ReadOnly); - if (result == true && To != 0) - result &= Skip(To); - return result; + if (TemporaryFileName.empty() == false) + iFd = open(TemporaryFileName.c_str(), O_RDONLY); + else if (FileName.empty() == false) + iFd = open(FileName.c_str(), O_RDONLY); + else + return _error->Error("Reopen is not implemented for OpenDescriptor()-FileFd!"); + + 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 APT_USE_ZLIB @@ -1521,7 +1385,7 @@ bool FileFd::Close() if (d != NULL) { - if (d->compressor_pid != -1) + if (d->compressor_pid > 0) ExecWait(d->compressor_pid, "FileFdCompressor", true); delete d; d = NULL; diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index f14f97b69..147535df1 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -178,14 +178,6 @@ bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0); pid_t ExecFork(); bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); -bool ExecCompressor(APT::Configuration::Compressor const &Prog, - pid_t *Pid, int const FileFd, int &OutFd, bool const Comp = true); -inline bool ExecDecompressor(APT::Configuration::Compressor const &Prog, - pid_t *Pid, int const FileFd, int &OutFd) -{ - return ExecCompressor(Prog, Pid, FileFd, OutFd, true); -} - // File string manipulators std::string flNotDir(std::string File); std::string flNotFile(std::string File); -- cgit v1.2.3 From 6fd947bd48449652edf783cfb1362391e63f9be1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 16 Dec 2011 00:04:52 +0100 Subject: try seeking on fds opened with OpenDescriptor before giving up --- apt-pkg/contrib/fileutl.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 44486905f..a98c2cb85 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1154,12 +1154,19 @@ bool FileFd::Seek(unsigned long long To) 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 - return _error->Error("Reopen is not implemented for OpenDescriptor()-FileFd!"); + { + 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()); -- cgit v1.2.3