Skip to content

Commit

Permalink
Support zstd compressed control files in debian packages
Browse files Browse the repository at this point in the history
  • Loading branch information
mlschroe committed Oct 18, 2021
1 parent e79734a commit ff88787
Showing 1 changed file with 108 additions and 5 deletions.
113 changes: 108 additions & 5 deletions ext/repo_deb.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef ENABLE_ZLIB_COMPRESSION
#include <zlib.h>
#endif
#ifdef ENABLE_LZMA_COMPRESSION
#include <lzma.h>
#include <errno.h>
#endif
#ifdef ENABLE_ZSTD_COMPRESSION
#include <zstd.h>
#endif

#include "pool.h"
#include "repo.h"
Expand All @@ -30,6 +37,10 @@
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif

#define MAX_CONTROL_SIZE 0x1000000

#ifdef ENABLE_ZLIB_COMPRESSION

static unsigned char *
decompress_gz(unsigned char *in, int inl, int *outlp, int maxoutl)
{
Expand Down Expand Up @@ -107,6 +118,18 @@ decompress_gz(unsigned char *in, int inl, int *outlp, int maxoutl)
return out;
}

#else

static unsigned char *
decompress_gz(unsigned char *in, int inl, int *outlp, int maxoutl)
{
return 0;
}

#endif /* ENABLE_ZLIB_COMPRESSION */

#ifdef ENABLE_LZMA_COMPRESSION

static unsigned char *
decompress_xz(unsigned char *in, int inl, int *outlp, int maxoutl)
{
Expand Down Expand Up @@ -159,6 +182,81 @@ decompress_xz(unsigned char *in, int inl, int *outlp, int maxoutl)
return out;
}

#else

static unsigned char *
decompress_xz(unsigned char *in, int inl, int *outlp, int maxoutl)
{
return 0;
}

#endif /* ENABLE_LZMA_COMPRESSION */

#ifdef ENABLE_ZSTD_COMPRESSION

static unsigned char *
decompress_zstd(unsigned char *in, int inl, int *outlp, int maxoutl)
{
ZSTD_DStream *dstream;
ZSTD_inBuffer inbuf;
ZSTD_outBuffer outbuf;
int ret;

dstream = ZSTD_createDStream();
if (!dstream)
return 0;
if (ZSTD_isError(ZSTD_initDStream(dstream)))
{
ZSTD_freeDStream(dstream);
return 0;
}
inbuf.src = in;
inbuf.pos = 0;
inbuf.size = inl;
outbuf.dst = solv_malloc(4096);
outbuf.pos = 0;
outbuf.size = 4096;
for (;;)
{
if (outbuf.pos == outbuf.size)
{
outbuf.size += 4096;
if (outbuf.size >= maxoutl)
{
ret = 1;
break;
}
outbuf.dst = solv_realloc(outbuf.dst, outbuf.size + 4096);
}
ret = ZSTD_decompressStream(dstream, &outbuf, &inbuf);
if (ret == 0 && inbuf.pos == inbuf.size)
break;
if (ZSTD_isError(ret) || (inbuf.pos == inbuf.size && outbuf.pos < outbuf.size))
{
ret = 1;
break;
}
}
ZSTD_freeDStream(dstream);
if (ret)
{
solv_free(outbuf.dst);
return 0;
}
*outlp = outbuf.pos;
return outbuf.dst;
}

#else

static unsigned char *
decompress_zstd(unsigned char *in, int inl, int *outlp, int maxoutl)
{
return 0;
}

#endif /* ENABLE_ZSTD_COMPRESSION */

static Id
parseonedep(Pool *pool, char *p)
{
Expand Down Expand Up @@ -544,6 +642,7 @@ repo_add_debdb(Repo *repo, int flags)
#define CONTROL_COMP_NONE 0
#define CONTROL_COMP_GZIP 1
#define CONTROL_COMP_XZ 2
#define CONTROL_COMP_ZSTD 3

Id
repo_add_deb(Repo *repo, const char *deb, int flags)
Expand Down Expand Up @@ -599,6 +698,8 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
control_comp = CONTROL_COMP_GZIP;
else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar.xz ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar.xz/ ", 16))
control_comp = CONTROL_COMP_XZ;
else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar.zst ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar.zst/", 16))
control_comp = CONTROL_COMP_ZSTD;
else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar/ ", 16))
control_comp = CONTROL_COMP_NONE;
else
Expand All @@ -611,7 +712,7 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
* just keeps from allocating arbitrarily large amounts of memory.
*/
clen = atoi((char *)buf + 8 + 60 + vlen + 48);
if (clen <= 0 || clen >= 0x1000000)
if (clen <= 0 || clen >= MAX_CONTROL_SIZE)
{
pool_error(pool, -1, "%s: control.tar has illegal size", deb);
fclose(fp);
Expand Down Expand Up @@ -645,9 +746,11 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
}
ctar = 0;
if (control_comp == CONTROL_COMP_GZIP)
ctar = decompress_gz(ctgz, clen, &ctarlen, 0x1000000);
ctar = decompress_gz(ctgz, clen, &ctarlen, MAX_CONTROL_SIZE);
else if (control_comp == CONTROL_COMP_XZ)
ctar = decompress_xz(ctgz, clen, &ctarlen, 0x1000000);
ctar = decompress_xz(ctgz, clen, &ctarlen, MAX_CONTROL_SIZE);
else if (control_comp == CONTROL_COMP_ZSTD)
ctar = decompress_zstd(ctgz, clen, &ctarlen, MAX_CONTROL_SIZE);
else
{
ctarlen = clen;
Expand All @@ -656,7 +759,7 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
solv_free(ctgz);
if (!ctar)
{
pool_error(pool, -1, "%s: control.tar is corrupt", deb);
pool_error(pool, -1, "%s: control.tar decompression error", deb);
return 0;
}
bp = ctar;
Expand Down

0 comments on commit ff88787

Please # to comment.