Enable LZMA compression for secondary DDT and manage memory allocation

This commit is contained in:
2025-10-06 23:42:05 +01:00
parent 173ecc6698
commit e5b9ebd92b

View File

@@ -1305,11 +1305,11 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo
// Prepare DDT header for the never-written cached table
memset(&ddt_header, 0, sizeof(DdtHeader2));
ddt_header.identifier = DeDuplicationTable2;
ddt_header.type = UserData;
ddt_header.compression = None; // Use no compression for simplicity
ddt_header.levels = ctx->userDataDdtHeader.levels;
ddt_header.tableLevel = ctx->userDataDdtHeader.tableLevel + 1;
ddt_header.identifier = DeDuplicationTable2;
ddt_header.type = UserData;
ddt_header.compression = ctx->compression_enabled ? Lzma : None; // Use no compression for simplicity
ddt_header.levels = ctx->userDataDdtHeader.levels;
ddt_header.tableLevel = ctx->userDataDdtHeader.tableLevel + 1;
ddt_header.previousLevelOffset = ctx->primaryDdtOffset;
ddt_header.negative = ctx->userDataDdtHeader.negative;
ddt_header.blocks = items_per_ddt_entry;
@@ -1327,8 +1327,6 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo
else
ddt_header.length = items_per_ddt_entry * sizeof(uint32_t);
ddt_header.cmpLength = ddt_header.length;
// Calculate CRC64 of the data
crc64_context = aaruf_crc64_init();
if(crc64_context == NULL)
@@ -1339,13 +1337,63 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo
}
if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType)
aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtSmall, ddt_header.length);
aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtSmall, (uint32_t)ddt_header.length);
else
aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtBig, ddt_header.length);
aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtBig, (uint32_t)ddt_header.length);
aaruf_crc64_final(crc64_context, &crc64);
ddt_header.crc64 = crc64;
ddt_header.cmpCrc64 = crc64;
ddt_header.crc64 = crc64;
uint8_t *cmp_buffer = NULL;
uint8_t lzma_properties[LZMA_PROPERTIES_LENGTH] = {0};
if(ddt_header.compression == None)
{
if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType)
cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtSmall;
else
cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig;
ddt_header.cmpCrc64 = ddt_header.crc64;
}
else
{
cmp_buffer = malloc((size_t)ddt_header.length * 2); // Allocate double size for compression
if(cmp_buffer == NULL)
{
TRACE("Failed to allocate memory for secondary DDT v2 compression");
return AARUF_ERROR_NOT_ENOUGH_MEMORY;
}
size_t dst_size = (size_t)ddt_header.length * 2 * 2;
size_t props_size = LZMA_PROPERTIES_LENGTH;
aaruf_lzma_encode_buffer(
cmp_buffer, &dst_size,
ctx->userDataDdtHeader.sizeType == SmallDdtSizeType ? (uint8_t *)ctx->cachedSecondaryDdtSmall
: (uint8_t *)ctx->cachedSecondaryDdtBig,
ddt_header.length, lzma_properties, &props_size, 9, ctx->lzma_dict_size, 4, 0, 2, 273, 8);
ddt_header.cmpLength = (uint32_t)dst_size;
if(ddt_header.cmpLength >= ddt_header.length)
{
ddt_header.compression = None;
free(cmp_buffer);
if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType)
cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtSmall;
else
cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig;
}
}
if(ddt_header.compression == None)
{
ddt_header.cmpLength = ddt_header.length;
ddt_header.cmpCrc64 = ddt_header.crc64;
}
else
ddt_header.cmpCrc64 = aaruf_crc64_data(cmp_buffer, (uint32_t)ddt_header.cmpLength);
if(ddt_header.compression == Lzma) ddt_header.cmpLength += LZMA_PROPERTIES_LENGTH;
// Write header
written_bytes = fwrite(&ddt_header, sizeof(DdtHeader2), 1, ctx->imageStream);
@@ -1357,18 +1405,17 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo
}
// Write data
if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType)
written_bytes = fwrite(ctx->cachedSecondaryDdtSmall, ddt_header.length, 1, ctx->imageStream);
else
written_bytes = fwrite(ctx->cachedSecondaryDdtBig, ddt_header.length, 1, ctx->imageStream);
if(ddt_header.compression == Lzma) fwrite(lzma_properties, LZMA_PROPERTIES_LENGTH, 1, ctx->imageStream);
if(written_bytes != 1)
if(fwrite(cmp_buffer, ddt_header.cmpLength, 1, ctx->imageStream) != 1)
{
FATAL("Could not write never-written DDT data to file.");
TRACE("Exiting set_ddt_multi_level_v2() = false");
return false;
}
if(ddt_header.compression == Lzma) free(cmp_buffer);
// Add index entry for the newly written secondary DDT
IndexEntry new_ddt_entry;
new_ddt_entry.blockType = DeDuplicationTable2;