mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2025-12-16 19:24:40 +00:00
Add function to retrieve block range for specific tape files
This commit is contained in:
@@ -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_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_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_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);
|
AARU_EXPORT int32_t AARU_CALL aaruf_set_dumphw(void *context, uint8_t *data, size_t length);
|
||||||
|
|
||||||
|
|||||||
@@ -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_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_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_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)
|
/** \name Non-fatal sector status codes (non-negative)
|
||||||
|
|||||||
@@ -219,3 +219,172 @@ void process_tape_files_block(aaruformatContext *ctx, const IndexEntry *entry)
|
|||||||
|
|
||||||
free(buffer);
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user