libaaruformat 1.0 Aaru Data Preservation Suite - Format Library

Loading...
Searching...
No Matches
create.c File Reference
`#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"`

Go to the source code of this file.

## Functions
static void | cleanup_failed_create (aaruformat_context *ctx)
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.

## Function Documentation

## ◆ 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.

Allocates and initializes a new aaruformat context and image file with the specified parameters. This function sets up all necessary data structures including headers, DDT (deduplication table), caches, and index entries for writing a new AaruFormat image. It also handles file creation, memory allocation, and proper initialization of the writing context. The function supports both block-based media (disks, optical media) and sequential tape media with different initialization strategies optimized for each media type.

Media Type Handling: The function creates different internal structures based on the is_tape parameter:

Block Media (is_tape = false):

- Initializes full DDT (Deduplication Table) version 2 for sector-level deduplication
- Allocates primary DDT table (userDataDdtMini or userDataDdtBig) as a preallocated array
- Configures multi-level DDT support for large images (> 138,412,552 sectors)
- Enables optional deduplication hash map for detecting duplicate sectors
- Reserves space for DDT at the beginning of the file (after header, block-aligned)
- Data blocks start after DDT table to maintain sequential layout
- DDT size is fixed and known upfront based on sector count

Tape Media (is_tape = true):

- Initializes DDT for sector-level deduplication using a different strategy
- Uses a growing hash table (tapeDdt) instead of a preallocated array
- Sets ctx->is_tape flag and initializes ctx->tapeDdt to NULL (populated on first write)
- Data blocks start immediately after the header (block-aligned)
- Hash table grows dynamically as blocks are written
- Optimized for sequential write patterns typical of tape media
- Tape file/partition metadata is managed separately via additional hash tables
- More memory-efficient for tapes with unknown final size

Initialization Flow:

1. Parse creation options (compression, alignment, deduplication, checksums)
2. Allocate and zero-initialize context structure
3. Create/open image file in binary write mode
4. Initialize AaruFormat header with application and version information
5. Set up image metadata and sector size information
6. Initialize block and header caches for performance
7. Initialize ECC context for Compact Disc support
8. Branch based on media type:
   - Block media: Configure DDT structures and calculate offsets with preallocated array
   - Tape media: Set tape flags and initialize for dynamic hash table DDT
9. Initialize index entries array for tracking all blocks
10. Configure compression, checksums, and deduplication based on options
11. Position file pointer at calculated data start position

DDT Configuration (Block Media Only): The function automatically selects optimal DDT parameters:

- Single-level DDT (tableShift=0): For images < 138,412,552 sectors
- Multi-level DDT (tableShift=22): For images ≥ 138,412,552 sectors

The DDT offset calculation ensures proper alignment:

- Primary DDT placed immediately after header (block-aligned)
- Data blocks positioned after DDT table (block-aligned)
- Alignment controlled by blockAlignmentShift from options

Parameters

  filepath | Path to the image file to create. The file will be created if it doesn't exist, or overwritten if it does. Must be a valid writable path.
  media_type | Media type identifier (e.g., CompactDisc, DVD, HardDisk, Tape formats). This affects how the image is structured and which features are enabled.
  sector_size | Size of each sector/block in bytes. Common values: 512 bytes: Hard disks, floppy disks 2048 bytes: CD-ROM, DVD Variable: Tape media (block size varies by format)
  user_sectors | Number of user data sectors/blocks in the image. This is the main data area excluding negative (lead-in) and overflow (lead-out) regions. For tape media, this may be an estimate as the final size is often unknown.
  negative_sectors | Number of negative sectors (typically lead-in area for optical media). Set to 0 for media types without lead-in areas. Not used for tape media.
  overflow_sectors | Number of overflow sectors (typically lead-out area for optical media). Set to 0 for media types without lead-out areas. Not used for tape media.
  options | String with creation options in key=value format, semicolon-separated. Supported options: "compress=true|false": Enable/disable LZMA compression "deduplicate=true|false": Enable/disable sector deduplication (all media types) "md5=true|false": Calculate MD5 checksum during write "sha1=true|false": Calculate SHA-1 checksum during write "sha256=true|false": Calculate SHA-256 checksum during write "spamsum=true|false": Calculate SpamSum fuzzy hash during write "blake3=true|false": Calculate BLAKE3 checksum during write "block_alignment=N": Block alignment shift value (default varies) "data_shift=N": Data shift value for DDT granularity "table_shift=N": Table shift for multi-level DDT (-1 for auto, block media only) "dictionary=N": LZMA dictionary size in bytes Example: "compress=true;deduplicate=true;md5=true;sha1=true"
  application_name | Pointer to the application name string (UTF-8 encoded). This identifies the software that created the image. The string will be copied directly to the image header.
  application_name_length | Length of the application name string in bytes. Must be ≤ AARU_HEADER_APP_NAME_LEN (64 bytes).
  application_major_version | Major version of the creating application (0-255).
  application_minor_version | Minor version of the creating application (0-255).
  is_tape | Boolean flag indicating tape media type: true: Initialize for tape media (sequential, dynamic hash table DDT, file/partition metadata) false: Initialize for block media (random access, preallocated array DDT)

Returns
  Returns one of the following:

Return values

  aaruformatContext* | Successfully created and initialized context. The returned pointer contains: Properly initialized AaruFormat headers and metadata For block media: Allocated and configured DDT structures with preallocated arrays For tape media: Tape flags set, DDT initialized as NULL (grows on demand) Initialized block and header caches for performance Open file stream ready for writing operations Index entries array ready for block tracking ECC context initialized for Compact Disc support Checksum contexts initialized based on options
  NULL | Creation failed. The specific error can be determined by checking errno, which will be set to: AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) when memory allocation fails for: Context allocation Readable sector tags array allocation Application version string allocation Image version string allocation DDT table allocation (userDataDdtMini or userDataDdtBig, block media only) Index entries array allocation AARUF_ERROR_CANNOT_CREATE_FILE (-19) when file operations fail: Unable to open the specified filepath for writing File seek operations fail during initialization File system errors or permission issues AARUF_ERROR_INVALID_APP_NAME_LENGTH (-20) when: application_name_length exceeds AARU_HEADER_APP_NAME_LEN (64 bytes)

Note
  Memory Management:
  - The function performs extensive memory allocation for various context structures
  - On failure, all previously allocated memory is properly cleaned up
  - The returned context must be freed using aaruf_close() when finished
  File Operations:
  - Creates a new file at the specified path (overwrites existing files)
  - Opens the file in binary read/write mode ("wb+")
  - Positions the file pointer at the calculated data start position
  - File alignment is handled based on parsed options
  DDT Initialization (Block Media Only):
  - Uses DDT version 2 format with configurable compression and alignment
  - Calculates optimal table sizes based on sector counts and shift parameters
  - All DDT entries are initialized to zero (indicating unallocated sectors)
  - Multi-level DDT is used for images with ≥ 138,412,552 total sectors
  - Single-level DDT is used for smaller images for efficiency
  - DDT is a fixed-size preallocated array written to file at known offset
  Tape Media Initialization:
  - Tape images use a dynamic hash table DDT for sector-level deduplication
  - File and partition metadata is managed via separate hash tables
  - ctx->is_tape is set to 1 to indicate tape mode throughout the library
  - ctx->tapeDdt is initialized to NULL and grows dynamically as blocks are written
  - Data blocks can start immediately after header for optimal sequential access
  - The hash table DDT allows for efficient deduplication without knowing final size
  - More memory-efficient for tapes with unpredictable or very large sizes
  - Deduplication hash map may still be used alongside tapeDdt if enabled in options
  Options Parsing:
  - The options string is parsed to extract block_alignment, data_shift, and table_shift
  - These parameters affect memory usage, performance, and file organization
  - Invalid options may result in suboptimal performance but won't cause failure
  - Compression and checksums can be enabled independently via options
  Checksum Initialization:
  - MD5, SHA-1, SHA-256, SpamSum, and BLAKE3 can be calculated during write
  - Checksum contexts are initialized only if requested in options
  - Checksums are computed incrementally as sectors/blocks are written
  - Final checksums are stored in checksum block during image finalization

Warning
  The created context is in writing mode and expects proper finalization before closing to ensure index and metadata are written correctly.
  Application name length validation is strict - exceeding the limit will cause creation failure with AARUF_ERROR_INVALID_APP_NAME_LENGTH.
  For tape media, the DDT structure is fundamentally different (hash table vs array). The is_tape flag must accurately reflect the media type being created.
  The negative_sectors and overflow_sectors parameters are used only for block media. For tape media, these parameters are ignored.

See also
  aaruf_close() for proper context cleanup and image finalization
  aaruf_write_sector() for writing sectors to block media images
  aaruf_set_tape_file() for defining tape file metadata
  aaruf_set_tape_partition() for defining tape partition metadata

< Size in bytes (UTF-16LE) of application name field (32 UTF-16 code units).

< Size in bytes of GUID / UUID-like binary identifier.

Definition at line 279 of file create.c.

References AARU_CALL, AARU_EXPORT, AARU_HEADER_APP_NAME_LEN, AARU_MAGIC, aaruf_ecc_cd_init(), AARUF_ERROR_CANNOT_CREATE_FILE, AARUF_ERROR_INVALID_APP_NAME_LENGTH, AARUF_ERROR_NOT_ENOUGH_MEMORY, aaruf_get_xml_mediatype(), aaruf_md5_init(), aaruf_sha1_init(), aaruf_sha256_init(), aaruf_spamsum_init(), AARUF_VERSION_V2, ImageInfo::Application, AaruHeaderV2::application, AaruHeaderV2::applicationMajorVersion, AaruHeaderV2::applicationMinorVersion, ImageInfo::ApplicationVersion, aaru_options::blake3, aaruformat_context::blake3_context, aaru_options::block_alignment, aaruformat_context::block_cache, aaruformat_context::block_header_cache, DdtHeader2::blockAlignmentShift, DdtHeader2::blocks, CacheHeader::cache, aaruformat_context::calculating_blake3, aaruformat_context::calculating_md5, aaruformat_context::calculating_sha1, aaruformat_context::calculating_sha256, aaruformat_context::calculating_spamsum, cleanup_failed_create(), aaru_options::compress, DdtHeader2::compression, aaruformat_context::compression_enabled, create_map(), ImageInfo::CreationTime, AaruHeaderV2::creationTime, aaru_options::data_shift, DdtHeader2::dataShift, aaru_options::deduplicate, aaruformat_context::deduplicate, DeDuplicationTable2, aaru_options::dictionary, aaruformat_context::ecc_cd_context, DdtHeader2::entries, FATAL, generate_random_bytes(), get_filetime_uint64(), AaruHeaderV2::guid, GUID_SIZE, aaruformat_context::header, AaruHeaderV2::identifier, DdtHeader2::identifier, aaruformat_context::image_info, AaruHeaderV2::imageMajorVersion, AaruHeaderV2::imageMinorVersion, ImageInfo::ImageSize, aaruformat_context::imageStream, aaruformat_context::in_memory_ddt, aaruformat_context::index_entries, AaruHeaderV2::indexOffset, aaruformat_context::is_tape, aaruformat_context::is_writing, aaruformat_context::last_written_block, ImageInfo::LastModificationTime, AaruHeaderV2::lastWrittenTime, DdtHeader2::levels, LIBAARUFORMAT_MAJOR_VERSION, LIBAARUFORMAT_MINOR_VERSION, aaruformat_context::library_major_version, aaruformat_context::library_minor_version, aaruformat_context::lzma_dict_size, aaruformat_context::magic, MAX_CACHE_SIZE, CacheHeader::max_items, MaxSectorTag, aaru_options::md5, aaruformat_context::md5_context, ImageInfo::MediaType, AaruHeaderV2::mediaType, ImageInfo::MetadataMediaType, DdtHeader2::negative, aaruformat_context::next_block_position, None, DdtHeader2::overflow, parse_options(), DdtHeader2::previousLevelOffset, aaruformat_context::primary_ddt_offset, aaruformat_context::readableSectorTags, aaruformat_context::rewinded, aaruformat_context::sector_hash_map, ImageInfo::Sectors, ImageInfo::SectorSize, aaru_options::sha1, aaruformat_context::sha1_context, aaru_options::sha256, aaruformat_context::sha256_context, aaruformat_context::shift, aaru_options::spamsum, aaruformat_context::spamsum_context, DdtHeader2::start, aaru_options::table_shift, DdtHeader2::tableLevel, DdtHeader2::tableShift, aaruformat_context::tape_ddt, TRACE, DdtHeader2::type, aaruformat_context::user_data_ddt2, aaruformat_context::user_data_ddt_header, UserData, and ImageInfo::Version.

## ◆ cleanup_failed_create()

void cleanup_failed_create | ( | aaruformat_context * | ctx | ) |
| static

Definition at line 30 of file create.c.

References aaruf_spamsum_free(), aaruformat_context::blake3_context, aaruformat_context::ecc_cd_context, free_map(), aaruformat_context::imageStream, aaruformat_context::index_entries, aaruformat_context::readableSectorTags, aaruformat_context::sector_hash_map, aaruformat_context::spamsum_context, and aaruformat_context::user_data_ddt2.

Referenced by aaruf_create().