1
// -*- mode: cpp; mode: fold -*-
3
/* ######################################################################
5
Bzip2 method - Take a file URI in and decompress it into the target
8
While the method is named "bzip2" it handles also other compression
9
types as it calls binaries based on the name of the method,
10
so it can also be used to handle gzip, lzma and others if named
13
##################################################################### */
15
// Include Files /*{{{*/
18
#include <apt-pkg/fileutl.h>
19
#include <apt-pkg/error.h>
20
#include <apt-pkg/acquire-method.h>
21
#include <apt-pkg/strutl.h>
22
#include <apt-pkg/hashes.h>
23
#include <apt-pkg/configuration.h>
35
class Bzip2Method : public pkgAcqMethod
37
virtual bool Fetch(FetchItem *Itm);
41
Bzip2Method() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {};
45
// Bzip2Method::Fetch - Decompress the passed URI /*{{{*/
46
// ---------------------------------------------------------------------
48
bool Bzip2Method::Fetch(FetchItem *Itm)
51
std::string Path = Get.Host + Get.Path; // To account for relative paths
53
std::string GzPathOption = "Dir::bin::" + std::string(Prog);
56
Res.Filename = Itm->DestFile;
59
// Open the source and destination files
60
FileFd From(Path,FileFd::ReadOnly);
62
if(From.FileSize() == 0)
63
return _error->Error(_("Empty files can't be valid archives"));
67
return _error->Errno("pipe",_("Couldn't open pipe for %s"),Prog);
70
pid_t Process = ExecFork();
74
dup2(From.Fd(),STDIN_FILENO);
75
dup2(GzOut[1],STDOUT_FILENO);
78
SetCloseExec(STDIN_FILENO,false);
79
SetCloseExec(STDOUT_FILENO,false);
82
std::string Tmp = _config->Find(GzPathOption,Prog);
83
Args[0] = Tmp.c_str();
86
execvp(Args[0],(char **)Args);
92
FileFd FromGz(GzOut[0]); // For autoclose
93
FileFd To(Itm->DestFile,FileFd::WriteAtomic);
95
if (_error->PendingError() == true)
98
// Read data from bzip2, generate checksums and write
103
unsigned char Buffer[4*1024];
105
ssize_t Count = read(GzOut[0],Buffer,sizeof(Buffer));
106
if (Count < 0 && errno == EINTR)
111
_error->Errno("read", _("Read error from %s process"),Prog);
119
Hash.Add(Buffer,Count);
120
if (To.Write(Buffer,Count) == false)
128
// Wait for bzip2 to finish
129
if (ExecWait(Process,_config->Find(GzPathOption,Prog).c_str(),false) == false)
140
// Transfer the modification times
142
if (stat(Path.c_str(),&Buf) != 0)
143
return _error->Errno("stat",_("Failed to stat"));
145
struct utimbuf TimeBuf;
146
TimeBuf.actime = Buf.st_atime;
147
TimeBuf.modtime = Buf.st_mtime;
148
if (utime(Itm->DestFile.c_str(),&TimeBuf) != 0)
149
return _error->Errno("utime",_("Failed to set modification time"));
151
if (stat(Itm->DestFile.c_str(),&Buf) != 0)
152
return _error->Errno("stat",_("Failed to stat"));
154
// Return a Done response
155
Res.LastModified = Buf.st_mtime;
156
Res.Size = Buf.st_size;
157
Res.TakeHashes(Hash);
165
int main(int argc, char *argv[])
167
setlocale(LC_ALL, "");
171
Prog = strrchr(argv[0],'/');