OPTION (ENABLE_LZMA_COMPRESSION "Build with lzma/xz compression support?" OFF)
OPTION (ENABLE_BZIP2_COMPRESSION "Build with bzip2 compression support?" OFF)
+OPTION (ENABLE_ZSTD_COMPRESSION "Build with zstd compression support?" OFF)
OPTION (WITH_LIBXML2 "Build with libxml2 instead of libexpat?" OFF)
FIND_PACKAGE (BZip2 REQUIRED)
ENDIF (ENABLE_BZIP2_COMPRESSION)
+IF (ENABLE_ZSTD_COMPRESSION)
+FIND_LIBRARY (ZSTD_LIBRARY NAMES zstd)
+ENDIF (ENABLE_ZSTD_COMPRESSION)
+
IF (RPM5)
MESSAGE (STATUS "Enabling RPM 5 support")
ADD_DEFINITIONS (-DRPM5)
ENABLE_SUSEREPO ENABLE_COMPS ENABLE_TESTCASE_HELIXREPO
ENABLE_HELIXREPO ENABLE_MDKREPO ENABLE_ARCHREPO ENABLE_DEBIAN ENABLE_HAIKU
ENABLE_ZLIB_COMPRESSION ENABLE_LZMA_COMPRESSION ENABLE_BZIP2_COMPRESSION
- ENABLE_PGPVRFY ENABLE_APPDATA)
+ ENABLE_ZSTD_COMPRESSION ENABLE_PGPVRFY ENABLE_APPDATA)
IF(${VAR})
ADD_DEFINITIONS (-D${VAR}=1)
SET (SWIG_FLAGS ${SWIG_FLAGS} -D${VAR})
IF (ENABLE_BZIP2_COMPRESSION)
SET (SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${BZIP2_LIBRARIES})
ENDIF (ENABLE_BZIP2_COMPRESSION)
+IF (ENABLE_ZSTD_COMPRESSION)
+SET (SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${ZSTD_LIBRARY})
+ENDIF (ENABLE_ZSTD_COMPRESSION)
IF (ENABLE_RPMDB)
SET (SYSTEM_LIBRARIES ${RPMDB_LIBRARY} ${SYSTEM_LIBRARIES})
ENDIF (ENABLE_RPMDB)
#endif /* ENABLE_LZMA_COMPRESSION */
+#ifdef ENABLE_ZSTD_COMPRESSION
+
+#include <zstd.h>
+
+typedef struct zstdfile {
+ ZSTD_CStream *cstream;
+ ZSTD_DStream *dstream;
+ FILE *file;
+ int encoding;
+ int eof;
+ ZSTD_inBuffer in;
+ ZSTD_outBuffer out;
+ unsigned char buf[1 << 15];
+} ZSTDFILE;
+
+static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd)
+{
+ int level = 7;
+ int encoding = 0;
+ FILE *fp;
+ ZSTDFILE *zstdfile;
+
+ if (!path && fd < 0)
+ return 0;
+ for (; *mode; mode++)
+ {
+ if (*mode == 'w')
+ encoding = 1;
+ else if (*mode == 'r')
+ encoding = 0;
+ else if (*mode >= '1' && *mode <= '9')
+ level = *mode - '0';
+ }
+ if (fd != -1)
+ fp = fdopen(fd, encoding ? "w" : "r");
+ else
+ fp = fopen(path, encoding ? "w" : "r");
+ if (!fp)
+ return 0;
+ zstdfile = solv_calloc(1, sizeof(*zstdfile));
+ zstdfile->encoding = encoding;
+ if (encoding)
+ {
+ zstdfile->cstream = ZSTD_createCStream();
+ zstdfile->encoding = 1;
+ if (!zstdfile->cstream)
+ {
+ solv_free(zstdfile);
+ fclose(fp);
+ return 0;
+ }
+ if (ZSTD_isError(ZSTD_initCStream(zstdfile->cstream, level)))
+ {
+ ZSTD_freeCStream(zstdfile->cstream);
+ solv_free(zstdfile);
+ fclose(fp);
+ return 0;
+ }
+ zstdfile->out.dst = zstdfile->buf;
+ zstdfile->out.pos = 0;
+ zstdfile->out.size = sizeof(zstdfile->buf);
+ }
+ else
+ {
+ zstdfile->dstream = ZSTD_createDStream();
+ if (ZSTD_isError(ZSTD_initDStream(zstdfile->dstream)))
+ {
+ ZSTD_freeDStream(zstdfile->dstream);
+ solv_free(zstdfile);
+ fclose(fp);
+ return 0;
+ }
+ zstdfile->in.src = zstdfile->buf;
+ zstdfile->in.pos = 0;
+ zstdfile->in.size = 0;
+ }
+ zstdfile->file = fp;
+ return zstdfile;
+}
+
+static int zstdclose(void *cookie)
+{
+ ZSTDFILE *zstdfile = cookie;
+ int rc;
+
+ if (!zstdfile)
+ return -1;
+ if (zstdfile->encoding)
+ {
+ for (;;)
+ {
+ size_t ret;
+ zstdfile->out.pos = 0;
+ ret = ZSTD_endStream(zstdfile->cstream, &zstdfile->out);
+ if (ZSTD_isError(ret))
+ return -1;
+ if (zstdfile->out.pos && fwrite(zstdfile->buf, 1, zstdfile->out.pos, zstdfile->file) != zstdfile->out.pos)
+ return -1;
+ if (ret == 0)
+ break;
+ }
+ ZSTD_freeCStream(zstdfile->cstream);
+ }
+ else
+ {
+ ZSTD_freeDStream(zstdfile->dstream);
+ }
+ rc = fclose(zstdfile->file);
+ free(zstdfile);
+ return rc;
+}
+
+static ssize_t zstdread(void *cookie, char *buf, size_t len)
+{
+ ZSTDFILE *zstdfile = cookie;
+ int eof = 0;
+ size_t ret = 0;
+ if (!zstdfile || zstdfile->encoding)
+ return -1;
+ if (zstdfile->eof)
+ return 0;
+ zstdfile->out.dst = buf;
+ zstdfile->out.pos = 0;
+ zstdfile->out.size = len;
+ for (;;)
+ {
+ if (!eof && zstdfile->in.pos == zstdfile->in.size)
+ {
+ zstdfile->in.pos = 0;
+ zstdfile->in.size = fread(zstdfile->buf, 1, sizeof(zstdfile->buf), zstdfile->file);
+ if (!zstdfile->in.size)
+ eof = 1;
+ }
+ if (ret || !eof)
+ ret = ZSTD_decompressStream(zstdfile->dstream, &zstdfile->out, &zstdfile->in);
+ if (ret == 0 && eof)
+ {
+ zstdfile->eof = 1;
+ return zstdfile->out.pos;
+ }
+ if (ZSTD_isError(ret))
+ return -1;
+ if (zstdfile->out.pos == len)
+ return len;
+ }
+}
+
+static ssize_t zstdwrite(void *cookie, const char *buf, size_t len)
+{
+ ZSTDFILE *zstdfile = cookie;
+ if (!zstdfile || !zstdfile->encoding)
+ return -1;
+ if (!len)
+ return 0;
+ zstdfile->in.src = buf;
+ zstdfile->in.pos = 0;
+ zstdfile->in.size = len;
+
+ for (;;)
+ {
+ size_t ret;
+ zstdfile->out.pos = 0;
+ ret = ZSTD_compressStream(zstdfile->cstream, &zstdfile->out, &zstdfile->in);
+ if (ZSTD_isError(ret))
+ return -1;
+ if (zstdfile->out.pos && fwrite(zstdfile->buf, 1, zstdfile->out.pos, zstdfile->file) != zstdfile->out.pos)
+ return -1;
+ if (zstdfile->in.pos == len)
+ return len;
+ }
+}
+
+static inline FILE *myzstdfopen(const char *fn, const char *mode)
+{
+ ZSTDFILE *zstdfile = zstdopen(fn, mode, -1);
+ return cookieopen(zstdfile, mode, zstdread, zstdwrite, zstdclose);
+}
+
+static inline FILE *myzstdfdopen(int fd, const char *mode)
+{
+ ZSTDFILE *zstdfile = zstdopen(0, mode, fd);
+ return cookieopen(zstdfile, mode, zstdread, zstdwrite, zstdclose);
+}
+
+#endif
FILE *
solv_xfopen(const char *fn, const char *mode)
#else
if (suf && !strcmp(suf, ".bz2"))
return 0;
+#endif
+#ifdef ENABLE_ZSTD_COMPRESSION
+ if (suf && !strcmp(suf, ".zst"))
+ return myzstdfopen(fn, mode);
+#else
+ if (suf && !strcmp(suf, ".zst"))
+ return 0;
#endif
return fopen(fn, mode);
}
#else
if (suf && !strcmp(suf, ".bz2"))
return 0;
+#endif
+#ifdef ENABLE_ZSTD_COMPRESSION
+ if (suf && !strcmp(suf, ".zst"))
+ return myzstdfdopen(fd, simplemode);
+#else
+ if (suf && !strcmp(suf, ".zst"))
+ return 0;
#endif
return fdopen(fd, mode);
}
return 1;
#else
return -1;
+#endif
+ if (!strcmp(suf, ".zst"))
+#ifdef ENABLE_ZSTD_COMPRESSION
+ return 1;
+#else
+ return -1;
#endif
return 0;
}