The following commit has been merged in the master branch: commit 7180e8e3e8583fe101b9d1883bad3a5b3af650aa Author: Guillem Jover <guil...@debian.org> Date: Thu Jun 7 10:55:59 2012 +0200
libdpkg: Add liblzma compression support Use liblzma if available instead of external commands to handle .xz and .lzma compressed files. Among other things, this means the xz-utils package no longer has to be part of the base system. Based-on-patch-by: Jonathan Nieder <jrnie...@gmail.com> Signed-off-by: Guillem Jover <guil...@debian.org> diff --git a/configure.ac b/configure.ac index 782287a..aef391b 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,7 @@ AC_SYS_LARGEFILE # Checks for libraries. DPKG_LIB_ZLIB DPKG_LIB_BZ2 +DPKG_LIB_LZMA DPKG_LIB_SELINUX if test "x$build_dselect" = "xyes"; then DPKG_LIB_CURSES diff --git a/debian/changelog b/debian/changelog index 8d50c64..3543537 100644 --- a/debian/changelog +++ b/debian/changelog @@ -58,6 +58,9 @@ dpkg (1.16.4) UNRELEASED; urgency=low fix a usege before declaration warning with perl 5.16. Closes: #676262 * Do not warn in dpkg-divert on missing files list file for packages never installed before. Closes: #673518 + * Add support for liblzma to handle .xz and .lzma compressed files, and + switch to it instead of using xz-utils. This removes the xz-utils + Pre-Depends from dpkg. Thanks to Jonathan Nieder <jrnie...@gmail.com>. [ Updated man page translations ] * German (Helge Kreutzmann). diff --git a/debian/control b/debian/control index c78d63c..5abf4fa 100644 --- a/debian/control +++ b/debian/control @@ -11,7 +11,7 @@ Vcs-Git: git://git.debian.org/git/dpkg/dpkg.git Standards-Version: 3.9.3 Build-Depends: debhelper (>= 7), pkg-config, flex, gettext (>= 0.18), po4a (>= 0.41), - zlib1g-dev (>= 1:1.1.3-19.1), libbz2-dev, + zlib1g-dev (>= 1:1.1.3-19.1), libbz2-dev, liblzma-dev, libselinux1-dev (>= 1.28-4) [linux-any], libncursesw5-dev, libtimedate-perl, libio-string-perl @@ -32,7 +32,7 @@ Package: dpkg Architecture: any Multi-Arch: foreign Essential: yes -Pre-Depends: ${shlibs:Depends}, tar (>= 1.23), xz-utils +Pre-Depends: ${shlibs:Depends}, tar (>= 1.23) Depends: ${misc:Depends} Breaks: dpkg-dev (<< 1.15.8), libdpkg-perl (<< 1.15.8), apt (<< 0.7.7), aptitude (<< 0.4.7-1), diff --git a/debian/rules b/debian/rules index 5a58ce5..b5e0d31 100755 --- a/debian/rules +++ b/debian/rules @@ -51,6 +51,7 @@ build-tree/config.status: configure --sysconfdir=/etc \ --localstatedir=/var \ --with-zlib \ + --with-liblzma \ --with-bz2 # Build the package in build-tree diff --git a/dpkg-deb/Makefile.am b/dpkg-deb/Makefile.am index 6f118cf..6b66d3e 100644 --- a/dpkg-deb/Makefile.am +++ b/dpkg-deb/Makefile.am @@ -22,4 +22,5 @@ dpkg_deb_LDADD = \ ../lib/compat/libcompat.a \ $(LIBINTL) \ $(ZLIB_LIBS) \ + $(LIBLZMA_LIBS) \ $(BZ2_LIBS) diff --git a/lib/dpkg/compress.c b/lib/dpkg/compress.c index 408cc3b..8d2a7e4 100644 --- a/lib/dpkg/compress.c +++ b/lib/dpkg/compress.c @@ -26,11 +26,15 @@ #include <errno.h> #include <string.h> #include <unistd.h> +#include <stdbool.h> #include <stdlib.h> #ifdef WITH_ZLIB #include <zlib.h> #endif +#ifdef WITH_LIBLZMA +#include <lzma.h> +#endif #ifdef WITH_BZ2 #include <bzlib.h> #endif @@ -43,6 +47,7 @@ #include <dpkg/buffer.h> #include <dpkg/command.h> #include <dpkg/compress.h> +#if !defined(WITH_ZLIB) || !defined(WITH_LIBLZMA) || !defined(WITH_BZ2) #include <dpkg/subproc.h> static void DPKG_ATTR_SENTINEL @@ -73,6 +78,7 @@ fd_fd_filter(int fd_in, int fd_out, const char *desc, const char *file, ...) } subproc_wait_check(pid, desc, 0); } +#endif struct compressor { const char *name; @@ -363,6 +369,194 @@ static const struct compressor compressor_bzip2 = { #define XZ "xz" +#ifdef WITH_LIBLZMA +enum dpkg_stream_status { + DPKG_STREAM_INIT = DPKG_BIT(1), + DPKG_STREAM_RUN = DPKG_BIT(2), + DPKG_STREAM_COMPRESS = DPKG_BIT(3), + DPKG_STREAM_DECOMPRESS = DPKG_BIT(4), + DPKG_STREAM_FILTER = DPKG_STREAM_COMPRESS | DPKG_STREAM_DECOMPRESS, +}; + +/* XXX: liblzma does not expose error messages. */ +static const char * +dpkg_lzma_strerror(lzma_ret code, enum dpkg_stream_status status) +{ + const char *const impossible = _("internal error (bug)"); + + switch (code) { + case LZMA_MEM_ERROR: + return strerror(ENOMEM); + case LZMA_MEMLIMIT_ERROR: + if (status & DPKG_STREAM_RUN) + return _("memory usage limit reached"); + return impossible; + case LZMA_OPTIONS_ERROR: + if (status == (DPKG_STREAM_INIT | DPKG_STREAM_COMPRESS)) + return _("unsupported compression preset"); + if (status == (DPKG_STREAM_RUN | DPKG_STREAM_DECOMPRESS)) + return _("unsupported options in file header"); + return impossible; + case LZMA_DATA_ERROR: + if (status & DPKG_STREAM_RUN) + return _("compressed data is corrupt"); + return impossible; + case LZMA_BUF_ERROR: + if (status & DPKG_STREAM_RUN) + return _("unexpected end of input"); + return impossible; + case LZMA_FORMAT_ERROR: + if (status == (DPKG_STREAM_RUN | DPKG_STREAM_DECOMPRESS)) + return _("file format not recognized"); + return impossible; + case LZMA_UNSUPPORTED_CHECK: + if (status == (DPKG_STREAM_INIT | DPKG_STREAM_COMPRESS)) + return _("unsupported type of integrity check"); + return impossible; + default: + return impossible; + } +} + +struct io_lzma { + const char *desc; + + struct compress_params *params; + enum dpkg_stream_status status; + lzma_action action; + + void (*init)(struct io_lzma *io, lzma_stream *s); + int (*code)(struct io_lzma *io, lzma_stream *s); + void (*done)(struct io_lzma *io, lzma_stream *s); +}; + +static void +filter_lzma(struct io_lzma *io, int fd_in, int fd_out) +{ + uint8_t buf_in[DPKG_BUFFER_SIZE]; + uint8_t buf_out[DPKG_BUFFER_SIZE]; + lzma_stream s = LZMA_STREAM_INIT; + lzma_ret ret; + + s.next_out = buf_out; + s.avail_out = sizeof(buf_out); + + io->action = LZMA_RUN; + io->status = DPKG_STREAM_INIT; + io->init(io, &s); + io->status = (io->status & DPKG_STREAM_FILTER) | DPKG_STREAM_RUN; + + do { + ssize_t len; + + if (s.avail_in == 0 && io->action != LZMA_FINISH) { + len = fd_read(fd_in, buf_in, sizeof(buf_in)); + if (len < 0) + ohshite(_("%s: lzma read error"), io->desc); + if (len == 0) + io->action = LZMA_FINISH; + s.next_in = buf_in; + s.avail_in = len; + } + + ret = io->code(io, &s); + + if (s.avail_out == 0 || ret == LZMA_STREAM_END) { + len = fd_write(fd_out, buf_out, s.next_out - buf_out); + if (len < 0) + ohshite(_("%s: lzma write error"), io->desc); + s.next_out = buf_out; + s.avail_out = sizeof(buf_out); + } + } while (ret != LZMA_STREAM_END); + + io->done(io, &s); + + if (close(fd_out)) + ohshite(_("%s: lzma close error"), io->desc); +} + +static void +filter_lzma_error(struct io_lzma *io, lzma_ret ret) +{ + ohshit(_("%s: lzma error: %s"), io->desc, + dpkg_lzma_strerror(ret, io->status)); +} + +static void +filter_unxz_init(struct io_lzma *io, lzma_stream *s) +{ + uint64_t memlimit = UINT64_MAX; + lzma_ret ret; + + io->status |= DPKG_STREAM_DECOMPRESS; + + ret = lzma_stream_decoder(s, memlimit, 0); + if (ret != LZMA_OK) + filter_lzma_error(io, ret); +} + +static void +filter_xz_init(struct io_lzma *io, lzma_stream *s) +{ + uint32_t preset; + lzma_ret ret; + + io->status |= DPKG_STREAM_COMPRESS; + + preset = io->params->level; + if (io->params->strategy == compressor_strategy_extreme) + preset |= LZMA_PRESET_EXTREME; + ret = lzma_easy_encoder(s, preset, LZMA_CHECK_CRC32); + if (ret != LZMA_OK) + filter_lzma_error(io, ret); +} + +static int +filter_lzma_code(struct io_lzma *io, lzma_stream *s) +{ + lzma_ret ret; + + ret = lzma_code(s, io->action); + if (ret != LZMA_OK && ret != LZMA_STREAM_END) + filter_lzma_error(io, ret); + + return ret; +} + +static void +filter_lzma_done(struct io_lzma *io, lzma_stream *s) +{ + lzma_end(s); +} + +static void +decompress_xz(int fd_in, int fd_out, const char *desc) +{ + struct io_lzma io; + + io.init = filter_unxz_init; + io.code = filter_lzma_code; + io.done = filter_lzma_done; + io.desc = desc; + + filter_lzma(&io, fd_in, fd_out); +} + +static void +compress_xz(int fd_in, int fd_out, struct compress_params *params, const char *desc) +{ + struct io_lzma io; + + io.init = filter_xz_init; + io.code = filter_lzma_code; + io.done = filter_lzma_done; + io.desc = desc; + io.params = params; + + filter_lzma(&io, fd_in, fd_out); +} +#else static void decompress_xz(int fd_in, int fd_out, const char *desc) { @@ -383,6 +577,7 @@ compress_xz(int fd_in, int fd_out, struct compress_params *params, const char *d snprintf(combuf, sizeof(combuf), "-c%d", params->level); fd_fd_filter(fd_in, fd_out, desc, XZ, combuf, strategy, NULL); } +#endif static const struct compressor compressor_xz = { .name = "xz", @@ -397,6 +592,67 @@ static const struct compressor compressor_xz = { * Lzma compressor. */ +#ifdef WITH_LIBLZMA +static void +filter_unlzma_init(struct io_lzma *io, lzma_stream *s) +{ + uint64_t memlimit = UINT64_MAX; + lzma_ret ret; + + io->status |= DPKG_STREAM_DECOMPRESS; + + ret = lzma_alone_decoder(s, memlimit); + if (ret != LZMA_OK) + filter_lzma_error(io, ret); +} + +static void +filter_lzma_init(struct io_lzma *io, lzma_stream *s) +{ + uint32_t preset; + lzma_options_lzma options; + lzma_ret ret; + + io->status |= DPKG_STREAM_COMPRESS; + + preset = io->params->level; + if (io->params->strategy == compressor_strategy_extreme) + preset |= LZMA_PRESET_EXTREME; + if (lzma_lzma_preset(&options, preset)) + filter_lzma_error(io, LZMA_OPTIONS_ERROR); + + ret = lzma_alone_encoder(s, &options); + if (ret != LZMA_OK) + filter_lzma_error(io, ret); +} + +static void +decompress_lzma(int fd_in, int fd_out, const char *desc) +{ + struct io_lzma io; + + io.init = filter_unlzma_init; + io.code = filter_lzma_code; + io.done = filter_lzma_done; + io.desc = desc; + + filter_lzma(&io, fd_in, fd_out); +} + +static void +compress_lzma(int fd_in, int fd_out, struct compress_params *params, const char *desc) +{ + struct io_lzma io; + + io.init = filter_lzma_init; + io.code = filter_lzma_code; + io.done = filter_lzma_done; + io.desc = desc; + io.params = params; + + filter_lzma(&io, fd_in, fd_out); +} +#else static void decompress_lzma(int fd_in, int fd_out, const char *desc) { @@ -411,6 +667,7 @@ compress_lzma(int fd_in, int fd_out, struct compress_params *params, const char snprintf(combuf, sizeof(combuf), "-c%d", params->level); fd_fd_filter(fd_in, fd_out, desc, XZ, combuf, "--format=lzma", NULL); } +#endif static const struct compressor compressor_lzma = { .name = "lzma", diff --git a/m4/dpkg-libs.m4 b/m4/dpkg-libs.m4 index 8a3134b..bbc096c 100644 --- a/m4/dpkg-libs.m4 +++ b/m4/dpkg-libs.m4 @@ -42,6 +42,13 @@ AC_DEFUN([DPKG_LIB_ZLIB], [ DPKG_WITH_COMPRESS_LIB([zlib], [zlib.h], [gzdopen], [z]) ])# DPKG_LIB_ZLIB +# DPKG_LIB_LZMA +# ------------- +# Check for lzma library. +AC_DEFUN([DPKG_LIB_LZMA], [ + DPKG_WITH_COMPRESS_LIB([liblzma], [lzma.h], [lzma_alone_decoder], [lzma]) +])# DPKG_LIB_LZMA + # DPKG_LIB_BZ2 # ------------ # Check for bz2 library. -- dpkg's main repository -- To UNSUBSCRIBE, email to debian-dpkg-cvs-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org