Blob Blame History Raw
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 */