From 127e6df37213a1fda0dd5b44182acf678ccbbf02 Mon Sep 17 00:00:00 2001 From: "martin@piware.de" <> Date: Tue, 6 Jul 2010 13:14:57 +0200 Subject: methods/gzip.cc: With FileFd now being able to read gzipped files, there is no need for the gzip method any more to spawn an external gzip process. Rewrite it to use FileFd directly, which makes the code a lot simpler, and also using less memory and overhead. --- methods/gzip.cc | 63 +++++++-------------------------------------------------- 1 file changed, 7 insertions(+), 56 deletions(-) (limited to 'methods') diff --git a/methods/gzip.cc b/methods/gzip.cc index f732c0b86..72e3ac909 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -23,8 +23,6 @@ #include /*}}}*/ -const char *Prog; - class GzipMethod : public pkgAcqMethod { virtual bool Fetch(FetchItem *Itm); @@ -43,14 +41,12 @@ bool GzipMethod::Fetch(FetchItem *Itm) URI Get = Itm->Uri; string Path = Get.Host + Get.Path; // To account for relative paths - string GzPathOption = "Dir::bin::"+string(Prog); - FetchResult Res; Res.Filename = Itm->DestFile; URIStart(Res); // Open the source and destination files - FileFd From(Path,FileFd::ReadOnly); + FileFd From(Path,FileFd::ReadOnlyGzip); // if the file is empty, just rename it and return if(From.Size() == 0) @@ -59,40 +55,12 @@ bool GzipMethod::Fetch(FetchItem *Itm) return true; } - int GzOut[2]; - if (pipe(GzOut) < 0) - return _error->Errno("pipe",_("Couldn't open pipe for %s"),Prog); - - // Fork gzip - pid_t Process = ExecFork(); - if (Process == 0) - { - close(GzOut[0]); - dup2(From.Fd(),STDIN_FILENO); - dup2(GzOut[1],STDOUT_FILENO); - From.Close(); - close(GzOut[1]); - SetCloseExec(STDIN_FILENO,false); - SetCloseExec(STDOUT_FILENO,false); - - const char *Args[3]; - string Tmp = _config->Find(GzPathOption,Prog); - Args[0] = Tmp.c_str(); - Args[1] = "-d"; - Args[2] = 0; - execvp(Args[0],(char **)Args); - _exit(100); - } - From.Close(); - close(GzOut[1]); - - FileFd FromGz(GzOut[0]); // For autoclose FileFd To(Itm->DestFile,FileFd::WriteEmpty); To.EraseOnFailure(); if (_error->PendingError() == true) return false; - // Read data from gzip, generate checksums and write + // Read data from source, generate checksums and write Hashes Hash; bool Failed = false; while (1) @@ -100,36 +68,23 @@ bool GzipMethod::Fetch(FetchItem *Itm) unsigned char Buffer[4*1024]; unsigned long Count; - Count = read(GzOut[0],Buffer,sizeof(Buffer)); - if (Count < 0 && errno == EINTR) - continue; - - if (Count < 0) + if (!From.Read(Buffer,sizeof(Buffer),&Count)) { - _error->Errno("read", _("Read error from %s process"),Prog); - Failed = true; - break; + To.OpFail(); + return false; } - if (Count == 0) break; - + Hash.Add(Buffer,Count); if (To.Write(Buffer,Count) == false) { Failed = true; - FromGz.Close(); break; } } - // Wait for gzip to finish - if (ExecWait(Process,_config->Find(GzPathOption,Prog).c_str(),false) == false) - { - To.OpFail(); - return false; - } - + From.Close(); To.Close(); if (Failed == true) @@ -165,9 +120,5 @@ int main(int argc, char *argv[]) setlocale(LC_ALL, ""); GzipMethod Mth; - - Prog = strrchr(argv[0],'/'); - Prog++; - return Mth.Run(); } -- cgit v1.2.3-70-g09d2 From b09663668c4d8203543e56b25db822ba55d21529 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 11 Jul 2010 21:57:51 +0200 Subject: * methods/bzip2.cc: - add a copycat of the old gzip.cc as we need it for bzip2 and lzma --- debian/changelog | 4 +- methods/bzip2.cc | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ methods/makefile | 20 ++++--- 3 files changed, 191 insertions(+), 10 deletions(-) create mode 100644 methods/bzip2.cc (limited to 'methods') diff --git a/debian/changelog b/debian/changelog index b0efc72e5..cfac23251 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,8 @@ apt (0.7.26~exp10) UNRELEASED; urgency=low * apt-pkg/deb/debmetaindex.cc: - do not query each architecture for flat file archives - fix typo preventing display of architecture in Info() + * methods/bzip2.cc: + - add a copycat of the old gzip.cc as we need it for bzip2 and lzma [ Martin Pitt ] * debian/rules: @@ -43,7 +45,7 @@ apt (0.7.26~exp10) UNRELEASED; urgency=low Rewrite it to use FileFd directly, which makes the code a lot simpler, and also using less memory and overhead. - -- David Kalnischkies Sat, 10 Jul 2010 13:44:32 +0200 + -- David Kalnischkies Sun, 11 Jul 2010 21:56:36 +0200 apt (0.7.26~exp9) experimental; urgency=low diff --git a/methods/bzip2.cc b/methods/bzip2.cc new file mode 100644 index 000000000..5da214bfc --- /dev/null +++ b/methods/bzip2.cc @@ -0,0 +1,177 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Bzip2 method - Take a file URI in and decompress it into the target + file. + + While the method is named "bzip2" it handles also other compression + types as it calls binaries based on the name of the method, + so it can also be used to handle gzip, lzma and others if named + correctly. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + /*}}}*/ + +const char *Prog; + +class Bzip2Method : public pkgAcqMethod +{ + virtual bool Fetch(FetchItem *Itm); + + public: + + Bzip2Method() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {}; +}; + + +// Bzip2Method::Fetch - Decompress the passed URI /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool Bzip2Method::Fetch(FetchItem *Itm) +{ + URI Get = Itm->Uri; + string Path = Get.Host + Get.Path; // To account for relative paths + + string GzPathOption = "Dir::bin::"+string(Prog); + + FetchResult Res; + Res.Filename = Itm->DestFile; + URIStart(Res); + + // Open the source and destination files + FileFd From(Path,FileFd::ReadOnly); + + // if the file is empty, just rename it and return + if(From.Size() == 0) + { + rename(Path.c_str(), Itm->DestFile.c_str()); + return true; + } + + int GzOut[2]; + if (pipe(GzOut) < 0) + return _error->Errno("pipe",_("Couldn't open pipe for %s"),Prog); + + // Fork bzip2 + pid_t Process = ExecFork(); + if (Process == 0) + { + close(GzOut[0]); + dup2(From.Fd(),STDIN_FILENO); + dup2(GzOut[1],STDOUT_FILENO); + From.Close(); + close(GzOut[1]); + SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDOUT_FILENO,false); + + const char *Args[3]; + string Tmp = _config->Find(GzPathOption,Prog); + Args[0] = Tmp.c_str(); + Args[1] = "-d"; + Args[2] = 0; + execvp(Args[0],(char **)Args); + _exit(100); + } + From.Close(); + close(GzOut[1]); + + FileFd FromGz(GzOut[0]); // For autoclose + FileFd To(Itm->DestFile,FileFd::WriteEmpty); + To.EraseOnFailure(); + if (_error->PendingError() == true) + return false; + + // Read data from bzip2, generate checksums and write + Hashes Hash; + bool Failed = false; + while (1) + { + unsigned char Buffer[4*1024]; + unsigned long Count; + + Count = read(GzOut[0],Buffer,sizeof(Buffer)); + if (Count < 0 && errno == EINTR) + continue; + + if (Count < 0) + { + _error->Errno("read", _("Read error from %s process"),Prog); + Failed = true; + break; + } + + if (Count == 0) + break; + + Hash.Add(Buffer,Count); + if (To.Write(Buffer,Count) == false) + { + Failed = true; + FromGz.Close(); + break; + } + } + + // Wait for bzip2 to finish + if (ExecWait(Process,_config->Find(GzPathOption,Prog).c_str(),false) == false) + { + To.OpFail(); + return false; + } + + To.Close(); + + if (Failed == true) + return false; + + // Transfer the modification times + struct stat Buf; + if (stat(Path.c_str(),&Buf) != 0) + return _error->Errno("stat",_("Failed to stat")); + + struct utimbuf TimeBuf; + TimeBuf.actime = Buf.st_atime; + TimeBuf.modtime = Buf.st_mtime; + if (utime(Itm->DestFile.c_str(),&TimeBuf) != 0) + return _error->Errno("utime",_("Failed to set modification time")); + + if (stat(Itm->DestFile.c_str(),&Buf) != 0) + return _error->Errno("stat",_("Failed to stat")); + + // Return a Done response + Res.LastModified = Buf.st_mtime; + Res.Size = Buf.st_size; + Res.TakeHashes(Hash); + + URIDone(Res); + + return true; +} + /*}}}*/ + +int main(int argc, char *argv[]) +{ + setlocale(LC_ALL, ""); + + Bzip2Method Mth; + + Prog = strrchr(argv[0],'/'); + Prog++; + + return Mth.Run(); +} diff --git a/methods/makefile b/methods/makefile index eabe85cfd..d94a85340 100644 --- a/methods/makefile +++ b/methods/makefile @@ -86,9 +86,16 @@ LIB_MAKES = apt-pkg/makefile SOURCE = mirror.cc http.cc rfc2553emu.cc connect.cc include $(PROGRAM_H) -# SSH and bzip2 method symlink -binary: $(BIN)/ssh $(BIN)/bzip2 $(BIN)/lzma -veryclean: clean-$(BIN)/ssh clean-$(BIN)/bzip2 clean-$(BIN)/lzma +# The gzip method +PROGRAM=bzip2 +SLIBS = -lapt-pkg $(INTLLIBS) +LIB_MAKES = apt-pkg/makefile +SOURCE = bzip2.cc +include $(PROGRAM_H) + +# SSH and lzma method symlink +binary: $(BIN)/ssh $(BIN)/lzma +veryclean: clean-$(BIN)/ssh clean-$(BIN)/lzma $(BIN)/ssh: echo "Installing ssh method link" @@ -96,13 +103,8 @@ $(BIN)/ssh: clean-$(BIN)/ssh: -rm $(BIN)/ssh -$(BIN)/bzip2: - echo "Installing bzip2 method link" - ln -fs gzip $(BIN)/bzip2 $(BIN)/lzma: echo "Installing lzma method link" - ln -fs gzip $(BIN)/lzma -clean-$(BIN)/bzip2: - -rm $(BIN)/bzip2 + ln -fs bzip2 $(BIN)/lzma clean-$(BIN)/lzma: -rm $(BIN)/lzma -- cgit v1.2.3-70-g09d2