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; +} +