diff --git a/include/aaruformat/context.h b/include/aaruformat/context.h index ce4434f..818be35 100644 --- a/include/aaruformat/context.h +++ b/include/aaruformat/context.h @@ -22,6 +22,30 @@ #include "lru.h" #include "structs.h" +#ifndef MD5_DIGEST_LENGTH +#define MD5_DIGEST_LENGTH 16 +#endif + +#ifndef SHA1_DIGEST_LENGTH +#define SHA1_DIGEST_LENGTH 20 +#endif + +#ifndef SHA256_DIGEST_LENGTH +#define SHA256_DIGEST_LENGTH 32 +#endif + +typedef struct Checksums +{ + bool hasMd5; + bool hasSha1; + bool hasSha256; + bool hasSpamSum; + uint8_t md5[MD5_DIGEST_LENGTH]; + uint8_t sha1[SHA1_DIGEST_LENGTH]; + uint8_t sha256[SHA256_DIGEST_LENGTH]; + uint8_t* spamsum; +} Checksums; + typedef struct aaruformatContext { uint64_t magic; @@ -59,6 +83,7 @@ typedef struct aaruformatContext bool* readableSectorTags; struct CacheHeader blockHeaderCache; struct CacheHeader blockCache; + struct Checksums checksums; } aaruformatContext; typedef struct dataLinkedList diff --git a/src/close.c b/src/close.c index 8c227c0..ca1574b 100644 --- a/src/close.c +++ b/src/close.c @@ -141,6 +141,9 @@ int aaruf_close(void* context) free(ctx->eccCdContext); ctx->eccCdContext = NULL; + free(ctx->checksums.spamsum); + ctx->checksums.spamsum = NULL; + // TODO: Free caches free(context); diff --git a/src/open.c b/src/open.c index 0295dda..1d52d7d 100644 --- a/src/open.c +++ b/src/open.c @@ -45,6 +45,8 @@ void* aaruf_open(const char* filepath) uint16_t e; uint8_t lzmaProperties[LZMA_PROPERTIES_LENGTH]; size_t lzmaSize; + ChecksumHeader checksum_header; + ChecksumEntry* checksum_entry; ctx = (aaruformatContext*)malloc(sizeof(aaruformatContext)); memset(ctx, 0, sizeof(aaruformatContext)); @@ -1405,6 +1407,84 @@ void* aaruf_open(const char* filepath) // TODO: qsort() } + 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); + break; default: fprintf(stderr, diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt index 8a4aac8..05e4e55 100644 --- a/tool/CMakeLists.txt +++ b/tool/CMakeLists.txt @@ -4,5 +4,5 @@ find_package(ICU COMPONENTS uc REQUIRED) include_directories(${ICU_INCLUDE_DIRS}) -add_executable(aaruformattool main.c main.h aaruformattool.h identify.c info.c) +add_executable(aaruformattool main.c main.h aaruformattool.h identify.c info.c helpers.c) target_link_libraries(aaruformattool "aaruformat" ICU::uc) diff --git a/tool/aaruformattool.h b/tool/aaruformattool.h index d95f236..e166341 100644 --- a/tool/aaruformattool.h +++ b/tool/aaruformattool.h @@ -19,7 +19,8 @@ #ifndef LIBAARUFORMAT_TOOL_AARUFORMATTOOL_H_ #define LIBAARUFORMAT_TOOL_AARUFORMATTOOL_H_ -int identify(char* path); -int info(char *path); +int identify(char* path); +int info(char* path); +char* byte_array_to_hex_string(const unsigned char* array, int array_size); #endif // LIBAARUFORMAT_TOOL_AARUFORMATTOOL_H_ diff --git a/tool/helpers.c b/tool/helpers.c new file mode 100644 index 0000000..3c0f82e --- /dev/null +++ b/tool/helpers.c @@ -0,0 +1,52 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2022 Natalia Portillo. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "aaruformattool.h" + +char* byte_array_to_hex_string(const unsigned char* array, int array_size) +{ + char* hex_string = NULL; + int j; + int i; + + hex_string = malloc(array_size * 2 + 1); + + if(hex_string == NULL) return NULL; + + j = 0; + for(i = 0; i < array_size; i++) + { + hex_string[j] = (array[i] >> 4) + '0'; + if(hex_string[j] > '9') hex_string[j] += 0x7; + + j++; + + hex_string[j] = (array[i] & 0xF) + '0'; + if(hex_string[j] > '9') hex_string[j] += 0x7; + + j++; + } + + hex_string[j] = 0; + + return hex_string; +} diff --git a/tool/info.c b/tool/info.c index 6225947..37f610b 100644 --- a/tool/info.c +++ b/tool/info.c @@ -23,6 +23,8 @@ #include +#include "aaruformattool.h" + int info(char* path) { aaruformatContext* ctx; @@ -287,11 +289,11 @@ int info(char* path) printf("\tTrack entry %d:\n", i); printf("\t\tSequence: %d\n", ctx->trackEntries[i].sequence); printf("\t\tType: %d\n", ctx->trackEntries[i].type); - printf("\t\tStart: %d\n", ctx->trackEntries[i].start); - printf("\t\tEnd: %d\n", ctx->trackEntries[i].end); - printf("\t\tPregap: %d\n", ctx->trackEntries[i].pregap); + printf("\t\tStart: %ld\n", ctx->trackEntries[i].start); + printf("\t\tEnd: %ld\n", ctx->trackEntries[i].end); + printf("\t\tPregap: %ld\n", ctx->trackEntries[i].pregap); printf("\t\tSession: %d\n", ctx->trackEntries[i].session); - printf("\t\tISRC: %0.13s\n", ctx->trackEntries[i].isrc); + printf("\t\tISRC: %.13s\n", ctx->trackEntries[i].isrc); printf("\t\tFlags: %d\n", ctx->trackEntries[i].flags); } } @@ -507,6 +509,29 @@ int info(char* path) ctx->imageInfo.Heads, ctx->imageInfo.SectorsPerTrack); + if(ctx->checksums.hasMd5) + { + strBuffer = byte_array_to_hex_string(ctx->checksums.md5, MD5_DIGEST_LENGTH); + printf("MD5: %s\n", strBuffer); + free(strBuffer); + } + + if(ctx->checksums.hasSha1) + { + strBuffer = byte_array_to_hex_string(ctx->checksums.sha1, SHA1_DIGEST_LENGTH); + printf("SHA1: %s\n", strBuffer); + free(strBuffer); + } + + if(ctx->checksums.hasSha256) + { + strBuffer = byte_array_to_hex_string(ctx->checksums.sha256, SHA256_DIGEST_LENGTH); + printf("SHA256: %s\n", strBuffer); + free(strBuffer); + } + + if(ctx->checksums.hasSpamSum) printf("SpamSum: %s\n", ctx->checksums.spamsum); + aaruf_close(ctx); return 0;