Loading...
Searching...
No Matches
tape.c
Go to the documentation of this file.
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2026 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 <http://www.gnu.org/licenses/>.
* */
#include "aaruformat.h"
#include "log.h"
void process_tape_files_block(aaruformat_context *ctx, const IndexEntry *entry)
{
long pos = 0;
size_t read_bytes = 0;
TapeFileHeader tape_file_header = {0};
// Check if the context and image stream are valid
if(ctx == NULL || ctx->imageStream == NULL)
{
FATAL("Invalid context or image stream.");
return;
}
// Seek to block
pos = fseek(ctx->imageStream, entry->offset, SEEK_SET);
if(pos < 0 || ftell(ctx->imageStream) != entry->offset)
{
FATAL("Could not seek to %" PRIu64 " as indicated by index entry...", entry->offset);
return;
}
// Even if those two checks shall have been done before
read_bytes = fread(&tape_file_header, 1, sizeof(TapeFileHeader), ctx->imageStream);
if(read_bytes != sizeof(TapeFileHeader))
{
TRACE("Could not read tape files header, continuing...");
return;
}
if(tape_file_header.identifier != TapeFileBlock)
{
TRACE("Incorrect identifier for data block at position %" PRIu64 "\n", entry->offset);
return;
}
ctx->image_info.ImageSize += sizeof(TapeFileEntry) * tape_file_header.entries;
uint8_t *buffer = malloc(sizeof(TapeFileEntry) * tape_file_header.entries);
if(buffer == NULL)
{
FATAL("Could not allocate memory for tape files block, continuing...");
return;
}
read_bytes = fread(buffer, sizeof(TapeFileEntry), tape_file_header.entries, ctx->imageStream);
if(read_bytes != tape_file_header.entries)
{
free(buffer);
FATAL("Could not read tape files block, continuing...");
return;
}
// Check CRC64
uint64_t crc64 = aaruf_crc64_data(buffer, sizeof(TapeFileEntry) * tape_file_header.entries);
if(crc64 != tape_file_header.crc64)
{
TRACE("Incorrect CRC found: 0x%" PRIx64 " found, expected 0x%" PRIx64 ", continuing...", crc64,
tape_file_header.crc64);
free(buffer);
return;
}
// Insert entries into UTHASH array indexed by partition << 32 | file number
const TapeFileEntry *entries = (TapeFileEntry *)buffer;
for(uint32_t i = 0; i < tape_file_header.entries; i++)
{
// Create hash table entry
tapeFileHashEntry *hash_entry = malloc(sizeof(tapeFileHashEntry));
if(hash_entry == NULL)
{
FATAL("Could not allocate memory for tape file hash entry");
continue;
}
// Create composite key: partition << 32 | file number
hash_entry->key = (uint64_t)entries[i].Partition << 32 | entries[i].File;
// Copy the tape file entry data
hash_entry->fileEntry = entries[i];
// Replace if exists, add if new
tapeFileHashEntry *old_entry = NULL;
HASH_REPLACE(hh, ctx->tape_files, key, sizeof(uint64_t), hash_entry, old_entry);
ctx->dirty_tape_file_block = true; // Mark tape file block as dirty
// Free old entry if it was replaced
if(old_entry != NULL)
{
TRACE("Replaced existing tape file entry for partition %u, file %u", entries[i].Partition, entries[i].File);
free(old_entry);
}
else
TRACE("Added new tape file entry for partition %u, file %u", entries[i].Partition, entries[i].File);
}
free(buffer);
}
void process_tape_partitions_block(aaruformat_context *ctx, const IndexEntry *entry)
{
long pos = 0;
size_t read_bytes = 0;
TapePartitionHeader tape_partition_header = {0};
// Check if the context and image stream are valid
if(ctx == NULL || ctx->imageStream == NULL)
{
FATAL("Invalid context or image stream.");
return;
}
// Seek to block
pos = fseek(ctx->imageStream, entry->offset, SEEK_SET);
if(pos < 0 || ftell(ctx->imageStream) != entry->offset)
{
FATAL("Could not seek to %" PRIu64 " as indicated by index entry...", entry->offset);
return;
}
// Even if those two checks shall have been done before
read_bytes = fread(&tape_partition_header, 1, sizeof(TapePartitionHeader), ctx->imageStream);
if(read_bytes != sizeof(TapePartitionHeader))
{
TRACE("Could not read tape partitions header, continuing...");
return;
}
if(tape_partition_header.identifier != TapePartitionBlock)
{
TRACE("Incorrect identifier for data block at position %" PRIu64 "\n", entry->offset);
return;
}
ctx->image_info.ImageSize += sizeof(TapePartitionEntry) * tape_partition_header.entries;
uint8_t *buffer = malloc(sizeof(TapePartitionEntry) * tape_partition_header.entries);
if(buffer == NULL)
{
FATAL("Could not allocate memory for tape partitions block, continuing...");
return;
}
read_bytes = fread(buffer, sizeof(TapePartitionEntry), tape_partition_header.entries, ctx->imageStream);
if(read_bytes != tape_partition_header.entries)
{
free(buffer);
FATAL("Could not read tape partitions block, continuing...");
return;
}
// Check CRC64
uint64_t crc64 = aaruf_crc64_data(buffer, sizeof(TapePartitionEntry) * tape_partition_header.entries);
if(crc64 != tape_partition_header.crc64)
{
TRACE("Incorrect CRC found: 0x%" PRIx64 " found, expected 0x%" PRIx64 ", continuing...", crc64,
tape_partition_header.crc64);
free(buffer);
return;
}
// Insert entries into UTHASH array indexed by partition
const TapePartitionEntry *entries = (TapePartitionEntry *)buffer;
for(uint32_t i = 0; i < tape_partition_header.entries; i++)
{
// Create hash table entry
TapePartitionHashEntry *hash_entry = malloc(sizeof(TapePartitionHashEntry));
if(hash_entry == NULL)
{
FATAL("Could not allocate memory for tape partition hash entry");
continue;
}
// Create key: partition
hash_entry->key = entries[i].Number;
// Copy the tape partition entry data
hash_entry->partitionEntry = entries[i];
// Replace if exists, add if new
TapePartitionHashEntry *old_entry = NULL;
HASH_REPLACE(hh, ctx->tape_partitions, key, sizeof(uint8_t), hash_entry, old_entry);
ctx->dirty_tape_partition_block = true; // Mark tape partition block as dirty
// Free old entry if it was replaced
if(old_entry != NULL)
{
TRACE("Replaced existing tape partition entry for partition %u", entries[i].Number);
free(old_entry);
}
else
TRACE("Added new tape partition entry for partition %u", entries[i].Number);
}
free(buffer);
}
AARU_EXPORT int32_t AARU_CALL 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 aaruformat_context *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->tape_files, &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;
}
AARU_EXPORT int32_t AARU_CALL aaruf_set_tape_file(void *context, const uint8_t partition, const uint32_t file,
const uint64_t starting_block, const uint64_t ending_block)
{
TRACE("Entering aaruf_set_tape_file(%p, %d, %d, %llu, %llu)", context, partition, file, starting_block,
ending_block);
aaruformat_context *ctx = NULL;
if(context == NULL)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_set_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_set_tape_file() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
// Check we are writing
if(!ctx->is_writing)
{
FATAL("Trying to write a read-only image");
TRACE("Exiting aaruf_set_tape_file() = AARUF_READ_ONLY");
return AARUF_READ_ONLY;
}
// Create hash table entry
tapeFileHashEntry *hash_entry = malloc(sizeof(tapeFileHashEntry));
if(hash_entry == NULL)
{
FATAL("Could not allocate memory for tape file hash entry");
TRACE("Exiting aaruf_set_tape_file() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
return AARUF_ERROR_NOT_ENOUGH_MEMORY;
}
// Create composite key: partition << 32 | file number
hash_entry->key = (uint64_t)partition << 32 | file;
// Copy the tape file entry data
hash_entry->fileEntry.File = file;
hash_entry->fileEntry.Partition = partition;
hash_entry->fileEntry.FirstBlock = starting_block;
hash_entry->fileEntry.LastBlock = ending_block;
// Replace if exists, add if new
tapeFileHashEntry *old_entry = NULL;
HASH_REPLACE(hh, ctx->tape_files, key, sizeof(uint64_t), hash_entry, old_entry);
ctx->dirty_tape_file_block = true; // Mark tape file block as dirty
// Free old entry if it was replaced
if(old_entry != NULL)
{
TRACE("Replaced existing tape file entry for partition %u, file %u", partition, file);
free(old_entry);
}
else
TRACE("Added new tape file entry for partition %u, file %u", partition, file);
TRACE("Exiting aaruf_set_tape_file(%p, %d, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, file,
starting_block, ending_block);
return AARUF_STATUS_OK;
}
AARU_EXPORT int32_t AARU_CALL aaruf_get_tape_partition(const void *context, const uint8_t partition,
uint64_t *starting_block, uint64_t *ending_block)
{
TRACE("Entering aaruf_get_tape_partition(%p, %d, %llu, %llu)", context, partition, *starting_block, *ending_block);
const aaruformat_context *ctx = NULL;
if(context == NULL)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_get_tape_partition() = 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_partition() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
uint8_t key = partition;
TapePartitionHashEntry *entry = NULL;
HASH_FIND(hh, ctx->tape_partitions, &key, sizeof(uint8_t), entry);
if(entry == NULL)
{
TRACE("Tape partition not found");
return AARUF_ERROR_TAPE_PARTITION_NOT_FOUND;
}
*starting_block = entry->partitionEntry.FirstBlock;
*ending_block = entry->partitionEntry.LastBlock;
TRACE("Exiting aaruf_get_tape_partition(%p, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, *starting_block,
*ending_block);
return AARUF_STATUS_OK;
}
AARU_EXPORT int32_t AARU_CALL aaruf_set_tape_partition(void *context, const uint8_t partition,
const uint64_t starting_block, const uint64_t ending_block)
{
TRACE("Entering aaruf_set_tape_partition(%p, %d, %llu, %llu)", context, partition, starting_block, ending_block);
aaruformat_context *ctx = NULL;
if(context == NULL)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_set_tape_partition() = 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_set_tape_partition() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
// Check we are writing
if(!ctx->is_writing)
{
FATAL("Trying to write a read-only image");
TRACE("Exiting aaruf_set_tape_partition() = AARUF_READ_ONLY");
return AARUF_READ_ONLY;
}
// Create hash table entry
TapePartitionHashEntry *hash_entry = malloc(sizeof(TapePartitionHashEntry));
if(hash_entry == NULL)
{
FATAL("Could not allocate memory for tape partition hash entry");
TRACE("Exiting aaruf_set_tape_partition() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
return AARUF_ERROR_NOT_ENOUGH_MEMORY;
}
// Create key: partition
hash_entry->key = partition;
// Copy the tape partition entry data
hash_entry->partitionEntry.Number = partition;
hash_entry->partitionEntry.FirstBlock = starting_block;
hash_entry->partitionEntry.LastBlock = ending_block;
// Replace if exists, add if new
TapePartitionHashEntry *old_entry = NULL;
HASH_REPLACE(hh, ctx->tape_partitions, key, sizeof(uint8_t), hash_entry, old_entry);
ctx->dirty_tape_partition_block = true; // Mark tape partition block as dirty
// Free old entry if it was replaced
if(old_entry != NULL)
{
TRACE("Replaced existing tape partition entry for partition %u", partition);
free(old_entry);
}
else
TRACE("Added new tape partition entry for partition %u", partition);
TRACE("Exiting aaruf_set_tape_partition(%p, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, starting_block,
ending_block);
return AARUF_STATUS_OK;
}
AARU_EXPORT int32_t AARU_CALL aaruf_get_all_tape_files(const void *context, uint8_t *buffer, size_t *length)
{
TRACE("Entering aaruf_get_all_tape_files(%p, %p, %zu)", context, buffer, (length ? *length : 0));
// Check context is correct AaruFormat context
if(context == NULL)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_get_all_tape_files() = 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_all_tape_files() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
if(ctx->tape_files == NULL)
{
FATAL("Image contains no tape files");
TRACE("Exiting aaruf_get_all_tape_files() = AARUF_ERROR_TAPE_FILE_NOT_FOUND");
return AARUF_ERROR_TAPE_FILE_NOT_FOUND;
}
// Iterate all tape files to count how many do we have
const size_t count = HASH_COUNT(ctx->tape_files);
const size_t required_size = count * sizeof(TapeFileEntry);
if(buffer == NULL || length == NULL || *length < required_size)
{
if(length) *length = required_size;
TRACE("Buffer too small for tape files, required %zu bytes", required_size);
TRACE("Exiting aaruf_get_all_tape_files() = AARUF_ERROR_BUFFER_TOO_SMALL");
return AARUF_ERROR_BUFFER_TOO_SMALL;
}
size_t index = 0;
const tapeFileHashEntry *entry;
const tapeFileHashEntry *tmp;
HASH_ITER(hh, ctx->tape_files, entry, tmp)
{
if(index < count)
{
memcpy(&((TapeFileEntry *)buffer)[index], &entry->fileEntry, sizeof(TapeFileEntry));
index++;
}
}
*length = required_size;
TRACE("Exiting aaruf_get_all_tape_files(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
return AARUF_STATUS_OK;
}
AARU_EXPORT int32_t AARU_CALL aaruf_get_all_tape_partitions(const void *context, uint8_t *buffer, size_t *length)
{
TRACE("Entering aaruf_get_all_tape_partitions(%p, %p, %zu)", context, buffer, (length ? *length : 0));
// Check context is correct AaruFormat context
if(context == NULL)
{
FATAL("Invalid context");
TRACE("Exiting aaruf_get_all_tape_partitions() = 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_all_tape_partitions() = AARUF_ERROR_NOT_AARUFORMAT");
return AARUF_ERROR_NOT_AARUFORMAT;
}
if(ctx->tape_partitions == NULL)
{
FATAL("Image contains no tape partitions");
TRACE("Exiting aaruf_get_all_tape_partitions() = AARUF_ERROR_TAPE_PARTITION_NOT_FOUND");
return AARUF_ERROR_TAPE_PARTITION_NOT_FOUND;
}
// Iterate all tape partitions to count how many do we have
const size_t count = HASH_COUNT(ctx->tape_partitions);
const size_t required_size = count * sizeof(TapePartitionEntry);
if(buffer == NULL || length == NULL || *length < required_size)
{
if(length) *length = required_size;
TRACE("Buffer too small for tape partitions, required %zu bytes", required_size);
TRACE("Exiting aaruf_get_all_tape_partitions() = AARUF_ERROR_BUFFER_TOO_SMALL");
return AARUF_ERROR_BUFFER_TOO_SMALL;
}
size_t index = 0;
const TapePartitionHashEntry *entry;
const TapePartitionHashEntry *tmp;
HASH_ITER(hh, ctx->tape_partitions, entry, tmp)
{
if(index < count)
{
memcpy(&((TapePartitionEntry *)buffer)[index], &entry->partitionEntry, sizeof(TapePartitionEntry));
index++;
}
}
*length = required_size;
TRACE("Exiting aaruf_get_all_tape_partitions(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
return AARUF_STATUS_OK;
}
aaruformat.h
AARU_MAGIC
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Definition consts.h:64
tapeFileHashEntry
struct TapeFileHashEntry tapeFileHashEntry
AARU_CALL
#define AARU_CALL
Definition decls.h:46
aaruf_crc64_data
uint64_t aaruf_crc64_data(const uint8_t *data, uint32_t len)
Definition crc64.c:160
AARU_EXPORT
#define AARU_EXPORT
Definition decls.h:55
TapePartitionBlock
@ TapePartitionBlock
Block containing list of partitions for a tape image.
Definition enums.h:162
TapeFileBlock
@ TapeFileBlock
Block containing list of files for a tape image.
Definition enums.h:161
AARUF_ERROR_TAPE_PARTITION_NOT_FOUND
#define AARUF_ERROR_TAPE_PARTITION_NOT_FOUND
Requested tape partition not present in image.
Definition errors.h:68
AARUF_STATUS_OK
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
Definition errors.h:77
AARUF_READ_ONLY
#define AARUF_READ_ONLY
Operation requires write mode but context is read-only.
Definition errors.h:61
AARUF_ERROR_NOT_ENOUGH_MEMORY
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
Definition errors.h:48
AARUF_ERROR_TAPE_FILE_NOT_FOUND
#define AARUF_ERROR_TAPE_FILE_NOT_FOUND
Requested tape file number not present in image.
Definition errors.h:67
AARUF_ERROR_NOT_AARUFORMAT
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
Definition errors.h:40
AARUF_ERROR_BUFFER_TOO_SMALL
#define AARUF_ERROR_BUFFER_TOO_SMALL
Caller-supplied buffer insufficient for data.
Definition errors.h:49
log.h
FATAL
#define FATAL(fmt,...)
Definition log.h:40
TRACE
#define TRACE(fmt,...)
Definition log.h:25
ImageInfo::ImageSize
uint64_t ImageSize
Size of the image payload in bytes (excludes headers/metadata).
Definition aaru.h:935
IndexEntry
Single index entry describing a block's type, (optional) data classification, and file offset.
Definition index.h:109
IndexEntry::offset
uint64_t offset
Absolute byte offset in the image where the referenced block header begins.
Definition index.h:112
TapeFileEntry
Describes a single logical file on a tape medium.
Definition tape.h:134
TapeFileEntry::File
uint32_t File
File number (unique within the partition).
Definition tape.h:135
TapeFileEntry::LastBlock
uint64_t LastBlock
Last block of the file (inclusive).
Definition tape.h:142
TapeFileEntry::FirstBlock
uint64_t FirstBlock
First block of the file (inclusive).
Definition tape.h:139
TapeFileEntry::Partition
uint8_t Partition
Partition number containing this file.
Definition tape.h:137
TapeFileHashEntry::key
uint64_t key
Composite key: partition << 32 | file.
Definition context.h:131
TapeFileHashEntry::fileEntry
TapeFileEntry fileEntry
The actual tape file data.
Definition context.h:132
TapeFileHeader
Header for a tape file metadata block containing file layout information.
Definition tape.h:238
TapeFileHeader::entries
uint32_t entries
Number of file entries following this header.
Definition tape.h:241
TapeFileHeader::identifier
uint32_t identifier
Block type identifier.
Definition tape.h:239
TapeFileHeader::crc64
uint64_t crc64
CRC64-ECMA checksum of the entry data.
Definition tape.h:245
TapePartitionEntry
Describes a single physical partition on a tape medium.
Definition tape.h:320
TapePartitionEntry::LastBlock
uint64_t LastBlock
Last block in the partition (inclusive).
Definition tape.h:325
TapePartitionEntry::FirstBlock
uint64_t FirstBlock
First block in the partition (inclusive).
Definition tape.h:323
TapePartitionEntry::Number
uint8_t Number
Partition number (unique identifier for this partition).
Definition tape.h:321
TapePartitionHashEntry
Definition context.h:137
TapePartitionHashEntry::key
uint8_t key
Key: partition.
Definition context.h:138
TapePartitionHashEntry::partitionEntry
TapePartitionEntry partitionEntry
The actual tape partition data.
Definition context.h:139
TapePartitionHeader
Header for a tape partition metadata block containing partition layout information.
Definition tape.h:441
TapePartitionHeader::crc64
uint64_t crc64
CRC64-ECMA checksum of the entry data.
Definition tape.h:448
TapePartitionHeader::entries
uint8_t entries
Number of partition entries following this header.
Definition tape.h:444
TapePartitionHeader::identifier
uint32_t identifier
Block type identifier.
Definition tape.h:442
aaruformat_context
Master context representing an open or in‑creation Aaru image.
Definition context.h:175
aaruformat_context::tape_files
tapeFileHashEntry * tape_files
Hash table root for tape files.
Definition context.h:306
aaruformat_context::dirty_tape_partition_block
bool dirty_tape_partition_block
True if tape partition block should be written during close.
Definition context.h:333
aaruformat_context::is_writing
bool is_writing
True if context opened/created for writing.
Definition context.h:295
aaruformat_context::magic
uint64_t magic
File magic (AARU_MAGIC) post-open.
Definition context.h:177
aaruformat_context::imageStream
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:179
aaruformat_context::dirty_tape_file_block
bool dirty_tape_file_block
True if tape file block should be written during close.
Definition context.h:332
aaruformat_context::image_info
ImageInfo image_info
Exposed high-level image info summary.
Definition context.h:263
aaruformat_context::tape_partitions
TapePartitionHashEntry * tape_partitions
Hash table root for tape partitions.
Definition context.h:307
aaruf_set_tape_file
int32_t aaruf_set_tape_file(void *context, const uint8_t partition, const uint32_t file, const uint64_t starting_block, const uint64_t ending_block)
Sets or updates the block range for a specific tape file in an Aaru tape image.
Definition tape.c:772
aaruf_get_all_tape_partitions
int32_t aaruf_get_all_tape_partitions(const void *context, uint8_t *buffer, size_t *length)
Retrieves all tape partition entries from the image.
Definition tape.c:1420
aaruf_get_tape_file
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)
Retrieves the block range for a specific tape file from an Aaru tape image.
Definition tape.c:571
process_tape_files_block
void process_tape_files_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a tape file metadata block from the image stream.
Definition tape.c:126
aaruf_get_tape_partition
int32_t aaruf_get_tape_partition(const void *context, const uint8_t partition, uint64_t *starting_block, uint64_t *ending_block)
Retrieves the block range for a specific tape partition from an Aaru tape image.
Definition tape.c:985
aaruf_set_tape_partition
int32_t aaruf_set_tape_partition(void *context, const uint8_t partition, const uint64_t starting_block, const uint64_t ending_block)
Sets or updates the block range for a specific tape partition in an Aaru tape image.
Definition tape.c:1199
process_tape_partitions_block
void process_tape_partitions_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a tape partition metadata block from the image stream.
Definition tape.c:347
aaruf_get_all_tape_files
int32_t aaruf_get_all_tape_files(const void *context, uint8_t *buffer, size_t *length)
Retrieves all tape file entries from the image.
Definition tape.c:1318