Skip to content

Commit

Permalink
Worked on format support #13
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimmetz committed Mar 2, 2024
1 parent 921a58c commit 26d0843
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 36 deletions.
21 changes: 15 additions & 6 deletions documentation/Extended File System (EXT).asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,9 @@ See section: <<checksum_types,checksum types>>
Some versions of mkfs.ext set the file system creation time even for ext2 and
when EXT3_FEATURE_COMPAT_HAS_JOURNAL is not set.

The checksum, if checksum type is CRC-32C, contain a CRC-32 of data in the
superblock before the checksum. The checksum is stored as 0xffffffff - CRC-32C.
The checksum is calculated from the data in the superblock before the checksum.

If checksum type is CRC-32C, the checksum is stored as 0xffffffff - CRC-32C.

[yellow-background]*Is the only way to determine the file system version the
compatibility and equivalent flags?*
Expand Down Expand Up @@ -641,8 +642,7 @@ Contains the lower 16-bit of the value if 64-bit support (EXT4_FEATURE_INCOMPAT_
The checksum is a CRC-32C [yellow-background]*TODO: crc32c(s_uuid+grp_num+ibitmap)*
| 28 | 2 | | Number of unused inodes +
Contains the lower 16-bit of the value if 64-bit support (EXT4_FEATURE_INCOMPAT_64BIT) is enabled +
| 30 | 2 | | Checksum +
The checksum is a CRC-16 [yellow-background]*TODO: crc16(sb_uuid+group+desc)*
| 30 | 2 | | Checksum
4+| _If 64-bit support (EXT4_FEATURE_INCOMPAT_64BIT) is enabled and group descriptor size > 32_
| 32 | 4 | | Block bitmap block number +
Contains the upper 32-bit of the value +
Expand Down Expand Up @@ -674,6 +674,15 @@ The checksum is a CRC-32C [yellow-background]*TODO: crc32c(s_uuid+grp_num+ibitma
| 64 | 4 | | [yellow-background]*Unknown (reserved)*
|===

The checksum is calculated from:

* file system identifier in the superblock
* group number
* data of the group descriptor with the checksum set to 0-byte values.

If checksum type is CRC-32C, the checksum is stored as the lower 16-bits of 0xffffffff
- CRC-32C, otherwise the checksum is stored as CRC-16.

=== [[block_group_flags]]Block group flags

*TODO: add description*
Expand Down Expand Up @@ -975,14 +984,14 @@ Contains the upper 16-bit of the checksum value
For a character and block device the first 2 bytes of the array of direct
block numbers contain the minor and major device number respectively.

The checksum, if checksum type is CRC-32C, contain a CRC-32 of:
The checksum is calculated from:

* file system identifier in the superblock
* inode number
* NFS generation number in the inode
* data of the inode with the lower and upper part of the checksum set to 0-byte values.

The checksum is stored as 0xffffffff - CRC-32C.
If checksum type is CRC-32C, the checksum is stored as 0xffffffff - CRC-32C.

[yellow-background]*TODO describe extra precision*

Expand Down
133 changes: 122 additions & 11 deletions libfsext/libfsext_group_descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <memory.h>
#include <types.h>

#include "libfsext_checksum.h"
#include "libfsext_definitions.h"
#include "libfsext_group_descriptor.h"
#include "libfsext_io_handle.h"
Expand Down Expand Up @@ -146,14 +147,16 @@ int libfsext_group_descriptor_read_data(
size_t data_size,
libcerror_error_t **error )
{
uint8_t checksum_data[ 4 ];
uint8_t empty_checksum_data[ 2 ] = { 0, 0 };

static char *function = "libfsext_group_descriptor_read_data";
size_t group_descriptor_data_size = 0;
uint64_t value_64bit = 0;
uint32_t calculated_checksum = 0;
uint32_t stored_checksum = 0;
uint32_t value_32bit = 0;

#if defined( HAVE_DEBUG_OUTPUT )
uint16_t value_16bit = 0;
#endif

if( group_descriptor == NULL )
{
Expand Down Expand Up @@ -331,6 +334,12 @@ int libfsext_group_descriptor_read_data(
( (fsext_group_descriptor_ext4_t *) data )->number_of_unused_inodes_lower,
group_descriptor->number_of_unused_inodes );

byte_stream_copy_to_uint16_little_endian(
( (fsext_group_descriptor_ext4_t *) data )->checksum,
value_16bit );

stored_checksum = value_16bit;

#if defined( HAVE_DEBUG_OUTPUT )
if( libcnotify_verbose != 0 )
{
Expand Down Expand Up @@ -587,21 +596,123 @@ int libfsext_group_descriptor_read_data(
function,
group_descriptor->number_of_unused_inodes );

libcnotify_printf(
"%s: block bitmap checksum\t\t\t: 0x%04" PRIx32 "\n",
function,
group_descriptor->block_bitmap_checksum );
if( ( io_handle->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_METADATA_CHECKSUM ) != 0 )
{
libcnotify_printf(
"%s: block bitmap checksum\t\t\t: 0x%08" PRIx32 "\n",
function,
group_descriptor->block_bitmap_checksum );

libcnotify_printf(
"%s: inode bitmap checksum\t\t\t: 0x%04" PRIx32 "\n",
function,
group_descriptor->inode_bitmap_checksum );
libcnotify_printf(
"%s: inode bitmap checksum\t\t\t: 0x%08" PRIx32 "\n",
function,
group_descriptor->inode_bitmap_checksum );
}
else
{
libcnotify_printf(
"%s: block bitmap checksum\t\t\t: 0x%04" PRIx32 "\n",
function,
group_descriptor->block_bitmap_checksum );

libcnotify_printf(
"%s: inode bitmap checksum\t\t\t: 0x%04" PRIx32 "\n",
function,
group_descriptor->inode_bitmap_checksum );
}
libcnotify_printf(
"\n" );
}
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
}
/* TODO add support for crc16 checksum */
if( ( io_handle->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_METADATA_CHECKSUM ) != 0 )
{
byte_stream_copy_from_uint32_little_endian(
checksum_data,
group_descriptor->group_number );

if( libfsext_checksum_calculate_crc32(
&calculated_checksum,
checksum_data,
4,
io_handle->metadata_checksum_seed,
error ) != 1 )
{
libcerror_error_set(
error,
LIBCERROR_ERROR_DOMAIN_RUNTIME,
LIBCERROR_RUNTIME_ERROR_SET_FAILED,
"%s: unable to calculate CRC-32.",
function );

return( -1 );
}
if( libfsext_checksum_calculate_crc32(
&calculated_checksum,
data,
30,
calculated_checksum,
error ) != 1 )
{
libcerror_error_set(
error,
LIBCERROR_ERROR_DOMAIN_RUNTIME,
LIBCERROR_RUNTIME_ERROR_SET_FAILED,
"%s: unable to calculate CRC-32.",
function );

return( -1 );
}
if( libfsext_checksum_calculate_crc32(
&calculated_checksum,
empty_checksum_data,
2,
calculated_checksum,
error ) != 1 )
{
libcerror_error_set(
error,
LIBCERROR_ERROR_DOMAIN_RUNTIME,
LIBCERROR_RUNTIME_ERROR_SET_FAILED,
"%s: unable to calculate CRC-32.",
function );

return( -1 );
}
if( libfsext_checksum_calculate_crc32(
&calculated_checksum,
&( data[ 32 ] ),
data_size - 32,
calculated_checksum,
error ) != 1 )
{
libcerror_error_set(
error,
LIBCERROR_ERROR_DOMAIN_RUNTIME,
LIBCERROR_RUNTIME_ERROR_SET_FAILED,
"%s: unable to calculate CRC-32.",
function );

return( -1 );
}
calculated_checksum = ( 0xffffffffUL - calculated_checksum ) & 0x0000ffffUL;

if( ( stored_checksum != 0 )
&& ( stored_checksum != calculated_checksum ) )
{
#if defined( HAVE_DEBUG_OUTPUT )
if( libcnotify_verbose != 0 )
{
libcnotify_printf(
"%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
function,
stored_checksum,
calculated_checksum );
}
#endif
}
}
return( 1 );
}

Expand Down
4 changes: 4 additions & 0 deletions libfsext/libfsext_group_descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ typedef struct libfsext_group_descriptor libfsext_group_descriptor_t;

struct libfsext_group_descriptor
{
/* Group number
*/
uint32_t group_number;

/* Block bitmap block number
*/
uint64_t block_bitmap_block_number;
Expand Down
8 changes: 4 additions & 4 deletions libfsext/libfsext_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,6 @@ int libfsext_inode_clone(
int libfsext_inode_read_data(
libfsext_inode_t *inode,
libfsext_io_handle_t *io_handle,
uint32_t inode_number,
const uint8_t *data,
size_t data_size,
libcerror_error_t **error )
Expand Down Expand Up @@ -1520,7 +1519,7 @@ int libfsext_inode_read_data(
{
byte_stream_copy_from_uint32_little_endian(
checksum_data,
inode_number + 1 );
inode->inode_number );

if( libfsext_checksum_calculate_crc32(
&calculated_checksum,
Expand Down Expand Up @@ -2562,7 +2561,7 @@ int libfsext_inode_read_element_data(
LIBFSEXT_UNREFERENCED_PARAMETER( element_flags )
LIBFSEXT_UNREFERENCED_PARAMETER( read_flags )

if( (uint64_t) element_index > (uint64_t) UINT32_MAX )
if( (uint64_t) element_index > (uint64_t) ( UINT32_MAX - 1 ) )
{
libcerror_error_set(
error,
Expand Down Expand Up @@ -2642,10 +2641,11 @@ int libfsext_inode_read_element_data(

goto on_error;
}
inode->inode_number = (uint32_t) element_index + 1;

if( libfsext_inode_read_data(
inode,
io_handle,
(uint32_t) element_index,
data,
(size_t) element_data_size,
error ) != 1 )
Expand Down
5 changes: 4 additions & 1 deletion libfsext/libfsext_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ typedef struct libfsext_inode libfsext_inode_t;

struct libfsext_inode
{
/* Inode number
*/
uint32_t inode_number;

/* File mode
*/
uint16_t file_mode;
Expand Down Expand Up @@ -154,7 +158,6 @@ int libfsext_inode_clone(
int libfsext_inode_read_data(
libfsext_inode_t *inode,
libfsext_io_handle_t *io_handle,
uint32_t inode_number,
const uint8_t *data,
size_t data_size,
libcerror_error_t **error );
Expand Down
2 changes: 2 additions & 0 deletions libfsext/libfsext_volume.c
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,8 @@ int libfsext_internal_volume_read_block_groups(

goto on_error;
}
group_descriptor->group_number = group_descriptor_index;

if( libfsext_group_descriptor_read_file_io_handle(
group_descriptor,
internal_volume->io_handle,
Expand Down
2 changes: 0 additions & 2 deletions tests/fsext_test_block_vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ int fsext_test_block_vector_initialize(
result = libfsext_inode_read_data(
inode,
io_handle,
0,
fsext_test_inode_data1,
128,
&error );
Expand Down Expand Up @@ -469,7 +468,6 @@ int fsext_test_block_vector_read_element_data(
result = libfsext_inode_read_data(
inode,
io_handle,
0,
fsext_test_inode_data1,
128,
&error );
Expand Down
2 changes: 0 additions & 2 deletions tests/fsext_test_directory.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,6 @@ int fsext_test_directory_read_file_io_handle(
result = libfsext_inode_read_data(
inode,
io_handle,
0,
fsext_test_inode_data1,
128,
&error );
Expand Down Expand Up @@ -1067,7 +1066,6 @@ int main(
result = libfsext_inode_read_data(
inode,
io_handle,
0,
fsext_test_inode_data1,
128,
&error );
Expand Down
Loading

0 comments on commit 26d0843

Please sign in to comment.