Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions libfsxfs/fsxfs_superblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,26 @@ struct fsxfs_superblock_v5
* Consists of 4 bytes
*/
uint8_t secondary_feature_flags_copy[ 4 ];

/* Compatible feature flags (v5 only)
* Consists of 4 bytes
*/
uint8_t features_compat[ 4 ];

/* Read-only compatible feature flags (v5 only)
* Consists of 4 bytes
*/
uint8_t features_ro_compat[ 4 ];

/* Incompatible feature flags (v5 only)
* Consists of 4 bytes
*/
uint8_t features_incompat[ 4 ];

/* Log incompatible feature flags (v5 only)
* Consists of 4 bytes
*/
uint8_t features_log_incompat[ 4 ];
};

#if defined( __cplusplus )
Expand Down
7 changes: 7 additions & 0 deletions libfsxfs/libfsxfs_definitions.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ enum LIBFSXFS_SECONDARY_FEATURE_FLAGS
LIBFSXFS_SECONDARY_FEATURE_FLAG_FILE_TYPE = 0x00000200UL
};

/* The incompatible feature flags (v5 only)
*/
enum LIBFSXFS_INCOMPAT_FEATURE_FLAGS
{
LIBFSXFS_INCOMPAT_FEATURE_FLAG_BIGTIME = 0x00000008UL
};

/* The fork types
*/
enum LIBFSXFS_FORK_TYPES
Expand Down
174 changes: 125 additions & 49 deletions libfsxfs/libfsxfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,23 +218,50 @@ int libfsxfs_inode_free(
return( result );
}

/* Converts bigtime ondisk timestamp to Unix nanoseconds
* Returns the Unix timestamp in nanoseconds
*/
static int64_t libfsxfs_inode_bigtime_to_unix(
uint64_t ondisk_nanoseconds )
{
#define FSXFS_BIGTIME_EPOCH_OFFSET -2147483648LL
#define NSEC_PER_SEC 1000000000ULL

uint64_t seconds;
uint32_t nanoseconds;
int64_t unix_seconds;
int64_t unix_nanoseconds;

seconds = ondisk_nanoseconds / NSEC_PER_SEC;
nanoseconds = ondisk_nanoseconds % NSEC_PER_SEC;

unix_seconds = (int64_t) seconds + FSXFS_BIGTIME_EPOCH_OFFSET;
unix_nanoseconds = unix_seconds * (int64_t) NSEC_PER_SEC + nanoseconds;

return( unix_nanoseconds );

#undef FSXFS_BIGTIME_EPOCH_OFFSET
#undef NSEC_PER_SEC
}

/* Reads the inode data
* Returns 1 if successful or -1 on error
*/
int libfsxfs_inode_read_data(
libfsxfs_inode_t *inode,
libfsxfs_io_handle_t *io_handle,
const uint8_t *data,
size_t data_size,
libcerror_error_t **error )
{
static char *function = "libfsxfs_inode_read_data";
size_t data_fork_size = 0;
size_t inode_data_size = 0;
uint64_t value_64bit = 0;
uint32_t value_32bit = 0;
uint8_t format_version = 0;

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

Expand Down Expand Up @@ -348,59 +375,95 @@ int libfsxfs_inode_read_data(
( (fsxfs_inode_v2_t *) data )->number_of_links,
inode->number_of_links );
}
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->access_time,
value_32bit );

inode->access_time = (int32_t) value_32bit * (int64_t) 1000000000;

byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->access_time_nano_seconds,
value_32bit );

if( inode->access_time > 0 )
if( ( io_handle->features_incompat & LIBFSXFS_INCOMPAT_FEATURE_FLAG_BIGTIME ) != 0 )
{
inode->access_time += value_32bit;
byte_stream_copy_to_uint64_big_endian(
( (fsxfs_inode_v1_t *) data )->access_time,
value_64bit );

inode->access_time = libfsxfs_inode_bigtime_to_unix(
value_64bit );
}
else
{
inode->access_time -= value_32bit;
}
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->modification_time,
value_32bit );
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->access_time,
value_32bit );

inode->modification_time = (int32_t) value_32bit * (int64_t) 1000000000;
inode->access_time = (int32_t) value_32bit * (int64_t) 1000000000;

byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->modification_time_nano_seconds,
value_32bit );
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->access_time_nano_seconds,
value_32bit );

if( inode->modification_time > 0 )
if( inode->access_time > 0 )
{
inode->access_time += value_32bit;
}
else
{
inode->access_time -= value_32bit;
}
}
if( ( io_handle->features_incompat & LIBFSXFS_INCOMPAT_FEATURE_FLAG_BIGTIME ) != 0 )
{
inode->modification_time += value_32bit;
byte_stream_copy_to_uint64_big_endian(
( (fsxfs_inode_v1_t *) data )->modification_time,
value_64bit );

inode->modification_time = libfsxfs_inode_bigtime_to_unix(
value_64bit );
}
else
{
inode->modification_time -= value_32bit;
}
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->inode_change_time,
value_32bit );
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->modification_time,
value_32bit );

inode->inode_change_time = (int32_t) value_32bit * (int64_t) 1000000000;
inode->modification_time = (int32_t) value_32bit * (int64_t) 1000000000;

byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->inode_change_time_nano_seconds,
value_32bit );
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->modification_time_nano_seconds,
value_32bit );

if( inode->inode_change_time > 0 )
if( inode->modification_time > 0 )
{
inode->modification_time += value_32bit;
}
else
{
inode->modification_time -= value_32bit;
}
}
if( ( io_handle->features_incompat & LIBFSXFS_INCOMPAT_FEATURE_FLAG_BIGTIME ) != 0 )
{
inode->inode_change_time += value_32bit;
byte_stream_copy_to_uint64_big_endian(
( (fsxfs_inode_v1_t *) data )->inode_change_time,
value_64bit );

inode->inode_change_time = libfsxfs_inode_bigtime_to_unix(
value_64bit );
}
else
{
inode->inode_change_time -= value_32bit;
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->inode_change_time,
value_32bit );

inode->inode_change_time = (int32_t) value_32bit * (int64_t) 1000000000;

byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v1_t *) data )->inode_change_time_nano_seconds,
value_32bit );

if( inode->inode_change_time > 0 )
{
inode->inode_change_time += value_32bit;
}
else
{
inode->inode_change_time -= value_32bit;
}
}
byte_stream_copy_to_uint64_big_endian(
( (fsxfs_inode_v1_t *) data )->data_size,
Expand Down Expand Up @@ -690,23 +753,35 @@ int libfsxfs_inode_read_data(
}
if( format_version == 3 )
{
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v3_t *) data )->creation_time,
value_32bit );

inode->creation_time = (int32_t) value_32bit * (int64_t) 1000000000;

byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v3_t *) data )->creation_time_nano_seconds,
value_32bit );

if( inode->creation_time > 0 )
if( ( io_handle->features_incompat & LIBFSXFS_INCOMPAT_FEATURE_FLAG_BIGTIME ) != 0 )
{
inode->creation_time += value_32bit;
byte_stream_copy_to_uint64_big_endian(
( (fsxfs_inode_v3_t *) data )->creation_time,
value_64bit );

inode->creation_time = libfsxfs_inode_bigtime_to_unix(
value_64bit );
}
else
{
inode->creation_time -= value_32bit;
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v3_t *) data )->creation_time,
value_32bit );

inode->creation_time = (int32_t) value_32bit * (int64_t) 1000000000;

byte_stream_copy_to_uint32_big_endian(
( (fsxfs_inode_v3_t *) data )->creation_time_nano_seconds,
value_32bit );

if( inode->creation_time > 0 )
{
inode->creation_time += value_32bit;
}
else
{
inode->creation_time -= value_32bit;
}
}
#if defined( HAVE_DEBUG_OUTPUT )
if( libcnotify_verbose != 0 )
Expand Down Expand Up @@ -931,6 +1006,7 @@ int libfsxfs_inode_read_file_io_handle(
}
if( libfsxfs_inode_read_data(
inode,
io_handle,
inode->data,
inode->data_size,
error ) != 1 )
Expand Down
1 change: 1 addition & 0 deletions libfsxfs/libfsxfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ int libfsxfs_inode_free(

int libfsxfs_inode_read_data(
libfsxfs_inode_t *inode,
libfsxfs_io_handle_t *io_handle,
const uint8_t *data,
size_t data_size,
libcerror_error_t **error );
Expand Down
4 changes: 4 additions & 0 deletions libfsxfs/libfsxfs_io_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ struct libfsxfs_io_handle
*/
uint32_t secondary_feature_flags;

/* Incompatible feature flags (v5 only)
*/
uint32_t features_incompat;

/* The block size
*/
uint32_t block_size;
Expand Down
6 changes: 6 additions & 0 deletions libfsxfs/libfsxfs_superblock.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ int libfsxfs_superblock_read_data(
( (fsxfs_superblock_t *) data )->secondary_feature_flags,
superblock->secondary_feature_flags );

if( superblock->format_version == 5 )
{
byte_stream_copy_to_uint32_big_endian(
( (fsxfs_superblock_v5_t *) data )->features_incompat,
superblock->features_incompat );
}
#if defined( HAVE_DEBUG_OUTPUT )
if( libcnotify_verbose != 0 )
{
Expand Down
4 changes: 4 additions & 0 deletions libfsxfs/libfsxfs_superblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ struct libfsxfs_superblock
*/
uint32_t secondary_feature_flags;

/* Incompatible feature flags (v5 only)
*/
uint32_t features_incompat;

/* Number of bits used for the relative block number
*/
uint8_t number_of_relative_block_number_bits;
Expand Down
1 change: 1 addition & 0 deletions libfsxfs/libfsxfs_volume.c
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@ int libfsxfs_internal_volume_open_read(
internal_volume->superblock = superblock;
internal_volume->io_handle->format_version = superblock->format_version;
internal_volume->io_handle->secondary_feature_flags = superblock->secondary_feature_flags;
internal_volume->io_handle->features_incompat = superblock->features_incompat;
internal_volume->io_handle->block_size = superblock->block_size;
internal_volume->io_handle->allocation_group_size = superblock->allocation_group_size;
internal_volume->io_handle->inode_size = superblock->inode_size;
Expand Down