57 if(element == NULL)
return;
91 HASH_ITER(hh, ctx->
flux_map, entry, tmp)
131 if(entry == NULL)
return -1;
136 entry->
index = index;
185 FATAL(
"Could not add flux capture to lookup map");
311 size_t read_bytes = 0;
317 FATAL(
"Invalid context or image stream.");
341 FATAL(
"Could not seek to %" PRIu64
" as indicated by index entry...\n", entry->
offset);
351 TRACE(
"Could not read flux data header, continuing...\n");
358 TRACE(
"Incorrect identifier for flux data block at position %" PRIu64
"\n", entry->
offset);
369 FATAL(
"Could not allocate memory for flux data block, continuing...\n");
380 FATAL(
"Could not read flux data block, continuing...\n");
388 TRACE(
"Incorrect CRC found: 0x%" PRIx64
" found, expected 0x%" PRIx64
", continuing...\n", crc64,
425 for(
unsigned int i = 0; i < utarray_len(ctx->
index_entries); i++)
485 TRACE(
"Entering aaruf_get_flux_captures(%p, %p, %zu)", context, buffer, (length ? *length : 0));
490 FATAL(
"Invalid context");
499 FATAL(
"Invalid context");
507 TRACE(
"Exiting aaruf_get_flux_captures() = %d", res);
513 FATAL(
"Image contains no flux captures");
514 TRACE(
"Exiting aaruf_get_flux_captures() = AARUF_ERROR_FLUX_DATA_NOT_FOUND");
522 TRACE(
"Buffer too small for flux captures, required %zu bytes", required_length);
523 TRACE(
"Exiting aaruf_get_flux_captures() = AARUF_ERROR_BUFFER_TOO_SMALL");
527 if(buffer == NULL || *length < required_length)
529 *length = required_length;
530 TRACE(
"Buffer too small for flux captures, required %zu bytes", required_length);
531 TRACE(
"Exiting aaruf_get_flux_captures() = AARUF_ERROR_BUFFER_TOO_SMALL");
547 *length = required_length;
549 TRACE(
"Exiting aaruf_get_flux_captures(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
603 uint32_t capture_index, uint64_t data_resolution,
604 uint64_t index_resolution,
const uint8_t *data,
605 uint32_t data_length,
const uint8_t *index,
606 uint32_t index_length)
608 TRACE(
"Entering aaruf_add_flux_capture(%p, %u, %u, %u, %u, %" PRIu64
", %" PRIu64
", %p, %u, %p, %u)", context,
609 head, track, subtrack, capture_index, data_resolution, index_resolution, data, data_length, index,
614 FATAL(
"Invalid context");
622 FATAL(
"Invalid context");
628 FATAL(
"Flux captures can only be added when writing");
632 if((index_length != 0 && index == NULL) || (data_length != 0 && data == NULL))
634 FATAL(
"Invalid flux capture buffers");
638 if((uint64_t)data_length + index_length > UINT32_MAX)
640 FATAL(
"Flux capture too large (%" PRIu64
" bytes)", (uint64_t)data_length + index_length);
649 FATAL(
"Could not allocate flux capture storage");
655 if(existing_captures >= UINT16_MAX)
657 FATAL(
"Flux capture limit exceeded (%zu >= %u)", existing_captures, UINT16_MAX);
661 uint8_t *data_copy = NULL;
662 uint8_t *index_copy = NULL;
666 data_copy = malloc(data_length);
667 if(data_copy == NULL)
669 FATAL(
"Could not allocate %u bytes for flux data", data_length);
672 memcpy(data_copy, data, data_length);
675 if(index_length != 0)
677 index_copy = malloc(index_length);
678 if(index_copy == NULL)
681 FATAL(
"Could not allocate %u bytes for flux index", index_length);
684 memcpy(index_copy, index, index_length);
702 if(new_entries == NULL)
706 FATAL(
"Could not grow flux entry array");
721 if(
flux_map_add(ctx, &key, (uint32_t)existing_captures) != 0)
723 FATAL(
"Could not add flux capture to lookup map");
728 if(existing_captures == 0)
778 TRACE(
"Entering aaruf_clear_flux_captures(%p)", context);
782 FATAL(
"Invalid context");
790 FATAL(
"Invalid context");
807 TRACE(
"Exiting aaruf_clear_flux_captures() = AARUF_STATUS_OK");
856 FATAL(
"Could not seek to flux payload at offset %" PRIu64, payload_offset);
857 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
862 if(file_position < 0 || (uint64_t)file_position != payload_offset)
864 FATAL(
"Invalid flux payload position (expected %" PRIu64
", got %ld)", payload_offset, file_position);
865 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
872 FATAL(
"Could not read flux payload header at offset %" PRIu64, payload_offset);
873 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
879 FATAL(
"Incorrect identifier 0x%08" PRIx32
" for flux payload at offset %" PRIu64, header->
identifier,
881 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
887 FATAL(
"Incorrect data type %u for flux payload at offset %" PRIu64
" (expected FluxData)", header->
dataType,
889 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
908 uint8_t **cmp_buffer, uint8_t **payload)
910 if(cmp_length != raw_length)
912 FATAL(
"Flux payload lengths mismatch for uncompressed block (cmp=%zu, raw=%zu)", cmp_length, raw_length);
913 TRACE(
"Exiting read_uncompressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
924 *cmp_buffer = (uint8_t *)malloc(cmp_length);
925 if(*cmp_buffer == NULL)
927 FATAL(
"Could not allocate %zu bytes for flux payload", cmp_length);
928 TRACE(
"Exiting read_uncompressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
932 size_t read_bytes = fread(*cmp_buffer, 1, cmp_length, ctx->
imageStream);
933 if(read_bytes != cmp_length)
935 FATAL(
"Could not read %zu bytes of flux payload", cmp_length);
938 TRACE(
"Exiting read_uncompressed_payload() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
942 *payload = *cmp_buffer;
959 uint8_t **cmp_buffer, uint8_t **payload)
963 FATAL(
"Flux payload compressed length %zu too small for LZMA", cmp_length);
964 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
968 *cmp_buffer = (uint8_t *)malloc(cmp_length);
969 if(*cmp_buffer == NULL)
971 FATAL(
"Could not allocate %zu bytes for flux payload", cmp_length);
972 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
976 size_t read_bytes = fread(*cmp_buffer, 1, cmp_length, ctx->
imageStream);
977 if(read_bytes != cmp_length)
979 FATAL(
"Could not read %zu bytes of flux payload", cmp_length);
982 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
992 *payload = (uint8_t *)malloc(raw_length);
995 FATAL(
"Could not allocate %zu bytes for decompressed flux payload", raw_length);
998 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
1003 size_t dst_len = raw_length;
1004 size_t src_len = cmp_stream_len;
1005 const uint8_t *cmp_props = *cmp_buffer;
1009 if(error_no != 0 || dst_len != raw_length)
1011 FATAL(
"LZMA decompression failed for flux payload (err=%d, dst=%zu/%zu)", error_no, dst_len, raw_length);
1016 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
1035 uint8_t **cmp_buffer, uint8_t **payload)
1039 FATAL(
"Flux payload compressed length is zero for zstd");
1040 TRACE(
"Exiting read_zstd_compressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
1044 *cmp_buffer = (uint8_t *)malloc(cmp_length);
1045 if(*cmp_buffer == NULL)
1047 FATAL(
"Could not allocate %zu bytes for flux payload", cmp_length);
1048 TRACE(
"Exiting read_zstd_compressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
1052 size_t read_bytes = fread(*cmp_buffer, 1, cmp_length, ctx->
imageStream);
1053 if(read_bytes != cmp_length)
1055 FATAL(
"Could not read %zu bytes of flux payload", cmp_length);
1058 TRACE(
"Exiting read_zstd_compressed_payload() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
1068 *payload = (uint8_t *)malloc(raw_length);
1069 if(*payload == NULL)
1071 FATAL(
"Could not allocate %zu bytes for decompressed flux payload", raw_length);
1074 TRACE(
"Exiting read_zstd_compressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
1079 if(dst_len != raw_length)
1081 FATAL(
"Zstd decompression failed for flux payload (dst=%zu/%zu)", dst_len, raw_length);
1086 TRACE(
"Exiting read_zstd_compressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
1106 size_t raw_length, uint64_t expected_cmp_crc, uint64_t expected_raw_crc)
1108 uint64_t cmp_crc = 0;
1109 if(cmp_length != 0 && cmp_buffer != NULL) cmp_crc =
aaruf_crc64_data(cmp_buffer, cmp_length);
1111 if(cmp_crc != expected_cmp_crc)
1113 FATAL(
"Flux payload compressed CRC mismatch (expected 0x%" PRIx64
", got 0x%" PRIx64
")", expected_cmp_crc,
1115 TRACE(
"Exiting validate_flux_payload_crcs() = AARUF_ERROR_INVALID_BLOCK_CRC\n");
1119 uint64_t raw_crc = 0;
1120 if(raw_length != 0 && payload != NULL) raw_crc =
aaruf_crc64_data(payload, raw_length);
1122 if(raw_crc != expected_raw_crc)
1124 FATAL(
"Flux payload raw CRC mismatch (expected 0x%" PRIx64
", got 0x%" PRIx64
")", expected_raw_crc, raw_crc);
1125 TRACE(
"Exiting validate_flux_payload_crcs() = AARUF_ERROR_INVALID_BLOCK_CRC\n");
1146 uint8_t *data_data, uint32_t *data_length, uint8_t *index_data,
1147 uint32_t *index_length)
1151 FATAL(
"Flux index offset %" PRIu64
" beyond payload length %zu", flux_entry->
indexOffset, raw_length);
1152 TRACE(
"Exiting extract_flux_data_buffers() = AARUF_ERROR_INVALID_BLOCK_CRC\n");
1156 uint64_t data_length_required64 = flux_entry->
indexOffset;
1157 uint64_t index_length_required64 = raw_length - flux_entry->
indexOffset;
1159 if(data_length_required64 > UINT32_MAX || index_length_required64 > UINT32_MAX)
1161 FATAL(
"Flux payload section length exceeds 32-bit limits (data=%" PRIu64
", index=%" PRIu64
")",
1162 data_length_required64, index_length_required64);
1163 TRACE(
"Exiting extract_flux_data_buffers() = AARUF_ERROR_INCORRECT_DATA_SIZE\n");
1167 uint32_t data_required = (uint32_t)data_length_required64;
1168 uint32_t index_required = (uint32_t)index_length_required64;
1170 uint32_t data_capacity = *data_length;
1171 uint32_t index_capacity = *index_length;
1173 *data_length = data_required;
1174 *index_length = index_required;
1176 if(data_data == NULL || index_data == NULL || data_capacity < data_required || index_capacity < index_required)
1178 TRACE(
"Returning required flux capture sizes (data=%u, index=%u)\n", data_required, index_required);
1182 const uint8_t *index_ptr = payload ? payload + data_length_required64 : NULL;
1183 const uint8_t *data_ptr = payload;
1185 if(data_required != 0 && data_ptr != NULL) memcpy(data_data, data_ptr, data_required);
1186 if(index_required != 0 && index_ptr != NULL) memcpy(index_data, index_ptr, index_required);
1259 uint32_t capture_index, uint8_t *index_data,
1260 uint32_t *index_length, uint8_t *data_data, uint32_t *data_length)
1262 TRACE(
"Entering aaruf_read_flux_capture(%p, %u, %u, %u, %u, %p, %p, %p, %p)", context, head, track, subtrack,
1263 capture_index, index_data, index_length, data_data, data_length);
1267 FATAL(
"Invalid context");
1268 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_NOT_AARUFORMAT");
1276 FATAL(
"Invalid context");
1277 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_NOT_AARUFORMAT");
1285 TRACE(
"Exiting aaruf_read_flux_capture() = %d", load_res);
1291 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_FLUX_DATA_NOT_FOUND");
1295 if(index_length == NULL || data_length == NULL)
1297 FATAL(
"index_length or data_length pointers are NULL");
1298 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_BUFFER_TOO_SMALL\n");
1304 FATAL(
"Invalid image stream");
1305 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_NOT_AARUFORMAT\n");
1311 if(flux_entry == NULL)
1313 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_FLUX_DATA_NOT_FOUND\n");
1317 TRACE(
"Requested flux capture: head=%u track=%u subtrack=%u captureIndex=%u payloadOffset=%" PRIu64
"\n",
1326 uint64_t absolute_payload_offset = flux_entry->
payloadOffset << block_alignment_shift;
1332 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1337 uint8_t *cmp_buffer = NULL;
1338 uint8_t *payload = NULL;
1339 size_t cmp_length = payload_header.
cmpLength;
1340 size_t raw_length = payload_header.
length;
1356 FATAL(
"Unsupported flux payload compression type %u", payload_header.
compression);
1357 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_UNSUPPORTED_COMPRESSION\n");
1363 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1368 payload_header.
crc64);
1371 if(payload != NULL && payload != cmp_buffer) free(payload);
1372 if(cmp_buffer != NULL) free(cmp_buffer);
1373 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1380 if(payload != NULL && payload != cmp_buffer) free(payload);
1381 if(cmp_buffer != NULL) free(cmp_buffer);
1382 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1386 if(payload != NULL && payload != cmp_buffer) free(payload);
1387 if(cmp_buffer != NULL) free(cmp_buffer);
1389 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_STATUS_OK\n");
Core public constants and compile‑time limits for the Aaru container format implementation.
#define LZMA_PROPERTIES_LENGTH
Size in bytes of the fixed LZMA properties header (lc/lp/pb + dictionary size).
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Central runtime context structures for libaaruformat (image state, caches, checksum buffers).
uint64_t aaruf_crc64_data(const uint8_t *data, uint32_t len)
int32_t aaruf_lzma_decode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer, size_t *src_size, const uint8_t *props, size_t props_size)
Decodes an LZMA-compressed buffer.
size_t aaruf_zstd_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size)
Decodes a Zstandard-compressed buffer.
@ FluxDataBlock
Block containing flux data metadata.
@ DataStreamPayloadBlock
Block containing compressed data stream payload (e.g., flux data, bitstreams).
@ kDataTypeFluxData
Flux data.
CompressionType
List of known compression types.
@ kCompressionLzma
LZMA compression.
@ kCompressionNone
Not compressed.
@ kCompressionZstd
Zstandard compression.
Public error and status code definitions for libaaruformat.
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
#define AARUF_READ_ONLY
Operation requires write mode but context is read-only.
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
#define AARUF_ERROR_CANNOT_READ_BLOCK
Generic block read failure (seek/read error).
#define AARUF_ERROR_INCORRECT_DATA_SIZE
Data size does not match expected size.
#define AARUF_ERROR_INVALID_BLOCK_CRC
CRC64 mismatch indicating corruption.
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
#define AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK
Decompression routine failed or size mismatch.
#define AARUF_ERROR_FLUX_DATA_NOT_FOUND
Requested flux data not present in image.
#define AARUF_ERROR_BUFFER_TOO_SMALL
Caller-supplied buffer insufficient for data.
#define AARUF_ERROR_UNSUPPORTED_COMPRESSION
Block marked with unsupported compression algorithm.
static int32_t validate_flux_payload_crcs(const uint8_t *cmp_buffer, size_t cmp_length, const uint8_t *payload, size_t raw_length, uint64_t expected_cmp_crc, uint64_t expected_raw_crc)
Validate CRC64 checksums for a flux payload block.
static const FluxEntry * find_flux_entry_by_key(const aaruformat_context *ctx, const FluxCaptureKey *key)
Find a flux entry by its identifier key.
static int32_t read_zstd_compressed_payload(const aaruformat_context *ctx, size_t cmp_length, size_t raw_length, uint8_t **cmp_buffer, uint8_t **payload)
Read and decompress a Zstandard-compressed flux payload.
static int32_t extract_flux_data_buffers(const FluxEntry *flux_entry, const uint8_t *payload, size_t raw_length, uint8_t *data_data, uint32_t *data_length, uint8_t *index_data, uint32_t *index_length)
Extract data and index buffers from decompressed payload and copy to output buffers.
static int flux_map_add(aaruformat_context *ctx, const FluxCaptureKey *key, uint32_t index)
Add or update a flux capture entry in the lookup map.
int32_t aaruf_clear_flux_captures(void *context)
Clear all flux captures from the context.
int32_t aaruf_read_flux_capture(void *context, uint32_t head, uint16_t track, uint8_t subtrack, uint32_t capture_index, uint8_t *index_data, uint32_t *index_length, uint8_t *data_data, uint32_t *data_length)
Read a specific flux capture's data and index buffers from the image.
static void flux_capture_record_dtor(void *element)
Destructor callback for FluxCaptureRecord elements in a utarray.
int32_t aaruf_get_flux_captures(void *context, uint8_t *buffer, size_t *length)
Retrieve metadata for all flux captures in the image.
static void flux_map_clear(aaruformat_context *ctx)
Clear and deallocate the flux capture lookup map.
static int32_t read_lzma_compressed_payload(const aaruformat_context *ctx, size_t cmp_length, size_t raw_length, uint8_t **cmp_buffer, uint8_t **payload)
Read and decompress an LZMA-compressed flux payload from the image stream.
static int32_t ensure_flux_entries_loaded(aaruformat_context *ctx)
Lazy load flux data block if not already loaded.
static int32_t read_uncompressed_payload(const aaruformat_context *ctx, size_t cmp_length, size_t raw_length, uint8_t **cmp_buffer, uint8_t **payload)
Read an uncompressed flux payload from the image stream.
void process_flux_data_block(aaruformat_context *ctx, const IndexEntry *entry)
Parse and integrate a Flux Data block from the image stream into the context.
static int32_t read_flux_payload_header(const aaruformat_context *ctx, uint64_t payload_offset, DataStreamPayloadHeader *header)
Read and validate a flux payload block header from the image stream.
int32_t aaruf_write_flux_capture(void *context, uint32_t head, uint16_t track, uint8_t subtrack, uint32_t capture_index, uint64_t data_resolution, uint64_t index_resolution, const uint8_t *data, uint32_t data_length, const uint8_t *index, uint32_t index_length)
Add a flux capture to the image during write mode.
int32_t flux_map_rebuild_from_entries(aaruformat_context *ctx)
Rebuild the flux capture lookup map from the flux_entries array.
static const UT_icd FLUX_CAPTURE_RECORD_ICD
On‑disk index block header and entry structures (versions 1, 2 and 3).
static int aaruf_fseek(FILE *stream, aaru_off_t offset, int origin)
static aaru_off_t aaruf_ftell(FILE *stream)
Key structure for flux capture lookup map.
uint16_t track
Track number identifying the capture location.
uint8_t subtrack
Subtrack number identifying the capture location.
uint32_t head
Head number identifying the capture location.
uint32_t captureIndex
Capture index, allowing multiple captures for the same location.
Internal hash table entry for flux capture lookup.
Internal structure for storing flux capture data during write mode.
FluxEntry entry
Flux entry metadata describing this capture.
uint32_t data_length
Length of the data buffer in bytes.
uint32_t index_length
Length of the index buffer in bytes.
uint8_t * index_buffer
Pointer to the flux index buffer. Owned by the utarray, freed automatically.
uint8_t * data_buffer
Pointer to the flux data buffer. Owned by the utarray, freed automatically.
Metadata entry describing a single flux capture in the FluxDataBlock.
uint64_t indexResolution
Resolution in picoseconds at which the index stream was sampled.
uint64_t dataResolution
Resolution in picoseconds at which the data stream was sampled.
uint32_t head
Head number the flux capture corresponds to. Typically 0 or 1 for double-sided media.
uint64_t payloadOffset
Block-aligned file offset where the DataStreamPayloadBlock containing this capture's data is stored,...
uint16_t track
Track number the flux capture corresponds to. Track numbering is format-dependent.
uint64_t indexOffset
Byte offset within the payload where the index buffer starts (equals data_length).
uint8_t subtrack
Subtrack number, allowing sub-stepping within a track. Used for fine positioning.
uint32_t captureIndex
Capture index, allowing multiple captures for the same location (e.g., multiple revolutions).
uint64_t ImageSize
Size of the image payload in bytes (excludes headers/metadata).
Single index entry describing a block's type, (optional) data classification, and file offset.
uint32_t blockType
Block identifier of the referenced block (value from BlockType).
uint64_t offset
Absolute byte offset in the image where the referenced block header begins.
Master context representing an open or in‑creation Aaru image.
FluxHeader flux_data_header
Flux data header (if present).
UT_array * flux_captures
Pending flux capture payloads (write path).
FluxCaptureMapEntry * flux_map
Hash map for flux capture lookup by head/track/subtrack/capture index.
FluxEntry * flux_entries
Array of flux entries (flux_data_header.entries elements).
bool is_writing
True if context opened/created for writing.
uint64_t magic
File magic (AARU_MAGIC) post-open.
FILE * imageStream
Underlying FILE* stream (binary mode).
UT_array * index_entries
Flattened index entries (UT_array of IndexEntry).
ImageInfo image_info
Exposed high-level image info summary.
bool dirty_flux_block
True if flux block should be written during close.