2022-05-28 12:57:21 +01:00
|
|
|
/*
|
|
|
|
|
* This file is part of the Aaru Data Preservation Suite.
|
|
|
|
|
* Copyright (c) 2019-2022 Natalia Portillo.
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU Lesser General Public License as
|
|
|
|
|
* published by the Free Software Foundation; either version 2.1 of the
|
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2019-03-17 20:39:40 +00:00
|
|
|
|
|
|
|
|
#include <errno.h>
|
2019-03-17 21:14:40 +00:00
|
|
|
#include <inttypes.h>
|
2019-03-31 20:52:06 +01:00
|
|
|
#include <stdio.h>
|
2022-10-03 18:15:13 +01:00
|
|
|
#include <stdlib.h>
|
2019-03-17 21:14:40 +00:00
|
|
|
#include <string.h>
|
2022-06-21 21:08:19 +01:00
|
|
|
|
|
|
|
|
#ifdef __linux__
|
2019-03-17 23:19:13 +00:00
|
|
|
#include <sys/mman.h>
|
2022-06-21 21:08:19 +01:00
|
|
|
#endif
|
2019-03-17 20:39:40 +00:00
|
|
|
|
2022-05-28 12:10:04 +01:00
|
|
|
#include <aaruformat.h>
|
|
|
|
|
|
2022-05-28 12:01:55 +01:00
|
|
|
void* aaruf_open(const char* filepath)
|
2019-03-17 20:39:40 +00:00
|
|
|
{
|
2020-03-01 19:51:13 +00:00
|
|
|
aaruformatContext* ctx;
|
|
|
|
|
int errorNo;
|
2020-03-01 19:59:51 +00:00
|
|
|
size_t readBytes;
|
2020-03-01 19:51:13 +00:00
|
|
|
long pos;
|
|
|
|
|
IndexHeader idxHeader;
|
|
|
|
|
IndexEntry* idxEntries;
|
|
|
|
|
uint8_t* data;
|
2022-10-04 18:34:42 +01:00
|
|
|
uint8_t* cmpData;
|
|
|
|
|
uint8_t* cstData;
|
2020-03-01 19:51:13 +00:00
|
|
|
uint32_t* cdDdt;
|
|
|
|
|
uint64_t crc64;
|
2022-10-03 18:46:39 +01:00
|
|
|
int i, j;
|
2020-03-01 19:51:13 +00:00
|
|
|
uint16_t e;
|
2022-10-04 18:34:42 +01:00
|
|
|
uint8_t lzmaProperties[LZMA_PROPERTIES_LENGTH];
|
|
|
|
|
size_t lzmaSize;
|
2022-10-04 19:44:34 +01:00
|
|
|
ChecksumHeader checksum_header;
|
|
|
|
|
ChecksumEntry* checksum_entry;
|
2020-03-01 19:51:13 +00:00
|
|
|
|
|
|
|
|
ctx = (aaruformatContext*)malloc(sizeof(aaruformatContext));
|
|
|
|
|
memset(ctx, 0, sizeof(aaruformatContext));
|
2019-03-17 20:39:40 +00:00
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
if(ctx == NULL)
|
|
|
|
|
{
|
|
|
|
|
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2019-03-17 20:39:40 +00:00
|
|
|
|
|
|
|
|
ctx->imageStream = fopen(filepath, "rb");
|
|
|
|
|
|
|
|
|
|
if(ctx->imageStream == NULL)
|
|
|
|
|
{
|
|
|
|
|
errorNo = errno;
|
|
|
|
|
free(ctx);
|
|
|
|
|
errno = errorNo;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fseek(ctx->imageStream, 0, SEEK_SET);
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&ctx->header, 1, sizeof(AaruHeader), ctx->imageStream);
|
2019-03-17 20:39:40 +00:00
|
|
|
|
2020-03-01 19:55:22 +00:00
|
|
|
if(readBytes != sizeof(AaruHeader))
|
2019-03-17 20:39:40 +00:00
|
|
|
{
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_FILE_TOO_SMALL;
|
2019-03-17 20:39:40 +00:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-01 19:58:09 +00:00
|
|
|
if(ctx->header.identifier != DIC_MAGIC && ctx->header.identifier != AARU_MAGIC)
|
2019-03-17 20:39:40 +00:00
|
|
|
{
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_NOT_AARUFORMAT;
|
2019-03-17 20:39:40 +00:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-01 19:53:05 +00:00
|
|
|
if(ctx->header.imageMajorVersion > AARUF_VERSION)
|
2019-03-17 20:39:40 +00:00
|
|
|
{
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_INCOMPATIBLE_VERSION;
|
2019-03-17 20:39:40 +00:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Opening image version %d.%d\n",
|
2019-03-17 20:39:40 +00:00
|
|
|
ctx->header.imageMajorVersion,
|
|
|
|
|
ctx->header.imageMinorVersion);
|
|
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->readableSectorTags = (bool*)malloc(sizeof(bool) * MaxSectorTag);
|
2019-03-31 14:56:03 +01:00
|
|
|
|
|
|
|
|
if(ctx->readableSectorTags == NULL)
|
|
|
|
|
{
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
|
2019-03-31 14:56:03 +01:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(ctx->readableSectorTags, 0, sizeof(bool) * MaxSectorTag);
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.Application = ctx->header.application;
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.ApplicationVersion = (uint8_t*)malloc(32);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.ApplicationVersion != NULL)
|
|
|
|
|
{
|
|
|
|
|
memset(ctx->imageInfo.ApplicationVersion, 0, 32);
|
2019-08-03 01:58:19 +01:00
|
|
|
sprintf((char*)ctx->imageInfo.ApplicationVersion,
|
2019-03-20 22:31:50 +00:00
|
|
|
"%d.%d",
|
|
|
|
|
ctx->header.applicationMajorVersion,
|
|
|
|
|
ctx->header.applicationMinorVersion);
|
|
|
|
|
}
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.Version = (uint8_t*)malloc(32);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.Version != NULL)
|
|
|
|
|
{
|
|
|
|
|
memset(ctx->imageInfo.Version, 0, 32);
|
2019-08-03 01:58:19 +01:00
|
|
|
sprintf((char*)ctx->imageInfo.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
|
2019-03-20 22:31:50 +00:00
|
|
|
}
|
|
|
|
|
ctx->imageInfo.MediaType = ctx->header.mediaType;
|
|
|
|
|
|
2019-03-17 21:14:40 +00:00
|
|
|
// Read the index header
|
2022-10-02 18:12:35 +01:00
|
|
|
pos = fseek(ctx->imageStream, ctx->header.indexOffset, SEEK_SET);
|
2019-03-17 21:14:40 +00:00
|
|
|
if(pos < 0)
|
|
|
|
|
{
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_CANNOT_READ_INDEX;
|
2019-03-17 21:14:40 +00:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = ftell(ctx->imageStream);
|
|
|
|
|
if(pos != ctx->header.indexOffset)
|
|
|
|
|
{
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_CANNOT_READ_INDEX;
|
2019-03-17 21:14:40 +00:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&idxHeader, 1, sizeof(IndexHeader), ctx->imageStream);
|
2019-03-17 21:14:40 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(IndexHeader) || idxHeader.identifier != IndexBlock)
|
|
|
|
|
{
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_CANNOT_READ_INDEX;
|
2019-03-17 21:14:40 +00:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Index at %" PRIu64 " contains %d entries\n",
|
|
|
|
|
ctx->header.indexOffset,
|
|
|
|
|
idxHeader.entries);
|
2019-03-17 21:14:40 +00:00
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
idxEntries = (IndexEntry*)malloc(sizeof(IndexEntry) * idxHeader.entries);
|
2019-03-17 21:14:40 +00:00
|
|
|
|
|
|
|
|
if(idxEntries == NULL)
|
|
|
|
|
{
|
|
|
|
|
errorNo = errno;
|
|
|
|
|
free(ctx);
|
|
|
|
|
errno = errorNo;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(idxEntries, 0, sizeof(IndexEntry) * idxHeader.entries);
|
|
|
|
|
readBytes = fread(idxEntries, sizeof(IndexEntry), idxHeader.entries, ctx->imageStream);
|
|
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
if(readBytes != idxHeader.entries)
|
2019-03-17 21:14:40 +00:00
|
|
|
{
|
|
|
|
|
free(idxEntries);
|
|
|
|
|
free(ctx);
|
2020-03-01 19:53:05 +00:00
|
|
|
errno = AARUF_ERROR_CANNOT_READ_INDEX;
|
2019-03-17 21:14:40 +00:00
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-03 02:11:36 +01:00
|
|
|
for(i = 0; i < idxHeader.entries; i++)
|
2019-03-17 21:14:40 +00:00
|
|
|
{
|
2019-03-31 20:52:06 +01:00
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Block type %4.4s with data type %d is indexed to be at %" PRIu64 "\n",
|
2019-08-03 01:58:19 +01:00
|
|
|
(char*)&idxEntries[i].blockType,
|
2022-10-03 18:16:34 +01:00
|
|
|
idxEntries[i].dataType,
|
2019-03-17 21:14:40 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-31 20:52:06 +01:00
|
|
|
bool foundUserDataDdt = false;
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.ImageSize = 0;
|
2019-08-03 02:11:36 +01:00
|
|
|
for(i = 0; i < idxHeader.entries; i++)
|
2019-03-17 21:32:02 +00:00
|
|
|
{
|
|
|
|
|
pos = fseek(ctx->imageStream, idxEntries[i].offset, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
if(pos < 0 || ftell(ctx->imageStream) != idxEntries[i].offset)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Could not seek to %" PRIu64 " as indicated by index entry %d, continuing...\n",
|
2019-03-17 21:32:02 +00:00
|
|
|
idxEntries[i].offset,
|
|
|
|
|
i);
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-17 23:19:13 +00:00
|
|
|
BlockHeader blockHeader;
|
|
|
|
|
DdtHeader ddtHeader;
|
|
|
|
|
|
2019-03-17 21:32:02 +00:00
|
|
|
switch(idxEntries[i].blockType)
|
|
|
|
|
{
|
|
|
|
|
case DataBlock:
|
2019-03-17 22:41:04 +00:00
|
|
|
// NOP block, skip
|
2019-03-31 20:52:06 +01:00
|
|
|
if(idxEntries[i].dataType == NoData) break;
|
2019-03-17 22:41:04 +00:00
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&blockHeader, 1, sizeof(BlockHeader), ctx->imageStream);
|
2019-03-17 22:41:04 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(BlockHeader))
|
|
|
|
|
{
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(
|
|
|
|
|
stderr, "libaaruformat: Could not read block header at %" PRIu64 "\n", idxEntries[i].offset);
|
2019-03-17 22:41:04 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.ImageSize += blockHeader.cmpLength;
|
2019-03-17 22:41:04 +00:00
|
|
|
|
|
|
|
|
// Unused, skip
|
|
|
|
|
if(idxEntries[i].dataType == UserData)
|
|
|
|
|
{
|
2019-03-20 22:31:50 +00:00
|
|
|
if(blockHeader.sectorSize > ctx->imageInfo.SectorSize)
|
|
|
|
|
ctx->imageInfo.SectorSize = blockHeader.sectorSize;
|
2019-03-17 22:41:04 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(blockHeader.identifier != idxEntries[i].blockType)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Incorrect identifier for data block at position %" PRIu64 "\n",
|
2019-03-17 22:41:04 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(blockHeader.type != idxEntries[i].dataType)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2020-03-01 19:51:13 +00:00
|
|
|
"libaaruformat: Expected block with data type %4.4s at position %" PRIu64
|
2022-10-02 18:12:35 +01:00
|
|
|
" but found data type %4.4s\n",
|
2019-08-03 01:58:19 +01:00
|
|
|
(char*)&idxEntries[i].blockType,
|
2019-03-17 22:41:04 +00:00
|
|
|
idxEntries[i].offset,
|
2019-08-03 01:58:19 +01:00
|
|
|
(char*)&blockHeader.type);
|
2019-03-17 22:41:04 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-31 20:52:06 +01:00
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Found data block with type %4.4s at position %" PRIu64 "\n",
|
2019-08-03 01:58:19 +01:00
|
|
|
(char*)&idxEntries[i].blockType,
|
2019-03-17 22:41:04 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
|
2022-10-04 18:34:42 +01:00
|
|
|
if(blockHeader.compression == Lzma || blockHeader.compression == LzmaClauniaSubchannelTransform)
|
|
|
|
|
{
|
|
|
|
|
if(blockHeader.compression == LzmaClauniaSubchannelTransform &&
|
|
|
|
|
blockHeader.type != CdSectorSubchannel)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"Invalid compression type %d for block with data type %d, continuing...\n",
|
|
|
|
|
blockHeader.compression,
|
|
|
|
|
blockHeader.type);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lzmaSize = blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH;
|
|
|
|
|
|
|
|
|
|
cmpData = (uint8_t*)malloc(lzmaSize);
|
|
|
|
|
if(cmpData == NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Cannot allocate memory for block, continuing...\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = (uint8_t*)malloc(blockHeader.length);
|
|
|
|
|
if(data == NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Cannot allocate memory for block, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(lzmaProperties, 1, LZMA_PROPERTIES_LENGTH, ctx->imageStream);
|
|
|
|
|
if(readBytes != LZMA_PROPERTIES_LENGTH)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Could not read LZMA properties, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(cmpData, 1, lzmaSize, ctx->imageStream);
|
|
|
|
|
if(readBytes != lzmaSize)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Could not read compressed block, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = blockHeader.length;
|
|
|
|
|
errorNo = aaruf_lzma_decode_buffer(
|
|
|
|
|
data, &readBytes, cmpData, &lzmaSize, lzmaProperties, LZMA_PROPERTIES_LENGTH);
|
|
|
|
|
|
|
|
|
|
if(errorNo != 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Got error %d from LZMA, continuing...\n", errorNo);
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(data);
|
|
|
|
|
errno = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK;
|
|
|
|
|
|
|
|
|
|
// TODO: Clean-up all memory!!!
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(readBytes != blockHeader.length)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"Error decompressing block, should be {0} bytes but got {1} bytes., continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(data);
|
|
|
|
|
errno = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK;
|
|
|
|
|
|
|
|
|
|
// TODO: Clean-up all memory!!!
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(blockHeader.compression == LzmaClauniaSubchannelTransform)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Needs to fix!
|
|
|
|
|
/*
|
|
|
|
|
cstData = malloc(blockHeader.length);
|
|
|
|
|
if(cstData == NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Cannot allocate memory for block, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aaruf_cst_untransform(data, cstData, blockHeader.length);
|
|
|
|
|
free(data);
|
|
|
|
|
data = cstData;
|
|
|
|
|
cstData = NULL;
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(cmpData);
|
|
|
|
|
}
|
|
|
|
|
else if(blockHeader.compression == None)
|
2019-03-17 22:41:04 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
data = (uint8_t*)malloc(blockHeader.length);
|
2019-03-17 22:41:04 +00:00
|
|
|
if(data == NULL)
|
|
|
|
|
{
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "Cannot allocate memory for block, continuing...\n");
|
2019-03-17 22:41:04 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(data, 1, blockHeader.length, ctx->imageStream);
|
2019-03-17 22:41:04 +00:00
|
|
|
|
|
|
|
|
if(readBytes != blockHeader.length)
|
|
|
|
|
{
|
|
|
|
|
free(data);
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "Could not read block, continuing...\n");
|
2019-03-17 22:41:04 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Found unknown compression type %d, continuing...\n",
|
2019-03-17 22:41:04 +00:00
|
|
|
blockHeader.compression);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-28 12:50:10 +01:00
|
|
|
crc64 = aaruf_crc64_data(data, blockHeader.length);
|
2022-10-03 18:16:11 +01:00
|
|
|
|
|
|
|
|
// Due to how C# wrote it, it is effectively reversed
|
|
|
|
|
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
|
|
|
|
|
|
2019-03-20 23:55:32 +00:00
|
|
|
if(crc64 != blockHeader.crc64)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2020-03-01 19:51:13 +00:00
|
|
|
"libaaruformat: Incorrect CRC found: 0x%" PRIx64 " found, expected 0x%" PRIx64
|
2022-10-02 18:12:35 +01:00
|
|
|
", continuing...\n",
|
2019-03-20 23:55:32 +00:00
|
|
|
crc64,
|
|
|
|
|
blockHeader.crc64);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-03-17 22:41:04 +00:00
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
dataLinkedList* mediaTag = NULL;
|
2019-03-17 23:01:54 +00:00
|
|
|
|
2019-03-17 22:41:04 +00:00
|
|
|
// Check if it's not a media tag, but a sector tag, and fill the appropriate table then
|
|
|
|
|
switch(idxEntries[i].dataType)
|
|
|
|
|
{
|
|
|
|
|
case CdSectorPrefix:
|
|
|
|
|
case CdSectorPrefixCorrected:
|
2019-03-31 20:52:06 +01:00
|
|
|
if(idxEntries[i].dataType == CdSectorPrefixCorrected) { ctx->sectorPrefixCorrected = data; }
|
2019-03-17 22:41:04 +00:00
|
|
|
else
|
|
|
|
|
ctx->sectorPrefix = data;
|
|
|
|
|
|
2019-03-31 14:56:03 +01:00
|
|
|
ctx->readableSectorTags[CdSectorSync] = true;
|
|
|
|
|
ctx->readableSectorTags[CdSectorHeader] = true;
|
2019-03-17 22:41:04 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case CdSectorSuffix:
|
|
|
|
|
case CdSectorSuffixCorrected:
|
2022-05-28 12:10:04 +01:00
|
|
|
if(idxEntries[i].dataType == CdSectorSuffixCorrected) ctx->sectorSuffixCorrected = data;
|
2019-03-17 22:41:04 +00:00
|
|
|
else
|
|
|
|
|
ctx->sectorSuffix = data;
|
|
|
|
|
|
2019-03-31 14:56:03 +01:00
|
|
|
ctx->readableSectorTags[CdSectorSubHeader] = true;
|
|
|
|
|
ctx->readableSectorTags[CdSectorEcc] = true;
|
|
|
|
|
ctx->readableSectorTags[CdSectorEccP] = true;
|
|
|
|
|
ctx->readableSectorTags[CdSectorEccQ] = true;
|
|
|
|
|
ctx->readableSectorTags[CdSectorEdc] = true;
|
2019-03-17 22:41:04 +00:00
|
|
|
break;
|
2019-03-31 20:52:06 +01:00
|
|
|
case CdSectorSubchannel:
|
|
|
|
|
ctx->sectorSubchannel = data;
|
2019-03-31 14:56:03 +01:00
|
|
|
ctx->readableSectorTags[CdSectorSubchannel] = true;
|
2019-03-17 22:41:04 +00:00
|
|
|
break;
|
|
|
|
|
case AppleProfileTag:
|
|
|
|
|
case AppleSonyTag:
|
2019-03-31 20:52:06 +01:00
|
|
|
case PriamDataTowerTag:
|
|
|
|
|
ctx->sectorSubchannel = data;
|
2019-03-31 14:56:03 +01:00
|
|
|
ctx->readableSectorTags[AppleSectorTag] = true;
|
2019-03-17 22:41:04 +00:00
|
|
|
break;
|
2019-03-31 20:52:06 +01:00
|
|
|
case CompactDiscMode2Subheader: ctx->mode2Subheaders = data; break;
|
2019-03-17 22:41:04 +00:00
|
|
|
default:
|
2019-03-17 23:01:54 +00:00
|
|
|
if(ctx->mediaTagsHead != NULL)
|
|
|
|
|
{
|
|
|
|
|
mediaTag = ctx->mediaTagsHead;
|
|
|
|
|
while(mediaTag != NULL)
|
|
|
|
|
{
|
|
|
|
|
if(mediaTag->type == blockHeader.type)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Media tag type %d duplicated, removing previous entry...\n",
|
2019-03-17 23:01:54 +00:00
|
|
|
blockHeader.type);
|
|
|
|
|
free(mediaTag->data);
|
|
|
|
|
mediaTag->data = data;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mediaTag = mediaTag->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 18:34:42 +01:00
|
|
|
// If the mediaTag is NULL means we have arrived the end of the list without finding a duplicate
|
2019-03-20 22:31:50 +00:00
|
|
|
// or the list was empty
|
2019-03-31 20:52:06 +01:00
|
|
|
if(mediaTag != NULL) break;
|
2019-03-17 23:01:54 +00:00
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
mediaTag = (dataLinkedList*)malloc(sizeof(dataLinkedList));
|
2019-03-17 23:01:54 +00:00
|
|
|
|
|
|
|
|
if(mediaTag == NULL)
|
|
|
|
|
{
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Cannot allocate memory for media tag list entry.\n");
|
2019-03-17 23:01:54 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
memset(mediaTag, 0, sizeof(dataLinkedList));
|
|
|
|
|
|
2022-05-28 12:01:55 +01:00
|
|
|
mediaTag->type = aaruf_get_media_tag_type_for_datatype(blockHeader.type);
|
2019-03-21 00:18:48 +00:00
|
|
|
mediaTag->data = data;
|
|
|
|
|
mediaTag->length = blockHeader.length;
|
2019-03-17 23:01:54 +00:00
|
|
|
|
2019-03-31 20:52:06 +01:00
|
|
|
if(ctx->mediaTagsHead == NULL) { ctx->mediaTagsHead = mediaTag; }
|
2019-03-17 23:01:54 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mediaTag->previous = ctx->mediaTagsTail;
|
|
|
|
|
ctx->mediaTagsTail->next = mediaTag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx->mediaTagsTail = mediaTag;
|
|
|
|
|
|
2019-03-17 22:41:04 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-17 21:32:02 +00:00
|
|
|
break;
|
2019-03-31 20:52:06 +01:00
|
|
|
case DeDuplicationTable:
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&ddtHeader, 1, sizeof(DdtHeader), ctx->imageStream);
|
2019-03-17 23:19:13 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(DdtHeader))
|
|
|
|
|
{
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(
|
|
|
|
|
stderr, "libaaruformat: Could not read block header at %" PRIu64 "\n", idxEntries[i].offset);
|
2019-03-17 23:19:13 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foundUserDataDdt = true;
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.ImageSize += ddtHeader.cmpLength;
|
|
|
|
|
|
2019-03-17 23:19:13 +00:00
|
|
|
if(idxEntries[i].dataType == UserData)
|
|
|
|
|
{
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.Sectors = ddtHeader.entries;
|
|
|
|
|
ctx->shift = ddtHeader.shift;
|
2019-03-17 23:19:13 +00:00
|
|
|
|
|
|
|
|
// Check for DDT compression
|
|
|
|
|
switch(ddtHeader.compression)
|
|
|
|
|
{
|
2022-10-04 18:34:42 +01:00
|
|
|
// TODO: Check CRC
|
|
|
|
|
case Lzma:
|
|
|
|
|
lzmaSize = ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH;
|
|
|
|
|
|
|
|
|
|
cmpData = (uint8_t*)malloc(lzmaSize);
|
|
|
|
|
if(cmpData == NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Cannot allocate memory for DDT, continuing...\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx->userDataDdt = (uint64_t*)malloc(ddtHeader.length);
|
|
|
|
|
if(ctx->userDataDdt == NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Cannot allocate memory for DDT, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(lzmaProperties, 1, LZMA_PROPERTIES_LENGTH, ctx->imageStream);
|
|
|
|
|
if(readBytes != LZMA_PROPERTIES_LENGTH)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Could not read LZMA properties, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(ctx->userDataDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(cmpData, 1, lzmaSize, ctx->imageStream);
|
|
|
|
|
if(readBytes != lzmaSize)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Could not read compressed block, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(ctx->userDataDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = ddtHeader.length;
|
|
|
|
|
errorNo = aaruf_lzma_decode_buffer((uint8_t*)ctx->userDataDdt,
|
|
|
|
|
&readBytes,
|
|
|
|
|
cmpData,
|
|
|
|
|
&lzmaSize,
|
|
|
|
|
lzmaProperties,
|
|
|
|
|
LZMA_PROPERTIES_LENGTH);
|
|
|
|
|
|
|
|
|
|
if(errorNo != 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Got error %d from LZMA, stopping...\n", errorNo);
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(ctx->userDataDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
errno = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK;
|
|
|
|
|
|
|
|
|
|
// TODO: Clean-up all memory!!!
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(readBytes != ddtHeader.length)
|
|
|
|
|
{
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(ctx->userDataDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
errno = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK;
|
|
|
|
|
|
|
|
|
|
// TODO: Clean-up all memory!!!
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx->inMemoryDdt = true;
|
|
|
|
|
foundUserDataDdt = true;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
// TODO: Check CRC
|
2019-03-31 20:52:06 +01:00
|
|
|
case None:
|
2022-06-21 21:08:19 +01:00
|
|
|
#ifdef __linux__
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->mappedMemoryDdtSize = sizeof(uint64_t) * ddtHeader.entries;
|
|
|
|
|
ctx->userDataDdt = mmap(NULL,
|
|
|
|
|
ctx->mappedMemoryDdtSize,
|
|
|
|
|
PROT_READ,
|
|
|
|
|
MAP_SHARED,
|
|
|
|
|
fileno(ctx->imageStream),
|
|
|
|
|
idxEntries[i].offset + sizeof(ddtHeader));
|
2019-03-17 23:19:13 +00:00
|
|
|
|
|
|
|
|
if(ctx->userDataDdt == MAP_FAILED)
|
|
|
|
|
{
|
|
|
|
|
foundUserDataDdt = false;
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read map deduplication table.\n");
|
2019-03-17 23:19:13 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx->inMemoryDdt = false;
|
|
|
|
|
break;
|
2022-06-21 21:08:19 +01:00
|
|
|
#else // TODO: Implement
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Uncompressed DDT not yet implemented...\n");
|
2022-06-21 21:08:19 +01:00
|
|
|
foundUserDataDdt = false;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
2019-03-17 23:19:13 +00:00
|
|
|
default:
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Found unknown compression type %d, continuing...\n",
|
2019-03-17 23:19:13 +00:00
|
|
|
blockHeader.compression);
|
|
|
|
|
foundUserDataDdt = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-03-17 23:25:45 +00:00
|
|
|
}
|
|
|
|
|
else if(idxEntries[i].dataType == CdSectorPrefixCorrected ||
|
|
|
|
|
idxEntries[i].dataType == CdSectorSuffixCorrected)
|
|
|
|
|
{
|
|
|
|
|
switch(ddtHeader.compression)
|
|
|
|
|
{
|
2022-10-04 18:34:42 +01:00
|
|
|
// TODO: Check CRC
|
|
|
|
|
case Lzma:
|
|
|
|
|
lzmaSize = ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH;
|
|
|
|
|
|
|
|
|
|
cmpData = (uint8_t*)malloc(lzmaSize);
|
|
|
|
|
if(cmpData == NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Cannot allocate memory for DDT, continuing...\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cdDdt = (uint32_t*)malloc(ddtHeader.length);
|
|
|
|
|
if(cdDdt == NULL)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Cannot allocate memory for DDT, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(lzmaProperties, 1, LZMA_PROPERTIES_LENGTH, ctx->imageStream);
|
|
|
|
|
if(readBytes != LZMA_PROPERTIES_LENGTH)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Could not read LZMA properties, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(cdDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(cmpData, 1, lzmaSize, ctx->imageStream);
|
|
|
|
|
if(readBytes != lzmaSize)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Could not read compressed block, continuing...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(cdDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = ddtHeader.length;
|
|
|
|
|
errorNo = aaruf_lzma_decode_buffer((uint8_t*)cdDdt,
|
|
|
|
|
&readBytes,
|
|
|
|
|
cmpData,
|
|
|
|
|
&lzmaSize,
|
|
|
|
|
lzmaProperties,
|
|
|
|
|
LZMA_PROPERTIES_LENGTH);
|
|
|
|
|
|
|
|
|
|
if(errorNo != 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Got error %d from LZMA, stopping...\n", errorNo);
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(cdDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
errno = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK;
|
|
|
|
|
|
|
|
|
|
// TODO: Clean-up all memory!!!
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(readBytes != ddtHeader.length)
|
|
|
|
|
{
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...\n");
|
|
|
|
|
free(cmpData);
|
|
|
|
|
free(cdDdt);
|
|
|
|
|
ctx->userDataDdt = NULL;
|
|
|
|
|
errno = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK;
|
|
|
|
|
|
|
|
|
|
// TODO: Clean-up all memory!!!
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(idxEntries[i].dataType == CdSectorPrefixCorrected) ctx->sectorPrefixDdt = cdDdt;
|
|
|
|
|
else if(idxEntries[i].dataType == CdSectorSuffixCorrected)
|
|
|
|
|
ctx->sectorSuffixDdt = cdDdt;
|
|
|
|
|
else
|
|
|
|
|
free(cdDdt);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// TODO: Check CRC
|
2019-03-31 20:52:06 +01:00
|
|
|
case None:
|
2019-08-03 01:58:19 +01:00
|
|
|
cdDdt = (uint32_t*)malloc(ddtHeader.entries * sizeof(uint32_t));
|
2019-03-17 23:25:45 +00:00
|
|
|
|
|
|
|
|
if(mediaTag == NULL)
|
|
|
|
|
{
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Cannot allocate memory for deduplication table.\n");
|
2019-03-17 23:25:45 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 18:34:42 +01:00
|
|
|
readBytes = fread(cdDdt, 1, ddtHeader.entries * sizeof(uint32_t), ctx->imageStream);
|
2019-03-17 23:25:45 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ddtHeader.entries * sizeof(uint32_t))
|
|
|
|
|
{
|
2022-10-04 18:34:42 +01:00
|
|
|
free(cdDdt);
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read deduplication table, continuing...\n");
|
2019-03-17 23:25:45 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-28 12:10:04 +01:00
|
|
|
if(idxEntries[i].dataType == CdSectorPrefixCorrected) ctx->sectorPrefixDdt = cdDdt;
|
2019-03-17 23:25:45 +00:00
|
|
|
else if(idxEntries[i].dataType == CdSectorSuffixCorrected)
|
2019-03-20 22:45:05 +00:00
|
|
|
ctx->sectorSuffixDdt = cdDdt;
|
|
|
|
|
else
|
|
|
|
|
free(cdDdt);
|
2019-03-17 23:25:45 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Found unknown compression type %d, continuing...\n",
|
2019-03-17 23:25:45 +00:00
|
|
|
blockHeader.compression);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-03-17 23:19:13 +00:00
|
|
|
}
|
2019-03-17 21:32:02 +00:00
|
|
|
break;
|
2019-03-17 23:29:29 +00:00
|
|
|
// Logical geometry block. It doesn't have a CRC coz, well, it's not so important
|
2019-03-31 20:52:06 +01:00
|
|
|
case GeometryBlock:
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&ctx->geometryBlock, 1, sizeof(GeometryBlockHeader), ctx->imageStream);
|
2019-03-17 23:29:29 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(GeometryBlockHeader))
|
|
|
|
|
{
|
2019-03-17 23:41:07 +00:00
|
|
|
memset(&ctx->geometryBlock, 0, sizeof(GeometryBlockHeader));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read geometry block, continuing...\n");
|
2019-03-17 23:29:29 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->geometryBlock.identifier == GeometryBlock)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Geometry set to %d cylinders %d heads %d sectors per track\n",
|
2019-03-17 23:29:29 +00:00
|
|
|
ctx->geometryBlock.cylinders,
|
|
|
|
|
ctx->geometryBlock.heads,
|
|
|
|
|
ctx->geometryBlock.sectorsPerTrack);
|
2019-03-20 22:31:50 +00:00
|
|
|
|
|
|
|
|
ctx->imageInfo.Cylinders = ctx->geometryBlock.cylinders;
|
|
|
|
|
ctx->imageInfo.Heads = ctx->geometryBlock.heads;
|
|
|
|
|
ctx->imageInfo.SectorsPerTrack = ctx->geometryBlock.sectorsPerTrack;
|
2019-03-17 23:29:29 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
memset(&ctx->geometryBlock, 0, sizeof(GeometryBlockHeader));
|
|
|
|
|
|
2019-03-17 21:32:02 +00:00
|
|
|
break;
|
2019-03-17 23:41:07 +00:00
|
|
|
// Metadata block
|
2019-03-31 20:52:06 +01:00
|
|
|
case MetadataBlock:
|
2022-10-02 18:12:35 +01:00
|
|
|
readBytes = fread(&ctx->metadataBlockHeader, 1, sizeof(MetadataBlockHeader), ctx->imageStream);
|
2019-03-17 23:41:07 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(MetadataBlockHeader))
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->metadataBlockHeader, 0, sizeof(MetadataBlockHeader));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read metadata block header, continuing...\n");
|
2019-03-17 23:41:07 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.identifier != idxEntries[i].blockType)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->metadataBlockHeader, 0, sizeof(MetadataBlockHeader));
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Incorrect identifier for data block at position %" PRIu64 "\n",
|
2019-03-17 23:41:07 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.ImageSize += ctx->metadataBlockHeader.blockSize;
|
|
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->metadataBlock = (uint8_t*)malloc(ctx->metadataBlockHeader.blockSize);
|
2019-03-17 23:41:07 +00:00
|
|
|
|
|
|
|
|
if(ctx->metadataBlock == NULL)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->metadataBlockHeader, 0, sizeof(MetadataBlockHeader));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not allocate memory for metadata block, continuing...\n");
|
2019-03-17 23:41:07 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(ctx->metadataBlock, 1, ctx->metadataBlockHeader.blockSize, ctx->imageStream);
|
2019-03-17 23:41:07 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->metadataBlockHeader.blockSize)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->metadataBlockHeader, 0, sizeof(MetadataBlockHeader));
|
|
|
|
|
free(ctx->metadataBlock);
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read metadata block, continuing...\n");
|
2019-03-17 23:41:07 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->metadataBlockHeader.mediaSequence > 0 && ctx->metadataBlockHeader.lastMediaSequence > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->imageInfo.MediaSequence = ctx->metadataBlockHeader.mediaSequence;
|
|
|
|
|
ctx->imageInfo.LastMediaSequence = ctx->metadataBlockHeader.lastMediaSequence;
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Setting media sequence as %d of %d\n",
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.MediaSequence,
|
|
|
|
|
ctx->imageInfo.LastMediaSequence);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.creatorLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.creatorOffset + ctx->metadataBlockHeader.creatorLength <=
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.Creator = (uint8_t*)malloc(ctx->metadataBlockHeader.creatorLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.Creator != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.Creator,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.creatorOffset,
|
|
|
|
|
ctx->metadataBlockHeader.creatorLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.commentsLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.commentsOffset + ctx->metadataBlockHeader.commentsLength <=
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.Comments = (uint8_t*)malloc(ctx->metadataBlockHeader.commentsLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.Comments != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.Comments,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.commentsOffset,
|
|
|
|
|
ctx->metadataBlockHeader.commentsLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.mediaTitleLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.mediaTitleOffset + ctx->metadataBlockHeader.mediaTitleLength <=
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.MediaTitle = (uint8_t*)malloc(ctx->metadataBlockHeader.mediaTitleLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.MediaTitle != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.MediaTitle,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.mediaTitleOffset,
|
|
|
|
|
ctx->metadataBlockHeader.mediaTitleLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.mediaManufacturerLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.mediaManufacturerOffset +
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.mediaManufacturerLength <=
|
|
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-03-20 22:45:05 +00:00
|
|
|
ctx->imageInfo.MediaManufacturer =
|
2019-08-03 01:58:19 +01:00
|
|
|
(uint8_t*)malloc(ctx->metadataBlockHeader.mediaManufacturerLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.MediaManufacturer != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.MediaManufacturer,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.mediaManufacturerOffset,
|
|
|
|
|
ctx->metadataBlockHeader.mediaManufacturerLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.mediaModelLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.mediaModelOffset + ctx->metadataBlockHeader.mediaModelLength <=
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.MediaModel = (uint8_t*)malloc(ctx->metadataBlockHeader.mediaModelOffset);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.MediaModel != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.MediaModel,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.mediaModelOffset,
|
|
|
|
|
ctx->metadataBlockHeader.mediaModelLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.mediaSerialNumberLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.mediaSerialNumberOffset +
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.mediaSerialNumberLength <=
|
|
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-03-20 22:45:05 +00:00
|
|
|
ctx->imageInfo.MediaSerialNumber =
|
2019-08-03 01:58:19 +01:00
|
|
|
(uint8_t*)malloc(ctx->metadataBlockHeader.mediaSerialNumberLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.MediaSerialNumber != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.MediaSerialNumber,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.mediaSerialNumberOffset,
|
|
|
|
|
ctx->metadataBlockHeader.mediaManufacturerLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.mediaBarcodeLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.mediaBarcodeOffset + ctx->metadataBlockHeader.mediaBarcodeLength <=
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.MediaBarcode = (uint8_t*)malloc(ctx->metadataBlockHeader.mediaBarcodeLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.MediaBarcode != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.MediaBarcode,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.mediaBarcodeOffset,
|
|
|
|
|
ctx->metadataBlockHeader.mediaBarcodeLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.mediaPartNumberLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.mediaPartNumberOffset + ctx->metadataBlockHeader.mediaPartNumberLength <=
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.MediaPartNumber = (uint8_t*)malloc(ctx->metadataBlockHeader.mediaPartNumberLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.MediaPartNumber != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.MediaPartNumber,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.mediaPartNumberOffset,
|
|
|
|
|
ctx->metadataBlockHeader.mediaPartNumberLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.driveManufacturerLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.driveManufacturerOffset +
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.driveManufacturerLength <=
|
|
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-03-20 22:45:05 +00:00
|
|
|
ctx->imageInfo.DriveManufacturer =
|
2019-08-03 01:58:19 +01:00
|
|
|
(uint8_t*)malloc(ctx->metadataBlockHeader.driveManufacturerLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.DriveManufacturer != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.DriveManufacturer,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.driveManufacturerOffset,
|
|
|
|
|
ctx->metadataBlockHeader.driveManufacturerLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.driveModelLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.driveModelOffset + ctx->metadataBlockHeader.driveModelLength <=
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->imageInfo.DriveModel = (uint8_t*)malloc(ctx->metadataBlockHeader.driveModelLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.DriveModel != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.DriveModel,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.driveModelOffset,
|
|
|
|
|
ctx->metadataBlockHeader.driveModelLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.driveSerialNumberLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.driveSerialNumberOffset +
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.driveSerialNumberLength <=
|
|
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-03-20 22:45:05 +00:00
|
|
|
ctx->imageInfo.DriveSerialNumber =
|
2019-08-03 01:58:19 +01:00
|
|
|
(uint8_t*)malloc(ctx->metadataBlockHeader.driveSerialNumberLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.DriveSerialNumber != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.DriveSerialNumber,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.driveSerialNumberOffset,
|
|
|
|
|
ctx->metadataBlockHeader.driveSerialNumberLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->metadataBlockHeader.driveManufacturerLength > 0 &&
|
|
|
|
|
ctx->metadataBlockHeader.driveFirmwareRevisionOffset +
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->metadataBlockHeader.driveManufacturerLength <=
|
|
|
|
|
ctx->metadataBlockHeader.blockSize)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
2019-03-20 22:45:05 +00:00
|
|
|
ctx->imageInfo.DriveFirmwareRevision =
|
2019-08-03 01:58:19 +01:00
|
|
|
(uint8_t*)malloc(ctx->metadataBlockHeader.driveFirmwareRevisionLength);
|
2019-03-20 22:31:50 +00:00
|
|
|
if(ctx->imageInfo.DriveFirmwareRevision != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->imageInfo.DriveFirmwareRevision,
|
|
|
|
|
ctx->metadataBlock + ctx->metadataBlockHeader.driveFirmwareRevisionLength,
|
|
|
|
|
ctx->metadataBlockHeader.driveFirmwareRevisionLength);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-17 21:32:02 +00:00
|
|
|
break;
|
2019-03-31 20:52:06 +01:00
|
|
|
case TracksBlock:
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&ctx->tracksHeader, 1, sizeof(TracksHeader), ctx->imageStream);
|
2019-03-18 00:10:24 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(TracksHeader))
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->tracksHeader, 0, sizeof(TracksHeader));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read tracks header, continuing...\n");
|
2019-03-18 00:10:24 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->tracksHeader.identifier != TracksBlock)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->tracksHeader, 0, sizeof(TracksHeader));
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Incorrect identifier for data block at position %" PRIu64 "\n",
|
2019-03-18 00:10:24 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.ImageSize += sizeof(TrackEntry) * ctx->tracksHeader.entries;
|
|
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->trackEntries = (TrackEntry*)malloc(sizeof(TrackEntry) * ctx->tracksHeader.entries);
|
2019-03-18 00:10:24 +00:00
|
|
|
|
|
|
|
|
if(ctx->trackEntries == NULL)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->tracksHeader, 0, sizeof(TracksHeader));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not allocate memory for metadata block, continuing...\n");
|
2019-03-18 00:10:24 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(ctx->trackEntries, sizeof(TrackEntry), ctx->tracksHeader.entries, ctx->imageStream);
|
|
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
if(readBytes != ctx->tracksHeader.entries)
|
2019-03-18 00:10:24 +00:00
|
|
|
{
|
|
|
|
|
memset(&ctx->tracksHeader, 0, sizeof(TracksHeader));
|
|
|
|
|
free(ctx->trackEntries);
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read metadata block, continuing...\n");
|
2019-03-18 00:10:24 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-02 16:05:25 +01:00
|
|
|
crc64 =
|
|
|
|
|
aaruf_crc64_data((const uint8_t*)ctx->trackEntries, ctx->tracksHeader.entries * sizeof(TrackEntry));
|
2022-10-03 18:16:11 +01:00
|
|
|
|
|
|
|
|
// Due to how C# wrote it, it is effectively reversed
|
|
|
|
|
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
|
|
|
|
|
|
2019-03-20 23:55:32 +00:00
|
|
|
if(crc64 != ctx->tracksHeader.crc64)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr,
|
2020-03-01 19:51:13 +00:00
|
|
|
"libaaruformat: Incorrect CRC found: 0x%" PRIx64 " found, expected 0x%" PRIx64
|
2022-10-02 18:12:35 +01:00
|
|
|
", continuing...\n",
|
2019-03-20 23:55:32 +00:00
|
|
|
crc64,
|
|
|
|
|
ctx->tracksHeader.crc64);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-18 00:10:24 +00:00
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Found %d tracks at position %" PRIu64 ".\n",
|
2019-03-18 00:10:24 +00:00
|
|
|
ctx->tracksHeader.entries,
|
|
|
|
|
idxEntries[i].offset);
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.HasPartitions = true;
|
|
|
|
|
ctx->imageInfo.HasSessions = true;
|
2019-03-18 00:10:24 +00:00
|
|
|
|
2019-03-23 23:18:54 +00:00
|
|
|
ctx->numberOfDataTracks = 0;
|
|
|
|
|
|
2022-10-03 19:21:20 +01:00
|
|
|
for(j = 0; j < ctx->tracksHeader.entries; j++)
|
2019-03-23 23:18:54 +00:00
|
|
|
{
|
2022-10-03 19:21:20 +01:00
|
|
|
if(ctx->trackEntries[j].sequence <= 99 && ctx->trackEntries[j].type != Audio)
|
|
|
|
|
ctx->numberOfDataTracks++;
|
2019-03-23 23:18:54 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-17 21:32:02 +00:00
|
|
|
break;
|
2019-03-18 22:06:10 +00:00
|
|
|
// CICM XML metadata block
|
2019-03-31 20:52:06 +01:00
|
|
|
case CicmBlock:
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&ctx->cicmBlockHeader, 1, sizeof(CicmMetadataBlock), ctx->imageStream);
|
2019-03-18 22:06:10 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(CicmMetadataBlock))
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->cicmBlockHeader, 0, sizeof(CicmMetadataBlock));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read CICM XML metadata header, continuing...\n");
|
2019-03-18 22:06:10 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->cicmBlockHeader.identifier != CicmBlock)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->cicmBlockHeader, 0, sizeof(CicmMetadataBlock));
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Incorrect identifier for data block at position %" PRIu64 "\n",
|
2019-03-18 22:06:10 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.ImageSize += ctx->cicmBlockHeader.length;
|
|
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->cicmBlock = (uint8_t*)malloc(ctx->cicmBlockHeader.length);
|
2019-03-18 22:06:10 +00:00
|
|
|
|
|
|
|
|
if(ctx->cicmBlock == NULL)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->cicmBlockHeader, 0, sizeof(CicmMetadataBlock));
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Could not allocate memory for CICM XML metadata block, continuing...\n");
|
2019-03-18 22:06:10 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(ctx->cicmBlock, 1, ctx->cicmBlockHeader.length, ctx->imageStream);
|
2019-03-18 22:06:10 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->metadataBlockHeader.blockSize)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->cicmBlockHeader, 0, sizeof(CicmMetadataBlock));
|
|
|
|
|
free(ctx->cicmBlock);
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read CICM XML metadata block, continuing...\n");
|
2019-03-18 22:06:10 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Found CICM XML metadata block %" PRIu64 ".\n", idxEntries[i].offset);
|
2019-03-17 21:32:02 +00:00
|
|
|
break;
|
2019-03-20 00:23:30 +00:00
|
|
|
// Dump hardware block
|
2019-03-31 20:52:06 +01:00
|
|
|
case DumpHardwareBlock:
|
2022-10-02 17:55:45 +01:00
|
|
|
readBytes = fread(&ctx->dumpHardwareHeader, 1, sizeof(DumpHardwareHeader), ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(DumpHardwareHeader))
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->dumpHardwareHeader, 0, sizeof(DumpHardwareHeader));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read dump hardware block header, continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareHeader.identifier != DumpHardwareBlock)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->dumpHardwareHeader, 0, sizeof(DumpHardwareHeader));
|
|
|
|
|
fprintf(stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Incorrect identifier for data block at position %" PRIu64 "\n",
|
2019-03-20 00:23:30 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
data = (uint8_t*)malloc(ctx->dumpHardwareHeader.length);
|
2022-10-03 18:46:17 +01:00
|
|
|
|
|
|
|
|
if(data == NULL)
|
2019-03-20 23:55:32 +00:00
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
memset(&ctx->dumpHardwareHeader, 0, sizeof(DumpHardwareHeader));
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Could not allocate memory for dump hardware block, continuing...\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-03-20 23:55:32 +00:00
|
|
|
|
2022-10-03 18:46:17 +01:00
|
|
|
readBytes = fread(data, 1, ctx->dumpHardwareHeader.length, ctx->imageStream);
|
2022-10-03 18:16:11 +01:00
|
|
|
|
2022-10-03 18:46:17 +01:00
|
|
|
if(readBytes == ctx->dumpHardwareHeader.length)
|
|
|
|
|
{
|
|
|
|
|
crc64 = aaruf_crc64_data(data, ctx->dumpHardwareHeader.length);
|
2022-10-03 18:16:11 +01:00
|
|
|
|
2022-10-03 18:46:17 +01:00
|
|
|
// Due to how C# wrote it, it is effectively reversed
|
|
|
|
|
if(ctx->header.imageMajorVersion <= AARUF_VERSION) crc64 = bswap_64(crc64);
|
2019-03-20 23:55:32 +00:00
|
|
|
|
2022-10-03 18:46:17 +01:00
|
|
|
if(crc64 != ctx->dumpHardwareHeader.crc64)
|
|
|
|
|
{
|
|
|
|
|
free(data);
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Incorrect CRC found: 0x%" PRIx64 " found, expected 0x%" PRIx64
|
|
|
|
|
", continuing...\n",
|
|
|
|
|
crc64,
|
|
|
|
|
ctx->dumpHardwareHeader.crc64);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-03-20 23:55:32 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-03 18:46:17 +01:00
|
|
|
free(data);
|
|
|
|
|
fseek(ctx->imageStream, -(long)readBytes, SEEK_CUR);
|
|
|
|
|
|
2019-08-03 01:58:19 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData = (DumpHardwareEntriesWithData*)malloc(
|
2019-03-31 20:52:06 +01:00
|
|
|
sizeof(DumpHardwareEntriesWithData) * ctx->dumpHardwareHeader.entries);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData == NULL)
|
|
|
|
|
{
|
|
|
|
|
memset(&ctx->dumpHardwareHeader, 0, sizeof(DumpHardwareHeader));
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Could not allocate memory for dump hardware block, continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(ctx->dumpHardwareEntriesWithData,
|
|
|
|
|
0,
|
|
|
|
|
sizeof(DumpHardwareEntriesWithData) * ctx->dumpHardwareHeader.entries);
|
|
|
|
|
|
2019-08-03 02:11:36 +01:00
|
|
|
for(e = 0; e < ctx->dumpHardwareHeader.entries; e++)
|
2019-03-20 00:23:30 +00:00
|
|
|
{
|
2019-03-31 20:52:06 +01:00
|
|
|
readBytes = fread(
|
2022-10-02 17:55:45 +01:00
|
|
|
&ctx->dumpHardwareEntriesWithData[e].entry, 1, sizeof(DumpHardwareEntry), ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != sizeof(DumpHardwareEntry))
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareHeader.entries = e;
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read dump hardware block entry, continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.manufacturerLength > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].manufacturer =
|
2022-10-03 18:46:17 +01:00
|
|
|
(uint8_t*)malloc(ctx->dumpHardwareEntriesWithData[e].entry.manufacturerLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].manufacturer != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e]
|
|
|
|
|
.manufacturer[ctx->dumpHardwareEntriesWithData[e].entry.manufacturerLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].manufacturer,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.manufacturerLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.manufacturerLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].manufacturer);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.manufacturerLength = 0;
|
|
|
|
|
fprintf(stderr,
|
2020-03-01 19:51:13 +00:00
|
|
|
"libaaruformat: Could not read dump hardware block entry manufacturer, "
|
2022-10-02 18:12:35 +01:00
|
|
|
"continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.modelLength > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].model =
|
2022-10-03 18:46:17 +01:00
|
|
|
(uint8_t*)malloc(ctx->dumpHardwareEntriesWithData[e].entry.modelLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].model != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e]
|
|
|
|
|
.model[ctx->dumpHardwareEntriesWithData[e].entry.modelLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].model,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.modelLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.modelLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].model);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.modelLength = 0;
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"libaaruformat: Could not read dump hardware block entry model, continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.revisionLength > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].revision =
|
2022-10-03 18:46:17 +01:00
|
|
|
(uint8_t*)malloc(ctx->dumpHardwareEntriesWithData[e].entry.revisionLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].revision != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e]
|
|
|
|
|
.revision[ctx->dumpHardwareEntriesWithData[e].entry.revisionLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].revision,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.revisionLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.revisionLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].revision);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.revisionLength = 0;
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Could not read dump hardware block entry revision, "
|
|
|
|
|
"continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.firmwareLength > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].firmware =
|
2022-10-03 18:46:17 +01:00
|
|
|
(uint8_t*)malloc(ctx->dumpHardwareEntriesWithData[e].entry.firmwareLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].firmware != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e]
|
|
|
|
|
.firmware[ctx->dumpHardwareEntriesWithData[e].entry.firmwareLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].firmware,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.firmwareLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.firmwareLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].firmware);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.firmwareLength = 0;
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Could not read dump hardware block entry firmware, "
|
|
|
|
|
"continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.serialLength > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].serial =
|
2022-10-03 18:46:17 +01:00
|
|
|
(uint8_t*)malloc(ctx->dumpHardwareEntriesWithData[e].entry.serialLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].serial != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e]
|
|
|
|
|
.serial[ctx->dumpHardwareEntriesWithData[e].entry.serialLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].serial,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.serialLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.serialLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].serial);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.serialLength = 0;
|
2020-03-01 19:51:13 +00:00
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
2022-10-02 18:12:35 +01:00
|
|
|
"libaaruformat: Could not read dump hardware block entry serial, continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.softwareNameLength > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].softwareName =
|
2022-10-03 18:46:17 +01:00
|
|
|
(uint8_t*)malloc(ctx->dumpHardwareEntriesWithData[e].entry.softwareNameLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].softwareName != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e]
|
|
|
|
|
.softwareName[ctx->dumpHardwareEntriesWithData[e].entry.softwareNameLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].softwareName,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.softwareNameLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.softwareNameLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].softwareName);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.softwareNameLength = 0;
|
|
|
|
|
fprintf(stderr,
|
2020-03-01 19:51:13 +00:00
|
|
|
"libaaruformat: Could not read dump hardware block entry software name, "
|
2022-10-02 18:12:35 +01:00
|
|
|
"continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.softwareVersionLength > 0)
|
|
|
|
|
{
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].softwareVersion =
|
2022-10-03 18:46:17 +01:00
|
|
|
(uint8_t*)malloc(ctx->dumpHardwareEntriesWithData[e].entry.softwareVersionLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].softwareVersion != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e]
|
|
|
|
|
.softwareVersion[ctx->dumpHardwareEntriesWithData[e].entry.softwareVersionLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].softwareVersion,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.softwareVersionLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.softwareVersionLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].softwareVersion);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.softwareVersionLength = 0;
|
|
|
|
|
fprintf(stderr,
|
2020-03-01 19:51:13 +00:00
|
|
|
"libaaruformat: Could not read dump hardware block entry software version, "
|
2022-10-02 18:12:35 +01:00
|
|
|
"continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].entry.softwareOperatingSystemLength > 0)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].softwareOperatingSystem = (uint8_t*)malloc(
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.softwareOperatingSystemLength + 1);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].softwareOperatingSystem != NULL)
|
|
|
|
|
{
|
2022-10-03 18:46:17 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].softwareOperatingSystem
|
|
|
|
|
[ctx->dumpHardwareEntriesWithData[e].entry.softwareOperatingSystemLength] = 0;
|
|
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].softwareOperatingSystem,
|
2019-03-31 20:52:06 +01:00
|
|
|
1,
|
2022-10-02 17:55:45 +01:00
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.softwareOperatingSystemLength,
|
2019-03-31 20:52:06 +01:00
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData[e].entry.softwareOperatingSystemLength)
|
|
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].softwareOperatingSystem);
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.softwareOperatingSystemLength = 0;
|
|
|
|
|
fprintf(stderr,
|
2020-03-01 19:51:13 +00:00
|
|
|
"libaaruformat: Could not read dump hardware block entry manufacturer, "
|
2022-10-02 18:12:35 +01:00
|
|
|
"continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].extents =
|
2019-08-03 01:58:19 +01:00
|
|
|
(DumpExtent*)malloc(sizeof(DumpExtent) * ctx->dumpHardwareEntriesWithData->entry.extents);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
|
|
|
|
if(ctx->dumpHardwareEntriesWithData[e].extents == NULL)
|
|
|
|
|
{
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Could not allocate memory for dump hardware block extents, "
|
|
|
|
|
"continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-31 20:52:06 +01:00
|
|
|
readBytes = fread(ctx->dumpHardwareEntriesWithData[e].extents,
|
|
|
|
|
sizeof(DumpExtent),
|
|
|
|
|
ctx->dumpHardwareEntriesWithData[e].entry.extents,
|
|
|
|
|
ctx->imageStream);
|
2019-03-20 00:23:30 +00:00
|
|
|
|
2022-10-02 17:55:45 +01:00
|
|
|
if(readBytes != ctx->dumpHardwareEntriesWithData->entry.extents)
|
2019-03-20 00:23:30 +00:00
|
|
|
{
|
|
|
|
|
free(ctx->dumpHardwareEntriesWithData[e].extents);
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not read dump hardware block extents, continuing...\n");
|
2019-03-20 00:23:30 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: qsort()
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 19:44:34 +01:00
|
|
|
break;
|
|
|
|
|
case ChecksumBlock:
|
|
|
|
|
readBytes = fread(&checksum_header, 1, sizeof(ChecksumHeader), ctx->imageStream);
|
|
|
|
|
|
|
|
|
|
if(readBytes != sizeof(ChecksumHeader))
|
|
|
|
|
{
|
|
|
|
|
memset(&checksum_header, 0, sizeof(ChecksumHeader));
|
|
|
|
|
fprintf(stderr, "libaaruformat: Could not read checksums block header, continuing...\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(checksum_header.identifier != ChecksumBlock)
|
|
|
|
|
{
|
|
|
|
|
memset(&checksum_header, 0, sizeof(ChecksumHeader));
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"libaaruformat: Incorrect identifier for checksum block at position %" PRIu64 "\n",
|
|
|
|
|
idxEntries[i].offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = (uint8_t*)malloc(checksum_header.length);
|
|
|
|
|
|
|
|
|
|
if(data == NULL)
|
|
|
|
|
{
|
|
|
|
|
memset(&checksum_header, 0, sizeof(ChecksumHeader));
|
|
|
|
|
fprintf(stderr, "libaaruformat: Could not allocate memory for checksum block, continuing...\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readBytes = fread(data, 1, checksum_header.length, ctx->imageStream);
|
|
|
|
|
|
|
|
|
|
if(readBytes != checksum_header.length)
|
|
|
|
|
{
|
|
|
|
|
memset(&checksum_header, 0, sizeof(ChecksumHeader));
|
|
|
|
|
free(data);
|
|
|
|
|
fprintf(stderr, "libaaruformat: Could not read checksums block, continuing...\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = 0;
|
|
|
|
|
for(j = 0; j < checksum_header.entries; j++)
|
|
|
|
|
{
|
|
|
|
|
checksum_entry = (ChecksumEntry*)(&data[pos]);
|
|
|
|
|
pos += sizeof(ChecksumEntry);
|
|
|
|
|
|
|
|
|
|
if(checksum_entry->type == Md5)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->checksums.md5, &data[pos], MD5_DIGEST_LENGTH);
|
|
|
|
|
ctx->checksums.hasMd5 = true;
|
|
|
|
|
}
|
|
|
|
|
else if(checksum_entry->type == Sha1)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->checksums.sha1, &data[pos], SHA1_DIGEST_LENGTH);
|
|
|
|
|
ctx->checksums.hasSha1 = true;
|
|
|
|
|
}
|
|
|
|
|
else if(checksum_entry->type == Sha256)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->checksums.sha256, &data[pos], SHA256_DIGEST_LENGTH);
|
|
|
|
|
ctx->checksums.hasSha256 = true;
|
|
|
|
|
}
|
|
|
|
|
else if(checksum_entry->type == SpamSum)
|
|
|
|
|
{
|
|
|
|
|
ctx->checksums.spamsum = malloc(checksum_entry->length + 1);
|
|
|
|
|
|
|
|
|
|
if(ctx->checksums.spamsum != NULL)
|
|
|
|
|
{
|
|
|
|
|
memcpy(ctx->checksums.spamsum, &data[pos], checksum_entry->length);
|
|
|
|
|
ctx->checksums.hasSpamSum = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx->checksums.spamsum[checksum_entry->length] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos += checksum_entry->length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checksum_entry = NULL;
|
|
|
|
|
free(data);
|
|
|
|
|
|
2019-03-17 21:32:02 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fprintf(stderr,
|
2022-10-03 18:16:11 +01:00
|
|
|
"libaaruformat: Unhandled block type %4.4s with data type %d is indexed to be at %" PRIu64 "\n",
|
2019-08-03 01:58:19 +01:00
|
|
|
(char*)&idxEntries[i].blockType,
|
2022-10-03 18:16:34 +01:00
|
|
|
idxEntries[i].dataType,
|
2019-03-17 21:32:02 +00:00
|
|
|
idxEntries[i].offset);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-20 22:45:05 +00:00
|
|
|
free(idxEntries);
|
|
|
|
|
|
2019-03-20 00:35:11 +00:00
|
|
|
if(!foundUserDataDdt)
|
|
|
|
|
{
|
2022-10-02 18:12:35 +01:00
|
|
|
fprintf(stderr, "libaaruformat: Could not find user data deduplication table, aborting...\n");
|
2022-05-28 12:01:55 +01:00
|
|
|
aaruf_close(ctx);
|
2019-03-20 00:35:11 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-20 22:31:50 +00:00
|
|
|
ctx->imageInfo.CreationTime = ctx->header.creationTime;
|
|
|
|
|
ctx->imageInfo.LastModificationTime = ctx->header.lastWrittenTime;
|
2022-05-28 12:01:55 +01:00
|
|
|
ctx->imageInfo.XmlMediaType = aaruf_get_xml_mediatype(ctx->header.mediaType);
|
2019-03-20 22:31:50 +00:00
|
|
|
|
2019-03-31 20:52:06 +01:00
|
|
|
if(ctx->geometryBlock.identifier != GeometryBlock && ctx->imageInfo.XmlMediaType == BlockMedia)
|
2019-03-20 22:31:50 +00:00
|
|
|
{
|
|
|
|
|
ctx->imageInfo.Cylinders = (uint32_t)(ctx->imageInfo.Sectors / 16 / 63);
|
|
|
|
|
ctx->imageInfo.Heads = 16;
|
|
|
|
|
ctx->imageInfo.SectorsPerTrack = 63;
|
|
|
|
|
}
|
2019-03-20 00:35:11 +00:00
|
|
|
|
2022-10-02 16:05:25 +01:00
|
|
|
// Initialize caches
|
|
|
|
|
ctx->blockHeaderCache.cache = NULL;
|
|
|
|
|
ctx->blockHeaderCache.max_items = MAX_CACHE_SIZE / (ctx->imageInfo.SectorSize * (1 << ctx->shift));
|
|
|
|
|
ctx->blockCache.cache = NULL;
|
|
|
|
|
ctx->blockCache.max_items = ctx->blockHeaderCache.max_items;
|
2019-03-20 00:35:11 +00:00
|
|
|
|
|
|
|
|
// TODO: Cache tracks and sessions?
|
2019-03-23 22:59:36 +00:00
|
|
|
|
|
|
|
|
// Initialize ECC for Compact Disc
|
2022-05-28 12:01:55 +01:00
|
|
|
ctx->eccCdContext = (CdEccContext*)aaruf_ecc_cd_init();
|
2019-03-20 00:35:11 +00:00
|
|
|
|
2020-03-01 19:58:09 +00:00
|
|
|
ctx->magic = AARU_MAGIC;
|
2020-03-01 19:53:05 +00:00
|
|
|
ctx->libraryMajorVersion = LIBAARUFORMAT_MAJOR_VERSION;
|
|
|
|
|
ctx->libraryMinorVersion = LIBAARUFORMAT_MINOR_VERSION;
|
2019-03-17 21:14:40 +00:00
|
|
|
|
2019-03-17 20:39:40 +00:00
|
|
|
return ctx;
|
|
|
|
|
}
|