Extract a Tar - Tar Extractor
Some performance measurements showed that zlib performed quite poorly
- in comparision to a forked gzip process. This tar extractor makes use
+ in comparison to a forked gzip process. This tar extractor makes use
of the fact that dup'd file descriptors have the same seek pointer
and that gzip will not read past the end of a compressed stream,
even if there is more data. We use the dup property to track extraction
#include <apt-pkg/error.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/configuration.h>
-#include <apt-pkg/macros.h>
+#include <apt-pkg/fileutl.h>
-#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <string>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
// ExtractTar::ExtractTar - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-ExtractTar::ExtractTar(FileFd &Fd,unsigned long Max,string DecompressionProgram) : File(Fd),
- MaxInSize(Max), DecompressProg(DecompressionProgram)
-
+#if APT_PKG_ABI >= 413
+ExtractTar::ExtractTar(FileFd &Fd,unsigned long long Max,string DecompressionProgram)
+ : File(Fd), MaxInSize(Max), DecompressProg(DecompressionProgram)
+#else
+ExtractTar::ExtractTar(FileFd &Fd,unsigned long Max,string DecompressionProgram)
+ : File(Fd), MaxInSize(Max), DecompressProg(DecompressionProgram)
+#endif
{
GZPid = -1;
Eof = false;
gzip will efficiently ignore the extra bits. */
bool ExtractTar::StartGzip()
{
+ if (DecompressProg.empty())
+ {
+ InFd.OpenDescriptor(File.Fd(), FileFd::ReadOnly, FileFd::None, false);
+ return true;
+ }
+
int Pipes[2];
if (pipe(Pipes) != 0)
return _error->Errno("pipe",_("Failed to create pipes"));
-
+
// Fork off the process
GZPid = ExecFork();
dup2(Fd,STDERR_FILENO);
close(Fd);
SetCloseExec(STDOUT_FILENO,false);
- SetCloseExec(STDIN_FILENO,false);
+ SetCloseExec(STDIN_FILENO,false);
SetCloseExec(STDERR_FILENO,false);
-
+
const char *Args[3];
string confvar = string("dir::bin::") + DecompressProg;
string argv0 = _config->Find(confvar.c_str(),DecompressProg.c_str());
case GNU_LongLink:
{
- unsigned long Length = Itm.Size;
+ unsigned long long Length = Itm.Size;
unsigned char Block[512];
while (Length > 0)
{
case GNU_LongName:
{
- unsigned long Length = Itm.Size;
+ unsigned long long Length = Itm.Size;
unsigned char Block[512];
while (Length > 0)
{
return false;
// Copy the file over the FD
- unsigned long Size = Itm.Size;
+ unsigned long long Size = Itm.Size;
while (Size != 0)
{
unsigned char Junk[32*1024];
- unsigned long Read = min(Size,(unsigned long)sizeof(Junk));
+ unsigned long Read = min(Size, (unsigned long long)sizeof(Junk));
if (InFd.Read(Junk,((Read+511)/512)*512) == false)
return false;