This commit is contained in:
2026-08-14 12:01:38 +02:00
commit 0bbc249155
21 changed files with 6786 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/* Minimal zstd decompressor for EROFS FreeBSD */
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include "internal.h"
#ifdef ZSTDIO
#define ZSTD_STATIC_LINKING_ONLY
#include <contrib/zstd/lib/zstd.h>
#endif
bool
erofs_zstd_available(void)
{
#ifdef ZSTDIO
return (true);
#else
return (false);
#endif
}
int
z_erofs_load_zstd_config(struct erofs_mount *em, const void *data,
size_t size)
{
const struct z_erofs_zstd_cfgs *zstd;
if (!erofs_zstd_available()) {
vfs_mount_error(em->mnt,
"erofs: ZSTD compression requires ZSTDIO support");
return (EOPNOTSUPP);
}
if (size < sizeof(*zstd))
return (EINVAL);
zstd = data;
if (zstd->format != 0 || zstd->windowlog > 10)
return (EOPNOTSUPP);
em->zstd_windowlog = zstd->windowlog;
return (0);
}
#ifdef ZSTDIO
static void *
zstd_alloc(void *opaque, size_t size)
{
return (malloc(size, opaque, M_WAITOK));
}
static void
zstd_free(void *opaque, void *address)
{
free(address, opaque);
}
static const ZSTD_customMem zstd_erofs_alloc = {
.customAlloc = zstd_alloc,
.customFree = zstd_free,
.opaque = M_EROFS,
};
int
zstd_decompress(void *src, size_t srclen, void *dst, size_t dstlen, int n,
bool partial)
{
ZSTD_DCtx *dctx;
ZSTD_inBuffer input;
ZSTD_outBuffer output;
size_t in_before, out_before, ret;
int error;
if (n < 10 || n > 20 || dstlen == 0)
return (-1);
dctx = ZSTD_createDCtx_advanced(zstd_erofs_alloc);
if (dctx == NULL)
return (-1);
ret = ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, n);
if (ZSTD_isError(ret)) {
ZSTD_freeDCtx(dctx);
return (-1);
}
input = (ZSTD_inBuffer) {
.src = src,
.size = srclen,
};
output = (ZSTD_outBuffer) {
.dst = dst,
.size = dstlen,
};
ret = 1;
while (output.pos != output.size) {
in_before = input.pos;
out_before = output.pos;
ret = ZSTD_decompressStream(dctx, &output, &input);
if (ZSTD_isError(ret) ||
(input.pos == in_before && output.pos == out_before))
break;
if (ret == 0)
break;
}
error = 0;
if (ZSTD_isError(ret) || output.pos != output.size)
error = -1;
else if (!partial && (ret != 0 || input.pos != input.size))
error = -1;
ret = ZSTD_freeDCtx(dctx);
if (ZSTD_isError(ret))
error = -1;
return (error);
}
#else
int
zstd_decompress(void *src, size_t srclen, void *dst, size_t dstlen, int n,
bool partial)
{
(void)src;
(void)srclen;
(void)dst;
(void)dstlen;
(void)n;
(void)partial;
return (-1);
}
#endif