Add function to serialize CD sector suffix block with EDC/ECC captures

This commit is contained in:
2025-10-03 23:10:49 +01:00
parent 74ba5c8bfe
commit dc0dbddddd

View File

@@ -774,6 +774,84 @@ static void write_sector_prefix(aaruformatContext *ctx)
}
}
/**
* @brief Serialize the optional CD sector suffix block (EDC/ECC region capture).
*
* The sector suffix contains trailing integrity and redundancy bytes of a raw CD sector that
* follow the user data area. Depending on the mode this includes:
* - Mode 1: 4-byte EDC, 8-byte reserved, 276 bytes (P/Q layers) ECC = 288 bytes total.
* - Mode 2 Form 1: 4-byte EDC, 8 reserved, 276 ECC = 288 bytes.
* - Mode 2 Form 2: 4-byte EDC only (no ECC) but when an error is detected the implementation
* may still store a 288-byte suffix container for uniformity when capturing errored data.
*
* During writing, when an error or uncorrectable condition is detected for a sector's suffix,
* the 288-byte trailing portion (starting at offset 2064 for Mode 1 / Form 1 or 2348/2349 for
* other layouts) is copied into an in-memory expandable buffer pointed to by ctx->sector_suffix.
* The per-sector DDT entry encodes either an inlined status (OK / No CRC / etc.) or an index to
* the stored suffix (ctx->sector_suffix_offset / 288). This function serializes the accumulated
* suffix buffer as a DataBlock of type CdSectorSuffix if any suffix bytes were stored.
*
* Layout considerations:
* - The block length is exactly the number of bytes copied (ctx->sector_suffix_offset).
* - No compression is applied; CRC64 is calculated on the raw suffix stream for integrity.
* - The write position is aligned to the DDT block alignment (2^blockAlignmentShift).
*
* Indexing: An IndexEntry is appended so later readers can locate the suffix collection. Absence
* of this block implies no per-sector suffix captures were required (all suffixes considered OK).
*
* Thread / reentrancy: This routine is called only once during finalization (aaruf_close) in a
* single-threaded context; no synchronization is performed.
*
* @param ctx Pointer to an initialized aaruformatContext in write mode. Must not be NULL.
* @internal
*/
static void write_sector_suffix(aaruformatContext *ctx)
{
if(ctx->sector_suffix == NULL) return;
fseek(ctx->imageStream, 0, SEEK_END);
long suffix_position = ftell(ctx->imageStream);
// Align index position to block boundary if needed
const uint64_t alignment_mask = (1ULL << ctx->userDataDdtHeader.blockAlignmentShift) - 1;
if(suffix_position & alignment_mask)
{
const uint64_t aligned_position = suffix_position + alignment_mask & ~alignment_mask;
fseek(ctx->imageStream, aligned_position, SEEK_SET);
suffix_position = aligned_position;
}
TRACE("Writing sector suffix block at position %ld", suffix_position);
BlockHeader suffix_block = {0};
suffix_block.identifier = DataBlock;
suffix_block.type = CdSectorSuffix;
suffix_block.compression = None;
suffix_block.length = (uint32_t)ctx->sector_suffix_offset;
suffix_block.cmpLength = suffix_block.length;
// Calculate CRC64
suffix_block.crc64 = aaruf_crc64_data(ctx->sector_suffix, suffix_block.length);
suffix_block.cmpCrc64 = suffix_block.crc64;
// Write header
if(fwrite(&suffix_block, sizeof(BlockHeader), 1, ctx->imageStream) == 1)
{
// Write data
const size_t written_bytes = fwrite(ctx->sector_suffix, suffix_block.length, 1, ctx->imageStream);
if(written_bytes == 1)
{
TRACE("Successfully wrote CD sector suffix block (%" PRIu64 " bytes)", suffix_block.length);
// Add suffix block to index
TRACE("Adding CD sector suffix block to index");
IndexEntry suffix_index_entry;
suffix_index_entry.blockType = DataBlock;
suffix_index_entry.dataType = CdSectorSuffix;
suffix_index_entry.offset = suffix_position;
utarray_push_back(ctx->indexEntries, &suffix_index_entry);
TRACE("Added CD sector suffix block index entry at offset %" PRIu64, suffix_position);
}
}
}
/**
* @brief Serialize the accumulated index entries at the end of the image and back-patch the header.
*
@@ -997,6 +1075,9 @@ int aaruf_close(void *context)
// Write CD sector prefix data block
write_sector_prefix(ctx);
// Write CD sector suffix data block (EDC/ECC captures)
write_sector_suffix(ctx);
// Write the complete index at the end of the file
res = write_index_block(ctx);
if(res != AARUF_STATUS_OK) return res;