diff --git a/include/internal.h b/include/internal.h index a634863..223d2f2 100644 --- a/include/internal.h +++ b/include/internal.h @@ -39,5 +39,7 @@ 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 sectorAddress, uint64_t *offset, uint64_t *blockOffset, uint8_t *sectorStatus); +int32_t decode_ddt_entry_v2(aaruformatContext *ctx, uint64_t sectorAddress, uint64_t *offset, uint64_t *blockOffset, + uint8_t *sectorStatus); #endif // LIBAARUFORMAT_INTERNAL_H diff --git a/src/ddt/ddt_v2.c b/src/ddt/ddt_v2.c index 2a79f4b..a77ba34 100644 --- a/src/ddt/ddt_v2.c +++ b/src/ddt/ddt_v2.c @@ -377,5 +377,59 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *foundUse } } + return AARUF_STATUS_OK; +} + +int32_t decode_ddt_entry_v2(aaruformatContext *ctx, uint64_t sectorAddress, uint64_t *offset, uint64_t *blockOffset, + uint8_t *sectorStatus) +{ + uint64_t ddtEntry = 0; + + // Check if the context and image stream are valid + if(ctx == NULL || ctx->imageStream == NULL) + { + fprintf(stderr, "Invalid context or image stream.\n"); + return AARUF_ERROR_NOT_AARUFORMAT; + } + + // TODO: Implement multi-level tables + if(ctx->userDataDdtHeader.tableShift != 0) return AARUF_ERROR_CANNOT_READ_BLOCK; + + // TODO: Take into account the negative and overflow blocks, library-wide + sectorAddress += ctx->userDataDdtHeader.negative; + + if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) + ddtEntry = ctx->userDataDdtMini[sectorAddress]; + else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) + ddtEntry = ctx->userDataDdtBig[sectorAddress]; + else + { + fprintf(stderr, "libaaruformat: Unknown DDT size type %d.\n", ctx->userDataDdtHeader.sizeType); + return AARUF_ERROR_CANNOT_READ_BLOCK; + } + + if(ddtEntry == 0) + { + *sectorStatus = SectorStatusNotDumped; + *offset = 0; + *blockOffset = 0; + return AARUF_STATUS_OK; + } + + if(ctx->userDataDdtHeader.sizeType == SmallDdtSizeType) + { + *sectorStatus = ddtEntry >> 12; + ddtEntry &= 0xfff; + } + else if(ctx->userDataDdtHeader.sizeType == BigDdtSizeType) + { + *sectorStatus = ddtEntry >> 28; + ddtEntry &= 0x0fffffff; + } + + const uint64_t offsetMask = (uint64_t)((1 << ctx->userDataDdtHeader.dataShift) - 1); + *offset = (ddtEntry & offsetMask) * (1 << ctx->userDataDdtHeader.blockAlignmentShift); + *blockOffset = ddtEntry >> ctx->userDataDdtHeader.dataShift; + return AARUF_STATUS_OK; } \ No newline at end of file diff --git a/src/read.c b/src/read.c index e265069..276b52b 100644 --- a/src/read.c +++ b/src/read.c @@ -81,7 +81,7 @@ int32_t aaruf_read_sector(void *context, uint64_t sectorAddress, uint8_t *data, if(ctx->ddtVersion == 1) errorNo = decode_ddt_entry_v1(ctx, sectorAddress, &offset, &blockOffset, §orStatus); else if(ctx->ddtVersion == 2) - return AARUF_ERROR_CANNOT_READ_BLOCK; + errorNo = decode_ddt_entry_v2(ctx, sectorAddress, &offset, &blockOffset, §orStatus); if(errorNo != AARUF_STATUS_OK) return errorNo;