Add function to retrieve readable media tags

This commit is contained in:
2025-10-18 17:53:38 +01:00
parent 0bb3a3376b
commit 5cfffbcb68
3 changed files with 177 additions and 3 deletions

View File

@@ -1007,7 +1007,8 @@ typedef enum
MiniDiscD5 = 70, ///< 4 bytes response to vendor command D5h
MiniDiscUTOC = 71, ///< User TOC, contains fragments, track names, and can be from 1 to 3 sectors of 2336 bytes
MiniDiscDTOC = 72, ///< Not entirely clear kind of TOC that only appears on MD-DATA discs
DVD_DiscKey_Decrypted = 73 ///< Decrypted DVD disc key
DVD_DiscKey_Decrypted = 73, ///< Decrypted DVD disc key,
MaxMediaTag = DVD_DiscKey_Decrypted
} MediaTagType;
/** @} */ /* end of MediaTags group */

View File

@@ -196,6 +196,7 @@ AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_model(void *context);
AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_serial_number(void *context);
AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_firmware_revision(void *context);
AARU_EXPORT int32_t AARU_CALL aaruf_get_readable_sector_tags(const void *context, uint8_t *buffer, size_t *length);
AARU_EXPORT int32_t AARU_CALL aaruf_get_readable_media_tags(const void *context, uint8_t *buffer, size_t *length);
AARU_EXPORT int32_t AARU_CALL aaruf_get_tape_file(const void *context, uint8_t partition, uint32_t file,
uint64_t *starting_block, uint64_t *ending_block);

View File

@@ -539,6 +539,82 @@ void process_aaru_metadata_json_block(aaruformat_context *ctx, const IndexEntry
TRACE("Exiting process_aaru_metadata_json_block()");
}
/**
* @brief Retrieves which sector tags are readable in the AaruFormat image.
*
* Returns an array of booleans indicating whether each SectorTagType was successfully read
* from the image. The array is indexed by SectorTagType enum values (0 to MaxSectorTag),
* where each boolean is true if the corresponding sector tag data is present and readable
* in the image. Sector tags contain per-sector metadata such as sync headers, ECC/EDC codes,
* subchannels, and other sector-level information essential for exact media reconstruction.
*
* @param context Pointer to the aaruformat context (must be a valid, opened image context).
* @param buffer Pointer to a buffer to store the boolean array. Can be NULL to query required length.
* @param length Pointer to the buffer length. On input, contains buffer size; on output, contains required size.
*
* @return Returns one of the following status codes:
* @retval AARUF_STATUS_OK (0) Successfully retrieved readable sector tags. This is returned when:
* - The context is valid and properly initialized
* - The readableSectorTags array is populated in the context
* - The buffer is large enough to hold all SectorTagType values (0 to MaxSectorTag)
* - The output array has been successfully copied from the internal readableSectorTags
*
* @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_METADATA_NOT_PRESENT (-30) The sector tags array is not available. This occurs when:
* - The readableSectorTags array is NULL (not initialized in the context)
* - The image was created without sector tag support
* - The image format does not support or require sector tags
*
* @retval AARUF_ERROR_BUFFER_TOO_SMALL (-10) The buffer is too small. This occurs when:
* - The buffer parameter is NULL
* - The length parameter is NULL
* - The provided buffer is smaller than required (size = (MaxSectorTag + 1) * sizeof(bool))
* - The length output will contain the required buffer size in bytes
*
* @note Buffer Size:
* The buffer must be at least (MaxSectorTag + 1) bytes, where each byte represents
* whether the corresponding SectorTagType data was successfully read in the image.
* On most systems, sizeof(bool) == 1, so the required size is (MaxSectorTag + 1) bytes.
*
* @note Sector Tag Types:
* Sector tags preserve on-disk structures not part of main user data. Examples include:
* - CD sector sync/header information (CdSectorSync, CdSectorHeader)
* - CD subheaders and ECC/EDC codes (CdSectorSubHeader, CdSectorEcc, CdSectorEdc)
* - DVD sector numbers and IED (DvdSectorNumber)
* - Media-specific proprietary tags (AppleProfileTagAaru, PriamDataTowerTagAaru)
*
* @note Query Mode:
* To query the required buffer size, pass buffer == NULL or *length < required.
* The function will return AARUF_ERROR_BUFFER_TOO_SMALL and set *length to required size.
* This allows allocation of properly sized buffers without prior knowledge of MaxSectorTag.
*
* @note Data Interpretation:
* A true value (non-zero) at buffer[i] indicates sector tag type i was readable.
* A false value (zero) at buffer[i] indicates that sector tag type i is either not present
* or was not successfully read from the image during opening.
* The readableSectorTags array is populated during image opening/processing in data blocks.
*
* @note Image Opening Context:
* The readableSectorTags array is initialized during aaruf_open() or aaruf_create()
* and populated as data blocks are processed. It reflects what was actually present
* and readable in the image file, not what theoretically could be present for the media type.
*
* @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 If readableSectorTags is NULL in the context, AARUF_ERROR_NOT_FOUND is returned.
* This typically indicates the image format does not support sector-level tags,
* rather than indicating an error state. Check return value to distinguish.
*
* @see SectorTagType for enumeration of all available sector tag types
* @see aaruf_read_sector_tag() for reading individual sector tag data
* @see aaruf_write_sector_tag() for writing sector tags during image creation
*/
AARU_EXPORT int32_t AARU_CALL aaruf_get_readable_sector_tags(const void *context, uint8_t *buffer, size_t *length)
{
TRACE("Entering aaruf_get_readable_sector_tags(%p, %p, %zu)", context, buffer, (length ? *length : 0));
@@ -576,8 +652,8 @@ AARU_EXPORT int32_t AARU_CALL aaruf_get_readable_sector_tags(const void *context
if(buffer == NULL || length == NULL || *length < required_length)
{
if(length) *length = required_length;
TRACE("Buffer too small for readable sector tags, required %zu bytes", required_length);
TRACE("Exiting aaruf_get_readable_sector_tags() = AARUF_ERROR_BUFFER_TOO_SMALL");
return AARUF_ERROR_BUFFER_TOO_SMALL;
}
@@ -587,4 +663,100 @@ AARU_EXPORT int32_t AARU_CALL aaruf_get_readable_sector_tags(const void *context
TRACE("Exiting aaruf_get_readable_sector_tags(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
return AARUF_STATUS_OK;
}
}
/**
* @brief Retrieves which media tags are present in the AaruFormat image.
*
* Returns an array of booleans indicating the presence of each MediaTagType in the image.
* The array is indexed by MediaTagType enum values (0 to MaxMediaTag), where each boolean
* is true if the corresponding media tag exists in the image's mediaTags hash table.
*
* @param context Pointer to the aaruformat context (must be a valid, opened image context).
* @param buffer Pointer to a buffer to store the boolean array. Can be NULL to query required length.
* @param length Pointer to the buffer length. On input, contains buffer size; on output, contains required size.
*
* @return Returns one of the following status codes:
* @retval AARUF_STATUS_OK (0) Successfully retrieved readable media tags. This is returned when:
* - The context is valid and properly initialized
* - The buffer is large enough to hold all MediaTagType values (0 to MaxMediaTag)
* - The output array has been populated with true/false for each MediaTagType
*
* @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)
*
* @retval AARUF_ERROR_BUFFER_TOO_SMALL (-10) The buffer is too small. This occurs when:
* - The buffer parameter is NULL
* - The length parameter is NULL
* - The provided buffer is smaller than required (size = MaxMediaTag + 1 bytes)
* - The length output will contain the required buffer size
*
* @note Buffer Size:
* The buffer must be at least (MaxMediaTag + 1) bytes, where each byte represents
* whether the corresponding MediaTagType is present in the image.
*
* @note Query Mode:
* To query the required buffer size, pass buffer == NULL or *length < required.
* The function will return AARUF_ERROR_BUFFER_TOO_SMALL and set *length to required size.
*
* @warning The output parameters are only modified on success (AARUF_STATUS_OK).
* On error, their values remain unchanged.
*/
AARU_EXPORT int32_t AARU_CALL aaruf_get_readable_media_tags(const void *context, uint8_t *buffer, size_t *length)
{
TRACE("Entering aaruf_get_readable_media_tags(%p, %p, %zu)", context, buffer, (length ? *length : 0));
// Check context is correct AaruFormat context
if(context == NULL)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_get_readable_media_tags() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
const aaruformat_context *ctx = context;
// Not a libaaruformat context
if(ctx->magic != AARU_MAGIC)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_get_readable_media_tags() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
// Required size: one byte for each MediaTagType (0 to MaxMediaTag)
size_t required_length = MaxMediaTag + 1;
if(buffer == NULL || length == NULL || *length < required_length)
{
if(length) *length = required_length;
TRACE("Buffer too small for readable media tags, required %zu bytes", required_length);
TRACE("Exiting aaruf_get_readable_media_tags() = AARUF_ERROR_BUFFER_TOO_SMALL");
return AARUF_ERROR_BUFFER_TOO_SMALL;
}
// Initialize all bytes to false (0)
memset(buffer, 0, required_length);
// Iterate through all media tag types and mark present ones as true
for(int32_t tag_type = 0; tag_type <= MaxMediaTag; tag_type++)
{
mediaTagEntry *item = NULL;
HASH_FIND_INT(ctx->mediaTags, &tag_type, item);
if(item != NULL)
{
buffer[tag_type] = 1;
TRACE("Media tag type %d is present", tag_type);
}
}
*length = required_length;
TRACE("Exiting aaruf_get_readable_media_tags(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
return AARUF_STATUS_OK;
}