|
libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
|
#include <errno.h>#include <stdbool.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "aaruformat.h"#include "internal.h"#include "log.h"#include "structs/lisa_tag.h"#include "xxhash.h"Go to the source code of this file.
Functions | |
| int32_t | aaruf_write_sector (void *context, uint64_t sector_address, bool negative, const uint8_t *data, uint8_t sector_status, uint32_t length) |
| Writes a sector to the AaruFormat image. | |
| int32_t | aaruf_write_sector_long (void *context, uint64_t sector_address, bool negative, const uint8_t *data, uint8_t sector_status, uint32_t length) |
| Writes a full ("long") raw sector from optical or block media, parsing structure and validating content. | |
| int32_t | aaruf_close_current_block (aaruformat_context *ctx) |
| Finalizes and writes the current data block to the AaruFormat image file. | |
| int32_t | aaruf_write_media_tag (void *context, const uint8_t *data, const int32_t type, const uint32_t length) |
| Writes a media tag to the AaruFormat image, storing medium-specific metadata and descriptors. | |
| int32_t | aaruf_write_sector_tag (void *context, const uint64_t sector_address, const bool negative, const uint8_t *data, const size_t length, const int32_t tag) |
| Writes per-sector tag data (auxiliary metadata) for a specific sector. | |
| int32_t aaruf_close_current_block | ( | aaruformat_context * | ctx | ) |
Finalizes and writes the current data block to the AaruFormat image file.
This function completes the current writing block by computing checksums, optionally compressing the buffered sector data, writing the block header and data to the image file, updating the index, and cleaning up resources. It is called automatically when a block is full (reaches maximum size determined by dataShift), when sector size changes, or when image finalization begins. The function supports multiple compression algorithms (FLAC for audio, LZMA for data) with automatic fallback to uncompressed storage if compression is ineffective.
Block Finalization Sequence:
Compression Handling:
Index Entry Creation:
Each closed block is registered in the index with:
This enables efficient block lookup during image reading via binary search on index entries.
File Layout:
Written to ctx->imageStream at ctx->nextBlockPosition:
Next Block Position Calculation:
After writing, nextBlockPosition is updated to the next aligned boundary:
This ensures all blocks begin on properly aligned file offsets for efficient I/O.
Resource Cleanup:
Before returning, the function:
This prepares the context for the next block or signals that no block is currently open.
| ctx | Pointer to an initialized aaruformatContext in write mode. |
| AARUF_STATUS_OK | (0) Successfully finalized and wrote the block. This is returned when:
|
| AARUF_ERROR_NOT_AARUFORMAT | (-1) The context is invalid. This occurs when:
|
| AARUF_READ_ONLY | (-22) Attempting to finalize block on read-only image. This occurs when:
|
| AARUF_ERROR_NOT_ENOUGH_MEMORY | (-9) Memory allocation failed. This occurs when:
|
| AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER | (-23) Failed to write block header. This occurs when:
|
| AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA | (-24) Failed to write block data. This occurs when:
|
Definition at line 1403 of file write.c.
References AARU_MAGIC, aaruf_crc64_data(), aaruf_crc64_final(), aaruf_crc64_free(), aaruf_crc64_init(), aaruf_crc64_update(), AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA, AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER, AARUF_ERROR_NOT_AARUFORMAT, AARUF_ERROR_NOT_ENOUGH_MEMORY, aaruf_flac_encode_redbook_buffer(), aaruf_lzma_encode_buffer(), AARUF_READ_ONLY, AARUF_STATUS_OK, DdtHeader2::blockAlignmentShift, IndexEntry::blockType, BlockHeader::cmpCrc64, BlockHeader::cmpLength, BlockHeader::compression, BlockHeader::crc64, aaruformat_context::crc64_context, aaruformat_context::current_block_header, aaruformat_context::current_block_offset, DataBlock, IndexEntry::dataType, FATAL, Flac, aaruformat_context::imageStream, aaruformat_context::index_entries, aaruformat_context::is_writing, BlockHeader::length, Lzma, aaruformat_context::lzma_dict_size, LZMA_PROPERTIES_LENGTH, aaruformat_context::magic, MAX_FLAKE_BLOCK, MIN_FLAKE_BLOCK, aaruformat_context::next_block_position, None, IndexEntry::offset, SAMPLES_PER_SECTOR, BlockHeader::sectorSize, TRACE, aaruformat_context::user_data_ddt_header, UserData, aaruformat_context::writing_buffer, and aaruformat_context::writing_buffer_position.
Referenced by aaruf_close(), aaruf_write_sector(), and set_ddt_multi_level_v2().
| int32_t aaruf_write_media_tag | ( | void * | context, |
| const uint8_t * | data, | ||
| const int32_t | type, | ||
| const uint32_t | length ) |
Writes a media tag to the AaruFormat image, storing medium-specific metadata and descriptors.
This function stores arbitrary media-specific metadata (media tags) in the AaruFormat image context for later serialization during image finalization. Media tags represent higher-level descriptors and metadata structures that characterize the storage medium beyond sector data, including disc information structures, lead-in/lead-out data, manufacturer identifiers, drive capabilities, and format-specific metadata. The function uses a hash table for efficient tag storage and retrieval, automatically replacing existing tags of the same type and managing memory for tag data.
Supported Media Tag Categories:
Optical Disc Metadata (CD/DVD/BD/HD DVD):
Recordable Media Structures:
Copy Protection and Security:
Device and Drive Information:
Flash and Solid-State Media:
Gaming Console Media:
Specialized Structures:
Data Processing Pipeline:
Memory Management Strategy:
Tag Type Identification: The type parameter accepts MediaTagType enumeration values (0-68) that identify the semantic meaning of the tag data. The library does not validate tag data structure or size against the type identifier - callers are responsible for providing correctly formatted tag data matching the declared type. Type values are preserved as-is and used during serialization to identify tag purpose during image reading.
Replacement Behavior: When a media tag of the same type already exists in the context:
Serialization and Persistence: Media tags written via this function are not immediately written to the image file. Instead, they are accumulated in the context's mediaTags hash table and serialized during aaruf_close() as part of the image finalization process. The serialization creates a metadata block in the image file that preserves all media tags with their type identifiers and data lengths.
Thread Safety and Concurrency: This function is NOT thread-safe. The context contains mutable shared state including:
Performance Considerations:
Typical Usage Scenarios:
Validation and Error Handling:
Data Format Requirements: The function accepts arbitrary binary data without format validation. Callers must ensure:
Integration with Image Creation Workflow: Media tags should typically be written after creating the image context (aaruf_create()) but before writing sector data. However, tags can be added or updated at any point during the writing process. Common workflow:
| context | Pointer to a valid aaruformatContext with magic == AARU_MAGIC opened for writing. Must be created via aaruf_create() and not yet closed. The context's isWriting flag must be true, indicating write mode is active. |
| data | Pointer to the media tag data buffer to write. Must be a valid non-NULL pointer to a buffer containing the complete tag data. The function performs a deep copy of this data, so the caller retains ownership and may free or modify the source buffer after this call returns. The data format must match the structure expected for the specified type parameter. |
| type | Integer identifier specifying the type of media tag (MediaTagType enumeration). Values range from 0 (CD_TOC) to 68 (CD_LeadIn). The type identifies the semantic meaning of the tag data and is preserved in the image file for interpretation during reading. The library does not validate that the data structure matches the declared type - caller responsibility to ensure correctness. |
| length | Length in bytes of the media tag data buffer. Must be greater than zero. Specifies how many bytes to copy from the data buffer. No maximum length enforced, but extremely large tags may cause memory allocation failures. |
| AARUF_STATUS_OK | (0) Successfully wrote the media tag. This is returned when:
|
| AARUF_ERROR_NOT_AARUFORMAT | (-1) Invalid context provided. This occurs when:
|
| AARUF_READ_ONLY | (-22) Attempting to write to read-only image. This occurs when:
|
| AARUF_ERROR_INCORRECT_DATA_SIZE | (-26) Invalid data or length parameters. This occurs when:
|
| AARUF_ERROR_NOT_ENOUGH_MEMORY | (-9) Memory allocation failed. This occurs when:
|
Definition at line 1800 of file write.c.
References AARU_CALL, AARU_EXPORT, AARU_MAGIC, AARUF_ERROR_INCORRECT_DATA_SIZE, AARUF_ERROR_NOT_AARUFORMAT, AARUF_ERROR_NOT_ENOUGH_MEMORY, AARUF_READ_ONLY, AARUF_STATUS_OK, mediaTagEntry::data, FATAL, aaruformat_context::is_writing, mediaTagEntry::length, aaruformat_context::magic, aaruformat_context::mediaTags, TRACE, and mediaTagEntry::type.
| int32_t aaruf_write_sector | ( | void * | context, |
| uint64_t | sector_address, | ||
| bool | negative, | ||
| const uint8_t * | data, | ||
| uint8_t | sector_status, | ||
| uint32_t | length ) |
Writes a sector to the AaruFormat image.
Writes the given data to the specified sector address in the image, with the given status and length. This function handles buffering data into blocks, automatically closing blocks when necessary (sector size changes or block size limits are reached), and managing the deduplication table (DDT) entries.
| context | Pointer to the aaruformat context. |
| sector_address | Logical sector address to write. |
| negative | Indicates if the sector address is negative. |
| data | Pointer to the data buffer to write. |
| sector_status | Status of the sector to write. |
| length | Length of the data buffer. |
| AARUF_STATUS_OK | (0) Successfully wrote the sector data. This is returned when:
|
| AARUF_ERROR_NOT_AARUFORMAT | (-1) The context is invalid. This occurs when:
|
| AARUF_READ_ONLY | (-22) Attempting to write to a read-only image. This occurs when:
|
| AARUF_ERROR_NOT_ENOUGH_MEMORY | (-9) Memory allocation failed. This occurs when:
|
| AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER | (-23) Failed to write block header to the image file. This can occur during automatic block closure when:
|
| AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA | (-24) Failed to write block data to the image file. This can occur during automatic block closure when:
|
| AARUF_ERROR_CANNOT_SET_DDT_ENTRY | (-25) Failed to update the deduplication table (DDT) entry. This occurs when:
|
Definition at line 98 of file write.c.
References AARU_CALL, AARU_EXPORT, AARU_MAGIC, aaruf_close_current_block(), AARUF_ERROR_CANNOT_SET_DDT_ENTRY, AARUF_ERROR_NOT_AARUFORMAT, AARUF_ERROR_NOT_ENOUGH_MEMORY, AARUF_ERROR_SECTOR_OUT_OF_BOUNDS, aaruf_md5_update(), AARUF_READ_ONLY, aaruf_sha1_update(), aaruf_sha256_update(), aaruf_spamsum_update(), AARUF_STATUS_OK, Audio, aaruformat_context::blake3_context, aaruformat_context::block_zero_written, aaruformat_context::calculating_blake3, aaruformat_context::calculating_md5, aaruformat_context::calculating_sha1, aaruformat_context::calculating_sha256, aaruformat_context::calculating_spamsum, BlockHeader::compression, aaruformat_context::compression_enabled, aaruformat_context::current_block_header, aaruformat_context::current_block_offset, aaruformat_context::current_track_type, Data, DataBlock, DdtHeader2::dataShift, aaruformat_context::deduplicate, TrackEntry::end, TracksHeader::entries, FATAL, Flac, BlockHeader::identifier, aaruformat_context::image_info, insert_map(), aaruformat_context::is_writing, JaguarCD, aaruformat_context::last_written_block, lookup_map(), Lzma, aaruformat_context::magic, aaruformat_context::md5_context, ImageInfo::MediaType, ImageInfo::MetadataMediaType, DdtHeader2::negative, aaruformat_context::next_block_position, None, OpticalDisc, DdtHeader2::overflow, aaruformat_context::rewinded, aaruformat_context::sector_hash_map, ImageInfo::Sectors, BlockHeader::sectorSize, TrackEntry::sequence, TrackEntry::session, set_ddt_entry_v2(), aaruformat_context::sha1_context, aaruformat_context::sha256_context, aaruformat_context::spamsum_context, TrackEntry::start, TRACE, aaruformat_context::track_entries, aaruformat_context::tracks_header, BlockHeader::type, TrackEntry::type, aaruformat_context::user_data_ddt_header, UserData, VideoNow, VideoNowColor, VideoNowXp, aaruformat_context::writing_buffer, aaruformat_context::writing_buffer_position, and aaruformat_context::writing_long.
Referenced by aaruf_write_sector_long().
| int32_t aaruf_write_sector_long | ( | void * | context, |
| uint64_t | sector_address, | ||
| bool | negative, | ||
| const uint8_t * | data, | ||
| uint8_t | sector_status, | ||
| uint32_t | length ) |
Writes a full ("long") raw sector from optical or block media, parsing structure and validating content.
This function processes complete raw sectors including structural metadata, error correction codes, and subchannel information. It is the primary entry point for ingesting raw sector data where the caller provides the complete sector including synchronization patterns, headers, user data, and error correction information. The function intelligently parses the sector structure based on media type and track information, validates correctness, and delegates user data writing to aaruf_write_sector().
Supported Media Types and Sector Formats:
Optical Disc Media (2352-byte sectors):
Block Media (512+ byte sectors with tags):
Data Processing Pipeline:
Memory Management Strategy:
Address Space Management: The function handles three logical address regions:
Sector Status Classification: Status codes stored in high nibble of mini-DDT entries:
Deduplication Integration: Long sector processing does not directly perform deduplication - this occurs in the delegated aaruf_write_sector() call for the extracted user data portion. The prefix/suffix/subheader metadata is stored separately and not subject to deduplication.
Hash Calculation Behavior:
Error Recovery and Validation:
Thread Safety and Concurrency: This function is NOT thread-safe. The context contains mutable shared state including:
Performance Considerations:
| context | Pointer to a valid aaruformatContext with magic == AARU_MAGIC opened for writing. |
| sector_address | Logical Block Address (LBA) for the sector. For negative regions, this is the negative-space address; for user/overflow regions, this is the standard 0-based LBA. |
| negative | true if sector_address refers to the negative (pre-gap) region; false for user or overflow regions. |
| data | Pointer to the complete raw sector buffer. Must contain:
|
| sector_status | Initial sector status hint from caller. May be overridden based on validation results when delegating to aaruf_write_sector(). |
| length | Length in bytes of the data buffer. Must be exactly 2352 for optical discs. For block media: 512 (no tags), 524 (Sony), 532 (Profile), or 536 (Priam). |
| AARUF_STATUS_OK | (0) Sector successfully processed and user data written. This occurs when:
|
| AARUF_ERROR_NOT_AARUFORMAT | (-1) Invalid context provided. This occurs when:
|
| AARUF_READ_ONLY | (-22) Attempting to write to read-only image. This occurs when:
|
| AARUF_ERROR_SECTOR_OUT_OF_BOUNDS | (-5) Sector address outside valid ranges. This occurs when:
|
| AARUF_ERROR_INCORRECT_DATA_SIZE | (-26) Invalid sector size for media type. This occurs when:
|
| AARUF_ERROR_NOT_ENOUGH_MEMORY | (-9) Memory allocation failed. This occurs when:
|
| AARUF_ERROR_INCORRECT_MEDIA_TYPE | (-12) Unsupported media type for long sectors. This occurs when:
|
| AARUF_ERROR_CANNOT_SET_DDT_ENTRY | (-25) DDT update failed. Propagated from aaruf_write_sector() when:
|
| AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER | (-23) Block header write failed. Propagated from aaruf_write_sector() when:
|
| AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA | (-24) Block data write failed. Propagated from aaruf_write_sector() when:
|
Definition at line 537 of file write.c.
References AARU_CALL, AARU_EXPORT, AARU_MAGIC, aaruf_ecc_cd_is_suffix_correct(), aaruf_ecc_cd_is_suffix_correct_mode2(), aaruf_edc_cd_compute(), AARUF_ERROR_INCORRECT_DATA_SIZE, AARUF_ERROR_INCORRECT_MEDIA_TYPE, AARUF_ERROR_NOT_AARUFORMAT, AARUF_ERROR_NOT_ENOUGH_MEMORY, AARUF_ERROR_SECTOR_OUT_OF_BOUNDS, aaruf_md5_update(), AARUF_READ_ONLY, aaruf_sha1_update(), aaruf_sha256_update(), aaruf_spamsum_update(), aaruf_write_sector(), AppleFileWare, AppleProfile, AppleSonyDS, AppleSonySS, AppleWidget, Audio, aaruformat_context::blake3_context, aaruformat_context::block_zero_written, BlockMedia, bytes_to_priam_tag(), bytes_to_profile_tag(), bytes_to_sony_tag(), aaruformat_context::calculating_blake3, aaruformat_context::calculating_md5, aaruformat_context::calculating_sha1, aaruformat_context::calculating_sha256, aaruformat_context::calculating_spamsum, CdMode1, CdMode2Form1, CdMode2Form2, CdMode2Formless, Data, DVDDownload, DVDPR, DVDPRDL, DVDPRW, DVDPRWDL, DVDR, DVDRAM, DVDRDL, DVDROM, DVDRW, DVDRWDL, aaruformat_context::ecc_cd_context, TrackEntry::end, TracksHeader::entries, FATAL, aaruformat_context::image_info, aaruformat_context::is_writing, aaruformat_context::last_written_block, aaruformat_context::magic, aaruformat_context::md5_context, ImageInfo::MediaType, ImageInfo::MetadataMediaType, aaruformat_context::mode2_subheaders, DdtHeader2::negative, Nuon, OpticalDisc, DdtHeader2::overflow, priam_tag_to_bytes(), priam_tag_to_profile(), priam_tag_to_sony(), PriamDataTower, profile_tag_to_bytes(), profile_tag_to_priam(), profile_tag_to_sony(), PS2DVD, PS3DVD, aaruformat_context::rewinded, SACD, aaruformat_context::sector_cpr_mai, aaruformat_context::sector_edc, aaruformat_context::sector_id, aaruformat_context::sector_ied, aaruformat_context::sector_prefix, aaruformat_context::sector_prefix_ddt2, aaruformat_context::sector_prefix_length, aaruformat_context::sector_prefix_offset, aaruformat_context::sector_subchannel, aaruformat_context::sector_suffix, aaruformat_context::sector_suffix_ddt2, aaruformat_context::sector_suffix_length, aaruformat_context::sector_suffix_offset, ImageInfo::Sectors, SectorStatusErrored, SectorStatusMode1Correct, SectorStatusMode2Form1Ok, SectorStatusMode2Form2NoCrc, SectorStatusMode2Form2Ok, SectorStatusNotDumped, TrackEntry::sequence, aaruformat_context::sha1_context, aaruformat_context::sha256_context, sony_tag_to_bytes(), sony_tag_to_priam(), sony_tag_to_profile(), aaruformat_context::spamsum_context, TrackEntry::start, TRACE, aaruformat_context::track_entries, aaruformat_context::tracks_header, TrackEntry::type, aaruformat_context::user_data_ddt_header, and aaruformat_context::writing_long.
| int32_t aaruf_write_sector_tag | ( | void * | context, |
| const uint64_t | sector_address, | ||
| const bool | negative, | ||
| const uint8_t * | data, | ||
| const size_t | length, | ||
| const int32_t | tag ) |
Writes per-sector tag data (auxiliary metadata) for a specific sector.
This function stores auxiliary metadata associated with individual sectors, such as CD subchannel data, DVD auxiliary fields, track metadata, or proprietary tag formats used by specific storage systems. Unlike media tags (which apply to the entire medium), sector tags are per-sector metadata that provide additional context, error correction, copy protection, or device-specific information for each individual sector.
The function validates the tag type against the media type, verifies the data size matches the expected length for that tag type, allocates buffers as needed, and stores the tag data at the appropriate offset within the tag buffer. Some tags (like track flags and ISRC) update track metadata rather than per-sector buffers.
Supported tag types and their characteristics:
Optical Disc (CD/DVD) Tags:
Block Media (Proprietary Format) Tags:
Sector addressing: The function supports both positive and negative sector addressing:
Buffer allocation: Tag buffers are allocated on-demand when the first tag of a given type is written. Buffers are sized to accommodate all sectors (negative + normal + overflow) and persist for the lifetime of the context. Memory is freed during aaruf_close().
| context | Pointer to the aaruformat context (must be a valid, write-enabled image context). |
| sector_address | The logical sector number to write the tag for. Must be within valid bounds for the image (0 to Sectors-1 for positive, 0 to negative-1 when using negative addressing). |
| negative | If true, sector_address refers to a negative (lead-in) sector; if false, it refers to a positive sector (main data or overflow area). |
| data | Pointer to the tag data to write. Must not be NULL. The data size must exactly match the expected size for the tag type. |
| length | Length of the tag data in bytes. Must match the required size for the tag type. |
| tag | Tag type identifier (from the tag enumeration). Determines which buffer to write to and the expected data size. |
| AARUF_STATUS_OK | (0) Successfully wrote sector tag. This is returned when:
|
| AARUF_ERROR_NOT_AARUFORMAT | (-1) The context is invalid. This occurs when:
|
| AARUF_READ_ONLY | (-13) The context is not opened for writing. This occurs when:
|
| AARUF_ERROR_SECTOR_OUT_OF_BOUNDS | (-5) Sector address is invalid. This occurs when:
|
| AARUF_ERROR_INCORRECT_DATA_SIZE | (-26) Invalid data or length. This occurs when:
|
| AARUF_ERROR_INCORRECT_MEDIA_TYPE | (-12) Invalid media type for tag. This occurs when:
|
| AARUF_ERROR_NOT_ENOUGH_MEMORY | (-9) Memory allocation failed. This occurs when:
|
| AARUF_ERROR_TRACK_NOT_FOUND | (-13) Track not found for sector. This occurs when:
|
| AARUF_ERROR_INVALID_TAG | (-27) Unsupported or unknown tag type. This occurs when:
|
Definition at line 2069 of file write.c.
References AARU_CALL, AARU_EXPORT, AARU_MAGIC, AARUF_ERROR_INCORRECT_DATA_SIZE, AARUF_ERROR_INCORRECT_MEDIA_TYPE, AARUF_ERROR_INVALID_TAG, AARUF_ERROR_NOT_AARUFORMAT, AARUF_ERROR_NOT_ENOUGH_MEMORY, AARUF_ERROR_SECTOR_OUT_OF_BOUNDS, AARUF_ERROR_TRACK_NOT_FOUND, AARUF_READ_ONLY, AARUF_STATUS_OK, AppleProfileTagAaru, AppleSonyTagAaru, BlockMedia, CdSectorSubchannelAaru, CdTrackFlags, CdTrackIsrc, DvdCmi, DvdSectorEdcAaru, DvdSectorIedAaru, DvdSectorInformation, DvdSectorNumber, DvdTitleKeyDecrypted, TracksHeader::entries, FATAL, TrackEntry::flags, aaruformat_context::image_info, aaruformat_context::is_writing, TrackEntry::isrc, aaruformat_context::magic, ImageInfo::MetadataMediaType, DdtHeader2::negative, OpticalDisc, DdtHeader2::overflow, PriamDataTowerTagAaru, aaruformat_context::sector_cpr_mai, aaruformat_context::sector_decrypted_title_key, aaruformat_context::sector_edc, aaruformat_context::sector_id, aaruformat_context::sector_ied, aaruformat_context::sector_subchannel, ImageInfo::Sectors, TrackEntry::start, TRACE, aaruformat_context::track_entries, aaruformat_context::tracks_header, and aaruformat_context::user_data_ddt_header.