Browse Source

* methods/bzip2.cc:

- add a copycat of the old gzip.cc as we need it for bzip2 and lzma
tags/debian/0.8.0
David Kalnischkies 11 years ago
parent
commit
b09663668c
3 changed files with 191 additions and 10 deletions
  1. +3
    -1
      debian/changelog
  2. +177
    -0
      methods/bzip2.cc
  3. +11
    -9
      methods/makefile

+ 3
- 1
debian/changelog View File

@@ -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 <kalnischkies@gmail.com> Sat, 10 Jul 2010 13:44:32 +0200
-- David Kalnischkies <kalnischkies@gmail.com> Sun, 11 Jul 2010 21:56:36 +0200

apt (0.7.26~exp9) experimental; urgency=low



+ 177
- 0
methods/bzip2.cc View File

@@ -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 <apt-pkg/fileutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/acquire-method.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/hashes.h>

#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
#include <stdio.h>
#include <errno.h>
#include <apti18n.h>
/*}}}*/

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();
}

+ 11
- 9
methods/makefile View File

@@ -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

Loading…
Cancel
Save