RAR (Roshall ARchiver) archive files: GraphViz block diagram (.dot) source

RAR is a archive format used by popular proprietary RAR archiver, created by Eugene Roshal. There are two major versions of format (v1.5-4.0 and RAR v5+).

File format essentially consists of a linear sequence of blocks. Each block has fixed header and custom body (that depends on block type), so it's possible to skip block even if one doesn't know how to process a certain block type.

Application

RAR archiver

File extension

rar

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.7

References

This page hosts a formal specification of RAR (Roshall ARchiver) archive files using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

rar.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__rar {
		label="Rar";
		graph[style=dotted];

		rar__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			<TR><TD PORT="magic_pos">0</TD><TD PORT="magic_size">8</TD><TD>MagicSignature</TD><TD PORT="magic_type">magic</TD></TR>
			<TR><TD PORT="blocks_pos">8</TD><TD PORT="blocks_size">...</TD><TD>switch (magic.version)</TD><TD PORT="blocks_type">blocks</TD></TR>
			<TR><TD COLSPAN="4" PORT="blocks__repeat">repeat to end of stream</TD></TR>
		</TABLE>>];
rar__seq_blocks_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
	<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
	<TR><TD>0</TD><TD PORT="case0">Block</TD></TR>
	<TR><TD>1</TD><TD PORT="case1">BlockV5</TD></TR>
</TABLE>>];
		subgraph cluster__magic_signature {
			label="Rar::MagicSignature";
			graph[style=dotted];

			magic_signature__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="magic1_pos">0</TD><TD PORT="magic1_size">6</TD><TD></TD><TD PORT="magic1_type">magic1</TD></TR>
				<TR><TD PORT="version_pos">6</TD><TD PORT="version_size">1</TD><TD>u1</TD><TD PORT="version_type">version</TD></TR>
				<TR><TD PORT="magic3_pos">7</TD><TD PORT="magic3_size">1</TD><TD></TD><TD PORT="magic3_type">magic3</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__block {
			label="Rar::Block";
			graph[style=dotted];

			block__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="crc16_pos">0</TD><TD PORT="crc16_size">2</TD><TD>u2le</TD><TD PORT="crc16_type">crc16</TD></TR>
				<TR><TD PORT="block_type_pos">2</TD><TD PORT="block_type_size">1</TD><TD>u1→BlockTypes</TD><TD PORT="block_type_type">block_type</TD></TR>
				<TR><TD PORT="flags_pos">3</TD><TD PORT="flags_size">2</TD><TD>u2le</TD><TD PORT="flags_type">flags</TD></TR>
				<TR><TD PORT="block_size_pos">5</TD><TD PORT="block_size_size">2</TD><TD>u2le</TD><TD PORT="block_size_type">block_size</TD></TR>
				<TR><TD PORT="add_size_pos">7</TD><TD PORT="add_size_size">4</TD><TD>u4le</TD><TD PORT="add_size_type">add_size</TD></TR>
				<TR><TD PORT="body_pos">11</TD><TD PORT="body_size">...</TD><TD>switch (block_type)</TD><TD PORT="body_type">body</TD></TR>
				<TR><TD PORT="add_body_pos">...</TD><TD PORT="add_body_size">add_size</TD><TD></TD><TD PORT="add_body_type">add_body</TD></TR>
			</TABLE>>];
			block__inst__has_add [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>has_add</TD><TD>(flags &amp; 32768) != 0</TD></TR>
			</TABLE>>];
			block__inst__header_size [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>header_size</TD><TD>(has_add ? 11 : 7)</TD></TR>
			</TABLE>>];
			block__inst__body_size [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>body_size</TD><TD>(block_size - header_size)</TD></TR>
			</TABLE>>];
block__seq_body_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
	<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
	<TR><TD>:block_types_file_header</TD><TD PORT="case0">BlockFileHeader</TD></TR>
</TABLE>>];
		}
		subgraph cluster__block_file_header {
			label="Rar::BlockFileHeader";
			graph[style=dotted];

			block_file_header__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="low_unp_size_pos">0</TD><TD PORT="low_unp_size_size">4</TD><TD>u4le</TD><TD PORT="low_unp_size_type">low_unp_size</TD></TR>
				<TR><TD PORT="host_os_pos">4</TD><TD PORT="host_os_size">1</TD><TD>u1→Oses</TD><TD PORT="host_os_type">host_os</TD></TR>
				<TR><TD PORT="file_crc32_pos">5</TD><TD PORT="file_crc32_size">4</TD><TD>u4le</TD><TD PORT="file_crc32_type">file_crc32</TD></TR>
				<TR><TD PORT="file_time_pos">9</TD><TD PORT="file_time_size">4</TD><TD>DosDatetime</TD><TD PORT="file_time_type">file_time</TD></TR>
				<TR><TD PORT="rar_version_pos">13</TD><TD PORT="rar_version_size">1</TD><TD>u1</TD><TD PORT="rar_version_type">rar_version</TD></TR>
				<TR><TD PORT="method_pos">14</TD><TD PORT="method_size">1</TD><TD>u1→Methods</TD><TD PORT="method_type">method</TD></TR>
				<TR><TD PORT="name_size_pos">15</TD><TD PORT="name_size_size">2</TD><TD>u2le</TD><TD PORT="name_size_type">name_size</TD></TR>
				<TR><TD PORT="attr_pos">17</TD><TD PORT="attr_size">4</TD><TD>u4le</TD><TD PORT="attr_type">attr</TD></TR>
				<TR><TD PORT="high_pack_size_pos">21</TD><TD PORT="high_pack_size_size">4</TD><TD>u4le</TD><TD PORT="high_pack_size_type">high_pack_size</TD></TR>
				<TR><TD PORT="file_name_pos">25</TD><TD PORT="file_name_size">name_size</TD><TD></TD><TD PORT="file_name_type">file_name</TD></TR>
				<TR><TD PORT="salt_pos">...</TD><TD PORT="salt_size">8</TD><TD>u8le</TD><TD PORT="salt_type">salt</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__block_v5 {
			label="Rar::BlockV5";
			graph[style=dotted];

			block_v5__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			</TABLE>>];
		}
	}
	rar__seq:magic_type -> magic_signature__seq [style=bold];
	rar__seq:blocks_type -> rar__seq_blocks_switch [style=bold];
	rar__seq_blocks_switch:case0 -> block__seq [style=bold];
	rar__seq_blocks_switch:case1 -> block_v5__seq [style=bold];
	magic_signature__seq:version_type -> rar__seq:blocks_type [color="#404040"];
	block__seq:body_type -> block__seq_body_switch [style=bold];
	block__seq_body_switch:case0 -> block_file_header__seq [style=bold];
	block__seq:block_type_type -> block__seq:body_type [color="#404040"];
	block__seq:add_size_type -> block__seq:add_body_size [color="#404040"];
	block__seq:flags_type -> block__inst__has_add [color="#404040"];
	block__inst__has_add:has_add_type -> block__inst__header_size [color="#404040"];
	block__seq:block_size_type -> block__inst__body_size [color="#404040"];
	block__inst__header_size:header_size_type -> block__inst__body_size [color="#404040"];
	block_file_header__seq:file_time_type -> dos_datetime__seq [style=bold];
	block_file_header__seq:name_size_type -> block_file_header__seq:file_name_size [color="#404040"];
}