diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c index cd223e8..f23fc11 100644 --- a/rpmio/rpmio.c +++ b/rpmio/rpmio.c @@ -5,6 +5,7 @@ #include "system.h" #include #include +#include #include #include @@ -873,7 +874,12 @@ static const char * getFdErrstr (FD_t fd) #include #include +#define LZMA_UNSTABLE #include +/* Multithreading support in stable API since xz 5.2.0 */ +#if LZMA_VERSION >= 50010020 +#define HAVE_LZMA_MT +#endif #define kBufferSize (1 << 15) @@ -897,7 +902,10 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int x LZFILE *lzfile; lzma_ret ret; lzma_stream init_strm = LZMA_STREAM_INIT; - + uint64_t mem_limit = rpmExpandNumeric("%{_xz_memlimit}"); +#ifdef HAVE_LZMA_MT + int threads = 0; +#endif for (; *mode; mode++) { if (*mode == 'w') encoding = 1; @@ -905,6 +913,21 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int x encoding = 0; else if (*mode >= '1' && *mode <= '9') level = *mode - '0'; + else if (*mode == 'T') { + if (isdigit(*(mode+1))) { +#ifdef HAVE_LZMA_MT + threads = atoi(++mode); +#endif + /* skip past rest of digits in string that atoi() + * should've processed + * */ + while(isdigit(*++mode)); + } +#ifdef HAVE_LZMA_MT + else + threads = -1; +#endif + } } if (fd != -1) fp = fdopen(fd, encoding ? "w" : "r"); @@ -924,16 +947,48 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int x lzfile->strm = init_strm; if (encoding) { if (xz) { - ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256); +#ifdef HAVE_LZMA_MT + if (!threads) { +#endif + ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256); +#ifdef HAVE_LZMA_MT + } else { + if (threads == -1) + threads = sysconf(_SC_NPROCESSORS_ONLN); + lzma_mt mt_options = { + .flags = 0, + .threads = threads, + .block_size = 0, + .timeout = 0, + .preset = level, + .filters = NULL, + .check = LZMA_CHECK_SHA256 }; + + ret = lzma_stream_encoder_mt(&lzfile->strm, &mt_options); + } +#endif } else { lzma_options_lzma options; lzma_lzma_preset(&options, level); ret = lzma_alone_encoder(&lzfile->strm, &options); } - } else { /* lzma_easy_decoder_memusage(level) is not ready yet, use hardcoded limit for now */ - ret = lzma_auto_decoder(&lzfile->strm, 100<<20, 0); + } else { /* lzma_easy_decoder_memusage(level) is not ready yet, use hardcoded limit for now */ + ret = lzma_auto_decoder(&lzfile->strm, mem_limit ? mem_limit : 100<<20, 0); } if (ret != LZMA_OK) { + switch (ret) { + case LZMA_MEM_ERROR: + rpmlog(RPMLOG_ERR, "liblzma: Memory allocation failed"); + break; + + case LZMA_DATA_ERROR: + rpmlog(RPMLOG_ERR, "liblzma: File size limits exceeded"); + break; + + default: + rpmlog(RPMLOG_ERR, "liblzma: