From bfdacb712c9a95b5c61857b2b3a7dd3cfd0faf3b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Feb 2016 21:26:28 +0100 Subject: decompressXZ: Ensure that lzma_end() is called Otherwise we might leak memory. --- src/libutil/compression.cc | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'src/libutil/compression.cc') diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index fb4160669a29..eaaaf246b18d 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -6,34 +6,43 @@ namespace nix { +/* RAII wrapper around lzma_stream. */ +struct LzmaStream +{ + lzma_stream strm; + LzmaStream() : strm(LZMA_STREAM_INIT) { }; + ~LzmaStream() { lzma_end(&strm); }; + lzma_stream & operator()() { return strm; } +}; + std::string decompressXZ(const std::string & in) { - lzma_stream strm = LZMA_STREAM_INIT; + LzmaStream strm; lzma_ret ret = lzma_stream_decoder( - &strm, UINT64_MAX, LZMA_CONCATENATED); + &strm(), UINT64_MAX, LZMA_CONCATENATED); if (ret != LZMA_OK) throw Error("unable to initialise lzma decoder"); lzma_action action = LZMA_RUN; uint8_t outbuf[BUFSIZ]; string res; - strm.next_in = (uint8_t *) in.c_str(); - strm.avail_in = in.size(); - strm.next_out = outbuf; - strm.avail_out = sizeof(outbuf); + strm().next_in = (uint8_t *) in.c_str(); + strm().avail_in = in.size(); + strm().next_out = outbuf; + strm().avail_out = sizeof(outbuf); while (true) { - if (strm.avail_in == 0) + if (strm().avail_in == 0) action = LZMA_FINISH; - lzma_ret ret = lzma_code(&strm, action); + lzma_ret ret = lzma_code(&strm(), action); - if (strm.avail_out == 0 || ret == LZMA_STREAM_END) { - res.append((char *) outbuf, sizeof(outbuf) - strm.avail_out); - strm.next_out = outbuf; - strm.avail_out = sizeof(outbuf); + if (strm().avail_out == 0 || ret == LZMA_STREAM_END) { + res.append((char *) outbuf, sizeof(outbuf) - strm().avail_out); + strm().next_out = outbuf; + strm().avail_out = sizeof(outbuf); } if (ret == LZMA_STREAM_END) -- cgit 1.4.1 From eff5021eaa6dc69f65ea1a8abe8f3ab11ef5eb0a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 15 Feb 2016 21:45:56 +0100 Subject: Add xz compression function This is used by the Hydra queue runner, but since it may also be useful for the C++ rewrite of nix-push, I'm putting it here. --- src/libutil/compression.cc | 40 ++++++++++++++++++++++++++++++++++++++++ src/libutil/compression.hh | 2 ++ 2 files changed, 42 insertions(+) (limited to 'src/libutil/compression.cc') diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index eaaaf246b18d..a3fa0dab737b 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -15,6 +15,46 @@ struct LzmaStream lzma_stream & operator()() { return strm; } }; +std::string compressXZ(const std::string & in) +{ + LzmaStream strm; + + // FIXME: apply the x86 BCJ filter? + + lzma_ret ret = lzma_easy_encoder( + &strm(), 6, LZMA_CHECK_CRC64); + if (ret != LZMA_OK) + throw Error("unable to initialise lzma encoder"); + + lzma_action action = LZMA_RUN; + uint8_t outbuf[BUFSIZ]; + string res; + strm().next_in = (uint8_t *) in.c_str(); + strm().avail_in = in.size(); + strm().next_out = outbuf; + strm().avail_out = sizeof(outbuf); + + while (true) { + + if (strm().avail_in == 0) + action = LZMA_FINISH; + + lzma_ret ret = lzma_code(&strm(), action); + + if (strm().avail_out == 0 || ret == LZMA_STREAM_END) { + res.append((char *) outbuf, sizeof(outbuf) - strm().avail_out); + strm().next_out = outbuf; + strm().avail_out = sizeof(outbuf); + } + + if (ret == LZMA_STREAM_END) + return res; + + if (ret != LZMA_OK) + throw Error("error while decompressing xz file"); + } +} + std::string decompressXZ(const std::string & in) { LzmaStream strm; diff --git a/src/libutil/compression.hh b/src/libutil/compression.hh index 962ce5ac7767..eb1697fc4aa4 100644 --- a/src/libutil/compression.hh +++ b/src/libutil/compression.hh @@ -4,6 +4,8 @@ namespace nix { +std::string compressXZ(const std::string & in); + std::string decompressXZ(const std::string & in); } -- cgit 1.4.1