From 806fa49d417fca778b3144de134c03be08f0de37 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 4 Oct 2025 23:12:31 +0100 Subject: [PATCH] Add function to retrieve CHS geometry from AaruFormat image --- CMakeLists.txt | 3 +- include/aaruformat/decls.h | 8 ++- src/metadata.c | 131 +++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 src/metadata.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 493877e..01a153e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,7 +133,8 @@ add_library(aaruformat SHARED include/aaruformat/consts.h include/aaruformat/enu src/checksum/sha256.c include/sha256.h src/lisa_tag.c - include/aaruformat/structs/lisa_tag.h) + include/aaruformat/structs/lisa_tag.h + src/metadata.c) include_directories(include include/aaruformat 3rdparty/uthash/include 3rdparty/uthash/src) diff --git a/include/aaruformat/decls.h b/include/aaruformat/decls.h index 5c47b48..e7ff1f7 100644 --- a/include/aaruformat/decls.h +++ b/include/aaruformat/decls.h @@ -96,7 +96,8 @@ AARU_EXPORT int32_t AARU_CALL aaruf_write_sector(void *context, uint64_t sector_ const uint8_t *data, uint8_t sector_status, uint32_t length); AARU_EXPORT int32_t AARU_CALL aaruf_write_sector_long(void *context, uint64_t sector_address, bool negative, const uint8_t *data, uint8_t sector_status, uint32_t length); -AARU_EXPORT int32_t AARU_CALL write_media_tag(void *context, const uint8_t *data, const int32_t type, const uint32_t length); +AARU_EXPORT int32_t AARU_CALL write_media_tag(void *context, const uint8_t *data, const int32_t type, + const uint32_t length); AARU_EXPORT int32_t AARU_CALL aaruf_verify_image(void *context); @@ -136,11 +137,12 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_track_sector(void *context, uint8_t *da uint32_t *length, uint8_t track); AARU_LOCAL int32_t AARU_CALL aaruf_get_media_tag_type_for_datatype(int32_t type); - AARU_LOCAL int32_t AARU_CALL aaruf_get_datatype_for_media_tag_type(int32_t tag_type); - AARU_LOCAL int32_t AARU_CALL aaruf_get_xml_mediatype(int32_t type); +AARU_EXPORT int32_t AARU_CALL aaruf_get_geometry(const void *context, uint32_t *cylinders, uint32_t *heads, + uint32_t *sectors_per_track); + AARU_EXPORT spamsum_ctx *AARU_CALL aaruf_spamsum_init(void); AARU_EXPORT int AARU_CALL aaruf_spamsum_update(spamsum_ctx *ctx, const uint8_t *data, uint32_t len); AARU_EXPORT int AARU_CALL aaruf_spamsum_final(spamsum_ctx *ctx, uint8_t *result); diff --git a/src/metadata.c b/src/metadata.c new file mode 100644 index 0000000..dbd2638 --- /dev/null +++ b/src/metadata.c @@ -0,0 +1,131 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2025 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 . + */ + +#include + +#include "aaruformat.h" +#include "log.h" + +/** + * @brief Retrieves the logical CHS geometry from the AaruFormat image. + * + * Reads the Cylinder-Head-Sector (CHS) geometry information from the image's geometry + * block and returns the values through output parameters. The geometry block contains + * legacy-style logical addressing parameters that describe how the storage medium was + * originally organized in terms of cylinders, heads (tracks per cylinder), and sectors + * per track. This information is essential for software that requires CHS addressing + * or for accurately representing the original medium's logical structure. + * + * @param context Pointer to the aaruformat context (must be a valid, opened image context). + * @param cylinders Pointer to store the number of cylinders. Updated on success. + * @param heads Pointer to store the number of heads (tracks per cylinder). Updated on success. + * @param sectors_per_track Pointer to store the number of sectors per track. Updated on success. + * + * @return Returns one of the following status codes: + * @retval AARUF_STATUS_OK (0) Successfully retrieved geometry information. This is returned when: + * - The context is valid and properly initialized + * - The geometry block is present in the image (identifier == GeometryBlock) + * - All three output parameters are successfully populated with geometry values + * - The cylinders parameter contains the total number of cylinders + * - The heads parameter contains the number of heads per cylinder + * - The sectors_per_track parameter contains the number of sectors per track + * + * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when: + * - The context parameter is NULL + * - The context magic number doesn't match AARU_MAGIC (invalid context type) + * - The context was not properly initialized by aaruf_open() or aaruf_create() + * + * @retval AARUF_ERROR_CANNOT_READ_BLOCK (-6) The geometry block is not present. This occurs when: + * - The image was created without geometry information + * - The geometryBlock.identifier field doesn't equal GeometryBlock + * - The geometry block was not found during image opening + * - The image format doesn't support or require CHS geometry + * + * @note Geometry Interpretation: + * - Total logical sectors = cylinders × heads × sectors_per_track + * - Sector size is not included in the geometry block and must be obtained separately + * (typically 512 bytes for most block devices, but can vary) + * - The geometry represents logical addressing, not necessarily physical medium geometry + * - Modern storage devices often report translated or synthetic geometry values + * + * @note CHS Addressing Context: + * - CHS addressing was historically used for hard disk drives and floppy disks + * - Legacy BIOS and older operating systems relied on CHS parameters + * - LBA (Logical Block Addressing) has largely replaced CHS for modern devices + * - Some disk image formats and emulators still require CHS information + * + * @note Geometry Block Availability: + * - Not all image types contain geometry blocks + * - Optical media (CDs, DVDs) typically don't have CHS geometry + * - Modern large-capacity drives may not have meaningful CHS values + * - Check the return value to determine if geometry is available + * + * @note Parameter Validation: + * - All output parameters must be non-NULL valid pointers + * - The function does not validate the geometry values themselves + * - Geometry values of zero or unusually large values may indicate issues + * + * @warning The output parameters are only modified on success (AARUF_STATUS_OK). + * On error, their values remain unchanged. Initialize them before calling + * if default values are needed on failure. + * + * @warning This function reads from the in-memory geometry block loaded during + * aaruf_open(). It does not perform file I/O operations. + * + * @warning Geometry values may not accurately represent physical device geometry, + * especially for modern drives with zone-based recording or flash storage. + */ +int32_t aaruf_get_geometry(const void *context, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors_per_track) +{ + TRACE("Entering aaruf_get_geometry(%p, %u, %u, %u)", context, *cylinders, *heads, *sectors_per_track); + + const aaruformatContext *ctx = NULL; + + if(context == NULL) + { + FATAL("Invalid context"); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_AARUFORMAT"); + return AARUF_ERROR_NOT_AARUFORMAT; + } + + ctx = context; + + // Not a libaaruformat context + if(ctx->magic != AARU_MAGIC) + { + FATAL("Invalid context"); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_AARUFORMAT"); + return AARUF_ERROR_NOT_AARUFORMAT; + } + + if(ctx->geometryBlock.identifier != GeometryBlock) + { + FATAL("No geometry block present"); + + TRACE("Exiting aaruf_get_geometry() = AARUF_ERROR_CANNOT_READ_BLOCK"); + return AARUF_ERROR_CANNOT_READ_BLOCK; + } + + *cylinders = ctx->geometryBlock.cylinders; + *heads = ctx->geometryBlock.heads; + *sectors_per_track = ctx->geometryBlock.sectorsPerTrack; + + return AARUF_STATUS_OK; +} \ No newline at end of file