mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2025-12-16 19:24:40 +00:00
561 lines
43 KiB
HTML
561 lines
43 KiB
HTML
<!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/dump.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"> 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('dump_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">dump.c File Reference</div></div>
|
||
</div><!--header-->
|
||
<div class="contents">
|
||
<div class="textblock"><code>#include <stdint.h></code><br />
|
||
<code>#include <stdlib.h></code><br />
|
||
<code>#include "<a class="el" href="aaruformat_8h_source.html">aaruformat.h</a>"</code><br />
|
||
<code>#include "<a class="el" href="internal_8h_source.html">internal.h</a>"</code><br />
|
||
<code>#include "<a class="el" href="log_8h_source.html">log.h</a>"</code><br />
|
||
</div>
|
||
<p><a href="dump_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-define-members" class="groupheader"><a id="define-members" name="define-members"></a>
|
||
Macros</h2></td></tr>
|
||
<tr class="memitem:a6b41f4a00a255e6704583614ef33571f" id="r_a6b41f4a00a255e6704583614ef33571f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="#a6b41f4a00a255e6704583614ef33571f">COPY_STRING_FIELD</a>(field)</td></tr>
|
||
</table><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:ab98a236ef7ac4de15fb37a2e3c3ce633" id="r_ab98a236ef7ac4de15fb37a2e3c3ce633"><td class="memItemLeft" align="right" valign="top">static void </td><td class="memItemRight" valign="bottom"><a class="el" href="#ab98a236ef7ac4de15fb37a2e3c3ce633">free_dump_hardware_entries</a> (<a class="el" href="structDumpHardwareEntriesWithData.html">DumpHardwareEntriesWithData</a> *entries, uint32_t count)</td></tr>
|
||
<tr class="memitem:a36af83897e131ba792c51ae8caec9984" id="r_a36af83897e131ba792c51ae8caec9984"><td class="memItemLeft" align="right" valign="top">int32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="#a36af83897e131ba792c51ae8caec9984">aaruf_get_dumphw</a> (void *context, uint8_t *buffer, size_t *length)</td></tr>
|
||
<tr class="memdesc:a36af83897e131ba792c51ae8caec9984"><td class="mdescLeft"> </td><td class="mdescRight">Retrieves the dump hardware block containing acquisition environment information. <br /></td></tr>
|
||
<tr class="memitem:ad98012dc12a51d9eadbd79a25aab8299" id="r_ad98012dc12a51d9eadbd79a25aab8299"><td class="memItemLeft" align="right" valign="top">int32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="#ad98012dc12a51d9eadbd79a25aab8299">aaruf_set_dumphw</a> (void *context, uint8_t *data, size_t length)</td></tr>
|
||
<tr class="memdesc:ad98012dc12a51d9eadbd79a25aab8299"><td class="mdescLeft"> </td><td class="mdescRight">Sets the dump hardware block for the image during creation. <br /></td></tr>
|
||
</table>
|
||
<a name="doc-define-members" id="doc-define-members"></a><h2 id="header-doc-define-members" class="groupheader">Macro Definition Documentation</h2>
|
||
<a id="a6b41f4a00a255e6704583614ef33571f" name="a6b41f4a00a255e6704583614ef33571f"></a>
|
||
<h2 class="memtitle"><span class="permalink"><a href="#a6b41f4a00a255e6704583614ef33571f">◆ </a></span>COPY_STRING_FIELD</h2>
|
||
|
||
<div class="memitem">
|
||
<div class="memproto">
|
||
<table class="memname">
|
||
<tr>
|
||
<td class="memname">#define COPY_STRING_FIELD</td>
|
||
<td>(</td>
|
||
<td class="paramtype"></td> <td class="paramname"><span class="paramname"><em>field</em></span></td><td>)</td>
|
||
<td></td>
|
||
</tr>
|
||
</table>
|
||
</div><div class="memdoc">
|
||
<b>Value:</b><div class="fragment"><div class="line"> <span class="keywordflow">do</span> { \</div>
|
||
<div class="line"> <span class="keyword">const</span> <span class="keywordtype">size_t</span> field##_length = copy[e].entry.field##Length; \</div>
|
||
<div class="line"> if(field##_length > 0) \</div>
|
||
<div class="line"> { \</div>
|
||
<div class="line"> if(field##_length > length - pos) <span class="keywordflow">goto</span> invalid_data; \</div>
|
||
<div class="line"> copy[e].field = (uint8_t *)calloc(1, field##_length + 1); \</div>
|
||
<div class="line"> if(copy[e].field == NULL) <span class="keywordflow">goto</span> free_copy_and_error; \</div>
|
||
<div class="line"> memcpy(copy[e].field, data + pos, field##_length); \</div>
|
||
<div class="line"> pos += field##_length; \</div>
|
||
<div class="line"> } \</div>
|
||
<div class="line"> } <span class="keywordflow">while</span>(0)</div>
|
||
</div><!-- fragment -->
|
||
<p class="reference">Referenced by <a class="el" href="dump_8c_source.html#l00531">aaruf_set_dumphw()</a>.</p>
|
||
|
||
</div>
|
||
</div>
|
||
<a name="doc-func-members" id="doc-func-members"></a><h2 id="header-doc-func-members" class="groupheader">Function Documentation</h2>
|
||
<a id="a36af83897e131ba792c51ae8caec9984" name="a36af83897e131ba792c51ae8caec9984"></a>
|
||
<h2 class="memtitle"><span class="permalink"><a href="#a36af83897e131ba792c51ae8caec9984">◆ </a></span>aaruf_get_dumphw()</h2>
|
||
|
||
<div class="memitem">
|
||
<div class="memproto">
|
||
<table class="memname">
|
||
<tr>
|
||
<td class="memname">int32_t aaruf_get_dumphw </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">uint8_t *</td> <td class="paramname"><span class="paramname"><em>buffer</em></span>, </td>
|
||
</tr>
|
||
<tr>
|
||
<td class="paramkey"></td>
|
||
<td></td>
|
||
<td class="paramtype">size_t *</td> <td class="paramname"><span class="paramname"><em>length</em></span> )</td>
|
||
</tr>
|
||
</table>
|
||
</div><div class="memdoc">
|
||
|
||
<p>Retrieves the dump hardware block containing acquisition environment information. </p>
|
||
<p>Extracts the complete DumpHardwareBlock from the image, which documents the hardware and software environments used to create the image. A dump hardware block records one or more "dump environments" – typically combinations of physical devices (drives, controllers, adapters) and the software stacks that performed the read operations. This metadata is essential for understanding the imaging context, validating acquisition integrity, reproducing imaging conditions, and supporting forensic or archival documentation requirements.</p>
|
||
<p>Each environment entry includes hardware identification (manufacturer, model, revision, firmware, serial number), software identification (name, version, operating system), and optional extent ranges that specify which logical sectors or units were contributed by that particular environment. This structure supports complex imaging scenarios where multiple devices or software configurations were used to create a composite image.</p>
|
||
<p>The function reconstructs the complete on-disk binary representation of the dump hardware block, including the <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> followed by all entries with their variable-length UTF-8 strings and extent arrays. The reconstructed block includes a calculated CRC64 checksum over the payload data for integrity verification.</p>
|
||
<p>This function supports a two-call pattern for buffer size determination:</p><ol type="1">
|
||
<li>First call with insufficient buffer (or NULL) returns AARUF_ERROR_BUFFER_TOO_SMALL and sets *length to the required size (sizeof(DumpHardwareHeader) + total payload length)</li>
|
||
<li>Second call with properly sized buffer retrieves the complete block data</li>
|
||
</ol>
|
||
<p>Alternatively, if the caller already knows the buffer is large enough, a single call will succeed and populate the buffer with the complete dump hardware block.</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, opened image context). </td></tr>
|
||
<tr><td class="paramname">buffer</td><td>Pointer to a buffer that will receive the dump hardware block data. Must be large enough to hold the complete block (at least *length bytes on input). May be NULL to query the required buffer size. The buffer will contain the <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> followed by serialized entries, strings, and extent arrays on success. </td></tr>
|
||
<tr><td class="paramname">length</td><td>Pointer to a size_t that serves dual purpose:<ul>
|
||
<li>On input: size of the provided buffer in bytes (ignored if buffer is NULL)</li>
|
||
<li>On output: actual size required/used for the dump hardware block in bytes If the function returns AARUF_ERROR_BUFFER_TOO_SMALL, this will be updated to contain the required buffer size for a subsequent successful call.</li>
|
||
</ul>
|
||
</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 retrieved dump hardware block. This is returned when:<ul>
|
||
<li>The context is valid and properly initialized</li>
|
||
<li>The dump hardware block is present (identifier == DumpHardwareBlock)</li>
|
||
<li>The provided buffer is large enough (>= required length)</li>
|
||
<li>All hardware entries with their strings and extents are copied to the buffer</li>
|
||
<li>The <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> is written with calculated CRC64 at buffer offset 0</li>
|
||
<li>The *length parameter is set to the actual block size</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#afc4932cdc795ffb2ef3a33d5b8c57656" title="Opens an existing AaruFormat image file.">aaruf_open()</a> or <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_ERROR_CANNOT_READ_BLOCK</td><td>(-6) The dump hardware block is not present. This occurs when:<ul>
|
||
<li>The image was created without dump hardware information</li>
|
||
<li>ctx->dumpHardwareEntriesWithData is NULL (no data loaded)</li>
|
||
<li>ctx->dumpHardwareHeader.entries == 0 (no hardware entries)</li>
|
||
<li>ctx->dumpHardwareHeader.identifier doesn't equal DumpHardwareBlock</li>
|
||
<li>The dump hardware block was not found during image opening</li>
|
||
</ul>
|
||
</td></tr>
|
||
<tr><td class="paramname">AARUF_ERROR_BUFFER_TOO_SMALL</td><td>(-12) The provided buffer is insufficient. This occurs when:<ul>
|
||
<li>buffer is NULL (size query mode)</li>
|
||
<li>The input *length is less than sizeof(DumpHardwareHeader) + payload length</li>
|
||
<li>The *length parameter is updated to contain the required buffer size</li>
|
||
<li>No data is copied to the buffer</li>
|
||
<li>The caller should allocate a larger buffer and call again</li>
|
||
<li>Also returned if calculated entry size exceeds buffer during iteration (sanity check)</li>
|
||
</ul>
|
||
</td></tr>
|
||
</table>
|
||
</dd>
|
||
</dl>
|
||
<dl class="section note"><dt>Note</dt><dd>Dump Hardware Block Structure:<ul>
|
||
<li><a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> (16 bytes): identifier, entries count, payload length, CRC64</li>
|
||
<li>For each entry (variable size):<ul>
|
||
<li><a class="el" href="structDumpHardwareEntry.html" title="Per-environment length table describing subsequent UTF-8 strings and optional extent array.">DumpHardwareEntry</a> (36 bytes): length fields for all strings and extent count</li>
|
||
<li>Variable-length UTF-8 strings (in order): manufacturer, model, revision, firmware, serial, software name, software version, software operating system</li>
|
||
<li>Array of <a class="el" href="structDumpExtent.html" title="Inclusive [start,end] logical sector range contributed by a single hardware environment.">DumpExtent</a> structures (16 bytes each) if extent count > 0</li>
|
||
</ul>
|
||
</li>
|
||
<li>All strings are UTF-8 encoded and NOT null-terminated in the serialized block</li>
|
||
<li>String lengths are in bytes, not character counts</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Dump Hardware Environments:<ul>
|
||
<li>Each entry represents one hardware/software combination used during imaging</li>
|
||
<li>Multiple entries support scenarios where different devices contributed different sectors</li>
|
||
<li>Extent arrays specify which logical sector ranges each environment contributed</li>
|
||
<li>Empty extent arrays (extents == 0) indicate the environment dumped the entire medium</li>
|
||
<li>Overlapping extents between entries may indicate verification passes or redundancy</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Hardware Identification Fields:<ul>
|
||
<li>manufacturer: Device manufacturer (e.g., "Plextor", "Sony", "Samsung")</li>
|
||
<li>model: Device model number (e.g., "PX-716A", "DRU-820A")</li>
|
||
<li>revision: Hardware revision identifier</li>
|
||
<li>firmware: Firmware version (e.g., "1.11", "KY08")</li>
|
||
<li>serial: Device serial number for unique identification</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Software Identification Fields:<ul>
|
||
<li>softwareName: Dumping software name (e.g., "Aaru", "ddrescue", "IsoBuster")</li>
|
||
<li>softwareVersion: Software version (e.g., "5.3.0", "1.25")</li>
|
||
<li>softwareOperatingSystem: Host OS (e.g., "Linux 5.10.0", "Windows 10", "macOS 12.0")</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
CRC64 Calculation:<ul>
|
||
<li>The function calculates CRC64-ECMA over the payload (everything after the header)</li>
|
||
<li>The calculated CRC64 is stored in the returned <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a></li>
|
||
<li>This allows verification of the serialized block integrity</li>
|
||
<li>The CRC64 is computed from buffer data, not from the original context</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Buffer Layout After Successful Call:<ul>
|
||
<li>Offset 0: <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> with calculated CRC64</li>
|
||
<li>Offset 16: First <a class="el" href="structDumpHardwareEntry.html" title="Per-environment length table describing subsequent UTF-8 strings and optional extent array.">DumpHardwareEntry</a></li>
|
||
<li>Followed by: First entry's UTF-8 strings (in documented order)</li>
|
||
<li>Followed by: First entry's <a class="el" href="structDumpExtent.html" title="Inclusive [start,end] logical sector range contributed by a single hardware environment.">DumpExtent</a> array (if extents > 0)</li>
|
||
<li>Repeated for all remaining entries</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Use Cases:<ul>
|
||
<li>Forensic documentation requiring complete equipment chain of custody</li>
|
||
<li>Archival metadata for long-term preservation requirements</li>
|
||
<li>Reproducing imaging conditions for verification or re-imaging</li>
|
||
<li>Identifying firmware-specific issues or drive-specific behaviors</li>
|
||
<li>Multi-device imaging scenario documentation</li>
|
||
<li>Correlating imaging artifacts with specific hardware/software combinations</li>
|
||
</ul>
|
||
</dd></dl>
|
||
<dl class="section warning"><dt>Warning</dt><dd>This function reads from the in-memory dump hardware data loaded during <a class="el" href="decls_8h.html#afc4932cdc795ffb2ef3a33d5b8c57656" title="Opens an existing AaruFormat image file.">aaruf_open()</a>. It does not perform file I/O operations. The data is reconstructed from the parsed context structures into the on-disk binary format.</dd>
|
||
<dd>
|
||
The buffer must be valid and large enough to hold the entire dump hardware block. Passing a buffer smaller than required will result in AARUF_ERROR_BUFFER_TOO_SMALL.</dd>
|
||
<dd>
|
||
String data in the serialized block is NOT null-terminated. Applications parsing the buffer must use the length fields in <a class="el" href="structDumpHardwareEntry.html" title="Per-environment length table describing subsequent UTF-8 strings and optional extent array.">DumpHardwareEntry</a> to determine string boundaries. The library adds null terminators only for in-memory convenience.</dd>
|
||
<dd>
|
||
The function performs bounds checking during serialization. If calculated entry sizes exceed the buffer length, AARUF_ERROR_BUFFER_TOO_SMALL is returned even after the initial size check. This should not occur with properly sized buffers but protects against data corruption.</dd></dl>
|
||
<dl class="section see"><dt>See also</dt><dd><a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> for the block header structure definition. </dd>
|
||
<dd>
|
||
<a class="el" href="structDumpHardwareEntry.html" title="Per-environment length table describing subsequent UTF-8 strings and optional extent array.">DumpHardwareEntry</a> for the per-environment entry structure definition. </dd>
|
||
<dd>
|
||
<a class="el" href="structDumpExtent.html" title="Inclusive [start,end] logical sector range contributed by a single hardware environment.">DumpExtent</a> for the extent range structure definition. </dd>
|
||
<dd>
|
||
<a class="el" href="blocks_2dump_8c.html#a0e2cfc858c0551bc9bef11d5bdb85aac" title="Processes a dump hardware block from the image stream.">process_dumphw_block()</a> for the loading process during image opening. </dd></dl>
|
||
|
||
<p class="definition">Definition at line <a class="el" href="dump_8c_source.html#l00186">186</a> of file <a class="el" href="dump_8c_source.html">dump.c</a>.</p>
|
||
|
||
<p class="reference">References <a class="el" href="decls_8h_source.html#l00045">AARU_CALL</a>, <a class="el" href="decls_8h_source.html#l00054">AARU_EXPORT</a>, <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="errors_8h_source.html#l00049">AARUF_ERROR_BUFFER_TOO_SMALL</a>, <a class="el" href="errors_8h_source.html#l00046">AARUF_ERROR_CANNOT_READ_BLOCK</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#l00075">AARUF_STATUS_OK</a>, <a class="el" href="dump_8h_source.html#l00095">DumpHardwareHeader::crc64</a>, <a class="el" href="context_8h_source.html#l00212">aaruformat_context::dump_hardware_entries_with_data</a>, <a class="el" href="context_8h_source.html#l00232">aaruformat_context::dump_hardware_header</a>, <a class="el" href="enums_8h_source.html#l00156">DumpHardwareBlock</a>, <a class="el" href="dump_8h_source.html#l00093">DumpHardwareHeader::entries</a>, <a class="el" href="context_8h_source.html#l00315">DumpHardwareEntriesWithData::entry</a>, <a class="el" href="context_8h_source.html#l00316">DumpHardwareEntriesWithData::extents</a>, <a class="el" href="dump_8h_source.html#l00122">DumpHardwareEntry::extents</a>, <a class="el" href="log_8h_source.html#l00040">FATAL</a>, <a class="el" href="context_8h_source.html#l00320">DumpHardwareEntriesWithData::firmware</a>, <a class="el" href="dump_8h_source.html#l00117">DumpHardwareEntry::firmwareLength</a>, <a class="el" href="dump_8h_source.html#l00092">DumpHardwareHeader::identifier</a>, <a class="el" href="dump_8h_source.html#l00094">DumpHardwareHeader::length</a>, <a class="el" href="context_8h_source.html#l00174">aaruformat_context::magic</a>, <a class="el" href="context_8h_source.html#l00317">DumpHardwareEntriesWithData::manufacturer</a>, <a class="el" href="dump_8h_source.html#l00114">DumpHardwareEntry::manufacturerLength</a>, <a class="el" href="context_8h_source.html#l00318">DumpHardwareEntriesWithData::model</a>, <a class="el" href="dump_8h_source.html#l00115">DumpHardwareEntry::modelLength</a>, <a class="el" href="context_8h_source.html#l00319">DumpHardwareEntriesWithData::revision</a>, <a class="el" href="dump_8h_source.html#l00116">DumpHardwareEntry::revisionLength</a>, <a class="el" href="context_8h_source.html#l00321">DumpHardwareEntriesWithData::serial</a>, <a class="el" href="dump_8h_source.html#l00118">DumpHardwareEntry::serialLength</a>, <a class="el" href="context_8h_source.html#l00322">DumpHardwareEntriesWithData::softwareName</a>, <a class="el" href="dump_8h_source.html#l00119">DumpHardwareEntry::softwareNameLength</a>, <a class="el" href="context_8h_source.html#l00324">DumpHardwareEntriesWithData::softwareOperatingSystem</a>, <a class="el" href="dump_8h_source.html#l00121">DumpHardwareEntry::softwareOperatingSystemLength</a>, <a class="el" href="context_8h_source.html#l00323">DumpHardwareEntriesWithData::softwareVersion</a>, <a class="el" href="dump_8h_source.html#l00120">DumpHardwareEntry::softwareVersionLength</a>, and <a class="el" href="log_8h_source.html#l00025">TRACE</a>.</p>
|
||
|
||
</div>
|
||
</div>
|
||
<a id="ad98012dc12a51d9eadbd79a25aab8299" name="ad98012dc12a51d9eadbd79a25aab8299"></a>
|
||
<h2 class="memtitle"><span class="permalink"><a href="#ad98012dc12a51d9eadbd79a25aab8299">◆ </a></span>aaruf_set_dumphw()</h2>
|
||
|
||
<div class="memitem">
|
||
<div class="memproto">
|
||
<table class="memname">
|
||
<tr>
|
||
<td class="memname">int32_t aaruf_set_dumphw </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">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">size_t</td> <td class="paramname"><span class="paramname"><em>length</em></span> )</td>
|
||
</tr>
|
||
</table>
|
||
</div><div class="memdoc">
|
||
|
||
<p>Sets the dump hardware block for the image during creation. </p>
|
||
<p>Embeds dump hardware information into the image being created. The dump hardware block documents the hardware and software environments used to create the image, recording one or more "dump
|
||
environments" – typically combinations of physical devices (drives, controllers, adapters) and the software stacks that performed the read operations. This metadata is essential for understanding the imaging context, validating acquisition integrity, reproducing imaging conditions, and supporting forensic or archival documentation requirements.</p>
|
||
<p>Each environment entry includes hardware identification (manufacturer, model, revision, firmware, serial number), software identification (name, version, operating system), and optional extent ranges that specify which logical sectors or units were contributed by that particular environment. This structure supports complex imaging scenarios where multiple devices or software configurations were used to create a composite image.</p>
|
||
<p>The function accepts a complete, pre-serialized DumpHardwareBlock in the on-disk binary format (as returned by <a class="el" href="#a36af83897e131ba792c51ae8caec9984" title="Retrieves the dump hardware block containing acquisition environment information.">aaruf_get_dumphw()</a> or manually constructed). The block is validated for correct identifier, length consistency, and CRC64 integrity before being parsed and stored in the context. The function deserializes the binary block, extracts all entries with their variable-length UTF-8 strings and extent arrays, and creates null-terminated in-memory copies for internal use.</p>
|
||
<p><b>Validation performed:</b></p><ol type="1">
|
||
<li>Context validation (non-NULL, correct magic, write mode)</li>
|
||
<li>Data buffer validation (non-NULL, non-zero length)</li>
|
||
<li>Block identifier validation (must be DumpHardwareBlock)</li>
|
||
<li>Length consistency (buffer length must equal sizeof(DumpHardwareHeader) + header.length)</li>
|
||
<li>CRC64 integrity verification (calculated CRC64 must match header.crc64)</li>
|
||
</ol>
|
||
<p><b>Parsing process:</b></p><ol type="1">
|
||
<li>Read and validate the <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> from the buffer</li>
|
||
<li>Allocate array for all dump hardware entries</li>
|
||
<li>For each entry:<ul>
|
||
<li>Read the <a class="el" href="structDumpHardwareEntry.html" title="Per-environment length table describing subsequent UTF-8 strings and optional extent array.">DumpHardwareEntry</a> structure (36 bytes)</li>
|
||
<li>Allocate and copy each non-empty UTF-8 string with +1 byte for null terminator</li>
|
||
<li>Allocate and copy the <a class="el" href="structDumpExtent.html" title="Inclusive [start,end] logical sector range contributed by a single hardware environment.">DumpExtent</a> array if extents > 0</li>
|
||
</ul>
|
||
</li>
|
||
<li>Free any previously set dump hardware data</li>
|
||
<li>Store the new parsed data in ctx->dumpHardwareEntriesWithData</li>
|
||
<li>Store the header in ctx->dumpHardwareHeader</li>
|
||
</ol>
|
||
<p><b>Memory management:</b> If any memory allocation fails during parsing, all previously allocated memory for the new data is freed via the free_copy_and_error label, and AARUF_ERROR_NOT_ENOUGH_MEMORY is returned. Any existing dump hardware data in the context is freed before storing new data, ensuring no memory leaks when replacing dump hardware information.</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">data</td><td>Pointer to the dump hardware block data in on-disk binary format. Must contain a complete DumpHardwareBlock starting with <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> followed by all entries, strings, and extent arrays. Must not be NULL. </td></tr>
|
||
<tr><td class="paramname">length</td><td>Length of the dump hardware block data in bytes. Must equal sizeof(DumpHardwareHeader) + header.length for validation to succeed.</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 set dump hardware block. This is returned when:<ul>
|
||
<li>The context is valid and properly initialized</li>
|
||
<li>The context is opened in write mode (ctx->isWriting is true)</li>
|
||
<li>The data buffer contains a valid DumpHardwareBlock</li>
|
||
<li>The block identifier is DumpHardwareBlock</li>
|
||
<li>The length is consistent (buffer length == header size + payload length)</li>
|
||
<li>The CRC64 checksum is valid</li>
|
||
<li>All memory allocations succeeded</li>
|
||
<li>All entries with strings and extents are parsed and stored</li>
|
||
<li>Any previous dump hardware data is freed</li>
|
||
<li>ctx->dumpHardwareEntriesWithData is populated with parsed entries</li>
|
||
<li>ctx->dumpHardwareHeader is updated with the new header</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_CANNOT_READ_BLOCK</td><td>(-6) Invalid block identifier. This occurs when:<ul>
|
||
<li>The identifier field in the <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> doesn't equal DumpHardwareBlock</li>
|
||
<li>The data buffer doesn't contain a valid dump hardware block</li>
|
||
<li>The block type is incorrect or corrupted</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 (empty block)</li>
|
||
<li>The buffer length doesn't match sizeof(DumpHardwareHeader) + header.length</li>
|
||
<li>Length inconsistency indicates corrupted or incomplete block data</li>
|
||
</ul>
|
||
</td></tr>
|
||
<tr><td class="paramname">AARUF_ERROR_INVALID_BLOCK_CRC</td><td>(-10) CRC64 checksum mismatch. This occurs when:<ul>
|
||
<li>The calculated CRC64 over the payload doesn't match header.crc64</li>
|
||
<li>Block data is corrupted or tampered with</li>
|
||
<li>Block was not properly constructed or serialized</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() or malloc() failed to allocate memory for entries array</li>
|
||
<li>Failed to allocate memory for any string field (manufacturer, model, etc.)</li>
|
||
<li>Failed to allocate memory for extent arrays</li>
|
||
<li>System is out of memory or memory is severely fragmented</li>
|
||
<li>All partially allocated memory is freed before returning</li>
|
||
</ul>
|
||
</td></tr>
|
||
</table>
|
||
</dd>
|
||
</dl>
|
||
<dl class="section note"><dt>Note</dt><dd>Dump Hardware Block Format:<ul>
|
||
<li>The data buffer must contain a complete serialized DumpHardwareBlock</li>
|
||
<li>Format: <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> + repeated entries with strings and extents</li>
|
||
<li>All strings are UTF-8 encoded and NOT null-terminated in the buffer</li>
|
||
<li>The function adds null terminators when copying strings to internal storage</li>
|
||
<li>String lengths are in bytes, not character counts</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Creating Block Data:<ul>
|
||
<li>Use <a class="el" href="#a36af83897e131ba792c51ae8caec9984" title="Retrieves the dump hardware block containing acquisition environment information.">aaruf_get_dumphw()</a> to retrieve a block from an existing image</li>
|
||
<li>Manually construct by serializing <a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a>, entries, strings, and extents</li>
|
||
<li>Calculate CRC64-ECMA over the payload (everything after the header)</li>
|
||
<li>Ensure all length fields accurately reflect the data sizes</li>
|
||
<li>Ensure total buffer size equals sizeof(DumpHardwareHeader) + payload length</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Hardware Identification Fields:<ul>
|
||
<li>manufacturer: Device manufacturer (e.g., "Plextor", "Sony", "Samsung")</li>
|
||
<li>model: Device model number (e.g., "PX-716A", "DRU-820A")</li>
|
||
<li>revision: Hardware revision identifier</li>
|
||
<li>firmware: Firmware version (e.g., "1.11", "KY08")</li>
|
||
<li>serial: Device serial number for unique identification</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Software Identification Fields:<ul>
|
||
<li>softwareName: Dumping software name (e.g., "Aaru", "ddrescue", "IsoBuster")</li>
|
||
<li>softwareVersion: Software version (e.g., "5.3.0", "1.25")</li>
|
||
<li>softwareOperatingSystem: Host OS (e.g., "Linux 5.10.0", "Windows 10", "macOS 12.0")</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Extent Arrays:<ul>
|
||
<li>Each <a class="el" href="structDumpExtent.html" title="Inclusive [start,end] logical sector range contributed by a single hardware environment.">DumpExtent</a> specifies a [start, end] logical sector range</li>
|
||
<li>Extents indicate which sectors this environment contributed</li>
|
||
<li>Empty extent arrays (extents == 0) mean the environment dumped entire medium</li>
|
||
<li>Extents are stored in the order provided in the input buffer</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Memory Ownership:<ul>
|
||
<li>The function creates internal copies of all data</li>
|
||
<li>The caller retains ownership of the input data buffer</li>
|
||
<li>The caller may free the input buffer immediately after this function returns</li>
|
||
<li>Internal copies are 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> or when replaced by another call</li>
|
||
</ul>
|
||
</dd>
|
||
<dd>
|
||
Replacing Existing Data:<ul>
|
||
<li>Calling this function multiple times replaces previous dump hardware data</li>
|
||
<li>All previous entries, strings, and extents are freed before storing new data</li>
|
||
<li>No memory leaks occur when updating dump hardware information</li>
|
||
</ul>
|
||
</dd></dl>
|
||
<dl class="section warning"><dt>Warning</dt><dd>The dump hardware block is only written 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>. Changes made by this function are not immediately persisted to disk.</dd>
|
||
<dd>
|
||
CRC64 validation protects against corrupted blocks, but construction errors in the input buffer (incorrect lengths, misaligned data) may cause parsing to fail or produce incorrect results even with a valid checksum.</dd>
|
||
<dd>
|
||
The function assumes the input buffer is properly formatted and packed according to the DumpHardwareBlock specification. Malformed input may cause crashes or memory corruption.</dd></dl>
|
||
<dl class="section see"><dt>See also</dt><dd><a class="el" href="structDumpHardwareHeader.html" title="Header that precedes a sequence of dump hardware entries and their variable-length payload.">DumpHardwareHeader</a> for the block header structure definition. </dd>
|
||
<dd>
|
||
<a class="el" href="structDumpHardwareEntry.html" title="Per-environment length table describing subsequent UTF-8 strings and optional extent array.">DumpHardwareEntry</a> for the per-environment entry structure definition. </dd>
|
||
<dd>
|
||
<a class="el" href="structDumpExtent.html" title="Inclusive [start,end] logical sector range contributed by a single hardware environment.">DumpExtent</a> for the extent range structure definition. </dd>
|
||
<dd>
|
||
<a class="el" href="#a36af83897e131ba792c51ae8caec9984" title="Retrieves the dump hardware block containing acquisition environment information.">aaruf_get_dumphw()</a> for retrieving dump hardware from opened images. </dd>
|
||
<dd>
|
||
<a class="el" href="close_8c.html#a796034966c1e918152e652635431dc39" title="Serialize the dump hardware block containing acquisition environment information.">write_dumphw_block()</a> for the serialization process during image closing. </dd></dl>
|
||
|
||
<p class="definition">Definition at line <a class="el" href="dump_8c_source.html#l00531">531</a> of file <a class="el" href="dump_8c_source.html">dump.c</a>.</p>
|
||
|
||
<p class="reference">References <a class="el" href="decls_8h_source.html#l00045">AARU_CALL</a>, <a class="el" href="decls_8h_source.html#l00054">AARU_EXPORT</a>, <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="errors_8h_source.html#l00046">AARUF_ERROR_CANNOT_READ_BLOCK</a>, <a class="el" href="errors_8h_source.html#l00065">AARUF_ERROR_INCORRECT_DATA_SIZE</a>, <a class="el" href="errors_8h_source.html#l00057">AARUF_ERROR_INVALID_BLOCK_CRC</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="helpers_8c_source.html#l00451">compare_extents()</a>, <a class="el" href="#a6b41f4a00a255e6704583614ef33571f">COPY_STRING_FIELD</a>, <a class="el" href="dump_8h_source.html#l00095">DumpHardwareHeader::crc64</a>, <a class="el" href="context_8h_source.html#l00212">aaruformat_context::dump_hardware_entries_with_data</a>, <a class="el" href="context_8h_source.html#l00232">aaruformat_context::dump_hardware_header</a>, <a class="el" href="enums_8h_source.html#l00156">DumpHardwareBlock</a>, <a class="el" href="dump_8h_source.html#l00093">DumpHardwareHeader::entries</a>, <a class="el" href="context_8h_source.html#l00315">DumpHardwareEntriesWithData::entry</a>, <a class="el" href="context_8h_source.html#l00316">DumpHardwareEntriesWithData::extents</a>, <a class="el" href="dump_8h_source.html#l00122">DumpHardwareEntry::extents</a>, <a class="el" href="log_8h_source.html#l00040">FATAL</a>, <a class="el" href="dump_8c_source.html#l00026">free_dump_hardware_entries()</a>, <a class="el" href="dump_8h_source.html#l00092">DumpHardwareHeader::identifier</a>, <a class="el" href="context_8h_source.html#l00292">aaruformat_context::is_writing</a>, <a class="el" href="dump_8h_source.html#l00094">DumpHardwareHeader::length</a>, <a class="el" href="context_8h_source.html#l00174">aaruformat_context::magic</a>, and <a class="el" href="log_8h_source.html#l00025">TRACE</a>.</p>
|
||
|
||
</div>
|
||
</div>
|
||
<a id="ab98a236ef7ac4de15fb37a2e3c3ce633" name="ab98a236ef7ac4de15fb37a2e3c3ce633"></a>
|
||
<h2 class="memtitle"><span class="permalink"><a href="#ab98a236ef7ac4de15fb37a2e3c3ce633">◆ </a></span>free_dump_hardware_entries()</h2>
|
||
|
||
<div class="memitem">
|
||
<div class="memproto">
|
||
<table class="mlabels">
|
||
<tr>
|
||
<td class="mlabels-left">
|
||
<table class="memname">
|
||
<tr>
|
||
<td class="memname">void free_dump_hardware_entries </td>
|
||
<td>(</td>
|
||
<td class="paramtype"><a class="el" href="structDumpHardwareEntriesWithData.html">DumpHardwareEntriesWithData</a> *</td> <td class="paramname"><span class="paramname"><em>entries</em></span>, </td>
|
||
</tr>
|
||
<tr>
|
||
<td class="paramkey"></td>
|
||
<td></td>
|
||
<td class="paramtype">uint32_t</td> <td class="paramname"><span class="paramname"><em>count</em></span> )</td>
|
||
</tr>
|
||
</table>
|
||
</td>
|
||
<td class="mlabels-right">
|
||
<span class="mlabels"><span class="mlabel static">static</span></span> </td>
|
||
</tr>
|
||
</table>
|
||
</div><div class="memdoc">
|
||
|
||
<p class="definition">Definition at line <a class="el" href="dump_8c_source.html#l00026">26</a> of file <a class="el" href="dump_8c_source.html">dump.c</a>.</p>
|
||
|
||
<p class="reference">Referenced by <a class="el" href="dump_8c_source.html#l00531">aaruf_set_dumphw()</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="dump_8c.html">dump.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>
|