diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7e739c1..f9a3d64 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -256,6 +256,7 @@ add_library(aaruformat
src/lisa_tag.c
include/aaruformat/structs/lisa_tag.h
src/metadata.c
+ src/metadata_write.c
src/dump.c
include/aaruformat/structs/tape.h
src/blocks/tape.c
diff --git a/src/metadata.c b/src/metadata.c
index b573399..dd689e4 100644
--- a/src/metadata.c
+++ b/src/metadata.c
@@ -15,6 +15,16 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see .
*/
+/**
+ * @file metadata.c
+ * @brief Read-only metadata accessors for libaaruformat.
+ *
+ * Contains all aaruf_get_* functions that retrieve metadata from an opened
+ * AaruFormat image context. Writer-side functions (aaruf_set_*, aaruf_clear_*)
+ * are in metadata_write.c.
+ *
+ * @see metadata_write.c
+ */
#include
#include
@@ -134,1721 +144,6 @@ AARU_EXPORT int32_t AARU_CALL aaruf_get_geometry(const void *context, uint32_t *
return AARUF_STATUS_OK;
}
-/**
- * @brief Sets the logical CHS geometry for the AaruFormat image.
- *
- * Configures the Cylinder-Head-Sector (CHS) geometry information for the image being
- * created or modified. This function populates both the geometry block (used for storage
- * in the image file) and the image information structure (used for runtime calculations).
- * The geometry block contains legacy-style logical addressing parameters that describe
- * how the storage medium should be logically organized in terms of cylinders, heads
- * (tracks per cylinder), and sectors per track. This information is crucial for creating
- * images that will be used with software requiring CHS addressing or for accurately
- * preserving the original medium's logical structure.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param cylinders The number of cylinders to set for the geometry.
- * @param heads The number of heads (tracks per cylinder) to set for the geometry.
- * @param sectors_per_track The number of sectors per track to set for the geometry.
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set geometry information. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - The geometry block identifier is set to GeometryBlock
- * - The geometry block fields (cylinders, heads, sectorsPerTrack) are updated
- * - The image info fields (Cylinders, Heads, SectorsPerTrack) are synchronized
- * - All parameters are stored for subsequent write operations
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @note Dual Storage:
- * - Geometry is stored in two locations within the context:
- * 1. ctx->geometryBlock: Written to the image file as a GeometryBlock during close
- * 2. ctx->imageInfo: Used for runtime calculations and metadata queries
- * - Both locations are kept synchronized by this function
- *
- * @note Geometry Calculation:
- * - Total logical sectors = cylinders × heads × sectors_per_track
- * - Ensure the product matches the actual sector count in the image
- * - Mismatched geometry may cause issues with legacy software or emulators
- * - Sector size is separate and should be set via other API calls
- *
- * @note CHS Addressing Requirements:
- * - Required for images intended for legacy BIOS or MBR partition schemes
- * - Essential for floppy disk images and older hard disk images
- * - May be optional or synthetic for modern large-capacity drives
- * - Some virtualization platforms require valid CHS geometry
- *
- * @note Parameter Constraints:
- * - No validation is performed on the geometry values
- * - Zero values are technically accepted but may cause issues
- * - Extremely large values may overflow in calculations (cylinders × heads × sectors_per_track)
- * - Common constraints for legacy systems:
- * * Cylinders: typically 1-1024 for BIOS, up to 65535 for modern systems
- * * Heads: typically 1-255 for most systems
- * * Sectors per track: typically 1-63 for BIOS, up to 255 for modern systems
- *
- * @note Write Mode Requirement:
- * - This function is intended for use during image creation
- * - Should be called after aaruf_create() and before writing sector data
- * - The geometry block is serialized during aaruf_close()
- * - Must be used with a write-enabled context
- *
- * @note Historical Context:
- * - CHS geometry was the original addressing scheme for disk drives
- * - Physical CHS reflected actual disk platters, heads, and sector layout
- * - Logical CHS often differs from physical due to zone-bit recording and translation
- * - Modern drives use LBA (Logical Block Addressing) internally
- *
- * @warning This function does not validate geometry consistency:
- * - Does not check if cylinders × heads × sectors_per_track equals image sector count
- * - Does not prevent overflow in the multiplication
- * - Caller must ensure geometry values are appropriate for the medium type
- * - Invalid geometry may cause boot failures or data access issues
- *
- * @warning The geometry block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- *
- * @warning Changing geometry after writing sector data may create inconsistencies.
- * Set geometry before beginning sector write operations for best results.
- *
- * @warning Some image formats and use cases don't require CHS geometry:
- * - Optical media (CD/DVD/BD) use different addressing schemes
- * - Modern GPT-partitioned disks don't rely on CHS
- * - Flash-based storage typically doesn't have meaningful CHS geometry
- * - Setting geometry for such media types is harmless but unnecessary
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_geometry(void *context, const uint32_t cylinders, const uint32_t heads,
- const uint32_t sectors_per_track)
-{
- TRACE("Entering aaruf_set_geometry(%p, %u, %u, %u)", context, cylinders, heads, sectors_per_track);
-
- aaruformat_context *ctx = NULL;
-
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_geometry() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_geometry() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_write_sector() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- ctx->geometry_block.identifier = GeometryBlock;
- ctx->geometry_block.cylinders = cylinders;
- ctx->geometry_block.heads = heads;
- ctx->geometry_block.sectorsPerTrack = sectors_per_track;
- ctx->cylinders = cylinders;
- ctx->heads = heads;
- ctx->sectors_per_track = sectors_per_track;
- ctx->dirty_geometry_block = true; // Mark geometry block as dirty
-
- TRACE("Exiting aaruf_set_geometry(%p, %u, %u, %u) = AARUF_STATUS_OK", context, cylinders, heads, sectors_per_track);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the media sequence information for multi-volume media sets.
- *
- * Configures the sequence numbering for media that is part of a larger set, such as
- * multi-disk software distributions, backup sets spanning multiple tapes, or optical
- * disc sets. This function records both the current media's position in the sequence
- * and the total number of media in the complete set. This metadata is essential for
- * proper ordering and completeness verification when working with multi-volume archives.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param sequence The sequence number of this media (1-based index indicating position in the set).
- * @param last_sequence The total number of media in the complete set (indicates the final sequence number).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set media sequence information. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The mediaSequence field is set to the provided sequence value
- * - The lastMediaSequence field is set to the provided last_sequence value
- * - Both values are stored for serialization during image close
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @note Sequence Numbering:
- * - Sequence numbers are typically 1-based (first disc is 1, not 0)
- * - The sequence parameter should be in the range [1, last_sequence]
- * - last_sequence indicates the total count of media in the set
- * - Example: For a 3-disc set, disc 2 would have sequence=2, last_sequence=3
- *
- * @note Common Use Cases:
- * - Multi-CD/DVD software installations (e.g., "Disc 2 of 4")
- * - Backup tape sets spanning multiple volumes
- * - Split archive formats requiring sequential processing
- * - Multi-floppy disk software distributions
- * - Large data sets divided across multiple optical discs
- *
- * @note Metadata Block Initialization:
- * - If the metadata block header is not yet initialized, this function initializes it
- * - The metadataBlockHeader.identifier is set to MetadataBlock automatically
- * - Multiple metadata setter functions can be called to build complete metadata
- * - All metadata is written to the image file during aaruf_close()
- *
- * @note Single Media Images:
- * - For standalone media not part of a set, use sequence=1, last_sequence=1
- * - Setting both values to 0 may be used to indicate "not part of a sequence"
- * - The function does not validate that sequence <= last_sequence
- *
- * @note Parameter Validation:
- * - No validation is performed on sequence numbers
- * - Negative values are accepted but may be semantically incorrect
- * - sequence > last_sequence is not prevented but indicates an error condition
- * - Callers should ensure sequence and last_sequence are logically consistent
- *
- * @note Archive Integrity:
- * - Proper sequence metadata is crucial for multi-volume restoration
- * - Archival software may refuse to extract if sequence information is incorrect
- * - Missing volumes can be detected by checking sequence completeness
- * - Helps prevent data loss from incomplete multi-volume sets
- *
- * @note Historical Context:
- * - Multi-volume sets were common in the floppy disk era due to size constraints
- * - CD/DVD sets were used for large software distributions (operating systems, games)
- * - Tape backup systems still use multi-volume sets for large archives
- * - Modern optical media (BD-R DL) reduced the need for multi-disc sets
- *
- * @warning This function does not validate the logical consistency of sequence numbers:
- * - Does not check if sequence <= last_sequence
- * - Does not prevent negative or zero values if semantically inappropriate
- * - Caller must ensure values represent a valid sequence relationship
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- *
- * @warning Incorrect sequence information may prevent proper reconstruction:
- * - Software relying on sequence numbers may fail to recognize media order
- * - Archival systems may incorrectly report missing volumes
- * - Restoration processes may fail if sequence is inconsistent
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_media_sequence(void *context, const int32_t sequence,
- const int32_t last_sequence)
-{
- TRACE("Entering aaruf_set_media_sequence(%p, %d, %d)", context, sequence, last_sequence);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_media_sequence() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- ctx->metadata_block_header.mediaSequence = sequence;
- ctx->metadata_block_header.lastMediaSequence = last_sequence;
-
- TRACE("Exiting aaruf_set_media_sequence(%p, %d, %d) = AARUF_STATUS_OK", context, sequence, last_sequence);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the creator (person/operator) information for the image.
- *
- * Records the name of the person or operator who created the AaruFormat image. This
- * metadata identifies the individual responsible for the imaging process, which is
- * valuable for provenance tracking, accountability, and understanding the human context
- * in which the image was created. The creator name is stored in UTF-16LE encoding and
- * preserved exactly as provided by the caller.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the creator name string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the creator data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set creator information. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the creator string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The creator data is copied to ctx->imageInfo.Creator
- * - The creatorLength field is set in the metadata block header
- * - Any previous creator string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the creator string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note UTF-16LE Encoding:
- * - The data parameter must contain a valid UTF-16LE encoded string
- * - Length must be in bytes, not character count (UTF-16LE uses 2 or 4 bytes per character)
- * - The library treats the data as opaque and does not validate UTF-16LE encoding
- * - Null termination is not required; length specifies the exact byte count
- * - Ensure even byte lengths to maintain UTF-16LE character alignment
- *
- * @note Creator Name Format:
- * - Typically contains the full name of the person who created the image
- * - May include titles, credentials, or institutional affiliations
- * - Common formats: "John Smith", "Dr. Jane Doe", "Smith, John (Archivist)"
- * - Should identify the individual operator, not the software used
- * - May include contact information or employee/operator ID in institutional settings
- *
- * @note Provenance and Accountability:
- * - Identifies who performed the imaging operation
- * - Important for establishing chain of custody in forensic contexts
- * - Provides contact point for questions about the imaging process
- * - Supports institutional recordkeeping and quality assurance
- * - May be required for compliance with archival standards
- *
- * @note Privacy Considerations:
- * - Consider privacy implications when recording personal names
- * - Some organizations may use operator IDs instead of full names
- * - Institutional policies may govern what personal information is recorded
- * - GDPR and similar regulations may apply in some jurisdictions
- *
- * @note Memory Management:
- * - The function allocates a new buffer and copies the data
- * - If a previous creator string exists, it is freed before replacement
- * - The caller retains ownership of the input data buffer
- * - The allocated memory is freed when the context is closed or destroyed
- *
- * @note Metadata Block Initialization:
- * - If the metadata block header is not yet initialized, this function initializes it
- * - The metadataBlockHeader.identifier is set to MetadataBlock automatically
- * - Multiple metadata setter functions can be called to build complete metadata
- *
- * @warning The data buffer must remain valid for the duration of this function call.
- * After the function returns, the caller may free or reuse the data buffer.
- *
- * @warning Invalid UTF-16LE encoding may cause issues when reading the metadata:
- * - The library does not validate UTF-16LE correctness
- * - Malformed strings may display incorrectly or cause decoding errors
- * - Ensure the data is properly encoded before calling this function
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_creator(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_creator(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_creator() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_creator() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_creator() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for creator");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->creator != NULL) free(ctx->creator);
- ctx->creator = copy;
- ctx->metadata_block_header.creatorLength = length;
-
- TRACE("Exiting aaruf_set_creator(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets user comments or notes for the image.
- *
- * Records arbitrary user-provided comments, notes, or annotations associated with the
- * AaruFormat image. This metadata field allows users to document the image's purpose,
- * provenance, condition, or any other relevant information. Comments are stored in
- * UTF-16LE encoding and can contain multi-line text, special characters, and detailed
- * descriptions.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the comments string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the comments data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set comments. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the comments string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The comments data is copied to ctx->imageInfo.Comments
- * - The commentsLength field is set in the metadata block header
- * - Any previous comments string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the comments string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note UTF-16LE Encoding:
- * - The data parameter must contain a valid UTF-16LE encoded string
- * - Length must be in bytes, not character count
- * - The library treats the data as opaque and does not validate encoding
- * - Null termination is not required; length specifies the exact byte count
- *
- * @note Common Uses for Comments:
- * - Documentation of image source and creation date
- * - Notes about media condition or read errors encountered
- * - Preservation metadata and archival notes
- * - User annotations for organizing image collections
- * - Workflow status or processing history
- *
- * @note Memory Management:
- * - The function allocates a new buffer and copies the data
- * - If previous comments exist, they are freed before replacement
- * - The caller retains ownership of the input data buffer
- * - The allocated memory is freed when the context is closed or destroyed
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_comments(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_comments(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_comments() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_comments() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_comments() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for comments");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->comments != NULL) free(ctx->comments);
- ctx->comments = copy;
- ctx->metadata_block_header.commentsLength = length;
-
- TRACE("Exiting aaruf_set_comments(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the media title or label for the image.
- *
- * Records the title, label, or name printed or written on the physical storage media.
- * This metadata is particularly useful for identifying discs, tapes, or other media
- * that have user-applied labels or manufacturer-printed titles. The title is stored
- * in UTF-16LE encoding to support international characters and special symbols.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the media title string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the media title data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set media title. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the media title string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The media title data is copied to ctx->imageInfo.MediaTitle
- * - The mediaTitleLength field is set in the metadata block header
- * - Any previous media title string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the media title string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Common Media Title Examples:
- * - Handwritten labels on optical discs or tapes
- * - Pre-printed software names on distribution media (e.g., "Windows 95 Setup Disk 1")
- * - Volume labels or disc names (e.g., "BACKUP_2024", "INSTALL_CD")
- * - Game titles printed on cartridges or discs
- * - Album or movie titles on multimedia discs
- *
- * @note Preservation Context:
- * - Important for archival purposes to record exactly what appears on the media
- * - Helps identify media in large collections
- * - May differ from filesystem volume labels
- * - Useful for matching physical media to digital images
- *
- * @note UTF-16LE Encoding:
- * - The data parameter must contain a valid UTF-16LE encoded string
- * - Length must be in bytes, not character count
- * - Supports international characters, emoji, and special symbols
- * - Null termination is not required; length specifies the exact byte count
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_media_title(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_media_title(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_media_title() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for media title");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->media_title != NULL) free(ctx->media_title);
- ctx->media_title = copy;
- ctx->metadata_block_header.mediaTitleLength = length;
- ctx->dirty_metadata_block = true; // Mark metadata block as dirty
-
- TRACE("Exiting aaruf_set_media_title(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the media manufacturer information for the image.
- *
- * Records the name of the company that manufactured the physical storage media.
- * This metadata is valuable for preservation and forensic purposes, as it can help
- * identify the media type, quality characteristics, and manufacturing period. The
- * manufacturer name is stored in UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the media manufacturer string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the media manufacturer data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set media manufacturer. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the media manufacturer string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The media manufacturer data is copied to ctx->imageInfo.MediaManufacturer
- * - The mediaManufacturerLength field is set in the metadata block header
- * - Any previous media manufacturer string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the media manufacturer string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Common Media Manufacturers:
- * - Optical discs: Verbatim, Sony, Maxell, TDK, Taiyo Yuden
- * - Magnetic tapes: Fujifilm, Maxell, Sony, IBM
- * - Floppy disks: 3M, Maxell, Sony, Verbatim
- * - Flash media: SanDisk, Kingston, Samsung
- *
- * @note Identification Methods:
- * - May be printed on the media surface or packaging
- * - Can sometimes be detected from media ID codes (e.g., ATIP for CD-R)
- * - Historical records or catalogs may provide this information
- * - Important for understanding media quality and longevity characteristics
- *
- * @note Preservation Value:
- * - Helps assess expected media lifespan and degradation patterns
- * - Useful for identifying counterfeit or remarked media
- * - Aids in research about media quality and failure modes
- * - Provides context for archival planning and migration strategies
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_media_manufacturer(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_media_manufacturer(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_media_manufacturer() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for media manufacturer");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->media_manufacturer != NULL) free(ctx->media_manufacturer);
- ctx->media_manufacturer = copy;
- ctx->metadata_block_header.mediaManufacturerLength = length;
-
- TRACE("Exiting aaruf_set_media_manufacturer(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the media model or product designation for the image.
- *
- * Records the specific model, product line, or type designation of the physical storage
- * media. This is more specific than the manufacturer and identifies the exact product
- * variant. This metadata helps in identifying specific media characteristics, performance
- * specifications, and compatibility information. The model information is stored in
- * UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the media model string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the media model data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set media model. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the media model string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The media model data is copied to ctx->imageInfo.MediaModel
- * - The mediaModelLength field is set in the metadata block header
- * - Any previous media model string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the media model string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Model Designation Examples:
- * - Optical discs: "DVD+R 16x", "CD-R 80min", "BD-R DL 50GB"
- * - Tapes: "LTO-7", "DLT-IV", "AIT-3"
- * - Floppy disks: "HD 1.44MB", "DD 720KB"
- * - Flash cards: "SDHC Class 10", "CompactFlash 1000x"
- *
- * @note Model Information Usage:
- * - Identifies specific capacity and speed ratings
- * - Indicates format compatibility (e.g., DVD-R vs DVD+R)
- * - Helps determine recording characteristics and quality tier
- * - Useful for matching replacement media or troubleshooting issues
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_media_model(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_media_model(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_media_model() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for media model");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->media_model != NULL) free(ctx->media_model);
- ctx->media_model = copy;
- ctx->metadata_block_header.mediaModelLength = length;
-
- TRACE("Exiting aaruf_set_media_model(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the media serial number for the image.
- *
- * Records the unique serial number assigned to the physical storage media by the
- * manufacturer. This metadata provides a unique identifier for the specific piece of
- * media, which is invaluable for tracking, authentication, and forensic analysis. Not
- * all media types have serial numbers; this is most common with professional-grade
- * media and some consumer optical discs. The serial number is stored in UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the media serial number string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the media serial number data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set media serial number. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the media serial number string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The media serial number data is copied to ctx->imageInfo.MediaSerialNumber
- * - The mediaSerialNumberLength field is set in the metadata block header
- * - Any previous media serial number string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the media serial number string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Serial Number Availability:
- * - Professional tape media (LTO, DLT, etc.) typically have printed serial numbers
- * - Some optical discs have embedded media IDs that can serve as serial numbers
- * - Hard drives and SSDs have electronically-readable serial numbers
- * - Consumer recordable media (CD-R, DVD-R) rarely have unique serial numbers
- * - May be printed on labels, hubs, or cartridge shells
- *
- * @note Forensic and Archival Importance:
- * - Uniquely identifies the specific physical media instance
- * - Critical for chain of custody in forensic investigations
- * - Enables tracking of media throughout its lifecycle
- * - Helps prevent mix-ups in large media collections
- * - Can verify authenticity and detect counterfeits
- *
- * @note Format Considerations:
- * - Serial numbers may be alphanumeric, numeric, or contain special characters
- * - Format varies widely between manufacturers and media types
- * - May include check digits or formatting separators
- * - Should be recorded exactly as it appears on the media
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_media_serial_number(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_media_serial_number(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_media_serial_number() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for media serial number");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->media_serial_number != NULL) free(ctx->media_serial_number);
- ctx->media_serial_number = copy;
- ctx->metadata_block_header.mediaSerialNumberLength = length;
-
- TRACE("Exiting aaruf_set_media_serial_number(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the media barcode information for the image.
- *
- * Records the barcode affixed to the physical storage media or its packaging. Barcodes
- * are commonly used in professional archival and library environments for automated
- * inventory management, tracking, and retrieval systems. This metadata enables correlation
- * between physical media location systems and digital image files. The barcode is stored
- * in UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the media barcode string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the media barcode data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set media barcode. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the media barcode string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The media barcode data is copied to ctx->imageInfo.MediaBarcode
- * - The mediaBarcodeLength field is set in the metadata block header
- * - Any previous media barcode string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the media barcode string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Common Barcode Uses:
- * - Library and archival tape management systems
- * - Automated tape library robotics (e.g., LTO tape cartridges)
- * - Inventory tracking in large media collections
- * - Asset management in corporate or institutional settings
- * - Chain of custody tracking in forensic environments
- *
- * @note Barcode Types and Formats:
- * - Code 39 and Code 128 are common for media labeling
- * - LTO tapes use specific 6 or 8-character barcode formats
- * - May include library-specific prefixes or location codes
- * - Some systems use 2D barcodes (QR codes, Data Matrix)
- * - Barcode should be recorded exactly as it appears
- *
- * @note Integration with Physical Systems:
- * - Enables automated correlation between physical and digital catalogs
- * - Supports robotic tape library operations
- * - Facilitates retrieval from off-site storage facilities
- * - Links to broader asset management databases
- * - Critical for large-scale archival operations
- *
- * @note Preservation Context:
- * - Important for long-term archival planning
- * - Helps maintain inventory accuracy over time
- * - Supports audit and compliance requirements
- * - Enables efficient physical media location and retrieval
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_media_barcode(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_media_barcode(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_media_barcode() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for media barcode");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->media_barcode != NULL) free(ctx->media_barcode);
- ctx->media_barcode = copy;
- ctx->metadata_block_header.mediaBarcodeLength = length;
-
- TRACE("Exiting aaruf_set_media_barcode(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the media part number or model designation for the image.
- *
- * Records the manufacturer's part number or catalog designation for the specific type
- * of physical storage media. This is distinct from the media model in that it represents
- * the exact ordering or catalog number used for procurement and inventory purposes. Part
- * numbers are particularly important for sourcing compatible replacement media and for
- * precise identification in technical documentation. The part number is stored in UTF-16LE
- * encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the media part number string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the media part number data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set media part number. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the media part number string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The media part number data is copied to ctx->imageInfo.MediaPartNumber
- * - The mediaPartNumberLength field is set in the metadata block header
- * - Any previous media part number string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the media part number string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Part Number Examples:
- * - Optical media: "MR-25332" (Verbatim DVD+R), "CDR80JC" (Sony CD-R)
- * - Tape media: "C7973A" (HP LTO-3), "TK88" (Maxell DLT-IV)
- * - Floppy disks: "MF2HD" (3.5" high-density), "2D" (5.25" double-density)
- * - May include regional variations or packaging size indicators
- *
- * @note Practical Applications:
- * - Procurement and ordering of compatible replacement media
- * - Cross-referencing with manufacturer specifications and datasheets
- * - Identifying specific product revisions or manufacturing batches
- * - Ensuring compatibility for archival media migration projects
- * - Tracking costs and suppliers in institutional settings
- *
- * @note Relationship to Model:
- * - Part number is more specific than model designation
- * - Model might be "DVD+R 16x", part number "MR-25332"
- * - Part numbers may vary by region, packaging quantity, or color
- * - Critical for exact product identification in catalogs and databases
- *
- * @note Documentation and Compliance:
- * - Useful for creating detailed preservation documentation
- * - Supports compliance with archival standards and best practices
- * - Enables precise replication of archival environments
- * - Facilitates research on media types and failure modes
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_media_part_number(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_media_part_number(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_media_part_number() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for creator");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->media_part_number != NULL) free(ctx->media_part_number);
- ctx->media_part_number = copy;
- ctx->metadata_block_header.mediaPartNumberLength = length;
-
- TRACE("Exiting aaruf_set_media_part_number(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the drive manufacturer information for the image.
- *
- * Records the name of the company that manufactured the drive or device used to read
- * or write the physical storage media. This metadata provides valuable context about
- * the imaging process, as different drives may have different capabilities, error
- * handling characteristics, and compatibility with specific media types. The manufacturer
- * name is stored in UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the drive manufacturer string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the drive manufacturer data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set drive manufacturer. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the drive manufacturer string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The drive manufacturer data is copied to ctx->imageInfo.DriveManufacturer
- * - The driveManufacturerLength field is set in the metadata block header
- * - Any previous drive manufacturer string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the drive manufacturer string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Common Drive Manufacturers:
- * - Optical drives: Pioneer, Plextor, LG, ASUS, Sony, Samsung
- * - Tape drives: HP, IBM, Quantum, Tandberg, Exabyte
- * - Hard drives: Seagate, Western Digital, Hitachi, Toshiba
- * - Floppy drives: Teac, Panasonic, Mitsumi, Sony
- *
- * @note Imaging Context and Quality:
- * - Different manufacturers have varying error recovery capabilities
- * - Some drives are better suited for archival-quality imaging
- * - Plextor drives were historically preferred for optical disc preservation
- * - Professional-grade drives often have better read accuracy
- * - Important for understanding potential limitations in the imaging process
- *
- * @note Forensic and Provenance Value:
- * - Documents the complete imaging environment
- * - Helps assess reliability and trustworthiness of the image
- * - Useful for troubleshooting or reproducing imaging results
- * - May be required for forensic chain of custody
- * - Supports quality assurance and validation processes
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_manufacturer(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_drive_manufacturer(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_drive_manufacturer() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for drive manufacturer");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->drive_manufacturer != NULL) free(ctx->drive_manufacturer);
- ctx->drive_manufacturer = copy;
- ctx->metadata_block_header.driveManufacturerLength = length;
-
- TRACE("Exiting aaruf_set_drive_manufacturer(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the drive model information for the image.
- *
- * Records the specific model or product designation of the drive or device used to read
- * or write the physical storage media. This metadata provides detailed information about
- * the imaging equipment, which can be important for understanding the capabilities,
- * limitations, and characteristics of the imaging process. Different drive models within
- * the same manufacturer's product line may have significantly different features and
- * performance characteristics. The model information is stored in UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the drive model string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the drive model data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set drive model. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the drive model string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The drive model data is copied to ctx->imageInfo.DriveModel
- * - The driveModelLength field is set in the metadata block header
- * - Any previous drive model string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the drive model string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Drive Model Examples:
- * - Optical drives: "DVR-111D" (Pioneer), "PX-716A" (Plextor), "GH24NSB0" (LG)
- * - Tape drives: "Ultrium 7-SCSI" (HP), "TS1140" (IBM), "SDLT600" (Quantum)
- * - Hard drives: "ST2000DM008" (Seagate), "WD40EZRZ" (Western Digital)
- * - Floppy drives: "FD-235HF" (Teac), "JU-257A633P" (Panasonic)
- *
- * @note Model-Specific Characteristics:
- * - Different models may have different error correction algorithms
- * - Some models are known for superior read quality (e.g., Plextor Premium)
- * - Certain models may have bugs or quirks in specific firmware versions
- * - Professional models often have features not available in consumer versions
- * - Important for reproducing imaging conditions or troubleshooting issues
- *
- * @note Forensic Documentation:
- * - Complete drive identification aids in forensic reporting
- * - Helps establish the reliability of the imaging process
- * - May be required for compliance with forensic standards
- * - Supports validation and verification procedures
- * - Enables assessment of tool suitability for the imaging task
- *
- * @note Historical and Research Value:
- * - Documents evolution of imaging technology over time
- * - Helps identify best practices for specific media types
- * - Useful for academic research on digital preservation
- * - Aids in understanding drive availability and obsolescence
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_model(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_drive_model(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_drive_model() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for media model");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->drive_model != NULL) free(ctx->drive_model);
- ctx->drive_model = copy;
- ctx->metadata_block_header.driveModelLength = length;
-
- TRACE("Exiting aaruf_set_drive_model(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the drive serial number for the image.
- *
- * Records the unique serial number of the drive or device used to read or write the
- * physical storage media. This metadata provides a unique identifier for the specific
- * piece of hardware used in the imaging process, which is particularly important for
- * forensic work, equipment tracking, and quality assurance. The serial number enables
- * correlation between multiple images created with the same drive and can help identify
- * drive-specific issues or characteristics. The serial number is stored in UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the drive serial number string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the drive serial number data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set drive serial number. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the drive serial number string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The drive serial number data is copied to ctx->imageInfo.DriveSerialNumber
- * - The driveSerialNumberLength field is set in the metadata block header
- * - Any previous drive serial number string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the drive serial number string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Serial Number Sources:
- * - Hard drives and SSDs: Retrieved via ATA/SCSI IDENTIFY commands
- * - Optical drives: Available through SCSI inquiry or ATA identify
- * - Tape drives: Typically reported via SCSI inquiry data
- * - USB devices: May have USB serial numbers or internal device serials
- * - Some older or consumer devices may not report serial numbers
- *
- * @note Forensic Applications:
- * - Critical for forensic chain of custody documentation
- * - Uniquely identifies the specific hardware used for imaging
- * - Enables tracking of drive calibration and maintenance history
- * - Supports correlation of images created with the same equipment
- * - May be required by forensic standards and best practices
- *
- * @note Equipment Management:
- * - Helps track drive usage and workload for maintenance planning
- * - Enables identification of drives requiring replacement or service
- * - Supports equipment inventory and asset management systems
- * - Useful for identifying drives with known issues or recalls
- * - Facilitates warranty and support claim processing
- *
- * @note Quality Assurance:
- * - Enables analysis of drive-specific error patterns
- * - Helps identify if multiple imaging issues stem from the same drive
- * - Supports statistical quality control processes
- * - Aids in evaluating drive reliability over time
- * - Can reveal degradation or calibration drift in aging hardware
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_serial_number(void *context, const uint8_t *data, const int32_t length)
-{
- TRACE("Entering aaruf_set_drive_serial_number(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_drive_serial_number() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for drive serial number");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->drive_serial_number != NULL) free(ctx->drive_serial_number);
- ctx->drive_serial_number = copy;
- ctx->metadata_block_header.driveSerialNumberLength = length;
-
- TRACE("Exiting aaruf_set_drive_serial_number(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Sets the drive firmware revision for the image.
- *
- * Records the firmware version or revision of the drive or device used to read or write
- * the physical storage media. Firmware revisions can significantly affect drive behavior,
- * error handling, performance, and compatibility. This metadata is crucial for understanding
- * the imaging environment, troubleshooting issues, and ensuring reproducibility. Different
- * firmware versions of the same drive model can behave quite differently, making this
- * information essential for comprehensive documentation. The firmware revision is stored
- * in UTF-16LE encoding.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the drive firmware revision string data in UTF-16LE encoding (opaque byte array).
- * @param length Length of the drive firmware revision data in bytes (must include full UTF-16LE character sequences).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set drive firmware revision. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the drive firmware revision string succeeded
- * - The metadata block header is initialized (identifier set to MetadataBlock)
- * - The drive firmware revision data is copied to ctx->imageInfo.DriveFirmwareRevision
- * - The driveFirmwareRevisionLength field is set in the metadata block header
- * - Any previous drive firmware revision string is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the drive firmware revision string
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Firmware Revision Examples:
- * - Optical drives: "1.07", "1.00a", "VER A302"
- * - Tape drives: "B8S1", "7760", "V4.0"
- * - Hard drives: "CC45", "80.00A80", "HPG9"
- * - Format varies by manufacturer and device type
- *
- * @note Firmware Impact on Imaging:
- * - Different firmware versions may have different error recovery strategies
- * - Bug fixes in newer firmware can improve read reliability
- * - Some firmware versions have known issues with specific media types
- * - Performance characteristics may vary between firmware revisions
- * - Firmware can affect features like C2 error reporting on optical drives
- *
- * @note Troubleshooting and Support:
- * - Essential for diagnosing drive-specific problems
- * - Manufacturer support often requires firmware version information
- * - Helps identify if issues are resolved in newer firmware
- * - Enables correlation of problems with known firmware bugs
- * - Supports decision-making about firmware updates
- *
- * @note Reproducibility and Documentation:
- * - Complete environment documentation for scientific reproducibility
- * - Important for forensic work requiring detailed equipment records
- * - Helps explain variations in imaging results over time
- * - Supports compliance with archival and preservation standards
- * - Enables future researchers to understand imaging conditions
- *
- * @note Historical Tracking:
- * - Documents firmware changes over the life of imaging equipment
- * - Helps assess impact of firmware updates on imaging quality
- * - Useful for long-term archival projects spanning years
- * - Aids in understanding evolution of drive technology
- *
- * @warning The metadata block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted.
- *
- * @warning Firmware revisions are device-specific and format varies widely:
- * - No standard format exists across manufacturers
- * - May include letters, numbers, dots, or other characters
- * - Should be recorded exactly as reported by the device
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_firmware_revision(void *context, const uint8_t *data,
- const int32_t length)
-{
- TRACE("Entering aaruf_set_drive_firmware_revision(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_drive_firmware_revision() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Initialize
- if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for creator");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-16LE string
- memcpy(copy, data, length);
- if(ctx->drive_firmware_revision != NULL) free(ctx->drive_firmware_revision);
- ctx->drive_firmware_revision = copy;
- ctx->metadata_block_header.driveFirmwareRevisionLength = length;
-
- TRACE("Exiting aaruf_set_drive_firmware_revision(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
/**
* @brief Retrieves the embedded CICM XML metadata sidecar from the image.
*
@@ -2152,167 +447,6 @@ AARU_EXPORT int32_t AARU_CALL aaruf_get_aaru_json_metadata(const void *context,
return AARUF_STATUS_OK;
}
-/**
- * @brief Sets the Aaru metadata JSON for the image during creation.
- *
- * Embeds Aaru metadata JSON into the image being created. The Aaru metadata JSON format is a
- * structured, machine-readable representation of comprehensive image metadata including media
- * information, imaging session details, hardware configuration, optical disc tracks and sessions,
- * checksums, and preservation metadata. This function stores the JSON payload in its original form
- * without parsing or validation, allowing callers to provide pre-generated JSON conforming to the
- * Aaru metadata schema. The JSON data will be written to the image file during aaruf_close() as
- * an AaruMetadataJsonBlock.
- *
- * The function accepts raw UTF-8 encoded JSON data as an opaque byte array and creates an internal
- * copy that persists for the lifetime of the context. If Aaru JSON metadata was previously set on
- * this context, the old data is freed and replaced with the new JSON. The JSON is treated as opaque
- * binary data by the library; no parsing, interpretation, or schema validation is performed during
- * the set operation.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- * @param data Pointer to the Aaru metadata JSON data in UTF-8 encoding (opaque byte array).
- * The JSON should conform to the Aaru metadata schema, though this is not validated.
- * Must not be NULL.
- * @param length Length of the JSON data in bytes. The payload may or may not be null-terminated;
- * the length should reflect the actual JSON data size.
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully set Aaru metadata JSON. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Memory allocation for the JSON data succeeded
- * - The JSON data is copied to ctx->jsonBlock
- * - The jsonBlockHeader is initialized with identifier AaruMetadataJsonBlock
- * - The jsonBlockHeader.length field is set to the provided length
- * - Any previous Aaru JSON data is properly freed before replacement
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
- * - malloc() failed to allocate the required memory for the JSON data
- * - System is out of memory or memory is severely fragmented
- * - The requested allocation size is too large
- *
- * @note Aaru JSON Format and Encoding:
- * - The JSON payload must be valid UTF-8 encoded data
- * - The payload may or may not be null-terminated
- * - The library treats the JSON as opaque binary data
- * - No JSON parsing, interpretation, or validation is performed during set
- * - Schema compliance is the caller's responsibility
- * - Ensure the JSON conforms to the Aaru metadata schema for compatibility
- *
- * @note Aaru Metadata JSON Purpose:
- * - Provides machine-readable structured metadata using modern JSON format
- * - Includes comprehensive information about media, sessions, tracks, and checksums
- * - Enables programmatic access to metadata without XML parsing overhead
- * - Documents imaging session details, hardware configuration, and preservation data
- * - Used by Aaru and compatible tools for metadata exchange and analysis
- * - Complements or serves as alternative to CICM XML metadata
- *
- * @note JSON Content Examples:
- * - Media type and physical characteristics
- * - Track and session information for optical media
- * - Partition and filesystem metadata
- * - Checksums (MD5, SHA-1, SHA-256, etc.) for integrity verification
- * - Hardware information (drive manufacturer, model, firmware)
- * - Imaging software version and configuration
- * - Timestamps for image creation and modification
- *
- * @note Memory Management:
- * - The function creates an internal copy of the JSON data
- * - The caller retains ownership of the input data buffer
- * - The caller may free the input data immediately after this function returns
- * - The internal copy is freed automatically during aaruf_close()
- * - Calling this function multiple times replaces previous JSON data
- *
- * @note Relationship to CICM XML:
- * - Both CICM XML and Aaru JSON can be set on the same image
- * - CICM XML follows the Canary Islands Computer Museum schema (older format)
- * - Aaru JSON follows the Aaru-specific metadata schema (newer format)
- * - Setting one does not affect the other
- * - Different tools may prefer one format over the other
- * - Consider including both for maximum compatibility
- *
- * @warning The Aaru JSON block is only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted to disk.
- *
- * @warning No validation is performed on the JSON data:
- * - Invalid JSON syntax will be stored and only detected during parsing
- * - Schema violations will not be caught by this function
- * - Ensure JSON is valid and schema-compliant before calling
- * - Use a JSON validation library before embedding if correctness is critical
- *
- * @warning The function accepts any length value:
- * - Ensure the length accurately reflects the JSON data size
- * - Incorrect length values may cause truncation or include garbage data
- * - For null-terminated JSON, length should not include the null terminator
- * unless it is intended to be part of the stored data
- *
- * @see AaruMetadataJsonBlockHeader for the on-disk structure definition.
- * @see aaruf_get_aaru_json_metadata() for retrieving Aaru JSON from opened images.
- * @see write_aaru_json_block() for the serialization process during image closing.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_set_aaru_json_metadata(void *context, uint8_t *data, size_t length)
-{
- TRACE("Entering aaruf_set_aaru_json_metadata(%p, %p, %d)", context, data, length);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_aaru_json_metadata() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_set_aaru_json_metadata() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_set_aaru_json_metadata() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- // Reserve memory
- uint8_t *copy = malloc(length);
- if(copy == NULL)
- {
- FATAL("Could not allocate memory for Aaru metadata JSON");
- return AARUF_ERROR_NOT_ENOUGH_MEMORY;
- }
-
- // Copy opaque UTF-8 string
- memcpy(copy, data, length);
- if(ctx->json_block != NULL) free(ctx->json_block);
- ctx->json_block = copy;
- ctx->json_block_header.identifier = AaruMetadataJsonBlock;
- ctx->json_block_header.length = (uint32_t)length;
- ctx->dirty_json_block = true; // Mark JSON block as dirty
-
- TRACE("Exiting aaruf_set_aaru_json_metadata(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
- return AARUF_STATUS_OK;
-}
-
/**
* @brief Retrieves the media sequence metadata for multi-volume image sets.
*
@@ -3676,1245 +1810,3 @@ AARU_EXPORT int32_t AARU_CALL aaruf_get_image_info(const void *context, ImageInf
return AARUF_STATUS_OK;
}
-/**
- * @brief Clears the media sequence information from the image metadata.
- *
- * Removes the media sequence and last media sequence fields from the AaruFormat image's
- * metadata block, effectively removing any indication that this media is part of a
- * multi-volume set. Both the current sequence number and the total sequence count are
- * reset to zero. If this operation results in all metadata fields being empty, the
- * entire metadata block is deinitialized (identifier set to 0) to avoid writing an
- * empty metadata block to the image file.
- *
- * This function is useful when repurposing an image that was originally part of a
- * multi-disc set but is now being treated as standalone media, or when correcting
- * metadata that was set incorrectly.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared media sequence information. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Either the metadata block was not initialized (early exit, nothing to clear)
- * - Or the mediaSequence and lastMediaSequence fields are set to 0
- * - If all metadata fields are now empty, the metadata block identifier is cleared
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @note Metadata Block State Management:
- * - If the metadata block header is not initialized (identifier != MetadataBlock),
- * the function returns successfully without any action (nothing to clear)
- * - After clearing, if all metadata fields are empty, the metadata block header
- * identifier is set to 0, preventing an empty block from being written
- * - This automatic cleanup ensures efficient storage and avoids unnecessary blocks
- *
- * @note Sequence Field Reset:
- * - Both mediaSequence and lastMediaSequence are set to 0
- * - Zero values typically indicate "not part of a sequence" or "unknown sequence"
- * - The function does not differentiate between never-set and explicitly-cleared
- *
- * @note Use Cases:
- * - Correcting incorrectly set sequence metadata
- * - Converting multi-volume images to standalone format
- * - Removing obsolete sequence information during image repurposing
- * - Cleaning up test or development images
- *
- * @note Relationship to Other Metadata:
- * - This function only affects sequence fields; other metadata is preserved
- * - Use aaruf_set_media_sequence() to set new sequence values after clearing
- * - If reconstructing multi-volume metadata, set sequence before other fields
- *
- * @warning The metadata changes are only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted to disk.
- *
- * @warning After clearing, the sequence information is permanently lost unless:
- * - The image file is not closed (context remains in memory)
- * - A backup of the original image exists
- * - The information is reconstructed from external sources
- *
- * @see aaruf_set_media_sequence() for setting sequence information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_sequence(void *context)
-{
- TRACE("Entering aaruf_clear_media_sequence(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_media_sequence() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_media_sequence() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- ctx->metadata_block_header.mediaSequence = 0;
- ctx->metadata_block_header.lastMediaSequence = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
- ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
- ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_media_sequence() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the creator (person/operator) information from the image metadata.
- *
- * Removes the creator name string from the AaruFormat image's metadata block, freeing
- * the associated memory and resetting the length field to zero. This effectively removes
- * any record of who created the image. If this operation results in all metadata fields
- * being empty, the entire metadata block is deinitialized to avoid writing an empty
- * metadata block to the image file.
- *
- * This function is useful when anonymizing images for distribution, removing personally
- * identifiable information for privacy compliance (e.g., GDPR), or correcting metadata
- * that was set incorrectly during image creation.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared creator information. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Either the metadata block was not initialized (early exit, nothing to clear)
- * - Or the creator string is freed (if it existed) and the pointer set to NULL
- * - The creatorLength field in the metadata block header is set to 0
- * - If all metadata fields are now empty, the metadata block identifier is cleared
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @note Memory Management:
- * - If ctx->creator is not NULL, the allocated memory is freed before clearing
- * - The ctx->creator pointer is set to NULL after freeing
- * - Safe to call even if creator was never set (NULL check protects against errors)
- * - No memory leaks occur when clearing previously set creator information
- *
- * @note Privacy and Anonymization:
- * - Removes personally identifiable information from image metadata
- * - Important for GDPR compliance and privacy protection
- * - Consider clearing creator before distributing images publicly
- * - May be required by institutional privacy policies
- *
- * @note Metadata Block State Management:
- * - If the metadata block header is not initialized, function returns success immediately
- * - After clearing, checks if all metadata fields are empty
- * - If all fields empty, sets metadata block identifier to 0 (deinitialized)
- * - Prevents writing empty metadata blocks, saving storage space
- *
- * @note Use Cases:
- * - Anonymizing images for public distribution or research datasets
- * - Compliance with data protection regulations (GDPR, CCPA, etc.)
- * - Removing incorrect or outdated operator information
- * - Preparing images for archival with institutional rather than personal attribution
- * - Sanitizing test or development images before production use
- *
- * @warning The metadata changes are only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted to disk.
- *
- * @warning After clearing, the creator information is permanently lost unless:
- * - The image file is not closed (context remains in memory)
- * - A backup of the original image exists
- * - The information is reconstructed from external documentation
- *
- * @warning Clearing creator may affect:
- * - Forensic chain of custody requirements
- * - Provenance documentation for archival purposes
- * - Accountability and quality assurance workflows
- * - Consider legal and institutional requirements before clearing
- *
- * @see aaruf_set_creator() for setting creator information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_creator(void *context)
-{
- TRACE("Entering aaruf_clear_creator(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_creator() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_creator() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_creator() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_creator() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->creator != NULL) free(ctx->creator);
-
- ctx->creator = NULL;
- ctx->metadata_block_header.creatorLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.commentsLength == 0 && ctx->metadata_block_header.mediaTitleLength == 0 &&
- ctx->metadata_block_header.mediaManufacturerLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
- ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
- ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_creator() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears user comments or notes from the image metadata.
- *
- * Removes the comments string from the AaruFormat image's metadata block, freeing the
- * associated memory and resetting the length field to zero. This effectively removes
- * any user-provided annotations, notes, or descriptions associated with the image.
- * If this operation results in all metadata fields being empty, the entire metadata
- * block is deinitialized to avoid writing an empty metadata block to the image file.
- *
- * This function is useful when removing outdated notes, clearing test comments before
- * production deployment, sanitizing images for distribution, or resetting an image to
- * a clean metadata state for repurposing.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared comments. This is returned when:
- * - The context is valid and properly initialized
- * - The context is opened in write mode (ctx->isWriting is true)
- * - Either the metadata block was not initialized (early exit, nothing to clear)
- * - Or the comments string is freed (if it existed) and the pointer set to NULL
- * - The commentsLength field in the metadata block header is set to 0
- * - If all metadata fields are now empty, the metadata block identifier is cleared
- *
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
- * - The context parameter is NULL
- * - The context magic number doesn't match AARU_MAGIC (invalid context type)
- * - The context was not properly initialized by aaruf_create()
- *
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
- * - The image was opened with aaruf_open() instead of aaruf_create()
- * - The context's isWriting flag is false
- * - Attempting to modify a read-only image
- *
- * @note Memory Management:
- * - If ctx->comments is not NULL, the allocated memory is freed before clearing
- * - The ctx->comments pointer is set to NULL after freeing
- * - Safe to call even if comments were never set (NULL check protects against errors)
- * - No memory leaks occur when clearing previously set comments
- *
- * @note Use Cases:
- * - Removing temporary or development notes before production deployment
- * - Clearing outdated comments that no longer apply
- * - Sanitizing images for distribution by removing internal notes
- * - Resetting images for repurposing with new documentation
- * - Removing potentially sensitive information from comments
- * - Preparing images for archival with standardized, minimal metadata
- *
- * @note Metadata Block State Management:
- * - If the metadata block header is not initialized, function returns success immediately
- * - After clearing, checks if all metadata fields are empty
- * - If all fields empty, sets metadata block identifier to 0 (deinitialized)
- * - Prevents writing empty metadata blocks, optimizing storage efficiency
- *
- * @note Information Loss Considerations:
- * - Comments may contain valuable provenance or preservation information
- * - Consider archiving comments externally before clearing if they contain important data
- * - Comments might document imaging conditions, errors encountered, or quality notes
- * - Workflow history and processing information may be lost
- *
- * @warning The metadata changes are only written to the image file during aaruf_close().
- * Changes made by this function are not immediately persisted to disk.
- *
- * @warning After clearing, the comments are permanently lost unless:
- * - The image file is not closed (context remains in memory)
- * - A backup of the original image exists
- * - The comments are documented in external metadata systems
- *
- * @see aaruf_set_comments() for setting comment information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_comments(void *context)
-{
- TRACE("Entering aaruf_clear_comments(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_comments() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_comments() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_comments() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_comments() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->comments != NULL) free(ctx->comments);
-
- ctx->comments = NULL;
- ctx->metadata_block_header.commentsLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.mediaTitleLength == 0 &&
- ctx->metadata_block_header.mediaManufacturerLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
- ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
- ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_comments() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the media title or label from the image metadata.
- *
- * Removes the media title string from the AaruFormat image's metadata block, freeing
- * the associated memory and resetting the length field to zero. This effectively removes
- * any record of the title, label, or name that was printed or written on the physical
- * storage media. If this operation results in all metadata fields being empty, the
- * entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared media title.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->media_title if not NULL and sets pointer to NULL.
- * @note Metadata Block: If all fields become empty, the metadata block is deinitialized.
- * @note Use Cases: Removing physical label information, anonymizing media, or correcting errors.
- *
- * @warning Changes are only persisted during aaruf_close(). Lost unless backed up or not closed.
- *
- * @see aaruf_set_media_title() for setting media title information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_title(void *context)
-{
- TRACE("Entering aaruf_clear_media_title(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_media_title() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_media_title() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->media_title != NULL) free(ctx->media_title);
-
- ctx->media_title = NULL;
- ctx->metadata_block_header.mediaTitleLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaManufacturerLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
- ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
- ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_media_title() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the media manufacturer information from the image metadata.
- *
- * Removes the media manufacturer name string from the AaruFormat image's metadata block,
- * freeing the associated memory and resetting the length field to zero. This removes
- * any record of the company that manufactured the physical storage media. If this
- * operation results in all metadata fields being empty, the entire metadata block is
- * deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared media manufacturer.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->media_manufacturer if not NULL and sets pointer to NULL.
- * @note Preservation Impact: Removes valuable information about media quality and lifespan characteristics.
- * @note Use Cases: Anonymizing media source, removing commercial information, or correcting errors.
- *
- * @warning Loss of manufacturer information may affect preservation planning and media assessment.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_media_manufacturer() for setting media manufacturer information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_manufacturer(void *context)
-{
- TRACE("Entering aaruf_clear_media_manufacturer(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->media_manufacturer != NULL) free(ctx->media_manufacturer);
-
- ctx->media_manufacturer = NULL;
- ctx->metadata_block_header.mediaManufacturerLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
- ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
- ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the media model or product designation from the image metadata.
- *
- * Removes the media model string from the AaruFormat image's metadata block, freeing
- * the associated memory and resetting the length field to zero. This removes any record
- * of the specific model, product line, or type designation of the physical storage media.
- * If this operation results in all metadata fields being empty, the entire metadata
- * block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared media model.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->media_model if not NULL and sets pointer to NULL.
- * @note Information Loss: Removes specific capacity, speed, and compatibility information.
- * @note Use Cases: Removing product-specific details, generalizing metadata, or correcting errors.
- *
- * @warning Loss of model information may affect media compatibility assessments.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_media_model() for setting media model information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_model(void *context)
-{
- TRACE("Entering aaruf_clear_media_model(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_media_model() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_media_model() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->media_model != NULL) free(ctx->media_model);
-
- ctx->media_model = NULL;
- ctx->metadata_block_header.mediaModelLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
- ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_media_model() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the media serial number from the image metadata.
- *
- * Removes the media serial number string from the AaruFormat image's metadata block,
- * freeing the associated memory and resetting the length field to zero. This removes
- * the unique identifier assigned to the specific piece of physical storage media by
- * the manufacturer. If this operation results in all metadata fields being empty,
- * the entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared media serial number.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->media_serial_number if not NULL and sets pointer to NULL.
- * @note Forensic Impact: Removes unique identification critical for chain of custody.
- * @note Privacy: May be necessary for anonymizing specific media instances.
- * @note Use Cases: Privacy compliance, removing tracking identifiers, or correcting errors.
- *
- * @warning Loss of serial number eliminates unique media instance identification.
- * @warning May affect forensic chain of custody and authentication capabilities.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_media_serial_number() for setting media serial number information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_serial_number(void *context)
-{
- TRACE("Entering aaruf_clear_media_serial_number(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->media_serial_number != NULL) free(ctx->media_serial_number);
-
- ctx->media_serial_number = NULL;
- ctx->metadata_block_header.mediaSerialNumberLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
- ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the media barcode information from the image metadata.
- *
- * Removes the media barcode string from the AaruFormat image's metadata block, freeing
- * the associated memory and resetting the length field to zero. This removes any record
- * of the barcode affixed to the physical storage media or its packaging, typically used
- * in professional archival and library inventory systems. If this operation results in
- * all metadata fields being empty, the entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared media barcode.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->media_barcode if not NULL and sets pointer to NULL.
- * @note Inventory Impact: Removes correlation with physical media location systems.
- * @note Use Cases: Anonymizing media, removing institutional tracking, or correcting errors.
- * @note Archive Systems: May affect automated retrieval and inventory management.
- *
- * @warning Loss of barcode breaks links to physical inventory and asset management systems.
- * @warning May affect robotic tape library operations and automated retrieval.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_media_barcode() for setting media barcode information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_barcode(void *context)
-{
- TRACE("Entering aaruf_clear_media_barcode(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_media_barcode() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_media_barcode() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->media_barcode != NULL) free(ctx->media_barcode);
-
- ctx->media_barcode = NULL;
- ctx->metadata_block_header.mediaBarcodeLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
- ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_media_barcode() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the media part number or model designation from the image metadata.
- *
- * Removes the media part number string from the AaruFormat image's metadata block,
- * freeing the associated memory and resetting the length field to zero. This removes
- * the manufacturer's part number or catalog designation used for procurement and exact
- * product identification. If this operation results in all metadata fields being empty,
- * the entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared media part number.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->media_part_number if not NULL and sets pointer to NULL.
- * @note Procurement Impact: Removes exact ordering and catalog reference information.
- * @note Use Cases: Removing commercial details, generalizing metadata, or correcting errors.
- * @note Documentation: May affect ability to source compatible replacement media.
- *
- * @warning Loss of part number affects precise product identification and procurement.
- * @warning May impact ability to cross-reference with manufacturer specifications.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_media_part_number() for setting media part number information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_part_number(void *context)
-{
- TRACE("Entering aaruf_clear_media_part_number(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_media_part_number() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_media_part_number() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->media_part_number != NULL) free(ctx->media_part_number);
-
- ctx->media_part_number = NULL;
- ctx->metadata_block_header.mediaPartNumberLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
- ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_media_part_number() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the drive manufacturer information from the image metadata.
- *
- * Removes the drive manufacturer name string from the AaruFormat image's metadata block,
- * freeing the associated memory and resetting the length field to zero. This removes
- * any record of the company that manufactured the drive or device used to read or write
- * the physical storage media during the imaging process. If this operation results in
- * all metadata fields being empty, the entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared drive manufacturer.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->drive_manufacturer if not NULL and sets pointer to NULL.
- * @note Provenance Impact: Removes imaging equipment context from preservation metadata.
- * @note Use Cases: Anonymizing imaging environment, removing commercial info, or correcting errors.
- * @note Quality Assessment: May affect ability to evaluate imaging tool quality and reliability.
- *
- * @warning Loss of drive manufacturer information reduces imaging process documentation.
- * @warning May affect forensic provenance and imaging environment reconstruction.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_drive_manufacturer() for setting drive manufacturer information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_manufacturer(void *context)
-{
- TRACE("Entering aaruf_clear_drive_manufacturer(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->drive_manufacturer != NULL) free(ctx->drive_manufacturer);
-
- ctx->drive_manufacturer = NULL;
- ctx->metadata_block_header.driveManufacturerLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
- ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
- ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the drive model information from the image metadata.
- *
- * Removes the drive model string from the AaruFormat image's metadata block, freeing
- * the associated memory and resetting the length field to zero. This removes any record
- * of the specific model or product designation of the drive or device used to read or
- * write the physical storage media during the imaging process. If this operation results
- * in all metadata fields being empty, the entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared drive model.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->drive_model if not NULL and sets pointer to NULL.
- * @note Technical Context: Removes specific drive capability and feature information.
- * @note Use Cases: Anonymizing imaging equipment, simplifying metadata, or correcting errors.
- * @note Troubleshooting: May affect ability to diagnose model-specific imaging issues.
- *
- * @warning Loss of drive model information reduces imaging tool documentation completeness.
- * @warning May affect understanding of drive-specific capabilities or limitations.
- * @warning Important for reproducing imaging conditions or troubleshooting issues.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_drive_model() for setting drive model information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_model(void *context)
-{
- TRACE("Entering aaruf_clear_drive_model(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_drive_model() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_drive_model() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->drive_model != NULL) free(ctx->drive_model);
-
- ctx->drive_model = NULL;
- ctx->metadata_block_header.driveModelLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
- ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
- ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_drive_model() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the drive serial number from the image metadata.
- *
- * Removes the drive serial number string from the AaruFormat image's metadata block,
- * freeing the associated memory and resetting the length field to zero. This removes
- * the unique identifier of the specific drive or device used to read or write the
- * physical storage media during the imaging process. If this operation results in
- * all metadata fields being empty, the entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared drive serial number.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->drive_serial_number if not NULL and sets pointer to NULL.
- * @note Forensic Impact: Removes unique hardware identification from imaging provenance.
- * @note Privacy: May be necessary for anonymizing specific equipment instances.
- * @note Use Cases: Privacy compliance, equipment anonymization, or correcting errors.
- * @note Equipment Tracking: Breaks correlation with equipment maintenance and calibration records.
- *
- * @warning Loss of drive serial number eliminates unique hardware instance identification.
- * @warning May affect forensic chain of custody documentation requirements.
- * @warning Impacts ability to correlate images with specific equipment for quality analysis.
- * @warning Removes equipment tracking capability for maintenance and workload management.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_drive_serial_number() for setting drive serial number information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_serial_number(void *context)
-{
- TRACE("Entering aaruf_clear_drive_serial_number(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->drive_serial_number != NULL) free(ctx->drive_serial_number);
-
- ctx->drive_serial_number = NULL;
- ctx->metadata_block_header.driveSerialNumberLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
- ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
- ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
-
-/**
- * @brief Clears the drive firmware revision from the image metadata.
- *
- * Removes the drive firmware revision string from the AaruFormat image's metadata block,
- * freeing the associated memory and resetting the length field to zero. This removes
- * any record of the firmware version or revision of the drive or device used to read
- * or write the physical storage media during the imaging process. If this operation
- * results in all metadata fields being empty, the entire metadata block is deinitialized.
- *
- * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
- *
- * @return Returns one of the following status codes:
- * @retval AARUF_STATUS_OK (0) Successfully cleared drive firmware revision.
- * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
- * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
- *
- * @note Memory Management: Frees ctx->drive_firmware_revision if not NULL and sets pointer to NULL.
- * @note Technical Impact: Removes specific firmware behavior and capability documentation.
- * @note Use Cases: Simplifying metadata, removing technical details, or correcting errors.
- * @note Troubleshooting: May affect ability to diagnose firmware-specific issues.
- * @note Reproducibility: Reduces ability to reproduce exact imaging conditions.
- *
- * @warning Loss of firmware revision information reduces imaging environment documentation.
- * @warning Firmware versions significantly affect drive behavior and error handling.
- * @warning May affect ability to identify firmware-related imaging issues or quirks.
- * @warning Impacts scientific reproducibility and technical troubleshooting capabilities.
- * @warning Changes are only persisted during aaruf_close().
- *
- * @see aaruf_set_drive_firmware_revision() for setting drive firmware revision information.
- */
-AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_firmware_revision(void *context)
-{
- TRACE("Entering aaruf_clear_drive_firmware_revision(%p)", context);
-
- // Check context is correct AaruFormat context
- if(context == NULL)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- aaruformat_context *ctx = context;
-
- // Not a libaaruformat context
- if(ctx->magic != AARU_MAGIC)
- {
- FATAL("Invalid context");
-
- TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
- return AARUF_ERROR_NOT_AARUFORMAT;
- }
-
- // Check we are writing
- if(!ctx->is_writing)
- {
- FATAL("Trying to write a read-only image");
-
- TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_READ_ONLY");
- return AARUF_READ_ONLY;
- }
-
- if(ctx->metadata_block_header.identifier != MetadataBlock)
- {
- TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
- }
-
- if(ctx->drive_firmware_revision != NULL) free(ctx->drive_firmware_revision);
-
- ctx->drive_firmware_revision = NULL;
- ctx->metadata_block_header.driveFirmwareRevisionLength = 0;
-
- // Check if all metadata is clear
- if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
- ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
- ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
- ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
- ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
- ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveManufacturerLength == 0 &&
- ctx->metadata_block_header.driveSerialNumberLength == 0)
- ctx->metadata_block_header.identifier = 0;
-
- TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_STATUS_OK");
- return AARUF_STATUS_OK;
-}
diff --git a/src/metadata_write.c b/src/metadata_write.c
new file mode 100644
index 0000000..19584e4
--- /dev/null
+++ b/src/metadata_write.c
@@ -0,0 +1,3153 @@
+/*
+ * 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 .
+ */
+/**
+ * @file metadata_write.c
+ * @brief Write-path metadata mutators for libaaruformat.
+ *
+ * Contains all aaruf_set_* and aaruf_clear_* functions that modify metadata
+ * in an AaruFormat image context opened for writing. Read-only accessors
+ * (aaruf_get_*) are in metadata.c.
+ *
+ * @see metadata.c
+ */
+
+#include
+#include
+
+#include "aaruformat.h"
+#include "log.h"
+
+/**
+ * @brief Sets the logical CHS geometry for the AaruFormat image.
+ *
+ * Configures the Cylinder-Head-Sector (CHS) geometry information for the image being
+ * created or modified. This function populates both the geometry block (used for storage
+ * in the image file) and the image information structure (used for runtime calculations).
+ * The geometry block contains legacy-style logical addressing parameters that describe
+ * how the storage medium should be logically organized in terms of cylinders, heads
+ * (tracks per cylinder), and sectors per track. This information is crucial for creating
+ * images that will be used with software requiring CHS addressing or for accurately
+ * preserving the original medium's logical structure.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param cylinders The number of cylinders to set for the geometry.
+ * @param heads The number of heads (tracks per cylinder) to set for the geometry.
+ * @param sectors_per_track The number of sectors per track to set for the geometry.
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set geometry information. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - The geometry block identifier is set to GeometryBlock
+ * - The geometry block fields (cylinders, heads, sectorsPerTrack) are updated
+ * - The image info fields (Cylinders, Heads, SectorsPerTrack) are synchronized
+ * - All parameters are stored for subsequent write operations
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @note Dual Storage:
+ * - Geometry is stored in two locations within the context:
+ * 1. ctx->geometryBlock: Written to the image file as a GeometryBlock during close
+ * 2. ctx->imageInfo: Used for runtime calculations and metadata queries
+ * - Both locations are kept synchronized by this function
+ *
+ * @note Geometry Calculation:
+ * - Total logical sectors = cylinders × heads × sectors_per_track
+ * - Ensure the product matches the actual sector count in the image
+ * - Mismatched geometry may cause issues with legacy software or emulators
+ * - Sector size is separate and should be set via other API calls
+ *
+ * @note CHS Addressing Requirements:
+ * - Required for images intended for legacy BIOS or MBR partition schemes
+ * - Essential for floppy disk images and older hard disk images
+ * - May be optional or synthetic for modern large-capacity drives
+ * - Some virtualization platforms require valid CHS geometry
+ *
+ * @note Parameter Constraints:
+ * - No validation is performed on the geometry values
+ * - Zero values are technically accepted but may cause issues
+ * - Extremely large values may overflow in calculations (cylinders × heads × sectors_per_track)
+ * - Common constraints for legacy systems:
+ * * Cylinders: typically 1-1024 for BIOS, up to 65535 for modern systems
+ * * Heads: typically 1-255 for most systems
+ * * Sectors per track: typically 1-63 for BIOS, up to 255 for modern systems
+ *
+ * @note Write Mode Requirement:
+ * - This function is intended for use during image creation
+ * - Should be called after aaruf_create() and before writing sector data
+ * - The geometry block is serialized during aaruf_close()
+ * - Must be used with a write-enabled context
+ *
+ * @note Historical Context:
+ * - CHS geometry was the original addressing scheme for disk drives
+ * - Physical CHS reflected actual disk platters, heads, and sector layout
+ * - Logical CHS often differs from physical due to zone-bit recording and translation
+ * - Modern drives use LBA (Logical Block Addressing) internally
+ *
+ * @warning This function does not validate geometry consistency:
+ * - Does not check if cylinders × heads × sectors_per_track equals image sector count
+ * - Does not prevent overflow in the multiplication
+ * - Caller must ensure geometry values are appropriate for the medium type
+ * - Invalid geometry may cause boot failures or data access issues
+ *
+ * @warning The geometry block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ *
+ * @warning Changing geometry after writing sector data may create inconsistencies.
+ * Set geometry before beginning sector write operations for best results.
+ *
+ * @warning Some image formats and use cases don't require CHS geometry:
+ * - Optical media (CD/DVD/BD) use different addressing schemes
+ * - Modern GPT-partitioned disks don't rely on CHS
+ * - Flash-based storage typically doesn't have meaningful CHS geometry
+ * - Setting geometry for such media types is harmless but unnecessary
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_geometry(void *context, const uint32_t cylinders, const uint32_t heads,
+ const uint32_t sectors_per_track)
+{
+ TRACE("Entering aaruf_set_geometry(%p, %u, %u, %u)", context, cylinders, heads, sectors_per_track);
+
+ aaruformat_context *ctx = NULL;
+
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_geometry() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_geometry() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_write_sector() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ ctx->geometry_block.identifier = GeometryBlock;
+ ctx->geometry_block.cylinders = cylinders;
+ ctx->geometry_block.heads = heads;
+ ctx->geometry_block.sectorsPerTrack = sectors_per_track;
+ ctx->cylinders = cylinders;
+ ctx->heads = heads;
+ ctx->sectors_per_track = sectors_per_track;
+ ctx->dirty_geometry_block = true; // Mark geometry block as dirty
+
+ TRACE("Exiting aaruf_set_geometry(%p, %u, %u, %u) = AARUF_STATUS_OK", context, cylinders, heads, sectors_per_track);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the media sequence information for multi-volume media sets.
+ *
+ * Configures the sequence numbering for media that is part of a larger set, such as
+ * multi-disk software distributions, backup sets spanning multiple tapes, or optical
+ * disc sets. This function records both the current media's position in the sequence
+ * and the total number of media in the complete set. This metadata is essential for
+ * proper ordering and completeness verification when working with multi-volume archives.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param sequence The sequence number of this media (1-based index indicating position in the set).
+ * @param last_sequence The total number of media in the complete set (indicates the final sequence number).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set media sequence information. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The mediaSequence field is set to the provided sequence value
+ * - The lastMediaSequence field is set to the provided last_sequence value
+ * - Both values are stored for serialization during image close
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @note Sequence Numbering:
+ * - Sequence numbers are typically 1-based (first disc is 1, not 0)
+ * - The sequence parameter should be in the range [1, last_sequence]
+ * - last_sequence indicates the total count of media in the set
+ * - Example: For a 3-disc set, disc 2 would have sequence=2, last_sequence=3
+ *
+ * @note Common Use Cases:
+ * - Multi-CD/DVD software installations (e.g., "Disc 2 of 4")
+ * - Backup tape sets spanning multiple volumes
+ * - Split archive formats requiring sequential processing
+ * - Multi-floppy disk software distributions
+ * - Large data sets divided across multiple optical discs
+ *
+ * @note Metadata Block Initialization:
+ * - If the metadata block header is not yet initialized, this function initializes it
+ * - The metadataBlockHeader.identifier is set to MetadataBlock automatically
+ * - Multiple metadata setter functions can be called to build complete metadata
+ * - All metadata is written to the image file during aaruf_close()
+ *
+ * @note Single Media Images:
+ * - For standalone media not part of a set, use sequence=1, last_sequence=1
+ * - Setting both values to 0 may be used to indicate "not part of a sequence"
+ * - The function does not validate that sequence <= last_sequence
+ *
+ * @note Parameter Validation:
+ * - No validation is performed on sequence numbers
+ * - Negative values are accepted but may be semantically incorrect
+ * - sequence > last_sequence is not prevented but indicates an error condition
+ * - Callers should ensure sequence and last_sequence are logically consistent
+ *
+ * @note Archive Integrity:
+ * - Proper sequence metadata is crucial for multi-volume restoration
+ * - Archival software may refuse to extract if sequence information is incorrect
+ * - Missing volumes can be detected by checking sequence completeness
+ * - Helps prevent data loss from incomplete multi-volume sets
+ *
+ * @note Historical Context:
+ * - Multi-volume sets were common in the floppy disk era due to size constraints
+ * - CD/DVD sets were used for large software distributions (operating systems, games)
+ * - Tape backup systems still use multi-volume sets for large archives
+ * - Modern optical media (BD-R DL) reduced the need for multi-disc sets
+ *
+ * @warning This function does not validate the logical consistency of sequence numbers:
+ * - Does not check if sequence <= last_sequence
+ * - Does not prevent negative or zero values if semantically inappropriate
+ * - Caller must ensure values represent a valid sequence relationship
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ *
+ * @warning Incorrect sequence information may prevent proper reconstruction:
+ * - Software relying on sequence numbers may fail to recognize media order
+ * - Archival systems may incorrectly report missing volumes
+ * - Restoration processes may fail if sequence is inconsistent
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_media_sequence(void *context, const int32_t sequence,
+ const int32_t last_sequence)
+{
+ TRACE("Entering aaruf_set_media_sequence(%p, %d, %d)", context, sequence, last_sequence);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_media_sequence() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ ctx->metadata_block_header.mediaSequence = sequence;
+ ctx->metadata_block_header.lastMediaSequence = last_sequence;
+
+ TRACE("Exiting aaruf_set_media_sequence(%p, %d, %d) = AARUF_STATUS_OK", context, sequence, last_sequence);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the creator (person/operator) information for the image.
+ *
+ * Records the name of the person or operator who created the AaruFormat image. This
+ * metadata identifies the individual responsible for the imaging process, which is
+ * valuable for provenance tracking, accountability, and understanding the human context
+ * in which the image was created. The creator name is stored in UTF-16LE encoding and
+ * preserved exactly as provided by the caller.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the creator name string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the creator data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set creator information. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the creator string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The creator data is copied to ctx->imageInfo.Creator
+ * - The creatorLength field is set in the metadata block header
+ * - Any previous creator string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the creator string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note UTF-16LE Encoding:
+ * - The data parameter must contain a valid UTF-16LE encoded string
+ * - Length must be in bytes, not character count (UTF-16LE uses 2 or 4 bytes per character)
+ * - The library treats the data as opaque and does not validate UTF-16LE encoding
+ * - Null termination is not required; length specifies the exact byte count
+ * - Ensure even byte lengths to maintain UTF-16LE character alignment
+ *
+ * @note Creator Name Format:
+ * - Typically contains the full name of the person who created the image
+ * - May include titles, credentials, or institutional affiliations
+ * - Common formats: "John Smith", "Dr. Jane Doe", "Smith, John (Archivist)"
+ * - Should identify the individual operator, not the software used
+ * - May include contact information or employee/operator ID in institutional settings
+ *
+ * @note Provenance and Accountability:
+ * - Identifies who performed the imaging operation
+ * - Important for establishing chain of custody in forensic contexts
+ * - Provides contact point for questions about the imaging process
+ * - Supports institutional recordkeeping and quality assurance
+ * - May be required for compliance with archival standards
+ *
+ * @note Privacy Considerations:
+ * - Consider privacy implications when recording personal names
+ * - Some organizations may use operator IDs instead of full names
+ * - Institutional policies may govern what personal information is recorded
+ * - GDPR and similar regulations may apply in some jurisdictions
+ *
+ * @note Memory Management:
+ * - The function allocates a new buffer and copies the data
+ * - If a previous creator string exists, it is freed before replacement
+ * - The caller retains ownership of the input data buffer
+ * - The allocated memory is freed when the context is closed or destroyed
+ *
+ * @note Metadata Block Initialization:
+ * - If the metadata block header is not yet initialized, this function initializes it
+ * - The metadataBlockHeader.identifier is set to MetadataBlock automatically
+ * - Multiple metadata setter functions can be called to build complete metadata
+ *
+ * @warning The data buffer must remain valid for the duration of this function call.
+ * After the function returns, the caller may free or reuse the data buffer.
+ *
+ * @warning Invalid UTF-16LE encoding may cause issues when reading the metadata:
+ * - The library does not validate UTF-16LE correctness
+ * - Malformed strings may display incorrectly or cause decoding errors
+ * - Ensure the data is properly encoded before calling this function
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_creator(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_creator(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_creator() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_creator() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_creator() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for creator");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->creator != NULL) free(ctx->creator);
+ ctx->creator = copy;
+ ctx->metadata_block_header.creatorLength = length;
+
+ TRACE("Exiting aaruf_set_creator(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets user comments or notes for the image.
+ *
+ * Records arbitrary user-provided comments, notes, or annotations associated with the
+ * AaruFormat image. This metadata field allows users to document the image's purpose,
+ * provenance, condition, or any other relevant information. Comments are stored in
+ * UTF-16LE encoding and can contain multi-line text, special characters, and detailed
+ * descriptions.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the comments string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the comments data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set comments. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the comments string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The comments data is copied to ctx->imageInfo.Comments
+ * - The commentsLength field is set in the metadata block header
+ * - Any previous comments string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the comments string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note UTF-16LE Encoding:
+ * - The data parameter must contain a valid UTF-16LE encoded string
+ * - Length must be in bytes, not character count
+ * - The library treats the data as opaque and does not validate encoding
+ * - Null termination is not required; length specifies the exact byte count
+ *
+ * @note Common Uses for Comments:
+ * - Documentation of image source and creation date
+ * - Notes about media condition or read errors encountered
+ * - Preservation metadata and archival notes
+ * - User annotations for organizing image collections
+ * - Workflow status or processing history
+ *
+ * @note Memory Management:
+ * - The function allocates a new buffer and copies the data
+ * - If previous comments exist, they are freed before replacement
+ * - The caller retains ownership of the input data buffer
+ * - The allocated memory is freed when the context is closed or destroyed
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_comments(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_comments(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_comments() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_comments() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_comments() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for comments");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->comments != NULL) free(ctx->comments);
+ ctx->comments = copy;
+ ctx->metadata_block_header.commentsLength = length;
+
+ TRACE("Exiting aaruf_set_comments(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the media title or label for the image.
+ *
+ * Records the title, label, or name printed or written on the physical storage media.
+ * This metadata is particularly useful for identifying discs, tapes, or other media
+ * that have user-applied labels or manufacturer-printed titles. The title is stored
+ * in UTF-16LE encoding to support international characters and special symbols.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the media title string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the media title data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set media title. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the media title string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The media title data is copied to ctx->imageInfo.MediaTitle
+ * - The mediaTitleLength field is set in the metadata block header
+ * - Any previous media title string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the media title string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Common Media Title Examples:
+ * - Handwritten labels on optical discs or tapes
+ * - Pre-printed software names on distribution media (e.g., "Windows 95 Setup Disk 1")
+ * - Volume labels or disc names (e.g., "BACKUP_2024", "INSTALL_CD")
+ * - Game titles printed on cartridges or discs
+ * - Album or movie titles on multimedia discs
+ *
+ * @note Preservation Context:
+ * - Important for archival purposes to record exactly what appears on the media
+ * - Helps identify media in large collections
+ * - May differ from filesystem volume labels
+ * - Useful for matching physical media to digital images
+ *
+ * @note UTF-16LE Encoding:
+ * - The data parameter must contain a valid UTF-16LE encoded string
+ * - Length must be in bytes, not character count
+ * - Supports international characters, emoji, and special symbols
+ * - Null termination is not required; length specifies the exact byte count
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_media_title(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_media_title(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_media_title() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for media title");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->media_title != NULL) free(ctx->media_title);
+ ctx->media_title = copy;
+ ctx->metadata_block_header.mediaTitleLength = length;
+ ctx->dirty_metadata_block = true; // Mark metadata block as dirty
+
+ TRACE("Exiting aaruf_set_media_title(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the media manufacturer information for the image.
+ *
+ * Records the name of the company that manufactured the physical storage media.
+ * This metadata is valuable for preservation and forensic purposes, as it can help
+ * identify the media type, quality characteristics, and manufacturing period. The
+ * manufacturer name is stored in UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the media manufacturer string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the media manufacturer data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set media manufacturer. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the media manufacturer string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The media manufacturer data is copied to ctx->imageInfo.MediaManufacturer
+ * - The mediaManufacturerLength field is set in the metadata block header
+ * - Any previous media manufacturer string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the media manufacturer string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Common Media Manufacturers:
+ * - Optical discs: Verbatim, Sony, Maxell, TDK, Taiyo Yuden
+ * - Magnetic tapes: Fujifilm, Maxell, Sony, IBM
+ * - Floppy disks: 3M, Maxell, Sony, Verbatim
+ * - Flash media: SanDisk, Kingston, Samsung
+ *
+ * @note Identification Methods:
+ * - May be printed on the media surface or packaging
+ * - Can sometimes be detected from media ID codes (e.g., ATIP for CD-R)
+ * - Historical records or catalogs may provide this information
+ * - Important for understanding media quality and longevity characteristics
+ *
+ * @note Preservation Value:
+ * - Helps assess expected media lifespan and degradation patterns
+ * - Useful for identifying counterfeit or remarked media
+ * - Aids in research about media quality and failure modes
+ * - Provides context for archival planning and migration strategies
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_media_manufacturer(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_media_manufacturer(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_media_manufacturer() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for media manufacturer");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->media_manufacturer != NULL) free(ctx->media_manufacturer);
+ ctx->media_manufacturer = copy;
+ ctx->metadata_block_header.mediaManufacturerLength = length;
+
+ TRACE("Exiting aaruf_set_media_manufacturer(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the media model or product designation for the image.
+ *
+ * Records the specific model, product line, or type designation of the physical storage
+ * media. This is more specific than the manufacturer and identifies the exact product
+ * variant. This metadata helps in identifying specific media characteristics, performance
+ * specifications, and compatibility information. The model information is stored in
+ * UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the media model string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the media model data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set media model. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the media model string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The media model data is copied to ctx->imageInfo.MediaModel
+ * - The mediaModelLength field is set in the metadata block header
+ * - Any previous media model string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the media model string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Model Designation Examples:
+ * - Optical discs: "DVD+R 16x", "CD-R 80min", "BD-R DL 50GB"
+ * - Tapes: "LTO-7", "DLT-IV", "AIT-3"
+ * - Floppy disks: "HD 1.44MB", "DD 720KB"
+ * - Flash cards: "SDHC Class 10", "CompactFlash 1000x"
+ *
+ * @note Model Information Usage:
+ * - Identifies specific capacity and speed ratings
+ * - Indicates format compatibility (e.g., DVD-R vs DVD+R)
+ * - Helps determine recording characteristics and quality tier
+ * - Useful for matching replacement media or troubleshooting issues
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_media_model(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_media_model(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_media_model() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for media model");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->media_model != NULL) free(ctx->media_model);
+ ctx->media_model = copy;
+ ctx->metadata_block_header.mediaModelLength = length;
+
+ TRACE("Exiting aaruf_set_media_model(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the media serial number for the image.
+ *
+ * Records the unique serial number assigned to the physical storage media by the
+ * manufacturer. This metadata provides a unique identifier for the specific piece of
+ * media, which is invaluable for tracking, authentication, and forensic analysis. Not
+ * all media types have serial numbers; this is most common with professional-grade
+ * media and some consumer optical discs. The serial number is stored in UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the media serial number string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the media serial number data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set media serial number. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the media serial number string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The media serial number data is copied to ctx->imageInfo.MediaSerialNumber
+ * - The mediaSerialNumberLength field is set in the metadata block header
+ * - Any previous media serial number string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the media serial number string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Serial Number Availability:
+ * - Professional tape media (LTO, DLT, etc.) typically have printed serial numbers
+ * - Some optical discs have embedded media IDs that can serve as serial numbers
+ * - Hard drives and SSDs have electronically-readable serial numbers
+ * - Consumer recordable media (CD-R, DVD-R) rarely have unique serial numbers
+ * - May be printed on labels, hubs, or cartridge shells
+ *
+ * @note Forensic and Archival Importance:
+ * - Uniquely identifies the specific physical media instance
+ * - Critical for chain of custody in forensic investigations
+ * - Enables tracking of media throughout its lifecycle
+ * - Helps prevent mix-ups in large media collections
+ * - Can verify authenticity and detect counterfeits
+ *
+ * @note Format Considerations:
+ * - Serial numbers may be alphanumeric, numeric, or contain special characters
+ * - Format varies widely between manufacturers and media types
+ * - May include check digits or formatting separators
+ * - Should be recorded exactly as it appears on the media
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_media_serial_number(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_media_serial_number(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_media_serial_number() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for media serial number");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->media_serial_number != NULL) free(ctx->media_serial_number);
+ ctx->media_serial_number = copy;
+ ctx->metadata_block_header.mediaSerialNumberLength = length;
+
+ TRACE("Exiting aaruf_set_media_serial_number(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the media barcode information for the image.
+ *
+ * Records the barcode affixed to the physical storage media or its packaging. Barcodes
+ * are commonly used in professional archival and library environments for automated
+ * inventory management, tracking, and retrieval systems. This metadata enables correlation
+ * between physical media location systems and digital image files. The barcode is stored
+ * in UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the media barcode string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the media barcode data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set media barcode. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the media barcode string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The media barcode data is copied to ctx->imageInfo.MediaBarcode
+ * - The mediaBarcodeLength field is set in the metadata block header
+ * - Any previous media barcode string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the media barcode string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Common Barcode Uses:
+ * - Library and archival tape management systems
+ * - Automated tape library robotics (e.g., LTO tape cartridges)
+ * - Inventory tracking in large media collections
+ * - Asset management in corporate or institutional settings
+ * - Chain of custody tracking in forensic environments
+ *
+ * @note Barcode Types and Formats:
+ * - Code 39 and Code 128 are common for media labeling
+ * - LTO tapes use specific 6 or 8-character barcode formats
+ * - May include library-specific prefixes or location codes
+ * - Some systems use 2D barcodes (QR codes, Data Matrix)
+ * - Barcode should be recorded exactly as it appears
+ *
+ * @note Integration with Physical Systems:
+ * - Enables automated correlation between physical and digital catalogs
+ * - Supports robotic tape library operations
+ * - Facilitates retrieval from off-site storage facilities
+ * - Links to broader asset management databases
+ * - Critical for large-scale archival operations
+ *
+ * @note Preservation Context:
+ * - Important for long-term archival planning
+ * - Helps maintain inventory accuracy over time
+ * - Supports audit and compliance requirements
+ * - Enables efficient physical media location and retrieval
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_media_barcode(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_media_barcode(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_media_barcode() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for media barcode");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->media_barcode != NULL) free(ctx->media_barcode);
+ ctx->media_barcode = copy;
+ ctx->metadata_block_header.mediaBarcodeLength = length;
+
+ TRACE("Exiting aaruf_set_media_barcode(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the media part number or model designation for the image.
+ *
+ * Records the manufacturer's part number or catalog designation for the specific type
+ * of physical storage media. This is distinct from the media model in that it represents
+ * the exact ordering or catalog number used for procurement and inventory purposes. Part
+ * numbers are particularly important for sourcing compatible replacement media and for
+ * precise identification in technical documentation. The part number is stored in UTF-16LE
+ * encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the media part number string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the media part number data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set media part number. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the media part number string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The media part number data is copied to ctx->imageInfo.MediaPartNumber
+ * - The mediaPartNumberLength field is set in the metadata block header
+ * - Any previous media part number string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the media part number string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Part Number Examples:
+ * - Optical media: "MR-25332" (Verbatim DVD+R), "CDR80JC" (Sony CD-R)
+ * - Tape media: "C7973A" (HP LTO-3), "TK88" (Maxell DLT-IV)
+ * - Floppy disks: "MF2HD" (3.5" high-density), "2D" (5.25" double-density)
+ * - May include regional variations or packaging size indicators
+ *
+ * @note Practical Applications:
+ * - Procurement and ordering of compatible replacement media
+ * - Cross-referencing with manufacturer specifications and datasheets
+ * - Identifying specific product revisions or manufacturing batches
+ * - Ensuring compatibility for archival media migration projects
+ * - Tracking costs and suppliers in institutional settings
+ *
+ * @note Relationship to Model:
+ * - Part number is more specific than model designation
+ * - Model might be "DVD+R 16x", part number "MR-25332"
+ * - Part numbers may vary by region, packaging quantity, or color
+ * - Critical for exact product identification in catalogs and databases
+ *
+ * @note Documentation and Compliance:
+ * - Useful for creating detailed preservation documentation
+ * - Supports compliance with archival standards and best practices
+ * - Enables precise replication of archival environments
+ * - Facilitates research on media types and failure modes
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_media_part_number(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_media_part_number(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_media_part_number() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for creator");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->media_part_number != NULL) free(ctx->media_part_number);
+ ctx->media_part_number = copy;
+ ctx->metadata_block_header.mediaPartNumberLength = length;
+
+ TRACE("Exiting aaruf_set_media_part_number(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the drive manufacturer information for the image.
+ *
+ * Records the name of the company that manufactured the drive or device used to read
+ * or write the physical storage media. This metadata provides valuable context about
+ * the imaging process, as different drives may have different capabilities, error
+ * handling characteristics, and compatibility with specific media types. The manufacturer
+ * name is stored in UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the drive manufacturer string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the drive manufacturer data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set drive manufacturer. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the drive manufacturer string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The drive manufacturer data is copied to ctx->imageInfo.DriveManufacturer
+ * - The driveManufacturerLength field is set in the metadata block header
+ * - Any previous drive manufacturer string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the drive manufacturer string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Common Drive Manufacturers:
+ * - Optical drives: Pioneer, Plextor, LG, ASUS, Sony, Samsung
+ * - Tape drives: HP, IBM, Quantum, Tandberg, Exabyte
+ * - Hard drives: Seagate, Western Digital, Hitachi, Toshiba
+ * - Floppy drives: Teac, Panasonic, Mitsumi, Sony
+ *
+ * @note Imaging Context and Quality:
+ * - Different manufacturers have varying error recovery capabilities
+ * - Some drives are better suited for archival-quality imaging
+ * - Plextor drives were historically preferred for optical disc preservation
+ * - Professional-grade drives often have better read accuracy
+ * - Important for understanding potential limitations in the imaging process
+ *
+ * @note Forensic and Provenance Value:
+ * - Documents the complete imaging environment
+ * - Helps assess reliability and trustworthiness of the image
+ * - Useful for troubleshooting or reproducing imaging results
+ * - May be required for forensic chain of custody
+ * - Supports quality assurance and validation processes
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_manufacturer(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_drive_manufacturer(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_drive_manufacturer() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for drive manufacturer");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->drive_manufacturer != NULL) free(ctx->drive_manufacturer);
+ ctx->drive_manufacturer = copy;
+ ctx->metadata_block_header.driveManufacturerLength = length;
+
+ TRACE("Exiting aaruf_set_drive_manufacturer(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the drive model information for the image.
+ *
+ * Records the specific model or product designation of the drive or device used to read
+ * or write the physical storage media. This metadata provides detailed information about
+ * the imaging equipment, which can be important for understanding the capabilities,
+ * limitations, and characteristics of the imaging process. Different drive models within
+ * the same manufacturer's product line may have significantly different features and
+ * performance characteristics. The model information is stored in UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the drive model string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the drive model data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set drive model. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the drive model string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The drive model data is copied to ctx->imageInfo.DriveModel
+ * - The driveModelLength field is set in the metadata block header
+ * - Any previous drive model string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the drive model string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Drive Model Examples:
+ * - Optical drives: "DVR-111D" (Pioneer), "PX-716A" (Plextor), "GH24NSB0" (LG)
+ * - Tape drives: "Ultrium 7-SCSI" (HP), "TS1140" (IBM), "SDLT600" (Quantum)
+ * - Hard drives: "ST2000DM008" (Seagate), "WD40EZRZ" (Western Digital)
+ * - Floppy drives: "FD-235HF" (Teac), "JU-257A633P" (Panasonic)
+ *
+ * @note Model-Specific Characteristics:
+ * - Different models may have different error correction algorithms
+ * - Some models are known for superior read quality (e.g., Plextor Premium)
+ * - Certain models may have bugs or quirks in specific firmware versions
+ * - Professional models often have features not available in consumer versions
+ * - Important for reproducing imaging conditions or troubleshooting issues
+ *
+ * @note Forensic Documentation:
+ * - Complete drive identification aids in forensic reporting
+ * - Helps establish the reliability of the imaging process
+ * - May be required for compliance with forensic standards
+ * - Supports validation and verification procedures
+ * - Enables assessment of tool suitability for the imaging task
+ *
+ * @note Historical and Research Value:
+ * - Documents evolution of imaging technology over time
+ * - Helps identify best practices for specific media types
+ * - Useful for academic research on digital preservation
+ * - Aids in understanding drive availability and obsolescence
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_model(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_drive_model(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_drive_model() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for media model");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->drive_model != NULL) free(ctx->drive_model);
+ ctx->drive_model = copy;
+ ctx->metadata_block_header.driveModelLength = length;
+
+ TRACE("Exiting aaruf_set_drive_model(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the drive serial number for the image.
+ *
+ * Records the unique serial number of the drive or device used to read or write the
+ * physical storage media. This metadata provides a unique identifier for the specific
+ * piece of hardware used in the imaging process, which is particularly important for
+ * forensic work, equipment tracking, and quality assurance. The serial number enables
+ * correlation between multiple images created with the same drive and can help identify
+ * drive-specific issues or characteristics. The serial number is stored in UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the drive serial number string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the drive serial number data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set drive serial number. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the drive serial number string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The drive serial number data is copied to ctx->imageInfo.DriveSerialNumber
+ * - The driveSerialNumberLength field is set in the metadata block header
+ * - Any previous drive serial number string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the drive serial number string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Serial Number Sources:
+ * - Hard drives and SSDs: Retrieved via ATA/SCSI IDENTIFY commands
+ * - Optical drives: Available through SCSI inquiry or ATA identify
+ * - Tape drives: Typically reported via SCSI inquiry data
+ * - USB devices: May have USB serial numbers or internal device serials
+ * - Some older or consumer devices may not report serial numbers
+ *
+ * @note Forensic Applications:
+ * - Critical for forensic chain of custody documentation
+ * - Uniquely identifies the specific hardware used for imaging
+ * - Enables tracking of drive calibration and maintenance history
+ * - Supports correlation of images created with the same equipment
+ * - May be required by forensic standards and best practices
+ *
+ * @note Equipment Management:
+ * - Helps track drive usage and workload for maintenance planning
+ * - Enables identification of drives requiring replacement or service
+ * - Supports equipment inventory and asset management systems
+ * - Useful for identifying drives with known issues or recalls
+ * - Facilitates warranty and support claim processing
+ *
+ * @note Quality Assurance:
+ * - Enables analysis of drive-specific error patterns
+ * - Helps identify if multiple imaging issues stem from the same drive
+ * - Supports statistical quality control processes
+ * - Aids in evaluating drive reliability over time
+ * - Can reveal degradation or calibration drift in aging hardware
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_serial_number(void *context, const uint8_t *data, const int32_t length)
+{
+ TRACE("Entering aaruf_set_drive_serial_number(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_drive_serial_number() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for drive serial number");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->drive_serial_number != NULL) free(ctx->drive_serial_number);
+ ctx->drive_serial_number = copy;
+ ctx->metadata_block_header.driveSerialNumberLength = length;
+
+ TRACE("Exiting aaruf_set_drive_serial_number(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the drive firmware revision for the image.
+ *
+ * Records the firmware version or revision of the drive or device used to read or write
+ * the physical storage media. Firmware revisions can significantly affect drive behavior,
+ * error handling, performance, and compatibility. This metadata is crucial for understanding
+ * the imaging environment, troubleshooting issues, and ensuring reproducibility. Different
+ * firmware versions of the same drive model can behave quite differently, making this
+ * information essential for comprehensive documentation. The firmware revision is stored
+ * in UTF-16LE encoding.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the drive firmware revision string data in UTF-16LE encoding (opaque byte array).
+ * @param length Length of the drive firmware revision data in bytes (must include full UTF-16LE character sequences).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set drive firmware revision. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the drive firmware revision string succeeded
+ * - The metadata block header is initialized (identifier set to MetadataBlock)
+ * - The drive firmware revision data is copied to ctx->imageInfo.DriveFirmwareRevision
+ * - The driveFirmwareRevisionLength field is set in the metadata block header
+ * - Any previous drive firmware revision string is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the drive firmware revision string
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Firmware Revision Examples:
+ * - Optical drives: "1.07", "1.00a", "VER A302"
+ * - Tape drives: "B8S1", "7760", "V4.0"
+ * - Hard drives: "CC45", "80.00A80", "HPG9"
+ * - Format varies by manufacturer and device type
+ *
+ * @note Firmware Impact on Imaging:
+ * - Different firmware versions may have different error recovery strategies
+ * - Bug fixes in newer firmware can improve read reliability
+ * - Some firmware versions have known issues with specific media types
+ * - Performance characteristics may vary between firmware revisions
+ * - Firmware can affect features like C2 error reporting on optical drives
+ *
+ * @note Troubleshooting and Support:
+ * - Essential for diagnosing drive-specific problems
+ * - Manufacturer support often requires firmware version information
+ * - Helps identify if issues are resolved in newer firmware
+ * - Enables correlation of problems with known firmware bugs
+ * - Supports decision-making about firmware updates
+ *
+ * @note Reproducibility and Documentation:
+ * - Complete environment documentation for scientific reproducibility
+ * - Important for forensic work requiring detailed equipment records
+ * - Helps explain variations in imaging results over time
+ * - Supports compliance with archival and preservation standards
+ * - Enables future researchers to understand imaging conditions
+ *
+ * @note Historical Tracking:
+ * - Documents firmware changes over the life of imaging equipment
+ * - Helps assess impact of firmware updates on imaging quality
+ * - Useful for long-term archival projects spanning years
+ * - Aids in understanding evolution of drive technology
+ *
+ * @warning The metadata block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted.
+ *
+ * @warning Firmware revisions are device-specific and format varies widely:
+ * - No standard format exists across manufacturers
+ * - May include letters, numbers, dots, or other characters
+ * - Should be recorded exactly as reported by the device
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_firmware_revision(void *context, const uint8_t *data,
+ const int32_t length)
+{
+ TRACE("Entering aaruf_set_drive_firmware_revision(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_drive_firmware_revision() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Initialize
+ if(ctx->metadata_block_header.identifier != MetadataBlock) ctx->metadata_block_header.identifier = MetadataBlock;
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for creator");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-16LE string
+ memcpy(copy, data, length);
+ if(ctx->drive_firmware_revision != NULL) free(ctx->drive_firmware_revision);
+ ctx->drive_firmware_revision = copy;
+ ctx->metadata_block_header.driveFirmwareRevisionLength = length;
+
+ TRACE("Exiting aaruf_set_drive_firmware_revision(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Sets the Aaru metadata JSON for the image during creation.
+ *
+ * Embeds Aaru metadata JSON into the image being created. The Aaru metadata JSON format is a
+ * structured, machine-readable representation of comprehensive image metadata including media
+ * information, imaging session details, hardware configuration, optical disc tracks and sessions,
+ * checksums, and preservation metadata. This function stores the JSON payload in its original form
+ * without parsing or validation, allowing callers to provide pre-generated JSON conforming to the
+ * Aaru metadata schema. The JSON data will be written to the image file during aaruf_close() as
+ * an AaruMetadataJsonBlock.
+ *
+ * The function accepts raw UTF-8 encoded JSON data as an opaque byte array and creates an internal
+ * copy that persists for the lifetime of the context. If Aaru JSON metadata was previously set on
+ * this context, the old data is freed and replaced with the new JSON. The JSON is treated as opaque
+ * binary data by the library; no parsing, interpretation, or schema validation is performed during
+ * the set operation.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ * @param data Pointer to the Aaru metadata JSON data in UTF-8 encoding (opaque byte array).
+ * The JSON should conform to the Aaru metadata schema, though this is not validated.
+ * Must not be NULL.
+ * @param length Length of the JSON data in bytes. The payload may or may not be null-terminated;
+ * the length should reflect the actual JSON data size.
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully set Aaru metadata JSON. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Memory allocation for the JSON data succeeded
+ * - The JSON data is copied to ctx->jsonBlock
+ * - The jsonBlockHeader is initialized with identifier AaruMetadataJsonBlock
+ * - The jsonBlockHeader.length field is set to the provided length
+ * - Any previous Aaru JSON data is properly freed before replacement
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @retval AARUF_ERROR_NOT_ENOUGH_MEMORY (-9) Memory allocation failed. This occurs when:
+ * - malloc() failed to allocate the required memory for the JSON data
+ * - System is out of memory or memory is severely fragmented
+ * - The requested allocation size is too large
+ *
+ * @note Aaru JSON Format and Encoding:
+ * - The JSON payload must be valid UTF-8 encoded data
+ * - The payload may or may not be null-terminated
+ * - The library treats the JSON as opaque binary data
+ * - No JSON parsing, interpretation, or validation is performed during set
+ * - Schema compliance is the caller's responsibility
+ * - Ensure the JSON conforms to the Aaru metadata schema for compatibility
+ *
+ * @note Aaru Metadata JSON Purpose:
+ * - Provides machine-readable structured metadata using modern JSON format
+ * - Includes comprehensive information about media, sessions, tracks, and checksums
+ * - Enables programmatic access to metadata without XML parsing overhead
+ * - Documents imaging session details, hardware configuration, and preservation data
+ * - Used by Aaru and compatible tools for metadata exchange and analysis
+ * - Complements or serves as alternative to CICM XML metadata
+ *
+ * @note JSON Content Examples:
+ * - Media type and physical characteristics
+ * - Track and session information for optical media
+ * - Partition and filesystem metadata
+ * - Checksums (MD5, SHA-1, SHA-256, etc.) for integrity verification
+ * - Hardware information (drive manufacturer, model, firmware)
+ * - Imaging software version and configuration
+ * - Timestamps for image creation and modification
+ *
+ * @note Memory Management:
+ * - The function creates an internal copy of the JSON data
+ * - The caller retains ownership of the input data buffer
+ * - The caller may free the input data immediately after this function returns
+ * - The internal copy is freed automatically during aaruf_close()
+ * - Calling this function multiple times replaces previous JSON data
+ *
+ * @note Relationship to CICM XML:
+ * - Both CICM XML and Aaru JSON can be set on the same image
+ * - CICM XML follows the Canary Islands Computer Museum schema (older format)
+ * - Aaru JSON follows the Aaru-specific metadata schema (newer format)
+ * - Setting one does not affect the other
+ * - Different tools may prefer one format over the other
+ * - Consider including both for maximum compatibility
+ *
+ * @warning The Aaru JSON block is only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted to disk.
+ *
+ * @warning No validation is performed on the JSON data:
+ * - Invalid JSON syntax will be stored and only detected during parsing
+ * - Schema violations will not be caught by this function
+ * - Ensure JSON is valid and schema-compliant before calling
+ * - Use a JSON validation library before embedding if correctness is critical
+ *
+ * @warning The function accepts any length value:
+ * - Ensure the length accurately reflects the JSON data size
+ * - Incorrect length values may cause truncation or include garbage data
+ * - For null-terminated JSON, length should not include the null terminator
+ * unless it is intended to be part of the stored data
+ *
+ * @see AaruMetadataJsonBlockHeader for the on-disk structure definition.
+ * @see aaruf_get_aaru_json_metadata() for retrieving Aaru JSON from opened images.
+ * @see write_aaru_json_block() for the serialization process during image closing.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_set_aaru_json_metadata(void *context, uint8_t *data, size_t length)
+{
+ TRACE("Entering aaruf_set_aaru_json_metadata(%p, %p, %d)", context, data, length);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_aaru_json_metadata() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_set_aaru_json_metadata() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_set_aaru_json_metadata() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ // Reserve memory
+ uint8_t *copy = malloc(length);
+ if(copy == NULL)
+ {
+ FATAL("Could not allocate memory for Aaru metadata JSON");
+ return AARUF_ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ // Copy opaque UTF-8 string
+ memcpy(copy, data, length);
+ if(ctx->json_block != NULL) free(ctx->json_block);
+ ctx->json_block = copy;
+ ctx->json_block_header.identifier = AaruMetadataJsonBlock;
+ ctx->json_block_header.length = (uint32_t)length;
+ ctx->dirty_json_block = true; // Mark JSON block as dirty
+
+ TRACE("Exiting aaruf_set_aaru_json_metadata(%p, %p, %d) = AARUF_STATUS_OK", context, data, length);
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the media sequence information from the image metadata.
+ *
+ * Removes the media sequence and last media sequence fields from the AaruFormat image's
+ * metadata block, effectively removing any indication that this media is part of a
+ * multi-volume set. Both the current sequence number and the total sequence count are
+ * reset to zero. If this operation results in all metadata fields being empty, the
+ * entire metadata block is deinitialized (identifier set to 0) to avoid writing an
+ * empty metadata block to the image file.
+ *
+ * This function is useful when repurposing an image that was originally part of a
+ * multi-disc set but is now being treated as standalone media, or when correcting
+ * metadata that was set incorrectly.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared media sequence information. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Either the metadata block was not initialized (early exit, nothing to clear)
+ * - Or the mediaSequence and lastMediaSequence fields are set to 0
+ * - If all metadata fields are now empty, the metadata block identifier is cleared
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @note Metadata Block State Management:
+ * - If the metadata block header is not initialized (identifier != MetadataBlock),
+ * the function returns successfully without any action (nothing to clear)
+ * - After clearing, if all metadata fields are empty, the metadata block header
+ * identifier is set to 0, preventing an empty block from being written
+ * - This automatic cleanup ensures efficient storage and avoids unnecessary blocks
+ *
+ * @note Sequence Field Reset:
+ * - Both mediaSequence and lastMediaSequence are set to 0
+ * - Zero values typically indicate "not part of a sequence" or "unknown sequence"
+ * - The function does not differentiate between never-set and explicitly-cleared
+ *
+ * @note Use Cases:
+ * - Correcting incorrectly set sequence metadata
+ * - Converting multi-volume images to standalone format
+ * - Removing obsolete sequence information during image repurposing
+ * - Cleaning up test or development images
+ *
+ * @note Relationship to Other Metadata:
+ * - This function only affects sequence fields; other metadata is preserved
+ * - Use aaruf_set_media_sequence() to set new sequence values after clearing
+ * - If reconstructing multi-volume metadata, set sequence before other fields
+ *
+ * @warning The metadata changes are only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted to disk.
+ *
+ * @warning After clearing, the sequence information is permanently lost unless:
+ * - The image file is not closed (context remains in memory)
+ * - A backup of the original image exists
+ * - The information is reconstructed from external sources
+ *
+ * @see aaruf_set_media_sequence() for setting sequence information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_sequence(void *context)
+{
+ TRACE("Entering aaruf_clear_media_sequence(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_sequence() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_media_sequence() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_media_sequence() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ ctx->metadata_block_header.mediaSequence = 0;
+ ctx->metadata_block_header.lastMediaSequence = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
+ ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
+ ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_media_sequence() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the creator (person/operator) information from the image metadata.
+ *
+ * Removes the creator name string from the AaruFormat image's metadata block, freeing
+ * the associated memory and resetting the length field to zero. This effectively removes
+ * any record of who created the image. If this operation results in all metadata fields
+ * being empty, the entire metadata block is deinitialized to avoid writing an empty
+ * metadata block to the image file.
+ *
+ * This function is useful when anonymizing images for distribution, removing personally
+ * identifiable information for privacy compliance (e.g., GDPR), or correcting metadata
+ * that was set incorrectly during image creation.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared creator information. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Either the metadata block was not initialized (early exit, nothing to clear)
+ * - Or the creator string is freed (if it existed) and the pointer set to NULL
+ * - The creatorLength field in the metadata block header is set to 0
+ * - If all metadata fields are now empty, the metadata block identifier is cleared
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @note Memory Management:
+ * - If ctx->creator is not NULL, the allocated memory is freed before clearing
+ * - The ctx->creator pointer is set to NULL after freeing
+ * - Safe to call even if creator was never set (NULL check protects against errors)
+ * - No memory leaks occur when clearing previously set creator information
+ *
+ * @note Privacy and Anonymization:
+ * - Removes personally identifiable information from image metadata
+ * - Important for GDPR compliance and privacy protection
+ * - Consider clearing creator before distributing images publicly
+ * - May be required by institutional privacy policies
+ *
+ * @note Metadata Block State Management:
+ * - If the metadata block header is not initialized, function returns success immediately
+ * - After clearing, checks if all metadata fields are empty
+ * - If all fields empty, sets metadata block identifier to 0 (deinitialized)
+ * - Prevents writing empty metadata blocks, saving storage space
+ *
+ * @note Use Cases:
+ * - Anonymizing images for public distribution or research datasets
+ * - Compliance with data protection regulations (GDPR, CCPA, etc.)
+ * - Removing incorrect or outdated operator information
+ * - Preparing images for archival with institutional rather than personal attribution
+ * - Sanitizing test or development images before production use
+ *
+ * @warning The metadata changes are only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted to disk.
+ *
+ * @warning After clearing, the creator information is permanently lost unless:
+ * - The image file is not closed (context remains in memory)
+ * - A backup of the original image exists
+ * - The information is reconstructed from external documentation
+ *
+ * @warning Clearing creator may affect:
+ * - Forensic chain of custody requirements
+ * - Provenance documentation for archival purposes
+ * - Accountability and quality assurance workflows
+ * - Consider legal and institutional requirements before clearing
+ *
+ * @see aaruf_set_creator() for setting creator information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_creator(void *context)
+{
+ TRACE("Entering aaruf_clear_creator(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_creator() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_creator() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_creator() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_creator() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->creator != NULL) free(ctx->creator);
+
+ ctx->creator = NULL;
+ ctx->metadata_block_header.creatorLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.commentsLength == 0 && ctx->metadata_block_header.mediaTitleLength == 0 &&
+ ctx->metadata_block_header.mediaManufacturerLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
+ ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
+ ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_creator() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears user comments or notes from the image metadata.
+ *
+ * Removes the comments string from the AaruFormat image's metadata block, freeing the
+ * associated memory and resetting the length field to zero. This effectively removes
+ * any user-provided annotations, notes, or descriptions associated with the image.
+ * If this operation results in all metadata fields being empty, the entire metadata
+ * block is deinitialized to avoid writing an empty metadata block to the image file.
+ *
+ * This function is useful when removing outdated notes, clearing test comments before
+ * production deployment, sanitizing images for distribution, or resetting an image to
+ * a clean metadata state for repurposing.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared comments. This is returned when:
+ * - The context is valid and properly initialized
+ * - The context is opened in write mode (ctx->isWriting is true)
+ * - Either the metadata block was not initialized (early exit, nothing to clear)
+ * - Or the comments string is freed (if it existed) and the pointer set to NULL
+ * - The commentsLength field in the metadata block header is set to 0
+ * - If all metadata fields are now empty, the metadata block identifier is cleared
+ *
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid. This occurs when:
+ * - The context parameter is NULL
+ * - The context magic number doesn't match AARU_MAGIC (invalid context type)
+ * - The context was not properly initialized by aaruf_create()
+ *
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing. This occurs when:
+ * - The image was opened with aaruf_open() instead of aaruf_create()
+ * - The context's isWriting flag is false
+ * - Attempting to modify a read-only image
+ *
+ * @note Memory Management:
+ * - If ctx->comments is not NULL, the allocated memory is freed before clearing
+ * - The ctx->comments pointer is set to NULL after freeing
+ * - Safe to call even if comments were never set (NULL check protects against errors)
+ * - No memory leaks occur when clearing previously set comments
+ *
+ * @note Use Cases:
+ * - Removing temporary or development notes before production deployment
+ * - Clearing outdated comments that no longer apply
+ * - Sanitizing images for distribution by removing internal notes
+ * - Resetting images for repurposing with new documentation
+ * - Removing potentially sensitive information from comments
+ * - Preparing images for archival with standardized, minimal metadata
+ *
+ * @note Metadata Block State Management:
+ * - If the metadata block header is not initialized, function returns success immediately
+ * - After clearing, checks if all metadata fields are empty
+ * - If all fields empty, sets metadata block identifier to 0 (deinitialized)
+ * - Prevents writing empty metadata blocks, optimizing storage efficiency
+ *
+ * @note Information Loss Considerations:
+ * - Comments may contain valuable provenance or preservation information
+ * - Consider archiving comments externally before clearing if they contain important data
+ * - Comments might document imaging conditions, errors encountered, or quality notes
+ * - Workflow history and processing information may be lost
+ *
+ * @warning The metadata changes are only written to the image file during aaruf_close().
+ * Changes made by this function are not immediately persisted to disk.
+ *
+ * @warning After clearing, the comments are permanently lost unless:
+ * - The image file is not closed (context remains in memory)
+ * - A backup of the original image exists
+ * - The comments are documented in external metadata systems
+ *
+ * @see aaruf_set_comments() for setting comment information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_comments(void *context)
+{
+ TRACE("Entering aaruf_clear_comments(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_comments() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_comments() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_comments() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_comments() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->comments != NULL) free(ctx->comments);
+
+ ctx->comments = NULL;
+ ctx->metadata_block_header.commentsLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.mediaTitleLength == 0 &&
+ ctx->metadata_block_header.mediaManufacturerLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
+ ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
+ ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_comments() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the media title or label from the image metadata.
+ *
+ * Removes the media title string from the AaruFormat image's metadata block, freeing
+ * the associated memory and resetting the length field to zero. This effectively removes
+ * any record of the title, label, or name that was printed or written on the physical
+ * storage media. If this operation results in all metadata fields being empty, the
+ * entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared media title.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->media_title if not NULL and sets pointer to NULL.
+ * @note Metadata Block: If all fields become empty, the metadata block is deinitialized.
+ * @note Use Cases: Removing physical label information, anonymizing media, or correcting errors.
+ *
+ * @warning Changes are only persisted during aaruf_close(). Lost unless backed up or not closed.
+ *
+ * @see aaruf_set_media_title() for setting media title information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_title(void *context)
+{
+ TRACE("Entering aaruf_clear_media_title(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_title() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_media_title() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_media_title() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->media_title != NULL) free(ctx->media_title);
+
+ ctx->media_title = NULL;
+ ctx->metadata_block_header.mediaTitleLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaManufacturerLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
+ ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
+ ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_media_title() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the media manufacturer information from the image metadata.
+ *
+ * Removes the media manufacturer name string from the AaruFormat image's metadata block,
+ * freeing the associated memory and resetting the length field to zero. This removes
+ * any record of the company that manufactured the physical storage media. If this
+ * operation results in all metadata fields being empty, the entire metadata block is
+ * deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared media manufacturer.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->media_manufacturer if not NULL and sets pointer to NULL.
+ * @note Preservation Impact: Removes valuable information about media quality and lifespan characteristics.
+ * @note Use Cases: Anonymizing media source, removing commercial information, or correcting errors.
+ *
+ * @warning Loss of manufacturer information may affect preservation planning and media assessment.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_media_manufacturer() for setting media manufacturer information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_manufacturer(void *context)
+{
+ TRACE("Entering aaruf_clear_media_manufacturer(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->media_manufacturer != NULL) free(ctx->media_manufacturer);
+
+ ctx->media_manufacturer = NULL;
+ ctx->metadata_block_header.mediaManufacturerLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaModelLength == 0 &&
+ ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
+ ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_media_manufacturer() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the media model or product designation from the image metadata.
+ *
+ * Removes the media model string from the AaruFormat image's metadata block, freeing
+ * the associated memory and resetting the length field to zero. This removes any record
+ * of the specific model, product line, or type designation of the physical storage media.
+ * If this operation results in all metadata fields being empty, the entire metadata
+ * block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared media model.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->media_model if not NULL and sets pointer to NULL.
+ * @note Information Loss: Removes specific capacity, speed, and compatibility information.
+ * @note Use Cases: Removing product-specific details, generalizing metadata, or correcting errors.
+ *
+ * @warning Loss of model information may affect media compatibility assessments.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_media_model() for setting media model information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_model(void *context)
+{
+ TRACE("Entering aaruf_clear_media_model(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_media_model() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_media_model() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->media_model != NULL) free(ctx->media_model);
+
+ ctx->media_model = NULL;
+ ctx->metadata_block_header.mediaModelLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaSerialNumberLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
+ ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_media_model() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the media serial number from the image metadata.
+ *
+ * Removes the media serial number string from the AaruFormat image's metadata block,
+ * freeing the associated memory and resetting the length field to zero. This removes
+ * the unique identifier assigned to the specific piece of physical storage media by
+ * the manufacturer. If this operation results in all metadata fields being empty,
+ * the entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared media serial number.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->media_serial_number if not NULL and sets pointer to NULL.
+ * @note Forensic Impact: Removes unique identification critical for chain of custody.
+ * @note Privacy: May be necessary for anonymizing specific media instances.
+ * @note Use Cases: Privacy compliance, removing tracking identifiers, or correcting errors.
+ *
+ * @warning Loss of serial number eliminates unique media instance identification.
+ * @warning May affect forensic chain of custody and authentication capabilities.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_media_serial_number() for setting media serial number information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_serial_number(void *context)
+{
+ TRACE("Entering aaruf_clear_media_serial_number(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->media_serial_number != NULL) free(ctx->media_serial_number);
+
+ ctx->media_serial_number = NULL;
+ ctx->metadata_block_header.mediaSerialNumberLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaBarcodeLength == 0 &&
+ ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_media_serial_number() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the media barcode information from the image metadata.
+ *
+ * Removes the media barcode string from the AaruFormat image's metadata block, freeing
+ * the associated memory and resetting the length field to zero. This removes any record
+ * of the barcode affixed to the physical storage media or its packaging, typically used
+ * in professional archival and library inventory systems. If this operation results in
+ * all metadata fields being empty, the entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared media barcode.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->media_barcode if not NULL and sets pointer to NULL.
+ * @note Inventory Impact: Removes correlation with physical media location systems.
+ * @note Use Cases: Anonymizing media, removing institutional tracking, or correcting errors.
+ * @note Archive Systems: May affect automated retrieval and inventory management.
+ *
+ * @warning Loss of barcode breaks links to physical inventory and asset management systems.
+ * @warning May affect robotic tape library operations and automated retrieval.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_media_barcode() for setting media barcode information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_barcode(void *context)
+{
+ TRACE("Entering aaruf_clear_media_barcode(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_barcode() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_media_barcode() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_media_barcode() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->media_barcode != NULL) free(ctx->media_barcode);
+
+ ctx->media_barcode = NULL;
+ ctx->metadata_block_header.mediaBarcodeLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
+ ctx->metadata_block_header.mediaPartNumberLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_media_barcode() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the media part number or model designation from the image metadata.
+ *
+ * Removes the media part number string from the AaruFormat image's metadata block,
+ * freeing the associated memory and resetting the length field to zero. This removes
+ * the manufacturer's part number or catalog designation used for procurement and exact
+ * product identification. If this operation results in all metadata fields being empty,
+ * the entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared media part number.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->media_part_number if not NULL and sets pointer to NULL.
+ * @note Procurement Impact: Removes exact ordering and catalog reference information.
+ * @note Use Cases: Removing commercial details, generalizing metadata, or correcting errors.
+ * @note Documentation: May affect ability to source compatible replacement media.
+ *
+ * @warning Loss of part number affects precise product identification and procurement.
+ * @warning May impact ability to cross-reference with manufacturer specifications.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_media_part_number() for setting media part number information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_media_part_number(void *context)
+{
+ TRACE("Entering aaruf_clear_media_part_number(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_media_part_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_media_part_number() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_media_part_number() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->media_part_number != NULL) free(ctx->media_part_number);
+
+ ctx->media_part_number = NULL;
+ ctx->metadata_block_header.mediaPartNumberLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
+ ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.driveModelLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_media_part_number() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the drive manufacturer information from the image metadata.
+ *
+ * Removes the drive manufacturer name string from the AaruFormat image's metadata block,
+ * freeing the associated memory and resetting the length field to zero. This removes
+ * any record of the company that manufactured the drive or device used to read or write
+ * the physical storage media during the imaging process. If this operation results in
+ * all metadata fields being empty, the entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared drive manufacturer.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->drive_manufacturer if not NULL and sets pointer to NULL.
+ * @note Provenance Impact: Removes imaging equipment context from preservation metadata.
+ * @note Use Cases: Anonymizing imaging environment, removing commercial info, or correcting errors.
+ * @note Quality Assessment: May affect ability to evaluate imaging tool quality and reliability.
+ *
+ * @warning Loss of drive manufacturer information reduces imaging process documentation.
+ * @warning May affect forensic provenance and imaging environment reconstruction.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_drive_manufacturer() for setting drive manufacturer information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_manufacturer(void *context)
+{
+ TRACE("Entering aaruf_clear_drive_manufacturer(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->drive_manufacturer != NULL) free(ctx->drive_manufacturer);
+
+ ctx->drive_manufacturer = NULL;
+ ctx->metadata_block_header.driveManufacturerLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
+ ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
+ ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_drive_manufacturer() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the drive model information from the image metadata.
+ *
+ * Removes the drive model string from the AaruFormat image's metadata block, freeing
+ * the associated memory and resetting the length field to zero. This removes any record
+ * of the specific model or product designation of the drive or device used to read or
+ * write the physical storage media during the imaging process. If this operation results
+ * in all metadata fields being empty, the entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared drive model.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->drive_model if not NULL and sets pointer to NULL.
+ * @note Technical Context: Removes specific drive capability and feature information.
+ * @note Use Cases: Anonymizing imaging equipment, simplifying metadata, or correcting errors.
+ * @note Troubleshooting: May affect ability to diagnose model-specific imaging issues.
+ *
+ * @warning Loss of drive model information reduces imaging tool documentation completeness.
+ * @warning May affect understanding of drive-specific capabilities or limitations.
+ * @warning Important for reproducing imaging conditions or troubleshooting issues.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_drive_model() for setting drive model information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_model(void *context)
+{
+ TRACE("Entering aaruf_clear_drive_model(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_model() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_drive_model() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_drive_model() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->drive_model != NULL) free(ctx->drive_model);
+
+ ctx->drive_model = NULL;
+ ctx->metadata_block_header.driveModelLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
+ ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
+ ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_drive_model() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the drive serial number from the image metadata.
+ *
+ * Removes the drive serial number string from the AaruFormat image's metadata block,
+ * freeing the associated memory and resetting the length field to zero. This removes
+ * the unique identifier of the specific drive or device used to read or write the
+ * physical storage media during the imaging process. If this operation results in
+ * all metadata fields being empty, the entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared drive serial number.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->drive_serial_number if not NULL and sets pointer to NULL.
+ * @note Forensic Impact: Removes unique hardware identification from imaging provenance.
+ * @note Privacy: May be necessary for anonymizing specific equipment instances.
+ * @note Use Cases: Privacy compliance, equipment anonymization, or correcting errors.
+ * @note Equipment Tracking: Breaks correlation with equipment maintenance and calibration records.
+ *
+ * @warning Loss of drive serial number eliminates unique hardware instance identification.
+ * @warning May affect forensic chain of custody documentation requirements.
+ * @warning Impacts ability to correlate images with specific equipment for quality analysis.
+ * @warning Removes equipment tracking capability for maintenance and workload management.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_drive_serial_number() for setting drive serial number information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_serial_number(void *context)
+{
+ TRACE("Entering aaruf_clear_drive_serial_number(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->drive_serial_number != NULL) free(ctx->drive_serial_number);
+
+ ctx->drive_serial_number = NULL;
+ ctx->metadata_block_header.driveSerialNumberLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
+ ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
+ ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveFirmwareRevisionLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_drive_serial_number() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+
+/**
+ * @brief Clears the drive firmware revision from the image metadata.
+ *
+ * Removes the drive firmware revision string from the AaruFormat image's metadata block,
+ * freeing the associated memory and resetting the length field to zero. This removes
+ * any record of the firmware version or revision of the drive or device used to read
+ * or write the physical storage media during the imaging process. If this operation
+ * results in all metadata fields being empty, the entire metadata block is deinitialized.
+ *
+ * @param context Pointer to the aaruformat context (must be a valid, write-enabled image context).
+ *
+ * @return Returns one of the following status codes:
+ * @retval AARUF_STATUS_OK (0) Successfully cleared drive firmware revision.
+ * @retval AARUF_ERROR_NOT_AARUFORMAT (-1) The context is invalid.
+ * @retval AARUF_READ_ONLY (-13) The context is not opened for writing.
+ *
+ * @note Memory Management: Frees ctx->drive_firmware_revision if not NULL and sets pointer to NULL.
+ * @note Technical Impact: Removes specific firmware behavior and capability documentation.
+ * @note Use Cases: Simplifying metadata, removing technical details, or correcting errors.
+ * @note Troubleshooting: May affect ability to diagnose firmware-specific issues.
+ * @note Reproducibility: Reduces ability to reproduce exact imaging conditions.
+ *
+ * @warning Loss of firmware revision information reduces imaging environment documentation.
+ * @warning Firmware versions significantly affect drive behavior and error handling.
+ * @warning May affect ability to identify firmware-related imaging issues or quirks.
+ * @warning Impacts scientific reproducibility and technical troubleshooting capabilities.
+ * @warning Changes are only persisted during aaruf_close().
+ *
+ * @see aaruf_set_drive_firmware_revision() for setting drive firmware revision information.
+ */
+AARU_EXPORT int32_t AARU_CALL aaruf_clear_drive_firmware_revision(void *context)
+{
+ TRACE("Entering aaruf_clear_drive_firmware_revision(%p)", context);
+
+ // Check context is correct AaruFormat context
+ if(context == NULL)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ aaruformat_context *ctx = context;
+
+ // Not a libaaruformat context
+ if(ctx->magic != AARU_MAGIC)
+ {
+ FATAL("Invalid context");
+
+ TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_ERROR_NOT_AARUFORMAT");
+ return AARUF_ERROR_NOT_AARUFORMAT;
+ }
+
+ // Check we are writing
+ if(!ctx->is_writing)
+ {
+ FATAL("Trying to write a read-only image");
+
+ TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_READ_ONLY");
+ return AARUF_READ_ONLY;
+ }
+
+ if(ctx->metadata_block_header.identifier != MetadataBlock)
+ {
+ TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+ }
+
+ if(ctx->drive_firmware_revision != NULL) free(ctx->drive_firmware_revision);
+
+ ctx->drive_firmware_revision = NULL;
+ ctx->metadata_block_header.driveFirmwareRevisionLength = 0;
+
+ // Check if all metadata is clear
+ if(ctx->metadata_block_header.mediaSequence == 0 && ctx->metadata_block_header.lastMediaSequence == 0 &&
+ ctx->metadata_block_header.creatorLength == 0 && ctx->metadata_block_header.commentsLength == 0 &&
+ ctx->metadata_block_header.mediaTitleLength == 0 && ctx->metadata_block_header.mediaManufacturerLength == 0 &&
+ ctx->metadata_block_header.mediaModelLength == 0 && ctx->metadata_block_header.mediaSerialNumberLength == 0 &&
+ ctx->metadata_block_header.mediaBarcodeLength == 0 && ctx->metadata_block_header.mediaPartNumberLength == 0 &&
+ ctx->metadata_block_header.driveModelLength == 0 && ctx->metadata_block_header.driveManufacturerLength == 0 &&
+ ctx->metadata_block_header.driveSerialNumberLength == 0)
+ ctx->metadata_block_header.identifier = 0;
+
+ TRACE("Exiting aaruf_clear_drive_firmware_revision() = AARUF_STATUS_OK");
+ return AARUF_STATUS_OK;
+}
+