From 544669c702f96ec7b73a13ddb89d9c77cb7505e4 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 21 Mar 2019 01:06:21 +0000 Subject: [PATCH] Implement sector reading. --- CMakeLists.txt | 2 +- include/dicformat/decls.h | 2 + include/dicformat/errors.h | 4 ++ src/read.c | 123 ++++++++++++++++++++++++++++++++++++- 4 files changed, 128 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8ad7c8..c1387e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(libdicformat C) set(CMAKE_C_STANDARD 99) add_compile_definitions(__STDC_FORMAT_MACROS=1) -add_library(libdicformat SHARED include/dicformat/consts.h include/dicformat/enums.h include/dic.h include/dicformat.h +add_library(dicformat SHARED include/dicformat/consts.h include/dicformat/enums.h include/dic.h include/dicformat.h include/dicformat/decls.h include/dicformat/structs.h src/identify.c src/open.c include/dicformat/context.h src/close.c include/dicformat/errors.h src/read.c src/crc64.c) include_directories(include include/dicformat) \ No newline at end of file diff --git a/include/dicformat/decls.h b/include/dicformat/decls.h index 33dcb73..0392387 100644 --- a/include/dicformat/decls.h +++ b/include/dicformat/decls.h @@ -58,4 +58,6 @@ uint64_t crc64_data(const uint8_t *data, size_t len, uint64_t polynomial, uint64 uint64_t crc64_data_ecma(const uint8_t *data, size_t len); +uint8_t *read_sector(void *context, uint64_t sectorAddress, uint32_t *length); + #endif //LIBDICFORMAT_DECLS_H diff --git a/include/dicformat/errors.h b/include/dicformat/errors.h index a01323b..6f132d9 100644 --- a/include/dicformat/errors.h +++ b/include/dicformat/errors.h @@ -9,5 +9,9 @@ #define DICF_ERROR_FILE_TOO_SMALL -2 #define DICF_ERROR_INCOMPATIBLE_VERSION -3 #define DICF_ERROR_CANNOT_READ_INDEX -4 +#define DICF_ERROR_SECTOR_OUT_OF_BOUNDS -5 +#define DICF_ERROR_CANNOT_READ_HEADER -6 +#define DICF_ERROR_CANNOT_READ_BLOCK -7 +#define DICF_ERROR_UNSUPPORTED_COMPRESSION -8 #endif //LIBDICFORMAT_ERRORS_H diff --git a/src/read.c b/src/read.c index 256f95e..a7b6978 100644 --- a/src/read.c +++ b/src/read.c @@ -32,9 +32,13 @@ #include #include +#include +#include uint8_t *read_media_tag(void *context, int32_t tag, uint32_t *length) { + dicformatContext *ctx; + dataLinkedList *item; *length = 0; if(context == NULL) @@ -43,7 +47,7 @@ uint8_t *read_media_tag(void *context, int32_t tag, uint32_t *length) return NULL; } - dicformatContext *ctx = context; + ctx = context; // TODO: Cast this field without casting the whole structure, as this can buffer overflow // Not a libdicformat context @@ -53,7 +57,7 @@ uint8_t *read_media_tag(void *context, int32_t tag, uint32_t *length) return NULL; } - dataLinkedList *item = ctx->mediaTagsHead; + item = ctx->mediaTagsHead; while(item != NULL) { @@ -67,4 +71,119 @@ uint8_t *read_media_tag(void *context, int32_t tag, uint32_t *length) } return NULL; +} + +uint8_t *read_sector(void *context, uint64_t sectorAddress, uint32_t *length) +{ + dicformatContext *ctx; + uint64_t ddtEntry; + uint32_t offsetMask; + uint64_t offset; + uint64_t blockOffset; + uint8_t *sector; + BlockHeader blockHeader; + uint8_t *block; + size_t readBytes; + + *length = 0; + + if(context == NULL) + { + errno = EINVAL; + return NULL; + } + + ctx = context; + + // TODO: Cast this field without casting the whole structure, as this can buffer overflow + // Not a libdicformat context + if(ctx->magic != DIC_MAGIC) + { + errno = EINVAL; + return NULL; + } + + if(sectorAddress > ctx->imageInfo.Sectors - 1) + { + errno = DICF_ERROR_SECTOR_OUT_OF_BOUNDS; + return NULL; + } + + ddtEntry = ctx->userDataDdt[sectorAddress]; + offsetMask = (uint32_t)((1 << ctx->shift) - 1); + offset = ddtEntry & offsetMask; + blockOffset = ddtEntry >> ctx->shift; + + // Partially written image... as we can't know the real sector size just assume it's common :/ + if(ddtEntry == 0) + { + sector = (uint8_t *)malloc(ctx->imageInfo.SectorSize); + + if(sector == NULL) + { + errno = ENOMEM; + return NULL; + } + + memset(sector, 0, ctx->imageInfo.SectorSize); + *length = ctx->imageInfo.SectorSize; + return sector; + } + + // Check if block is cached + // TODO: Caches + + // Read block header + fseek(ctx->imageStream, blockOffset, SEEK_SET); + readBytes = fread(&blockHeader, sizeof(BlockHeader), 1, ctx->imageStream); + + if(readBytes != sizeof(BlockHeader)) + { + errno = DICF_ERROR_CANNOT_READ_HEADER; + return NULL; + } + + // Decompress block + switch(blockHeader.compression) + { + case None:block = (uint8_t *)malloc(blockHeader.length); + if(block == NULL) + { + errno = ENOMEM; + return NULL; + } + + readBytes = fread(block, blockHeader.length, 1, ctx->imageStream); + + if(readBytes != blockHeader.length) + { + free(block); + errno = DICF_ERROR_CANNOT_READ_BLOCK; + return NULL; + } + + break; + default:errno = DICF_ERROR_UNSUPPORTED_COMPRESSION; + return NULL; + } + + // Check if cache needs to be emptied + // TODO: Caches + + // Add block to cache + // TODO: Caches + + sector = (uint8_t *)malloc(blockHeader.sectorSize); + + if(sector == NULL) + { + free(block); + errno = ENOMEM; + return NULL; + } + + memcpy(sector, block + offset, blockHeader.sectorSize); + *length = blockHeader.sectorSize; + free(block); + return sector; } \ No newline at end of file