mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2025-12-16 19:24:40 +00:00
Refactor DDT initialization for improved memory management and alignment handling
This commit is contained in:
64
src/create.c
64
src/create.c
@@ -23,6 +23,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "aaruformat.h"
|
#include "aaruformat.h"
|
||||||
|
#include "enums.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
@@ -427,58 +428,81 @@ void *aaruf_create(const char *filepath, const uint32_t media_type, const uint32
|
|||||||
ctx->userDataDdtHeader.start = 0;
|
ctx->userDataDdtHeader.start = 0;
|
||||||
ctx->userDataDdtHeader.blockAlignmentShift = parsed_options.block_alignment;
|
ctx->userDataDdtHeader.blockAlignmentShift = parsed_options.block_alignment;
|
||||||
ctx->userDataDdtHeader.dataShift = parsed_options.data_shift;
|
ctx->userDataDdtHeader.dataShift = parsed_options.data_shift;
|
||||||
ctx->userDataDdtHeader.sizeType = 1;
|
ctx->userDataDdtHeader.sizeType = BigDdtSizeType;
|
||||||
ctx->userDataDdtHeader.entries = ctx->userDataDdtHeader.blocks / (1 << ctx->userDataDdtHeader.tableShift);
|
|
||||||
|
|
||||||
if(parsed_options.table_shift == -1)
|
if(parsed_options.table_shift == -1)
|
||||||
{
|
{
|
||||||
const uint64_t total_sectors = user_sectors + overflow_sectors + negative_sectors;
|
const uint64_t total_sectors = user_sectors + overflow_sectors + negative_sectors;
|
||||||
|
|
||||||
if(total_sectors < 0x8388608ULL)
|
if(total_sectors < 0x8388608ULL)
|
||||||
{
|
|
||||||
ctx->userDataDdtHeader.levels = 1;
|
|
||||||
ctx->userDataDdtHeader.tableShift = 0;
|
ctx->userDataDdtHeader.tableShift = 0;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ctx->userDataDdtHeader.levels = 2;
|
|
||||||
ctx->userDataDdtHeader.tableShift = 22;
|
ctx->userDataDdtHeader.tableShift = 22;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
ctx->userDataDdtHeader.tableShift =
|
||||||
|
parsed_options.table_shift > 0 ? (uint8_t)parsed_options.table_shift : 0;
|
||||||
|
|
||||||
|
ctx->userDataDdtHeader.levels = ctx->userDataDdtHeader.tableShift > 0 ? 2 : 1;
|
||||||
|
|
||||||
|
uint8_t effective_table_shift = ctx->userDataDdtHeader.tableShift;
|
||||||
|
if(effective_table_shift >= 63)
|
||||||
{
|
{
|
||||||
ctx->userDataDdtHeader.levels = parsed_options.table_shift > 0 ? 2 : 1;
|
TRACE("Clamping table shift from %u to 62 to avoid overflow", effective_table_shift);
|
||||||
ctx->userDataDdtHeader.tableShift = parsed_options.table_shift;
|
effective_table_shift = 62;
|
||||||
|
ctx->userDataDdtHeader.tableShift = effective_table_shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ctx->userDataDdtHeader.blocks % (1 << ctx->userDataDdtHeader.tableShift) != 0)
|
const uint64_t sectors_per_entry = 1ULL << effective_table_shift;
|
||||||
|
ctx->userDataDdtHeader.entries = ctx->userDataDdtHeader.blocks / sectors_per_entry;
|
||||||
|
if(ctx->userDataDdtHeader.blocks % sectors_per_entry != 0 || ctx->userDataDdtHeader.entries == 0)
|
||||||
ctx->userDataDdtHeader.entries++;
|
ctx->userDataDdtHeader.entries++;
|
||||||
|
|
||||||
TRACE("Initializing primary/single DDT");
|
TRACE("Initializing primary/single DDT");
|
||||||
if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType)
|
if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType)
|
||||||
|
{
|
||||||
ctx->userDataDdtMini =
|
ctx->userDataDdtMini =
|
||||||
(uint16_t *)calloc(ctx->userDataDdtHeader.entries, sizeof(uint16_t)); // All entries to zero
|
(uint16_t *)calloc(ctx->userDataDdtHeader.entries, sizeof(uint16_t)); // All entries to zero
|
||||||
|
if(ctx->userDataDdtMini == NULL)
|
||||||
|
{
|
||||||
|
FATAL("Not enough memory to allocate primary DDT (mini)");
|
||||||
|
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
TRACE("Exiting aaruf_create() = NULL");
|
||||||
|
cleanup_failed_create(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType)
|
else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType)
|
||||||
|
{
|
||||||
ctx->userDataDdtBig =
|
ctx->userDataDdtBig =
|
||||||
(uint32_t *)calloc(ctx->userDataDdtHeader.entries, sizeof(uint32_t)); // All entries to zero
|
(uint32_t *)calloc(ctx->userDataDdtHeader.entries, sizeof(uint32_t)); // All entries to zero
|
||||||
|
if(ctx->userDataDdtBig == NULL)
|
||||||
|
{
|
||||||
|
FATAL("Not enough memory to allocate primary DDT (big)");
|
||||||
|
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
TRACE("Exiting aaruf_create() = NULL");
|
||||||
|
cleanup_failed_create(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set the primary DDT offset (just after the header, block aligned)
|
// Set the primary DDT offset (just after the header, block aligned)
|
||||||
ctx->primaryDdtOffset = sizeof(AaruHeaderV2); // Start just after the header
|
ctx->primaryDdtOffset = sizeof(AaruHeaderV2); // Start just after the header
|
||||||
const uint64_t alignmentMask = (1ULL << ctx->userDataDdtHeader.blockAlignmentShift) - 1;
|
const uint64_t alignment_mask = (1ULL << ctx->userDataDdtHeader.blockAlignmentShift) - 1;
|
||||||
ctx->primaryDdtOffset = ctx->primaryDdtOffset + alignmentMask & ~alignmentMask;
|
ctx->primaryDdtOffset = ctx->primaryDdtOffset + alignment_mask & ~alignment_mask;
|
||||||
|
|
||||||
TRACE("Primary DDT will be placed at offset %" PRIu64, ctx->primaryDdtOffset);
|
TRACE("Primary DDT will be placed at offset %" PRIu64, ctx->primaryDdtOffset);
|
||||||
|
|
||||||
// Calculate size of primary DDT table
|
// Calculate size of primary DDT table
|
||||||
const uint64_t primaryTableSize = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType
|
const uint64_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType
|
||||||
? ctx->userDataDdtHeader.entries * sizeof(uint16_t)
|
? ctx->userDataDdtHeader.entries * sizeof(uint16_t)
|
||||||
: ctx->userDataDdtHeader.entries * sizeof(uint32_t);
|
: ctx->userDataDdtHeader.entries * sizeof(uint32_t);
|
||||||
|
|
||||||
// Calculate where data blocks can start (after primary DDT + header)
|
// Calculate where data blocks can start (after primary DDT + header)
|
||||||
if(ctx->userDataDdtHeader.tableShift > 0)
|
if(ctx->userDataDdtHeader.tableShift > 0)
|
||||||
{
|
{
|
||||||
const uint64_t dataStartPosition = ctx->primaryDdtOffset + sizeof(DdtHeader2) + primaryTableSize;
|
const uint64_t data_start_position = ctx->primaryDdtOffset + sizeof(DdtHeader2) + primary_table_size;
|
||||||
ctx->nextBlockPosition = dataStartPosition + alignmentMask & ~alignmentMask;
|
ctx->nextBlockPosition = data_start_position + alignment_mask & ~alignment_mask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ctx->nextBlockPosition = ctx->primaryDdtOffset; // Single-level DDT can start anywhere
|
ctx->nextBlockPosition = ctx->primaryDdtOffset; // Single-level DDT can start anywhere
|
||||||
@@ -490,9 +514,9 @@ void *aaruf_create(const char *filepath, const uint32_t media_type, const uint32
|
|||||||
ctx->userDataDdtHeader.dataShift = parsed_options.data_shift;
|
ctx->userDataDdtHeader.dataShift = parsed_options.data_shift;
|
||||||
|
|
||||||
// Calculate aligned next block position
|
// Calculate aligned next block position
|
||||||
const uint64_t alignmentMask = (1ULL << parsed_options.block_alignment) - 1;
|
const uint64_t alignment_mask = (1ULL << parsed_options.block_alignment) - 1;
|
||||||
ctx->nextBlockPosition = sizeof(AaruHeaderV2); // Start just after the header
|
ctx->nextBlockPosition = sizeof(AaruHeaderV2); // Start just after the header
|
||||||
ctx->nextBlockPosition = ctx->nextBlockPosition + alignmentMask & ~alignmentMask;
|
ctx->nextBlockPosition = ctx->nextBlockPosition + alignment_mask & ~alignment_mask;
|
||||||
ctx->is_tape = 1;
|
ctx->is_tape = 1;
|
||||||
ctx->tapeDdt = NULL;
|
ctx->tapeDdt = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user