diff --git a/build/pack.c b/build/pack.c index 523367b..c3b1245 100644 --- a/build/pack.c +++ b/build/pack.c @@ -379,13 +379,20 @@ rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName, if (strcmp(s+1, "gzdio") == 0) { compr = "gzip"; +#if HAVE_BZLIB_H } else if (strcmp(s+1, "bzdio") == 0) { compr = "bzip2"; /* Add prereq on rpm version that understands bzip2 payloads */ (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1"); +#endif +#if HAVE_LZMA_H + } else if (strcmp(s+1, "xzdio") == 0) { + compr = "xz"; + (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1"); } else if (strcmp(s+1, "lzdio") == 0) { compr = "lzma"; - (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.90-1"); + (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1"); +#endif } else { rpmlog(RPMLOG_ERR, _("Unknown payload compression: %s\n"), rpmio_flags); diff --git a/build/parsePrep.c b/build/parsePrep.c index 52f192e..c14af1c 100644 --- a/build/parsePrep.c +++ b/build/parsePrep.c @@ -213,6 +213,9 @@ static char *doUntar(rpmSpec spec, uint32_t c, int quietly) case COMPRESSED_LZMA: t = "%{__lzma} -dc"; break; + case COMPRESSED_XZ: + t = "%{__xz} -dc"; + break; } zipper = rpmGetPath(t, NULL); if (needtar) { diff --git a/configure.ac b/configure.ac index a72dd3b..3c84b65 100644 --- a/configure.ac +++ b/configure.ac @@ -155,6 +155,7 @@ AC_SUBST(__ID_U) AC_PATH_PROG(__INSTALL, install, /usr/bin/install, $MYPATH) AC_PATH_PROG(__LZMA, lzma, /usr/bin/lzma, $MYPATH) +AC_PATH_PROG(__XZ, xz, /usr/bin/xz, $MYPATH) AC_PATH_PROG(__MAKE, make, /usr/bin/make, $MYPATH) AC_PATH_PROG(__MKDIR, mkdir, /bin/mkdir, $MYPATH) AC_PATH_PROG(__MV, mv, /bin/mv, $MYPATH) @@ -224,7 +225,7 @@ AC_SUBST(WITH_BZ2_LIB) # Check for lzma library. AC_CHECK_HEADERS([lzma.h],[ - AC_CHECK_LIB(lzma, lzma_auto_decoder, [WITH_LZMA_LIB=-llzma]) + AC_CHECK_LIB(lzma, lzma_easy_encoder, [WITH_LZMA_LIB=-llzma]) ]) AC_SUBST(WITH_LZMA_LIB) diff --git a/lib/psm.c b/lib/psm.c index 9070c6d..d476d14 100644 --- a/lib/psm.c +++ b/lib/psm.c @@ -1706,6 +1706,8 @@ assert(psm->mi == NULL); psm->rpmio_flags = "r.gzdio"; if (!strcmp(payload_compressor, "bzip2")) psm->rpmio_flags = "r.bzdio"; + if (!strcmp(payload_compressor, "xz")) + psm->rpmio_flags = "r.xzdio"; if (!strcmp(payload_compressor, "lzma")) psm->rpmio_flags = "r.lzdio"; rpmtdFreeData(&pc); diff --git a/lib/rpmds.c b/lib/rpmds.c index 6b59a6c..4f4b0cd 100644 --- a/lib/rpmds.c +++ b/lib/rpmds.c @@ -984,9 +984,14 @@ static const struct rpmlibProvides_s rpmlibProvides[] = { (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), N_("package payload can be compressed using bzip2.") }, #endif - { "rpmlib(PayloadIsLzma)", "4.4.90-1", +#if HAVE_LZMA_H + { "rpmlib(PayloadIsXz)", "5.2-1", + (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), + N_("package payload can be compressed using xz.") }, + { "rpmlib(PayloadIsLzma)", "4.4.2-1", (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), N_("package payload can be compressed using lzma.") }, +#endif { "rpmlib(PayloadFilesHavePrefix)", "4.0-1", (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), N_("package payload file(s) have \"./\" prefix.") }, diff --git a/macros.in b/macros.in index 28a048c..d0a4208 100644 --- a/macros.in +++ b/macros.in @@ -47,6 +47,7 @@ %__install @__INSTALL@ %__ln_s @LN_S@ %__lzma @__LZMA@ +%__xz @__XZ@ %__make @__MAKE@ %__mkdir @__MKDIR@ %__mkdir_p @MKDIR_P@ @@ -322,7 +323,8 @@ package or when debugging this package.\ # Compression type and level for source/binary package payloads. # "w9.gzdio" gzip level 9 (default). # "w9.bzdio" bzip2 level 9. -# "w7.lzdio" lzma level 7, lzma's default. +# "w7.xzdio" xz level 7, xz's default. +# "w7.lzdio" lzma-alone level 7, lzma's default # #%_source_payload w9.gzdio #%_binary_payload w9.gzdio diff --git a/rpm2cpio.c b/rpm2cpio.c index 6674a72..eabefa1 100644 --- a/rpm2cpio.c +++ b/rpm2cpio.c @@ -78,6 +78,8 @@ int main(int argc, char *argv[]) rpmio_flags = "r.gzdio"; if (!strcmp(payload_compressor, "bzip2")) rpmio_flags = "r.bzdio"; + if (!strcmp(payload_compressor, "xz")) + rpmio_flags = "r.xzdio"; if (!strcmp(payload_compressor, "lzma")) rpmio_flags = "r.lzdio"; rpmtdFreeData(&pc); diff --git a/rpmio/macro.c b/rpmio/macro.c index d1cbf93..9e7c3a5 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -981,6 +981,9 @@ doFoo(MacroBuf mb, int negate, const char * f, size_t fn, case COMPRESSED_LZMA: sprintf(be, "%%__lzma -dc %s", b); break; + case COMPRESSED_XZ: + sprintf(be, "%%__xz -dc %s", b); + break; } b = be; } else if (STREQ("S", f, fn)) { diff --git a/rpmio/rpmfileutil.c b/rpmio/rpmfileutil.c index de326e6..8286647 100644 --- a/rpmio/rpmfileutil.c +++ b/rpmio/rpmfileutil.c @@ -353,11 +353,11 @@ int rpmFileIsCompressed(const char * file, rpmCompressedMagic * compressed) } else if ((magic[0] == 0120) && (magic[1] == 0113) && (magic[2] == 0003) && (magic[3] == 0004)) { /* pkzip */ *compressed = COMPRESSED_ZIP; - } else if ((magic[0] == 0xff) && (magic[1] == 0x4c) && - (magic[2] == 0x5a) && (magic[3] == 0x4d) && - (magic[4] == 0x41) && (magic[5] == 0x00)) { - /* new style lzma with magic */ - *compressed = COMPRESSED_LZMA; + } else if ((magic[0] == 0xfd) && (magic[1] == 0x37) && + (magic[2] == 0x7a) && (magic[3] == 0x58) && + (magic[4] == 0x5a) && (magic[5] == 0x00)) { + /* new style xz (lzma) with magic */ + *compressed = COMPRESSED_XZ; } else if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */ ((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */ ((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */ diff --git a/rpmio/rpmfileutil.h b/rpmio/rpmfileutil.h index 7f92cbc..c39abf1 100644 --- a/rpmio/rpmfileutil.h +++ b/rpmio/rpmfileutil.h @@ -22,7 +22,8 @@ typedef enum rpmCompressedMagic_e { COMPRESSED_OTHER = 1, /*!< gzip can handle */ COMPRESSED_BZIP2 = 2, /*!< bzip2 can handle */ COMPRESSED_ZIP = 3, /*!< unzip can handle */ - COMPRESSED_LZMA = 4 /*!< lzma can handle */ + COMPRESSED_LZMA = 4, /*!< lzma can handle */ + COMPRESSED_XZ = 5 /*!< xz can handle */ } rpmCompressedMagic; /** \ingroup rpmfileutil diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c index be9e99d..78a86c8 100644 --- a/rpmio/rpmio.c +++ b/rpmio/rpmio.c @@ -36,7 +36,7 @@ extern int h_errno; #define FDONLY(fd) assert(fdGetIo(fd) == fdio) #define GZDONLY(fd) assert(fdGetIo(fd) == gzdio) #define BZDONLY(fd) assert(fdGetIo(fd) == bzdio) -#define LZDONLY(fd) assert(fdGetIo(fd) == lzdio) +#define LZDONLY(fd) assert(fdGetIo(fd) == xzdio || fdGetIo(fd) == lzdio) #define UFDONLY(fd) /* assert(fdGetIo(fd) == ufdio) */ @@ -91,6 +91,7 @@ static const FDIO_t fpio; static const FDIO_t ufdio; static const FDIO_t gzdio; static const FDIO_t bzdio; +static const FDIO_t xzdio; static const FDIO_t lzdio; /** @@ -140,6 +141,8 @@ static const char * fdbg(FD_t fd) sprintf(be, "BZD %p fdno %d", fps->fp, fps->fdno); #endif #if HAVE_LZMA_H + } else if (fps->io == xzdio) { + sprintf(be, "XZD %p fdno %d", fps->fp, fps->fdno); } else if (fps->io == lzdio) { sprintf(be, "LZD %p fdno %d", fps->fp, fps->fdno); #endif @@ -1158,7 +1161,7 @@ static const char * getFdErrstr (FD_t fd) } else #endif /* HAVE_BZLIB_H */ #ifdef HAVE_LZMA_H - if (fdGetIo(fd) == lzdio) { + if (fdGetIo(fd) == xzdio || fdGetIo(fd) == lzdio) { errstr = fd->errcookie; } else #endif /* HAVE_LZMA_H */ @@ -1194,13 +1197,14 @@ typedef struct lzfile { } LZFILE; -static LZFILE *lzopen_internal(const char *path, const char *mode, int fd) +static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int xz) { - int level = 5; + int level = 7; /* Use XZ's default compression level if unspecified */ int encoding = 0; FILE *fp; LZFILE *lzfile; lzma_ret ret; + lzma_stream init_strm = LZMA_STREAM_INIT; for (; *mode; mode++) { if (*mode == 'w') @@ -1221,17 +1225,21 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd) fclose(fp); return 0; } + lzfile->file = fp; lzfile->encoding = encoding; lzfile->eof = 0; - lzfile->strm = LZMA_STREAM_INIT_VAR; + lzfile->strm = init_strm; if (encoding) { - lzma_options_alone alone; - alone.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN; - memcpy(&alone.lzma, &lzma_preset_lzma[level - 1], sizeof(alone.lzma)); - ret = lzma_alone_encoder(&lzfile->strm, &alone); - } else { - ret = lzma_auto_decoder(&lzfile->strm, 0, 0); + if (xz) { + ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256); + } 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); } if (ret != LZMA_OK) { fclose(fp); @@ -1241,16 +1249,28 @@ static LZFILE *lzopen_internal(const char *path, const char *mode, int fd) return lzfile; } +static LZFILE *xzopen(const char *path, const char *mode) +{ + return lzopen_internal(path, mode, -1, 1); +} + +static LZFILE *xzdopen(int fd, const char *mode) +{ + if (fd < 0) + return 0; + return lzopen_internal(0, mode, fd, 1); +} + static LZFILE *lzopen(const char *path, const char *mode) { - return lzopen_internal(path, mode, -1); + return lzopen_internal(path, mode, -1, 0); } static LZFILE *lzdopen(int fd, const char *mode) { if (fd < 0) return 0; - return lzopen_internal(0, mode, fd); + return lzopen_internal(0, mode, fd, 0); } static int lzflush(LZFILE *lzfile) @@ -1352,7 +1372,7 @@ static inline void * lzdFileno(FD_t fd) FDSANE(fd); for (i = fd->nfps; i >= 0; i--) { FDSTACK_t * fps = &fd->fps[i]; - if (fps->io != lzdio) + if (fps->io != xzdio && fps->io != lzdio) continue; rc = fps->fp; break; @@ -1361,6 +1381,33 @@ static inline void * lzdFileno(FD_t fd) return rc; } +static FD_t xzdOpen(const char * path, const char * mode) +{ + FD_t fd; + LZFILE *lzfile; + if ((lzfile = xzopen(path, mode)) == NULL) + return NULL; + fd = fdNew("open (xzdOpen)"); + fdPop(fd); fdPush(fd, xzdio, lzfile, -1); + return fdLink(fd, "xzdOpen"); +} + +static FD_t xzdFdopen(void * cookie, const char * fmode) +{ + FD_t fd = c2f(cookie); + int fdno; + LZFILE *lzfile; + + if (fmode == NULL) return NULL; + fdno = fdFileno(fd); + fdSetFdno(fd, -1); /* XXX skip the fdio close */ + if (fdno < 0) return NULL; + lzfile = xzdopen(fdno, fmode); + if (lzfile == NULL) return NULL; + fdPush(fd, xzdio, lzfile, fdno); + return fdLink(fd, "xzdFdopen"); +} + static FD_t lzdOpen(const char * path, const char * mode) { FD_t fd; @@ -1368,7 +1415,7 @@ static FD_t lzdOpen(const char * path, const char * mode) if ((lzfile = lzopen(path, mode)) == NULL) return NULL; fd = fdNew("open (lzdOpen)"); - fdPop(fd); fdPush(fd, lzdio, lzfile, -1); + fdPop(fd); fdPush(fd, xzdio, lzfile, -1); return fdLink(fd, "lzdOpen"); } @@ -1384,7 +1431,7 @@ static FD_t lzdFdopen(void * cookie, const char * fmode) if (fdno < 0) return NULL; lzfile = lzdopen(fdno, fmode); if (lzfile == NULL) return NULL; - fdPush(fd, lzdio, lzfile, fdno); + fdPush(fd, xzdio, lzfile, fdno); return fdLink(fd, "lzdFdopen"); } @@ -1468,17 +1515,22 @@ static int lzdClose(void * cookie) DBGIO(fd, (stderr, "==>\tlzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd))); - if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "LZDIO", stderr); + if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "XZDIO", stderr); if (rc == 0) fd = fdFree(fd, "open (lzdClose)"); return rc; } +static struct FDIO_s xzdio_s = { + lzdRead, lzdWrite, lzdSeek, lzdClose, NULL, NULL, NULL, fdFileno, + NULL, xzdOpen, lzdFileno, lzdFlush +}; +static const FDIO_t xzdio = &xzdio_s; + static struct FDIO_s lzdio_s = { lzdRead, lzdWrite, lzdSeek, lzdClose, NULL, NULL, NULL, fdFileno, NULL, lzdOpen, lzdFileno, lzdFlush }; - static const FDIO_t lzdio = &lzdio_s; #endif /* HAVE_LZMA_H */ @@ -1716,6 +1768,9 @@ fprintf(stderr, "*** Fdopen(%p,%s) %s\n", fd, fmode, fdbg(fd)); fd = bzdFdopen(fd, zstdio); #endif #if HAVE_LZMA_H + } else if (!strcmp(end, "xzdio")) { + iof = xzdio; + fd = xzdFdopen(fd, zstdio); } else if (!strcmp(end, "lzdio")) { iof = lzdio; fd = lzdFdopen(fd, zstdio); @@ -1847,7 +1902,7 @@ int Fflush(FD_t fd) return bzdFlush(vh); #endif #if HAVE_LZMA_H - if (vh && fdGetIo(fd) == lzdio) + if (vh && (fdGetIo(fd) == xzdio || fdGetIo(fd) == lzdio)) return lzdFlush(vh); #endif /* FIXME: If we get here, something went wrong above */ @@ -1876,9 +1931,9 @@ int Ferror(FD_t fd) i--; /* XXX fdio under bzdio always has fdno == -1 */ #endif #if HAVE_LZMA_H - } else if (fps->io == lzdio) { + } else if (fps->io == xzdio || fps->io == lzdio) { ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0; - i--; /* XXX fdio under lzdio always has fdno == -1 */ + i--; /* XXX fdio under xzdio/lzdio always has fdno == -1 */ #endif } else { /* XXX need to check ufdio/gzdio/bzdio/fdio errors correctly. */ diff --git a/rpmio/rpmio_internal.h b/rpmio/rpmio_internal.h index 25c6d5b..a6a6252 100644 --- a/rpmio/rpmio_internal.h +++ b/rpmio/rpmio_internal.h @@ -53,7 +53,7 @@ struct _FD_s { ssize_t bytesRemain; /* ufdio: */ int syserrno; /* last system errno encountered */ - const void *errcookie; /* gzdio/bzdio/ufdio: */ + const void *errcookie; /* gzdio/bzdio/ufdio/xzdio: */ FDSTAT_t stats; /* I/O statistics */