diff --git a/include/aaruformat/context.h b/include/aaruformat/context.h index fe65814..3c4a769 100644 --- a/include/aaruformat/context.h +++ b/include/aaruformat/context.h @@ -188,8 +188,10 @@ typedef struct aaruformatContext bool inMemoryDdt; ///< True if primary (and possibly secondary) DDT loaded. uint64_t *userDataDdt; ///< Legacy flat DDT pointer (NULL when using v2 mini/big arrays). size_t mappedMemoryDdtSize; ///< Length of mmapped DDT if userDataDdt is mmapped. - uint32_t *sectorPrefixDdt; ///< Legacy CD sector prefix DDT (deprecated by *_Mini/Big). + uint32_t *sectorPrefixDdt; ///< Legacy CD sector prefix DDT (deprecated by *2). uint32_t *sectorSuffixDdt; ///< Legacy CD sector suffix DDT. + uint32_t *sectorPrefixDdt2; ///< CD sector prefix DDT V2. + uint32_t *sectorSuffixDdt2; ///< CD sector suffix DDT V2. GeometryBlockHeader geometryBlock; ///< Logical geometry block (if present). MetadataBlockHeader metadataBlockHeader; ///< Metadata block header. @@ -213,18 +215,14 @@ typedef struct aaruformatContext Checksums checksums; ///< Whole-image checksums discovered. mediaTagEntry *mediaTags; ///< Hash table of extra media tags (uthash root). - DdtHeader2 userDataDdtHeader; ///< Active user data DDT v2 header (primary table meta). - int ddtVersion; ///< DDT version in use (1=legacy, 2=v2 hierarchical). - uint16_t *userDataDdtMini; ///< DDT entries (small variant) primary/secondary current. - uint32_t *userDataDdtBig; ///< DDT entries (big variant) primary/secondary current. - uint16_t *sectorPrefixDdtMini; ///< CD sector prefix corrected DDT (small) if present. - uint16_t *sectorSuffixDdtMini; ///< CD sector suffix corrected DDT (small) if present. + DdtHeader2 userDataDdtHeader; ///< Active user data DDT v2 header (primary table meta). + int ddtVersion; ///< DDT version in use (1=legacy, 2=v2 hierarchical). + uint32_t *userDataDdtBig; ///< DDT entries (big variant) primary/secondary current. - uint64_t cachedDdtOffset; ///< File offset of currently cached secondary DDT (0=none). - uint64_t cachedDdtPosition; ///< Position index of cached secondary DDT. - uint64_t primaryDdtOffset; ///< File offset of the primary DDT v2 table. - uint16_t *cachedSecondaryDdtSmall; ///< Cached secondary table (small entries) or NULL. - uint32_t *cachedSecondaryDdtBig; ///< Cached secondary table (big entries) or NULL. + uint64_t cachedDdtOffset; ///< File offset of currently cached secondary DDT (0=none). + uint64_t cachedDdtPosition; ///< Position index of cached secondary DDT. + uint64_t primaryDdtOffset; ///< File offset of the primary DDT v2 table. + uint32_t *cachedSecondaryDdtBig; ///< Cached secondary table (big entries) or NULL. bool isWriting; ///< True if context opened/created for writing. BlockHeader currentBlockHeader; ///< Header for block currently being assembled (write path). diff --git a/include/aaruformat/enums.h b/include/aaruformat/enums.h index b0dfafc..a4e92b8 100644 --- a/include/aaruformat/enums.h +++ b/include/aaruformat/enums.h @@ -226,8 +226,7 @@ typedef enum */ typedef enum { - SmallDdtSizeType = 0, ///< Small sized DDT entries. - BigDdtSizeType = 1 ///< Large sized DDT entries. + BigDdtSizeType = 1 ///< Large sized DDT entries. } DdtSizeType; /** diff --git a/src/close.c b/src/close.c index ac52a55..594478f 100644 --- a/src/close.c +++ b/src/close.c @@ -79,8 +79,7 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) // Write cached secondary table to file end and update primary table entry with its position // Check if we have a cached table that needs to be written (either it has an offset or exists in memory) bool has_cached_secondary_ddt = - ctx->userDataDdtHeader.tableShift > 0 && - (ctx->cachedDdtOffset != 0 || ctx->cachedSecondaryDdtSmall != NULL || ctx->cachedSecondaryDdtBig != NULL); + ctx->userDataDdtHeader.tableShift > 0 && (ctx->cachedDdtOffset != 0 || ctx->cachedSecondaryDdtBig != NULL); if(!has_cached_secondary_ddt) return AARUF_STATUS_OK; @@ -126,19 +125,13 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) ddt_header.start = ctx->cachedDdtPosition * items_per_ddt_entry; // Calculate data size - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ddt_header.length = items_per_ddt_entry * sizeof(uint16_t); - else - ddt_header.length = items_per_ddt_entry * sizeof(uint32_t); + ddt_header.length = items_per_ddt_entry * sizeof(uint32_t); // Calculate CRC64 of the data crc64_ctx *crc64_context = aaruf_crc64_init(); if(crc64_context != NULL) { - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtSmall, (uint32_t)ddt_header.length); - else - aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtBig, (uint32_t)ddt_header.length); + aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtBig, (uint32_t)ddt_header.length); uint64_t crc64; aaruf_crc64_final(crc64_context, &crc64); @@ -150,10 +143,7 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) if(ddt_header.compression == None) { - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - buffer = (uint8_t *)ctx->cachedSecondaryDdtSmall; - else - buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; + buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; ddt_header.cmpCrc64 = ddt_header.crc64; } else @@ -167,11 +157,10 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) size_t dst_size = (size_t)ddt_header.length * 2 * 2; size_t props_size = LZMA_PROPERTIES_LENGTH; - aaruf_lzma_encode_buffer( - 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); + aaruf_lzma_encode_buffer(buffer, &dst_size, + + (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; @@ -179,10 +168,7 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) { ddt_header.compression = None; free(buffer); - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - buffer = (uint8_t *)ctx->cachedSecondaryDdtSmall; - else - buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; + buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; } } @@ -207,10 +193,7 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) // Update primary table entry to point to new location const uint64_t new_secondary_table_block_offset = end_of_file >> ctx->userDataDdtHeader.blockAlignmentShift; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ctx->userDataDdtMini[ctx->cachedDdtPosition] = (uint16_t)new_secondary_table_block_offset; - else - ctx->userDataDdtBig[ctx->cachedDdtPosition] = (uint32_t)new_secondary_table_block_offset; + ctx->userDataDdtBig[ctx->cachedDdtPosition] = (uint32_t)new_secondary_table_block_offset; // Update index: remove old entry for cached DDT and add new one TRACE("Updating index for cached secondary DDT"); @@ -247,15 +230,10 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) long saved_pos = ftell(ctx->imageStream); fseek(ctx->imageStream, ctx->primaryDdtOffset + sizeof(DdtHeader2), SEEK_SET); - size_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? ctx->userDataDdtHeader.entries * sizeof(uint16_t) - : ctx->userDataDdtHeader.entries * sizeof(uint32_t); + size_t primary_table_size = ctx->userDataDdtHeader.entries * sizeof(uint32_t); size_t primary_written_bytes = 0; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - primary_written_bytes = fwrite(ctx->userDataDdtMini, primary_table_size, 1, ctx->imageStream); - else - primary_written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); + primary_written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); if(primary_written_bytes != 1) { @@ -272,17 +250,9 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) TRACE("Failed to write cached secondary DDT header"); // Free the cached table - if(ctx->cachedSecondaryDdtSmall != NULL) - { - free(ctx->cachedSecondaryDdtSmall); - ctx->cachedSecondaryDdtSmall = NULL; - } - if(ctx->cachedSecondaryDdtBig != NULL) - { - free(ctx->cachedSecondaryDdtBig); - ctx->cachedSecondaryDdtBig = NULL; - } - ctx->cachedDdtOffset = 0; + free(ctx->cachedSecondaryDdtBig); + ctx->cachedSecondaryDdtBig = NULL; + ctx->cachedDdtOffset = 0; // Set position fseek(ctx->imageStream, 0, SEEK_END); @@ -312,8 +282,7 @@ static int32_t write_cached_secondary_ddt(aaruformatContext *ctx) static int32_t write_primary_ddt(aaruformatContext *ctx) { // Write the cached primary DDT table back to its position in the file - if(ctx->userDataDdtHeader.tableShift <= 0 || ctx->userDataDdtMini == NULL && ctx->userDataDdtBig == NULL) - return AARUF_STATUS_OK; + if(ctx->userDataDdtHeader.tableShift <= 0 || ctx->userDataDdtBig == NULL) return AARUF_STATUS_OK; TRACE("Writing cached primary DDT table back to file"); @@ -321,14 +290,9 @@ static int32_t write_primary_ddt(aaruformatContext *ctx) crc64_ctx *crc64_context = aaruf_crc64_init(); if(crc64_context != NULL) { - size_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? ctx->userDataDdtHeader.entries * sizeof(uint16_t) - : ctx->userDataDdtHeader.entries * sizeof(uint32_t); + size_t primary_table_size = ctx->userDataDdtHeader.entries * sizeof(uint32_t); - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - aaruf_crc64_update(crc64_context, (uint8_t *)ctx->userDataDdtMini, primary_table_size); - else - aaruf_crc64_update(crc64_context, (uint8_t *)ctx->userDataDdtBig, primary_table_size); + aaruf_crc64_update(crc64_context, (uint8_t *)ctx->userDataDdtBig, primary_table_size); uint64_t crc64; aaruf_crc64_final(crc64_context, &crc64); @@ -358,16 +322,11 @@ static int32_t write_primary_ddt(aaruformatContext *ctx) } // Then write the table data (position is already after the header) - size_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? ctx->userDataDdtHeader.entries * sizeof(uint16_t) - : ctx->userDataDdtHeader.entries * sizeof(uint32_t); + size_t primary_table_size = ctx->userDataDdtHeader.entries * sizeof(uint32_t); // Write the primary table data size_t written_bytes = 0; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - written_bytes = fwrite(ctx->userDataDdtMini, primary_table_size, 1, ctx->imageStream); - else - written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); + written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); if(written_bytes == 1) { @@ -409,15 +368,12 @@ static int32_t write_primary_ddt(aaruformatContext *ctx) static int32_t write_single_level_ddt(aaruformatContext *ctx) { // Write the single level DDT table block aligned just after the header - if(ctx->userDataDdtHeader.tableShift != 0 || ctx->userDataDdtMini == NULL && ctx->userDataDdtBig == NULL) - return AARUF_STATUS_OK; + if(ctx->userDataDdtHeader.tableShift != 0 || ctx->userDataDdtBig == NULL) return AARUF_STATUS_OK; TRACE("Writing single-level DDT table to file"); // Calculate CRC64 of the primary DDT table data - const size_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? ctx->userDataDdtHeader.entries * sizeof(uint16_t) - : ctx->userDataDdtHeader.entries * sizeof(uint32_t); + const size_t primary_table_size = ctx->userDataDdtHeader.entries * sizeof(uint32_t); // Properly populate all header fields ctx->userDataDdtHeader.identifier = DeDuplicationTable2; @@ -431,10 +387,7 @@ static int32_t write_single_level_ddt(aaruformatContext *ctx) ctx->userDataDdtHeader.length = primary_table_size; ctx->userDataDdtHeader.cmpLength = primary_table_size; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ctx->userDataDdtHeader.crc64 = aaruf_crc64_data((uint8_t *)ctx->userDataDdtMini, primary_table_size); - else - ctx->userDataDdtHeader.crc64 = aaruf_crc64_data((uint8_t *)ctx->userDataDdtBig, primary_table_size); + ctx->userDataDdtHeader.crc64 = aaruf_crc64_data((uint8_t *)ctx->userDataDdtBig, primary_table_size); TRACE("Calculated CRC64 for single-level DDT: 0x%16lX", ctx->userDataDdtHeader.crc64); @@ -443,10 +396,8 @@ static int32_t write_single_level_ddt(aaruformatContext *ctx) if(ctx->userDataDdtHeader.compression == None) { - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - cmp_buffer = (uint8_t *)ctx->userDataDdtMini; - else - cmp_buffer = (uint8_t *)ctx->userDataDdtBig; + + cmp_buffer = (uint8_t *)ctx->userDataDdtBig; ctx->userDataDdtHeader.cmpCrc64 = ctx->userDataDdtHeader.crc64; } else @@ -460,11 +411,8 @@ static int32_t write_single_level_ddt(aaruformatContext *ctx) size_t dst_size = (size_t)ctx->userDataDdtHeader.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->userDataDdtMini - : (uint8_t *)ctx->userDataDdtBig, - ctx->userDataDdtHeader.length, lzma_properties, &props_size, 9, ctx->lzma_dict_size, 4, - 0, 2, 273, 8); + aaruf_lzma_encode_buffer(cmp_buffer, &dst_size, (uint8_t *)ctx->userDataDdtBig, ctx->userDataDdtHeader.length, + lzma_properties, &props_size, 9, ctx->lzma_dict_size, 4, 0, 2, 273, 8); ctx->userDataDdtHeader.cmpLength = (uint32_t)dst_size; @@ -472,10 +420,8 @@ static int32_t write_single_level_ddt(aaruformatContext *ctx) { ctx->userDataDdtHeader.compression = None; free(cmp_buffer); - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - cmp_buffer = (uint8_t *)ctx->userDataDdtMini; - else - cmp_buffer = (uint8_t *)ctx->userDataDdtBig; + + cmp_buffer = (uint8_t *)ctx->userDataDdtBig; } } @@ -1241,7 +1187,7 @@ static void write_sector_suffix(aaruformatContext *ctx) * Notes: * - Unlike DDT v1, there are no CD_XFIX_MASK / CD_DFIX_MASK macros used here. The bit layout is compact * and directly encoded when writing (status values are pre-shifted where needed in write.c). - * - Only the 16-bit mini variant is currently produced (sectorPrefixDdtMini). A 32-bit form is reserved + * - Only the 16-bit mini variant is currently produced (sectorPrefixDdt2). A 32-bit form is reserved * for future expansion (sectorPrefixDdt) but is not emitted unless populated. * - The table length equals (negative + Sectors + overflow) * entrySize. * - dataShift is set to 4 (2^4 = 16) expressing the granularity of referenced prefix units. @@ -1257,7 +1203,7 @@ static void write_sector_suffix(aaruformatContext *ctx) */ static void write_sector_prefix_ddt(aaruformatContext *ctx) { - if(ctx->sectorPrefixDdtMini == NULL) return; + if(ctx->sectorPrefixDdt2 == NULL) return; fseek(ctx->imageStream, 0, SEEK_END); long prefix_ddt_position = ftell(ctx->imageStream); @@ -1282,20 +1228,20 @@ static void write_sector_prefix_ddt(aaruformatContext *ctx) ddt_header2.blockAlignmentShift = ctx->userDataDdtHeader.blockAlignmentShift; ddt_header2.dataShift = ctx->userDataDdtHeader.dataShift; ddt_header2.tableShift = 0; // Single-level DDT - ddt_header2.sizeType = SmallDdtSizeType; + ddt_header2.sizeType = BigDdtSizeType; ddt_header2.entries = ctx->imageInfo.Sectors + ctx->userDataDdtHeader.negative + ctx->userDataDdtHeader.overflow; ddt_header2.blocks = ctx->userDataDdtHeader.blocks; ddt_header2.start = 0; - ddt_header2.length = ddt_header2.entries * sizeof(uint16_t); + ddt_header2.length = ddt_header2.entries * sizeof(uint32_t); // Calculate CRC64 - ddt_header2.crc64 = aaruf_crc64_data((uint8_t *)ctx->sectorPrefixDdtMini, (uint32_t)ddt_header2.length); + ddt_header2.crc64 = aaruf_crc64_data((uint8_t *)ctx->sectorPrefixDdt2, (uint32_t)ddt_header2.length); uint8_t *buffer = NULL; uint8_t lzma_properties[LZMA_PROPERTIES_LENGTH] = {0}; if(ddt_header2.compression == None) { - buffer = (uint8_t *)ctx->sectorPrefixDdtMini; + buffer = (uint8_t *)ctx->sectorPrefixDdt2; ddt_header2.cmpCrc64 = ddt_header2.crc64; } else @@ -1309,7 +1255,7 @@ static void write_sector_prefix_ddt(aaruformatContext *ctx) size_t dst_size = (size_t)ddt_header2.length * 2 * 2; size_t props_size = LZMA_PROPERTIES_LENGTH; - aaruf_lzma_encode_buffer(buffer, &dst_size, (uint8_t *)ctx->sectorPrefixDdtMini, ddt_header2.length, + aaruf_lzma_encode_buffer(buffer, &dst_size, (uint8_t *)ctx->sectorPrefixDdt2, ddt_header2.length, lzma_properties, &props_size, 9, ctx->lzma_dict_size, 4, 0, 2, 273, 8); ddt_header2.cmpLength = (uint32_t)dst_size; @@ -1318,7 +1264,7 @@ static void write_sector_prefix_ddt(aaruformatContext *ctx) { ddt_header2.compression = None; free(buffer); - buffer = (uint8_t *)ctx->sectorPrefixDdtMini; + buffer = (uint8_t *)ctx->sectorPrefixDdt2; } } @@ -1375,13 +1321,13 @@ static void write_sector_prefix_ddt(aaruformatContext *ctx) * * Characteristics & constraints: * - Only DDT v2 is supported here; no fallback or mixed-mode emission with v1 occurs. - * - Only the compact "mini" (16-bit) table form is currently produced (sectorSuffixDdtMini filled during write). + * - Only the compact "mini" (16-bit) table form is currently produced (sectorSuffixDdt2 filled during write). * - Table length = (negative + total Sectors + overflow) * sizeof(uint16_t). * - dataShift mirrors userDataDdtHeader.dataShift (expressing granularity for index referencing). * - Single-level table (levels = 1, tableLevel = 0, tableShift = 0). * - Compression is applied if enabled; CRC64 protects the table bytes. * - Alignment: The table is aligned to 2^(blockAlignmentShift) before writing to guarantee block boundary access. - * - Idempotence: If sectorSuffixDdtMini is NULL the function is a no-op (indicating no suffix anomalies captured). + * - Idempotence: If sectorSuffixDdt2 is NULL the function is a no-op (indicating no suffix anomalies captured). * * Index integration: * On success an IndexEntry (blockType = DeDuplicationTable2, dataType = CdSectorSuffix, offset = file position) @@ -1395,14 +1341,14 @@ static void write_sector_prefix_ddt(aaruformatContext *ctx) * * Preconditions: * - ctx must be a valid non-NULL pointer opened for writing. - * - ctx->sectorSuffixDdtMini must point to a fully populated contiguous array of uint16_t entries. + * - ctx->sectorSuffixDdt2 must point to a fully populated contiguous array of uint16_t entries. * * @param ctx Active aaruformatContext being finalized. * @internal */ static void write_sector_suffix_ddt(aaruformatContext *ctx) { - if(ctx->sectorSuffixDdtMini == NULL) return; + if(ctx->sectorSuffixDdt2 == NULL) return; fseek(ctx->imageStream, 0, SEEK_END); long suffix_ddt_position = ftell(ctx->imageStream); @@ -1427,20 +1373,20 @@ static void write_sector_suffix_ddt(aaruformatContext *ctx) ddt_header2.blockAlignmentShift = ctx->userDataDdtHeader.blockAlignmentShift; ddt_header2.dataShift = ctx->userDataDdtHeader.dataShift; ddt_header2.tableShift = 0; // Single-level DDT - ddt_header2.sizeType = SmallDdtSizeType; + ddt_header2.sizeType = BigDdtSizeType; ddt_header2.entries = ctx->imageInfo.Sectors + ctx->userDataDdtHeader.negative + ctx->userDataDdtHeader.overflow; ddt_header2.blocks = ctx->userDataDdtHeader.blocks; ddt_header2.start = 0; - ddt_header2.length = ddt_header2.entries * sizeof(uint16_t); + ddt_header2.length = ddt_header2.entries * sizeof(uint32_t); // Calculate CRC64 - ddt_header2.crc64 = aaruf_crc64_data((uint8_t *)ctx->sectorSuffixDdtMini, (uint32_t)ddt_header2.length); + ddt_header2.crc64 = aaruf_crc64_data((uint8_t *)ctx->sectorSuffixDdt2, (uint32_t)ddt_header2.length); uint8_t *buffer = NULL; uint8_t lzma_properties[LZMA_PROPERTIES_LENGTH] = {0}; if(ddt_header2.compression == None) { - buffer = (uint8_t *)ctx->sectorSuffixDdtMini; + buffer = (uint8_t *)ctx->sectorSuffixDdt2; ddt_header2.cmpCrc64 = ddt_header2.crc64; } else @@ -1454,7 +1400,7 @@ static void write_sector_suffix_ddt(aaruformatContext *ctx) size_t dst_size = (size_t)ddt_header2.length * 2 * 2; size_t props_size = LZMA_PROPERTIES_LENGTH; - aaruf_lzma_encode_buffer(buffer, &dst_size, (uint8_t *)ctx->sectorSuffixDdtMini, ddt_header2.length, + aaruf_lzma_encode_buffer(buffer, &dst_size, (uint8_t *)ctx->sectorSuffixDdt2, ddt_header2.length, lzma_properties, &props_size, 9, ctx->lzma_dict_size, 4, 0, 2, 273, 8); ddt_header2.cmpLength = (uint32_t)dst_size; @@ -1463,7 +1409,7 @@ static void write_sector_suffix_ddt(aaruformatContext *ctx) { ddt_header2.compression = None; free(buffer); - buffer = (uint8_t *)ctx->sectorSuffixDdtMini; + buffer = (uint8_t *)ctx->sectorSuffixDdt2; } } @@ -4226,12 +4172,12 @@ int aaruf_close(void *context) } #endif - free(ctx->sectorPrefixDdtMini); - ctx->sectorPrefixDdtMini = NULL; + free(ctx->sectorPrefixDdt2); + ctx->sectorPrefixDdt2 = NULL; free(ctx->sectorPrefixDdt); ctx->sectorPrefixDdt = NULL; - free(ctx->sectorSuffixDdtMini); - ctx->sectorSuffixDdtMini = NULL; + free(ctx->sectorSuffixDdt2); + ctx->sectorSuffixDdt2 = NULL; free(ctx->sectorSuffixDdt); ctx->sectorSuffixDdt = NULL; diff --git a/src/create.c b/src/create.c index 4ee9106..484ecb6 100644 --- a/src/create.c +++ b/src/create.c @@ -43,12 +43,6 @@ static void cleanup_failed_create(aaruformatContext *ctx) ctx->indexEntries = NULL; } - if(ctx->userDataDdtMini != NULL) - { - free(ctx->userDataDdtMini); - ctx->userDataDdtMini = NULL; - } - if(ctx->userDataDdtBig != NULL) { free(ctx->userDataDdtBig); @@ -397,7 +391,7 @@ void *aaruf_create(const char *filepath, const uint32_t media_type, const uint32 // Initialize caches TRACE("Initializing caches"); - ctx->blockHeaderCache.cache = NULL; + ctx->blockHeaderCache.cache = NULL; const uint64_t cache_divisor = (uint64_t)ctx->imageInfo.SectorSize * (1ULL << ctx->shift); ctx->blockHeaderCache.max_items = cache_divisor == 0 ? 0 : MAX_CACHE_SIZE / cache_divisor; ctx->blockCache.cache = NULL; @@ -459,20 +453,7 @@ void *aaruf_create(const char *filepath, const uint32_t media_type, const uint32 ctx->userDataDdtHeader.entries++; TRACE("Initializing primary/single DDT"); - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - { - ctx->userDataDdtMini = - (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) + if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) { ctx->userDataDdtBig = (uint32_t *)calloc(ctx->userDataDdtHeader.entries, sizeof(uint32_t)); // All entries to zero @@ -487,16 +468,14 @@ void *aaruf_create(const char *filepath, const uint32_t media_type, const uint32 } // 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 alignment_mask = (1ULL << ctx->userDataDdtHeader.blockAlignmentShift) - 1; - ctx->primaryDdtOffset = ctx->primaryDdtOffset + alignment_mask & ~alignment_mask; + ctx->primaryDdtOffset = ctx->primaryDdtOffset + alignment_mask & ~alignment_mask; TRACE("Primary DDT will be placed at offset %" PRIu64, ctx->primaryDdtOffset); // Calculate size of primary DDT table - const uint64_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? ctx->userDataDdtHeader.entries * sizeof(uint16_t) - : ctx->userDataDdtHeader.entries * sizeof(uint32_t); + const uint64_t primary_table_size = ctx->userDataDdtHeader.entries * sizeof(uint32_t); // Calculate where data blocks can start (after primary DDT + header) if(ctx->userDataDdtHeader.tableShift > 0) @@ -514,11 +493,11 @@ void *aaruf_create(const char *filepath, const uint32_t media_type, const uint32 ctx->userDataDdtHeader.dataShift = parsed_options.data_shift; // Calculate aligned next block position - const uint64_t alignment_mask = (1ULL << parsed_options.block_alignment) - 1; - ctx->nextBlockPosition = sizeof(AaruHeaderV2); // Start just after the header - ctx->nextBlockPosition = ctx->nextBlockPosition + alignment_mask & ~alignment_mask; - ctx->is_tape = 1; - ctx->tapeDdt = NULL; + const uint64_t alignment_mask = (1ULL << parsed_options.block_alignment) - 1; + ctx->nextBlockPosition = sizeof(AaruHeaderV2); // Start just after the header + ctx->nextBlockPosition = ctx->nextBlockPosition + alignment_mask & ~alignment_mask; + ctx->is_tape = 1; + ctx->tapeDdt = NULL; } TRACE("Data blocks will start at position %" PRIu64, ctx->nextBlockPosition); diff --git a/src/ddt/ddt_v2.c b/src/ddt/ddt_v2.c index a1d06e5..a1d0500 100644 --- a/src/ddt/ddt_v2.c +++ b/src/ddt/ddt_v2.c @@ -247,10 +247,7 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us return AARUF_ERROR_INVALID_BLOCK_CRC; } - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->userDataDdtMini = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->userDataDdtBig = (uint32_t *)buffer; + ctx->userDataDdtBig = (uint32_t *)buffer; ctx->inMemoryDdt = true; *found_user_data_ddt = true; @@ -296,10 +293,7 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us return AARUF_ERROR_INVALID_BLOCK_CRC; } - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->userDataDdtMini = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->userDataDdtBig = (uint32_t *)buffer; + ctx->userDataDdtBig = (uint32_t *)buffer; ctx->inMemoryDdt = true; *found_user_data_ddt = true; @@ -405,20 +399,8 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us return AARUF_ERROR_INVALID_BLOCK_CRC; } - if(entry->dataType == CdSectorPrefixCorrected) - { - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->sectorPrefixDdtMini = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->sectorPrefixDdt = (uint32_t *)buffer; - } - else if(entry->dataType == CdSectorSuffixCorrected) - { - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->sectorSuffixDdtMini = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->sectorSuffixDdt = (uint32_t *)buffer; - } + if(entry->dataType == CdSectorPrefixCorrected) { ctx->sectorPrefixDdt = (uint32_t *)buffer; } + else if(entry->dataType == CdSectorSuffixCorrected) { ctx->sectorSuffixDdt = (uint32_t *)buffer; } else free(buffer); @@ -463,20 +445,8 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us return AARUF_ERROR_INVALID_BLOCK_CRC; } - if(entry->dataType == CdSectorPrefixCorrected) - { - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->sectorPrefixDdtMini = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->sectorPrefixDdt = (uint32_t *)buffer; - } - else if(entry->dataType == CdSectorSuffixCorrected) - { - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->sectorSuffixDdtMini = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->sectorSuffixDdt = (uint32_t *)buffer; - } + if(entry->dataType == CdSectorPrefixCorrected) { ctx->sectorPrefixDdt = (uint32_t *)buffer; } + else if(entry->dataType == CdSectorSuffixCorrected) { ctx->sectorSuffixDdt = (uint32_t *)buffer; } else free(buffer); @@ -646,9 +616,7 @@ int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_addre else sector_address += ctx->userDataDdtHeader.negative; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ddt_entry = ctx->userDataDdtMini[sector_address]; - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) + if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) ddt_entry = ctx->userDataDdtBig[sector_address]; else { @@ -667,16 +635,8 @@ int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_addre return AARUF_STATUS_OK; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - { - *sector_status = ddt_entry >> 12; - ddt_entry &= 0xfff; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - { - *sector_status = ddt_entry >> 28; - ddt_entry &= 0x0fffffff; - } + *sector_status = ddt_entry >> 28; + ddt_entry &= 0x0fffffff; const uint64_t offset_mask = (uint64_t)((1 << ctx->userDataDdtHeader.dataShift) - 1); *offset = ddt_entry & offset_mask; @@ -818,9 +778,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres items_per_ddt_entry = 1 << ctx->userDataDdtHeader.tableShift; ddt_position = sector_address / items_per_ddt_entry; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - secondary_ddt_offset = ctx->userDataDdtMini[ddt_position]; - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) + if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) secondary_ddt_offset = ctx->userDataDdtBig[ddt_position]; else { @@ -949,10 +907,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres return AARUF_ERROR_INVALID_BLOCK_CRC; } - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->cachedSecondaryDdtSmall = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; + ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; ctx->cachedDdtOffset = secondary_ddt_offset; @@ -998,10 +953,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres return AARUF_ERROR_INVALID_BLOCK_CRC; } - if(ddt_header.sizeType == SmallDdtSizeType) - ctx->cachedSecondaryDdtSmall = (uint16_t *)buffer; - else if(ddt_header.sizeType == BigDdtSizeType) - ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; + ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; ctx->cachedDdtOffset = secondary_ddt_offset; @@ -1013,10 +965,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres } } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ddt_entry = ctx->cachedSecondaryDdtSmall[sector_address % items_per_ddt_entry]; - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - ddt_entry = ctx->cachedSecondaryDdtBig[sector_address % items_per_ddt_entry]; + ddt_entry = ctx->cachedSecondaryDdtBig[sector_address % items_per_ddt_entry]; if(ddt_entry == 0) { @@ -1029,16 +978,8 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres return AARUF_STATUS_OK; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - { - *sector_status = ddt_entry >> 12; - ddt_entry &= 0xfff; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - { - *sector_status = ddt_entry >> 28; - ddt_entry &= 0x0fffffff; - } + *sector_status = ddt_entry >> 28; + ddt_entry &= 0x0fffffff; const uint64_t offset_mask = (uint64_t)((1 << ctx->userDataDdtHeader.dataShift) - 1); *offset = ddt_entry & offset_mask; @@ -1134,41 +1075,20 @@ bool set_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_address, co const uint64_t block_index = block_offset >> ctx->userDataDdtHeader.blockAlignmentShift; *ddt_entry = offset & (1ULL << ctx->userDataDdtHeader.dataShift) - 1 | block_index << ctx->userDataDdtHeader.dataShift; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - { // Overflow detection for DDT entry - if(*ddt_entry > 0xFFF) - { - FATAL("DDT overflow: media does not fit in small DDT"); - TRACE("Exiting set_ddt_single_level_v2() = false"); - return false; - } - *ddt_entry |= (uint64_t)sector_status << 12; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) + // Overflow detection for DDT entry + if(*ddt_entry > 0xFFFFFFF) { - // Overflow detection for DDT entry - if(*ddt_entry > 0xFFFFFFF) - { - FATAL("DDT overflow: media does not fit in big DDT"); - TRACE("Exiting set_ddt_single_level_v2() = false"); - return false; - } - - *ddt_entry |= (uint64_t)sector_status << 28; + FATAL("DDT overflow: media does not fit in big DDT"); + TRACE("Exiting set_ddt_single_level_v2() = false"); + return false; } + + *ddt_entry |= (uint64_t)sector_status << 28; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - { - TRACE("Setting small single-level DDT entry %d to %u", sector_address, (uint16_t)*ddt_entry); - ctx->userDataDdtMini[sector_address] = (uint16_t)*ddt_entry; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - { - TRACE("Setting big single-level DDT entry %d to %u", sector_address, (uint32_t)*ddt_entry); - ctx->userDataDdtBig[sector_address] = (uint32_t)*ddt_entry; - } + TRACE("Setting big single-level DDT entry %d to %u", sector_address, (uint32_t)*ddt_entry); + ctx->userDataDdtBig[sector_address] = (uint32_t)*ddt_entry; TRACE("Exiting set_ddt_single_level_v2() = true"); return true; @@ -1234,9 +1154,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo items_per_ddt_entry = 1 << ctx->userDataDdtHeader.tableShift; ddt_position = sector_address / items_per_ddt_entry; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - secondary_ddt_offset = ctx->userDataDdtMini[ddt_position]; - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) + if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) secondary_ddt_offset = ctx->userDataDdtBig[ddt_position]; else { @@ -1258,44 +1176,19 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo *ddt_entry = offset & (1ULL << ctx->userDataDdtHeader.dataShift) - 1 | block_index << ctx->userDataDdtHeader.dataShift; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) + // Overflow detection for DDT entry + if(*ddt_entry > 0xFFFFFFF) { - // Overflow detection for DDT entry - if(*ddt_entry > 0xFFF) - { - FATAL("DDT overflow: media does not fit in small DDT"); - TRACE("Exiting set_ddt_multi_level_v2() = false"); - return false; - } - - *ddt_entry |= (uint64_t)sector_status << 12; + FATAL("DDT overflow: media does not fit in big DDT"); + TRACE("Exiting set_ddt_multi_level_v2() = false"); + return false; } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - { - // Overflow detection for DDT entry - if(*ddt_entry > 0xFFFFFFF) - { - FATAL("DDT overflow: media does not fit in big DDT"); - TRACE("Exiting set_ddt_multi_level_v2() = false"); - return false; - } - *ddt_entry |= (uint64_t)sector_status << 28; - } + *ddt_entry |= (uint64_t)sector_status << 28; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - { - TRACE("Setting small secondary DDT entry %d to %u", sector_address % items_per_ddt_entry, - (uint16_t)*ddt_entry); - ctx->cachedSecondaryDdtSmall[sector_address % items_per_ddt_entry] = (uint16_t)*ddt_entry; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - { - TRACE("Setting small secondary DDT entry %d to %u", sector_address % items_per_ddt_entry, - (uint16_t)*ddt_entry); - ctx->cachedSecondaryDdtBig[sector_address % items_per_ddt_entry] = (uint32_t)*ddt_entry; - } + TRACE("Setting small secondary DDT entry %d to %u", sector_address % items_per_ddt_entry, (uint16_t)*ddt_entry); + ctx->cachedSecondaryDdtBig[sector_address % items_per_ddt_entry] = (uint32_t)*ddt_entry; TRACE("Updated cached secondary DDT entry at position %" PRIu64, sector_address % items_per_ddt_entry); TRACE("Exiting set_ddt_multi_level_v2() = true"); @@ -1304,7 +1197,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo // Step 2.5: Handle case where we have a cached secondary DDT that has never been written to disk // but does not contain the requested block - if(ctx->cachedDdtOffset == 0 && (ctx->cachedSecondaryDdtSmall != NULL || ctx->cachedSecondaryDdtBig != NULL)) + if(ctx->cachedDdtOffset == 0 && (ctx->cachedSecondaryDdtBig != NULL)) { // Only write the cached table to disk if the requested block belongs to a different DDT position if(ddt_position != ctx->cachedDdtPosition) @@ -1346,10 +1239,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo ddt_header.entries = items_per_ddt_entry; // Calculate data size - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ddt_header.length = items_per_ddt_entry * sizeof(uint16_t); - else - ddt_header.length = items_per_ddt_entry * sizeof(uint32_t); + + ddt_header.length = items_per_ddt_entry * sizeof(uint32_t); // Calculate CRC64 of the data crc64_context = aaruf_crc64_init(); @@ -1360,10 +1251,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo return false; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtSmall, (uint32_t)ddt_header.length); - else - aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtBig, (uint32_t)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; @@ -1373,10 +1261,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo if(ddt_header.compression == None) { - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtSmall; - else - cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; + + cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; ddt_header.cmpCrc64 = ddt_header.crc64; } else @@ -1390,11 +1276,9 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo 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); + aaruf_lzma_encode_buffer(cmp_buffer, &dst_size, (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; @@ -1402,10 +1286,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo { 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; + + cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; } } @@ -1452,23 +1334,15 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo // Update the primary level table entry to point to the new location of the secondary table uint64_t new_secondary_table_block_offset = end_of_file >> ctx->userDataDdtHeader.blockAlignmentShift; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ctx->userDataDdtMini[ctx->cachedDdtPosition] = (uint16_t)new_secondary_table_block_offset; - else - ctx->userDataDdtBig[ctx->cachedDdtPosition] = (uint32_t)new_secondary_table_block_offset; + ctx->userDataDdtBig[ctx->cachedDdtPosition] = (uint32_t)new_secondary_table_block_offset; // Write the updated primary table back to its original position in the file long saved_pos = ftell(ctx->imageStream); fseek(ctx->imageStream, ctx->primaryDdtOffset + sizeof(DdtHeader2), SEEK_SET); - size_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? ctx->userDataDdtHeader.entries * sizeof(uint16_t) - : ctx->userDataDdtHeader.entries * sizeof(uint32_t); + size_t primary_table_size = ctx->userDataDdtHeader.entries * sizeof(uint32_t); - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - written_bytes = fwrite(ctx->userDataDdtMini, primary_table_size, 1, ctx->imageStream); - else - written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); + written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); if(written_bytes != 1) { @@ -1485,16 +1359,9 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo TRACE("Updated nextBlockPosition after never-written DDT write to %" PRIu64, ctx->nextBlockPosition); // Free the cached table - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType && ctx->cachedSecondaryDdtSmall) - { - free(ctx->cachedSecondaryDdtSmall); - ctx->cachedSecondaryDdtSmall = NULL; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType && ctx->cachedSecondaryDdtBig) - { - free(ctx->cachedSecondaryDdtBig); - ctx->cachedSecondaryDdtBig = NULL; - } + + free(ctx->cachedSecondaryDdtBig); + ctx->cachedSecondaryDdtBig = NULL; // Reset cached values since we've written and freed the table ctx->cachedDdtOffset = 0; @@ -1549,10 +1416,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo ddt_header.entries = items_per_ddt_entry; // Calculate data size - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ddt_header.length = items_per_ddt_entry * sizeof(uint16_t); - else - ddt_header.length = items_per_ddt_entry * sizeof(uint32_t); + + ddt_header.length = items_per_ddt_entry * sizeof(uint32_t); // Calculate CRC64 of the data crc64_context = aaruf_crc64_init(); @@ -1563,10 +1428,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo return false; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - aaruf_crc64_update(crc64_context, (uint8_t *)ctx->cachedSecondaryDdtSmall, 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, ddt_header.length); aaruf_crc64_final(crc64_context, &crc64); ddt_header.crc64 = crc64; @@ -1576,10 +1438,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo if(ddt_header.compression == None) { - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtSmall; - else - cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; + + cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; ddt_header.cmpCrc64 = ddt_header.crc64; } else @@ -1593,11 +1453,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo 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); + aaruf_lzma_encode_buffer(cmp_buffer, &dst_size, (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; @@ -1605,10 +1462,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo { 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; + + cmp_buffer = (uint8_t *)ctx->cachedSecondaryDdtBig; } } @@ -1681,23 +1536,16 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo // Update the primary table entry to point to the new location of the secondary table // Use ddtPosition which was calculated from sectorAddress, not cachedDdtOffset - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ctx->userDataDdtMini[ddt_position] = (uint16_t)new_secondary_table_block_offset; - else - ctx->userDataDdtBig[ddt_position] = (uint32_t)new_secondary_table_block_offset; + + ctx->userDataDdtBig[ddt_position] = (uint32_t)new_secondary_table_block_offset; // Write the updated primary table back to its original position in the file long saved_pos = ftell(ctx->imageStream); fseek(ctx->imageStream, ctx->primaryDdtOffset + sizeof(DdtHeader2), SEEK_SET); - size_t primary_table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? ctx->userDataDdtHeader.entries * sizeof(uint16_t) - : ctx->userDataDdtHeader.entries * sizeof(uint32_t); + size_t primary_table_size = ctx->userDataDdtHeader.entries * sizeof(uint32_t); - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - written_bytes = fwrite(ctx->userDataDdtMini, primary_table_size, 1, ctx->imageStream); - else - written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); + written_bytes = fwrite(ctx->userDataDdtBig, primary_table_size, 1, ctx->imageStream); if(written_bytes != 1) { @@ -1716,23 +1564,16 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo fseek(ctx->imageStream, saved_pos, SEEK_SET); // Free the cached table - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType && ctx->cachedSecondaryDdtSmall) - { - free(ctx->cachedSecondaryDdtSmall); - ctx->cachedSecondaryDdtSmall = NULL; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType && ctx->cachedSecondaryDdtBig) - { - free(ctx->cachedSecondaryDdtBig); - ctx->cachedSecondaryDdtBig = NULL; - } + + free(ctx->cachedSecondaryDdtBig); + ctx->cachedSecondaryDdtBig = NULL; // Restore file position fseek(ctx->imageStream, current_pos, SEEK_SET); } // Step 5: Check if the specified block already has an existing secondary level table - create_new_table = ctx->cachedSecondaryDdtSmall == NULL && ctx->cachedSecondaryDdtBig == NULL; + create_new_table = ctx->cachedSecondaryDdtBig == NULL; if(!create_new_table && secondary_ddt_offset != 0) { @@ -1788,10 +1629,8 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo } // Cache the loaded table - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ctx->cachedSecondaryDdtSmall = (uint16_t *)buffer; - else - ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; + + ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; ctx->cachedDdtOffset = secondary_ddt_offset; } @@ -1799,9 +1638,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo if(create_new_table) { // Create a new empty table - size_t table_size = ctx->userDataDdtHeader.sizeType == SmallDdtSizeType - ? items_per_ddt_entry * sizeof(uint16_t) - : items_per_ddt_entry * sizeof(uint32_t); + size_t table_size = items_per_ddt_entry * sizeof(uint32_t); buffer = calloc(1, table_size); if(buffer == NULL) @@ -1811,10 +1648,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo return false; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - ctx->cachedSecondaryDdtSmall = (uint16_t *)buffer; - else - ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; + ctx->cachedSecondaryDdtBig = (uint32_t *)buffer; ctx->cachedDdtOffset = 0; // Will be set when written to file ctx->cachedDdtPosition = ddt_position; // Track which primary DDT position this new table belongs to @@ -1828,42 +1662,19 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo *ddt_entry = offset & (1ULL << ctx->userDataDdtHeader.dataShift) - 1 | block_index << ctx->userDataDdtHeader.dataShift; - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) + // Overflow detection for DDT entry + if(*ddt_entry > 0xFFFFFFF) { - // Overflow detection for DDT entry - if(*ddt_entry > 0xFFF) - { - FATAL("DDT overflow: media does not fit in small DDT"); - TRACE("Exiting set_ddt_multi_level_v2() = false"); - return false; - } - - *ddt_entry |= (uint64_t)sector_status << 12; + FATAL("DDT overflow: media does not fit in big DDT"); + TRACE("Exiting set_ddt_multi_level_v2() = false"); + return false; } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - { - // Overflow detection for DDT entry - if(*ddt_entry > 0xFFFFFFF) - { - FATAL("DDT overflow: media does not fit in big DDT"); - TRACE("Exiting set_ddt_multi_level_v2() = false"); - return false; - } - *ddt_entry |= (uint64_t)sector_status << 28; - } + *ddt_entry |= (uint64_t)sector_status << 28; } - if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) - { - TRACE("Setting small secondary DDT entry %d to %u", sector_address % items_per_ddt_entry, (uint16_t)*ddt_entry); - ctx->cachedSecondaryDdtSmall[sector_address % items_per_ddt_entry] = (uint16_t)*ddt_entry; - } - else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) - { - TRACE("Setting big secondary DDT entry %d to %u", sector_address % items_per_ddt_entry, (uint32_t)*ddt_entry); - ctx->cachedSecondaryDdtBig[sector_address % items_per_ddt_entry] = (uint32_t)*ddt_entry; - } + TRACE("Setting big secondary DDT entry %d to %u", sector_address % items_per_ddt_entry, (uint32_t)*ddt_entry); + ctx->cachedSecondaryDdtBig[sector_address % items_per_ddt_entry] = (uint32_t)*ddt_entry; TRACE("Updated secondary DDT entry at position %" PRIu64, sector_address % items_per_ddt_entry); TRACE("Exiting set_ddt_multi_level_v2() = true"); diff --git a/src/write.c b/src/write.c index 6a21223..2e3ee4c 100644 --- a/src/write.c +++ b/src/write.c @@ -371,8 +371,8 @@ int32_t aaruf_write_sector(void *context, uint64_t sector_address, bool negative * * **Memory Management Strategy:** * - **Mini-DDT Arrays**: Lazily allocated 16-bit arrays sized for total addressable space (negative + user + overflow) - * * sectorPrefixDdtMini: Tracks prefix status and buffer offsets (high 4 bits = status, low 12 bits = offset/16) - * * sectorSuffixDdtMini: Tracks suffix status and buffer offsets (high 4 bits = status, low 12 bits = offset/288) + * * sectorPrefixDdt2: Tracks prefix status and buffer offsets (high 4 bits = status, low 12 bits = offset/16) + * * sectorSuffixDdt2: Tracks suffix status and buffer offsets (high 4 bits = status, low 12 bits = offset/288) * - **Prefix Buffer**: Dynamically growing buffer storing non-standard 16-byte CD prefixes * - **Suffix Buffer**: Dynamically growing buffer storing non-standard CD suffixes (288 bytes for Mode 1, 4 bytes for * Mode 2 Form 2, 280 bytes for Mode 2 Form 1) @@ -468,7 +468,7 @@ int32_t aaruf_write_sector(void *context, uint64_t sector_address, bool negative * - length not in {512, 524, 532, 536} for supported block media types * * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when: - * - Failed to allocate mini-DDT arrays (sectorPrefixDdtMini, sectorSuffixDdtMini) + * - Failed to allocate mini-DDT arrays (sectorPrefixDdt2, sectorSuffixDdt2) * - Failed to allocate or grow prefix buffer (sector_prefix) * - Failed to allocate or grow suffix buffer (sector_suffix) * - Failed to allocate subheader buffer (mode2_subheaders) @@ -686,13 +686,13 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg case CdMode1: // If we do not have a DDT V2 for sector prefix, create one - if(ctx->sectorPrefixDdtMini == NULL) + if(ctx->sectorPrefixDdt2 == NULL) { - ctx->sectorPrefixDdtMini = - calloc(1, sizeof(uint16_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + + ctx->sectorPrefixDdt2 = + calloc(1, sizeof(uint32_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + ctx->userDataDdtHeader.overflow)); - if(ctx->sectorPrefixDdtMini == NULL) + if(ctx->sectorPrefixDdt2 == NULL) { FATAL("Could not allocate memory for CD sector prefix DDT"); @@ -702,13 +702,13 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg } // If we do not have a DDT V2 for sector suffix, create one - if(ctx->sectorSuffixDdtMini == NULL) + if(ctx->sectorSuffixDdt2 == NULL) { - ctx->sectorSuffixDdtMini = - calloc(1, sizeof(uint16_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + + ctx->sectorSuffixDdt2 = + calloc(1, sizeof(uint32_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + ctx->userDataDdtHeader.overflow)); - if(ctx->sectorSuffixDdtMini == NULL) + if(ctx->sectorSuffixDdt2 == NULL) { FATAL("Could not allocate memory for CD sector prefix DDT"); @@ -758,8 +758,8 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg if(empty) { - ctx->sectorPrefixDdtMini[corrected_sector_address] = SectorStatusNotDumped; - ctx->sectorSuffixDdtMini[corrected_sector_address] = SectorStatusNotDumped; + ctx->sectorPrefixDdt2[corrected_sector_address] = SectorStatusNotDumped; + ctx->sectorSuffixDdt2[corrected_sector_address] = SectorStatusNotDumped; return aaruf_write_sector(context, sector_address, negative, data + 16, SectorStatusNotDumped, 2048); } @@ -782,13 +782,13 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg } if(prefix_correct) - ctx->sectorPrefixDdtMini[corrected_sector_address] = SectorStatusMode1Correct << 12; + ctx->sectorPrefixDdt2[corrected_sector_address] = SectorStatusMode1Correct << 28; else { // Copy CD prefix from data buffer to prefix buffer memcpy(ctx->sector_prefix + ctx->sector_prefix_offset, data, 16); - ctx->sectorPrefixDdtMini[corrected_sector_address] = (uint16_t)(ctx->sector_prefix_offset / 16); - ctx->sectorPrefixDdtMini[corrected_sector_address] |= SectorStatusErrored << 12; + ctx->sectorPrefixDdt2[corrected_sector_address] = (uint32_t)(ctx->sector_prefix_offset / 16); + ctx->sectorPrefixDdt2[corrected_sector_address] |= SectorStatusErrored << 28; ctx->sector_prefix_offset += 16; // Grow prefix buffer if needed @@ -810,14 +810,13 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg const bool suffix_correct = aaruf_ecc_cd_is_suffix_correct(context, data); if(suffix_correct) - ctx->sectorSuffixDdtMini[corrected_sector_address] = SectorStatusMode1Correct << 12; + ctx->sectorSuffixDdt2[corrected_sector_address] = SectorStatusMode1Correct << 28; else { // Copy CD suffix from data buffer to suffix buffer memcpy(ctx->sector_suffix + ctx->sector_suffix_offset, data + 2064, 288); - ctx->sectorSuffixDdtMini[corrected_sector_address] = - (uint16_t)(ctx->sector_suffix_offset / 288); - ctx->sectorSuffixDdtMini[corrected_sector_address] |= SectorStatusErrored << 12; + ctx->sectorSuffixDdt2[corrected_sector_address] = (uint32_t)(ctx->sector_suffix_offset / 288); + ctx->sectorSuffixDdt2[corrected_sector_address] |= SectorStatusErrored << 28; ctx->sector_suffix_offset += 288; // Grow suffix buffer if needed @@ -842,13 +841,13 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg case CdMode2Form2: case CdMode2Formless: // If we do not have a DDT V2 for sector prefix, create one - if(ctx->sectorPrefixDdtMini == NULL) + if(ctx->sectorPrefixDdt2 == NULL) { - ctx->sectorPrefixDdtMini = - calloc(1, sizeof(uint16_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + + ctx->sectorPrefixDdt2 = + calloc(1, sizeof(uint32_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + ctx->userDataDdtHeader.overflow)); - if(ctx->sectorPrefixDdtMini == NULL) + if(ctx->sectorPrefixDdt2 == NULL) { FATAL("Could not allocate memory for CD sector prefix DDT"); @@ -858,13 +857,13 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg } // If we do not have a DDT V2 for sector suffix, create one - if(ctx->sectorSuffixDdtMini == NULL) + if(ctx->sectorSuffixDdt2 == NULL) { - ctx->sectorSuffixDdtMini = - calloc(1, sizeof(uint16_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + + ctx->sectorSuffixDdt2 = + calloc(1, sizeof(uint32_t) * (ctx->userDataDdtHeader.negative + ctx->imageInfo.Sectors + ctx->userDataDdtHeader.overflow)); - if(ctx->sectorSuffixDdtMini == NULL) + if(ctx->sectorSuffixDdt2 == NULL) { FATAL("Could not allocate memory for CD sector prefix DDT"); @@ -914,8 +913,8 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg if(empty) { - ctx->sectorPrefixDdtMini[corrected_sector_address] = SectorStatusNotDumped; - ctx->sectorSuffixDdtMini[corrected_sector_address] = SectorStatusNotDumped; + ctx->sectorPrefixDdt2[corrected_sector_address] = SectorStatusNotDumped; + ctx->sectorSuffixDdt2[corrected_sector_address] = SectorStatusNotDumped; return aaruf_write_sector(context, sector_address, negative, data + 16, SectorStatusNotDumped, 2328); } @@ -940,14 +939,14 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg } if(prefix_correct) - ctx->sectorPrefixDdtMini[corrected_sector_address] = - (form2 ? SectorStatusMode2Form2Ok : SectorStatusMode2Form1Ok) << 12; + ctx->sectorPrefixDdt2[corrected_sector_address] = + (form2 ? SectorStatusMode2Form2Ok : SectorStatusMode2Form1Ok) << 28; else { // Copy CD prefix from data buffer to prefix buffer memcpy(ctx->sector_prefix + ctx->sector_prefix_offset, data, 16); - ctx->sectorPrefixDdtMini[corrected_sector_address] = (uint16_t)(ctx->sector_prefix_offset / 16); - ctx->sectorPrefixDdtMini[corrected_sector_address] |= SectorStatusErrored << 12; + ctx->sectorPrefixDdt2[corrected_sector_address] = (uint32_t)(ctx->sector_prefix_offset / 16); + ctx->sectorPrefixDdt2[corrected_sector_address] |= SectorStatusErrored << 28; ctx->sector_prefix_offset += 16; // Grow prefix buffer if needed @@ -989,16 +988,16 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg const bool correct_edc = computed_edc == edc; if(correct_edc) - ctx->sectorSuffixDdtMini[corrected_sector_address] = SectorStatusMode2Form2Ok << 12; + ctx->sectorSuffixDdt2[corrected_sector_address] = SectorStatusMode2Form2Ok << 28; else if(edc == 0) - ctx->sectorSuffixDdtMini[corrected_sector_address] = SectorStatusMode2Form2NoCrc << 12; + ctx->sectorSuffixDdt2[corrected_sector_address] = SectorStatusMode2Form2NoCrc << 28; else { // Copy CD suffix from data buffer to suffix buffer memcpy(ctx->sector_suffix + ctx->sector_suffix_offset, data + 2348, 4); - ctx->sectorSuffixDdtMini[corrected_sector_address] = - (uint16_t)(ctx->sector_suffix_offset / 288); - ctx->sectorSuffixDdtMini[corrected_sector_address] |= SectorStatusErrored << 12; + ctx->sectorSuffixDdt2[corrected_sector_address] = + (uint32_t)(ctx->sector_suffix_offset / 288); + ctx->sectorSuffixDdt2[corrected_sector_address] |= SectorStatusErrored << 28; ctx->sector_suffix_offset += 288; // Grow suffix buffer if needed @@ -1033,14 +1032,13 @@ int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool neg const bool correct_edc = computed_edc == edc; if(correct_ecc && correct_edc) - ctx->sectorSuffixDdtMini[corrected_sector_address] = SectorStatusMode2Form1Ok << 12; + ctx->sectorSuffixDdt2[corrected_sector_address] = SectorStatusMode2Form1Ok << 28; else { // Copy CD suffix from data buffer to suffix buffer memcpy(ctx->sector_suffix + ctx->sector_suffix_offset, data + 2072, 280); - ctx->sectorSuffixDdtMini[corrected_sector_address] = - (uint16_t)(ctx->sector_suffix_offset / 288); - ctx->sectorSuffixDdtMini[corrected_sector_address] |= SectorStatusErrored << 12; + ctx->sectorSuffixDdt2[corrected_sector_address] = (uint32_t)(ctx->sector_suffix_offset / 288); + ctx->sectorSuffixDdt2[corrected_sector_address] |= SectorStatusErrored << 28; ctx->sector_suffix_offset += 288; // Grow suffix buffer if needed