Files
libaaruformat/docs/html/write_8c.html

1228 lines
108 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.14.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>libaaruformat: src/write.c File Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectalign">
<div id="projectname">libaaruformat<span id="projectnumber">&#160;1.0</span>
</div>
<div id="projectbrief">Aaru Data Preservation Suite - Format Library</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.14.0 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search/",'.html');
</script>
<script type="text/javascript">
$(function() { codefold.init(); });
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('',true,false,'search.php','Search',true);
$(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
$(function(){initNavTree('write_8c.html','',''); });
</script>
<div id="container">
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
<div class="header">
<div class="headertitle"><div class="title">write.c File Reference</div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><code>#include &lt;errno.h&gt;</code><br />
<code>#include &lt;stdbool.h&gt;</code><br />
<code>#include &lt;stdint.h&gt;</code><br />
<code>#include &lt;stdio.h&gt;</code><br />
<code>#include &lt;stdlib.h&gt;</code><br />
<code>#include &lt;string.h&gt;</code><br />
<code>#include &quot;<a class="el" href="aaruformat_8h_source.html">aaruformat.h</a>&quot;</code><br />
<code>#include &quot;<a class="el" href="internal_8h_source.html">internal.h</a>&quot;</code><br />
<code>#include &quot;<a class="el" href="log_8h_source.html">log.h</a>&quot;</code><br />
<code>#include &quot;<a class="el" href="lisa__tag_8h_source.html">structs/lisa_tag.h</a>&quot;</code><br />
<code>#include &quot;xxhash.h&quot;</code><br />
</div>
<p><a href="write_8c_source.html">Go to the source code of this file.</a></p>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 id="header-func-members" class="groupheader"><a id="func-members" name="func-members"></a>
Functions</h2></td></tr>
<tr class="memitem:a4b8cd2bb5fd9e2c670a0a13695c6f9e3" id="r_a4b8cd2bb5fd9e2c670a0a13695c6f9e3"><td class="memItemLeft" align="right" valign="top">int32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3">aaruf_write_sector</a> (void *context, uint64_t sector_address, bool negative, const uint8_t *data, uint8_t sector_status, uint32_t length)</td></tr>
<tr class="memdesc:a4b8cd2bb5fd9e2c670a0a13695c6f9e3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Writes a sector to the AaruFormat image. <br /></td></tr>
<tr class="memitem:a69ca66242c0becf7640b3d1cc8da8f9c" id="r_a69ca66242c0becf7640b3d1cc8da8f9c"><td class="memItemLeft" align="right" valign="top">int32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="#a69ca66242c0becf7640b3d1cc8da8f9c">aaruf_write_sector_long</a> (void *context, uint64_t sector_address, bool negative, const uint8_t *data, uint8_t sector_status, uint32_t length)</td></tr>
<tr class="memdesc:a69ca66242c0becf7640b3d1cc8da8f9c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Writes a full ("long") raw sector from optical or block media, parsing structure and validating content. <br /></td></tr>
<tr class="memitem:a2402812f5e04ba16765208c0b70fa6c5" id="r_a2402812f5e04ba16765208c0b70fa6c5"><td class="memItemLeft" align="right" valign="top">int32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="#a2402812f5e04ba16765208c0b70fa6c5">aaruf_close_current_block</a> (<a class="el" href="structaaruformat__context.html">aaruformat_context</a> *ctx)</td></tr>
<tr class="memdesc:a2402812f5e04ba16765208c0b70fa6c5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Finalizes and writes the current data block to the AaruFormat image file. <br /></td></tr>
<tr class="memitem:a35c5d9f10c59a1efe8f625963c9e91ba" id="r_a35c5d9f10c59a1efe8f625963c9e91ba"><td class="memItemLeft" align="right" valign="top">int32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="#a35c5d9f10c59a1efe8f625963c9e91ba">aaruf_write_media_tag</a> (void *context, const uint8_t *data, const int32_t type, const uint32_t length)</td></tr>
<tr class="memdesc:a35c5d9f10c59a1efe8f625963c9e91ba"><td class="mdescLeft">&#160;</td><td class="mdescRight">Writes a media tag to the AaruFormat image, storing medium-specific metadata and descriptors. <br /></td></tr>
<tr class="memitem:a2dc7f13b0cd44153f1456d3ed4c15a0c" id="r_a2dc7f13b0cd44153f1456d3ed4c15a0c"><td class="memItemLeft" align="right" valign="top">int32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="#a2dc7f13b0cd44153f1456d3ed4c15a0c">aaruf_write_sector_tag</a> (void *context, const uint64_t sector_address, const bool negative, const uint8_t *data, const size_t length, const int32_t tag)</td></tr>
<tr class="memdesc:a2dc7f13b0cd44153f1456d3ed4c15a0c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Writes per-sector tag data (auxiliary metadata) for a specific sector. <br /></td></tr>
</table>
<a name="doc-func-members" id="doc-func-members"></a><h2 id="header-doc-func-members" class="groupheader">Function Documentation</h2>
<a id="a2402812f5e04ba16765208c0b70fa6c5" name="a2402812f5e04ba16765208c0b70fa6c5"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a2402812f5e04ba16765208c0b70fa6c5">&#9670;&#160;</a></span>aaruf_close_current_block()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int32_t aaruf_close_current_block </td>
<td>(</td>
<td class="paramtype"><a class="el" href="structaaruformat__context.html">aaruformat_context</a> *</td> <td class="paramname"><span class="paramname"><em>ctx</em></span></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Finalizes and writes the current data block to the AaruFormat image file. </p>
<p>This function completes the current writing block by computing checksums, optionally compressing the buffered sector data, writing the block header and data to the image file, updating the index, and cleaning up resources. It is called automatically when a block is full (reaches maximum size determined by dataShift), when sector size changes, or when image finalization begins. The function supports multiple compression algorithms (FLAC for audio, LZMA for data) with automatic fallback to uncompressed storage if compression is ineffective.</p>
<p><b>Block Finalization Sequence:</b></p>
<ol type="1">
<li><b>Context Validation</b>: Verify context is valid and opened for writing</li>
<li><b>Length Calculation</b>: Set block length = currentBlockOffset × sectorSize</li>
<li><b>CRC64 Computation</b>: Calculate checksum of uncompressed block data</li>
<li><b>Compression Processing</b> (if enabled):<ul>
<li>FLAC: For audio tracks, compress using Red Book audio encoding with configurable block size</li>
<li>LZMA: For data tracks, compress using LZMA algorithm with dictionary size optimization</li>
<li>Fallback: If compressed size ≥ uncompressed size, use uncompressed storage</li>
</ul>
</li>
<li><b>Compressed CRC64</b>: Calculate checksum of compressed data (if compression was applied)</li>
<li><b>Index Registration</b>: Add <a class="el" href="structIndexEntry.html" title="Single index entry describing a block&#39;s type, (optional) data classification, and file offset.">IndexEntry</a> to ctx-&gt;indexEntries for block lookup</li>
<li><b>File Writing</b>: Write <a class="el" href="structBlockHeader.html" title="Header preceding the compressed data payload of a data block (BlockType::DataBlock).">BlockHeader</a>, optional LZMA properties, and block data to image stream</li>
<li><b>Position Update</b>: Calculate next block position with alignment boundary adjustment</li>
<li><b>Resource Cleanup</b>: Free buffers, reset counters, clear block header</li>
</ol>
<p><b>Compression Handling:</b></p>
<ul>
<li><b>None (<a class="el" href="enums_8h.html#affec749ed88365143745313ae9168263" title="List of known compression types.">CompressionType</a> = 0)</b>: No compression applied<ul>
<li>cmpLength = length (uncompressed size)</li>
<li>cmpCrc64 = crc64 (same checksum)</li>
<li>Direct write of ctx-&gt;writingBuffer to file</li>
</ul>
</li>
<li><b>FLAC (<a class="el" href="enums_8h.html#affec749ed88365143745313ae9168263" title="List of known compression types.">CompressionType</a> = 2)</b>: For CD audio tracks (Red Book format)<ul>
<li>Allocates 2× length buffer for compressed data</li>
<li>Calculates optimal FLAC block size (MIN_FLAKE_BLOCK to MAX_FLAKE_BLOCK range)</li>
<li>Pads incomplete blocks with zeros to meet FLAC block size requirements</li>
<li>Encoding parameters: mid-side stereo, Hamming apodization, 12 max LPC order</li>
<li>Falls back to None if compression ineffective (compressed ≥ uncompressed)</li>
</ul>
</li>
<li><b>LZMA (<a class="el" href="enums_8h.html#affec749ed88365143745313ae9168263" title="List of known compression types.">CompressionType</a> = 1)</b>: For data tracks and non-audio content<ul>
<li>Allocates 2× length buffer for compressed data</li>
<li>LZMA properties: level 9, dictionary size from ctx-&gt;lzma_dict_size</li>
<li>Properties stored as 5-byte header: lc=4, lp=0, pb=2, fb=273, threads=8</li>
<li>Falls back to None if compression ineffective (compressed ≥ uncompressed)</li>
<li>Compressed length includes LZMA_PROPERTIES_LENGTH (5 bytes) overhead</li>
</ul>
</li>
</ul>
<p><b>Index Entry Creation:</b></p>
<p>Each closed block is registered in the index with:</p><ul>
<li>blockType = DataBlock (0x4B4C4244)</li>
<li>dataType = UserData (1)</li>
<li>offset = ctx-&gt;nextBlockPosition (file position where block was written)</li>
</ul>
<p>This enables efficient block lookup during image reading via binary search on index entries.</p>
<p><b>File Layout:</b></p>
<p>Written to ctx-&gt;imageStream at ctx-&gt;nextBlockPosition:</p><ol type="1">
<li><a class="el" href="structBlockHeader.html" title="Header preceding the compressed data payload of a data block (BlockType::DataBlock).">BlockHeader</a> (sizeof(BlockHeader) bytes)</li>
<li>LZMA properties (5 bytes, only if compression = Lzma)</li>
<li>Block data (cmpLength bytes - compressed or uncompressed depending on compression type)</li>
</ol>
<p><b>Next Block Position Calculation:</b></p>
<p>After writing, nextBlockPosition is updated to the next aligned boundary:</p><ul>
<li>block_total_size = sizeof(BlockHeader) + cmpLength</li>
<li>alignment_mask = (1 &lt;&lt; blockAlignmentShift) - 1</li>
<li>nextBlockPosition = (currentPosition + block_total_size + alignment_mask) &amp; ~alignment_mask</li>
</ul>
<p>This ensures all blocks begin on properly aligned file offsets for efficient I/O.</p>
<p><b>Resource Cleanup:</b></p>
<p>Before returning, the function:</p><ul>
<li>Frees ctx-&gt;writingBuffer and sets pointer to NULL</li>
<li>Resets ctx-&gt;currentBlockOffset to 0</li>
<li>Clears ctx-&gt;currentBlockHeader (memset to 0)</li>
<li>Frees ctx-&gt;crc64Context</li>
<li>Resets ctx-&gt;writingBufferPosition to 0</li>
</ul>
<p>This prepares the context for the next block or signals that no block is currently open.</p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">ctx</td><td>Pointer to an initialized aaruformatContext in write mode.</td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Returns one of the following status codes: </dd></dl>
<dl class="retval"><dt>Return values</dt><dd>
<table class="retval">
<tr><td class="paramname">AARUF_STATUS_OK</td><td>(0) Successfully finalized and wrote the block. This is returned when:<ul>
<li>The context is valid and properly initialized</li>
<li>CRC64 computation completed successfully</li>
<li>Compression (if applicable) succeeded or fell back appropriately</li>
<li>Block header was successfully written to the image file</li>
<li>Block data (compressed or uncompressed) was successfully written</li>
<li>LZMA properties (if applicable) were successfully written</li>
<li>Index entry was added to ctx-&gt;indexEntries</li>
<li>Next block position was calculated and updated</li>
<li>All resources were freed and context reset for next block</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_AARUFORMAT</td><td>(-1) The context is invalid. This occurs when:<ul>
<li>The context parameter is NULL</li>
<li>The context magic number doesn't match AARU_MAGIC (invalid context type)</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_READ_ONLY</td><td>(-22) Attempting to finalize block on read-only image. This occurs when:<ul>
<li>The context's isWriting flag is false</li>
<li>The image was opened in read-only mode with <a class="el" href="decls_8h.html#afc4932cdc795ffb2ef3a33d5b8c57656" title="Opens an existing AaruFormat image file.">aaruf_open()</a></li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_ENOUGH_MEMORY</td><td>(-9) Memory allocation failed. This occurs when:<ul>
<li>Cannot allocate compression buffer (2× block length) for FLAC compression</li>
<li>Cannot allocate compression buffer (2× block length) for LZMA compression</li>
<li>System is out of memory or memory is severely fragmented</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER</td><td>(-23) Failed to write block header. This occurs when:<ul>
<li>fwrite() for <a class="el" href="structBlockHeader.html" title="Header preceding the compressed data payload of a data block (BlockType::DataBlock).">BlockHeader</a> returns != 1 (incomplete write or I/O error)</li>
<li>Disk space is insufficient for header</li>
<li>File system errors or permissions prevent writing</li>
<li>Media errors on the destination storage device</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA</td><td>(-24) Failed to write block data. This occurs when:<ul>
<li>fwrite() for LZMA properties returns != 1 (when compression = Lzma)</li>
<li>fwrite() for uncompressed data returns != 1 (when compression = None)</li>
<li>fwrite() for compressed data returns != 1 (when compression = Flac/Lzma)</li>
<li>Disk space is insufficient for block data</li>
<li>File system errors or permissions prevent writing</li>
<li>Invalid compression type (not None, Flac, or Lzma)</li>
</ul>
</td></tr>
</table>
</dd>
</dl>
<dl class="section note"><dt>Note</dt><dd>Compression Algorithm Selection:<ul>
<li>Compression type is determined when block is created in <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a></li>
<li>Audio tracks (<a class="el" href="enums_8h.html#ad80740dd555f7d3688d2c4d9f44d3b04" title="Track (partitioning element) types for optical media.">TrackType</a> = Audio) use FLAC compression if enabled</li>
<li>Data tracks use LZMA compression if enabled</li>
<li>Special cases (JaguarCD data in audio, VideoNow) force LZMA even for audio tracks</li>
<li>Compression can be disabled entirely via ctx-&gt;compression_enabled flag</li>
</ul>
</dd>
<dd>
Compression Fallback Logic:<ul>
<li>If compressed size ≥ uncompressed size, compression is abandoned</li>
<li>Compression buffer is freed and compression type set to None</li>
<li>This prevents storage expansion from ineffective compression</li>
<li>Fallback is transparent to caller; function still returns success</li>
</ul>
</dd>
<dd>
FLAC Encoding Parameters:<ul>
<li>Encoding for Red Book audio (44.1kHz, 16-bit stereo)</li>
<li>Block size: auto-selected between MIN_FLAKE_BLOCK and MAX_FLAKE_BLOCK samples</li>
<li>Mid-side stereo enabled for better compression on correlated channels</li>
<li>Hamming window apodization for LPC analysis</li>
<li>Max LPC order: 12, QLP coefficient precision: 15 bits</li>
<li>Application ID: "Aaru" with 4-byte signature</li>
</ul>
</dd>
<dd>
LZMA Encoding Parameters:<ul>
<li>Compression level: 9 (maximum compression)</li>
<li>Dictionary size: from ctx-&gt;lzma_dict_size (configurable per context)</li>
<li>Literal context bits (lc): 4</li>
<li>Literal position bits (lp): 0</li>
<li>Position bits (pb): 2</li>
<li>Fast bytes (fb): 273</li>
<li>Threads: 8 (for multi-threaded compression)</li>
</ul>
</dd>
<dd>
Index Management:<ul>
<li>Every closed block gets an index entry for efficient lookup</li>
<li>Index entries are stored in ctx-&gt;indexEntries (dynamic array)</li>
<li>Final index is serialized during <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> for image finalization</li>
<li>Index enables O(log n) block lookup during image reading</li>
</ul>
</dd>
<dd>
Alignment Requirements:<ul>
<li>Blocks must start on aligned boundaries per blockAlignmentShift</li>
<li>Typical alignment: 512 bytes (shift=9) or 4096 bytes (shift=12)</li>
<li>Alignment ensures efficient sector-aligned I/O on modern storage</li>
<li>Gap between blocks is implicit; no padding data is written</li>
</ul>
</dd></dl>
<dl class="section warning"><dt>Warning</dt><dd>This function assumes ctx-&gt;writingBuffer contains valid data for ctx-&gt;currentBlockOffset sectors of ctx-&gt;currentBlockHeader.sectorSize bytes each.</dd>
<dd>
Do not call this function when no block is open (ctx-&gt;writingBuffer == NULL). This will result in undefined behavior or segmentation fault.</dd>
<dd>
The function modifies ctx-&gt;nextBlockPosition, which affects where subsequent blocks are written. Ensure file positioning is properly managed.</dd>
<dd>
Memory allocated for compression buffers is freed before returning. Do not retain pointers to compressed data after function completion.</dd>
<dd>
CRC64 context (ctx-&gt;crc64Context) is freed during cleanup. Do not access this pointer after calling this function. </dd></dl>
<p class="definition">Definition at line <a class="el" href="write_8c_source.html#l01383">1383</a> of file <a class="el" href="write_8c_source.html">write.c</a>.</p>
<p class="reference">References <a class="el" href="consts_8h_source.html#l00064">AARU_MAGIC</a>, <a class="el" href="crc64_8c_source.html#l00160">aaruf_crc64_data()</a>, <a class="el" href="crc64_8c_source.html#l00141">aaruf_crc64_final()</a>, <a class="el" href="crc64_8c_source.html#l00155">aaruf_crc64_free()</a>, <a class="el" href="crc64_8c_source.html#l00032">aaruf_crc64_init()</a>, <a class="el" href="crc64_8c_source.html#l00055">aaruf_crc64_update()</a>, <a class="el" href="errors_8h_source.html#l00063">AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA</a>, <a class="el" href="errors_8h_source.html#l00062">AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER</a>, <a class="el" href="errors_8h_source.html#l00040">AARUF_ERROR_NOT_AARUFORMAT</a>, <a class="el" href="errors_8h_source.html#l00048">AARUF_ERROR_NOT_ENOUGH_MEMORY</a>, <a class="el" href="flac_8c_source.html#l00175">aaruf_flac_encode_redbook_buffer()</a>, <a class="el" href="lzma_8c_source.html#l00065">aaruf_lzma_encode_buffer()</a>, <a class="el" href="errors_8h_source.html#l00061">AARUF_READ_ONLY</a>, <a class="el" href="errors_8h_source.html#l00075">AARUF_STATUS_OK</a>, <a class="el" href="ddt_8h_source.html#l00154">DdtHeader2::blockAlignmentShift</a>, <a class="el" href="index_8h_source.html#l00110">IndexEntry::blockType</a>, <a class="el" href="data_8h_source.html#l00078">BlockHeader::cmpCrc64</a>, <a class="el" href="data_8h_source.html#l00076">BlockHeader::cmpLength</a>, <a class="el" href="data_8h_source.html#l00074">BlockHeader::compression</a>, <a class="el" href="data_8h_source.html#l00079">BlockHeader::crc64</a>, <a class="el" href="context_8h_source.html#l00249">aaruformat_context::crc64_context</a>, <a class="el" href="context_8h_source.html#l00281">aaruformat_context::current_block_header</a>, <a class="el" href="context_8h_source.html#l00288">aaruformat_context::current_block_offset</a>, <a class="el" href="enums_8h_source.html#l00141">DataBlock</a>, <a class="el" href="index_8h_source.html#l00111">IndexEntry::dataType</a>, <a class="el" href="log_8h_source.html#l00040">FATAL</a>, <a class="el" href="enums_8h_source.html#l00035">Flac</a>, <a class="el" href="context_8h_source.html#l00176">aaruformat_context::imageStream</a>, <a class="el" href="context_8h_source.html#l00252">aaruformat_context::index_entries</a>, <a class="el" href="context_8h_source.html#l00292">aaruformat_context::is_writing</a>, <a class="el" href="data_8h_source.html#l00077">BlockHeader::length</a>, <a class="el" href="enums_8h_source.html#l00034">Lzma</a>, <a class="el" href="context_8h_source.html#l00297">aaruformat_context::lzma_dict_size</a>, <a class="el" href="consts_8h_source.html#l00082">LZMA_PROPERTIES_LENGTH</a>, <a class="el" href="context_8h_source.html#l00174">aaruformat_context::magic</a>, <a class="el" href="consts_8h_source.html#l00094">MAX_FLAKE_BLOCK</a>, <a class="el" href="consts_8h_source.html#l00096">MIN_FLAKE_BLOCK</a>, <a class="el" href="context_8h_source.html#l00282">aaruformat_context::next_block_position</a>, <a class="el" href="enums_8h_source.html#l00033">None</a>, <a class="el" href="index_8h_source.html#l00112">IndexEntry::offset</a>, <a class="el" href="consts_8h_source.html#l00090">SAMPLES_PER_SECTOR</a>, <a class="el" href="data_8h_source.html#l00075">BlockHeader::sectorSize</a>, <a class="el" href="log_8h_source.html#l00025">TRACE</a>, <a class="el" href="context_8h_source.html#l00189">aaruformat_context::user_data_ddt_header</a>, <a class="el" href="enums_8h_source.html#l00046">UserData</a>, <a class="el" href="context_8h_source.html#l00280">aaruformat_context::writing_buffer</a>, and <a class="el" href="context_8h_source.html#l00289">aaruformat_context::writing_buffer_position</a>.</p>
<p class="reference">Referenced by <a class="el" href="close_8c_source.html#l03995">aaruf_close()</a>, <a class="el" href="write_8c_source.html#l00098">aaruf_write_sector()</a>, and <a class="el" href="ddt__v2_8c_source.html#l01092">set_ddt_multi_level_v2()</a>.</p>
</div>
</div>
<a id="a35c5d9f10c59a1efe8f625963c9e91ba" name="a35c5d9f10c59a1efe8f625963c9e91ba"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a35c5d9f10c59a1efe8f625963c9e91ba">&#9670;&#160;</a></span>aaruf_write_media_tag()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int32_t aaruf_write_media_tag </td>
<td>(</td>
<td class="paramtype">void *</td> <td class="paramname"><span class="paramname"><em>context</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const uint8_t *</td> <td class="paramname"><span class="paramname"><em>data</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const int32_t</td> <td class="paramname"><span class="paramname"><em>type</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const uint32_t</td> <td class="paramname"><span class="paramname"><em>length</em></span>&#160;)</td>
</tr>
</table>
</div><div class="memdoc">
<p>Writes a media tag to the AaruFormat image, storing medium-specific metadata and descriptors. </p>
<p>This function stores arbitrary media-specific metadata (media tags) in the AaruFormat image context for later serialization during image finalization. Media tags represent higher-level descriptors and metadata structures that characterize the storage medium beyond sector data, including disc information structures, lead-in/lead-out data, manufacturer identifiers, drive capabilities, and format-specific metadata. The function uses a hash table for efficient tag storage and retrieval, automatically replacing existing tags of the same type and managing memory for tag data.</p>
<p><b>Supported Media Tag Categories:</b></p>
<p><b>Optical Disc Metadata (CD/DVD/BD/HD DVD):</b></p><ul>
<li><b>CD_TOC (0)</b>: Table of Contents from READ TOC/PMA/ATIP command (Format 0000b - Formatted TOC)<ul>
<li>Contains track entries, session boundaries, lead-in/lead-out addressing, and track types</li>
<li>Essential for multi-session and mixed-mode CD structure representation</li>
</ul>
</li>
<li><b>CD_FullTOC (1)</b>: Full TOC (Format 0010b) including session info and point/ADR/control fields<ul>
<li>Provides complete session structure with ADR field interpretation and sub-Q channel details</li>
</ul>
</li>
<li><b>CD_SessionInfo (2)</b>: Session information (Format 0001b) for multi-session discs</li>
<li><b>CD_TEXT (3)</b>: CD-TEXT data from lead-in area (artist, title, performer, songwriter metadata)</li>
<li><b>CD_ATIP (4)</b>: Absolute Time In Pregroove (CD-R/RW timing calibration and media manufacturer data)</li>
<li><b>CD_PMA (5)</b>: Power Management Area (CD-R/RW recording session management metadata)</li>
<li><b>DVD_PFI (6)</b>: Physical Format Information (DVD layer characteristics, book type, linear density)</li>
<li><b>DVD_DMI (7)</b>: Disc Manufacturing Information (DVD unique identifier and replication metadata)</li>
<li><b>DVD_BCA (8)</b>: Burst Cutting Area (copy protection and regional management data for DVD-Video)</li>
<li><b>BD_DI (28)</b>: Disc Information (Blu-ray layer count, recording format, disc size, channel bit length)</li>
<li><b>BD_BCA (29)</b>: Blu-ray Burst Cutting Area (unique disc identifier and anti-counterfeiting data)</li>
</ul>
<p><b>Recordable Media Structures:</b></p><ul>
<li><b>DVDR_RMD (17)</b>: Recorded Media Data (last border-out RMD for DVD-R/-RW finalization state)</li>
<li><b>DVDR_PreRecordedInfo (18)</b>: Pre-recorded information area from lead-in (DVD-R physical specs)</li>
<li><b>DVDR_MediaIdentifier (19)</b>: Writable media identifier (DVD-R/-RW unique ID from manufacturer)</li>
<li><b>BD_DDS (30)</b>: Disc Definition Structure (BD-R/RE recording management and spare area allocation)</li>
<li><b>BD_SpareArea (32)</b>: BD spare area allocation map (defect management for recordable Blu-ray)</li>
</ul>
<p><b>Copy Protection and Security:</b></p><ul>
<li><b>AACS_VolumeIdentifier (33)</b>: AACS Volume Identifier (content identifier for AACS-protected media)</li>
<li><b>AACS_SerialNumber (34)</b>: Pre-recorded media serial number (unique per AACS disc pressing)</li>
<li><b>AACS_MediaIdentifier (35)</b>: AACS Media Identifier (cryptographic binding to physical medium)</li>
<li><b>AACS_MKB (36)</b>: AACS Media Key Block (encrypted title keys and revocation lists)</li>
<li><b>AACS_DataKeys (37)</b>: Extracted AACS title/volume keys (when decrypted, for archival purposes)</li>
<li><b>AACS_CPRM_MKB (39)</b>: CPRM Media Key Block (Content Protection for Recordable Media)</li>
</ul>
<p><b>Device and Drive Information:</b></p><ul>
<li><b>SCSI_INQUIRY (45)</b>: SCSI INQUIRY standard data (device type, vendor, model, firmware revision)</li>
<li><b>SCSI_MODEPAGE_2A (46)</b>: SCSI Mode Page 2Ah (CD/DVD/BD capabilities and supported features)</li>
<li><b>ATA_IDENTIFY (47)</b>: ATA IDENTIFY DEVICE response (512 bytes of drive capabilities and geometry)</li>
<li><b>ATAPI_IDENTIFY (48)</b>: ATA PACKET IDENTIFY DEVICE (ATAPI drive identification and features)</li>
<li><b>MMC_WriteProtection (41)</b>: Write protection status from MMC GET CONFIGURATION command</li>
<li><b>MMC_DiscInformation (42)</b>: Disc Information (recordable status, erasable flag, last session)</li>
</ul>
<p><b>Flash and Solid-State Media:</b></p><ul>
<li><b>SD_CID (50)</b>: SecureDigital Card ID register (manufacturer, OEM, product name, serial number)</li>
<li><b>SD_CSD (51)</b>: SecureDigital Card Specific Data (capacity, speed class, file format)</li>
<li><b>SD_SCR (52)</b>: SecureDigital Configuration Register (SD spec version, bus widths, security)</li>
<li><b>SD_OCR (53)</b>: SecureDigital Operation Conditions Register (voltage ranges, capacity type)</li>
<li><b>MMC_CID (54)</b>: MMC Card ID (similar to SD_CID for eMMC/MMC devices)</li>
<li><b>MMC_CSD (55)</b>: MMC Card Specific Data (MMC device parameters)</li>
<li><b>MMC_ExtendedCSD (57)</b>: MMC Extended CSD (512 bytes of extended MMC capabilities)</li>
</ul>
<p><b>Gaming Console Media:</b></p><ul>
<li><b>Xbox_SecuritySector (58)</b>: Xbox/Xbox 360 Security Sector (SS.bin - anti-piracy signature data)</li>
<li><b>Xbox_DMI (66)</b>: Xbox Disc Manufacturing Info (manufacturing plant and batch metadata)</li>
<li><b>Xbox_PFI (67)</b>: Xbox Physical Format Information (Xbox-specific DVD layer configuration)</li>
</ul>
<p><b>Specialized Structures:</b></p><ul>
<li><b>CD_FirstTrackPregap (61)</b>: First track pregap (index 0 contents, typically silent on audio CDs)</li>
<li><b>CD_LeadOut (62)</b>: Lead-out area contents (post-data region signaling disc end)</li>
<li><b>CD_LeadIn (68)</b>: Raw lead-in data (TOC frames and sub-Q channel from pre-data region)</li>
<li><b>Floppy_LeadOut (59)</b>: Manufacturer/duplication cylinder (floppy copy protection metadata)</li>
<li><b>PCMCIA_CIS (49)</b>: PCMCIA/CardBus Card Information Structure tuple chain</li>
<li><b>USB_Descriptors (65)</b>: Concatenated USB descriptors (device/config/interface for USB drives)</li>
</ul>
<p><b>Data Processing Pipeline:</b></p><ol type="1">
<li><b>Context Validation</b>: Verifies context is valid AaruFormat context with write permissions</li>
<li><b>Parameter Validation</b>: Checks data pointer is non-NULL and length is non-zero</li>
<li><b>Memory Allocation</b>: Allocates new buffer for tag data and <a class="el" href="structmediaTagEntry.html" title="Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).">mediaTagEntry</a> structure</li>
<li><b>Data Copying</b>: Performs deep copy of tag data to ensure context owns the memory</li>
<li><b>Hash Table Insertion</b>: Adds or replaces entry in mediaTags hash table using uthash HASH_REPLACE_INT</li>
<li><b>Cleanup</b>: Frees old media tag entry and data if replacement occurred</li>
<li><b>Return Success</b>: Returns AARUF_STATUS_OK on successful completion</li>
</ol>
<p><b>Memory Management Strategy:</b></p><ul>
<li><b>Deep Copy Semantics</b>: Function performs deep copy of input data; caller retains ownership of original buffer</li>
<li><b>Automatic Replacement</b>: Existing tag of same type is automatically freed when replaced</li>
<li><b>Hash Table Storage</b>: Media tags stored in uthash-based hash table for O(1) lookup by type</li>
<li><b>Deferred Serialization</b>: Tag data remains in memory until <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> serializes to image file</li>
<li><b>Cleanup on Close</b>: All media tag memory automatically freed during <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a></li>
</ul>
<p><b>Tag Type Identification:</b> The type parameter accepts <a class="el" href="group__MediaTags.html#gabdd09c559df8f34ae68fcb2ff1892ebe">MediaTagType</a> enumeration values (0-68) that identify the semantic meaning of the tag data. The library does not validate tag data structure or size against the type identifier - callers are responsible for providing correctly formatted tag data matching the declared type. Type values are preserved as-is and used during serialization to identify tag purpose during image reading.</p>
<p><b>Replacement Behavior:</b> When a media tag of the same type already exists in the context:</p><ul>
<li>The old tag entry is removed from the hash table</li>
<li>The old tag's data buffer is freed</li>
<li>The old tag entry structure is freed</li>
<li>The new tag replaces the old tag in the hash table</li>
<li>No warning or error is generated for replacement This allows incremental updates to media tags during image creation.</li>
</ul>
<p><b>Serialization and Persistence:</b> Media tags written via this function are not immediately written to the image file. Instead, they are accumulated in the context's mediaTags hash table and serialized during <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> as part of the image finalization process. The serialization creates a metadata block in the image file that preserves all media tags with their type identifiers and data lengths.</p>
<p><b>Thread Safety and Concurrency:</b> This function is NOT thread-safe. The context contains mutable shared state including:</p><ul>
<li>mediaTags hash table modification</li>
<li>Memory allocation and deallocation</li>
<li>No internal locking or synchronization External synchronization required for concurrent access from multiple threads.</li>
</ul>
<p><b>Performance Considerations:</b></p><ul>
<li>Hash table insertion is O(1) average case for new tags</li>
<li>Hash table replacement is O(1) for existing tags</li>
<li>Memory allocation overhead proportional to tag data size</li>
<li>No disk I/O occurs during this call (deferred to <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a>)</li>
<li>Suitable for frequent tag updates during image creation workflow</li>
</ul>
<p><b>Typical Usage Scenarios:</b></p><ul>
<li><b>Optical Disc Imaging</b>: Store TOC, PMA, ATIP, CD-TEXT from READ TOC family commands</li>
<li><b>Copy Protection Preservation</b>: Store BCA, AACS structures, media identifiers for archival</li>
<li><b>Drive Capabilities</b>: Store INQUIRY, Mode Page 2Ah, IDENTIFY data for forensic metadata</li>
<li><b>Flash Card Imaging</b>: Store CID, CSD, SCR, OCR registers from SD/MMC cards</li>
<li><b>Console Game Preservation</b>: Store Xbox security sectors and manufacturing metadata</li>
<li><b>Recordable Media</b>: Store RMD, media identifiers, spare area maps for write-once media</li>
</ul>
<p><b>Validation and Error Handling:</b></p><ul>
<li>Context validity checked via magic number comparison (AARU_MAGIC)</li>
<li>Write permission verified via isWriting flag</li>
<li>NULL data pointer triggers AARUF_ERROR_INCORRECT_DATA_SIZE</li>
<li>Zero length triggers AARUF_ERROR_INCORRECT_DATA_SIZE</li>
<li>Memory allocation failures return AARUF_ERROR_NOT_ENOUGH_MEMORY</li>
<li>No validation of tag data structure or size against type identifier</li>
</ul>
<p><b>Data Format Requirements:</b> The function accepts arbitrary binary data without format validation. Callers must ensure:</p><ul>
<li>Tag data matches the declared <a class="el" href="group__MediaTags.html#gabdd09c559df8f34ae68fcb2ff1892ebe">MediaTagType</a> structure and size</li>
<li>Binary data is properly byte-ordered for the target platform</li>
<li>Variable-length tags include proper internal length fields if required</li>
<li>Tag data represents a complete, self-contained structure</li>
</ul>
<p><b>Integration with Image Creation Workflow:</b> Media tags should typically be written after creating the image context (<a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a>) but before writing sector data. However, tags can be added or updated at any point during the writing process. Common workflow:</p><ol type="1">
<li>Create image context with <a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a></li>
<li>Set tracks with <a class="el" href="decls_8h.html#a518d8d68debf1b9a24af3eb6bc2f9e49" title="Replace (or clear) the in-memory track table for an AaruFormat image context.">aaruf_set_tracks()</a> if applicable</li>
<li>Write media tags with write_media_tag() for all available metadata</li>
<li>Write sector data with <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> or <a class="el" href="#a69ca66242c0becf7640b3d1cc8da8f9c" title="Writes a full (&quot;long&quot;) raw sector from optical or block media, parsing structure and validating conte...">aaruf_write_sector_long()</a></li>
<li>Close image with <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> to finalize and serialize all metadata</li>
</ol>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">context</td><td>Pointer to a valid aaruformatContext with magic == AARU_MAGIC opened for writing. Must be created via <a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a> and not yet closed. The context's isWriting flag must be true, indicating write mode is active. </td></tr>
<tr><td class="paramname">data</td><td>Pointer to the media tag data buffer to write. Must be a valid non-NULL pointer to a buffer containing the complete tag data. The function performs a deep copy of this data, so the caller retains ownership and may free or modify the source buffer after this call returns. The data format must match the structure expected for the specified type parameter. </td></tr>
<tr><td class="paramname">type</td><td>Integer identifier specifying the type of media tag (<a class="el" href="group__MediaTags.html#gabdd09c559df8f34ae68fcb2ff1892ebe">MediaTagType</a> enumeration). Values range from 0 (CD_TOC) to 68 (CD_LeadIn). The type identifies the semantic meaning of the tag data and is preserved in the image file for interpretation during reading. The library does not validate that the data structure matches the declared type - caller responsibility to ensure correctness. </td></tr>
<tr><td class="paramname">length</td><td>Length in bytes of the media tag data buffer. Must be greater than zero. Specifies how many bytes to copy from the data buffer. No maximum length enforced, but extremely large tags may cause memory allocation failures.</td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Returns one of the following status codes: </dd></dl>
<dl class="retval"><dt>Return values</dt><dd>
<table class="retval">
<tr><td class="paramname">AARUF_STATUS_OK</td><td>(0) Successfully wrote the media tag. This is returned when:<ul>
<li>Context is valid with correct magic number (AARU_MAGIC)</li>
<li>Context is in writing mode (isWriting == true)</li>
<li>Data pointer is non-NULL and length is non-zero</li>
<li>Memory allocation succeeded for both tag data and entry structure</li>
<li>Tag entry successfully inserted into mediaTags hash table</li>
<li>If replacing existing tag, old tag successfully freed</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_AARUFORMAT</td><td>(-1) Invalid context provided. This occurs when:<ul>
<li>context parameter is NULL (no context provided)</li>
<li>Context magic number != AARU_MAGIC (wrong context type, corrupted context, or uninitialized)</li>
<li>Context was not created by <a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a> or has been corrupted</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_READ_ONLY</td><td>(-22) Attempting to write to read-only image. This occurs when:<ul>
<li>Context isWriting flag is false</li>
<li>Image was opened with <a class="el" href="decls_8h.html#afc4932cdc795ffb2ef3a33d5b8c57656" title="Opens an existing AaruFormat image file.">aaruf_open()</a> instead of <a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a></li>
<li>Context is in read-only mode and modifications are not permitted</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_INCORRECT_DATA_SIZE</td><td>(-8) Invalid data or length parameters. This occurs when:<ul>
<li>data parameter is NULL (no tag data provided)</li>
<li>length parameter is zero (no data to write)</li>
<li>Parameters indicate invalid or empty tag data</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_ENOUGH_MEMORY</td><td>(-9) Memory allocation failed. This occurs when:<ul>
<li>Failed to allocate buffer for tag data copy (malloc(length) failed)</li>
<li>Failed to allocate <a class="el" href="structmediaTagEntry.html" title="Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).">mediaTagEntry</a> structure (malloc(sizeof(mediaTagEntry)) failed)</li>
<li>System is out of available memory for requested allocation size</li>
<li>Memory allocation fails due to resource exhaustion or fragmentation</li>
</ul>
</td></tr>
</table>
</dd>
</dl>
<dl class="section note"><dt>Note</dt><dd><b>Cross-References</b>: This function is the write counterpart to <a class="el" href="decls_8h.html#a48f93ec154d0aed7cb713391a7717b46" title="Reads a media tag from the AaruFormat image.">aaruf_read_media_tag()</a>. See also:<ul>
<li><a class="el" href="decls_8h.html#a48f93ec154d0aed7cb713391a7717b46" title="Reads a media tag from the AaruFormat image.">aaruf_read_media_tag()</a>: Reads media tag data from opened image</li>
<li><a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a>: Creates writable image context required for this function</li>
<li><a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a>: Serializes media tags to image file and frees tag memory</li>
<li><a class="el" href="group__MediaTags.html#gabdd09c559df8f34ae68fcb2ff1892ebe">MediaTagType</a> enumeration in <a class="el" href="aaru_8h.html" title="Public high-level API types: media classifications, per-sector / per-media tag enums and image summar...">aaru.h</a>: Defines valid type identifier values</li>
</ul>
</dd>
<dd>
<b>Memory Ownership</b>: The function performs a deep copy of tag data. After successful return, the context owns the copied tag data and the caller may free or modify the original data buffer. On failure, no memory is retained by the context - caller maintains full ownership of input buffer regardless of success or failure.</dd>
<dd>
<b>Tag Uniqueness</b>: Only one media tag of each type can exist in an image. Writing a tag with a type that already exists will replace the previous tag, freeing its memory and using the new tag data. No error or warning is generated for replacements.</dd>
<dd>
<b>Deferred Serialization</b>: Media tags are not written to disk until <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> is called. All tags remain in memory throughout the image creation process. For images with many or large media tags, memory usage may be significant.</dd>
<dd>
<b>No Type Validation</b>: The library does not validate that tag data matches the declared type. Callers must ensure data structure correctness. Mismatched data may cause reading applications to fail or misinterpret tag contents.</dd></dl>
<dl class="section warning"><dt>Warning</dt><dd><b>Memory Growth</b>: Each media tag consumes memory equal to tag data size plus <a class="el" href="structmediaTagEntry.html" title="Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).">mediaTagEntry</a> structure overhead. Large tags or many tags can significantly increase memory usage. Monitor memory consumption when writing extensive metadata.</dd>
<dd>
<b>Type Correctness</b>: No validation occurs for tag data format against type identifier. Providing incorrectly formatted data or mismatched type identifiers will create a valid image file with invalid tag data that may cause failures when reading. Ensure data format matches <a class="el" href="group__MediaTags.html#gabdd09c559df8f34ae68fcb2ff1892ebe">MediaTagType</a> specification requirements.</dd>
<dd>
<b>Replacement Silent</b>: Replacing an existing tag does not generate warnings or errors. Applications expecting to detect duplicate tag writes must track this externally. The most recent write_media_tag() call for each type determines the final tag value.</dd></dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="decls_8h.html#a48f93ec154d0aed7cb713391a7717b46" title="Reads a media tag from the AaruFormat image.">aaruf_read_media_tag()</a> for corresponding media tag reading functionality </dd>
<dd>
<a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a> for image context creation in write mode </dd>
<dd>
<a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> for media tag serialization and memory cleanup </dd>
<dd>
<a class="el" href="group__MediaTags.html#gabdd09c559df8f34ae68fcb2ff1892ebe">MediaTagType</a> enumeration for valid type identifier values and meanings </dd></dl>
<p class="definition">Definition at line <a class="el" href="write_8c_source.html#l01780">1780</a> of file <a class="el" href="write_8c_source.html">write.c</a>.</p>
<p class="reference">References <a class="el" href="consts_8h_source.html#l00064">AARU_MAGIC</a>, <a class="el" href="errors_8h_source.html#l00065">AARUF_ERROR_INCORRECT_DATA_SIZE</a>, <a class="el" href="errors_8h_source.html#l00040">AARUF_ERROR_NOT_AARUFORMAT</a>, <a class="el" href="errors_8h_source.html#l00048">AARUF_ERROR_NOT_ENOUGH_MEMORY</a>, <a class="el" href="errors_8h_source.html#l00061">AARUF_READ_ONLY</a>, <a class="el" href="errors_8h_source.html#l00075">AARUF_STATUS_OK</a>, <a class="el" href="context_8h_source.html#l00120">mediaTagEntry::data</a>, <a class="el" href="log_8h_source.html#l00040">FATAL</a>, <a class="el" href="context_8h_source.html#l00292">aaruformat_context::is_writing</a>, <a class="el" href="context_8h_source.html#l00122">mediaTagEntry::length</a>, <a class="el" href="context_8h_source.html#l00174">aaruformat_context::magic</a>, <a class="el" href="context_8h_source.html#l00264">aaruformat_context::mediaTags</a>, <a class="el" href="log_8h_source.html#l00025">TRACE</a>, and <a class="el" href="context_8h_source.html#l00121">mediaTagEntry::type</a>.</p>
</div>
</div>
<a id="a4b8cd2bb5fd9e2c670a0a13695c6f9e3" name="a4b8cd2bb5fd9e2c670a0a13695c6f9e3"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3">&#9670;&#160;</a></span>aaruf_write_sector()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int32_t aaruf_write_sector </td>
<td>(</td>
<td class="paramtype">void *</td> <td class="paramname"><span class="paramname"><em>context</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">uint64_t</td> <td class="paramname"><span class="paramname"><em>sector_address</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">bool</td> <td class="paramname"><span class="paramname"><em>negative</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const uint8_t *</td> <td class="paramname"><span class="paramname"><em>data</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">uint8_t</td> <td class="paramname"><span class="paramname"><em>sector_status</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">uint32_t</td> <td class="paramname"><span class="paramname"><em>length</em></span>&#160;)</td>
</tr>
</table>
</div><div class="memdoc">
<p>Writes a sector to the AaruFormat image. </p>
<p>Writes the given data to the specified sector address in the image, with the given status and length. This function handles buffering data into blocks, automatically closing blocks when necessary (sector size changes or block size limits are reached), and managing the deduplication table (DDT) entries.</p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">context</td><td>Pointer to the aaruformat context. </td></tr>
<tr><td class="paramname">sector_address</td><td>Logical sector address to write. </td></tr>
<tr><td class="paramname">negative</td><td>Indicates if the sector address is negative. </td></tr>
<tr><td class="paramname">data</td><td>Pointer to the data buffer to write. </td></tr>
<tr><td class="paramname">sector_status</td><td>Status of the sector to write. </td></tr>
<tr><td class="paramname">length</td><td>Length of the data buffer.</td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Returns one of the following status codes: </dd></dl>
<dl class="retval"><dt>Return values</dt><dd>
<table class="retval">
<tr><td class="paramname">AARUF_STATUS_OK</td><td>(0) Successfully wrote the sector data. This is returned when:<ul>
<li>The sector data is successfully copied to the writing buffer</li>
<li>The DDT entry is successfully updated for the sector address</li>
<li>Block management operations complete successfully</li>
<li>Buffer positions and offsets are properly updated</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_AARUFORMAT</td><td>(-1) The context is invalid. This occurs when:<ul>
<li>The context parameter is NULL</li>
<li>The context magic number doesn't match AARU_MAGIC (invalid context type)</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_READ_ONLY</td><td>(-22) Attempting to write to a read-only image. This occurs when:<ul>
<li>The context's isWriting flag is false</li>
<li>The image was opened in read-only mode</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_ENOUGH_MEMORY</td><td>(-9) Memory allocation failed. This occurs when:<ul>
<li>Failed to allocate memory for the writing buffer when creating a new block</li>
<li>The system is out of available memory for buffer allocation</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER</td><td>(-23) Failed to write block header to the image file. This can occur during automatic block closure when:<ul>
<li>The fwrite() call for the block header fails</li>
<li>Disk space is insufficient or file system errors occur</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA</td><td>(-24) Failed to write block data to the image file. This can occur during automatic block closure when:<ul>
<li>The fwrite() call for the block data fails</li>
<li>Disk space is insufficient or file system errors occur</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_SET_DDT_ENTRY</td><td>(-25) Failed to update the deduplication table (DDT) entry. This occurs when:<ul>
<li>The DDT entry for the specified sector address could not be set or updated</li>
<li>Internal DDT management functions return failure</li>
<li>DDT table corruption or memory issues prevent entry updates</li>
</ul>
</td></tr>
</table>
</dd>
</dl>
<dl class="section note"><dt>Note</dt><dd>Block Management:<ul>
<li>The function automatically closes the current block when sector size changes</li>
<li>Blocks are also closed when they reach the maximum size (determined by dataShift)</li>
<li>New blocks are created automatically when needed with appropriate headers</li>
</ul>
</dd>
<dd>
Memory Management:<ul>
<li>Writing buffers are allocated on-demand when creating new blocks</li>
<li>Buffer memory is freed when blocks are closed</li>
<li>Buffer size is calculated based on sector size and data shift parameters</li>
</ul>
</dd>
<dd>
DDT Updates:<ul>
<li>Each written sector updates the corresponding DDT entry</li>
<li>DDT entries track block offset, position, and sector status</li>
<li>Uses DDT version 2 format for entries</li>
</ul>
</dd></dl>
<dl class="section warning"><dt>Warning</dt><dd>The function may trigger automatic block closure, which can result in disk I/O operations and potential write errors even for seemingly simple sector writes. </dd></dl>
<p class="definition">Definition at line <a class="el" href="write_8c_source.html#l00098">98</a> of file <a class="el" href="write_8c_source.html">write.c</a>.</p>
<p class="reference">References <a class="el" href="consts_8h_source.html#l00064">AARU_MAGIC</a>, <a class="el" href="write_8c_source.html#l01383">aaruf_close_current_block()</a>, <a class="el" href="errors_8h_source.html#l00064">AARUF_ERROR_CANNOT_SET_DDT_ENTRY</a>, <a class="el" href="errors_8h_source.html#l00040">AARUF_ERROR_NOT_AARUFORMAT</a>, <a class="el" href="errors_8h_source.html#l00048">AARUF_ERROR_NOT_ENOUGH_MEMORY</a>, <a class="el" href="errors_8h_source.html#l00044">AARUF_ERROR_SECTOR_OUT_OF_BOUNDS</a>, <a class="el" href="md5_8c_source.html#l00436">aaruf_md5_update()</a>, <a class="el" href="errors_8h_source.html#l00061">AARUF_READ_ONLY</a>, <a class="el" href="sha1_8c_source.html#l00089">aaruf_sha1_update()</a>, <a class="el" href="sha256_8c_source.html#l00090">aaruf_sha256_update()</a>, <a class="el" href="spamsum_8c_source.html#l00059">aaruf_spamsum_update()</a>, <a class="el" href="errors_8h_source.html#l00075">AARUF_STATUS_OK</a>, <a class="el" href="enums_8h_source.html#l00195">Audio</a>, <a class="el" href="context_8h_source.html#l00268">aaruformat_context::blake3_context</a>, <a class="el" href="context_8h_source.html#l00277">aaruformat_context::calculating_blake3</a>, <a class="el" href="context_8h_source.html#l00273">aaruformat_context::calculating_md5</a>, <a class="el" href="context_8h_source.html#l00274">aaruformat_context::calculating_sha1</a>, <a class="el" href="context_8h_source.html#l00275">aaruformat_context::calculating_sha256</a>, <a class="el" href="context_8h_source.html#l00276">aaruformat_context::calculating_spamsum</a>, <a class="el" href="data_8h_source.html#l00074">BlockHeader::compression</a>, <a class="el" href="context_8h_source.html#l00299">aaruformat_context::compression_enabled</a>, <a class="el" href="context_8h_source.html#l00281">aaruformat_context::current_block_header</a>, <a class="el" href="context_8h_source.html#l00288">aaruformat_context::current_block_offset</a>, <a class="el" href="context_8h_source.html#l00290">aaruformat_context::current_track_type</a>, <a class="el" href="enums_8h_source.html#l00196">Data</a>, <a class="el" href="enums_8h_source.html#l00141">DataBlock</a>, <a class="el" href="ddt_8h_source.html#l00155">DdtHeader2::dataShift</a>, <a class="el" href="context_8h_source.html#l00298">aaruformat_context::deduplicate</a>, <a class="el" href="optical_8h_source.html#l00076">TrackEntry::end</a>, <a class="el" href="optical_8h_source.html#l00064">TracksHeader::entries</a>, <a class="el" href="log_8h_source.html#l00040">FATAL</a>, <a class="el" href="enums_8h_source.html#l00035">Flac</a>, <a class="el" href="data_8h_source.html#l00072">BlockHeader::identifier</a>, <a class="el" href="context_8h_source.html#l00260">aaruformat_context::image_info</a>, <a class="el" href="hash__map_8c_source.html#l00153">insert_map()</a>, <a class="el" href="context_8h_source.html#l00292">aaruformat_context::is_writing</a>, <a class="el" href="aaru_8h_source.html#l00232">JaguarCD</a>, <a class="el" href="context_8h_source.html#l00283">aaruformat_context::last_written_block</a>, <a class="el" href="hash__map_8c_source.html#l00196">lookup_map()</a>, <a class="el" href="enums_8h_source.html#l00034">Lzma</a>, <a class="el" href="context_8h_source.html#l00174">aaruformat_context::magic</a>, <a class="el" href="context_8h_source.html#l00270">aaruformat_context::md5_context</a>, <a class="el" href="aaru_8h_source.html#l00881">ImageInfo::MediaType</a>, <a class="el" href="aaru_8h_source.html#l00882">ImageInfo::MetadataMediaType</a>, <a class="el" href="ddt_8h_source.html#l00149">DdtHeader2::negative</a>, <a class="el" href="context_8h_source.html#l00282">aaruformat_context::next_block_position</a>, <a class="el" href="enums_8h_source.html#l00033">None</a>, <a class="el" href="enums_8h_source.html#l00218">OpticalDisc</a>, <a class="el" href="ddt_8h_source.html#l00151">DdtHeader2::overflow</a>, <a class="el" href="context_8h_source.html#l00293">aaruformat_context::rewinded</a>, <a class="el" href="context_8h_source.html#l00253">aaruformat_context::sector_hash_map</a>, <a class="el" href="aaru_8h_source.html#l00874">ImageInfo::Sectors</a>, <a class="el" href="data_8h_source.html#l00075">BlockHeader::sectorSize</a>, <a class="el" href="optical_8h_source.html#l00073">TrackEntry::sequence</a>, <a class="el" href="optical_8h_source.html#l00078">TrackEntry::session</a>, <a class="el" href="ddt__v2_8c_source.html#l00988">set_ddt_entry_v2()</a>, <a class="el" href="context_8h_source.html#l00271">aaruformat_context::sha1_context</a>, <a class="el" href="context_8h_source.html#l00272">aaruformat_context::sha256_context</a>, <a class="el" href="context_8h_source.html#l00267">aaruformat_context::spamsum_context</a>, <a class="el" href="optical_8h_source.html#l00075">TrackEntry::start</a>, <a class="el" href="log_8h_source.html#l00025">TRACE</a>, <a class="el" href="context_8h_source.html#l00242">aaruformat_context::track_entries</a>, <a class="el" href="context_8h_source.html#l00244">aaruformat_context::tracks_header</a>, <a class="el" href="data_8h_source.html#l00073">BlockHeader::type</a>, <a class="el" href="optical_8h_source.html#l00074">TrackEntry::type</a>, <a class="el" href="context_8h_source.html#l00189">aaruformat_context::user_data_ddt_header</a>, <a class="el" href="enums_8h_source.html#l00046">UserData</a>, <a class="el" href="aaru_8h_source.html#l00771">VideoNow</a>, <a class="el" href="aaru_8h_source.html#l00772">VideoNowColor</a>, <a class="el" href="aaru_8h_source.html#l00773">VideoNowXp</a>, <a class="el" href="context_8h_source.html#l00280">aaruformat_context::writing_buffer</a>, <a class="el" href="context_8h_source.html#l00289">aaruformat_context::writing_buffer_position</a>, and <a class="el" href="context_8h_source.html#l00294">aaruformat_context::writing_long</a>.</p>
<p class="reference">Referenced by <a class="el" href="write_8c_source.html#l00532">aaruf_write_sector_long()</a>.</p>
</div>
</div>
<a id="a69ca66242c0becf7640b3d1cc8da8f9c" name="a69ca66242c0becf7640b3d1cc8da8f9c"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a69ca66242c0becf7640b3d1cc8da8f9c">&#9670;&#160;</a></span>aaruf_write_sector_long()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int32_t aaruf_write_sector_long </td>
<td>(</td>
<td class="paramtype">void *</td> <td class="paramname"><span class="paramname"><em>context</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">uint64_t</td> <td class="paramname"><span class="paramname"><em>sector_address</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">bool</td> <td class="paramname"><span class="paramname"><em>negative</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const uint8_t *</td> <td class="paramname"><span class="paramname"><em>data</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">uint8_t</td> <td class="paramname"><span class="paramname"><em>sector_status</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">uint32_t</td> <td class="paramname"><span class="paramname"><em>length</em></span>&#160;)</td>
</tr>
</table>
</div><div class="memdoc">
<p>Writes a full ("long") raw sector from optical or block media, parsing structure and validating content. </p>
<p>This function processes complete raw sectors including structural metadata, error correction codes, and subchannel information. It is the primary entry point for ingesting raw sector data where the caller provides the complete sector including synchronization patterns, headers, user data, and error correction information. The function intelligently parses the sector structure based on media type and track information, validates correctness, and delegates user data writing to <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a>.</p>
<p>Supported Media Types and Sector Formats:</p>
<p><b>Optical Disc Media (2352-byte sectors):</b></p><ul>
<li><b>Audio tracks</b>: Raw PCM audio data (2352 bytes) passed directly to <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a></li>
<li><b>Data tracks</b>: Raw data sectors passed directly to <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a></li>
<li><b>CD Mode 1</b>: Sync(12) + Header(4) + <a class="el" href="enums_8h.html#ad8ed01ff3ff33333d8e19db4d2818bb6a73bb26133ccd01972725933b00ec3a06" title="User (main) data.">UserData(2048)</a> + EDC(4) + Reserved(8) + ECC_P(172) + ECC_Q(104)<ul>
<li>Validates sync pattern (00 FF FF FF FF FF FF FF FF FF FF 00), mode byte (01), and MSF timing</li>
<li>Checks EDC/ECC correctness using <a class="el" href="decls_8h.html#afbc09e16b1a654de04706e07c3212ecb" title="Checks if the suffix (EDC/ECC) of a CD sector is correct (Mode 1).">aaruf_ecc_cd_is_suffix_correct()</a></li>
<li>Stores anomalous prefixes/suffixes in separate buffers with mini-DDT indexing</li>
</ul>
</li>
<li><b>CD Mode 2 Form 1</b>: Sync(12) + Header(4) + Subheader(8) + <a class="el" href="enums_8h.html#ad8ed01ff3ff33333d8e19db4d2818bb6a73bb26133ccd01972725933b00ec3a06" title="User (main) data.">UserData(2048)</a> + EDC(4) + ECC_P(172) + ECC_Q(104)<ul>
<li>Validates sync pattern, mode byte (02), and Form 1 identification in subheader</li>
<li>Checks both EDC and ECC correctness for Form 1 sectors</li>
<li>Extracts and stores 8-byte subheader separately in mode2_subheaders buffer</li>
</ul>
</li>
<li><b>CD Mode 2 Form 2</b>: Sync(12) + Header(4) + Subheader(8) + <a class="el" href="enums_8h.html#ad8ed01ff3ff33333d8e19db4d2818bb6a73bb26133ccd01972725933b00ec3a06" title="User (main) data.">UserData(2324)</a> + EDC(4)<ul>
<li>Validates sync pattern, mode byte (02), and Form 2 identification in subheader</li>
<li>Checks EDC correctness, handles missing EDC (zero) as valid state</li>
<li>No ECC validation for Form 2 sectors (not present in format)</li>
</ul>
</li>
<li><b>CD Mode 2 Formless</b>: Similar to Form 2 but without form determination from subheader</li>
</ul>
<p><b>Block Media (512+ byte sectors with tags):</b></p><ul>
<li><b>Apple Profile/FileWare</b>: 512-byte sectors + 20-byte Profile tags</li>
<li><b>Apple Sony SS/DS</b>: 512-byte sectors + 12-byte Sony tags</li>
<li><b>Apple Widget</b>: 512-byte sectors with tag conversion support</li>
<li><b>Priam DataTower</b>: 512-byte sectors + 24-byte Priam tags</li>
<li>Supports automatic tag format conversion between Sony (12), Profile (20), and Priam (24) byte formats</li>
<li>Tag data stored in sector_subchannel buffer for preservation</li>
</ul>
<p><b>Data Processing Pipeline:</b></p><ol type="1">
<li><b>Context and Parameter Validation</b>: Verifies context magic, write permissions, and sector bounds</li>
<li><b>Track Resolution</b>: Locates track entry covering the sector address to determine track type</li>
<li><b>Rewind Detection</b>: Detects out-of-order writing and disables hash calculations to maintain integrity</li>
<li><b>Hash Updates</b>: Updates MD5, SHA1, SHA256, SpamSum, and BLAKE3 contexts for user-range sectors</li>
<li><b>Structure Parsing</b>: Splits raw sector into prefix, user data, and suffix components</li>
<li><b>Validation</b>: Checks sync patterns, timing fields, EDC/ECC correctness, and format compliance</li>
<li><b>Metadata Storage</b>: Stores anomalous or non-standard components in dedicated buffers</li>
<li><b>User Data Delegation</b>: Calls <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> with extracted user data and derived status</li>
</ol>
<p><b>Memory Management Strategy:</b></p><ul>
<li><b>DDT Arrays</b>: Lazily allocated 64-bit arrays sized for total addressable space (negative + user + overflow)<ul>
<li>sectorPrefixDdt2: Tracks prefix status and buffer offsets (high 4 bits = status, low 60 bits = offset/16)</li>
<li>sectorSuffixDdt2: Tracks suffix status and buffer offsets (high 4 bits = status, low 60 bits = offset/288)</li>
</ul>
</li>
<li><b>Prefix Buffer</b>: Dynamically growing buffer storing non-standard 16-byte CD prefixes</li>
<li><b>Suffix Buffer</b>: Dynamically growing buffer storing non-standard CD suffixes (288 bytes for Mode 1, 4 bytes for Mode 2 Form 2, 280 bytes for Mode 2 Form 1)</li>
<li><b>Subheader Buffer</b>: Fixed-size buffer (8 bytes per sector) for Mode 2 subheaders</li>
<li><b>Subchannel Buffer</b>: Fixed-size buffer for block media tag data</li>
<li>All buffers use doubling reallocation strategy when capacity exceeded</li>
</ul>
<p><b>Address Space Management:</b> The function handles three logical address regions:</p><ul>
<li><b>Negative Region</b>: Pre-gap sectors (sector_address &lt; negative region size, negative=true)</li>
<li><b>User Region</b>: Main data sectors (0 ≤ sector_address &lt; Sectors, negative=false)</li>
<li><b>Overflow Region</b>: Post-data sectors (sector_address ≥ Sectors, negative=false) Internal corrected_sector_address provides linear indexing: corrected = address ± negative_size</li>
</ul>
<p><b>Sector Status Classification:</b> Status codes stored in high nibble of mini-DDT entries:</p><ul>
<li><b>SectorStatusMode1Correct</b>: Valid Mode 1 sector with correct sync, timing, EDC, and ECC</li>
<li><b>SectorStatusMode2Form1Ok</b>: Valid Mode 2 Form 1 with correct subheader, EDC, and ECC</li>
<li><b>SectorStatusMode2Form2Ok</b>: Valid Mode 2 Form 2 with correct subheader and EDC</li>
<li><b>SectorStatusMode2Form2NoCrc</b>: Mode 2 Form 2 with zero EDC (acceptable state)</li>
<li><b>SectorStatusErrored</b>: Sector with validation errors, anomalous data stored in buffers</li>
<li><b>SectorStatusNotDumped</b>: All-zero sectors treated as not dumped</li>
</ul>
<p><b>Deduplication Integration:</b> Long sector processing does not directly perform deduplication - this occurs in the delegated <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> call for the extracted user data portion. The prefix/suffix/subheader metadata is stored separately and not subject to deduplication.</p>
<p><b>Hash Calculation Behavior:</b></p><ul>
<li>Hashes computed on complete raw sector data (all 2352 bytes for optical, full tag+data for block)</li>
<li>Only performed for sectors in user address range (not negative or overflow regions)</li>
<li>Permanently disabled upon rewind detection to prevent corrupted streaming digests</li>
<li>Supports MD5, SHA1, SHA256, SpamSum, and BLAKE3 simultaneously when enabled</li>
</ul>
<p><b>Error Recovery and Validation:</b></p><ul>
<li>Sync pattern validation for optical sectors (CD standard 12-byte sync)</li>
<li>MSF timing validation (Minutes:Seconds:Frames converted to LBA must match sector_address)</li>
<li>Mode byte validation (01 for Mode 1, 02 for Mode 2)</li>
<li>EDC validation using <a class="el" href="decls_8h.html#a67c65c3f2ca5cdf1596c16fa35558df1" title="Computes the EDC (Error Detection Code) for a CD sector.">aaruf_edc_cd_compute()</a> for computed vs stored comparison</li>
<li>ECC validation using <a class="el" href="decls_8h.html#afbc09e16b1a654de04706e07c3212ecb" title="Checks if the suffix (EDC/ECC) of a CD sector is correct (Mode 1).">aaruf_ecc_cd_is_suffix_correct()</a> and <a class="el" href="decls_8h.html#ab77ca170a2e8d2f0a2a7ea1a8a51690a" title="Checks if the suffix (EDC/ECC) of a CD sector is correct (Mode 2).">aaruf_ecc_cd_is_suffix_correct_mode2()</a></li>
<li>Form determination from subheader flags (bit 5 of bytes 18 and 22)</li>
<li>Tag format validation and conversion for block media</li>
</ul>
<p><b>Thread Safety and Concurrency:</b> This function is NOT thread-safe. The context contains mutable shared state including:</p><ul>
<li>Buffer pointers and offsets</li>
<li>Hash computation contexts</li>
<li>Rewind detection state</li>
<li>DDT modification operations External synchronization required for concurrent access.</li>
</ul>
<p><b>Performance Considerations:</b></p><ul>
<li>Buffer allocation occurs lazily on first use</li>
<li>Buffer growth uses doubling strategy to amortize allocation cost</li>
<li>Validation operations are optimized for common cases (correct sectors)</li>
<li>Memory copying minimized for standard compliant sectors</li>
<li>Hash updates operate on full sector to maintain streaming performance</li>
</ul>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">context</td><td>Pointer to a valid aaruformatContext with magic == AARU_MAGIC opened for writing. </td></tr>
<tr><td class="paramname">sector_address</td><td>Logical Block Address (LBA) for the sector. For negative regions, this is the negative-space address; for user/overflow regions, this is the standard 0-based LBA. </td></tr>
<tr><td class="paramname">negative</td><td>true if sector_address refers to the negative (pre-gap) region; false for user or overflow regions. </td></tr>
<tr><td class="paramname">data</td><td>Pointer to the complete raw sector buffer. Must contain:<ul>
<li>For optical: exactly 2352 bytes of raw sector data</li>
<li>For block media: 512 bytes + tag data (12, 20, or 24 bytes depending on format) </li>
</ul>
</td></tr>
<tr><td class="paramname">sector_status</td><td>Initial sector status hint from caller. May be overridden based on validation results when delegating to <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a>. </td></tr>
<tr><td class="paramname">length</td><td>Length in bytes of the data buffer. Must be exactly 2352 for optical discs. For block media: 512 (no tags), 524 (Sony), 532 (Profile), or 536 (Priam).</td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Returns one of the following status codes: </dd></dl>
<dl class="retval"><dt>Return values</dt><dd>
<table class="retval">
<tr><td class="paramname">AARUF_STATUS_OK</td><td>(0) Sector successfully processed and user data written. This occurs when:<ul>
<li>Raw sector structure parsed and validated successfully</li>
<li>Prefix/suffix/subheader metadata stored appropriately</li>
<li>User data portion successfully delegated to <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a></li>
<li>All buffer allocations and DDT updates completed successfully</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_AARUFORMAT</td><td>(-1) Invalid context provided. This occurs when:<ul>
<li>context parameter is NULL</li>
<li>Context magic number != AARU_MAGIC (wrong context type or corruption)</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_READ_ONLY</td><td>(-22) Attempting to write to read-only image. This occurs when:<ul>
<li>Context isWriting flag is false</li>
<li>Image was opened without write permissions</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_SECTOR_OUT_OF_BOUNDS</td><td>(-7) Sector address outside valid ranges. This occurs when:<ul>
<li>negative=true and sector_address &gt;= negative region size</li>
<li>negative=false and sector_address &gt;= (Sectors + overflow region size)</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_INCORRECT_DATA_SIZE</td><td>(-8) Invalid sector size for media type. This occurs when:<ul>
<li>length != 2352 for optical disc media</li>
<li>length not in {512, 524, 532, 536} for supported block media types</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_ENOUGH_MEMORY</td><td>(-9) Memory allocation failed. This occurs when:<ul>
<li>Failed to allocate mini-DDT arrays (sectorPrefixDdt2, sectorSuffixDdt2)</li>
<li>Failed to allocate or grow prefix buffer (sector_prefix)</li>
<li>Failed to allocate or grow suffix buffer (sector_suffix)</li>
<li>Failed to allocate subheader buffer (mode2_subheaders)</li>
<li>Failed to allocate subchannel buffer (sector_subchannel)</li>
<li>System out of memory during buffer reallocation</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_INCORRECT_MEDIA_TYPE</td><td>(-26) Unsupported media type for long sectors. This occurs when:<ul>
<li>Media type is not OpticalDisc or supported BlockMedia variant</li>
<li>Block media type does not support the provided tag format</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_SET_DDT_ENTRY</td><td>(-25) DDT update failed. Propagated from <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> when:<ul>
<li>User data DDT entry could not be updated</li>
<li>DDT table corruption prevents entry modification</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER</td><td>(-23) Block header write failed. Propagated from <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> when:<ul>
<li>Automatic block closure triggered by user data write fails</li>
<li>File system error prevents header write</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA</td><td>(-24) Block data write failed. Propagated from <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> when:<ul>
<li>User data portion write fails during block flush</li>
<li>Insufficient disk space or I/O error occurs</li>
</ul>
</td></tr>
</table>
</dd>
</dl>
<dl class="section note"><dt>Note</dt><dd><b>Cross-References</b>: This function is the primary companion to <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> for raw sector ingestion. See also:<ul>
<li><a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a>: Handles user data portion writing and deduplication</li>
<li><a class="el" href="decls_8h.html#afbc09e16b1a654de04706e07c3212ecb" title="Checks if the suffix (EDC/ECC) of a CD sector is correct (Mode 1).">aaruf_ecc_cd_is_suffix_correct()</a>: CD Mode 1 ECC validation</li>
<li><a class="el" href="decls_8h.html#ab77ca170a2e8d2f0a2a7ea1a8a51690a" title="Checks if the suffix (EDC/ECC) of a CD sector is correct (Mode 2).">aaruf_ecc_cd_is_suffix_correct_mode2()</a>: CD Mode 2 Form 1 ECC validation</li>
<li><a class="el" href="decls_8h.html#a67c65c3f2ca5cdf1596c16fa35558df1" title="Computes the EDC (Error Detection Code) for a CD sector.">aaruf_edc_cd_compute()</a>: EDC calculation and validation for all CD modes</li>
<li><a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a>: Serializes prefix/suffix/subheader metadata to image file</li>
</ul>
</dd>
<dd>
<b>Buffer Management</b>: All dynamically allocated buffers (prefix, suffix, subheader, subchannel) are automatically freed during <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a>. Applications should not attempt to access these buffers directly or free them manually.</dd>
<dd>
<b>Metadata Persistence</b>: Prefix, suffix, and subheader data captured by this function is serialized to the image file during <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> as separate metadata blocks with corresponding mini-DDT tables for efficient access during reading.</dd>
<dd>
<b>Tag Format Conversion</b>: For block media, automatic conversion between Sony, Profile, and Priam tag formats ensures compatibility regardless of source format. Conversion preserves all semantic information while adapting to target media type requirements.</dd></dl>
<dl class="section warning"><dt>Warning</dt><dd><b>Rewind Detection</b>: Writing sectors out of strictly increasing order triggers rewind detection, permanently disabling hash calculations for the session. This prevents corrupted streaming digests but means hash values will be unavailable if non-sequential writing occurs. Plan sector writing order carefully if digest calculation is required.</dd>
<dd>
<b>Memory Growth</b>: Prefix and suffix buffers grow dynamically and can consume significant memory for images with many non-standard sectors. Monitor memory usage when processing damaged or non-compliant optical media.</dd>
<dd>
<b>Media Type Constraints</b>: This function only supports OpticalDisc and specific BlockMedia types. Other media types will return AARUF_ERROR_INCORRECT_MEDIA_TYPE. Use <a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> directly for unsupported media types.</dd></dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="#a4b8cd2bb5fd9e2c670a0a13695c6f9e3" title="Writes a sector to the AaruFormat image.">aaruf_write_sector()</a> for user data writing and deduplication </dd>
<dd>
<a class="el" href="decls_8h.html#a719a992be38ee90a5e302725c18a791b" title="Reads a complete sector with all metadata from the AaruFormat image.">aaruf_read_sector_long()</a> for corresponding long sector reading functionality </dd>
<dd>
<a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> for metadata serialization and cleanup </dd></dl>
<p class="definition">Definition at line <a class="el" href="write_8c_source.html#l00532">532</a> of file <a class="el" href="write_8c_source.html">write.c</a>.</p>
<p class="reference">References <a class="el" href="consts_8h_source.html#l00064">AARU_MAGIC</a>, <a class="el" href="ecc__cd_8c_source.html#l00101">aaruf_ecc_cd_is_suffix_correct()</a>, <a class="el" href="ecc__cd_8c_source.html#l00165">aaruf_ecc_cd_is_suffix_correct_mode2()</a>, <a class="el" href="ecc__cd_8c_source.html#l00543">aaruf_edc_cd_compute()</a>, <a class="el" href="errors_8h_source.html#l00065">AARUF_ERROR_INCORRECT_DATA_SIZE</a>, <a class="el" href="errors_8h_source.html#l00051">AARUF_ERROR_INCORRECT_MEDIA_TYPE</a>, <a class="el" href="errors_8h_source.html#l00040">AARUF_ERROR_NOT_AARUFORMAT</a>, <a class="el" href="errors_8h_source.html#l00048">AARUF_ERROR_NOT_ENOUGH_MEMORY</a>, <a class="el" href="errors_8h_source.html#l00044">AARUF_ERROR_SECTOR_OUT_OF_BOUNDS</a>, <a class="el" href="md5_8c_source.html#l00436">aaruf_md5_update()</a>, <a class="el" href="errors_8h_source.html#l00061">AARUF_READ_ONLY</a>, <a class="el" href="sha1_8c_source.html#l00089">aaruf_sha1_update()</a>, <a class="el" href="sha256_8c_source.html#l00090">aaruf_sha256_update()</a>, <a class="el" href="spamsum_8c_source.html#l00059">aaruf_spamsum_update()</a>, <a class="el" href="write_8c_source.html#l00098">aaruf_write_sector()</a>, <a class="el" href="aaru_8h_source.html#l00249">AppleFileWare</a>, <a class="el" href="aaru_8h_source.html#l00698">AppleProfile</a>, <a class="el" href="aaru_8h_source.html#l00248">AppleSonyDS</a>, <a class="el" href="aaru_8h_source.html#l00247">AppleSonySS</a>, <a class="el" href="aaru_8h_source.html#l00699">AppleWidget</a>, <a class="el" href="enums_8h_source.html#l00195">Audio</a>, <a class="el" href="context_8h_source.html#l00268">aaruformat_context::blake3_context</a>, <a class="el" href="enums_8h_source.html#l00219">BlockMedia</a>, <a class="el" href="lisa__tag_8c_source.html#l00112">bytes_to_priam_tag()</a>, <a class="el" href="lisa__tag_8c_source.html#l00142">bytes_to_profile_tag()</a>, <a class="el" href="lisa__tag_8c_source.html#l00082">bytes_to_sony_tag()</a>, <a class="el" href="context_8h_source.html#l00277">aaruformat_context::calculating_blake3</a>, <a class="el" href="context_8h_source.html#l00273">aaruformat_context::calculating_md5</a>, <a class="el" href="context_8h_source.html#l00274">aaruformat_context::calculating_sha1</a>, <a class="el" href="context_8h_source.html#l00275">aaruformat_context::calculating_sha256</a>, <a class="el" href="context_8h_source.html#l00276">aaruformat_context::calculating_spamsum</a>, <a class="el" href="enums_8h_source.html#l00197">CdMode1</a>, <a class="el" href="enums_8h_source.html#l00199">CdMode2Form1</a>, <a class="el" href="enums_8h_source.html#l00200">CdMode2Form2</a>, <a class="el" href="enums_8h_source.html#l00198">CdMode2Formless</a>, <a class="el" href="enums_8h_source.html#l00196">Data</a>, <a class="el" href="aaru_8h_source.html#l00146">DVDDownload</a>, <a class="el" href="aaru_8h_source.html#l00139">DVDPR</a>, <a class="el" href="aaru_8h_source.html#l00143">DVDPRDL</a>, <a class="el" href="aaru_8h_source.html#l00140">DVDPRW</a>, <a class="el" href="aaru_8h_source.html#l00141">DVDPRWDL</a>, <a class="el" href="aaru_8h_source.html#l00137">DVDR</a>, <a class="el" href="aaru_8h_source.html#l00144">DVDRAM</a>, <a class="el" href="aaru_8h_source.html#l00142">DVDRDL</a>, <a class="el" href="aaru_8h_source.html#l00136">DVDROM</a>, <a class="el" href="aaru_8h_source.html#l00138">DVDRW</a>, <a class="el" href="aaru_8h_source.html#l00145">DVDRWDL</a>, <a class="el" href="context_8h_source.html#l00248">aaruformat_context::ecc_cd_context</a>, <a class="el" href="optical_8h_source.html#l00076">TrackEntry::end</a>, <a class="el" href="optical_8h_source.html#l00064">TracksHeader::entries</a>, <a class="el" href="log_8h_source.html#l00040">FATAL</a>, <a class="el" href="context_8h_source.html#l00260">aaruformat_context::image_info</a>, <a class="el" href="context_8h_source.html#l00292">aaruformat_context::is_writing</a>, <a class="el" href="context_8h_source.html#l00283">aaruformat_context::last_written_block</a>, <a class="el" href="context_8h_source.html#l00174">aaruformat_context::magic</a>, <a class="el" href="context_8h_source.html#l00270">aaruformat_context::md5_context</a>, <a class="el" href="aaru_8h_source.html#l00881">ImageInfo::MediaType</a>, <a class="el" href="aaru_8h_source.html#l00882">ImageInfo::MetadataMediaType</a>, <a class="el" href="context_8h_source.html#l00204">aaruformat_context::mode2_subheaders</a>, <a class="el" href="ddt_8h_source.html#l00149">DdtHeader2::negative</a>, <a class="el" href="aaru_8h_source.html#l00238">Nuon</a>, <a class="el" href="enums_8h_source.html#l00218">OpticalDisc</a>, <a class="el" href="ddt_8h_source.html#l00151">DdtHeader2::overflow</a>, <a class="el" href="lisa__tag_8c_source.html#l00409">priam_tag_to_bytes()</a>, <a class="el" href="lisa__tag_8c_source.html#l00325">priam_tag_to_profile()</a>, <a class="el" href="lisa__tag_8c_source.html#l00291">priam_tag_to_sony()</a>, <a class="el" href="aaru_8h_source.html#l00701">PriamDataTower</a>, <a class="el" href="lisa__tag_8c_source.html#l00357">profile_tag_to_bytes()</a>, <a class="el" href="lisa__tag_8c_source.html#l00228">profile_tag_to_priam()</a>, <a class="el" href="lisa__tag_8c_source.html#l00257">profile_tag_to_sony()</a>, <a class="el" href="aaru_8h_source.html#l00205">PS2DVD</a>, <a class="el" href="aaru_8h_source.html#l00206">PS3DVD</a>, <a class="el" href="context_8h_source.html#l00293">aaruformat_context::rewinded</a>, <a class="el" href="aaru_8h_source.html#l00121">SACD</a>, <a class="el" href="context_8h_source.html#l00207">aaruformat_context::sector_cpr_mai</a>, <a class="el" href="context_8h_source.html#l00208">aaruformat_context::sector_edc</a>, <a class="el" href="context_8h_source.html#l00205">aaruformat_context::sector_id</a>, <a class="el" href="context_8h_source.html#l00206">aaruformat_context::sector_ied</a>, <a class="el" href="context_8h_source.html#l00199">aaruformat_context::sector_prefix</a>, <a class="el" href="context_8h_source.html#l00185">aaruformat_context::sector_prefix_ddt2</a>, <a class="el" href="context_8h_source.html#l00284">aaruformat_context::sector_prefix_length</a>, <a class="el" href="context_8h_source.html#l00286">aaruformat_context::sector_prefix_offset</a>, <a class="el" href="context_8h_source.html#l00203">aaruformat_context::sector_subchannel</a>, <a class="el" href="context_8h_source.html#l00201">aaruformat_context::sector_suffix</a>, <a class="el" href="context_8h_source.html#l00186">aaruformat_context::sector_suffix_ddt2</a>, <a class="el" href="context_8h_source.html#l00285">aaruformat_context::sector_suffix_length</a>, <a class="el" href="context_8h_source.html#l00287">aaruformat_context::sector_suffix_offset</a>, <a class="el" href="aaru_8h_source.html#l00874">ImageInfo::Sectors</a>, <a class="el" href="enums_8h_source.html#l00232">SectorStatusErrored</a>, <a class="el" href="enums_8h_source.html#l00233">SectorStatusMode1Correct</a>, <a class="el" href="enums_8h_source.html#l00234">SectorStatusMode2Form1Ok</a>, <a class="el" href="enums_8h_source.html#l00236">SectorStatusMode2Form2NoCrc</a>, <a class="el" href="enums_8h_source.html#l00235">SectorStatusMode2Form2Ok</a>, <a class="el" href="enums_8h_source.html#l00230">SectorStatusNotDumped</a>, <a class="el" href="optical_8h_source.html#l00073">TrackEntry::sequence</a>, <a class="el" href="context_8h_source.html#l00271">aaruformat_context::sha1_context</a>, <a class="el" href="context_8h_source.html#l00272">aaruformat_context::sha256_context</a>, <a class="el" href="lisa__tag_8c_source.html#l00466">sony_tag_to_bytes()</a>, <a class="el" href="lisa__tag_8c_source.html#l00201">sony_tag_to_priam()</a>, <a class="el" href="lisa__tag_8c_source.html#l00173">sony_tag_to_profile()</a>, <a class="el" href="context_8h_source.html#l00267">aaruformat_context::spamsum_context</a>, <a class="el" href="optical_8h_source.html#l00075">TrackEntry::start</a>, <a class="el" href="log_8h_source.html#l00025">TRACE</a>, <a class="el" href="context_8h_source.html#l00242">aaruformat_context::track_entries</a>, <a class="el" href="context_8h_source.html#l00244">aaruformat_context::tracks_header</a>, <a class="el" href="optical_8h_source.html#l00074">TrackEntry::type</a>, <a class="el" href="context_8h_source.html#l00189">aaruformat_context::user_data_ddt_header</a>, and <a class="el" href="context_8h_source.html#l00294">aaruformat_context::writing_long</a>.</p>
</div>
</div>
<a id="a2dc7f13b0cd44153f1456d3ed4c15a0c" name="a2dc7f13b0cd44153f1456d3ed4c15a0c"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a2dc7f13b0cd44153f1456d3ed4c15a0c">&#9670;&#160;</a></span>aaruf_write_sector_tag()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int32_t aaruf_write_sector_tag </td>
<td>(</td>
<td class="paramtype">void *</td> <td class="paramname"><span class="paramname"><em>context</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const uint64_t</td> <td class="paramname"><span class="paramname"><em>sector_address</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const bool</td> <td class="paramname"><span class="paramname"><em>negative</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const uint8_t *</td> <td class="paramname"><span class="paramname"><em>data</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const size_t</td> <td class="paramname"><span class="paramname"><em>length</em></span>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const int32_t</td> <td class="paramname"><span class="paramname"><em>tag</em></span>&#160;)</td>
</tr>
</table>
</div><div class="memdoc">
<p>Writes per-sector tag data (auxiliary metadata) for a specific sector. </p>
<p>This function stores auxiliary metadata associated with individual sectors, such as CD subchannel data, DVD auxiliary fields, track metadata, or proprietary tag formats used by specific storage systems. Unlike media tags (which apply to the entire medium), sector tags are per-sector metadata that provide additional context, error correction, copy protection, or device-specific information for each individual sector.</p>
<p>The function validates the tag type against the media type, verifies the data size matches the expected length for that tag type, allocates buffers as needed, and stores the tag data at the appropriate offset within the tag buffer. Some tags (like track flags and ISRC) update track metadata rather than per-sector buffers.</p>
<p><b>Supported tag types and their characteristics:</b></p>
<p><b>Optical Disc (CD/DVD) Tags:</b></p><ul>
<li><b>CdTrackFlags</b> (1 byte): Track control flags for CD tracks<ul>
<li>Updates track metadata in ctx-&gt;trackEntries for the track containing the sector</li>
<li>Includes flags like copy permitted, data track, four-channel audio, etc.</li>
</ul>
</li>
<li><b>CdTrackIsrc</b> (12 bytes): International Standard Recording Code for CD tracks<ul>
<li>Updates track metadata in ctx-&gt;trackEntries for the track containing the sector</li>
<li>Identifies the recording for copyright and royalty purposes</li>
</ul>
</li>
<li><b>CdSectorSubchannel</b> (96 bytes): CD subchannel data (P-W subchannels)<ul>
<li>Stored in ctx-&gt;sector_subchannel buffer</li>
<li>Contains control information, track numbers, timecodes, and CD-TEXT data</li>
</ul>
</li>
<li><b>DvdSectorCprMai</b> (6 bytes): DVD Copyright Management Information<ul>
<li>Stored in ctx-&gt;sector_cpr_mai buffer</li>
<li>Contains copy protection and media authentication information</li>
</ul>
</li>
<li><b>DvdSectorInformation</b> (1 byte): DVD sector information field<ul>
<li>Stored in first byte of ctx-&gt;sector_id buffer (4 bytes per sector)</li>
<li>Contains sector type and layer information</li>
</ul>
</li>
<li><b>DvdSectorNumber</b> (3 bytes): DVD sector number field<ul>
<li>Stored in bytes 1-3 of ctx-&gt;sector_id buffer (4 bytes per sector)</li>
<li>Physical sector address encoded in the sector header</li>
</ul>
</li>
<li><b>DvdSectorIed</b> (2 bytes): DVD ID Error Detection field<ul>
<li>Stored in ctx-&gt;sector_ied buffer</li>
<li>Error detection code for the sector ID field</li>
</ul>
</li>
<li><b>DvdSectorEdc</b> (4 bytes): DVD Error Detection Code<ul>
<li>Stored in ctx-&gt;sector_edc buffer</li>
<li>Error detection code for the entire sector</li>
</ul>
</li>
<li><b>DvdDiscKeyDecrypted</b> (5 bytes): Decrypted DVD title key<ul>
<li>Stored in ctx-&gt;sector_decrypted_title_key buffer</li>
<li>Used for accessing encrypted DVD content</li>
</ul>
</li>
</ul>
<p><b>Block Media (Proprietary Format) Tags:</b></p><ul>
<li><b>AppleSonyTag</b> (12 bytes): Apple II Sony 3.5" disk tag data<ul>
<li>Stored in ctx-&gt;sector_subchannel buffer</li>
<li>Contains file system metadata used by Apple II systems</li>
</ul>
</li>
<li><b>AppleProfileTag</b> (20 bytes): Apple ProFile/FileWare hard drive tag data<ul>
<li>Stored in ctx-&gt;sector_subchannel buffer</li>
<li>Contains file system and bad block metadata</li>
</ul>
</li>
<li><b>PriamDataTowerTag</b> (24 bytes): Priam Data Tower hard drive tag data<ul>
<li>Stored in ctx-&gt;sector_subchannel buffer</li>
<li>Contains proprietary metadata used by Priam drives</li>
</ul>
</li>
</ul>
<p><b>Sector addressing:</b> The function supports both positive and negative sector addressing:</p><ul>
<li>Negative sectors: Lead-in area before sector 0 (for optical media)</li>
<li>Positive sectors: Main data area and lead-out overflow area</li>
<li>Internal correction adjusts addresses to buffer offsets</li>
</ul>
<p><b>Buffer allocation:</b> Tag buffers are allocated on-demand when the first tag of a given type is written. Buffers are sized to accommodate all sectors (negative + normal + overflow) and persist for the lifetime of the context. Memory is freed during <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a>.</p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">context</td><td>Pointer to the aaruformat context (must be a valid, write-enabled image context). </td></tr>
<tr><td class="paramname">sector_address</td><td>The logical sector number to write the tag for. Must be within valid bounds for the image (0 to Sectors-1 for positive, 0 to negative-1 when using negative addressing). </td></tr>
<tr><td class="paramname">negative</td><td>If true, sector_address refers to a negative (lead-in) sector; if false, it refers to a positive sector (main data or overflow area). </td></tr>
<tr><td class="paramname">data</td><td>Pointer to the tag data to write. Must not be NULL. The data size must exactly match the expected size for the tag type. </td></tr>
<tr><td class="paramname">length</td><td>Length of the tag data in bytes. Must match the required size for the tag type. </td></tr>
<tr><td class="paramname">tag</td><td>Tag type identifier (from the tag enumeration). Determines which buffer to write to and the expected data size.</td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Returns one of the following status codes: </dd></dl>
<dl class="retval"><dt>Return values</dt><dd>
<table class="retval">
<tr><td class="paramname">AARUF_STATUS_OK</td><td>(0) Successfully wrote sector tag. This is returned when:<ul>
<li>The context is valid and properly initialized</li>
<li>The context is opened in write mode (ctx-&gt;isWriting is true)</li>
<li>The sector address is within valid bounds</li>
<li>The tag type is supported and appropriate for the media type</li>
<li>The data length matches the required size for the tag type</li>
<li>Memory allocation succeeded (if buffer needed to be created)</li>
<li>Tag data was copied to the appropriate buffer or track metadata updated</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_AARUFORMAT</td><td>(-1) The context is invalid. This occurs when:<ul>
<li>The context parameter is NULL</li>
<li>The context magic number doesn't match AARU_MAGIC (invalid context type)</li>
<li>The context was not properly initialized by <a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a></li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_READ_ONLY</td><td>(-13) The context is not opened for writing. This occurs when:<ul>
<li>The image was opened with <a class="el" href="decls_8h.html#afc4932cdc795ffb2ef3a33d5b8c57656" title="Opens an existing AaruFormat image file.">aaruf_open()</a> instead of <a class="el" href="decls_8h.html#a7065a9fefcaabfecc4184528f01ef013" title="Creates a new AaruFormat image file.">aaruf_create()</a></li>
<li>The context's isWriting flag is false</li>
<li>Attempting to modify a read-only image</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_SECTOR_OUT_OF_BOUNDS</td><td>(-4) Sector address is invalid. This occurs when:<ul>
<li>negative is true and sector_address &gt; negative-1</li>
<li>negative is false and sector_address &gt; Sectors+overflow-1</li>
<li>Attempting to write beyond the image boundaries</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_INCORRECT_DATA_SIZE</td><td>(-11) Invalid data or length. This occurs when:<ul>
<li>The data parameter is NULL</li>
<li>The length parameter is 0</li>
<li>The length doesn't match the required size for the tag type</li>
<li>Tag size validation failed</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_INCORRECT_MEDIA_TYPE</td><td>(-26) Invalid media type for tag. This occurs when:<ul>
<li>Attempting to write optical disc tags (CD/DVD) to block media</li>
<li>Attempting to write block media tags to optical disc</li>
<li>Tag type is incompatible with ctx-&gt;imageInfo.XmlMediaType</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_NOT_ENOUGH_MEMORY</td><td>(-8) Memory allocation failed. This occurs when:<ul>
<li>calloc() failed to allocate buffer for tag data</li>
<li>System is out of memory or memory is severely fragmented</li>
<li>Buffer allocation is required but cannot be satisfied</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_TRACK_NOT_FOUND</td><td>(-25) Track not found for sector. This occurs when:<ul>
<li>Writing CdTrackFlags or CdTrackIsrc tags</li>
<li>The specified sector is not contained within any defined track</li>
<li>Track metadata has not been initialized</li>
</ul>
</td></tr>
<tr><td class="paramname">AARUF_ERROR_INVALID_TAG</td><td>(-27) Unsupported or unknown tag type. This occurs when:<ul>
<li>The tag parameter doesn't match any known tag type</li>
<li>The tag type is not implemented</li>
<li>Invalid tag identifier provided</li>
</ul>
</td></tr>
</table>
</dd>
</dl>
<dl class="section note"><dt>Note</dt><dd>Tag Data Persistence:<ul>
<li>Tag data is stored in memory until <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a> is called</li>
<li>Tags are written as separate data blocks during image finalization</li>
<li>CD subchannel and DVD auxiliary fields are written by dedicated block writers</li>
<li>Track metadata (flags, ISRC) is written as part of the tracks block</li>
</ul>
</dd>
<dd>
Buffer Reuse:<ul>
<li>Some tag types share the same buffer (ctx-&gt;sector_subchannel)</li>
<li>CD subchannel uses 96 bytes per sector</li>
<li>Apple Sony tag uses 12 bytes per sector</li>
<li>Apple Profile tag uses 20 bytes per sector</li>
<li>Priam Data Tower tag uses 24 bytes per sector</li>
<li>Ensure consistent tag type usage within a single image</li>
</ul>
</dd>
<dd>
DVD Sector ID Split:<ul>
<li>DVD sector ID is 4 bytes but written as two separate tags</li>
<li>DvdSectorInformation writes byte 0 (sector info)</li>
<li>DvdSectorNumber writes bytes 1-3 (sector number)</li>
<li>Both tags share ctx-&gt;sector_id buffer</li>
</ul>
</dd>
<dd>
Tag Size Validation:<ul>
<li>Each tag type has a fixed expected size</li>
<li>Size mismatches are rejected with AARUF_ERROR_INCORRECT_DATA_SIZE</li>
<li>This prevents partial writes and buffer corruption</li>
</ul>
</dd>
<dd>
Media Type Validation:<ul>
<li>Optical disc tags require <a class="el" href="enums_8h.html#abaa37b51ab0a4cc3d5d1a0b4820c8466" title="Enumeration of media types defined in CICM metadata.">XmlMediaType</a> == OpticalDisc</li>
<li>Block media tags require <a class="el" href="enums_8h.html#abaa37b51ab0a4cc3d5d1a0b4820c8466" title="Enumeration of media types defined in CICM metadata.">XmlMediaType</a> == BlockMedia</li>
<li>This prevents incompatible tag types from being written</li>
</ul>
</dd>
<dd>
Multiple Writes to Same Sector:<ul>
<li>Writing the same tag type to the same sector multiple times replaces the previous value</li>
<li>No warning or error is generated for overwrites</li>
<li>Last write wins</li>
</ul>
</dd></dl>
<dl class="section warning"><dt>Warning</dt><dd>Tag data is not immediately written to disk. All tag data is buffered in memory and written during <a class="el" href="decls_8h.html#a6823e139f81a9dfd08efcb0e9b213a49" title="Close an Aaru image context, flushing pending data structures and releasing resources.">aaruf_close()</a>. Ensure sufficient memory is available for large images with extensive tag data.</dd>
<dd>
Mixing incompatible tag types that share buffers (e.g., CD subchannel and Apple tags) will cause data corruption. Only use tag types appropriate for your media format.</dd>
<dd>
For track-based tags (CdTrackFlags, CdTrackIsrc), tracks must be defined before writing tags. Call <a class="el" href="decls_8h.html#a518d8d68debf1b9a24af3eb6bc2f9e49" title="Replace (or clear) the in-memory track table for an AaruFormat image context.">aaruf_set_tracks()</a> to initialize track metadata first.</dd></dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="#a35c5d9f10c59a1efe8f625963c9e91ba" title="Writes a media tag to the AaruFormat image, storing medium-specific metadata and descriptors.">aaruf_write_media_tag()</a> for writing whole-medium tags. </dd>
<dd>
<a class="el" href="#a69ca66242c0becf7640b3d1cc8da8f9c" title="Writes a full (&quot;long&quot;) raw sector from optical or block media, parsing structure and validating conte...">aaruf_write_sector_long()</a> for writing sectors with embedded tag data. </dd>
<dd>
<a class="el" href="close_8c.html#ae0a4b670cbb5359edd44751e1b76ca9c" title="Serialize the per-sector subchannel or tag data block.">write_sector_subchannel()</a> for the serialization of <a class="el" href="group__MediaTypes.html#gga1499e9f8a76cb81b43b7a4b0dbe7e44aa9aea9e501fa935b114b235e8e9754267" title="Any unknown or standard violating CD.">CD</a> subchannel data. </dd>
<dd>
<a class="el" href="close_8c.html#a13f6c475294969c1eb8c59ff53c91af9" title="Serialize DVD long sector auxiliary data blocks to the image file.">write_dvd_long_sector_blocks()</a> for the serialization of DVD auxiliary data. </dd></dl>
<p class="definition">Definition at line <a class="el" href="write_8c_source.html#l02048">2048</a> of file <a class="el" href="write_8c_source.html">write.c</a>.</p>
<p class="reference">References <a class="el" href="consts_8h_source.html#l00064">AARU_MAGIC</a>, <a class="el" href="errors_8h_source.html#l00065">AARUF_ERROR_INCORRECT_DATA_SIZE</a>, <a class="el" href="errors_8h_source.html#l00051">AARUF_ERROR_INCORRECT_MEDIA_TYPE</a>, <a class="el" href="errors_8h_source.html#l00066">AARUF_ERROR_INVALID_TAG</a>, <a class="el" href="errors_8h_source.html#l00040">AARUF_ERROR_NOT_AARUFORMAT</a>, <a class="el" href="errors_8h_source.html#l00048">AARUF_ERROR_NOT_ENOUGH_MEMORY</a>, <a class="el" href="errors_8h_source.html#l00044">AARUF_ERROR_SECTOR_OUT_OF_BOUNDS</a>, <a class="el" href="errors_8h_source.html#l00052">AARUF_ERROR_TRACK_NOT_FOUND</a>, <a class="el" href="errors_8h_source.html#l00061">AARUF_READ_ONLY</a>, <a class="el" href="errors_8h_source.html#l00075">AARUF_STATUS_OK</a>, <a class="el" href="enums_8h_source.html#l00117">AppleProfileTag</a>, <a class="el" href="enums_8h_source.html#l00118">AppleSonyTag</a>, <a class="el" href="enums_8h_source.html#l00219">BlockMedia</a>, <a class="el" href="enums_8h_source.html#l00116">CdSectorSubchannel</a>, <a class="el" href="aaru_8h_source.html#l00907">CdTrackFlags</a>, <a class="el" href="aaru_8h_source.html#l00905">CdTrackIsrc</a>, <a class="el" href="aaru_8h_source.html#l00908">DvdCmi</a>, <a class="el" href="enums_8h_source.html#l00130">DvdSectorEdc</a>, <a class="el" href="enums_8h_source.html#l00129">DvdSectorIed</a>, <a class="el" href="aaru_8h_source.html#l00912">DvdSectorInformation</a>, <a class="el" href="aaru_8h_source.html#l00913">DvdSectorNumber</a>, <a class="el" href="aaru_8h_source.html#l00911">DvdTitleKeyDecrypted</a>, <a class="el" href="optical_8h_source.html#l00064">TracksHeader::entries</a>, <a class="el" href="log_8h_source.html#l00040">FATAL</a>, <a class="el" href="optical_8h_source.html#l00080">TrackEntry::flags</a>, <a class="el" href="context_8h_source.html#l00260">aaruformat_context::image_info</a>, <a class="el" href="context_8h_source.html#l00292">aaruformat_context::is_writing</a>, <a class="el" href="optical_8h_source.html#l00079">TrackEntry::isrc</a>, <a class="el" href="context_8h_source.html#l00174">aaruformat_context::magic</a>, <a class="el" href="aaru_8h_source.html#l00882">ImageInfo::MetadataMediaType</a>, <a class="el" href="ddt_8h_source.html#l00149">DdtHeader2::negative</a>, <a class="el" href="enums_8h_source.html#l00218">OpticalDisc</a>, <a class="el" href="ddt_8h_source.html#l00151">DdtHeader2::overflow</a>, <a class="el" href="enums_8h_source.html#l00119">PriamDataTowerTag</a>, <a class="el" href="context_8h_source.html#l00207">aaruformat_context::sector_cpr_mai</a>, <a class="el" href="context_8h_source.html#l00209">aaruformat_context::sector_decrypted_title_key</a>, <a class="el" href="context_8h_source.html#l00208">aaruformat_context::sector_edc</a>, <a class="el" href="context_8h_source.html#l00205">aaruformat_context::sector_id</a>, <a class="el" href="context_8h_source.html#l00206">aaruformat_context::sector_ied</a>, <a class="el" href="context_8h_source.html#l00203">aaruformat_context::sector_subchannel</a>, <a class="el" href="aaru_8h_source.html#l00874">ImageInfo::Sectors</a>, <a class="el" href="optical_8h_source.html#l00075">TrackEntry::start</a>, <a class="el" href="log_8h_source.html#l00025">TRACE</a>, <a class="el" href="context_8h_source.html#l00242">aaruformat_context::track_entries</a>, <a class="el" href="context_8h_source.html#l00244">aaruformat_context::tracks_header</a>, and <a class="el" href="context_8h_source.html#l00189">aaruformat_context::user_data_ddt_header</a>.</p>
</div>
</div>
</div><!-- contents -->
</div><!-- doc-content -->
<div id="page-nav" class="page-nav-panel">
<div id="page-nav-resize-handle"></div>
<div id="page-nav-tree">
<div id="page-nav-contents">
</div><!-- page-nav-contents -->
</div><!-- page-nav-tree -->
</div><!-- page-nav -->
</div><!-- container -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="navelem"><a href="dir_68267d1309a1af8e8297ef4c3efbcdba.html">src</a></li><li class="navelem"><a href="write_8c.html">write.c</a></li>
<li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.14.0 </li>
</ul>
</div>
</body>
</html>