ソースを参照

use liblzma-dev to provide xz/lzma support

We have xz/lzma support for a while, but only via an external binary
provided by xz-utils. Now that the Debian archive provides xz by default
and dpkg pre-depends on the library provided by liblzma-dev we can switch
now to use this library as well to avoid requiring an external binary.
For now the binary is in a prio:required package, but this might change
in the future.

API wise it is quiet similar to bz2 code expect that it doesn't provide
file I/O methods, so we piece this together on our own.
David Kalnischkies 12 年 前
コミット
7f350a377e
共有7 個のファイルを変更した271 個の追加39 個の削除を含む
  1. 8 0
      apt-pkg/aptconfiguration.cc
  2. 245 35
      apt-pkg/contrib/fileutl.cc
  3. 3 0
      apt-pkg/makefile
  4. 3 0
      buildlib/config.h.in
  5. 1 0
      buildlib/environment.mak.in
  6. 7 0
      configure.ac
  7. 4 4
      debian/control

+ 8 - 0
apt-pkg/aptconfiguration.cc

@@ -462,8 +462,16 @@ const Configuration::getCompressors(bool const Cached) {
 #endif
 #endif
 	if (_config->Exists("Dir::Bin::xz") == false || FileExists(_config->FindFile("Dir::Bin::xz")) == true)
 	if (_config->Exists("Dir::Bin::xz") == false || FileExists(_config->FindFile("Dir::Bin::xz")) == true)
 		compressors.push_back(Compressor("xz",".xz","xz","-6","-d",4));
 		compressors.push_back(Compressor("xz",".xz","xz","-6","-d",4));
+#ifdef HAVE_LZMA
+	else
+		compressors.push_back(Compressor("xz",".xz","false", NULL, NULL, 4));
+#endif
 	if (_config->Exists("Dir::Bin::lzma") == false || FileExists(_config->FindFile("Dir::Bin::lzma")) == true)
 	if (_config->Exists("Dir::Bin::lzma") == false || FileExists(_config->FindFile("Dir::Bin::lzma")) == true)
 		compressors.push_back(Compressor("lzma",".lzma","lzma","-9","-d",5));
 		compressors.push_back(Compressor("lzma",".lzma","lzma","-9","-d",5));
+#ifdef HAVE_LZMA
+	else
+		compressors.push_back(Compressor("lzma",".lzma","false", NULL, NULL, 5));
+#endif
 
 
 	std::vector<std::string> const comp = _config->FindVector("APT::Compressor");
 	std::vector<std::string> const comp = _config->FindVector("APT::Compressor");
 	for (std::vector<std::string>::const_iterator c = comp.begin();
 	for (std::vector<std::string>::const_iterator c = comp.begin();

+ 245 - 35
apt-pkg/contrib/fileutl.cc

@@ -58,6 +58,9 @@
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
 	#include <bzlib.h>
 	#include <bzlib.h>
 #endif
 #endif
+#ifdef HAVE_LZMA
+	#include <lzma.h>
+#endif
 
 
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
 #include <inttypes.h>
 #include <inttypes.h>
@@ -72,13 +75,47 @@ class FileFdPrivate {
 	public:
 	public:
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
 	gzFile gz;
 	gzFile gz;
-#else
-	void* gz;
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
 	BZFILE* bz2;
 	BZFILE* bz2;
-#else
-	void* bz2;
+#endif
+#ifdef HAVE_LZMA
+	struct LZMAFILE {
+	   FILE* file;
+	   uint8_t buffer[4096];
+	   lzma_stream stream;
+	   lzma_ret err;
+	   bool eof;
+	   bool compressing;
+
+	   LZMAFILE() : file(NULL), eof(false), compressing(false) {}
+	   ~LZMAFILE() {
+	      if (compressing == true)
+	      {
+		for (;;) {
+			stream.avail_out = sizeof(buffer)/sizeof(buffer[0]);
+			stream.next_out = buffer;
+			err = lzma_code(&stream, LZMA_FINISH);
+			if (err != LZMA_OK && err != LZMA_STREAM_END)
+			{
+				_error->Error("~LZMAFILE: Compress finalisation failed");
+				break;
+			}
+			size_t const n =  sizeof(buffer)/sizeof(buffer[0]) - stream.avail_out;
+			if (n && fwrite(buffer, 1, n, file) != n)
+			{
+				_error->Errno("~LZMAFILE",_("Write error"));
+				break;
+			}
+			if (err == LZMA_STREAM_END)
+				break;
+		}
+	      }
+	      lzma_end(&stream);
+	      fclose(file);
+	   }
+	};
+	LZMAFILE* lzma;
 #endif
 #endif
 	int compressed_fd;
 	int compressed_fd;
 	pid_t compressor_pid;
 	pid_t compressor_pid;
@@ -86,7 +123,16 @@ class FileFdPrivate {
 	APT::Configuration::Compressor compressor;
 	APT::Configuration::Compressor compressor;
 	unsigned int openmode;
 	unsigned int openmode;
 	unsigned long long seekpos;
 	unsigned long long seekpos;
-	FileFdPrivate() : gz(NULL), bz2(NULL),
+	FileFdPrivate() :
+#ifdef HAVE_ZLIB
+			  gz(NULL),
+#endif
+#ifdef HAVE_BZ2
+			  bz2(NULL),
+#endif
+#ifdef HAVE_LZMA
+			  lzma(NULL),
+#endif
 			  compressed_fd(-1), compressor_pid(-1), pipe(false),
 			  compressed_fd(-1), compressor_pid(-1), pipe(false),
 			  openmode(0), seekpos(0) {};
 			  openmode(0), seekpos(0) {};
 	bool CloseDown(std::string const &FileName)
 	bool CloseDown(std::string const &FileName)
@@ -106,6 +152,12 @@ class FileFdPrivate {
 	      BZ2_bzclose(bz2);
 	      BZ2_bzclose(bz2);
 	      bz2 = NULL;
 	      bz2 = NULL;
 	   }
 	   }
+#endif
+#ifdef HAVE_LZMA
+	   if (lzma != NULL) {
+	      delete lzma;
+	      lzma = NULL;
+	   }
 #endif
 #endif
 	   if (compressor_pid > 0)
 	   if (compressor_pid > 0)
 	      ExecWait(compressor_pid, "FileFdCompressor", true);
 	      ExecWait(compressor_pid, "FileFdCompressor", true);
@@ -1089,12 +1141,14 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
    if (compressor.Name == "." || compressor.Binary.empty() == true)
    if (compressor.Name == "." || compressor.Binary.empty() == true)
       return true;
       return true;
 
 
-#if defined HAVE_ZLIB || defined HAVE_BZ2
+#if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
    // the API to open files is similar, so setup to avoid code duplicates later
    // the API to open files is similar, so setup to avoid code duplicates later
    // and while at it ensure that we close before opening (if its a reopen)
    // and while at it ensure that we close before opening (if its a reopen)
    void* (*compress_open)(int, const char *) = NULL;
    void* (*compress_open)(int, const char *) = NULL;
+   if (false)
+      /* dummy so that the rest can be 'else if's */;
 #define APT_COMPRESS_INIT(NAME,OPEN,CLOSE,STRUCT) \
 #define APT_COMPRESS_INIT(NAME,OPEN,CLOSE,STRUCT) \
-   if (compressor.Name == NAME) \
+   else if (compressor.Name == NAME) \
    { \
    { \
       compress_open = (void*(*)(int, const char *)) OPEN; \
       compress_open = (void*(*)(int, const char *)) OPEN; \
       if (d != NULL && STRUCT != NULL) { CLOSE(STRUCT); STRUCT = NULL; } \
       if (d != NULL && STRUCT != NULL) { CLOSE(STRUCT); STRUCT = NULL; } \
@@ -1105,6 +1159,17 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
    APT_COMPRESS_INIT("bzip2", BZ2_bzdopen, BZ2_bzclose, d->bz2)
    APT_COMPRESS_INIT("bzip2", BZ2_bzdopen, BZ2_bzclose, d->bz2)
 #endif
 #endif
+#ifdef HAVE_LZMA
+   else if (compressor.Name == "xz" || compressor.Name == "lzma")
+   {
+      compress_open = (void*(*)(int, const char*)) fdopen;
+      if (d != NULL && d->lzma != NULL)
+      {
+	 delete d->lzma;
+	 d->lzma = NULL;
+      }
+   }
+#endif
 #undef APT_COMPRESS_INIT
 #undef APT_COMPRESS_INIT
 #endif
 #endif
 
 
@@ -1113,7 +1178,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
       d = new FileFdPrivate();
       d = new FileFdPrivate();
       d->openmode = Mode;
       d->openmode = Mode;
       d->compressor = compressor;
       d->compressor = compressor;
-#if defined HAVE_ZLIB || defined HAVE_BZ2
+#if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
       if (AutoClose == false && compress_open != NULL)
       if (AutoClose == false && compress_open != NULL)
       {
       {
 	 // Need to duplicate fd here or gz/bz2 close for cleanup will close the fd as well
 	 // Need to duplicate fd here or gz/bz2 close for cleanup will close the fd as well
@@ -1125,7 +1190,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
 #endif
 #endif
    }
    }
 
 
-#if defined HAVE_ZLIB || defined HAVE_BZ2
+#if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
    if (compress_open != NULL)
    if (compress_open != NULL)
    {
    {
       void* compress_struct = NULL;
       void* compress_struct = NULL;
@@ -1138,13 +1203,60 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
       if (compress_struct == NULL)
       if (compress_struct == NULL)
 	 return false;
 	 return false;
 
 
+      if (false)
+	 /* dummy so that the rest can be 'else if's */;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-      if (compressor.Name == "gzip")
+      else if (compressor.Name == "gzip")
 	 d->gz = (gzFile) compress_struct;
 	 d->gz = (gzFile) compress_struct;
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
-      if (compressor.Name == "bzip2")
+      else if (compressor.Name == "bzip2")
 	 d->bz2 = (BZFILE*) compress_struct;
 	 d->bz2 = (BZFILE*) compress_struct;
+#endif
+#ifdef HAVE_LZMA
+      else if (compressor.Name == "xz" || compressor.Name == "lzma")
+      {
+	 uint32_t const xzlevel = 6;
+	 uint64_t const memlimit = UINT64_MAX;
+	 if (d->lzma == NULL)
+	    d->lzma = new FileFdPrivate::LZMAFILE;
+	 d->lzma->file = (FILE*) compress_struct;
+	 d->lzma->stream = LZMA_STREAM_INIT;
+
+	 if ((Mode & ReadWrite) == ReadWrite)
+	    return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str());
+
+	 if ((Mode & WriteOnly) == WriteOnly)
+	 {
+	    if (compressor.Name == "xz")
+	    {
+	       if (lzma_easy_encoder(&d->lzma->stream, xzlevel, LZMA_CHECK_CRC32) != LZMA_OK)
+		  return false;
+	    }
+	    else
+	    {
+	       lzma_options_lzma options;
+	       lzma_lzma_preset(&options, xzlevel);
+	       if (lzma_alone_encoder(&d->lzma->stream, &options) != LZMA_OK)
+		  return false;
+	    }
+	    d->lzma->compressing = true;
+	 }
+	 else
+	 {
+	    if (compressor.Name == "xz")
+	    {
+	       if (lzma_auto_decoder(&d->lzma->stream, memlimit, 0) != LZMA_OK)
+		  return false;
+	    }
+	    else
+	    {
+	       if (lzma_alone_decoder(&d->lzma->stream, memlimit) != LZMA_OK)
+		  return false;
+	    }
+	    d->lzma->compressing = false;
+	 }
+      }
 #endif
 #endif
       Flags |= Compressed;
       Flags |= Compressed;
       return true;
       return true;
@@ -1202,7 +1314,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
       }
       }
       else
       else
       {
       {
-	 if (FileName.empty() == true)
+	 if (d->compressed_fd != -1)
 	    dup2(d->compressed_fd,STDIN_FILENO);
 	    dup2(d->compressed_fd,STDIN_FILENO);
 	 dup2(Pipe[1],STDOUT_FILENO);
 	 dup2(Pipe[1],STDOUT_FILENO);
       }
       }
@@ -1271,24 +1383,55 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
    *((char *)To) = '\0';
    *((char *)To) = '\0';
    do
    do
    {
    {
+      if (false)
+	 /* dummy so that the rest can be 'else if's */;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-      if (d != NULL && d->gz != NULL)
+      else if (d != NULL && d->gz != NULL)
 	 Res = gzread(d->gz,To,Size);
 	 Res = gzread(d->gz,To,Size);
-      else
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
-      if (d != NULL && d->bz2 != NULL)
+      else if (d != NULL && d->bz2 != NULL)
 	 Res = BZ2_bzread(d->bz2,To,Size);
 	 Res = BZ2_bzread(d->bz2,To,Size);
-      else
 #endif
 #endif
+#ifdef HAVE_LZMA
+      else if (d != NULL && d->lzma != NULL)
+      {
+	 if (d->lzma->eof == true)
+	    break;
+
+	 d->lzma->stream.next_out = (uint8_t *) To;
+	 d->lzma->stream.avail_out = Size;
+	 if (d->lzma->stream.avail_in == 0)
+	 {
+	    d->lzma->stream.next_in = d->lzma->buffer;
+	    d->lzma->stream.avail_in = fread(d->lzma->buffer, 1, sizeof(d->lzma->buffer)/sizeof(d->lzma->buffer[0]), d->lzma->file);
+	 }
+	 d->lzma->err = lzma_code(&d->lzma->stream, LZMA_RUN);
+	 if (d->lzma->err == LZMA_STREAM_END)
+	 {
+	    d->lzma->eof = true;
+	    Res = Size - d->lzma->stream.avail_out;
+	 }
+	 else if (d->lzma->err != LZMA_OK)
+	 {
+	    Res = -1;
+	    errno = 0;
+	 }
+	 else
+	    Res = Size - d->lzma->stream.avail_out;
+      }
+#endif
+      else
          Res = read(iFd,To,Size);
          Res = read(iFd,To,Size);
 
 
       if (Res < 0)
       if (Res < 0)
       {
       {
 	 if (errno == EINTR)
 	 if (errno == EINTR)
 	    continue;
 	    continue;
+	 if (false)
+	    /* dummy so that the rest can be 'else if's */;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-	 if (d != NULL && d->gz != NULL)
+	 else if (d != NULL && d->gz != NULL)
 	 {
 	 {
 	    int err;
 	    int err;
 	    char const * const errmsg = gzerror(d->gz, &err);
 	    char const * const errmsg = gzerror(d->gz, &err);
@@ -1297,13 +1440,17 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
 	 }
 	 }
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
-	 if (d != NULL && d->bz2 != NULL)
+	 else if (d != NULL && d->bz2 != NULL)
 	 {
 	 {
 	    int err;
 	    int err;
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    if (err != BZ_IO_ERROR)
 	    if (err != BZ_IO_ERROR)
 	       return FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg);
 	       return FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg);
 	 }
 	 }
+#endif
+#ifdef HAVE_LZMA
+	 else if (d != NULL && d->lzma != NULL)
+	    return FileFdError("lzma_read: %s (%d)", _("Read error"), d->lzma->err);
 #endif
 #endif
 	 return FileFdErrno("read",_("Read error"));
 	 return FileFdErrno("read",_("Read error"));
       }
       }
@@ -1368,23 +1515,45 @@ bool FileFd::Write(const void *From,unsigned long long Size)
    errno = 0;
    errno = 0;
    do
    do
    {
    {
+      if (false)
+	 /* dummy so that the rest can be 'else if's */;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-      if (d != NULL && d->gz != NULL)
-         Res = gzwrite(d->gz,From,Size);
-      else
+      else if (d != NULL && d->gz != NULL)
+	 Res = gzwrite(d->gz,From,Size);
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
-      if (d != NULL && d->bz2 != NULL)
-         Res = BZ2_bzwrite(d->bz2,(void*)From,Size);
-      else
+      else if (d != NULL && d->bz2 != NULL)
+	 Res = BZ2_bzwrite(d->bz2,(void*)From,Size);
 #endif
 #endif
-         Res = write(iFd,From,Size);
+#ifdef HAVE_LZMA
+      else if (d != NULL && d->lzma != NULL)
+      {
+	 d->lzma->stream.next_in = (uint8_t *)From;
+	 d->lzma->stream.avail_in = Size;
+	 d->lzma->stream.next_out = d->lzma->buffer;
+	 d->lzma->stream.avail_out = sizeof(d->lzma->buffer)/sizeof(d->lzma->buffer[0]);
+	 d->lzma->err = lzma_code(&d->lzma->stream, LZMA_RUN);
+	 if (d->lzma->err != LZMA_OK)
+	    return false;
+	 size_t const n = sizeof(d->lzma->buffer)/sizeof(d->lzma->buffer[0]) - d->lzma->stream.avail_out;
+	 size_t const m = (n == 0) ? 0 : fwrite(d->lzma->buffer, 1, n, d->lzma->file);
+	 if (m != n)
+	    Res = -1;
+	 else
+	    Res = Size - d->lzma->stream.avail_in;
+      }
+#endif
+      else
+	 Res = write(iFd,From,Size);
+
       if (Res < 0 && errno == EINTR)
       if (Res < 0 && errno == EINTR)
 	 continue;
 	 continue;
       if (Res < 0)
       if (Res < 0)
       {
       {
+	 if (false)
+	    /* dummy so that the rest can be 'else if's */;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-	 if (d != NULL && d->gz != NULL)
+	 else if (d != NULL && d->gz != NULL)
 	 {
 	 {
 	    int err;
 	    int err;
 	    char const * const errmsg = gzerror(d->gz, &err);
 	    char const * const errmsg = gzerror(d->gz, &err);
@@ -1393,13 +1562,17 @@ bool FileFd::Write(const void *From,unsigned long long Size)
 	 }
 	 }
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
-	 if (d != NULL && d->bz2 != NULL)
+	 else if (d != NULL && d->bz2 != NULL)
 	 {
 	 {
 	    int err;
 	    int err;
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    if (err != BZ_IO_ERROR)
 	    if (err != BZ_IO_ERROR)
 	       return FileFdError("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
 	       return FileFdError("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
 	 }
 	 }
+#endif
+#ifdef HAVE_LZMA
+	 else if (d != NULL && d->lzma != NULL)
+	    return FileFdErrno("lzma_fwrite", _("Write error"));
 #endif
 #endif
 	 return FileFdErrno("write",_("Write error"));
 	 return FileFdErrno("write",_("Write error"));
       }
       }
@@ -1447,6 +1620,9 @@ bool FileFd::Seek(unsigned long long To)
    if (d != NULL && (d->pipe == true
    if (d != NULL && (d->pipe == true
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
 			|| d->bz2 != NULL
 			|| d->bz2 != NULL
+#endif
+#ifdef HAVE_LZMA
+			|| d->lzma != NULL
 #endif
 #endif
 	))
 	))
    {
    {
@@ -1459,12 +1635,21 @@ bool FileFd::Seek(unsigned long long To)
 
 
       if ((d->openmode & ReadOnly) != ReadOnly)
       if ((d->openmode & ReadOnly) != ReadOnly)
 	 return FileFdError("Reopen is only implemented for read-only files!");
 	 return FileFdError("Reopen is only implemented for read-only files!");
+      if (false)
+	 /* dummy so that the rest can be 'else if's */;
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
-     if (d->bz2 != NULL) 
-     {
-	BZ2_bzclose(d->bz2);
-	d->bz2 = NULL;
-     }
+      else if (d->bz2 != NULL)
+      {
+	 BZ2_bzclose(d->bz2);
+	 d->bz2 = NULL;
+      }
+#endif
+#ifdef HAVE_LZMA
+      else if (d->lzma != NULL)
+      {
+	 delete d->lzma;
+	 d->lzma = NULL;
+      }
 #endif
 #endif
       if (iFd != -1)
       if (iFd != -1)
 	 close(iFd);
 	 close(iFd);
@@ -1514,6 +1699,9 @@ bool FileFd::Skip(unsigned long long Over)
    if (d != NULL && (d->pipe == true
    if (d != NULL && (d->pipe == true
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
 			|| d->bz2 != NULL
 			|| d->bz2 != NULL
+#endif
+#ifdef HAVE_LZMA
+			|| d->lzma != NULL
 #endif
 #endif
 	))
 	))
    {
    {
@@ -1552,8 +1740,18 @@ bool FileFd::Truncate(unsigned long long To)
    // truncating /dev/null is always successful - as we get an error otherwise
    // truncating /dev/null is always successful - as we get an error otherwise
    if (To == 0 && FileName == "/dev/null")
    if (To == 0 && FileName == "/dev/null")
       return true;
       return true;
-#if defined HAVE_ZLIB || defined HAVE_BZ2
-   if (d != NULL && (d->gz != NULL || d->bz2 != NULL))
+#if defined HAVE_ZLIB || defined HAVE_BZ2 || defined HAVE_LZMA
+   if (d != NULL && (
+#ifdef HAVE_ZLIB
+	    d->gz != NULL ||
+#endif
+#ifdef HAVE_BZ2
+	    d->bz2 != NULL ||
+#endif
+#ifdef HAVE_LZMA
+	    d->lzma != NULL ||
+#endif
+	    false))
       return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str());
       return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str());
 #endif
 #endif
    if (ftruncate(iFd,To) != 0)
    if (ftruncate(iFd,To) != 0)
@@ -1574,6 +1772,9 @@ unsigned long long FileFd::Tell()
    if (d != NULL && (d->pipe == true
    if (d != NULL && (d->pipe == true
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
 			|| d->bz2 != NULL
 			|| d->bz2 != NULL
+#endif
+#ifdef HAVE_LZMA
+			|| d->lzma != NULL
 #endif
 #endif
 	))
 	))
       return d->seekpos;
       return d->seekpos;
@@ -1653,6 +1854,9 @@ unsigned long long FileFd::Size()
    if (d != NULL && (d->pipe == true
    if (d != NULL && (d->pipe == true
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
 			|| (d->bz2 && size > 0)
 			|| (d->bz2 && size > 0)
+#endif
+#ifdef HAVE_LZMA
+			|| (d->lzma && size > 0)
 #endif
 #endif
 	))
 	))
    {
    {
@@ -1797,7 +2001,13 @@ bool FileFd::FileFdError(const char *Description,...) {
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 
-gzFile FileFd::gzFd() { return d->gz; }
+APT_DEPRECATED gzFile FileFd::gzFd() {
+#ifdef HAVE_ZLIB
+   return d->gz;
+#else
+   return NULL;
+#endif
+}
 
 
 
 
 // Glob - wrapper around "glob()"                                      /*{{{*/
 // Glob - wrapper around "glob()"                                      /*{{{*/

+ 3 - 0
apt-pkg/makefile

@@ -21,6 +21,9 @@ endif
 ifeq ($(HAVE_BZ2),yes)
 ifeq ($(HAVE_BZ2),yes)
 SLIBS+= -lbz2
 SLIBS+= -lbz2
 endif
 endif
+ifeq ($(HAVE_LZMA),yes)
+SLIBS+= -llzma
+endif
 APT_DOMAIN:=libapt-pkg$(LIBAPTPKG_MAJOR)
 APT_DOMAIN:=libapt-pkg$(LIBAPTPKG_MAJOR)
 
 
 # Source code for the contributed non-core things
 # Source code for the contributed non-core things

+ 3 - 0
buildlib/config.h.in

@@ -11,6 +11,9 @@
 /* Define if we have the bz2 library for bzip2 */
 /* Define if we have the bz2 library for bzip2 */
 #undef HAVE_BZ2
 #undef HAVE_BZ2
 
 
+/* Define if we have the lzma library for lzma/xz */
+#undef HAVE_LZMA
+
 /* These two are used by the statvfs shim for glibc2.0 and bsd */
 /* These two are used by the statvfs shim for glibc2.0 and bsd */
 /* Define if we have sys/vfs.h */
 /* Define if we have sys/vfs.h */
 #undef HAVE_VFS_H
 #undef HAVE_VFS_H

+ 1 - 0
buildlib/environment.mak.in

@@ -61,6 +61,7 @@ INTLLIBS = @INTLLIBS@
 HAVE_STATVFS = @HAVE_STATVFS@
 HAVE_STATVFS = @HAVE_STATVFS@
 HAVE_ZLIB = @HAVE_ZLIB@
 HAVE_ZLIB = @HAVE_ZLIB@
 HAVE_BZ2 = @HAVE_BZ2@
 HAVE_BZ2 = @HAVE_BZ2@
+HAVE_LZMA = @HAVE_LZMA@
 NEED_SOCKLEN_T_DEFINE = @NEED_SOCKLEN_T_DEFINE@
 NEED_SOCKLEN_T_DEFINE = @NEED_SOCKLEN_T_DEFINE@
 
 
 # Shared library things
 # Shared library things

+ 7 - 0
configure.ac

@@ -107,6 +107,13 @@ if test "x$HAVE_BZ2" = "xyes"; then
 	AC_DEFINE(HAVE_BZ2)
 	AC_DEFINE(HAVE_BZ2)
 fi
 fi
 
 
+HAVE_LZMA=no
+AC_CHECK_LIB(lzma, lzma_easy_encoder,[AC_CHECK_HEADER(lzma.h, [HAVE_LZMA=yes], [])], [])
+AC_SUBST(HAVE_LZMA)
+if test "x$HAVE_LZMA" = "xyes"; then
+	AC_DEFINE(HAVE_LZMA)
+fi
+
 dnl Converts the ARCH to be something singular for this general CPU family
 dnl Converts the ARCH to be something singular for this general CPU family
 dnl This is often the dpkg architecture string.
 dnl This is often the dpkg architecture string.
 dnl First check against the full canonical canoncial-system-type in $target
 dnl First check against the full canonical canoncial-system-type in $target

+ 4 - 4
debian/control

@@ -7,8 +7,9 @@ Uploaders: Michael Vogt <mvo@debian.org>, Christian Perrier <bubulle@debian.org>
 Standards-Version: 3.9.5
 Standards-Version: 3.9.5
 Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev,
 Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev,
  gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~),
  gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~),
- zlib1g-dev, libbz2-dev, xsltproc, docbook-xsl, docbook-xml,
- po4a (>= 0.34-2), autotools-dev, autoconf, automake
+ zlib1g-dev, libbz2-dev, liblzma-dev,
+ xsltproc, docbook-xsl, docbook-xml, po4a (>= 0.34-2),
+ autotools-dev, autoconf, automake
 Build-Depends-Indep: doxygen, debiandoc-sgml, graphviz
 Build-Depends-Indep: doxygen, debiandoc-sgml, graphviz
 Build-Conflicts: autoconf2.13, automake1.4
 Build-Conflicts: autoconf2.13, automake1.4
 Vcs-Git: git://anonscm.debian.org/apt/apt.git
 Vcs-Git: git://anonscm.debian.org/apt/apt.git
@@ -41,7 +42,7 @@ Package: libapt-pkg4.12
 Architecture: any
 Architecture: any
 Multi-Arch: same
 Multi-Arch: same
 Pre-Depends: ${misc:Pre-Depends}
 Pre-Depends: ${misc:Pre-Depends}
-Depends: ${shlibs:Depends}, ${misc:Depends}, xz-utils
+Depends: ${shlibs:Depends}, ${misc:Depends}
 Breaks: apt (<< 0.9.4~), libapt-inst1.5 (<< 0.9.9~)
 Breaks: apt (<< 0.9.4~), libapt-inst1.5 (<< 0.9.9~)
 Section: libs
 Section: libs
 Description: package management runtime library
 Description: package management runtime library
@@ -107,7 +108,6 @@ Description: documentation for APT development
 Package: apt-utils
 Package: apt-utils
 Architecture: any
 Architecture: any
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Depends: ${shlibs:Depends}, ${misc:Depends}
-Suggests: xz-utils
 Description: package management related utility programs
 Description: package management related utility programs
  This package contains some less used commandline utilities related
  This package contains some less used commandline utilities related
  to package management with APT.
  to package management with APT.