Skip to content

Commit ff88787

Browse files
committed
Support zstd compressed control files in debian packages
1 parent e79734a commit ff88787

1 file changed

Lines changed: 108 additions & 5 deletions

File tree

ext/repo_deb.c

Lines changed: 108 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@
1111
#include <stdlib.h>
1212
#include <string.h>
1313
#include <unistd.h>
14+
#include <errno.h>
15+
#ifdef ENABLE_ZLIB_COMPRESSION
1416
#include <zlib.h>
17+
#endif
18+
#ifdef ENABLE_LZMA_COMPRESSION
1519
#include <lzma.h>
16-
#include <errno.h>
20+
#endif
21+
#ifdef ENABLE_ZSTD_COMPRESSION
22+
#include <zstd.h>
23+
#endif
1724

1825
#include "pool.h"
1926
#include "repo.h"
@@ -30,6 +37,10 @@
3037
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
3138
#endif
3239

40+
#define MAX_CONTROL_SIZE 0x1000000
41+
42+
#ifdef ENABLE_ZLIB_COMPRESSION
43+
3344
static unsigned char *
3445
decompress_gz(unsigned char *in, int inl, int *outlp, int maxoutl)
3546
{
@@ -107,6 +118,18 @@ decompress_gz(unsigned char *in, int inl, int *outlp, int maxoutl)
107118
return out;
108119
}
109120

121+
#else
122+
123+
static unsigned char *
124+
decompress_gz(unsigned char *in, int inl, int *outlp, int maxoutl)
125+
{
126+
return 0;
127+
}
128+
129+
#endif /* ENABLE_ZLIB_COMPRESSION */
130+
131+
#ifdef ENABLE_LZMA_COMPRESSION
132+
110133
static unsigned char *
111134
decompress_xz(unsigned char *in, int inl, int *outlp, int maxoutl)
112135
{
@@ -159,6 +182,81 @@ decompress_xz(unsigned char *in, int inl, int *outlp, int maxoutl)
159182
return out;
160183
}
161184

185+
#else
186+
187+
static unsigned char *
188+
decompress_xz(unsigned char *in, int inl, int *outlp, int maxoutl)
189+
{
190+
return 0;
191+
}
192+
193+
#endif /* ENABLE_LZMA_COMPRESSION */
194+
195+
#ifdef ENABLE_ZSTD_COMPRESSION
196+
197+
static unsigned char *
198+
decompress_zstd(unsigned char *in, int inl, int *outlp, int maxoutl)
199+
{
200+
ZSTD_DStream *dstream;
201+
ZSTD_inBuffer inbuf;
202+
ZSTD_outBuffer outbuf;
203+
int ret;
204+
205+
dstream = ZSTD_createDStream();
206+
if (!dstream)
207+
return 0;
208+
if (ZSTD_isError(ZSTD_initDStream(dstream)))
209+
{
210+
ZSTD_freeDStream(dstream);
211+
return 0;
212+
}
213+
inbuf.src = in;
214+
inbuf.pos = 0;
215+
inbuf.size = inl;
216+
outbuf.dst = solv_malloc(4096);
217+
outbuf.pos = 0;
218+
outbuf.size = 4096;
219+
for (;;)
220+
{
221+
if (outbuf.pos == outbuf.size)
222+
{
223+
outbuf.size += 4096;
224+
if (outbuf.size >= maxoutl)
225+
{
226+
ret = 1;
227+
break;
228+
}
229+
outbuf.dst = solv_realloc(outbuf.dst, outbuf.size + 4096);
230+
}
231+
ret = ZSTD_decompressStream(dstream, &outbuf, &inbuf);
232+
if (ret == 0 && inbuf.pos == inbuf.size)
233+
break;
234+
if (ZSTD_isError(ret) || (inbuf.pos == inbuf.size && outbuf.pos < outbuf.size))
235+
{
236+
ret = 1;
237+
break;
238+
}
239+
}
240+
ZSTD_freeDStream(dstream);
241+
if (ret)
242+
{
243+
solv_free(outbuf.dst);
244+
return 0;
245+
}
246+
*outlp = outbuf.pos;
247+
return outbuf.dst;
248+
}
249+
250+
#else
251+
252+
static unsigned char *
253+
decompress_zstd(unsigned char *in, int inl, int *outlp, int maxoutl)
254+
{
255+
return 0;
256+
}
257+
258+
#endif /* ENABLE_ZSTD_COMPRESSION */
259+
162260
static Id
163261
parseonedep(Pool *pool, char *p)
164262
{
@@ -544,6 +642,7 @@ repo_add_debdb(Repo *repo, int flags)
544642
#define CONTROL_COMP_NONE 0
545643
#define CONTROL_COMP_GZIP 1
546644
#define CONTROL_COMP_XZ 2
645+
#define CONTROL_COMP_ZSTD 3
547646

548647
Id
549648
repo_add_deb(Repo *repo, const char *deb, int flags)
@@ -599,6 +698,8 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
599698
control_comp = CONTROL_COMP_GZIP;
600699
else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar.xz ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar.xz/ ", 16))
601700
control_comp = CONTROL_COMP_XZ;
701+
else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar.zst ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar.zst/", 16))
702+
control_comp = CONTROL_COMP_ZSTD;
602703
else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar/ ", 16))
603704
control_comp = CONTROL_COMP_NONE;
604705
else
@@ -611,7 +712,7 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
611712
* just keeps from allocating arbitrarily large amounts of memory.
612713
*/
613714
clen = atoi((char *)buf + 8 + 60 + vlen + 48);
614-
if (clen <= 0 || clen >= 0x1000000)
715+
if (clen <= 0 || clen >= MAX_CONTROL_SIZE)
615716
{
616717
pool_error(pool, -1, "%s: control.tar has illegal size", deb);
617718
fclose(fp);
@@ -645,9 +746,11 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
645746
}
646747
ctar = 0;
647748
if (control_comp == CONTROL_COMP_GZIP)
648-
ctar = decompress_gz(ctgz, clen, &ctarlen, 0x1000000);
749+
ctar = decompress_gz(ctgz, clen, &ctarlen, MAX_CONTROL_SIZE);
649750
else if (control_comp == CONTROL_COMP_XZ)
650-
ctar = decompress_xz(ctgz, clen, &ctarlen, 0x1000000);
751+
ctar = decompress_xz(ctgz, clen, &ctarlen, MAX_CONTROL_SIZE);
752+
else if (control_comp == CONTROL_COMP_ZSTD)
753+
ctar = decompress_zstd(ctgz, clen, &ctarlen, MAX_CONTROL_SIZE);
651754
else
652755
{
653756
ctarlen = clen;
@@ -656,7 +759,7 @@ repo_add_deb(Repo *repo, const char *deb, int flags)
656759
solv_free(ctgz);
657760
if (!ctar)
658761
{
659-
pool_error(pool, -1, "%s: control.tar is corrupt", deb);
762+
pool_error(pool, -1, "%s: control.tar decompression error", deb);
660763
return 0;
661764
}
662765
bp = ctar;

0 commit comments

Comments
 (0)