diff --git a/include/aaruformat/decls.h b/include/aaruformat/decls.h index ad84ae0..ae2849b 100644 --- a/include/aaruformat/decls.h +++ b/include/aaruformat/decls.h @@ -144,6 +144,19 @@ AARU_EXPORT int32_t AARU_CALL aaruf_get_geometry(const void *context, uint32_t * uint32_t *sectors_per_track); AARU_EXPORT int32_t AARU_CALL aaruf_set_geometry(void *context, uint32_t cylinders, uint32_t heads, uint32_t sectors_per_track); +AARU_EXPORT int32_t AARU_CALL aaruf_set_media_sequence(void *context, int32_t sequence, int32_t last_sequence); +AARU_EXPORT int32_t AARU_CALL aaruf_set_creator(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_comments(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_media_title(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_media_manufacturer(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_media_model(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_media_serial_number(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_media_barcode(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_media_part_number(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_manufacturer(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_model(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_serial_number(void *context, const uint8_t *data, int32_t length); +AARU_EXPORT int32_t AARU_CALL aaruf_set_drive_firmware_revision(void *context, const uint8_t *data, int32_t length); AARU_EXPORT spamsum_ctx *AARU_CALL aaruf_spamsum_init(void); AARU_EXPORT int AARU_CALL aaruf_spamsum_update(spamsum_ctx *ctx, const uint8_t *data, uint32_t len); diff --git a/src/metadata.c b/src/metadata.c index 01f7932..b1d76bf 100644 --- a/src/metadata.c +++ b/src/metadata.c @@ -270,4 +270,1575 @@ int32_t aaruf_set_geometry(void *context, const uint32_t cylinders, const uint32 TRACE("Exiting aaruf_set_geometry(%p, %u, %u, %u) = AARUF_STATUS_OK", context, cylinders, heads, sectors_per_track); return AARUF_STATUS_OK; -} \ No newline at end of file +} + +/** + * @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 + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_media_sequence() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.identifier = MetadataBlock; + + ctx->metadataBlockHeader.mediaSequence = sequence; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_creator() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.Creator != NULL) free(ctx->imageInfo.Creator); + ctx->imageInfo.Creator = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_comments() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.Comments != NULL) free(ctx->imageInfo.Comments); + ctx->imageInfo.Comments = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_media_title() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.MediaTitle != NULL) free(ctx->imageInfo.MediaTitle); + ctx->imageInfo.MediaTitle = copy; + ctx->metadataBlockHeader.mediaTitleLength = length; + + 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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_media_manufacturer() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.MediaManufacturer != NULL) free(ctx->imageInfo.MediaManufacturer); + ctx->imageInfo.MediaManufacturer = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_media_model() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.MediaModel != NULL) free(ctx->imageInfo.MediaModel); + ctx->imageInfo.MediaModel = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + 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->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.MediaSerialNumber != NULL) free(ctx->imageInfo.MediaSerialNumber); + ctx->imageInfo.MediaSerialNumber = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_media_barcode() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.MediaBarcode != NULL) free(ctx->imageInfo.MediaBarcode); + ctx->imageInfo.MediaBarcode = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + 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->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.MediaPartNumber != NULL) free(ctx->imageInfo.MediaPartNumber); + ctx->imageInfo.MediaPartNumber = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_drive_manufacturer() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.DriveManufacturer != NULL) free(ctx->imageInfo.DriveManufacturer); + ctx->imageInfo.DriveManufacturer = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + FATAL("Trying to write a read-only image"); + + TRACE("Exiting aaruf_set_drive_model() = AARUF_READ_ONLY"); + return AARUF_READ_ONLY; + } + + // Initialize + if(ctx->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.DriveModel != NULL) free(ctx->imageInfo.DriveModel); + ctx->imageInfo.DriveModel = copy; + ctx->metadataBlockHeader.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 (-8) 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. + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + 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->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.DriveSerialNumber != NULL) free(ctx->imageInfo.DriveSerialNumber); + ctx->imageInfo.DriveSerialNumber = copy; + ctx->metadataBlockHeader.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 (-8) 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 + */ +int32_t 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; + } + + aaruformatContext *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->isWriting) + { + 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->metadataBlockHeader.identifier != MetadataBlock) ctx->metadataBlockHeader.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->imageInfo.DriveFirmwareRevision != NULL) free(ctx->imageInfo.DriveFirmwareRevision); + ctx->imageInfo.DriveFirmwareRevision = copy; + ctx->metadataBlockHeader.driveFirmwareRevisionLength = length; + + TRACE("Exiting aaruf_set_drive_firmware_revision(%p, %p, %d) = AARUF_STATUS_OK", context, data, length); + return AARUF_STATUS_OK; +}