56 if(element == NULL)
return;
90 HASH_ITER(hh, ctx->
flux_map, entry, tmp)
130 if(entry == NULL)
return -1;
135 entry->
index = index;
184 FATAL(
"Could not add flux capture to lookup map");
310 size_t read_bytes = 0;
316 FATAL(
"Invalid context or image stream.");
340 FATAL(
"Could not seek to %" PRIu64
" as indicated by index entry...\n", entry->
offset);
350 TRACE(
"Could not read flux data header, continuing...\n");
357 TRACE(
"Incorrect identifier for flux data block at position %" PRIu64
"\n", entry->
offset);
368 FATAL(
"Could not allocate memory for flux data block, continuing...\n");
379 FATAL(
"Could not read flux data block, continuing...\n");
387 TRACE(
"Incorrect CRC found: 0x%" PRIx64
" found, expected 0x%" PRIx64
", continuing...\n", crc64,
430 for(
unsigned int i = 0; i < utarray_len(ctx->
index_entries); i++)
499 TRACE(
"Entering aaruf_get_flux_captures(%p, %p, %zu)", context, buffer, (length ? *length : 0));
504 FATAL(
"Invalid context");
513 FATAL(
"Invalid context");
521 TRACE(
"Exiting aaruf_get_flux_captures() = %d", res);
527 FATAL(
"Image contains no flux captures");
528 TRACE(
"Exiting aaruf_get_flux_captures() = AARUF_ERROR_FLUX_DATA_NOT_FOUND");
536 TRACE(
"Buffer too small for flux captures, required %zu bytes", required_length);
537 TRACE(
"Exiting aaruf_get_flux_captures() = AARUF_ERROR_BUFFER_TOO_SMALL");
541 if(buffer == NULL || *length < required_length)
543 *length = required_length;
544 TRACE(
"Buffer too small for flux captures, required %zu bytes", required_length);
545 TRACE(
"Exiting aaruf_get_flux_captures() = AARUF_ERROR_BUFFER_TOO_SMALL");
561 *length = required_length;
563 TRACE(
"Exiting aaruf_get_flux_captures(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
617 uint32_t capture_index, uint64_t data_resolution,
618 uint64_t index_resolution,
const uint8_t *data,
619 uint32_t data_length,
const uint8_t *index,
620 uint32_t index_length)
622 TRACE(
"Entering aaruf_add_flux_capture(%p, %u, %u, %u, %u, %" PRIu64
", %" PRIu64
", %p, %u, %p, %u)", context,
623 head, track, subtrack, capture_index, data_resolution, index_resolution, data, data_length, index,
628 FATAL(
"Invalid context");
636 FATAL(
"Invalid context");
642 FATAL(
"Flux captures can only be added when writing");
646 if((index_length != 0 && index == NULL) || (data_length != 0 && data == NULL))
648 FATAL(
"Invalid flux capture buffers");
652 if((uint64_t)data_length + index_length > UINT32_MAX)
654 FATAL(
"Flux capture too large (%" PRIu64
" bytes)", (uint64_t)data_length + index_length);
663 FATAL(
"Could not allocate flux capture storage");
669 if(existing_captures >= UINT16_MAX)
671 FATAL(
"Flux capture limit exceeded (%zu >= %u)", existing_captures, UINT16_MAX);
675 uint8_t *data_copy = NULL;
676 uint8_t *index_copy = NULL;
680 data_copy = malloc(data_length);
681 if(data_copy == NULL)
683 FATAL(
"Could not allocate %u bytes for flux data", data_length);
686 memcpy(data_copy, data, data_length);
689 if(index_length != 0)
691 index_copy = malloc(index_length);
692 if(index_copy == NULL)
695 FATAL(
"Could not allocate %u bytes for flux index", index_length);
698 memcpy(index_copy, index, index_length);
716 if(new_entries == NULL)
720 FATAL(
"Could not grow flux entry array");
735 if(
flux_map_add(ctx, &key, (uint32_t)existing_captures) != 0)
737 FATAL(
"Could not add flux capture to lookup map");
742 if(existing_captures == 0)
792 TRACE(
"Entering aaruf_clear_flux_captures(%p)", context);
796 FATAL(
"Invalid context");
804 FATAL(
"Invalid context");
821 TRACE(
"Exiting aaruf_clear_flux_captures() = AARUF_STATUS_OK");
868 if(fseek(ctx->
imageStream, payload_offset, SEEK_SET) < 0)
870 FATAL(
"Could not seek to flux payload at offset %" PRIu64, payload_offset);
871 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
876 if(file_position < 0 || (uint64_t)file_position != payload_offset)
878 FATAL(
"Invalid flux payload position (expected %" PRIu64
", got %ld)", payload_offset, file_position);
879 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
886 FATAL(
"Could not read flux payload header at offset %" PRIu64, payload_offset);
887 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
893 FATAL(
"Incorrect identifier 0x%08" PRIx32
" for flux payload at offset %" PRIu64, header->
identifier,
895 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
901 FATAL(
"Incorrect data type %u for flux payload at offset %" PRIu64
" (expected FluxData)", header->
dataType,
903 TRACE(
"Exiting read_flux_payload_header() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
922 uint8_t **cmp_buffer, uint8_t **payload)
924 if(cmp_length != raw_length)
926 FATAL(
"Flux payload lengths mismatch for uncompressed block (cmp=%zu, raw=%zu)", cmp_length, raw_length);
927 TRACE(
"Exiting read_uncompressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
938 *cmp_buffer = (uint8_t *)malloc(cmp_length);
939 if(*cmp_buffer == NULL)
941 FATAL(
"Could not allocate %zu bytes for flux payload", cmp_length);
942 TRACE(
"Exiting read_uncompressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
946 size_t read_bytes = fread(*cmp_buffer, 1, cmp_length, ctx->
imageStream);
947 if(read_bytes != cmp_length)
949 FATAL(
"Could not read %zu bytes of flux payload", cmp_length);
952 TRACE(
"Exiting read_uncompressed_payload() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
956 *payload = *cmp_buffer;
972 uint8_t **cmp_buffer, uint8_t **payload)
976 FATAL(
"Flux payload compressed length %zu too small for LZMA", cmp_length);
977 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
981 *cmp_buffer = (uint8_t *)malloc(cmp_length);
982 if(*cmp_buffer == NULL)
984 FATAL(
"Could not allocate %zu bytes for flux payload", cmp_length);
985 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
989 size_t read_bytes = fread(*cmp_buffer, 1, cmp_length, ctx->
imageStream);
990 if(read_bytes != cmp_length)
992 FATAL(
"Could not read %zu bytes of flux payload", cmp_length);
995 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_CANNOT_READ_BLOCK\n");
1005 *payload = (uint8_t *)malloc(raw_length);
1006 if(*payload == NULL)
1008 FATAL(
"Could not allocate %zu bytes for decompressed flux payload", raw_length);
1011 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_NOT_ENOUGH_MEMORY\n");
1016 size_t dst_len = raw_length;
1017 size_t src_len = cmp_stream_len;
1018 const uint8_t *cmp_props = *cmp_buffer;
1022 if(error_no != 0 || dst_len != raw_length)
1024 FATAL(
"LZMA decompression failed for flux payload (err=%d, dst=%zu/%zu)", error_no, dst_len, raw_length);
1029 TRACE(
"Exiting read_lzma_compressed_payload() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK\n");
1049 size_t raw_length, uint64_t expected_cmp_crc, uint64_t expected_raw_crc)
1051 uint64_t cmp_crc = 0;
1052 if(cmp_length != 0 && cmp_buffer != NULL) cmp_crc =
aaruf_crc64_data(cmp_buffer, cmp_length);
1054 if(cmp_crc != expected_cmp_crc)
1056 FATAL(
"Flux payload compressed CRC mismatch (expected 0x%" PRIx64
", got 0x%" PRIx64
")", expected_cmp_crc,
1058 TRACE(
"Exiting validate_flux_payload_crcs() = AARUF_ERROR_INVALID_BLOCK_CRC\n");
1062 uint64_t raw_crc = 0;
1063 if(raw_length != 0 && payload != NULL) raw_crc =
aaruf_crc64_data(payload, raw_length);
1065 if(raw_crc != expected_raw_crc)
1067 FATAL(
"Flux payload raw CRC mismatch (expected 0x%" PRIx64
", got 0x%" PRIx64
")", expected_raw_crc, raw_crc);
1068 TRACE(
"Exiting validate_flux_payload_crcs() = AARUF_ERROR_INVALID_BLOCK_CRC\n");
1089 uint8_t *data_data, uint32_t *data_length, uint8_t *index_data,
1090 uint32_t *index_length)
1094 FATAL(
"Flux index offset %" PRIu64
" beyond payload length %zu", flux_entry->
indexOffset, raw_length);
1095 TRACE(
"Exiting extract_flux_data_buffers() = AARUF_ERROR_INVALID_BLOCK_CRC\n");
1099 uint64_t data_length_required64 = flux_entry->
indexOffset;
1100 uint64_t index_length_required64 = raw_length - flux_entry->
indexOffset;
1102 if(data_length_required64 > UINT32_MAX || index_length_required64 > UINT32_MAX)
1104 FATAL(
"Flux payload section length exceeds 32-bit limits (data=%" PRIu64
", index=%" PRIu64
")",
1105 data_length_required64, index_length_required64);
1106 TRACE(
"Exiting extract_flux_data_buffers() = AARUF_ERROR_INCORRECT_DATA_SIZE\n");
1110 uint32_t data_required = (uint32_t)data_length_required64;
1111 uint32_t index_required = (uint32_t)index_length_required64;
1113 uint32_t data_capacity = *data_length;
1114 uint32_t index_capacity = *index_length;
1116 *data_length = data_required;
1117 *index_length = index_required;
1119 if(data_data == NULL || index_data == NULL || data_capacity < data_required || index_capacity < index_required)
1121 TRACE(
"Returning required flux capture sizes (data=%u, index=%u)\n", data_required, index_required);
1125 const uint8_t *index_ptr = payload ? payload + data_length_required64 : NULL;
1126 const uint8_t *data_ptr = payload;
1128 if(data_required != 0 && data_ptr != NULL) memcpy(data_data, data_ptr, data_required);
1129 if(index_required != 0 && index_ptr != NULL) memcpy(index_data, index_ptr, index_required);
1202 uint32_t capture_index, uint8_t *index_data,
1203 uint32_t *index_length, uint8_t *data_data, uint32_t *data_length)
1205 TRACE(
"Entering aaruf_read_flux_capture(%p, %u, %u, %u, %u, %p, %p, %p, %p)", context, head, track, subtrack,
1206 capture_index, index_data, index_length, data_data, data_length);
1210 FATAL(
"Invalid context");
1211 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_NOT_AARUFORMAT");
1219 FATAL(
"Invalid context");
1220 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_NOT_AARUFORMAT");
1228 TRACE(
"Exiting aaruf_read_flux_capture() = %d", load_res);
1234 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_FLUX_DATA_NOT_FOUND");
1238 if(index_length == NULL || data_length == NULL)
1240 FATAL(
"index_length or data_length pointers are NULL");
1241 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_BUFFER_TOO_SMALL\n");
1247 FATAL(
"Invalid image stream");
1248 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_NOT_AARUFORMAT\n");
1254 if(flux_entry == NULL)
1256 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_FLUX_DATA_NOT_FOUND\n");
1260 TRACE(
"Requested flux capture: head=%u track=%u subtrack=%u captureIndex=%u payloadOffset=%" PRIu64
"\n",
1269 uint64_t absolute_payload_offset = flux_entry->
payloadOffset << block_alignment_shift;
1275 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1280 uint8_t *cmp_buffer = NULL;
1281 uint8_t *payload = NULL;
1282 size_t cmp_length = payload_header.
cmpLength;
1283 size_t raw_length = payload_header.
length;
1285 if(compression ==
None)
1289 else if(compression ==
Lzma)
1295 FATAL(
"Unsupported flux payload compression type %u", payload_header.
compression);
1296 TRACE(
"Exiting aaruf_read_flux_capture() = AARUF_ERROR_UNSUPPORTED_COMPRESSION\n");
1302 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1307 payload_header.
crc64);
1310 if(payload != NULL && payload != cmp_buffer) free(payload);
1311 if(cmp_buffer != NULL) free(cmp_buffer);
1312 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1320 if(payload != NULL && payload != cmp_buffer) free(payload);
1321 if(cmp_buffer != NULL) free(cmp_buffer);
1322 TRACE(
"Exiting aaruf_read_flux_capture() = %d\n", res);
1326 if(payload != NULL && payload != cmp_buffer) free(payload);
1327 if(cmp_buffer != NULL) free(cmp_buffer);
1329 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.
@ FluxDataBlock
Block containing flux data metadata.
@ DataStreamPayloadBlock
Block containing compressed data stream payload (e.g., flux data, bitstreams).
CompressionType
List of known compression types.
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 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).
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.