Add function to retrieve block range for specific tape files

This commit is contained in:
2025-10-07 11:45:46 +01:00
parent f62899ed06
commit 345d101df1
3 changed files with 173 additions and 0 deletions

View File

@@ -164,6 +164,9 @@ AARU_EXPORT int32_t AARU_CALL aaruf_get_cicm_metadata(const void *context, uint8
AARU_EXPORT int32_t AARU_CALL aaruf_get_aaru_json_metadata(const void *context, uint8_t *buffer, size_t *length);
AARU_EXPORT int32_t AARU_CALL aaruf_set_aaru_json_metadata(void *context, uint8_t *data, 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);
AARU_EXPORT int32_t AARU_CALL aaruf_get_dumphw(void *context, uint8_t *buffer, size_t *length);
AARU_EXPORT int32_t AARU_CALL aaruf_set_dumphw(void *context, uint8_t *data, size_t length);

View File

@@ -64,6 +64,7 @@
#define AARUF_ERROR_CANNOT_SET_DDT_ENTRY (-25) ///< Failed to encode/store a DDT entry (overflow or IO).
#define AARUF_ERROR_INCORRECT_DATA_SIZE (-26) ///< Data size does not match expected size.
#define AARUF_ERROR_INVALID_TAG (-27) ///< Invalid or unsupported media or sector tag format.
#define AARUF_ERROR_TAPE_FILE_NOT_FOUND (-28) ///< Requested tape file number not present in image.
/** @} */
/** \name Non-fatal sector status codes (non-negative)

View File

@@ -218,4 +218,173 @@ void process_tape_files_block(aaruformatContext *ctx, const IndexEntry *entry)
}
free(buffer);
}
/**
* @brief Retrieves the block range for a specific tape file from an Aaru tape image.
*
* Queries the tape file hash table to locate a file by its partition and file number,
* returning the first and last block addresses that define the file's extent on the
* tape medium. This function provides the core lookup mechanism for accessing logical
* files stored in tape images.
*
* **Tape File Identification:**
* Each tape file is uniquely identified by a combination of:
* - **Partition number** (8-bit): The tape partition containing the file
* - **File number** (32-bit): The sequential file number within that partition
*
* These two values are combined into a 64-bit composite key:
* key = (partition << 32) | file_number
*
* This composite key is used to perform a hash table lookup in the context's
* tapeFiles table, which was previously populated by process_tape_files_block()
* during image initialization.
*
* **Block Range Semantics:**
* The returned block range [FirstBlock, LastBlock] is inclusive on both ends:
* - FirstBlock: The first block address where the file begins
* - LastBlock: The final block address where the file ends (inclusive)
* - Block count: (LastBlock - FirstBlock + 1)
*
* Block addresses are absolute positions within the tape image's logical
* block space, not relative to the partition or file.
*
* **Typical Usage Flow:**
* 1. Open an Aaru tape image with aaruf_open()
* 2. Call aaruf_get_tape_file() to get the block range for a specific file
* 3. Use the returned block range to read the file's data blocks
* 4. Repeat for other files as needed
*
* **Error Handling:**
* The function performs validation in the following order:
* 1. Context pointer validation (NULL check)
* 2. Magic number verification (ensures valid aaruformat context)
* 3. Hash table lookup for the specified partition/file combination
*
* If any validation fails, an appropriate error code is returned and the
* output parameters (starting_block, ending_block) are left unmodified.
*
* **Thread Safety:**
* This function performs read-only operations on the context and is safe
* to call from multiple threads concurrently, provided the context is not
* being modified by other operations (e.g., during image opening/closing).
*
* **Performance Characteristics:**
* - Hash table lookup: O(1) average case
* - No I/O operations performed
* - Minimal stack usage
* - Suitable for high-frequency queries
*
* @param context Pointer to an initialized aaruformat context. Must not be NULL.
* The context must have been successfully opened with aaruf_open()
* and contain a valid tape file hash table. The context is treated
* as const and is not modified by this operation.
*
* @param partition The partition number (0-255) containing the requested file.
* For single-partition tapes, this is typically 0. Multi-partition
* tapes may have files in different partitions with potentially
* overlapping file numbers.
*
* @param file The file number within the specified partition. File numbers are
* typically sequential starting from 0 or 1, but gaps may exist if
* files were deleted or the tape was written non-sequentially.
*
* @param[out] starting_block Pointer to receive the first block address of the file.
* Must not be NULL. Only modified on success.
* The value written represents the inclusive start of the
* file's block range.
*
* @param[out] ending_block Pointer to receive the last block address of the file.
* Must not be NULL. Only modified on success.
* The value written represents the inclusive end of the
* file's block range.
*
* @retval AARUF_STATUS_OK (0) Successfully retrieved tape file information. Both
* output parameters have been populated with valid block addresses. The
* requested partition/file combination exists in the image's file table.
*
* @retval AARUF_ERROR_NOT_AARUFORMAT (-1) Invalid context or context validation failed.
* This is returned when:
* - The context pointer is NULL
* - The context magic number doesn't match AARU_MAGIC (corrupted or wrong type)
* The output parameters are not modified.
*
* @retval AARUF_ERROR_TAPE_FILE_NOT_FOUND (-28) The requested partition/file combination
* does not exist in the image's tape file table. This is returned when:
* - The specified partition number has no files
* - The specified file number doesn't exist in the given partition
* - The tape file block was not present or failed to load during image open
* The output parameters are not modified.
*
* @note The function logs entry and exit points via TRACE macros when tracing is
* enabled, including parameter values and return codes for debugging.
*
* @note The tape file hash table (ctx->tapeFiles) must have been populated during
* image initialization. If the image doesn't contain a TapeFileBlock, or if
* that block failed to load, all queries will return AARUF_ERROR_TAPE_FILE_NOT_FOUND.
*
* @note For images without tape file metadata, applications should fall back to
* direct block-based access or partition-level operations.
*
* @note The returned block addresses are logical block numbers. To read actual data,
* these must be translated through the appropriate read functions that handle
* the image's block encoding, compression, and DDT mapping.
*
* @warning The output parameter pointers must be valid. Passing NULL for either
* starting_block or ending_block will cause undefined behavior (likely
* a crash when the function attempts to dereference them on success).
*
* @warning If the same partition/file combination appears multiple times in the
* TapeFileBlock, only the last occurrence is retained (due to HASH_REPLACE
* behavior in process_tape_files_block). This should not occur in valid
* images but may happen with corrupted or malformed tape file metadata.
*
* @see process_tape_files_block() for tape file table initialization
* @see TapeFileEntry for the structure defining file block ranges
* @see tapeFileHashEntry for the hash table entry structure
* @see aaruf_get_tape_partition() for partition-level queries (if available)
*/
int32_t aaruf_get_tape_file(const void *context, const uint8_t partition, const uint32_t file, uint64_t *starting_block,
uint64_t *ending_block)
{
TRACE("Entering aaruf_get_tape_file(%p, %d, %d, %llu, %llu)", context, partition, file, *starting_block,
*ending_block);
const aaruformatContext *ctx = NULL;
if(context == NULL)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_get_tape_file() = 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_get_tape_file() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
uint64_t key = (uint64_t)partition << 32 | file;
tapeFileHashEntry *entry = NULL;
HASH_FIND(hh, ctx->tapeFiles, &key, sizeof(uint64_t), entry);
if(entry == NULL)
{
TRACE("Tape file not found");
return AARUF_ERROR_TAPE_FILE_NOT_FOUND;
}
*starting_block = entry->fileEntry.FirstBlock;
*ending_block = entry->fileEntry.LastBlock;
TRACE("Exiting aaruf_get_tape_file(%p, %d, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, file,
*starting_block, *ending_block);
return AARUF_STATUS_OK;
}