diff --git a/include/aaruformat/decls.h b/include/aaruformat/decls.h index a3729a7..58790ac 100644 --- a/include/aaruformat/decls.h +++ b/include/aaruformat/decls.h @@ -79,13 +79,13 @@ AARU_EXPORT void AARU_CALL aaruf_crc64_free(crc64_ctx *ctx); AARU_EXPORT void AARU_CALL aaruf_crc64_slicing(uint64_t *previous_crc, const uint8_t *data, uint32_t len); AARU_EXPORT uint64_t AARU_CALL aaruf_crc64_data(const uint8_t *data, uint32_t len); -AARU_EXPORT int32_t AARU_CALL aaruf_read_sector(void *context, uint64_t sector_address, uint8_t *data, +AARU_EXPORT int32_t AARU_CALL aaruf_read_sector(void *context, uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length); -AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, uint64_t sector_address, uint8_t *data, - uint32_t *length); +AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, uint64_t sector_address, bool negative, + uint8_t *data, uint32_t *length); -AARU_EXPORT int32_t AARU_CALL aaruf_write_sector(void *context, uint64_t sector_address, const uint8_t *data, - uint8_t sector_status, uint32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_write_sector(void *context, uint64_t sector_address, bool negative, + const uint8_t *data, uint8_t sector_status, uint32_t length); AARU_EXPORT int32_t AARU_CALL aaruf_verify_image(void *context); diff --git a/include/internal.h b/include/internal.h index bfb9c36..c85ede6 100644 --- a/include/internal.h +++ b/include/internal.h @@ -39,14 +39,14 @@ void process_checksum_block(aaruformatContext *ctx, const IndexEntry *entry void add_subindex_entries(aaruformatContext *ctx, UT_array *index_entries, IndexEntry *subindex_entry); int32_t decode_ddt_entry_v1(aaruformatContext *ctx, uint64_t sector_address, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status); -int32_t decode_ddt_entry_v2(aaruformatContext *ctx, uint64_t sector_address, uint64_t *offset, uint64_t *block_offset, - uint8_t *sector_status); -int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_address, uint64_t *offset, +int32_t decode_ddt_entry_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t *offset, + uint64_t *block_offset, uint8_t *sector_status); +int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status); -int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, uint64_t *offset, +int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status); -bool set_ddt_entry_v2(aaruformatContext *ctx, uint64_t sector_address, uint64_t offset, uint64_t block_offset, - uint8_t sector_status, uint64_t *ddt_entry); +bool set_ddt_entry_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t offset, + uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry); bool set_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t offset, uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry); bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t offset, diff --git a/src/ddt/ddt_v2.c b/src/ddt/ddt_v2.c index e938613..73874aa 100644 --- a/src/ddt/ddt_v2.c +++ b/src/ddt/ddt_v2.c @@ -484,6 +484,7 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us * * @param ctx Pointer to the aaruformat context containing the loaded DDT structures. * @param sector_address Logical sector address to decode (will be adjusted for negative sectors). + * @param negative Indicates if the sector address is negative. * @param offset Pointer to store the resulting sector offset within the block. * @param block_offset Pointer to store the resulting block offset in the image. * @param sector_status Pointer to store the sector status (dumped, not dumped, etc.). @@ -517,11 +518,11 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us * @warning All output parameters must be valid pointers. No bounds checking is performed * on the sector_address parameter at this level. */ -int32_t decode_ddt_entry_v2(aaruformatContext *ctx, const uint64_t sector_address, uint64_t *offset, +int32_t decode_ddt_entry_v2(aaruformatContext *ctx, const uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status) { - TRACE("Entering decode_ddt_entry_v2(%p, %" PRIu64 ", %llu, %llu, %d)", ctx, sector_address, *offset, *block_offset, - *sector_status); + TRACE("Entering decode_ddt_entry_v2(%p, %" PRIu64 ", %d, %llu, %llu, %d)", ctx, sector_address, negative, *offset, + *block_offset, *sector_status); // Check if the context and image stream are valid if(ctx == NULL || ctx->imageStream == NULL) { @@ -532,9 +533,9 @@ int32_t decode_ddt_entry_v2(aaruformatContext *ctx, const uint64_t sector_addres } if(ctx->userDataDdtHeader.tableShift > 0) - return decode_ddt_multi_level_v2(ctx, sector_address, offset, block_offset, sector_status); + return decode_ddt_multi_level_v2(ctx, sector_address, negative, offset, block_offset, sector_status); - return decode_ddt_single_level_v2(ctx, sector_address, offset, block_offset, sector_status); + return decode_ddt_single_level_v2(ctx, sector_address, negative, offset, block_offset, sector_status); } /** @@ -547,6 +548,7 @@ int32_t decode_ddt_entry_v2(aaruformatContext *ctx, const uint64_t sector_addres * * @param ctx Pointer to the aaruformat context containing the loaded DDT table. * @param sector_address Logical sector address to decode (adjusted for negative sectors). + * @param negative Indicates if the sector address is negative. * @param offset Pointer to store the resulting sector offset within the block. * @param block_offset Pointer to store the resulting block offset in the image. * @param sector_status Pointer to store the sector status (dumped, not dumped, etc.). @@ -596,11 +598,11 @@ int32_t decode_ddt_entry_v2(aaruformatContext *ctx, const uint64_t sector_addres * @warning This function should only be called when tableShift is 0. Calling it with * tableShift > 0 will result in AARUF_ERROR_CANNOT_READ_BLOCK. */ -int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_address, uint64_t *offset, +int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status) { - TRACE("Entering decode_ddt_single_level_v2(%p, %" PRIu64 ", %llu, %llu, %d)", ctx, sector_address, *offset, - *block_offset, *sector_status); + TRACE("Entering decode_ddt_single_level_v2(%p, %" PRIu64 ", %d, %llu, %llu, %d)", ctx, sector_address, negative, + *offset, *block_offset, *sector_status); uint64_t ddt_entry = 0; @@ -621,8 +623,11 @@ int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_addre return AARUF_ERROR_CANNOT_READ_BLOCK; } - // TODO: Take into account the negative and overflow blocks, library-wide - sector_address += ctx->userDataDdtHeader.negative; + // Calculate positive or negative sector + if(negative) + sector_address -= ctx->userDataDdtHeader.negative; + else + sector_address += ctx->userDataDdtHeader.negative; if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) ddt_entry = ctx->userDataDdtMini[sector_address]; @@ -660,8 +665,8 @@ int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_addre *offset = ddt_entry & offset_mask; *block_offset = (ddt_entry >> ctx->userDataDdtHeader.dataShift) * (1 << ctx->userDataDdtHeader.blockAlignmentShift); - TRACE("Exiting decode_ddt_single_level_v2(%p, %" PRIu64 ", %llu, %llu, %d) = AARUF_STATUS_OK", ctx, sector_address, - *offset, *block_offset, *sector_status); + TRACE("Exiting decode_ddt_single_level_v2(%p, %" PRIu64 ", %d, %llu, %llu, %d) = AARUF_STATUS_OK", ctx, + sector_address, negative, *offset, *block_offset, *sector_status); return AARUF_STATUS_OK; } @@ -676,6 +681,7 @@ int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_addre * * @param ctx Pointer to the aaruformat context containing the loaded primary DDT table. * @param sector_address Logical sector address to decode (adjusted for negative sectors). + * @param negative Indicates if the sector address is negative. * @param offset Pointer to store the resulting sector offset within the block. * @param block_offset Pointer to store the resulting block offset in the image. * @param sector_status Pointer to store the sector status (dumped, not dumped, etc.). @@ -752,11 +758,11 @@ int32_t decode_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_addre * @warning No bounds checking is performed on sector_address or calculated DDT positions. * Accessing beyond table boundaries will result in undefined behavior. */ -int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, uint64_t *offset, +int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status) { - TRACE("Entering decode_ddt_multi_level_v2(%p, %" PRIu64 ", %llu, %llu, %d)", ctx, sector_address, *offset, - *block_offset, *sector_status); + TRACE("Entering decode_ddt_multi_level_v2(%p, %" PRIu64 ", %d, %llu, %llu, %d)", ctx, sector_address, negative, + *offset, *block_offset, *sector_status); uint64_t ddt_entry = 0; uint8_t lzma_properties[LZMA_PROPERTIES_LENGTH]; @@ -786,8 +792,11 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres return AARUF_ERROR_CANNOT_READ_BLOCK; } - // TODO: Take into account the negative and overflow blocks, library-wide - sector_address += ctx->userDataDdtHeader.negative; + // Calculate positive or negative sector + if(negative) + sector_address -= ctx->userDataDdtHeader.negative; + else + sector_address += ctx->userDataDdtHeader.negative; items_per_ddt_entry = 1 << ctx->userDataDdtHeader.tableShift; ddt_position = sector_address / items_per_ddt_entry; @@ -1011,8 +1020,8 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres *offset = ddt_entry & offset_mask; *block_offset = (ddt_entry >> ctx->userDataDdtHeader.dataShift) * (1 << ctx->userDataDdtHeader.blockAlignmentShift); - TRACE("Exiting decode_ddt_multi_level_v2(%p, %" PRIu64 ", %llu, %llu, %d) = AARUF_STATUS_OK", ctx, sector_address, - *offset, *block_offset, *sector_status); + TRACE("Exiting decode_ddt_multi_level_v2(%p, %" PRIu64 ", %d, %llu, %llu, %d) = AARUF_STATUS_OK", ctx, + sector_address, negative, *offset, *block_offset, *sector_status); return AARUF_STATUS_OK; } @@ -1023,6 +1032,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres * * @param ctx Pointer to the aaruformat context. * @param sector_address Logical sector address to set. + * @param negative Indicates if the sector address is negative. * @param offset Offset to set for the sector. * @param block_offset Block offset to set for the sector. * @param sector_status Status to set for the sector. @@ -1031,11 +1041,11 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres * @return Returns one of the following status codes: * @retval true if the entry was set successfully, false otherwise. */ -bool set_ddt_entry_v2(aaruformatContext *ctx, const uint64_t sector_address, const uint64_t offset, +bool set_ddt_entry_v2(aaruformatContext *ctx, const uint64_t sector_address, bool negative, const uint64_t offset, const uint64_t block_offset, const uint8_t sector_status, uint64_t *ddt_entry) { - TRACE("Entering set_ddt_entry_v2(%p, %" PRIu64 ", %llu, %llu, %d)", ctx, sector_address, offset, block_offset, - sector_status); + TRACE("Entering set_ddt_entry_v2(%p, %" PRIu64 ", %d, %llu, %llu, %d)", ctx, sector_address, negative, offset, + block_offset, sector_status); // Check if the context and image stream are valid if(ctx == NULL || ctx->imageStream == NULL) @@ -1070,8 +1080,8 @@ bool set_ddt_single_level_v2(aaruformatContext *ctx, uint64_t sector_address, co const uint64_t offset, const uint64_t block_offset, const uint8_t sector_status, uint64_t *ddt_entry) { - TRACE("Entering set_ddt_single_level_v2(%p, %" PRIu64 ", %llu, %llu, %d)", ctx, sector_address, offset, - block_offset, sector_status); + TRACE("Entering set_ddt_single_level_v2(%p, %" PRIu64 ", %d, %llu, %llu, %d)", ctx, sector_address, negative, + offset, block_offset, sector_status); // Check if the context and image stream are valid if(ctx == NULL || ctx->imageStream == NULL) diff --git a/src/read.c b/src/read.c index f72a1a4..e4d4e5f 100644 --- a/src/read.c +++ b/src/read.c @@ -145,6 +145,7 @@ int32_t aaruf_read_media_tag(void *context, uint8_t *data, const int32_t tag, ui * * @param context Pointer to the aaruformat context. * @param sector_address The logical sector address to read from. + * @param negative Indicates if the sector address is negative. * @param data Pointer to buffer where sector data will be stored. Can be NULL to query length. * @param length Pointer to variable containing buffer size on input, actual data length on output. * @@ -237,9 +238,9 @@ int32_t aaruf_read_media_tag(void *context, uint8_t *data, const int32_t tag, ui * @warning Sector addresses are zero-based. The maximum valid address is * ctx->imageInfo.Sectors - 1. */ -int32_t aaruf_read_sector(void *context, const uint64_t sector_address, uint8_t *data, uint32_t *length) +int32_t aaruf_read_sector(void *context, const uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length) { - TRACE("Entering aaruf_read_sector(%p, %" PRIu64 ", %p, %u)", context, sector_address, data, *length); + TRACE("Entering aaruf_read_sector(%p, %" PRIu64 ", %d, %p, %u)", context, sector_address, negative, data, *length); aaruformatContext *ctx = NULL; uint64_t offset = 0; @@ -281,9 +282,17 @@ int32_t aaruf_read_sector(void *context, const uint64_t sector_address, uint8_t } if(ctx->ddtVersion == 1) + { + if(negative) + { + FATAL("Negative sector addresses not supported in this image"); + return AARUF_ERROR_SECTOR_OUT_OF_BOUNDS; + } + error_no = decode_ddt_entry_v1(ctx, sector_address, &offset, &block_offset, §or_status); + } else if(ctx->ddtVersion == 2) - error_no = decode_ddt_entry_v2(ctx, sector_address, &offset, &block_offset, §or_status); + error_no = decode_ddt_entry_v2(ctx, sector_address, negative, &offset, &block_offset, §or_status); if(error_no != AARUF_STATUS_OK) { @@ -635,7 +644,7 @@ int32_t aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sec for(int i = 0; i < ctx->numberOfDataTracks; i++) if(ctx->dataTracks[i].sequence == track) - return aaruf_read_sector(context, ctx->dataTracks[i].start + sector_address, data, length); + return aaruf_read_sector(context, ctx->dataTracks[i].start + sector_address, false, data, length); TRACE("Track %d not found", track); TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_TRACK_NOT_FOUND"); @@ -654,6 +663,7 @@ int32_t aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sec * * @param context Pointer to the aaruformat context. * @param sector_address The logical sector address to read from. + * @param negative Indicates if the sector address is negative. * @param data Pointer to buffer where complete sector data will be stored. Can be NULL to query length. * @param length Pointer to variable containing buffer size on input, actual data length on output. * @@ -741,9 +751,9 @@ int32_t aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sec * @warning Not all AaruFormat images contain the metadata necessary for long sector * reading. Some images may only support basic sector reading via aaruf_read_sector(). */ -int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uint8_t *data, uint32_t *length) +int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length) { - TRACE("Entering aaruf_read_sector_long(%p, %" PRIu64 ", %p, %u)", context, sector_address, data, *length); + TRACE("Entering aaruf_read_sector_long(%p, %" PRIu64 ", %d, %p, %u)", context, sector_address, data, *length); const aaruformatContext *ctx = NULL; uint32_t bare_length = 0; @@ -773,6 +783,14 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin return AARUF_ERROR_NOT_AARUFORMAT; } + uint64_t corrected_sector_address = sector_address; + + // Calculate positive or negative sector + if(negative) + corrected_sector_address -= ctx->userDataDdtHeader.negative; + else + corrected_sector_address += ctx->userDataDdtHeader.negative; + switch(ctx->imageInfo.XmlMediaType) { case OpticalDisc: @@ -786,10 +804,10 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin } if((ctx->sectorSuffix == NULL || ctx->sectorPrefix == NULL) && (ctx->sectorSuffixCorrected == NULL || ctx->sectorPrefixCorrected == NULL)) - return aaruf_read_sector(context, sector_address, data, length); + return aaruf_read_sector(context, sector_address, negative, data, length); bare_length = 0; - aaruf_read_sector(context, sector_address, NULL, &bare_length); + aaruf_read_sector(context, sector_address, negative, NULL, &bare_length); TRACE("Allocating memory for bare data"); bare_data = (uint8_t *)malloc(bare_length); @@ -802,7 +820,7 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin return AARUF_ERROR_NOT_ENOUGH_MEMORY; } - res = aaruf_read_sector(context, sector_address, bare_data, &bare_length); + res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length); if(res < AARUF_STATUS_OK) { @@ -840,20 +858,20 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin memcpy(data + 16, bare_data, 2048); if(ctx->sectorPrefix != NULL) - memcpy(data, ctx->sectorPrefix + sector_address * 16, 16); + memcpy(data, ctx->sectorPrefix + corrected_sector_address * 16, 16); else if(ctx->sectorPrefixDdt != NULL) { - if((ctx->sectorPrefixDdt[sector_address] & CD_XFIX_MASK) == Correct) + if((ctx->sectorPrefixDdt[corrected_sector_address] & CD_XFIX_MASK) == Correct) { aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address); res = AARUF_STATUS_OK; } - else if((ctx->sectorPrefixDdt[sector_address] & CD_XFIX_MASK) == NotDumped) + else if((ctx->sectorPrefixDdt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; else memcpy(data, ctx->sectorPrefixCorrected + - ((ctx->sectorPrefixDdt[sector_address] & CD_DFIX_MASK) - 1) * 16, + ((ctx->sectorPrefixDdt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 16, 16); } else @@ -865,20 +883,20 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin if(res != AARUF_STATUS_OK) return res; if(ctx->sectorSuffix != NULL) - memcpy(data + 2064, ctx->sectorSuffix + sector_address * 288, 288); + memcpy(data + 2064, ctx->sectorSuffix + corrected_sector_address * 288, 288); else if(ctx->sectorSuffixDdt != NULL) { - if((ctx->sectorSuffixDdt[sector_address] & CD_XFIX_MASK) == Correct) + if((ctx->sectorSuffixDdt[corrected_sector_address] & CD_XFIX_MASK) == Correct) { aaruf_ecc_cd_reconstruct(ctx->eccCdContext, data, trk.type); res = AARUF_STATUS_OK; } - else if((ctx->sectorSuffixDdt[sector_address] & CD_XFIX_MASK) == NotDumped) + else if((ctx->sectorSuffixDdt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; else memcpy(data + 2064, ctx->sectorSuffixCorrected + - ((ctx->sectorSuffixDdt[sector_address] & CD_DFIX_MASK) - 1) * 288, + ((ctx->sectorSuffixDdt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 288, 288); } else @@ -892,20 +910,20 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin case CdMode2Form1: case CdMode2Form2: if(ctx->sectorPrefix != NULL) - memcpy(data, ctx->sectorPrefix + sector_address * 16, 16); + memcpy(data, ctx->sectorPrefix + corrected_sector_address * 16, 16); else if(ctx->sectorPrefixDdt != NULL) { - if((ctx->sectorPrefixDdt[sector_address] & CD_XFIX_MASK) == Correct) + if((ctx->sectorPrefixDdt[corrected_sector_address] & CD_XFIX_MASK) == Correct) { aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address); res = AARUF_STATUS_OK; } - else if((ctx->sectorPrefixDdt[sector_address] & CD_XFIX_MASK) == NotDumped) + else if((ctx->sectorPrefixDdt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; else memcpy(data, ctx->sectorPrefixCorrected + - ((ctx->sectorPrefixDdt[sector_address] & CD_DFIX_MASK) - 1) * 16, + ((ctx->sectorPrefixDdt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 16, 16); } else @@ -918,21 +936,21 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin if(ctx->mode2Subheaders != NULL && ctx->sectorSuffixDdt != NULL) { - memcpy(data + 16, ctx->mode2Subheaders + sector_address * 8, 8); + memcpy(data + 16, ctx->mode2Subheaders + corrected_sector_address * 8, 8); - if((ctx->sectorSuffixDdt[sector_address] & CD_XFIX_MASK) == Mode2Form1Ok) + if((ctx->sectorSuffixDdt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form1Ok) { memcpy(data + 24, bare_data, 2048); aaruf_ecc_cd_reconstruct(ctx->eccCdContext, data, CdMode2Form1); } - else if((ctx->sectorSuffixDdt[sector_address] & CD_XFIX_MASK) == Mode2Form2Ok || - (ctx->sectorSuffixDdt[sector_address] & CD_XFIX_MASK) == Mode2Form2NoCrc) + else if((ctx->sectorSuffixDdt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2Ok || + (ctx->sectorSuffixDdt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2NoCrc) { memcpy(data + 24, bare_data, 2324); - if((ctx->sectorSuffixDdt[sector_address] & CD_XFIX_MASK) == Mode2Form2Ok) + if((ctx->sectorSuffixDdt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2Ok) aaruf_ecc_cd_reconstruct(ctx->eccCdContext, data, CdMode2Form2); } - else if((ctx->sectorSuffixDdt[sector_address] & CD_XFIX_MASK) == NotDumped) + else if((ctx->sectorSuffixDdt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped) res = AARUF_STATUS_SECTOR_NOT_DUMPED; else // Mode 2 where ECC failed @@ -940,7 +958,7 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin } else if(ctx->mode2Subheaders != NULL) { - memcpy(data + 16, ctx->mode2Subheaders + sector_address * 8, 8); + memcpy(data + 16, ctx->mode2Subheaders + corrected_sector_address * 8, 8); memcpy(data + 24, bare_data, 2328); } else @@ -963,7 +981,7 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin case AppleSonyDS: case AppleWidget: case PriamDataTower: - if(ctx->sectorSubchannel == NULL) return aaruf_read_sector(context, sector_address, data, length); + if(ctx->sectorSubchannel == NULL) return aaruf_read_sector(context, sector_address, negative, data, length); switch(ctx->imageInfo.MediaType) { @@ -1008,7 +1026,7 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin return AARUF_ERROR_NOT_ENOUGH_MEMORY; } - res = aaruf_read_sector(context, sector_address, bare_data, &bare_length); + res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length); if(bare_length != 512) { @@ -1019,7 +1037,7 @@ int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, uin return res; } - memcpy(data, ctx->sectorSubchannel + sector_address * tag_length, tag_length); + memcpy(data, ctx->sectorSubchannel + corrected_sector_address * tag_length, tag_length); memcpy(data, bare_data, 512); free(bare_data); diff --git a/src/write.c b/src/write.c index 413abeb..2a471f6 100644 --- a/src/write.c +++ b/src/write.c @@ -36,6 +36,7 @@ * * @param context Pointer to the aaruformat context. * @param sector_address Logical sector address to write. + * @param negative Indicates if the sector address is negative. * @param data Pointer to the data buffer to write. * @param sector_status Status of the sector to write. * @param length Length of the data buffer. @@ -96,11 +97,11 @@ * @warning No bounds checking is performed on sector_address. Writing beyond media limits * may result in undefined behavior (TODO: implement bounds checking). */ -int32_t aaruf_write_sector(void *context, uint64_t sector_address, const uint8_t *data, uint8_t sector_status, - uint32_t length) +int32_t aaruf_write_sector(void *context, uint64_t sector_address, bool negative, const uint8_t *data, + uint8_t sector_status, uint32_t length) { - TRACE("Entering aaruf_write_sector(%p, %" PRIu64 ", %p, %u, %u)", context, sector_address, data, sector_status, - length); + TRACE("Entering aaruf_write_sector(%p, %" PRIu64 ", %d, %p, %u, %u)", context, sector_address, negative, data, + sector_status, length); // Check context is correct AaruFormat context if(context == NULL) @@ -169,8 +170,8 @@ int32_t aaruf_write_sector(void *context, uint64_t sector_address, const uint8_t bool existing = lookup_map(ctx->sectorHashMap, hash, &ddt_entry); TRACE("Block does %s exist in deduplication map", existing ? "already" : "not yet"); - ddt_ok = set_ddt_entry_v2(ctx, sector_address, ctx->currentBlockOffset, ctx->nextBlockPosition, sector_status, - &ddt_entry); + ddt_ok = set_ddt_entry_v2(ctx, sector_address, negative, ctx->currentBlockOffset, ctx->nextBlockPosition, + sector_status, &ddt_entry); if(!ddt_ok) { TRACE("Exiting aaruf_write_sector() = AARUF_ERROR_CANNOT_SET_DDT_ENTRY"); @@ -188,8 +189,8 @@ int32_t aaruf_write_sector(void *context, uint64_t sector_address, const uint8_t insert_map(ctx->sectorHashMap, hash, ddt_entry); } else - ddt_ok = set_ddt_entry_v2(ctx, sector_address, ctx->currentBlockOffset, ctx->nextBlockPosition, sector_status, - &ddt_entry); + ddt_ok = set_ddt_entry_v2(ctx, sector_address, negative, ctx->currentBlockOffset, ctx->nextBlockPosition, + sector_status, &ddt_entry); if(!ddt_ok) { diff --git a/tool/cli_compare.c b/tool/cli_compare.c index 401256c..07b2d63 100644 --- a/tool/cli_compare.c +++ b/tool/cli_compare.c @@ -106,8 +106,8 @@ int cli_compare(const char *path1, const char *path2) buffer1_length = ctx1->imageInfo.SectorSize; buffer2_length = ctx2->imageInfo.SectorSize; - read_result1 = aaruf_read_sector(ctx1, sector, buffer1, &buffer1_length); - read_result2 = aaruf_read_sector(ctx2, sector, buffer2, &buffer2_length); + read_result1 = aaruf_read_sector(ctx1, sector, false, buffer1, &buffer1_length); + read_result2 = aaruf_read_sector(ctx2, sector, false, buffer2, &buffer2_length); // Handle read errors or missing sectors const bool sector1_available = read_result1 == AARUF_STATUS_OK; diff --git a/tool/compare.c b/tool/compare.c index 3ecb510..9f16db9 100644 --- a/tool/compare.c +++ b/tool/compare.c @@ -489,7 +489,7 @@ int compare(const char *path1, const char *path2) tb_printf(2, height - 5, TB_WHITE | TB_BOLD, TB_BLUE, "Comparing sector %llu of %llu", i + 1, sectors); draw_progress_bar(height - 4, i * 100 / sectors); - errno = aaruf_read_sector(ctx1, i, buffer1, §orSize); + errno = aaruf_read_sector(ctx1, i, false, buffer1, §orSize); if(errno != AARUF_STATUS_OK && errno != AARUF_STATUS_SECTOR_NOT_DUMPED) { tb_printf(2, lr++, TB_RED | TB_BOLD, TB_BLUE, "Error reading sector %llu: %s", i, errno); @@ -497,7 +497,7 @@ int compare(const char *path1, const char *path2) continue; } - errno = aaruf_read_sector(ctx2, i, buffer2, §orSize); + errno = aaruf_read_sector(ctx2, i, false, buffer2, §orSize); if(errno != AARUF_STATUS_OK && errno != AARUF_STATUS_SECTOR_NOT_DUMPED) { tb_printf(2, rr++, TB_RED | TB_BOLD, TB_BLUE, "Error reading sector %llu: %s", i, errno); diff --git a/tool/convert.c b/tool/convert.c index 7ac559a..46b7417 100644 --- a/tool/convert.c +++ b/tool/convert.c @@ -93,7 +93,7 @@ int convert(const char *input_path, const char *output_path) } // Read sector from input - res = aaruf_read_sector(input_ctx, sector, sector_data, &read_length); + res = aaruf_read_sector(input_ctx, sector, false, sector_data, &read_length); if(res != AARUF_STATUS_OK) { printf("\nError %d when reading sector %llu from input image.\n", res, (unsigned long long)sector); @@ -101,7 +101,7 @@ int convert(const char *input_path, const char *output_path) } // Write sector to output - res = aaruf_write_sector(output_ctx, sector, sector_data, SectorStatusDumped, read_length); + res = aaruf_write_sector(output_ctx, sector, false, sector_data, SectorStatusDumped, read_length); if(res != AARUF_STATUS_OK) { printf("\nError %d when writing sector %llu to output image.\n", res, (unsigned long long)sector); diff --git a/tool/read.c b/tool/read.c index 280932a..229c800 100644 --- a/tool/read.c +++ b/tool/read.c @@ -39,7 +39,7 @@ int read(const unsigned long long sector_no, const char *path) return errno; } - res = aaruf_read_sector(ctx, sector_no, NULL, &length); + res = aaruf_read_sector(ctx, sector_no, false, NULL, &length); if(res != AARUF_STATUS_OK && res != AARUF_ERROR_BUFFER_TOO_SMALL) { @@ -58,7 +58,7 @@ int read(const unsigned long long sector_no, const char *path) return AARUF_ERROR_NOT_ENOUGH_MEMORY; } - res = aaruf_read_sector(ctx, sector_no, data, &length); + res = aaruf_read_sector(ctx, sector_no, false, data, &length); if(res != AARUF_STATUS_OK) { @@ -91,7 +91,7 @@ int read_long(const unsigned long long sector_no, const char *path) return errno; } - res = aaruf_read_sector_long(ctx, sector_no, NULL, &length); + res = aaruf_read_sector_long(ctx, sector_no, false, NULL, &length); if(res != AARUF_STATUS_OK && res != AARUF_ERROR_BUFFER_TOO_SMALL) { @@ -110,7 +110,7 @@ int read_long(const unsigned long long sector_no, const char *path) return AARUF_ERROR_NOT_ENOUGH_MEMORY; } - res = aaruf_read_sector_long(ctx, sector_no, data, &length); + res = aaruf_read_sector_long(ctx, sector_no, false, data, &length); if(res != AARUF_STATUS_OK) { diff --git a/tool/verify.c b/tool/verify.c index 83958c2..fa6e294 100644 --- a/tool/verify.c +++ b/tool/verify.c @@ -83,7 +83,7 @@ int verify_sectors(const char *path) for(uint64_t s = 0; s < ctx->imageInfo.Sectors; s++) { printf("\rVerifying sector %llu...", s); - res = aaruf_read_sector_long(ctx, s, buffer, &buffer_len); + res = aaruf_read_sector_long(ctx, s, buffer, false, &buffer_len); if(res != AARUF_STATUS_OK) {