Loading...
Searching...
No Matches
create.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 <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aaruformat.h"
#include "enums.h"
#include "internal.h"
#include "log.h"
static void cleanup_failed_create(aaruformat_context *ctx)
{
if(ctx == NULL) return;
if(ctx->sector_hash_map != NULL)
{
free_map(ctx->sector_hash_map);
ctx->sector_hash_map = NULL;
}
if(ctx->index_entries != NULL)
{
utarray_free(ctx->index_entries);
ctx->index_entries = NULL;
}
if(ctx->user_data_ddt2 != NULL)
{
free(ctx->user_data_ddt2);
ctx->user_data_ddt2 = NULL;
}
if(ctx->spamsum_context != NULL)
{
aaruf_spamsum_free(ctx->spamsum_context);
ctx->spamsum_context = NULL;
}
if(ctx->blake3_context != NULL)
{
free(ctx->blake3_context);
ctx->blake3_context = NULL;
}
if(ctx->ecc_cd_context != NULL)
{
free(ctx->ecc_cd_context);
ctx->ecc_cd_context = NULL;
}
if(ctx->readableSectorTags != NULL)
{
free(ctx->readableSectorTags);
ctx->readableSectorTags = NULL;
}
// ApplicationVersion and Version are fixed-size arrays, not pointers - no need to free
if(ctx->imageStream != NULL)
{
fclose(ctx->imageStream);
ctx->imageStream = NULL;
}
free(ctx);
}
AARU_EXPORT void AARU_CALL *aaruf_create(const char *filepath, const uint32_t media_type, const uint32_t sector_size,
const uint64_t user_sectors, const uint64_t negative_sectors,
const uint64_t overflow_sectors, const char *options,
const uint8_t *application_name, const uint8_t application_name_length,
const uint8_t application_major_version,
const uint8_t application_minor_version, const bool is_tape)
{
TRACE("Entering aaruf_create(%s, %u, %u, %llu, %llu, %llu, %s, %s, %u, %u, %u, %d)", filepath, media_type,
sector_size, user_sectors, negative_sectors, overflow_sectors, options,
application_name ? (const char *)application_name : "NULL", application_name_length,
application_major_version, application_minor_version, is_tape);
// Parse the options
TRACE("Parsing options");
bool table_shift_found = false;
const aaru_options parsed_options = parse_options(options, &table_shift_found);
// Allocate context
TRACE("Allocating memory for context");
aaruformat_context *ctx = malloc(sizeof(aaruformat_context));
if(ctx == NULL)
{
FATAL("Not enough memory to create context");
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
TRACE("Exiting aaruf_create() = NULL");
return NULL;
}
memset(ctx, 0, sizeof(aaruformat_context));
// Create the image file
TRACE("Creating image file %s", filepath);
ctx->imageStream = fopen(filepath, "wb+");
if(ctx->imageStream == NULL)
{
FATAL("Error %d opening file %s for writing", errno, filepath);
errno = AARUF_ERROR_CANNOT_CREATE_FILE;
TRACE("Exiting aaruf_create() = NULL");
cleanup_failed_create(ctx);
return NULL;
}
if(application_name_length > AARU_HEADER_APP_NAME_LEN)
{
FATAL("Application name too long (%u bytes, maximum %u bytes)", application_name_length,
AARU_HEADER_APP_NAME_LEN);
errno = AARUF_ERROR_INVALID_APP_NAME_LENGTH;
TRACE("Exiting aaruf_create() = NULL");
cleanup_failed_create(ctx);
return NULL;
}
// Initialize header
TRACE("Initializing header");
ctx->header.identifier = AARU_MAGIC;
memcpy(ctx->header.application, application_name, application_name_length);
ctx->header.imageMajorVersion = AARUF_VERSION_V2;
ctx->header.imageMinorVersion = 0;
ctx->header.applicationMajorVersion = application_major_version;
ctx->header.applicationMinorVersion = application_minor_version;
ctx->header.mediaType = media_type;
ctx->header.indexOffset = 0;
ctx->header.creationTime = get_filetime_uint64();
ctx->header.lastWrittenTime = get_filetime_uint64();
// Generate random GUID for the image
TRACE("Generating random GUID");
generate_random_bytes(ctx->header.guid, GUID_SIZE);
ctx->readableSectorTags = (bool *)malloc(sizeof(bool) * MaxSectorTag);
if(ctx->readableSectorTags == NULL)
{
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
TRACE("Exiting aaruf_create() = NULL");
cleanup_failed_create(ctx);
return NULL;
}
memset(ctx->readableSectorTags, 0, sizeof(bool) * MaxSectorTag);
// Initialize image info
TRACE("Initializing image info");
// Copy application name (UTF-8) to image_info
memset(ctx->image_info.Application, 0, 64);
size_t copy_len = application_name_length < 63 ? application_name_length : 63;
memcpy(ctx->image_info.Application, application_name, copy_len);
ctx->image_info.Application[63] = '\0';
// Set application version string directly in the fixed-size array
memset(ctx->image_info.ApplicationVersion, 0, 32);
sprintf(ctx->image_info.ApplicationVersion, "%d.%d", ctx->header.applicationMajorVersion,
ctx->header.applicationMinorVersion);
// Set image version string directly in the fixed-size array
memset(ctx->image_info.Version, 0, 32);
sprintf(ctx->image_info.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
ctx->image_info.MediaType = ctx->header.mediaType;
ctx->image_info.ImageSize = 0;
ctx->image_info.CreationTime = ctx->header.creationTime;
ctx->image_info.LastModificationTime = ctx->header.lastWrittenTime;
ctx->image_info.MetadataMediaType = aaruf_get_xml_mediatype(ctx->header.mediaType);
ctx->image_info.SectorSize = sector_size;
ctx->image_info.Sectors = user_sectors;
// Initialize caches
TRACE("Initializing caches");
ctx->block_header_cache.cache = NULL;
const uint64_t cache_divisor = (uint64_t)ctx->image_info.SectorSize * (1ULL << ctx->shift);
ctx->block_header_cache.max_items = cache_divisor == 0 ? 0 : MAX_CACHE_SIZE / cache_divisor;
ctx->block_cache.cache = NULL;
ctx->block_cache.max_items = ctx->block_header_cache.max_items;
// TODO: Cache tracks and sessions?
// Initialize ECC for Compact Disc
TRACE("Initializing Compact Disc ECC");
ctx->ecc_cd_context = (CdEccContext *)aaruf_ecc_cd_init();
ctx->magic = AARU_MAGIC;
ctx->library_major_version = LIBAARUFORMAT_MAJOR_VERSION;
ctx->library_minor_version = LIBAARUFORMAT_MINOR_VERSION;
if(!is_tape)
{ // Initialize DDT2
TRACE("Initializing DDT2");
ctx->in_memory_ddt = true;
ctx->user_data_ddt_header.identifier = DeDuplicationTable2;
ctx->user_data_ddt_header.type = UserData;
ctx->user_data_ddt_header.compression = None;
ctx->user_data_ddt_header.tableLevel = 0;
ctx->user_data_ddt_header.previousLevelOffset = 0;
ctx->user_data_ddt_header.negative = negative_sectors;
ctx->user_data_ddt_header.blocks = user_sectors + overflow_sectors + negative_sectors;
ctx->user_data_ddt_header.overflow = overflow_sectors;
ctx->user_data_ddt_header.start = 0;
ctx->user_data_ddt_header.blockAlignmentShift = parsed_options.block_alignment;
ctx->user_data_ddt_header.dataShift = parsed_options.data_shift;
if(parsed_options.table_shift == -1 || !table_shift_found)
{
const uint64_t total_sectors = user_sectors + overflow_sectors + negative_sectors;
if(total_sectors < 8388608ULL)
ctx->user_data_ddt_header.tableShift = 0;
else
ctx->user_data_ddt_header.tableShift = 22;
}
else
ctx->user_data_ddt_header.tableShift =
parsed_options.table_shift > 0 ? (uint8_t)parsed_options.table_shift : 0;
ctx->user_data_ddt_header.levels = ctx->user_data_ddt_header.tableShift > 0 ? 2 : 1;
uint8_t effective_table_shift = ctx->user_data_ddt_header.tableShift;
if(effective_table_shift >= 63)
{
TRACE("Clamping table shift from %u to 62 to avoid overflow", effective_table_shift);
effective_table_shift = 62;
ctx->user_data_ddt_header.tableShift = effective_table_shift;
}
const uint64_t sectors_per_entry = 1ULL << effective_table_shift;
ctx->user_data_ddt_header.entries = ctx->user_data_ddt_header.blocks / sectors_per_entry;
if(ctx->user_data_ddt_header.blocks % sectors_per_entry != 0 || ctx->user_data_ddt_header.entries == 0)
ctx->user_data_ddt_header.entries++;
TRACE("Initializing primary/single DDT");
ctx->user_data_ddt2 =
(uint64_t *)calloc(ctx->user_data_ddt_header.entries, sizeof(uint64_t)); // All entries to zero
if(ctx->user_data_ddt2 == NULL)
{
FATAL("Not enough memory to allocate primary DDT (big)");
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
TRACE("Exiting aaruf_create() = NULL");
cleanup_failed_create(ctx);
return NULL;
}
// Set the primary DDT offset (just after the header, block aligned)
ctx->primary_ddt_offset = sizeof(AaruHeaderV2); // Start just after the header
const uint64_t alignment_mask = (1ULL << ctx->user_data_ddt_header.blockAlignmentShift) - 1;
ctx->primary_ddt_offset = ctx->primary_ddt_offset + alignment_mask & ~alignment_mask;
TRACE("Primary DDT will be placed at offset %" PRIu64, ctx->primary_ddt_offset);
// Calculate size of primary DDT table
const uint64_t primary_table_size = ctx->user_data_ddt_header.entries * sizeof(uint64_t);
// Calculate where data blocks can start (after primary DDT + header)
if(ctx->user_data_ddt_header.tableShift > 0)
{
const uint64_t data_start_position = ctx->primary_ddt_offset + sizeof(DdtHeader2) + primary_table_size;
ctx->next_block_position = data_start_position + alignment_mask & ~alignment_mask;
}
else
ctx->next_block_position = ctx->primary_ddt_offset; // Single-level DDT can start anywhere
}
else
{
// Fill needed values
ctx->user_data_ddt_header.blockAlignmentShift = parsed_options.block_alignment;
ctx->header.blockAlignmentShift = parsed_options.block_alignment;
ctx->user_data_ddt_header.dataShift = parsed_options.data_shift;
// Calculate aligned next block position
const uint64_t alignment_mask = (1ULL << parsed_options.block_alignment) - 1;
ctx->next_block_position = sizeof(AaruHeaderV2); // Start just after the header
ctx->next_block_position = ctx->next_block_position + alignment_mask & ~alignment_mask;
ctx->is_tape = 1;
ctx->tape_ddt = NULL;
}
TRACE("Data blocks will start at position %" PRIu64, ctx->next_block_position);
// Position file pointer at the data start position
if(fseek(ctx->imageStream, ctx->next_block_position, SEEK_SET) != 0)
{
FATAL("Could not seek to data start position");
errno = AARUF_ERROR_CANNOT_CREATE_FILE;
TRACE("Exiting aaruf_create() = NULL");
cleanup_failed_create(ctx);
return NULL;
}
// Initialize index entries array
TRACE("Initializing index entries array");
const UT_icd index_entry_icd = {sizeof(IndexEntry), NULL, NULL, NULL};
utarray_new(ctx->index_entries, &index_entry_icd);
if(ctx->index_entries == NULL)
{
FATAL("Not enough memory to create index entries array");
errno = AARUF_ERROR_NOT_ENOUGH_MEMORY;
TRACE("Exiting aaruf_create() = NULL");
cleanup_failed_create(ctx);
return NULL;
}
ctx->compression_enabled = parsed_options.compress;
ctx->lzma_dict_size = parsed_options.dictionary;
ctx->deduplicate = parsed_options.deduplicate;
if(ctx->deduplicate)
ctx->sector_hash_map = create_map(ctx->user_data_ddt_header.blocks * 25 / 100); // 25% of total sectors
ctx->rewinded = false;
ctx->last_written_block = 0;
if(parsed_options.md5)
{
ctx->calculating_md5 = true;
aaruf_md5_init(&ctx->md5_context);
}
if(parsed_options.sha1)
{
ctx->calculating_sha1 = true;
aaruf_sha1_init(&ctx->sha1_context);
}
if(parsed_options.sha256)
{
ctx->calculating_sha256 = true;
aaruf_sha256_init(&ctx->sha256_context);
}
if(parsed_options.spamsum)
{
ctx->calculating_spamsum = true;
ctx->spamsum_context = aaruf_spamsum_init();
}
if(parsed_options.blake3)
{
ctx->blake3_context = calloc(1, sizeof(blake3_hasher));
if(ctx->blake3_context != NULL)
{
ctx->calculating_blake3 = true;
blake3_hasher_init(ctx->blake3_context);
}
}
// Is writing
ctx->is_writing = true;
// Initialize dirty flags - all true by default for new images
ctx->dirty_secondary_ddt = true;
ctx->dirty_primary_ddt = true;
ctx->dirty_single_level_ddt = true;
ctx->dirty_checksum_block = true;
ctx->dirty_tracks_block = true;
ctx->dirty_mode2_subheaders_block = true;
ctx->dirty_sector_prefix_block = true;
ctx->dirty_sector_prefix_ddt = true;
ctx->dirty_sector_suffix_block = true;
ctx->dirty_sector_suffix_ddt = true;
ctx->dirty_sector_subchannel_block = true;
ctx->dirty_dvd_long_sector_blocks = true;
ctx->dirty_dvd_title_key_decrypted_block = true;
ctx->dirty_media_tags = true;
ctx->dirty_tape_ddt = true;
ctx->dirty_tape_file_block = true;
ctx->dirty_tape_partition_block = true;
ctx->dirty_geometry_block = true;
ctx->dirty_metadata_block = true;
ctx->dirty_dumphw_block = true;
ctx->dirty_cicm_block = true;
ctx->dirty_json_block = true;
ctx->dirty_flux_block = true;
ctx->dirty_index_block = true;
TRACE("Exiting aaruf_create() = %p", ctx);
// Return context
return ctx;
}
aaruformat.h
LIBAARUFORMAT_MAJOR_VERSION
#define LIBAARUFORMAT_MAJOR_VERSION
Definition aaruformat.h:22
LIBAARUFORMAT_MINOR_VERSION
#define LIBAARUFORMAT_MINOR_VERSION
Definition aaruformat.h:23
AARU_MAGIC
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Definition consts.h:64
MAX_CACHE_SIZE
#define MAX_CACHE_SIZE
Maximum read cache size (bytes).
Definition consts.h:79
AARUF_VERSION_V2
#define AARUF_VERSION_V2
Second on‑disk version (C implementation).
Definition consts.h:75
aaruf_create
void * aaruf_create(const char *filepath, const uint32_t media_type, const uint32_t sector_size, const uint64_t user_sectors, const uint64_t negative_sectors, const uint64_t overflow_sectors, const char *options, const uint8_t *application_name, const uint8_t application_name_length, const uint8_t application_major_version, const uint8_t application_minor_version, const bool is_tape)
Creates a new AaruFormat image file.
Definition create.c:279
cleanup_failed_create
static void cleanup_failed_create(aaruformat_context *ctx)
Definition create.c:30
AARU_CALL
#define AARU_CALL
Definition decls.h:46
aaruf_sha256_init
void aaruf_sha256_init(sha256_ctx *ctx)
Definition sha256.c:76
aaruf_md5_init
void aaruf_md5_init(md5_ctx *ctx)
Definition md5.c:436
aaruf_spamsum_free
void aaruf_spamsum_free(spamsum_ctx *ctx)
Frees a spamsum (fuzzy hash) context.
Definition spamsum.c:75
aaruf_spamsum_init
spamsum_ctx * aaruf_spamsum_init(void)
Definition spamsum.c:37
AARU_EXPORT
#define AARU_EXPORT
Definition decls.h:55
aaruf_sha1_init
void aaruf_sha1_init(sha1_ctx *ctx)
Definition sha1.c:34
aaruf_ecc_cd_init
void * aaruf_ecc_cd_init()
Initializes a Compact Disc ECC context.
Definition ecc_cd.c:35
aaruf_get_xml_mediatype
int32_t aaruf_get_xml_mediatype(int32_t type)
Definition helpers.c:351
enums.h
DeDuplicationTable2
@ DeDuplicationTable2
Block containing a deduplication table v2.
Definition enums.h:146
UserData
@ UserData
User (main) data.
Definition enums.h:46
None
@ None
Not compressed.
Definition enums.h:33
AARUF_ERROR_CANNOT_CREATE_FILE
#define AARUF_ERROR_CANNOT_CREATE_FILE
Output file could not be created / opened for write.
Definition errors.h:58
AARUF_ERROR_INVALID_APP_NAME_LENGTH
#define AARUF_ERROR_INVALID_APP_NAME_LENGTH
Application name field length invalid (sanity limit).
Definition errors.h:59
AARUF_ERROR_NOT_ENOUGH_MEMORY
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
Definition errors.h:48
MaxSectorTag
@ MaxSectorTag
Definition aaru.h:980
create_map
hash_map_t * create_map(size_t size)
Creates a new hash map with the specified initial size.
Definition hash_map.c:51
free_map
void free_map(hash_map_t *map)
Frees all memory associated with a hash map.
Definition hash_map.c:78
GUID_SIZE
#define GUID_SIZE
Size in bytes of GUID / UUID-like binary identifier.
Definition header.h:60
AARU_HEADER_APP_NAME_LEN
#define AARU_HEADER_APP_NAME_LEN
Size in bytes (UTF-16LE) of application name field (32 UTF-16 code units).
Definition header.h:59
internal.h
get_filetime_uint64
uint64_t get_filetime_uint64()
Gets the current time as a 64-bit FILETIME value.
Definition time.c:45
generate_random_bytes
void generate_random_bytes(uint8_t *buffer, size_t length)
Generates cryptographically strong random bytes.
Definition helpers.c:484
parse_options
aaru_options parse_options(const char *options, bool *table_shift_found)
Parses the options string for AaruFormat image creation/opening.
Definition options.c:38
log.h
FATAL
#define FATAL(fmt,...)
Definition log.h:40
TRACE
#define TRACE(fmt,...)
Definition log.h:25
AaruHeaderV2
Version 2 container header with GUID, alignment shifts, and feature negotiation bitmaps.
Definition header.h:107
AaruHeaderV2::application
uint8_t application[64]
UTF-8 creator application name (fixed 64 bytes).
Definition header.h:109
AaruHeaderV2::applicationMajorVersion
uint8_t applicationMajorVersion
Creator application major version.
Definition header.h:112
AaruHeaderV2::identifier
uint64_t identifier
File magic (AARU_MAGIC).
Definition header.h:108
AaruHeaderV2::lastWrittenTime
int64_t lastWrittenTime
Last modification FILETIME (100 ns since 1601-01-01 UTC).
Definition header.h:117
AaruHeaderV2::indexOffset
uint64_t indexOffset
Absolute byte offset to primary index block (MUST be > 0; 0 => corrupt/unreadable).
Definition header.h:115
AaruHeaderV2::applicationMinorVersion
uint8_t applicationMinorVersion
Creator application minor / patch version.
Definition header.h:113
AaruHeaderV2::guid
uint8_t guid[16]
128-bit image GUID (binary, not text); stable across children.
Definition header.h:118
AaruHeaderV2::mediaType
uint32_t mediaType
Media type enumeration (value from MediaType).
Definition header.h:114
AaruHeaderV2::blockAlignmentShift
uint8_t blockAlignmentShift
log2 block alignment (block size alignment = 2^blockAlignmentShift bytes).
Definition header.h:119
AaruHeaderV2::imageMinorVersion
uint8_t imageMinorVersion
Container format minor version.
Definition header.h:111
AaruHeaderV2::creationTime
int64_t creationTime
Creation FILETIME (100 ns since 1601-01-01 UTC).
Definition header.h:116
AaruHeaderV2::imageMajorVersion
uint8_t imageMajorVersion
Container format major version.
Definition header.h:110
CacheHeader::cache
struct CacheEntry * cache
Hash root (uthash). NULL when empty.
Definition lru.h:48
CacheHeader::max_items
uint64_t max_items
Hard limit for number of entries (policy: enforce/ignore depends on implementation).
Definition lru.h:47
CdEccContext
Lookup tables and state for Compact Disc EDC/ECC (P/Q) regeneration / verification.
Definition context.h:89
DdtHeader2
Header preceding a version 2 hierarchical deduplication table.
Definition ddt.h:142
DdtHeader2::type
uint16_t type
Data classification (DataType) for sectors referenced by this table.
Definition ddt.h:144
DdtHeader2::start
uint64_t start
Base internal index covered by this table (used for secondary tables; currently informational).
Definition ddt.h:153
DdtHeader2::entries
uint64_t entries
Number of entries contained in (uncompressed) table payload.
Definition ddt.h:158
DdtHeader2::levels
uint8_t levels
Total number of hierarchy levels (root depth); > 0.
Definition ddt.h:146
DdtHeader2::identifier
uint32_t identifier
Block identifier, must be BlockType::DeDuplicationTable2.
Definition ddt.h:143
DdtHeader2::tableShift
uint8_t tableShift
2^tableShift = number of logical sectors per primary entry (multi-level only; 0 for single-level or s...
Definition ddt.h:156
DdtHeader2::blocks
uint64_t blocks
Total internal span (negative + usable + overflow) in logical sectors.
Definition ddt.h:150
DdtHeader2::blockAlignmentShift
uint8_t blockAlignmentShift
2^blockAlignmentShift = block alignment boundary in bytes.
Definition ddt.h:154
DdtHeader2::overflow
uint32_t overflow
Trailing dumped sectors beyond user area (overflow range), still mapped with entries.
Definition ddt.h:151
DdtHeader2::negative
uint32_t negative
Leading negative LBA count; added to external L to build internal index.
Definition ddt.h:149
DdtHeader2::tableLevel
uint8_t tableLevel
Zero-based level index of this table (0 = root, increases downward).
Definition ddt.h:147
DdtHeader2::compression
uint16_t compression
Compression algorithm for this table body (CompressionType).
Definition ddt.h:145
DdtHeader2::dataShift
uint8_t dataShift
2^dataShift = sectors represented per increment in blockIndex field.
Definition ddt.h:155
DdtHeader2::previousLevelOffset
uint64_t previousLevelOffset
Absolute byte offset of the parent (previous) level table; 0 if root.
Definition ddt.h:148
ImageInfo::MediaType
uint32_t MediaType
Media type identifier (see MediaType enum; 0=Unknown).
Definition aaru.h:943
ImageInfo::MetadataMediaType
uint8_t MetadataMediaType
Media type for sidecar generation (internal archival use).
Definition aaru.h:944
ImageInfo::SectorSize
uint32_t SectorSize
Size of each logical sector in bytes (512, 2048, 2352, 4096, etc.).
Definition aaru.h:937
ImageInfo::Application
char Application[64]
Name of application that created the image (NUL-terminated).
Definition aaru.h:939
ImageInfo::ImageSize
uint64_t ImageSize
Size of the image payload in bytes (excludes headers/metadata).
Definition aaru.h:935
ImageInfo::CreationTime
int64_t CreationTime
Image creation timestamp (Windows FILETIME: 100ns since 1601-01-01 UTC).
Definition aaru.h:941
ImageInfo::LastModificationTime
int64_t LastModificationTime
Last modification timestamp (Windows FILETIME format).
Definition aaru.h:942
ImageInfo::Version
char Version[32]
Image format version string (NUL-terminated, e.g., "6.0").
Definition aaru.h:938
ImageInfo::Sectors
uint64_t Sectors
Total count of addressable logical sectors/blocks.
Definition aaru.h:936
ImageInfo::ApplicationVersion
char ApplicationVersion[32]
Version of the creating application (NUL-terminated).
Definition aaru.h:940
IndexEntry
Single index entry describing a block's type, (optional) data classification, and file offset.
Definition index.h:109
aaru_options
Parsed user-specified tunables controlling compression, deduplication, hashing and DDT geometry.
Definition options.h:217
aaru_options::deduplicate
bool deduplicate
Storage dedup flag (DDT always exists).
Definition options.h:219
aaru_options::data_shift
uint8_t data_shift
Global data shift: low bits encode sector offset inside a block (2^data_shift span).
Definition options.h:223
aaru_options::dictionary
uint32_t dictionary
LZMA dictionary size in bytes (>= 4096 recommended). Default: 33554432 (32 MiB).
Definition options.h:221
aaru_options::compress
bool compress
Enable adaptive compression (LZMA for data blocks, FLAC for audio). Default: true.
Definition options.h:218
aaru_options::sha256
bool sha256
Generate SHA-256 checksum (ChecksumAlgorithm::Sha256) when finalizing image.
Definition options.h:227
aaru_options::spamsum
bool spamsum
Generate SpamSum fuzzy hash (ChecksumAlgorithm::SpamSum) if enabled.
Definition options.h:229
aaru_options::table_shift
int8_t table_shift
DDT table shift (multi-level fan-out exponent). Default: heuristically calculated.
Definition options.h:222
aaru_options::md5
bool md5
Generate MD5 checksum (ChecksumAlgorithm::Md5) when finalizing image.
Definition options.h:225
aaru_options::blake3
bool blake3
Generate BLAKE3 checksum if supported (not stored if algorithm unavailable).
Definition options.h:228
aaru_options::sha1
bool sha1
Generate SHA-1 checksum (ChecksumAlgorithm::Sha1) when finalizing image.
Definition options.h:226
aaru_options::block_alignment
uint8_t block_alignment
log2 underlying block alignment (2^n bytes). Default: 9 (512 bytes).
Definition options.h:224
aaruformat_context
Master context representing an open or in‑creation Aaru image.
Definition context.h:175
aaruformat_context::user_data_ddt_header
DdtHeader2 user_data_ddt_header
Active user data DDT v2 header (primary table meta).
Definition context.h:192
aaruformat_context::library_major_version
uint8_t library_major_version
Linked library major version.
Definition context.h:180
aaruformat_context::dirty_checksum_block
bool dirty_checksum_block
True if checksum block should be written during close.
Definition context.h:320
aaruformat_context::deduplicate
bool deduplicate
Storage deduplication active (duplicates coalesce).
Definition context.h:302
aaruformat_context::compression_enabled
bool compression_enabled
True if block compression enabled (writing path).
Definition context.h:303
aaruformat_context::last_written_block
uint64_t last_written_block
Last written block number (write path).
Definition context.h:286
aaruformat_context::dirty_media_tags
bool dirty_media_tags
True if media tags should be written during close.
Definition context.h:330
aaruformat_context::sector_hash_map
hash_map_t * sector_hash_map
Deduplication hash map (fingerprint->entry mapping).
Definition context.h:256
aaruformat_context::sha256_context
sha256_ctx sha256_context
Opaque SHA-256 context for streaming updates.
Definition context.h:275
aaruformat_context::calculating_sha256
bool calculating_sha256
True if whole-image SHA-256 being calculated on-the-fly.
Definition context.h:278
aaruformat_context::dirty_primary_ddt
bool dirty_primary_ddt
True if primary DDT table should be written during close.
Definition context.h:318
aaruformat_context::block_header_cache
struct CacheHeader block_header_cache
LRU/Cache header for block headers.
Definition context.h:259
aaruformat_context::md5_context
md5_ctx md5_context
Opaque MD5 context for streaming updates.
Definition context.h:273
aaruformat_context::dirty_sector_suffix_block
bool dirty_sector_suffix_block
True if sector suffix block should be written during close.
Definition context.h:325
aaruformat_context::user_data_ddt2
uint64_t * user_data_ddt2
DDT entries (big variant) primary/secondary current.
Definition context.h:190
aaruformat_context::shift
uint8_t shift
Legacy overall shift (deprecated by data_shift/table_shift).
Definition context.h:198
aaruformat_context::dirty_dvd_title_key_decrypted_block
bool dirty_dvd_title_key_decrypted_block
True if decrypted title key block should be written during close.
Definition context.h:329
aaruformat_context::dirty_mode2_subheaders_block
bool dirty_mode2_subheaders_block
True if MODE2 subheader block should be written during close.
Definition context.h:322
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::dirty_cicm_block
bool dirty_cicm_block
True if CICM metadata block should be written during close.
Definition context.h:337
aaruformat_context::is_tape
bool is_tape
True if the image is a tape image.
Definition context.h:308
aaruformat_context::calculating_sha1
bool calculating_sha1
True if whole-image SHA-1 being calculated on-the-fly.
Definition context.h:277
aaruformat_context::dirty_tracks_block
bool dirty_tracks_block
True if tracks block should be written during close.
Definition context.h:321
aaruformat_context::ecc_cd_context
CdEccContext * ecc_cd_context
CD ECC/EDC helper tables (allocated on demand).
Definition context.h:251
aaruformat_context::rewinded
bool rewinded
True if stream has been rewound after open (write path).
Definition context.h:296
aaruformat_context::block_cache
struct CacheHeader block_cache
LRU/Cache header for block payloads.
Definition context.h:260
aaruformat_context::dirty_sector_prefix_block
bool dirty_sector_prefix_block
True if sector prefix block should be written during close.
Definition context.h:323
aaruformat_context::in_memory_ddt
bool in_memory_ddt
True if primary (and possibly secondary) DDT loaded.
Definition context.h:199
aaruformat_context::dirty_index_block
bool dirty_index_block
True if index block should be written during close.
Definition context.h:340
aaruformat_context::header
AaruHeaderV2 header
Parsed container header (v2).
Definition context.h:178
aaruformat_context::dirty_json_block
bool dirty_json_block
True if JSON metadata block should be written during close.
Definition context.h:338
aaruformat_context::is_writing
bool is_writing
True if context opened/created for writing.
Definition context.h:295
aaruformat_context::tape_ddt
TapeDdtHashEntry * tape_ddt
Hash table root for tape DDT entries.
Definition context.h:185
aaruformat_context::spamsum_context
spamsum_ctx * spamsum_context
Opaque SpamSum context for streaming updates.
Definition context.h:270
aaruformat_context::dirty_single_level_ddt
bool dirty_single_level_ddt
True if single-level DDT should be written during close.
Definition context.h:319
aaruformat_context::magic
uint64_t magic
File magic (AARU_MAGIC) post-open.
Definition context.h:177
aaruformat_context::calculating_spamsum
bool calculating_spamsum
True if whole-image SpamSum being calculated on-the-fly.
Definition context.h:279
aaruformat_context::primary_ddt_offset
uint64_t primary_ddt_offset
File offset of the primary DDT v2 table.
Definition context.h:195
aaruformat_context::blake3_context
blake3_hasher * blake3_context
Opaque BLAKE3 context for streaming updates.
Definition context.h:271
aaruformat_context::calculating_blake3
bool calculating_blake3
True if whole-image BLAKE3 being calculated on-the-fly.
Definition context.h:280
aaruformat_context::library_minor_version
uint8_t library_minor_version
Linked library minor version;.
Definition context.h:181
aaruformat_context::next_block_position
uint64_t next_block_position
Absolute file offset where next block will be written.
Definition context.h:285
aaruformat_context::calculating_md5
bool calculating_md5
True if whole-image MD5 being calculated on-the-fly.
Definition context.h:276
aaruformat_context::dirty_sector_suffix_ddt
bool dirty_sector_suffix_ddt
True if sector suffix DDT should be written during close.
Definition context.h:326
aaruformat_context::dirty_dumphw_block
bool dirty_dumphw_block
True if dump hardware block should be written during close.
Definition context.h:336
aaruformat_context::dirty_metadata_block
bool dirty_metadata_block
True if metadata block should be written during close.
Definition context.h:335
aaruformat_context::dirty_sector_subchannel_block
bool dirty_sector_subchannel_block
True if subchannel block should be written during close.
Definition context.h:327
aaruformat_context::imageStream
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:179
aaruformat_context::dirty_dvd_long_sector_blocks
bool dirty_dvd_long_sector_blocks
True if DVD long sector blocks should be written during close.
Definition context.h:328
aaruformat_context::dirty_sector_prefix_ddt
bool dirty_sector_prefix_ddt
True if sector prefix DDT should be written during close.
Definition context.h:324
aaruformat_context::index_entries
UT_array * index_entries
Flattened index entries (UT_array of IndexEntry).
Definition context.h:255
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::dirty_flux_block
bool dirty_flux_block
True if flux block should be written during close.
Definition context.h:339
aaruformat_context::sha1_context
sha1_ctx sha1_context
Opaque SHA-1 context for streaming updates.
Definition context.h:274
aaruformat_context::dirty_secondary_ddt
bool dirty_secondary_ddt
True if secondary DDT tables should be written during close.
Definition context.h:317
aaruformat_context::readableSectorTags
bool * readableSectorTags
Per-sector boolean array (optical tags read successfully?).
Definition context.h:266
aaruformat_context::dirty_tape_ddt
bool dirty_tape_ddt
True if tape DDT should be written during close.
Definition context.h:331
aaruformat_context::lzma_dict_size
uint32_t lzma_dict_size
LZMA dictionary size (writing path).
Definition context.h:301
aaruformat_context::dirty_geometry_block
bool dirty_geometry_block
True if geometry block should be written during close.
Definition context.h:334