test code v1

This commit is contained in:
2026-08-13 10:48:49 +02:00
parent f3b1165f19
commit f6aeadb22d
300 changed files with 0 additions and 31306 deletions
+204
View File
@@ -0,0 +1,204 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2019 HUAWEI, Inc.
* https://www.huawei.com/
* Copyright (C) 2024 Alibaba Cloud
*/
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include "internal.h"
static int
z_erofs_load_lz4_config(struct erofs_mount *em,
const struct erofs_super_block *dsb, const void *data, size_t size)
{
const struct z_erofs_lz4_cfgs *lz4;
uint32_t max_pclusterblks;
uint16_t distance;
if (data != NULL) {
if (size < sizeof(*lz4))
return (EINVAL);
lz4 = data;
distance = le16toh(lz4->max_distance);
max_pclusterblks = le16toh(lz4->max_pclusterblks);
if (max_pclusterblks == 0)
max_pclusterblks = 1;
else if (max_pclusterblks >
(Z_EROFS_PCLUSTER_MAX_SIZE >> em->block_bits))
return (EINVAL);
} else {
distance = le16toh(dsb->u1.lz4_max_distance);
if (distance == 0 && !erofs_sb_has_lz4_0padding(em))
return (0);
max_pclusterblks = 1;
em->available_compr_algs = 1U << Z_EROFS_COMPRESSION_LZ4;
}
em->lz4.max_pclusterblks = max_pclusterblks;
em->lz4.max_distance_pages = distance != 0 ?
howmany(distance, PAGE_SIZE) + 1 :
howmany(UINT16_MAX, PAGE_SIZE) + 1;
return (0);
}
static int
z_erofs_read_cfg(struct erofs_mount *em, uint64_t *offset, void **bufp,
size_t *sizep)
{
uint8_t length_buf[2];
uint64_t aligned;
uint16_t length;
void *buf;
int error;
aligned = roundup2(*offset, 4);
if (aligned > UINT64_MAX - sizeof(length_buf))
return (EOVERFLOW);
error = erofs_bread(em, aligned, sizeof(length_buf), &buf);
if (error != 0)
return (error);
memcpy(length_buf, buf, sizeof(length_buf));
erofs_brelse(buf);
length = le16dec(length_buf);
*sizep = length != 0 ? length : UINT16_MAX + 1U;
if (*sizep > 65536 || aligned + sizeof(length_buf) >
UINT64_MAX - *sizep)
return (EOVERFLOW);
*offset = aligned + sizeof(length_buf);
error = erofs_bread(em, *offset, *sizep, bufp);
if (error == 0)
*offset += *sizep;
return (error);
}
int
z_erofs_parse_cfgs(struct erofs_mount *em,
const struct erofs_super_block *dsb)
{
uint64_t offset;
uint16_t algorithms;
void *data;
size_t size;
int algorithm, error;
if (!erofs_sb_has_compr_cfgs(em))
return (z_erofs_load_lz4_config(em, dsb, NULL, 0));
algorithms = le16toh(dsb->u1.available_compr_algs);
em->available_compr_algs = algorithms;
if ((algorithms & ~Z_EROFS_ALL_COMPR_ALGS) != 0)
return (EOPNOTSUPP);
offset = EROFS_SUPER_OFFSET + em->sb_size;
for (algorithm = 0; algorithm < Z_EROFS_COMPRESSION_MAX;
++algorithm) {
if ((algorithms & (1U << algorithm)) == 0)
continue;
error = z_erofs_read_cfg(em, &offset, &data, &size);
if (error != 0)
return (error);
switch (algorithm) {
case Z_EROFS_COMPRESSION_LZ4:
error = z_erofs_load_lz4_config(em, dsb, data, size);
break;
case Z_EROFS_COMPRESSION_LZMA:
error = z_erofs_load_lzma_config(em, data, size);
break;
case Z_EROFS_COMPRESSION_DEFLATE:
error = z_erofs_load_deflate_config(em, data, size);
break;
case Z_EROFS_COMPRESSION_ZSTD:
error = z_erofs_load_zstd_config(em, data, size);
break;
default:
error = EOPNOTSUPP;
break;
}
erofs_brelse(data);
if (error != 0)
return (error);
}
return (0);
}
static int
z_erofs_transform_plain(struct erofs_mount *em,
const struct erofs_map_blocks *map, const uint8_t *src, size_t srclen,
uint8_t *dst, size_t dstlen)
{
size_t first, offset;
if (dstlen > srclen)
return (EINTEGRITY);
if (map->m_algorithmformat == Z_EROFS_COMPRESSION_SHIFTED) {
memmove(dst, src, dstlen);
return (0);
}
first = MIN((size_t)(em->block_size -
(map->m_la & (em->block_size - 1))), dstlen);
offset = (srclen - first) & (em->block_size - 1);
if (offset > srclen || first > srclen - offset)
return (EINTEGRITY);
memmove(dst, src + offset, first);
if (first < dstlen)
memmove(dst + first, src, dstlen - first);
return (0);
}
int
z_erofs_decompress(struct erofs_mount *em,
const struct erofs_map_blocks *map, const void *src0, size_t srclen,
void *dst, size_t dstlen, bool partial)
{
const uint8_t *src;
size_t padding, padding_limit;
int ret;
if (map->m_algorithmformat == Z_EROFS_COMPRESSION_SHIFTED ||
map->m_algorithmformat == Z_EROFS_COMPRESSION_INTERLACED)
return (z_erofs_transform_plain(em, map, src0, srclen, dst,
dstlen));
if ((unsigned char)map->m_algorithmformat >= Z_EROFS_COMPRESSION_MAX)
return (EOPNOTSUPP);
src = src0;
if (map->m_algorithmformat != Z_EROFS_COMPRESSION_LZ4 ||
erofs_sb_has_lz4_0padding(em)) {
padding_limit = MIN(srclen, em->block_size -
(map->m_pa & (em->block_size - 1)));
for (padding = 0; padding < padding_limit && src[padding] == 0;
++padding)
;
if (padding == padding_limit)
return (EINTEGRITY);
src += padding;
srclen -= padding;
}
switch (map->m_algorithmformat) {
case Z_EROFS_COMPRESSION_LZ4:
ret = lz4_decompress(__DECONST(void *, src), dst, srclen,
dstlen, partial);
break;
case Z_EROFS_COMPRESSION_LZMA:
if (em->lzma_dict_size == 0)
return (EINTEGRITY);
ret = lzma_decompress(src, srclen, dst, dstlen,
em->lzma_dict_size, partial);
break;
case Z_EROFS_COMPRESSION_DEFLATE:
ret = deflate_decompress(__DECONST(void *, src), srclen, dst,
dstlen, em->deflate_windowbits, partial);
break;
case Z_EROFS_COMPRESSION_ZSTD:
ret = zstd_decompress(__DECONST(void *, src), srclen, dst,
dstlen, em->zstd_windowlog + 10, partial);
break;
default:
return (EOPNOTSUPP);
}
return (ret == 0 ? 0 : EIO);
}