Implement support for reading file format header version 2.

This commit is contained in:
2025-08-02 20:23:32 +01:00
parent 9a5a994702
commit b504c8392d
10 changed files with 71 additions and 46 deletions

View File

@@ -30,7 +30,15 @@
#define AARU_MAGIC 0x544D524655524141
/** Image format version. A change in this number indicates an incompatible change to the format that prevents older
* implementations from reading it correctly, if at all. */
#define AARUF_VERSION 1
#define AARUF_VERSION 2
/** First version of AaruFormat, created in C#.
* CRC64 was byte-swapped
*/
#define AARUF_VERSION_V1 1
/** Second version of AaruFormat, created in C.
* Introduced new header, many new features, and blocks.
*/
#define AARUF_VERSION_V2 2
/** Maximum read cache size, 512MiB. */
#define MAX_CACHE_SIZE 536870912
/** Size in bytes of LZMA properties. */

View File

@@ -34,16 +34,18 @@
#define SHA256_DIGEST_LENGTH 32
#endif
typedef struct Crc64Context {
typedef struct Crc64Context
{
uint64_t finalSeed;
uint64_t table[256];
uint64_t hashInt;
} Crc64Context;
typedef struct CdEccContext {
bool initedEdc;
uint8_t *eccBTable;
uint8_t *eccFTable;
typedef struct CdEccContext
{
bool initedEdc;
uint8_t *eccBTable;
uint8_t *eccFTable;
uint32_t *edcTable;
} CdEccContext;
@@ -73,7 +75,7 @@ typedef struct aaruformatContext
uint8_t libraryMajorVersion;
uint8_t libraryMinorVersion;
FILE *imageStream;
AaruHeader header;
AaruHeaderV2 header;
uint8_t *sectorPrefix;
uint8_t *sectorPrefixCorrected;
uint8_t *sectorSuffix;

View File

@@ -219,7 +219,7 @@ int32_t process_data_block(aaruformatContext *ctx, IndexEntry *entry)
crc64 = aaruf_crc64_data(data, blockHeader.length);
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != blockHeader.crc64)
{

View File

@@ -79,7 +79,7 @@ void process_dumphw_block(aaruformatContext *ctx, const IndexEntry *entry)
crc64 = aaruf_crc64_data(data, ctx->dumpHardwareHeader.length);
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != ctx->dumpHardwareHeader.crc64)
{

View File

@@ -87,7 +87,7 @@ void process_tracks_block(aaruformatContext *ctx, const IndexEntry *entry)
crc64 = aaruf_crc64_data((const uint8_t *)ctx->trackEntries, ctx->tracksHeader.entries * sizeof(TrackEntry));
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != ctx->tracksHeader.crc64)
{

View File

@@ -107,7 +107,7 @@ int32_t verify_index_v1(aaruformatContext *ctx)
crc64 = aaruf_crc64_data((const uint8_t *)index_entries, sizeof(IndexEntry) * index_header.entries);
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != index_header.crc64)
{

View File

@@ -107,7 +107,7 @@ int32_t verify_index_v2(aaruformatContext *ctx)
crc64 = aaruf_crc64_data((const uint8_t *)index_entries, sizeof(IndexEntry) * index_header.entries);
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != index_header.crc64)
{

View File

@@ -76,6 +76,21 @@ void *aaruf_open(const char *filepath)
return NULL;
}
// Read new header version
if(ctx->header.imageMajorVersion >= AARUF_VERSION_V2)
{
fseek(ctx->imageStream, 0, SEEK_SET);
readBytes = fread(&ctx->header, 1, sizeof(AaruHeaderV2), ctx->imageStream);
if(readBytes != sizeof(AaruHeaderV2))
{
free(ctx);
errno = AARUF_ERROR_FILE_TOO_SMALL;
return NULL;
}
}
if(ctx->header.imageMajorVersion > AARUF_VERSION)
{
free(ctx);

View File

@@ -137,7 +137,7 @@ int32_t aaruf_verify_image(void *context)
aaruf_crc64_final(crc64_context, &crc64);
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != block_header.cmpCrc64)
{
@@ -180,7 +180,7 @@ int32_t aaruf_verify_image(void *context)
aaruf_crc64_final(crc64_context, &crc64);
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != ddt_header.cmpCrc64)
{
@@ -214,7 +214,7 @@ int32_t aaruf_verify_image(void *context)
aaruf_crc64_final(crc64_context, &crc64);
// Due to how C# wrote it, it is effectively reversed
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
if(ctx->header.imageMajorVersion <= AARUF_VERSION_V1) crc64 = bswap_64(crc64);
if(crc64 != tracks_header.crc64)
{

View File

@@ -29,13 +29,13 @@
int info(char *path)
{
aaruformatContext *ctx = NULL;
char *strBuffer = NULL;
UErrorCode u_error_code = U_ZERO_ERROR;
uint i = 0, j = 0;
mediaTagEntry const *mediaTag = NULL;
aaruformatContext *ctx = NULL;
char *strBuffer = NULL;
UErrorCode u_error_code = U_ZERO_ERROR;
uint i = 0, j = 0;
mediaTagEntry const *mediaTag = NULL;
mediaTagEntry const *tmpMediaTag = NULL;
UChar ustr[128];
UChar ustr[128];
ctx = aaruf_open(path);
@@ -59,7 +59,7 @@ int info(char *path)
printf("\tApplication version: %d.%d\n", ctx->header.applicationMajorVersion, ctx->header.applicationMinorVersion);
printf("\tImage format version: %d.%d\n", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
printf("\tMedia type: %d\n", ctx->header.mediaType);
printf("\tMedia type: %u\n", ctx->header.mediaType);
printf("\tIndex offset: %llu\n", ctx->header.indexOffset);
printf("\tCreation time: %lld\n", ctx->header.creationTime);
printf("\tLast written time: %lld\n", ctx->header.lastWrittenTime);
@@ -103,8 +103,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.creatorLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.creatorLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.creatorLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.creatorLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.creatorLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.creatorOffset),
@@ -115,8 +115,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.commentsLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.commentsLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.commentsLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.commentsLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.commentsLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.commentsOffset),
@@ -127,8 +127,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.mediaTitleLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaTitleLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaTitleLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.mediaTitleLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.mediaTitleLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.mediaTitleOffset),
@@ -139,8 +139,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.mediaManufacturerLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaManufacturerLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaManufacturerLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.mediaManufacturerLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.mediaManufacturerLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.mediaManufacturerOffset),
@@ -151,8 +151,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.mediaModelLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaModelLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaModelLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.mediaModelLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.mediaModelLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.mediaModelOffset),
@@ -163,8 +163,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.mediaSerialNumberLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaSerialNumberLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaSerialNumberLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.mediaSerialNumberLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.mediaSerialNumberLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.mediaSerialNumberOffset),
@@ -175,8 +175,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.mediaBarcodeLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaBarcodeLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaBarcodeLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.mediaBarcodeLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.mediaBarcodeLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.mediaBarcodeOffset),
@@ -187,8 +187,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.mediaPartNumberLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaPartNumberLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.mediaPartNumberLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.mediaPartNumberLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.mediaPartNumberLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.mediaPartNumberOffset),
@@ -199,8 +199,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.driveManufacturerLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveManufacturerLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveManufacturerLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.driveManufacturerLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.driveManufacturerLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.driveManufacturerOffset),
@@ -211,8 +211,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.driveModelLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveModelLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveModelLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.driveModelLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.driveModelLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.driveModelOffset),
@@ -223,8 +223,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.driveSerialNumberLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveSerialNumberLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveSerialNumberLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.driveSerialNumberLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.driveSerialNumberLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.driveSerialNumberOffset),
@@ -235,8 +235,8 @@ int info(char *path)
if(ctx->metadataBlockHeader.driveFirmwareRevisionLength > 0)
{
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveFirmwareRevisionLength + 1);
u_error_code = U_ZERO_ERROR; // Reset error code before conversion
strBuffer = malloc(ctx->metadataBlockHeader.driveFirmwareRevisionLength + 1);
memset(strBuffer, 0, ctx->metadataBlockHeader.driveFirmwareRevisionLength + 1);
ucnv_convert(NULL, "UTF-16LE", strBuffer, (int)ctx->metadataBlockHeader.driveFirmwareRevisionLength,
(char *)(ctx->metadataBlock + ctx->metadataBlockHeader.driveFirmwareRevisionOffset),