Skip to content

Commit

Permalink
Changes to documentation and code clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimmetz committed Nov 9, 2024
1 parent ca158c7 commit f272c91
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 32 deletions.
93 changes: 71 additions & 22 deletions documentation/QEMU Copy-On-Write file format.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ for the libqcow project.
== License

....
Copyright (C) 2010-2020, Joachim Metz <[email protected]>.
Copyright (C) 2010-2024, Joachim Metz <[email protected]>.
Permission is granted to copy, distribute and/or modify this document under the
terms of the GNU Free Documentation License, Version 1.3 or any later version
published by the Free Software Foundation; with no Invariant Sections, no
Expand All @@ -55,6 +55,7 @@ May 2013 | Additional information regarding QCOW version 1, compression and encr
| 0.0.7 | J.B. Metz | December 2014 | Additional information regarding QCOW version 3.
| 0.0.8 | J.B. Metz | July 2020 | Formatting changes.
| 0.0.9 | J.B. Metz | December 2020 | Additional information regarding QCOW version 3.
| 0.0.10 | J.B. Metz | November 2024 | Textual changes.
|===

:numbered:
Expand Down Expand Up @@ -144,12 +145,12 @@ The version 1 file header is 48 bytes of size and consist of:

[cols="1,1,1,5",options="header"]
|===
| Offset | Size | Value | Description
| 0 | 4 | "QFI\xfb" | The signature (magic identifier) +
0x51 0x46 0x49 0xfb
| Offset
| 0 | 4 | "QFI\xfb" +
0x51 0x46 0x49 0xfb | The signature (magic identifier)
| 4 | 4 | 1 | Version
| 8 | 8 | | Backing filename offset
| 16 | 4 | | Backing filename size
| 8 | 8 | | Backing file name offset
| 16 | 4 | | Backing file name size
| 20 | 4 | | Modification date and time +
Contains a POSIX timestamp
| 24 | 8 | | Storage media size
Expand Down Expand Up @@ -189,21 +190,71 @@ else
level 1 table size *= 8
....

The backing filename is set in snapshot image files and is normally stored
The backing file name is set in snapshot image files and is normally stored
after the file header.

=== File header – version 2

The version 2 file header is 72 bytes of size and consist of:

[cols="1,1,1,5",options="header"]
|===
| Offset | Size | Value | Description
| 0 | 4 | "QFI\xfb" +
0x51 0x46 0x49 0xfb | The signature (magic identifier)
| 4 | 4 | 2 | Version
| 8 | 8 | | Backing file name offset
| 16 | 4 | | Backing file name size
| 20 | 4 | | Number of cluster block bits
| 24 | 8 | | Storage media size
| 32 | 4 | | Encryption method
| 36 | 4 | | Number of level 1 table references
| 40 | 8 | | Level 1 table offset
| 48 | 8 | | Reference count table offset
| 56 | 4 | | Reference count table clusters
| 60 | 4 | | Number of snapshots
| 64 | 8 | | Snapshots offset
|===

The cluster block size is calculated as:

....
cluster block size = 1 << number of cluster block bits
....

The number of level 2 table bits is calculated as:

....
number of level 2 table bits = number of cluster block bits - 3
....

The level table 2 size is calculated as:

....
level table 2 size = ( 1 << number of level 2 table bits ) * 8
....

The level 1 table size is calculated as:

....
level 1 table size = number of level 1 table references * 8
....

The backing file name is set in snapshot image files and is normally stored
after the file header.

=== File header – version 2 or 3
=== File header – version 3

The version 2 file header is 72 or 112 bytes of size and consist of:
The version 3 file header is 104 or 112 bytes of size and consist of:

[cols="1,1,1,5",options="header"]
|===
| Offset | Size | Value | Description
| 0 | 4 | "QFI\xfb" | The signature (magic identifier) +
0x51 0x46 0x49 0xfb
| 4 | 4 | 2 or 3 | Version
| 8 | 8 | | Backing filename offset
| 16 | 4 | | Backing filename size
| 0 | 4 | "QFI\xfb" +
0x51 0x46 0x49 0xfb | The signature (magic identifier)
| 4 | 4 | 3 | Version
| 8 | 8 | | Backing file name offset
| 16 | 4 | | Backing file name size
| 20 | 4 | | Number of cluster block bits
| 24 | 8 | | Storage media size
| 32 | 4 | | Encryption method
Expand All @@ -213,16 +264,14 @@ The version 2 file header is 72 or 112 bytes of size and consist of:
| 56 | 4 | | Reference count table clusters
| 60 | 4 | | Number of snapshots
| 64 | 8 | | Snapshots offset
4+| _Introduced in version 3_
| 72 | 8 | | Incompatible feature flags
| 80 | 8 | | Compatible feature flags
| 88 | 8 | | Auto-clear feature flags
| 96 | 4 | | Reference count order
| 100 | 4 | 104 +
112 | File header size +
| 100 | 4 | 104 or 112 | File header size +
Contains the size of the file header, this value does not include the size of the file header extensions
4+| _If file header size > 104_
| 104 | 1 | | Compression type
4+| _If file header size equals 112_
| 104 | 1 | | Compression method
| 105 | 7 | | [yellow-background]*Unknown (padding)*
|===

Expand Down Expand Up @@ -250,7 +299,7 @@ The level 1 table size is calculated as:
level 1 table size = number of level 1 table references * 8
....

The backing filename is set in snapshot image files and is normally stored
The backing file name is set in snapshot image files and is normally stored
after the file header.

=== Encryption methods
Expand Down Expand Up @@ -292,7 +341,7 @@ after the file header.
| 0x00000002 | QCOW2_AUTOCLEAR_DATA_FILE_RAW |
|===

=== Compression types
=== Compression methods

[cols="1,1,5",options="header"]
|===
Expand Down Expand Up @@ -592,7 +641,7 @@ The compressed data uses a zlib inflate window bits value of -12

== Snapshots

As of version 1 QCOW can use the backing filename in the file header to point
As of version 1 QCOW can use the backing file name in the file header to point
to a parent image that contains the snapshot image where the current image only
contains the modifications. Version 2 adds support to store snapshot inside the
image.
Expand Down
20 changes: 10 additions & 10 deletions tests/qcow_test_file_header.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ uint8_t qcow_test_file_header_data1[ 512 ] = {
int qcow_test_file_header_initialize(
void )
{
libcerror_error_t *error = NULL;
libcerror_error_t *error = NULL;
libqcow_file_header_t *file_header = NULL;
int result = 0;
int result = 0;

#if defined( HAVE_QCOW_TEST_MEMORY )
int number_of_malloc_fail_tests = 1;
int number_of_memset_fail_tests = 1;
int test_number = 0;
int number_of_malloc_fail_tests = 1;
int number_of_memset_fail_tests = 1;
int test_number = 0;
#endif

/* Test regular cases
Expand Down Expand Up @@ -313,9 +313,9 @@ int qcow_test_file_header_free(
int qcow_test_file_header_read_data(
void )
{
libcerror_error_t *error = NULL;
libcerror_error_t *error = NULL;
libqcow_file_header_t *file_header = NULL;
int result = 0;
int result = 0;

/* Initialize test
*/
Expand Down Expand Up @@ -534,10 +534,10 @@ int qcow_test_file_header_read_data(
int qcow_test_file_header_read_file_io_handle(
void )
{
libbfio_handle_t *file_io_handle = NULL;
libcerror_error_t *error = NULL;
libbfio_handle_t *file_io_handle = NULL;
libcerror_error_t *error = NULL;
libqcow_file_header_t *file_header = NULL;
int result = 0;
int result = 0;

/* Initialize test
*/
Expand Down

0 comments on commit f272c91

Please sign in to comment.