diff --git a/libvslvm_logical_volume.c b/libvslvm_logical_volume.c new file mode 100644 index 0000000..f17d335 --- /dev/null +++ b/libvslvm_logical_volume.c @@ -0,0 +1,1721 @@ +/* + * Logical volume functions + * + * Copyright (C) 2014-2023, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "libvslvm_chunk_data.h" +#include "libvslvm_data_area_descriptor.h" +#include "libvslvm_definitions.h" +#include "libvslvm_io_handle.h" +#include "libvslvm_libbfio.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_libcthreads.h" +#include "libvslvm_libfcache.h" +#include "libvslvm_libfdata.h" +#include "libvslvm_logical_volume.h" +#include "libvslvm_logical_volume_values.h" +#include "libvslvm_physical_volume.h" +#include "libvslvm_segment.h" +#include "libvslvm_stripe.h" +#include "libvslvm_types.h" +#include "libvslvm_unused.h" +#include "libvslvm_volume_group.h" +#include "libvslvm_raid.h" + +/* Creates a logical volume + * Make sure the value logical_volume is referencing, is set to NULL + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_initialize( + libvslvm_logical_volume_t **logical_volume, + libvslvm_io_handle_t *io_handle, + libvslvm_volume_group_t *volume_group, + libbfio_pool_t *physical_volume_file_io_pool, + libvslvm_logical_volume_values_t *logical_volume_values, + libcerror_error_t **error ) +{ + char physical_volume_name[ 64 ]; + + libvslvm_data_area_descriptor_t *data_area_descriptor = NULL; + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + libvslvm_physical_volume_t *physical_volume = NULL; + libvslvm_segment_t *segment = NULL; + libvslvm_raid_t *raid = NULL; + libvslvm_stripe_t *stripe = NULL; + static char *function = "libvslvm_logical_volume_initialize"; + off64_t segment_offset = 0; + off64_t stripe_offset = 0; + size64_t segment_size = 0; + size_t physical_volume_name_length = 0; + int element_index = 0; + int number_of_segments = 0; + int number_of_stripes = 0; + int result = 0; + int segment_index = 0; + int stripe_index = 0; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + if( *logical_volume != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid logical volume value already set.", + function ); + + return( -1 ); + } + if( logical_volume_values == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume values.", + function ); + + return( -1 ); + } + internal_logical_volume = memory_allocate_structure( + libvslvm_internal_logical_volume_t ); + + if( internal_logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create logical volume.", + function ); + + goto on_error; + } + if( memory_set( + internal_logical_volume, + 0, + sizeof( libvslvm_internal_logical_volume_t ) ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to clear logical volume.", + function ); + + memory_free( + internal_logical_volume ); + + return( -1 ); + } +/* TODO determine how the LVM raid chunk size is determined, 64k seems to be pretty standard */ + if( libfdata_vector_initialize( + &( internal_logical_volume->chunks_vector ), + (size64_t) ( 64 * 1024 ), + NULL, + NULL, + NULL, + (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libvslvm_logical_volume_read_chunk_data, + NULL, + LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create chunks vector.", + function ); + + goto on_error; + } + if( libvslvm_logical_volume_values_get_number_of_segments( + logical_volume_values, + &number_of_segments, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of segments.", + function ); + + goto on_error; + } + for( segment_index = 0; + segment_index < number_of_segments; + segment_index++ ) + { + if( libvslvm_logical_volume_values_get_segment( + logical_volume_values, + segment_index, + &segment, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve segment: %d.", + function, + segment_index ); + + goto on_error; + } + if( libvslvm_segment_get_range( + segment, + &segment_offset, + &segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve segment: %d range.", + function, + segment_index ); + + goto on_error; + } + //get the type + int segment_type = LVM_LV_TYPE_UNKNOWN; + if (libvslvm_segment_get_type(segment, &segment_type, error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve thesegment type", + function); + + goto on_error; + } + if (LVM_LV_TYPE_JBOD == segment_type) + { + if (libvslvm_segment_get_number_of_stripes( + segment, + &number_of_stripes, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of stripes.", + function); + + goto on_error; + } + /* TODO add support for multi stripe segments */ + if (number_of_stripes != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported number of stripes.", + function); + + goto on_error; + } + for (stripe_index = 0; + stripe_index < number_of_stripes; + stripe_index++) + { + if (libvslvm_segment_get_stripe( + segment, + stripe_index, + &stripe, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve stripe: %d.", + function, + stripe_index); + + goto on_error; + } + if (libvslvm_stripe_get_physical_volume_name( + stripe, + physical_volume_name, + 64, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve stripe: %d physical volume name.", + function, + stripe_index); + + goto on_error; + } + if (libvslvm_stripe_get_data_area_offset( + stripe, + &stripe_offset, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve stripe: %d data area offset.", + function, + stripe_index); + + goto on_error; + } + if (libvslvm_stripe_free( + &stripe, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free stripe: %d.", + function, + stripe_index); + + goto on_error; + } + physical_volume_name_length = narrow_string_length( + physical_volume_name) + 1; + + if (libvslvm_volume_group_get_physical_volume_by_name( + volume_group, + physical_volume_name, + physical_volume_name_length, + &physical_volume, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve physical volume by name.", + function); + + goto on_error; + } + result = libvslvm_physical_volume_get_data_area_descriptor_by_offset( + physical_volume, + stripe_offset, + &data_area_descriptor, + error); + + if (result == -1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve data area descriptor by offset: 0x%08" PRIx64 ".", + function, + segment_offset); + + goto on_error; + } + else if (result != 0) + { + if (data_area_descriptor == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing data area descriptor.", + function); + + goto on_error; + } + /* The stripe data area offset is relative to the start + * of the data area of the volume + */ + stripe_offset += data_area_descriptor->offset; + } + /* TODO check segment size ? */ + //add by lb 20191103 + if (libvslvm_physical_volume_free( + &physical_volume, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free physical volume: %s.", + function, + physical_volume_name); + + goto on_error; + } + } + } + + /* TODO skip the append if the physical volumes are not available? */ + if( libfdata_vector_append_segment( + internal_logical_volume->chunks_vector, + &element_index, + 0, + stripe_offset, + segment_size, + 0, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append segment to chunks vector.", + function ); + + goto on_error; + } + segment = NULL; + } + if( libfdata_vector_get_size( + internal_logical_volume->chunks_vector, + &( internal_logical_volume->size ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve size from chunks vector.", + function ); + + goto on_error; + } + if( libfcache_cache_initialize( + &( internal_logical_volume->chunks_cache ), + LIBVSLVM_MAXIMUM_CACHE_ENTRIES_CHUNKS, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create chunks cache.", + function ); + + goto on_error; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_initialize( + &( internal_logical_volume->read_write_lock ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to initialize read/write lock.", + function ); + + goto on_error; + } +#endif + internal_logical_volume->io_handle = io_handle; + internal_logical_volume->physical_volume_file_io_pool = physical_volume_file_io_pool; + internal_logical_volume->logical_volume_values = logical_volume_values; + + *logical_volume= (libvslvm_logical_volume_t *) internal_logical_volume; + + return( 1 ); + +on_error: + if( stripe != NULL ) + { + libvslvm_stripe_free( + &stripe, + NULL ); + } + if( internal_logical_volume != NULL ) + { + if( internal_logical_volume->chunks_cache != NULL ) + { + libfcache_cache_free( + &( internal_logical_volume->chunks_cache ), + NULL ); + } + if( internal_logical_volume->chunks_vector != NULL ) + { + libfdata_vector_free( + &( internal_logical_volume->chunks_vector ), + NULL ); + } + memory_free( + internal_logical_volume ); + } + return( -1 ); +} + +/* Frees a logical volume + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_free( + libvslvm_logical_volume_t **logical_volume, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_free"; + int result = 1; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + if( *logical_volume != NULL ) + { + internal_logical_volume = (libvslvm_internal_logical_volume_t *) *logical_volume; + *logical_volume = NULL; + + /* The logical_volume_values and physical_volume_file_io_pool references are freed elsewhere + */ + if( libfdata_vector_free( + &( internal_logical_volume->chunks_vector ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free chunks vector.", + function ); + + result = -1; + } + if( libfcache_cache_free( + &( internal_logical_volume->chunks_cache ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free chunks cache.", + function ); + + result = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_free( + &( internal_logical_volume->read_write_lock ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free read/write lock.", + function ); + + result = -1; + } +#endif + memory_free( + internal_logical_volume ); + } + return( result ); +} + +/* Reads (logical volume) data at the current offset into a buffer using a Basic File IO (bfio) pool + * This function is not multi-thread safe acquire write lock before call + * Returns the number of bytes read or -1 on error + */ +ssize_t libvslvm_internal_logical_volume_read_buffer_from_file_io_pool( + libvslvm_internal_logical_volume_t *internal_logical_volume, + libbfio_pool_t *physical_volume_file_io_pool, + void *buffer, + size_t buffer_size, + libcerror_error_t **error ) +{ + libvslvm_chunk_data_t *chunk_data = NULL; + static char *function = "libvslvm_internal_logical_volume_read_buffer_from_file_io_pool"; + off64_t element_data_offset = 0; + size_t buffer_offset = 0; + size_t read_size = 0; + + if( internal_logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + if( internal_logical_volume->current_offset < 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid logical volume - current offset value out of bounds.", + function ); + + return( -1 ); + } + if( buffer_size == 0 ) + { + return( 0 ); + } + if( (size64_t) internal_logical_volume->current_offset >= internal_logical_volume->size ) + { + return( 0 ); + } + if( (size64_t) ( internal_logical_volume->current_offset + buffer_size ) > internal_logical_volume->size ) + { + buffer_size = (size_t) ( internal_logical_volume->size - internal_logical_volume->current_offset ); + } + while( buffer_size > 0 ) + { + if( libfdata_vector_get_element_value_at_offset( + internal_logical_volume->chunks_vector, + (intptr_t *) physical_volume_file_io_pool, + (libfdata_cache_t *) internal_logical_volume->chunks_cache, + internal_logical_volume->current_offset, + &element_data_offset, + (intptr_t **) &chunk_data, + 0, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve chunk data at offset: 0x%08" PRIx64 ".", + function, + internal_logical_volume->current_offset ); + + return( -1 ); + } + if( chunk_data == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing chunk data.", + function ); + + return( -1 ); + } + read_size = chunk_data->data_size - (size_t) element_data_offset; + + if( buffer_size < read_size ) + { + read_size = buffer_size; + } + if( memory_copy( + &( ( (uint8_t *) buffer )[ buffer_offset ] ), + &( chunk_data->data[ element_data_offset ] ), + read_size ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy chunk data.", + function ); + + return( -1 ); + } + internal_logical_volume->current_offset += read_size; + buffer_offset += read_size; + buffer_size -= read_size; + } + return( (ssize_t) buffer_offset ); +} + +/* Reads (logical volume) data at the current offset into a buffer + * Returns the number of bytes read or -1 on error + */ +ssize_t libvslvm_logical_volume_read_buffer( + libvslvm_logical_volume_t *logical_volume, + void *buffer, + size_t buffer_size, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_read_buffer"; + ssize_t read_count = 0; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_write( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for writing.", + function ); + + return( -1 ); + } +#endif + read_count = libvslvm_internal_logical_volume_read_buffer_from_file_io_pool( + internal_logical_volume, + internal_logical_volume->physical_volume_file_io_pool, + buffer, + buffer_size, + error ); + + if( read_count == -1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read buffer from logical volume.", + function ); + + read_count = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_write( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for writing.", + function ); + + return( -1 ); + } +#endif + return( read_count ); +} + +/* Reads (logical volume) data at a specific offset + * Returns the number of bytes read or -1 on error + */ +ssize_t libvslvm_logical_volume_read_buffer_at_offset( + libvslvm_logical_volume_t *logical_volume, + void *buffer, + size_t buffer_size, + off64_t offset, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_read_buffer_at_offset"; + ssize_t read_count = 0; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_write( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for writing.", + function ); + + return( -1 ); + } +#endif + if( libvslvm_internal_logical_volume_seek_offset( + internal_logical_volume, + offset, + SEEK_SET, + error ) == -1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_SEEK_FAILED, + "%s: unable to seek offset.", + function ); + + goto on_error; + } + read_count = libvslvm_internal_logical_volume_read_buffer_from_file_io_pool( + internal_logical_volume, + internal_logical_volume->physical_volume_file_io_pool, + buffer, + buffer_size, + error ); + + if( read_count == -1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read buffer.", + function ); + + goto on_error; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_write( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for writing.", + function ); + + return( -1 ); + } +#endif + return( read_count ); + +on_error: +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + libcthreads_read_write_lock_release_for_write( + internal_logical_volume->read_write_lock, + NULL ); +#endif + return( -1 ); +} + +/* Seeks a certain offset of the (logical volume) data + * This function is not multi-thread safe acquire write lock before call + * Returns the offset if seek is successful or -1 on error + */ +off64_t libvslvm_internal_logical_volume_seek_offset( + libvslvm_internal_logical_volume_t *internal_logical_volume, + off64_t offset, + int whence, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_internal_logical_volume_seek_offset"; + + if( internal_logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + if( ( whence != SEEK_CUR ) + && ( whence != SEEK_END ) + && ( whence != SEEK_SET ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported whence.", + function ); + + return( -1 ); + } + if( whence == SEEK_CUR ) + { + offset += internal_logical_volume->current_offset; + } + else if( whence == SEEK_END ) + { + offset += (off64_t) internal_logical_volume->size; + } + if( offset < 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid offset value out of bounds.", + function ); + + return( -1 ); + } + internal_logical_volume->current_offset = offset; + + return( offset ); +} + +/* Seeks a certain offset of the (logical volume) data + * Returns the offset if seek is successful or -1 on error + */ +off64_t libvslvm_logical_volume_seek_offset( + libvslvm_logical_volume_t *logical_volume, + off64_t offset, + int whence, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_seek_offset"; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_write( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for writing.", + function ); + + return( -1 ); + } +#endif + offset = libvslvm_internal_logical_volume_seek_offset( + internal_logical_volume, + offset, + whence, + error ); + + if( offset == -1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_SEEK_FAILED, + "%s: unable to seek offset.", + function ); + + offset = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_write( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for writing.", + function ); + + return( -1 ); + } +#endif + return( offset ); +} + +/* Retrieves the current offset of the (logical volume) data + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_offset( + libvslvm_logical_volume_t *logical_volume, + off64_t *offset, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_get_offset"; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + + if( offset == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid offset.", + function ); + + return( -1 ); + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + *offset = internal_logical_volume->current_offset; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( 1 ); +} + +/* Retrieves the size + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_size( + libvslvm_logical_volume_t *logical_volume, + size64_t *size, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_get_size"; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + + if( size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid size.", + function ); + + return( -1 ); + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + *size = internal_logical_volume->size; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( 1 ); +} + +/* Retrieves the size of the ASCII formatted name + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_name_size( + libvslvm_logical_volume_t *logical_volume, + size_t *name_size, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_get_name_size"; + int result = 1; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + if( libvslvm_logical_volume_values_get_name_size( + internal_logical_volume->logical_volume_values, + name_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve name size.", + function ); + + result = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( result ); +} + +/* Retrieves the ASCII formatted name + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_name( + libvslvm_logical_volume_t *logical_volume, + char *name, + size_t name_size, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_set_name"; + int result = 1; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + if( libvslvm_logical_volume_values_get_name( + internal_logical_volume->logical_volume_values, + name, + name_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve name.", + function ); + + result = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( result ); +} + +/* Retrieves the size of the ASCII formatted identifier + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_identifier_size( + libvslvm_logical_volume_t *logical_volume, + size_t *identifier_size, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_get_identifier_size"; + int result = 1; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logicalogical.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + if( libvslvm_logical_volume_values_get_identifier_size( + internal_logical_volume->logical_volume_values, + identifier_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve identifier size.", + function ); + + result = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( result ); +} + +/* Retrieves the ASCII formatted identifier + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_identifier( + libvslvm_logical_volume_t *logical_volume, + char *identifier, + size_t identifier_size, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_set_identifier"; + int result = 1; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + if( libvslvm_logical_volume_values_get_identifier( + internal_logical_volume->logical_volume_values, + identifier, + identifier_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve identifier.", + function ); + + result = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( result ); +} + +/* Retrieves the number of segments + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_number_of_segments( + libvslvm_logical_volume_t *logical_volume, + int *number_of_segments, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_get_number_of_segments"; + int result = 1; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + if( libvslvm_logical_volume_values_get_number_of_segments( + internal_logical_volume->logical_volume_values, + number_of_segments, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of segments.", + function ); + + result = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( result ); +} + +/* Retrieves a specific segment + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_get_segment( + libvslvm_logical_volume_t *logical_volume, + int segment_index, + libvslvm_segment_t **segment, + libcerror_error_t **error ) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_get_segment"; + int result = 1; + + if( logical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume.", + function ); + + return( -1 ); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *) logical_volume; + +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_grab_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to grab read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + if( libvslvm_logical_volume_values_get_segment( + internal_logical_volume->logical_volume_values, + segment_index, + segment, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve segment: %d.", + function, + segment_index ); + + result = -1; + } +#if defined( HAVE_MULTI_THREAD_SUPPORT ) + if( libcthreads_read_write_lock_release_for_read( + internal_logical_volume->read_write_lock, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to release read/write lock for reading.", + function ); + + return( -1 ); + } +#endif + return( result ); +} + +int libvslvm_logical_volume_compare_by_name( + libvslvm_logical_volume_t * logical_volume, + const char * name, + size_t name_length, + libcerror_error_t ** error) +{ + libvslvm_internal_logical_volume_t *internal_logical_volume = NULL; + static char *function = "libvslvm_logical_volume_compare_by_name"; + + if (logical_volume == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function); + + return(-1); + } + internal_logical_volume = (libvslvm_internal_logical_volume_t *)logical_volume; + + if (name == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid name.", + function); + + return(-1); + } + if (name_length > (size_t)(SSIZE_MAX - 1)) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: name length value exceeds maximum.", + function); + + return(-1); + } + if ((internal_logical_volume->logical_volume_values->name_size == name_length ) + && (memory_compare( + name, + internal_logical_volume->logical_volume_values->name, + internal_logical_volume->logical_volume_values->name_size) == 0)) + { + return(1); + } + return(0); +} + +/* Reads chunk data + * Callback function for the chunk data vector + * Returns 1 if successful or -1 on error + */ +int libvslvm_logical_volume_read_chunk_data( + intptr_t *data_handle LIBVSLVM_ATTRIBUTE_UNUSED, + libbfio_pool_t *file_io_pool, + libfdata_vector_t *vector, + libfdata_cache_t *cache, + int element_index, + int element_data_file_index, + off64_t element_data_offset, + size64_t element_data_size, + uint32_t element_data_flags LIBVSLVM_ATTRIBUTE_UNUSED, + uint8_t read_flags LIBVSLVM_ATTRIBUTE_UNUSED, + libcerror_error_t **error ) +{ + libvslvm_chunk_data_t *chunk_data = NULL; + static char *function = "libvslvm_logical_volume_read_chunk_data"; + + LIBVSLVM_UNREFERENCED_PARAMETER( data_handle ); + LIBVSLVM_UNREFERENCED_PARAMETER( element_data_flags ); + LIBVSLVM_UNREFERENCED_PARAMETER( read_flags ); + + if( element_data_size > (size64_t) SSIZE_MAX ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid element data size value exceeds maximum.", + function ); + + goto on_error; + } + if( libvslvm_chunk_data_initialize( + &chunk_data, + (size_t) element_data_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create chunk data.", + function ); + + goto on_error; + } + if( libvslvm_chunk_data_read_file_io_pool( + chunk_data, + file_io_pool, + element_data_file_index, + element_data_offset, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read chunk data.", + function ); + + goto on_error; + } + if( libfdata_vector_set_element_value_by_index( + vector, + (intptr_t *) file_io_pool, + cache, + element_index, + (intptr_t *) chunk_data, + (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_chunk_data_free, + LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set chunk data as element value.", + function ); + + goto on_error; + } + return( 1 ); + +on_error: + if( chunk_data != NULL ) + { + libvslvm_chunk_data_free( + &chunk_data, + NULL ); + } + return( -1 ); +} + diff --git a/libvslvm_metadata.c b/libvslvm_metadata.c new file mode 100644 index 0000000..83dbb94 --- /dev/null +++ b/libvslvm_metadata.c @@ -0,0 +1,4508 @@ +/* + * The metadata functions + * + * Copyright (C) 2014-2023, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "libvslvm_checksum.h" +#include "libvslvm_definitions.h" +#include "libvslvm_libbfio.h" +#include "libvslvm_libcdata.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_libcnotify.h" +#include "libvslvm_libcsplit.h" +#include "libvslvm_libfvalue.h" +#include "libvslvm_logical_volume_values.h" +#include "libvslvm_metadata.h" +#include "libvslvm_physical_volume.h" +#include "libvslvm_raw_location_descriptor.h" +#include "libvslvm_segment.h" +#include "libvslvm_stripe.h" +#include "libvslvm_volume_group.h" + +/* Creates a metadata + * Make sure the value metadata is referencing, is set to NULL + * Returns 1 if successful or -1 on error + */ +int libvslvm_metadata_initialize( + libvslvm_metadata_t **metadata, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_metadata_initialize"; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( *metadata != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid metadata value already set.", + function ); + + return( -1 ); + } + *metadata = memory_allocate_structure( + libvslvm_metadata_t ); + + if( *metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create metadata.", + function ); + + goto on_error; + } + if( memory_set( + *metadata, + 0, + sizeof( libvslvm_metadata_t ) ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to clear metadata.", + function ); + + memory_free( + *metadata ); + + *metadata = NULL; + + return( -1 ); + } + return( 1 ); + +on_error: + if( *metadata != NULL ) + { + memory_free( + *metadata ); + + *metadata = NULL; + } + return( -1 ); +} + +/* Frees a metadata + * Returns 1 if successful or -1 on error + */ +int libvslvm_metadata_free( + libvslvm_metadata_t **metadata, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_metadata_free"; + int result = 1; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( *metadata != NULL ) + { + if( ( *metadata )->volume_group != NULL ) + { + if( libvslvm_internal_volume_group_free( + (libvslvm_internal_volume_group_t **) &( ( *metadata )->volume_group ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free volume group.", + function ); + + result = -1; + } + } + memory_free( + *metadata ); + + *metadata = NULL; + } + return( result ); +} + +/* Reads the metadata + * Returns 1 if successful or -1 on error + */ +int libvslvm_metadata_read_data( + libvslvm_metadata_t *metadata, + const uint8_t *data, + size_t data_size, + uint32_t stored_checksum, + libcerror_error_t **error ) +{ + libcsplit_narrow_split_string_t *lines = NULL; + static char *function = "libvslvm_metadata_read_data"; + uint32_t calculated_checksum = 0; + int line_index = 0; + int number_of_lines = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( data == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid data.", + function ); + + return( -1 ); + } + if( ( data_size == 0 ) + || ( data_size > (size_t) SSIZE_MAX ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid data size value out of bounds.", + function ); + + return( -1 ); + } + if( libvslvm_checksum_calculate_weak_crc32( + &calculated_checksum, + data, + data_size, + 0xf597a6cfUL, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to calculate CRC-32.", + function ); + + goto on_error; + } + if( ( stored_checksum != 0 ) + && ( stored_checksum != calculated_checksum ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_INPUT, + LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, + "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).", + function, + stored_checksum, + calculated_checksum ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: metadata:\n%s", + function, + data ); + } +#endif + if( libcsplit_narrow_string_split( + (char *) data, + data_size, + '\n', + &lines, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to split data into lines.", + function ); + + goto on_error; + } + if( libcsplit_narrow_split_string_get_number_of_segments( + lines, + &number_of_lines, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to retrieve number of lines.", + function ); + + goto on_error; + } + if( libvslvm_metadata_read_volume_group( + metadata, + lines, + number_of_lines, + &line_index, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read volume group.", + function ); + + goto on_error; + } + if( libcsplit_narrow_split_string_free( + &lines, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free lines.", + function ); + + goto on_error; + } + return( 1 ); + +on_error: + if( lines != NULL ) + { + libcsplit_narrow_split_string_free( + &lines, + NULL ); + } + return( -1 ); +} + +/* Reads the metadata + * Returns 1 if successful or -1 on error + */ +int libvslvm_metadata_read_file_io_handle( + libvslvm_metadata_t *metadata, + libbfio_handle_t *file_io_handle, + off64_t file_offset, + size64_t metadata_size, + uint32_t stored_checksum, + libcerror_error_t **error ) +{ + uint8_t *data = NULL; + static char *function = "libvslvm_metadata_read_file_io_handle"; + ssize_t read_count = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( ( metadata_size == 0 ) + || ( metadata_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid metadata size value out of bounds.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: reading metadata at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", + function, + file_offset, + file_offset ); + } +#endif + data = (uint8_t *) memory_allocate( + (size_t) metadata_size ); + + if( data == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create data.", + function ); + + goto on_error; + } + read_count = libbfio_handle_read_buffer_at_offset( + file_io_handle, + data, + (size_t) metadata_size, + file_offset, + error ); + + if( read_count != (ssize_t) metadata_size ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read metadata at offset: %" PRIi64 " (0x%08" PRIx64 ").", + function, + file_offset, + file_offset ); + + goto on_error; + } + if( libvslvm_metadata_read_data( + metadata, + data, + (size_t) metadata_size, + stored_checksum, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read metadata.", + function ); + + goto on_error; + } + memory_free( + data ); + + return( 1 ); + +on_error: + if( data != NULL ) + { + memory_free( + data ); + } + return( -1 ); +} + +/* Reads the volume group + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_volume_group( + libvslvm_metadata_t *metadata, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ) +{ + libvslvm_internal_volume_group_t *internal_volume_group = NULL; + char *line_string_segment = NULL; + char *value = NULL; + char *value_identifier = NULL; + static char *function = "libvslvm_metadata_read_volume_group"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + size_t value_identifier_length = 0; + size_t value_length = 0; + uint64_t value_64bit = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( metadata->volume_group != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid metadata - volume group value already set.", + function ); + + return( -1 ); + } + if( line_index == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function ); + + return( -1 ); + } + if( number_of_lines <= 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function ); + + return( -1 ); + } + if( ( *line_index < 0 ) + || ( *line_index >= number_of_lines ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function ); + + return( -1 ); + } + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( ( line_string_segment_size < 3 ) + || ( line_string_segment[ line_string_segment_size - 3 ] != ' ' ) + || ( line_string_segment[ line_string_segment_size - 2 ] != '{' ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported volume group signature.", + function ); + + goto on_error; + } + if( libvslvm_volume_group_initialize( + &( metadata->volume_group ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create volume group.", + function ); + + goto on_error; + } + internal_volume_group = (libvslvm_internal_volume_group_t *) metadata->volume_group; + + if( ( line_string_segment_size < 2 ) + || ( line_string_segment_index >= ( line_string_segment_size - 2 ) ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line string segment size value out of bounds.", + function ); + + goto on_error; + } + if( libvslvm_internal_volume_group_set_name( + (libvslvm_internal_volume_group_t *) metadata->volume_group, + &( line_string_segment[ line_string_segment_index ] ), + line_string_segment_size - ( line_string_segment_index + 2 ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set volume group name.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: name\t\t\t\t: %s\n", + function, + internal_volume_group->name ); + } +#endif + *line_index += 1; + + while( *line_index < number_of_lines ) + { + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if( ( ( line_string_segment_size - line_string_segment_index ) == 2 ) + && ( line_string_segment[ line_string_segment_index ] == '}' ) ) + { + *line_index += 1; + + break; + } + /* Check for the start of a sub section + */ + if( ( line_string_segment_size - line_string_segment_index ) == 18 ) + { + if( narrow_string_compare( + &( line_string_segment[ line_string_segment_index ] ), + "logical_volumes {", + 17 ) == 0 ) + { + if( libvslvm_metadata_read_logical_volumes( + metadata, + metadata->volume_group, + lines, + number_of_lines, + line_index, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read logical volumes.", + function ); + + goto on_error; + } + continue; + } + } + else if( ( line_string_segment_size - line_string_segment_index ) == 19 ) + { + if( narrow_string_compare( + &( line_string_segment[ line_string_segment_index ] ), + "physical_volumes {", + 18 ) == 0 ) + { + if( libvslvm_metadata_read_physical_volumes( + metadata, + metadata->volume_group, + lines, + number_of_lines, + line_index, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read physical volumes.", + function ); + + goto on_error; + } + continue; + } + } + /* Determine the value identifier + */ + value_identifier = &( line_string_segment[ line_string_segment_index ] ); + value_identifier_length = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] == '\t' ) + || ( line_string_segment[ line_string_segment_index ] == '\n' ) + || ( line_string_segment[ line_string_segment_index ] == '\f' ) + || ( line_string_segment[ line_string_segment_index ] == '\v' ) + || ( line_string_segment[ line_string_segment_index ] == '\r' ) + || ( line_string_segment[ line_string_segment_index ] == ' ' ) + || ( line_string_segment[ line_string_segment_index ] == '=' ) ) + { + break; + } + value_identifier_length++; + + line_string_segment_index++; + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[ line_string_segment_index ] = 0; + + line_string_segment_index++; + + /* Ignore whitespace + */ + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( line_string_segment[ line_string_segment_index ] == '=' ) + { + line_string_segment_index++; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Determine the value + */ + value = &( line_string_segment[ line_string_segment_index ] ); + value_length = line_string_segment_size - 1; + + /* Ingore quotes at the beginning of the value data + */ + if( ( line_string_segment[ line_string_segment_index ] == '"' ) + || ( line_string_segment[ line_string_segment_index ] == '\'' ) ) + { + line_string_segment_index++; + value++; + value_length--; + } + /* Ingore quotes at the end of the value data + */ + if( ( line_string_segment[ value_length - 1 ] == '"' ) + || ( line_string_segment[ value_length - 1 ] == '\'' ) ) + { + value_length--; + } + /* Make sure the value is terminated by an end of string + */ + line_string_segment[ value_length ] = 0; + + value_length -= line_string_segment_index; + + if( value_identifier_length == 2 ) + { + if( narrow_string_compare( + value_identifier, + "id", + 2 ) == 0 ) + { + if( libvslvm_volume_group_set_identifier( + metadata->volume_group, + value, + value_length + 1, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set volume group identifier.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: identifier\t\t\t\t: %s\n", + function, + internal_volume_group->identifier ); + } +#endif + } + } + else if( value_identifier_length == 5 ) + { + if( narrow_string_compare( + value_identifier, + "flags", + 5 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: flags\t\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + else if( narrow_string_compare( + value_identifier, + "seqno", + 5 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: sequence number\t\t\t: %s\n", + function, + value ); + } +#endif + if( libfvalue_utf8_string_copy_to_integer( + (uint8_t *) value, + value_length + 1, + &value_64bit, + 32, + LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to set sequence number.", + function ); + + goto on_error; + } + if( value_64bit > (uint64_t) UINT32_MAX ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid sequence number value exceeds maximum.", + function ); + + goto on_error; + } + internal_volume_group->sequence_number = (uint32_t) value_64bit; + } + } + else if( value_identifier_length == 6 ) + { + if( narrow_string_compare( + value_identifier, + "max_lv", + 6 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: max_lv\t\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + else if( narrow_string_compare( + value_identifier, + "max_pv", + 6 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: max_pv\t\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + else if( narrow_string_compare( + value_identifier, + "status", + 6 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: status flags\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + } + else if( value_identifier_length == 11 ) + { + if( narrow_string_compare( + value_identifier, + "extent_size", + 11 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: extent size\t\t\t: %s\n", + function, + value ); + } +#endif + if( libfvalue_utf8_string_copy_to_integer( + (uint8_t *) value, + value_length + 1, + &value_64bit, + 64, + LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to set extent size.", + function ); + + goto on_error; + } + if( value_64bit > (uint64_t) ( UINT64_MAX / 512 ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid extent size value exceeds maximum.", + function ); + + goto on_error; + } + value_64bit *= 512; + + internal_volume_group->extent_size = value_64bit; + } + } + else if( value_identifier_length == 15 ) + { + if( narrow_string_compare( + value_identifier, + "metadata_copies", + 15 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: metadata copies\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + } +#if defined( HAVE_DEBUG_OUTPUT ) + else if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: value: %d\t\t\t: %s = %s\n", + function, + *line_index, + value_identifier, + value ); + } +#endif + *line_index += 1; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "\n" ); + } +#endif + return( 1 ); + +on_error: + if( metadata->volume_group != NULL ) + { + libvslvm_internal_volume_group_free( + (libvslvm_internal_volume_group_t **) &( metadata->volume_group ), + NULL ); + } + return( -1 ); +} + +/* Reads the physical volumes + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_physical_volumes( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ) +{ + char *line_string_segment = NULL; + static char *function = "libvslvm_metadata_read_physical_volumes"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( line_index == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function ); + + return( -1 ); + } + if( number_of_lines <= 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function ); + + return( -1 ); + } + if( ( *line_index < 0 ) + || ( *line_index >= number_of_lines ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function ); + + return( -1 ); + } + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + return( -1 ); + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + return( -1 ); + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( ( ( line_string_segment_size - line_string_segment_index ) != 19 ) + || ( narrow_string_compare( + &( line_string_segment[ line_string_segment_index ] ), + "physical_volumes {", + 18 ) != 0 ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported physical volumes signature.", + function ); + + return( -1 ); + } + *line_index += 1; + + while( *line_index < number_of_lines ) + { + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + return( -1 ); + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + return( -1 ); + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if( ( ( line_string_segment_size - line_string_segment_index ) == 2 ) + && ( line_string_segment[ line_string_segment_index ] == '}' ) ) + { + *line_index += 1; + + break; + } + /* Check for the start of a sub section + */ + if( ( line_string_segment_size >= 3 ) + && ( line_string_segment[ line_string_segment_size - 3 ] == ' ' ) + && ( line_string_segment[ line_string_segment_size - 2 ] == '{' ) ) + { + if( libvslvm_metadata_read_physical_volume( + metadata, + volume_group, + lines, + number_of_lines, + line_index, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read physical volume.", + function ); + + return( -1 ); + } + } + else + { +/* TODO debug print other lines ? */ + *line_index += 1; + } + } + return( 1 ); +} + +/* Reads the physical volume + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_physical_volume( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ) +{ + libvslvm_physical_volume_t *physical_volume = NULL; + char *line_string_segment = NULL; + char *value = NULL; + char *value_identifier = NULL; + static char *function = "libvslvm_metadata_read_physical_volume"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + size_t value_identifier_length = 0; + size_t value_length = 0; + uint64_t value_64bit = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( volume_group == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid volume group.", + function ); + + return( -1 ); + } + if( line_index == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function ); + + return( -1 ); + } + if( number_of_lines <= 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function ); + + return( -1 ); + } + if( ( *line_index < 0 ) + || ( *line_index >= number_of_lines ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function ); + + return( -1 ); + } + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( ( line_string_segment_size < 3 ) + || ( line_string_segment[ line_string_segment_size - 3 ] != ' ' ) + || ( line_string_segment[ line_string_segment_size - 2 ] != '{' ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported physical volume signature.", + function ); + + goto on_error; + } + if( libvslvm_physical_volume_initialize( + &physical_volume, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create physical volume.", + function ); + + goto on_error; + } + if( ( line_string_segment_size < 2 ) + || ( line_string_segment_index >= ( line_string_segment_size - 2 ) ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line string segment size value out of bounds.", + function ); + + goto on_error; + } + if( libvslvm_physical_volume_set_name( + physical_volume, + &( line_string_segment[ line_string_segment_index ] ), + line_string_segment_size - ( line_string_segment_index + 2 ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set physical volume name.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "\n" ); + + libcnotify_printf( + "%s: name\t\t\t\t: %s\n", + function, + ( (libvslvm_internal_physical_volume_t *) physical_volume )->name ); + } +#endif + *line_index += 1; + + while( *line_index < number_of_lines ) + { + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if( ( ( line_string_segment_size - line_string_segment_index ) == 2 ) + && ( line_string_segment[ line_string_segment_index ] == '}' ) ) + { + *line_index += 1; + + break; + } + /* Determine the value identifier + */ + value_identifier = &( line_string_segment[ line_string_segment_index ] ); + value_identifier_length = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] == '\t' ) + || ( line_string_segment[ line_string_segment_index ] == '\n' ) + || ( line_string_segment[ line_string_segment_index ] == '\f' ) + || ( line_string_segment[ line_string_segment_index ] == '\v' ) + || ( line_string_segment[ line_string_segment_index ] == '\r' ) + || ( line_string_segment[ line_string_segment_index ] == ' ' ) + || ( line_string_segment[ line_string_segment_index ] == '=' ) ) + { + break; + } + value_identifier_length++; + + line_string_segment_index++; + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[ line_string_segment_index ] = 0; + + line_string_segment_index++; + + /* Ignore whitespace + */ + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( line_string_segment[ line_string_segment_index ] == '=' ) + { + line_string_segment_index++; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Determine the value + */ + value = &( line_string_segment[ line_string_segment_index ] ); + value_length = line_string_segment_size - 1; + + /* Ingore quotes at the beginning of the value data + */ + if( ( line_string_segment[ line_string_segment_index ] == '"' ) + || ( line_string_segment[ line_string_segment_index ] == '\'' ) ) + { + line_string_segment_index++; + value++; + value_length--; + } + /* Ingore quotes at the end of the value data + */ + if( ( line_string_segment[ value_length - 1 ] == '"' ) + || ( line_string_segment[ value_length - 1 ] == '\'' ) ) + { + value_length--; + } + /* Make sure the value is terminated by an end of string + */ + line_string_segment[ value_length ] = 0; + + value_length -= line_string_segment_index; + + if( value_identifier_length == 2 ) + { + if( narrow_string_compare( + value_identifier, + "id", + 2 ) == 0 ) + { + if( libvslvm_physical_volume_set_identifier( + physical_volume, + value, + value_length + 1, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set physical volume identifier.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: identifier\t\t\t: %s\n", + function, + ( (libvslvm_internal_physical_volume_t *) physical_volume )->identifier ); + } +#endif + } + } + else if( value_identifier_length == 5 ) + { + if( narrow_string_compare( + value_identifier, + "flags", + 5 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: flags\t\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + } + else if( value_identifier_length == 6 ) + { + if( narrow_string_compare( + value_identifier, + "device", + 6 ) == 0 ) + { + if( libvslvm_physical_volume_set_device_path( + physical_volume, + value, + value_length + 1, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set physical volume device path.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: device path\t\t\t: %s\n", + function, + ( (libvslvm_internal_physical_volume_t *) physical_volume )->device_path ); + } +#endif + } + else if( narrow_string_compare( + value_identifier, + "status", + 6 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: status flags\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + + } + else if( value_identifier_length == 8 ) + { + if( narrow_string_compare( + value_identifier, + "dev_size", + 8 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: volume size\t\t\t: %s\n", + function, + value ); + } +#endif + if( libfvalue_utf8_string_copy_to_integer( + (uint8_t *) value, + value_length + 1, + &value_64bit, + 64, + LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to set volume size.", + function ); + + goto on_error; + } + if( value_64bit > (uint64_t) ( UINT64_MAX / 512 ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid volume size value exceeds maximum.", + function ); + + goto on_error; + } + value_64bit *= 512; + + ( (libvslvm_internal_physical_volume_t *) physical_volume )->size = value_64bit; + } + else if( narrow_string_compare( + value_identifier, + "pe_count", + 8 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: pe_count\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + else if( narrow_string_compare( + value_identifier, + "pe_start", + 8 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: pe_start\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + } +#if defined( HAVE_DEBUG_OUTPUT ) + else if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: value: %d\t\t\t: %s = %s\n", + function, + *line_index, + value_identifier, + value ); + } +#endif + *line_index += 1; + } + if( libvslvm_volume_group_append_physical_volume( + volume_group, + physical_volume, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append physical volume to volume group.", + function ); + + goto on_error; + } + physical_volume = NULL; + + return( 1 ); + +on_error: + if( physical_volume != NULL ) + { + libvslvm_internal_physical_volume_free( + (libvslvm_internal_physical_volume_t **) &physical_volume, + NULL ); + } + return( -1 ); +} + +/* Reads the logical volumes + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_logical_volumes( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ) +{ + char *line_string_segment = NULL; + static char *function = "libvslvm_metadata_read_logical_volumes"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( line_index == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function ); + + return( -1 ); + } + if( number_of_lines <= 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function ); + + return( -1 ); + } + if( ( *line_index < 0 ) + || ( *line_index >= number_of_lines ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function ); + + return( -1 ); + } + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + return( -1 ); + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + return( -1 ); + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( ( ( line_string_segment_size - line_string_segment_index ) != 18 ) + || ( narrow_string_compare( + &( line_string_segment[ line_string_segment_index ] ), + "logical_volumes {", + 17 ) != 0 ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported logical volumes signature.", + function ); + + return( -1 ); + } + *line_index += 1; + + while( *line_index < number_of_lines ) + { + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + return( -1 ); + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + return( -1 ); + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if( ( ( line_string_segment_size - line_string_segment_index ) == 2 ) + && ( line_string_segment[ line_string_segment_index ] == '}' ) ) + { + *line_index += 1; + + break; + } + /* Check for the start of a sub section + */ + if( ( line_string_segment_size >= 3 ) + && ( line_string_segment[ line_string_segment_size - 3 ] == ' ' ) + && ( line_string_segment[ line_string_segment_size - 2 ] == '{' ) ) + { + if( libvslvm_metadata_read_logical_volume( + metadata, + volume_group, + lines, + number_of_lines, + line_index, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read logical volume.", + function ); + + return( -1 ); + } + } + else + { +/* TODO debug print other lines ? */ + *line_index += 1; + } + } + return( 1 ); +} + +/* Reads the logical volume + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_logical_volume( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ) +{ + libvslvm_logical_volume_values_t *logical_volume_values = NULL; + char *line_string_segment = NULL; + char *value = NULL; + char *value_identifier = NULL; + static char *function = "libvslvm_metadata_read_logical_volume"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + size_t value_identifier_length = 0; + size_t value_length = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( volume_group == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid volume group.", + function ); + + return( -1 ); + } + if( line_index == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function ); + + return( -1 ); + } + if( number_of_lines <= 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function ); + + return( -1 ); + } + if( ( *line_index < 0 ) + || ( *line_index >= number_of_lines ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function ); + + return( -1 ); + } + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( ( line_string_segment_size < 3 ) + || ( line_string_segment[ line_string_segment_size - 3 ] != ' ' ) + || ( line_string_segment[ line_string_segment_size - 2 ] != '{' ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported logical volume signature.", + function ); + + goto on_error; + } + if( libvslvm_logical_volume_values_initialize( + &logical_volume_values, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create logical volume values.", + function ); + + goto on_error; + } + if( ( line_string_segment_size < 2 ) + || ( line_string_segment_index >= ( line_string_segment_size - 2 ) ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line string segment size value out of bounds.", + function ); + + goto on_error; + } + if( libvslvm_logical_volume_values_set_name( + logical_volume_values, + &( line_string_segment[ line_string_segment_index ] ), + line_string_segment_size - ( line_string_segment_index + 2 ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set logical volume name.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "\n" ); + + libcnotify_printf( + "%s: name\t\t\t\t: %s\n", + function, + logical_volume_values->name ); + } +#endif + *line_index += 1; + + while( *line_index < number_of_lines ) + { + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if( ( ( line_string_segment_size - line_string_segment_index ) == 2 ) + && ( line_string_segment[ line_string_segment_index ] == '}' ) ) + { + *line_index += 1; + + break; + } + /* Check for the start of a sub section + */ + if( ( line_string_segment_size >= 3 ) + && ( line_string_segment[ line_string_segment_size - 3 ] == ' ' ) + && ( line_string_segment[ line_string_segment_size - 2 ] == '{' ) + && ( ( line_string_segment_size - line_string_segment_index ) >= 7 ) + && ( narrow_string_compare( + &( line_string_segment[ line_string_segment_index ] ), + "segment", + 7 ) == 0 ) ) + { + if( libvslvm_metadata_read_segment( + metadata, + logical_volume_values, + lines, + number_of_lines, + line_index, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read segment.", + function ); + + goto on_error; + } + continue; + } + /* Determine the value identifier + */ + value_identifier = &( line_string_segment[ line_string_segment_index ] ); + value_identifier_length = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] == '\t' ) + || ( line_string_segment[ line_string_segment_index ] == '\n' ) + || ( line_string_segment[ line_string_segment_index ] == '\f' ) + || ( line_string_segment[ line_string_segment_index ] == '\v' ) + || ( line_string_segment[ line_string_segment_index ] == '\r' ) + || ( line_string_segment[ line_string_segment_index ] == ' ' ) + || ( line_string_segment[ line_string_segment_index ] == '=' ) ) + { + break; + } + value_identifier_length++; + + line_string_segment_index++; + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[ line_string_segment_index ] = 0; + + line_string_segment_index++; + + /* Ignore whitespace + */ + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( line_string_segment[ line_string_segment_index ] == '=' ) + { + line_string_segment_index++; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Determine the value + */ + value = &( line_string_segment[ line_string_segment_index ] ); + value_length = line_string_segment_size - 1; + + /* Ingore quotes at the beginning of the value data + */ + if( ( line_string_segment[ line_string_segment_index ] == '"' ) + || ( line_string_segment[ line_string_segment_index ] == '\'' ) ) + { + line_string_segment_index++; + value++; + value_length--; + } + /* Ingore quotes at the end of the value data + */ + if( ( line_string_segment[ value_length - 1 ] == '"' ) + || ( line_string_segment[ value_length - 1 ] == '\'' ) ) + { + value_length--; + } + /* Make sure the value is terminated by an end of string + */ + line_string_segment[ value_length ] = 0; + + value_length -= line_string_segment_index; + + if( value_identifier_length == 2 ) + { + if( narrow_string_compare( + value_identifier, + "id", + 2 ) == 0 ) + { + if( libvslvm_logical_volume_values_set_identifier( + logical_volume_values, + value, + value_length + 1, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set logical volume identifier.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: identifier\t\t\t: %s\n", + function, + logical_volume_values->identifier ); + } +#endif + } + } + else if( value_identifier_length == 5 ) + { + if( narrow_string_compare( + value_identifier, + "flags", + 5 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: flags\t\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + } + else if( value_identifier_length == 6 ) + { + if( narrow_string_compare( + value_identifier, + "status", + 6 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: status flags\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + + } + else if( value_identifier_length == 13 ) + { + if( narrow_string_compare( + value_identifier, + "segment_count", + 13 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: number of segments\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + + } +#if defined( HAVE_DEBUG_OUTPUT ) + else if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: value: %d\t\t\t: %s = %s\n", + function, + *line_index, + value_identifier, + value ); + } +#endif + *line_index += 1; + } + if( libvslvm_volume_group_append_logical_volume( + volume_group, + logical_volume_values, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append logical volume to volume group.", + function ); + + goto on_error; + } + logical_volume_values = NULL; + + return( 1 ); + +on_error: + if( logical_volume_values != NULL ) + { + libvslvm_logical_volume_values_free( + &logical_volume_values, + NULL ); + } + return( -1 ); +} + +/* Reads the segment + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_segment( + libvslvm_metadata_t *metadata, + libvslvm_logical_volume_values_t *logical_volume_values, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ) +{ + libvslvm_internal_volume_group_t *internal_volume_group = NULL; + libvslvm_segment_t *segment = NULL; + char *line_string_segment = NULL; + char *value = NULL; + char *value_identifier = NULL; + static char *function = "libvslvm_metadata_read_segment"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + size_t value_identifier_length = 0; + size_t value_length = 0; + uint64_t value_64bit = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( metadata->volume_group == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: invalid metadata - missing volume group.", + function ); + + return( -1 ); + } + internal_volume_group = (libvslvm_internal_volume_group_t *) metadata->volume_group; + + if( internal_volume_group->extent_size == 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid volume group - extent size value out of bounds.", + function ); + + return( -1 ); + } + if( logical_volume_values == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid logical volume values.", + function ); + + return( -1 ); + } + if( line_index == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function ); + + return( -1 ); + } + if( number_of_lines <= 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function ); + + return( -1 ); + } + if( ( *line_index < 0 ) + || ( *line_index >= number_of_lines ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function ); + + return( -1 ); + } + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( ( line_string_segment_size < ( 7 + 3 ) ) + || ( line_string_segment[ line_string_segment_size - 3 ] != ' ' ) + || ( line_string_segment[ line_string_segment_size - 2 ] != '{' ) + || ( narrow_string_compare( + &( line_string_segment[ line_string_segment_index ] ), + "segment", + 7 ) != 0 ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported segment signature.", + function ); + + goto on_error; + } + if( libvslvm_segment_initialize( + &segment, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create segment.", + function ); + + goto on_error; + } + if( ( line_string_segment_size < 2 ) + || ( line_string_segment_index >= ( line_string_segment_size - 2 ) ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line string segment size value out of bounds.", + function ); + + goto on_error; + } + if( libvslvm_internal_segment_set_name( + (libvslvm_internal_segment_t *) segment, + &( line_string_segment[ line_string_segment_index ] ), + line_string_segment_size - ( line_string_segment_index + 2 ), + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set segment name.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "\n" ); + + libcnotify_printf( + "%s: name\t\t\t\t\t: %s\n", + function, + ( (libvslvm_internal_segment_t *) segment )->name ); + } +#endif + *line_index += 1; + + while( *line_index < number_of_lines ) + { + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if( ( ( line_string_segment_size - line_string_segment_index ) == 2 ) + && ( line_string_segment[ line_string_segment_index ] == '}' ) ) + { + *line_index += 1; + + break; + } + /* Determine the value identifier + */ + value_identifier = &( line_string_segment[ line_string_segment_index ] ); + value_identifier_length = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] == '\t' ) + || ( line_string_segment[ line_string_segment_index ] == '\n' ) + || ( line_string_segment[ line_string_segment_index ] == '\f' ) + || ( line_string_segment[ line_string_segment_index ] == '\v' ) + || ( line_string_segment[ line_string_segment_index ] == '\r' ) + || ( line_string_segment[ line_string_segment_index ] == ' ' ) + || ( line_string_segment[ line_string_segment_index ] == '=' ) ) + { + break; + } + value_identifier_length++; + + line_string_segment_index++; + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[ line_string_segment_index ] = 0; + + line_string_segment_index++; + + /* Ignore whitespace + */ + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( line_string_segment[ line_string_segment_index ] == '=' ) + { + line_string_segment_index++; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Ingore quotes at the beginning of the value data + */ + if( ( line_string_segment[ line_string_segment_index ] == '"' ) + || ( line_string_segment[ line_string_segment_index ] == '\'' ) ) + { + line_string_segment_index++; + } + /* Determine the value + */ + value = &( line_string_segment[ line_string_segment_index ] ); + value_length = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] == 0 ) + || ( line_string_segment[ line_string_segment_index ] == '\t' ) + || ( line_string_segment[ line_string_segment_index ] == '\n' ) + || ( line_string_segment[ line_string_segment_index ] == '\f' ) + || ( line_string_segment[ line_string_segment_index ] == '\v' ) + || ( line_string_segment[ line_string_segment_index ] == '\r' ) + || ( line_string_segment[ line_string_segment_index ] == '#' ) ) + { + break; + } + line_string_segment_index++; + value_length++; + } + /* Ingore quotes at the end of the value data + */ + if( ( line_string_segment[ line_string_segment_index - 1 ] == '"' ) + || ( line_string_segment[ line_string_segment_index - 1 ] == '\'' ) ) + { + line_string_segment_index--; + value_length--; + } + /* Make sure the value is terminated by an end of string + */ + line_string_segment[ line_string_segment_index ] = 0; + + if( value_identifier_length == 4 ) + { + if( narrow_string_compare( + value_identifier, + "type", + 4 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: type\t\t\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + /*++ liubo 20190306 raid lvm*/ + uint32_t type = 0; + if (narrow_string_compare(value, STRIPED, value_length) == 0) + { + type = LVM_LV_TYPE_JBOD; + } + else if (narrow_string_compare(value, RAID1, value_length) == 0) + { + type = LVM_LV_TYPE_RAID1; + } + else if (narrow_string_compare(value, RAID4, value_length) == 0) + { + type = LVM_LV_TYPE_RAID4; + } + else if (narrow_string_compare(value, RAID5, value_length) == 0) + { + type = LVM_LV_TYPE_RAID5_LS; + } + else if (narrow_string_compare(value, RAID5_LA, value_length) == 0) + { + type = LVM_LV_TYPE_RAID5_LA; + } + else if (narrow_string_compare(value, RAID5_RA, value_length) == 0) + { + type = LVM_LV_TYPE_RAID5_RA; + } + else if (narrow_string_compare(value, RAID5_LS, value_length) == 0) + { + type = LVM_LV_TYPE_RAID5_LS; + } + else if (narrow_string_compare(value, RAID5_RS, value_length) == 0) + { + type = LVM_LV_TYPE_RAID5_RS; + } + else if (narrow_string_compare(value, RAID6, value_length) == 0) + { + type = LVM_LV_TYPE_RAID6_ZR; + } + else if (narrow_string_compare(value, RAID6_ZR, value_length) == 0) + { + type = LVM_LV_TYPE_RAID6_ZR; + } + else if (narrow_string_compare(value, RAID6_NR, value_length) == 0) + { + type = LVM_LV_TYPE_RAID6_NR; + } + else if (narrow_string_compare(value, RAID6_NC, value_length) == 0) + { + type = LVM_LV_TYPE_RAID6_NC; + } + else if (narrow_string_compare(value, RAID10, value_length) == 0) + { + type = LVM_LV_TYPE_RAID10; + } + else + { + type = LVM_LV_TYPE_UNKNOWN; + } + + ((libvslvm_internal_segment_t *)segment)->type = type; + + /*-- liubo 20190306 raid lvm*/ + } + } + else if( value_identifier_length == 7 ) + { + if( narrow_string_compare( + value_identifier, + "stripes", + 7 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: stripes list:\n", + function ); + } +#endif + if( ( value_length != 1 ) + || ( value[ 0 ] != '[' ) + || ( libvslvm_metadata_read_stripes_list( + metadata, + segment, + lines, + number_of_lines, + line_index, + error ) != 1 ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read stripes list.", + function ); + + goto on_error; + } +/* TODO validate number of stripes */ + } + } + else if( value_identifier_length == 12 ) + { + if( narrow_string_compare( + value_identifier, + "extent_count", + 12 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: number of extents\t\t\t: %s\n", + function, + value ); + } +#endif + if( libfvalue_utf8_string_copy_to_integer( + (uint8_t *) value, + value_length + 1, + &value_64bit, + 64, + LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to set number of extents.", + function ); + + goto on_error; + } + if( value_64bit > (uint64_t) ( UINT64_MAX / internal_volume_group->extent_size ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid number of extents value exceeds maximum.", + function ); + + goto on_error; + } + value_64bit *= internal_volume_group->extent_size; + + ( (libvslvm_internal_segment_t *) segment )->size = value_64bit; + } + else if( narrow_string_compare( + value_identifier, + "start_extent", + 12 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: start extent\t\t\t\t: %s\n", + function, + value ); + } +#endif + if( libfvalue_utf8_string_copy_to_integer( + (uint8_t *) value, + value_length + 1, + &value_64bit, + 64, + LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to set start extent.", + function ); + + goto on_error; + } + if( value_64bit > (uint64_t) ( UINT64_MAX / internal_volume_group->extent_size ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid start extent value exceeds maximum.", + function ); + + goto on_error; + } + value_64bit *= internal_volume_group->extent_size; + + ( (libvslvm_internal_segment_t *) segment )->offset = value_64bit; + } + else if( narrow_string_compare( + value_identifier, + "stripe_count", + 12 ) == 0 ) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: number of stripes\t\t\t: %s\n", + function, + value ); + } +#endif +/* TODO */ + } + } + /*20190306 Lliubo raid lvm + */ + else if (value_identifier_length == 11) + { + if (narrow_string_compare( + value_identifier, + "stripe_size", + 11) == 0) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if (libcnotify_verbose != 0) + { + libcnotify_printf( + "%s: stripe_size\t\t\t: %s\n", + function, + value); + } +#endif + if (libfvalue_utf8_string_copy_to_integer( + (uint8_t *)value, + value_length + 1, + &value_64bit, + 64, + LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to set stripe_size.", + function); + + goto on_error; + } + ((libvslvm_internal_segment_t *)segment)->stripe_size = value_64bit; + } + } + /*20190306 Lliubo raid lvm + */ + else if (value_identifier_length == 5) + { + if (narrow_string_compare( + value_identifier, + "raids", + 5) == 0) + { +#if defined( HAVE_DEBUG_OUTPUT ) + if (libcnotify_verbose != 0) + { + libcnotify_printf( + "%s: raids list:\n", + function); + } +#endif + if ((value_length != 1) + || (value[0] != '[') + || (libvslvm_metadata_read_raids_list( + metadata, + segment, + lines, + number_of_lines, + line_index, + error) != 1)) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read stripes list.", + function); + + return(-1); + } + /* TODO validate number of stripes */ + } + } +#if defined( HAVE_DEBUG_OUTPUT ) + else if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: value: %d\t\t\t\t: %s = %s\n", + function, + *line_index, + value_identifier, + value ); + } +#endif + *line_index += 1; + } + if( libvslvm_logical_volume_values_append_segment( + logical_volume_values, + segment, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append segment to logical volume values.", + function ); + + goto on_error; + } + segment = NULL; + + return( 1 ); + +on_error: + if( segment != NULL ) + { + libvslvm_internal_segment_free( + (libvslvm_internal_segment_t **) &segment, + NULL ); + } + return( -1 ); +} + +/* Reads the stripes list + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_stripes_list( + libvslvm_metadata_t *metadata, + libvslvm_segment_t *segment, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ) +{ + libvslvm_internal_volume_group_t *internal_volume_group = NULL; + libvslvm_stripe_t *stripe = NULL; + char *line_string_segment = NULL; + char *value = NULL; + char *value_identifier = NULL; + static char *function = "libvslvm_metadata_read_stripes_list"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + size_t value_identifier_length = 0; + size_t value_length = 0; + uint64_t value_64bit = 0; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( metadata->volume_group == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: invalid metadata - missing volume group.", + function ); + + return( -1 ); + } + internal_volume_group = (libvslvm_internal_volume_group_t *) metadata->volume_group; + + if( internal_volume_group->extent_size == 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid volume group - extent size value out of bounds.", + function ); + + return( -1 ); + } + if( line_index == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function ); + + return( -1 ); + } + if( number_of_lines <= 0 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function ); + + return( -1 ); + } + if( ( *line_index < 0 ) + || ( *line_index >= number_of_lines ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function ); + + return( -1 ); + } + *line_index += 1; + + while( *line_index < number_of_lines ) + { + if( libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index ); + + goto on_error; + } + if( line_string_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index ); + + goto on_error; + } + /* Ignore trailing white space + */ + if( line_string_segment_size >= 2 ) + { + line_string_segment_index = line_string_segment_size - 2; + + while( line_string_segment_index > 0 ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if( ( ( line_string_segment_size - line_string_segment_index ) == 2 ) + && ( line_string_segment[ line_string_segment_index ] == ']' ) ) + { + break; + } + /* Ingore quotes at the beginning of the value data + */ + if( ( line_string_segment[ line_string_segment_index ] == '"' ) + || ( line_string_segment[ line_string_segment_index ] == '\'' ) ) + { + line_string_segment_index++; + } + /* Determine the value identifier + */ + value_identifier = &( line_string_segment[ line_string_segment_index ] ); + value_identifier_length = 0; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] == '\t' ) + || ( line_string_segment[ line_string_segment_index ] == '\n' ) + || ( line_string_segment[ line_string_segment_index ] == '\f' ) + || ( line_string_segment[ line_string_segment_index ] == '\v' ) + || ( line_string_segment[ line_string_segment_index ] == '\r' ) + || ( line_string_segment[ line_string_segment_index ] == ' ' ) + || ( line_string_segment[ line_string_segment_index ] == ',' ) ) + { + break; + } + value_identifier_length++; + + line_string_segment_index++; + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Ingore quotes at the end of the value identifier + */ + if( ( line_string_segment[ line_string_segment_index - 1 ] == '"' ) + || ( line_string_segment[ line_string_segment_index - 1 ] == '\'' ) ) + { + value_identifier_length--; + + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[ line_string_segment_index - 1 ] = 0; + } + else + { + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[ line_string_segment_index ] = 0; + } + line_string_segment_index++; + + /* Ignore whitespace + */ + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + if( line_string_segment[ line_string_segment_index ] == ',' ) + { + line_string_segment_index++; + + while( line_string_segment_index < line_string_segment_size ) + { + if( ( line_string_segment[ line_string_segment_index ] != '\t' ) + && ( line_string_segment[ line_string_segment_index ] != '\n' ) + && ( line_string_segment[ line_string_segment_index ] != '\f' ) + && ( line_string_segment[ line_string_segment_index ] != '\v' ) + && ( line_string_segment[ line_string_segment_index ] != '\r' ) + && ( line_string_segment[ line_string_segment_index ] != ' ' ) ) + { + break; + } + line_string_segment_index++; + } + } + /* Skip a line not containing a value + */ + if( ( line_string_segment_index >= line_string_segment_size ) + || ( line_string_segment[ line_string_segment_index ] == 0 ) ) + { + *line_index += 1; + + continue; + } + /* Determine the value + */ + value = &( line_string_segment[ line_string_segment_index ] ); + value_length = line_string_segment_size - 1; + + /* Make sure the value is terminated by an end of string + */ + line_string_segment[ value_length ] = 0; + + value_length -= line_string_segment_index; + +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: value: %d\t\t\t\t: %s, %s\n", + function, + *line_index, + value_identifier, + value ); + } +#endif + *line_index += 1; + + if( libfvalue_utf8_string_copy_to_integer( + (uint8_t *) value, + value_length + 1, + &value_64bit, + 64, + LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to set data area offset.", + function ); + + goto on_error; + } + if( value_64bit > (uint64_t) ( UINT64_MAX / internal_volume_group->extent_size ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid data area offset value exceeds maximum.", + function ); + + goto on_error; + } + value_64bit *= internal_volume_group->extent_size; + + if( libvslvm_stripe_initialize( + &stripe, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create stripe.", + function ); + + goto on_error; + } + if( libvslvm_internal_stripe_set_physical_volume_name( + (libvslvm_internal_stripe_t *) stripe, + value_identifier, + value_identifier_length + 1, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set physical volume name.", + function ); + + goto on_error; + } + if( libvslvm_stripe_set_data_area_offset( + stripe, + value_64bit, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set data area offset.", + function ); + + goto on_error; + } + if( libvslvm_segment_append_stripe( + segment, + stripe, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append stripe to segment.", + function ); + + goto on_error; + } + stripe = NULL; + } + return( 1 ); + +on_error: + if( stripe != NULL ) + { + libvslvm_internal_stripe_free( + (libvslvm_internal_stripe_t **) &stripe, + NULL ); + } + return( -1 ); +} + +/* Retrieves the volume group + * Returns 1 if successful, 0 if not available or -1 on error + */ +int libvslvm_metadata_get_volume_group( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t **volume_group, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_metadata_get_volume_group"; + + if( metadata == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function ); + + return( -1 ); + } + if( volume_group == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid volume group.", + function ); + + return( -1 ); + } + if( *volume_group != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid volume group value already set.", + function ); + + return( -1 ); + } + if( metadata->volume_group == NULL ) + { + return( 0 ); + } + *volume_group = metadata->volume_group; + + return( 1 ); +} + + + +/* Reads the raids list + * Returns the 1 if succesful or -1 on error + */ +int libvslvm_metadata_read_raids_list( + libvslvm_metadata_t *metadata, + libvslvm_segment_t *segment, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error) +{ + libvslvm_internal_volume_group_t *internal_volume_group = NULL; + libvslvm_raid_t *raid = NULL; + char *line_string_segment = NULL; + char *image_name = NULL; // image_name + char *meta_name = NULL; // meta name + static char *function = "libvslvm_metadata_read_raids_list"; + size_t line_string_segment_index = 0; + size_t line_string_segment_size = 0; + size_t meta_length = 0; // meta size + size_t image_length = 0; // image size + + if (metadata == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid metadata.", + function); + + return(-1); + } + if (metadata->volume_group == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: invalid metadata - missing volume group.", + function); + + goto on_error; + } + internal_volume_group = (libvslvm_internal_volume_group_t *)metadata->volume_group; + + if (line_index == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid line index.", + function); + + return(-1); + } + if (number_of_lines <= 0) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid number of lines value out of bounds.", + function); + + return(-1); + } + if ((*line_index < 0) + || (*line_index >= number_of_lines)) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid line index value out of bounds.", + function); + + return(-1); + } + *line_index += 1; + + while (*line_index < number_of_lines) + { + if (libcsplit_narrow_split_string_get_segment_by_index( + lines, + *line_index, + &line_string_segment, + &line_string_segment_size, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve line: %d.", + function, + *line_index); + + goto on_error; + } + if (line_string_segment == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing line string segment: %d.", + function, + *line_index); + + goto on_error; + } + /* Ignore trailing white space + */ + line_string_segment_index = line_string_segment_size - 2; + + while (line_string_segment_index > 0) + { + if ((line_string_segment[line_string_segment_index] != '\t') + && (line_string_segment[line_string_segment_index] != '\n') + && (line_string_segment[line_string_segment_index] != '\f') + && (line_string_segment[line_string_segment_index] != '\v') + && (line_string_segment[line_string_segment_index] != '\r') + && (line_string_segment[line_string_segment_index] != ' ')) + { + break; + } + line_string_segment_index--; + line_string_segment_size--; + } + /* Ignore leading white space + */ + line_string_segment_index = 0; + + while (line_string_segment_index < line_string_segment_size) + { + if ((line_string_segment[line_string_segment_index] != '\t') + && (line_string_segment[line_string_segment_index] != '\n') + && (line_string_segment[line_string_segment_index] != '\f') + && (line_string_segment[line_string_segment_index] != '\v') + && (line_string_segment[line_string_segment_index] != '\r') + && (line_string_segment[line_string_segment_index] != ' ')) + { + break; + } + line_string_segment_index++; + } + /* Skip an empty line + */ + if ((line_string_segment_index >= line_string_segment_size) + || (line_string_segment[line_string_segment_index] == 0)) + { + *line_index += 1; + + continue; + } + /* Check for the end of section + */ + if (((line_string_segment_size - line_string_segment_index) == 2) + && (line_string_segment[line_string_segment_index] == ']')) + { + break; + } + /* Ingore quotes at the beginning of the value data + */ + if ((line_string_segment[line_string_segment_index] == '"') + || (line_string_segment[line_string_segment_index] == '\'')) + { + line_string_segment_index++; + } + /* Determine the value identifier + */ + meta_name = &(line_string_segment[line_string_segment_index]); + meta_length = 0; + + while (line_string_segment_index < line_string_segment_size) + { + if ((line_string_segment[line_string_segment_index] == '\t') + || (line_string_segment[line_string_segment_index] == '\n') + || (line_string_segment[line_string_segment_index] == '\f') + || (line_string_segment[line_string_segment_index] == '\v') + || (line_string_segment[line_string_segment_index] == '\r') + || (line_string_segment[line_string_segment_index] == ' ') + || (line_string_segment[line_string_segment_index] == ',')) + { + break; + } + meta_length++; + + line_string_segment_index++; + } + /* Skip a line not containing a value + */ + if ((line_string_segment_index >= line_string_segment_size) + || (line_string_segment[line_string_segment_index] == 0)) + { + *line_index += 1; + + continue; + } + /* Ingore quotes at the end of the value identifier + */ + if ((line_string_segment[line_string_segment_index - 1] == '"') + || (line_string_segment[line_string_segment_index - 1] == '\'')) + { + meta_length--; + + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[line_string_segment_index - 1] = 0; + } + else + { + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[line_string_segment_index] = 0; + } + // line_string_segment_index++; + + /* Ignore whitespace + */ + while (line_string_segment_index < line_string_segment_size) + { + if ((line_string_segment[line_string_segment_index] != '\t') + && (line_string_segment[line_string_segment_index] != '\n') + && (line_string_segment[line_string_segment_index] != '\f') + && (line_string_segment[line_string_segment_index] != '\v') + && (line_string_segment[line_string_segment_index] != '\r') + && (line_string_segment[line_string_segment_index] != ' ')) + { + break; + } + line_string_segment_index++; + } + if (line_string_segment[line_string_segment_index] == ',') + { + line_string_segment_index++; + + while (line_string_segment_index < line_string_segment_size) + { + if ((line_string_segment[line_string_segment_index] != '\t') + && (line_string_segment[line_string_segment_index] != '\n') + && (line_string_segment[line_string_segment_index] != '\f') + && (line_string_segment[line_string_segment_index] != '\v') + && (line_string_segment[line_string_segment_index] != '\r') + && (line_string_segment[line_string_segment_index] != ' ')) + { + break; + } + line_string_segment_index++; + } + } + /* Skip a line not containing a value + */ + if ((line_string_segment_index >= line_string_segment_size) + || (line_string_segment[line_string_segment_index] == 0)) + { + *line_index += 1; + continue; + } + + if ((line_string_segment[line_string_segment_index] == '"') + || (line_string_segment[line_string_segment_index] == '\'')) + { + line_string_segment_index++; + } + + /* Determine the value + */ + image_name = &(line_string_segment[line_string_segment_index]); + image_length = 0; + + while (line_string_segment_index < line_string_segment_size) + { + if ((line_string_segment[line_string_segment_index] == '\t') + || (line_string_segment[line_string_segment_index] == '\n') + || (line_string_segment[line_string_segment_index] == '\f') + || (line_string_segment[line_string_segment_index] == '\v') + || (line_string_segment[line_string_segment_index] == '\r') + || (line_string_segment[line_string_segment_index] == ' ') + || (line_string_segment[line_string_segment_index] == ',') + || (line_string_segment[line_string_segment_index] == '\0') ) + { + break; + } + image_length++; + + line_string_segment_index++; + } + /* Ingore quotes at the end of the value identifier + */ + if ((line_string_segment[line_string_segment_index - 1] == '"') + || (line_string_segment[line_string_segment_index - 1] == '\'')) + { + image_length--; + + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[line_string_segment_index - 1] = 0; + } + else + { + /* Make sure the value identifier is terminated by an end of string + */ + line_string_segment[line_string_segment_index] = 0; + } + line_string_segment_index++; + +#if defined( HAVE_DEBUG_OUTPUT ) + if (libcnotify_verbose != 0) + { + libcnotify_printf( + "%s: value: %d\t\t\t\t: %s, %s\n", + function, + *line_index, + value_identifier, + value); + } +#endif + *line_index += 1; + + if (libvslvm_raid_initialize( + &raid, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create raid.", + function); + + goto on_error; + } + if (libvslvm_raid_set_meta_name( + raid, + meta_name, + meta_length + 1, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set physical volume name.", + function); + + goto on_error; + } + if (libvslvm_raid_set_image_name( + raid, + image_name, + image_length + 1, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set data area offset.", + function); + + goto on_error; + } + if (libvslvm_segment_append_raid( + segment, + raid, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append raid to segment.", + function); + + goto on_error; + } + raid = NULL; + } + return(1); + +on_error: + if (raid != NULL) + { + libvslvm_internal_raid_free( + (libvslvm_internal_raid_t **)&raid, + NULL); + } + return(-1); +} \ No newline at end of file diff --git a/libvslvm_metadata.h b/libvslvm_metadata.h new file mode 100644 index 0000000..001afbc --- /dev/null +++ b/libvslvm_metadata.h @@ -0,0 +1,146 @@ +/* + * The metadata functions + * + * Copyright (C) 2014-2023, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#if !defined( _LIBVSLVM_METADATA_H ) +#define _LIBVSLVM_METADATA_H + +#include +#include + +#include "libvslvm_libbfio.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_libcsplit.h" +#include "libvslvm_logical_volume_values.h" +#include "libvslvm_segment.h" +#include "libvslvm_volume_group.h" + +#if defined( __cplusplus ) +extern "C" { +#endif + +typedef struct libvslvm_metadata libvslvm_metadata_t; + +struct libvslvm_metadata +{ + /* The volume group + */ + libvslvm_volume_group_t *volume_group; +}; + +int libvslvm_metadata_initialize( + libvslvm_metadata_t **metadata, + libcerror_error_t **error ); + +int libvslvm_metadata_free( + libvslvm_metadata_t **metadata, + libcerror_error_t **error ); + +int libvslvm_metadata_read_data( + libvslvm_metadata_t *metadata, + const uint8_t *data, + size_t data_size, + uint32_t stored_checksum, + libcerror_error_t **error ); + +int libvslvm_metadata_read_file_io_handle( + libvslvm_metadata_t *metadata, + libbfio_handle_t *file_io_handle, + off64_t file_offset, + size64_t metadata_size, + uint32_t stored_checksum, + libcerror_error_t **error ); + +int libvslvm_metadata_read_volume_group( + libvslvm_metadata_t *metadata, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ); + +int libvslvm_metadata_read_physical_volumes( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ); + +int libvslvm_metadata_read_physical_volume( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ); + +int libvslvm_metadata_read_logical_volumes( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ); + +int libvslvm_metadata_read_logical_volume( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t *volume_group, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ); + +int libvslvm_metadata_read_segment( + libvslvm_metadata_t *metadata, + libvslvm_logical_volume_values_t *logical_volume_values, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ); + +int libvslvm_metadata_read_stripes_list( + libvslvm_metadata_t *metadata, + libvslvm_segment_t *segment, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error ); + +int libvslvm_metadata_get_volume_group( + libvslvm_metadata_t *metadata, + libvslvm_volume_group_t **volume_group, + libcerror_error_t **error ); + +/* 20190306 liubo raid lvm +*/ +int libvslvm_metadata_read_raids_list( + libvslvm_metadata_t *metadata, + libvslvm_segment_t *segment, + libcsplit_narrow_split_string_t *lines, + int number_of_lines, + int *line_index, + libcerror_error_t **error); + +#if defined( __cplusplus ) +} +#endif + +#endif /* !defined( _LIBVSLVM_METADATA_H ) */ + diff --git a/libvslvm_physical_volume.c b/libvslvm_physical_volume.c new file mode 100644 index 0000000..9c7ebca --- /dev/null +++ b/libvslvm_physical_volume.c @@ -0,0 +1,2015 @@ +/* + * Physical volume functions + * + * Copyright (C) 2014-2023, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "libvslvm_checksum.h" +#include "libvslvm_data_area_descriptor.h" +#include "libvslvm_libbfio.h" +#include "libvslvm_libcdata.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_libcnotify.h" +#include "libvslvm_physical_volume.h" +#include "libvslvm_types.h" +#include "libvslvm_unused.h" + +#include "vslvm_physical_volume_label.h" + +const char *vslvm_physical_volume_label_signature = "LABELONE"; + +const uint8_t vslvm_empty_data_area_descriptor[ 16 ] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* Creates a physical volume + * Make sure the value physical_volume is referencing, is set to NULL + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_initialize( + libvslvm_physical_volume_t **physical_volume, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_initialize"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + if( *physical_volume != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid physical volume value already set.", + function ); + + return( -1 ); + } + internal_physical_volume = memory_allocate_structure( + libvslvm_internal_physical_volume_t ); + + if( internal_physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create physical volume.", + function ); + + goto on_error; + } + if( memory_set( + internal_physical_volume, + 0, + sizeof( libvslvm_internal_physical_volume_t ) ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to clear physical volume.", + function ); + + memory_free( + internal_physical_volume ); + + return( -1 ); + } + if( libcdata_array_initialize( + &( internal_physical_volume->data_area_descriptors_array ), + 0, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create data area descripors array.", + function ); + + goto on_error; + } + if( libcdata_array_initialize( + &( internal_physical_volume->metadata_area_descriptors_array ), + 0, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create metadata area descripors array.", + function ); + + goto on_error; + } + *physical_volume= (libvslvm_physical_volume_t *) internal_physical_volume; + + return( 1 ); + +on_error: + if( internal_physical_volume != NULL ) + { + if( internal_physical_volume->data_area_descriptors_array != NULL ) + { + libcdata_array_free( + &( internal_physical_volume->data_area_descriptors_array ), + NULL, + NULL ); + } + memory_free( + internal_physical_volume ); + } + return( -1 ); +} + +/* Frees a physical volume + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_free( + libvslvm_physical_volume_t **physical_volume, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_physical_volume_free"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + if( *physical_volume != NULL ) + { + *physical_volume = NULL; + } + return( 1 ); +} + +/* Frees a physical volume + * Returns 1 if successful or -1 on error + */ +int libvslvm_internal_physical_volume_free( + libvslvm_internal_physical_volume_t **internal_physical_volume, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_internal_physical_volume_free"; + int result = 1; + + if( internal_physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + if( *internal_physical_volume != NULL ) + { + if( ( *internal_physical_volume )->name != NULL ) + { + memory_free( + ( *internal_physical_volume )->name ); + } + if( ( *internal_physical_volume )->device_path != NULL ) + { + memory_free( + ( *internal_physical_volume )->device_path ); + } + if( libcdata_array_free( + &( ( *internal_physical_volume )->data_area_descriptors_array ), + (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_data_area_descriptor_free, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free data area descriptors array.", + function ); + + result = -1; + } + if( libcdata_array_free( + &( ( *internal_physical_volume )->metadata_area_descriptors_array ), + (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_data_area_descriptor_free, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free metadata area descriptors array.", + function ); + + result = -1; + } + memory_free( + *internal_physical_volume ); + + *internal_physical_volume = NULL; + } + return( result ); +} + +/* Retrieves the size of the ASCII formatted name + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_name_size( + libvslvm_physical_volume_t *physical_volume, + size_t *name_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_name_size"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( name_size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid name size.", + function ); + + return( -1 ); + } + *name_size = internal_physical_volume->name_size; + + return( 1 ); +} + +/* Retrieves the ASCII formatted name + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_name( + libvslvm_physical_volume_t *physical_volume, + char *name, + size_t name_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_name"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( name == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid name.", + function ); + + return( -1 ); + } + if( name_size > (size_t) SSIZE_MAX ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid name size value exceeds maximum.", + function ); + + return( -1 ); + } + if( name_size < internal_physical_volume->name_size ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, + "%s: invalid name size value too small.", + function ); + + return( -1 ); + } + if( memory_copy( + name, + internal_physical_volume->name, + internal_physical_volume->name_size ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy name.", + function ); + + return( -1 ); + } + name[ internal_physical_volume->name_size - 1 ] = 0; + + return( 1 ); +} + +/* Sets the name + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_set_name( + libvslvm_physical_volume_t *physical_volume, + const char *name, + size_t name_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_set_name"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( name == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid name.", + function ); + + return( -1 ); + } + if( ( name_size == 0 ) + || ( name_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid name size value out of bounds.", + function ); + + return( -1 ); + } + if( internal_physical_volume->name != NULL ) + { + memory_free( + internal_physical_volume->name ); + + internal_physical_volume->name = NULL; + internal_physical_volume->name_size = 0; + } + internal_physical_volume->name = (char *) memory_allocate( + sizeof( char ) * name_size ); + + if( internal_physical_volume->name == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create name.", + function ); + + goto on_error; + } + if( memory_copy( + internal_physical_volume->name, + name, + name_size ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy name.", + function ); + + goto on_error; + } + internal_physical_volume->name[ name_size - 1 ] = 0; + + internal_physical_volume->name_size = name_size; + + return( 1 ); + +on_error: + if( internal_physical_volume->name != NULL ) + { + memory_free( + internal_physical_volume->name ); + + internal_physical_volume->name = NULL; + } + internal_physical_volume->name_size = 0; + + return( -1 ); +} + +/* Compares the name with that of the physical volume + * Returns 1 if the name matches, 0 if not or -1 on error + */ +int libvslvm_physical_volume_compare_by_name( + libvslvm_physical_volume_t *physical_volume, + const char *name, + size_t name_length, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_compare_by_name"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( name == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid name.", + function ); + + return( -1 ); + } + if( name_length > (size_t) ( SSIZE_MAX - 1 ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: name length value exceeds maximum.", + function ); + + return( -1 ); + } + if( ( internal_physical_volume->name_size == ( name_length + 1 ) ) + && ( memory_compare( + name, + internal_physical_volume->name, + internal_physical_volume->name_size ) == 0 ) ) + { + return( 1 ); + } + return( 0 ); +} + +/* Retrieves the size of the ASCII formatted identifier + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_identifier_size( + libvslvm_physical_volume_t *physical_volume, + size_t *identifier_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_identifier_size"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( identifier_size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid identifier size.", + function ); + + return( -1 ); + } + if( internal_physical_volume->identifier[ 0 ] == 0 ) + { + *identifier_size = 0; + } + else + { + *identifier_size = 39; + } + return( 1 ); +} + +/* Retrieves the ASCII formatted identifier + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_identifier( + libvslvm_physical_volume_t *physical_volume, + char *identifier, + size_t identifier_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_set_identifier"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( identifier == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid identifier.", + function ); + + return( -1 ); + } + if( identifier_size > (size_t) SSIZE_MAX ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid identifier size value exceeds maximum.", + function ); + + return( -1 ); + } + if( identifier_size < 39 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, + "%s: invalid identifier size value too small.", + function ); + + return( -1 ); + } + if( memory_copy( + identifier, + internal_physical_volume->identifier, + 39 ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy identifier.", + function ); + + return( -1 ); + } + identifier[ 38 ] = 0; + + return( 1 ); +} + +/* Sets the identifier + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_set_identifier( + libvslvm_physical_volume_t *physical_volume, + const char *identifier, + size_t identifier_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_set_identifier"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( identifier == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid identifier.", + function ); + + return( -1 ); + } + if( identifier_size != 39 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: identifier size value out of bounds.", + function ); + + return( -1 ); + } + if( memory_copy( + internal_physical_volume->identifier, + identifier, + 39 ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy identifier.", + function ); + + return( -1 ); + } + internal_physical_volume->identifier[ 38 ] = 0; + + return( 1 ); +} + +/* Retrieves the size of the ASCII formatted device path + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_device_path_size( + libvslvm_physical_volume_t *physical_volume, + size_t *device_path_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_device_path_size"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( device_path_size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid device path size.", + function ); + + return( -1 ); + } + *device_path_size = internal_physical_volume->device_path_size; + + return( 1 ); +} + +/* Retrieves the ASCII formatted device path + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_device_path( + libvslvm_physical_volume_t *physical_volume, + char *device_path, + size_t device_path_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_set_device_path"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( device_path == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid device_path.", + function ); + + return( -1 ); + } + if( device_path_size > (size_t) SSIZE_MAX ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid device path size value exceeds maximum.", + function ); + + return( -1 ); + } + if( device_path_size < internal_physical_volume->device_path_size ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, + "%s: invalid device path size value too small.", + function ); + + return( -1 ); + } + if( memory_copy( + device_path, + internal_physical_volume->device_path, + internal_physical_volume->device_path_size ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy device path.", + function ); + + return( -1 ); + } + device_path[ internal_physical_volume->device_path_size - 1 ] = 0; + + return( 1 ); +} + +/* Sets the device path + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_set_device_path( + libvslvm_physical_volume_t *physical_volume, + const char *device_path, + size_t device_path_size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_set_device_path"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( device_path == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid device path.", + function ); + + return( -1 ); + } + if( ( device_path_size == 0 ) + || ( device_path_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid device path size value out of bounds.", + function ); + + return( -1 ); + } + //+++add by liubo 2020017 resoved physical_volumes's device = "" + if (device_path_size <= 0) + { + //device_path_size = 1; + internal_physical_volume->device_path == NULL; + internal_physical_volume->device_path_size = 0; + return(1); + } + //--- + if( internal_physical_volume->device_path != NULL ) + { + memory_free( + internal_physical_volume->device_path ); + + internal_physical_volume->device_path = NULL; + internal_physical_volume->device_path_size = 0; + } + internal_physical_volume->device_path = (char *) memory_allocate( + sizeof( char ) * device_path_size ); + + if( internal_physical_volume->device_path == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create device path.", + function ); + + goto on_error; + } + if( memory_copy( + internal_physical_volume->device_path, + device_path, + device_path_size ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy device path.", + function ); + + goto on_error; + } + internal_physical_volume->device_path[ device_path_size - 1 ] = 0; + + internal_physical_volume->device_path_size = device_path_size; + + return( 1 ); + +on_error: + if( internal_physical_volume->device_path != NULL ) + { + memory_free( + internal_physical_volume->device_path ); + + internal_physical_volume->device_path = NULL; + } + internal_physical_volume->device_path_size = 0; + + return( -1 ); +} + +/* Retrieves the size + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_size( + libvslvm_physical_volume_t *physical_volume, + size64_t *size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_size"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid size.", + function ); + + return( -1 ); + } + *size = internal_physical_volume->size; + + return( 1 ); +} + +/* Retrieves the number of data area descriptors + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_number_of_data_area_descriptors( + libvslvm_physical_volume_t *physical_volume, + int *number_of_data_area_descriptors, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_number_of_data_area_descriptors"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( libcdata_array_get_number_of_entries( + internal_physical_volume->data_area_descriptors_array, + number_of_data_area_descriptors, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of data area descriptors from array.", + function ); + + return( -1 ); + } + return( 1 ); +} + +/* Retrieves a specific data area descriptor + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_data_area_descriptor( + libvslvm_physical_volume_t *physical_volume, + int data_area_descriptor_index, + libvslvm_data_area_descriptor_t **data_area_descriptor, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_data_area_descriptor"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( libcdata_array_get_entry_by_index( + internal_physical_volume->data_area_descriptors_array, + data_area_descriptor_index, + (intptr_t **) data_area_descriptor, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve data area descriptor: %d.", + function, + data_area_descriptor_index ); + + return( -1 ); + } + return( 1 ); +} + +/* Retrieves the data area descriptor for a specific offset + * Returns 1 if successful, 0 if no such data area descriptor or -1 on error + */ +int libvslvm_physical_volume_get_data_area_descriptor_by_offset( + libvslvm_physical_volume_t *physical_volume, + uint64_t offset, + libvslvm_data_area_descriptor_t **data_area_descriptor, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_data_area_descriptor_by_offset"; + int data_area_descriptor_index = 0; + int number_of_data_area_descriptors = 0; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( data_area_descriptor == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid data area descriptor.", + function ); + + return( -1 ); + } + if( *data_area_descriptor != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid data area descriptor value already set.", + function ); + + return( -1 ); + } + if( libcdata_array_get_number_of_entries( + internal_physical_volume->data_area_descriptors_array, + &number_of_data_area_descriptors, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of data area descriptors from array.", + function ); + + return( -1 ); + } + for( data_area_descriptor_index = 0; + data_area_descriptor_index < number_of_data_area_descriptors; + data_area_descriptor_index++ ) + { + if( libcdata_array_get_entry_by_index( + internal_physical_volume->data_area_descriptors_array, + data_area_descriptor_index, + (intptr_t **) data_area_descriptor, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve data area descriptor: %d.", + function, + data_area_descriptor_index ); + + return( -1 ); + } + if( *data_area_descriptor == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, + "%s: missing data area descriptor: %d.", + function, + data_area_descriptor_index ); + + return( -1 ); + } + if( ( *data_area_descriptor )->size == 0 ) + { + return( 1 ); + } + offset -= ( *data_area_descriptor )->size; + } + return( 0 ); +} + +/* Retrieves the number of metadata area descriptors + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_number_of_metadata_area_descriptors( + libvslvm_physical_volume_t *physical_volume, + int *number_of_data_area_descriptors, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_number_of_metadata_area_descriptors"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( libcdata_array_get_number_of_entries( + internal_physical_volume->metadata_area_descriptors_array, + number_of_data_area_descriptors, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of metadata area descriptors from array.", + function ); + + return( -1 ); + } + return( 1 ); +} + +/* Retrieves a specific metadata area descriptor + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_metadata_area_descriptor( + libvslvm_physical_volume_t *physical_volume, + int data_area_descriptor_index, + libvslvm_data_area_descriptor_t **data_area_descriptor, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_metadata_area_descriptor"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( libcdata_array_get_entry_by_index( + internal_physical_volume->metadata_area_descriptors_array, + data_area_descriptor_index, + (intptr_t **) data_area_descriptor, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve metadata area descriptor: %d.", + function, + data_area_descriptor_index ); + + return( -1 ); + } + return( 1 ); +} + +/* TODO move function into libvslvm_physical_volume_label.c */ + +/* Reads a physical volume label + * Returns 1 if successful, 0 if not found or -1 on error + */ +int libvslvm_internal_physical_volume_read_label_data( + libvslvm_internal_physical_volume_t *internal_physical_volume, + const uint8_t *data, + size_t data_size, + libcerror_error_t **error ) +{ + libvslvm_data_area_descriptor_t *data_area_descriptor = NULL; + static char *function = "libvslvm_internal_physical_volume_read_label_data"; + size_t data_offset = 0; + uint64_t offset = 0; + uint64_t size = 0; + uint32_t calculated_checksum = 0; + uint32_t stored_checksum = 0; + int entry_index = 0; + int result = 0; + +#if defined( HAVE_DEBUG_OUTPUT ) + uint64_t value_64bit = 0; + uint32_t value_32bit = 0; +#endif + + if( internal_physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + if( data == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid data.", + function ); + + return( -1 ); + } + if( ( data_size == 0 ) + || ( data_size > (size_t) SSIZE_MAX ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid data size value out of bounds.", + function ); + + return( -1 ); + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: physical volume label data:\n", + function ); + libcnotify_print_data( + data, + 512, + LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); + } +#endif +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: physical volume label header:\n", + function ); + libcnotify_print_data( + data, + sizeof( vslvm_physical_volume_label_header_t ), + 0 ); + } +#endif + if( memory_compare( + ( (vslvm_physical_volume_label_header_t *) data )->signature, + vslvm_physical_volume_label_signature, + 8 ) != 0 ) + { + return( 0 ); + } + byte_stream_copy_to_uint32_little_endian( + ( (vslvm_physical_volume_label_header_t *) data )->checksum, + stored_checksum ); + +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: signature\t\t: %c%c%c%c%c%c%c%c\n", + function, + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 0 ], + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 1 ], + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 2 ], + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 3 ], + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 4 ], + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 5 ], + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 6 ], + ( (vslvm_physical_volume_label_header_t *) data )->signature[ 7 ] ); + + byte_stream_copy_to_uint64_little_endian( + ( (vslvm_physical_volume_label_header_t *) data )->sector_number, + value_64bit ); + libcnotify_printf( + "%s: sector number\t: %" PRIu64 "\n", + function, + value_64bit ); + + libcnotify_printf( + "%s: checksum\t\t: 0x%08" PRIx32 "\n", + function, + stored_checksum ); + + byte_stream_copy_to_uint32_little_endian( + ( (vslvm_physical_volume_label_header_t *) data )->data_offset, + value_32bit ); + libcnotify_printf( + "%s: data offset\t\t: 0x%08" PRIx32 "\n", + function, + value_32bit ); + + libcnotify_printf( + "%s: type indicator\t: %c%c%c%c%c%c%c%c\n", + function, + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 0 ], + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 1 ], + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 2 ], + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 3 ], + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 4 ], + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 5 ], + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 6 ], + ( (vslvm_physical_volume_label_header_t *) data )->type_indicator[ 7 ] ); + + libcnotify_printf( + "\n" ); + } +#endif /* defined( HAVE_DEBUG_OUTPUT ) */ + + if( libvslvm_checksum_calculate_weak_crc32( + &calculated_checksum, + &( data[ 20 ] ), + 512 - 20, + 0xf597a6cfUL, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to calculate CRC-32.", + function ); + + goto on_error; + } + if( ( stored_checksum != 0 ) + && ( stored_checksum != calculated_checksum ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_INPUT, + LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, + "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).", + function, + stored_checksum, + calculated_checksum ); + + goto on_error; + } + data_offset = sizeof( vslvm_physical_volume_label_header_t ); + +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: physical volume header data:\n", + function ); + libcnotify_print_data( + &( data[ data_offset ] ), + sizeof( vslvm_physical_volume_header_t ), + 0 ); + } +#endif +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: identifier\t\t: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", + function, + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 0 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 1 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 2 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 3 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 4 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 5 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 6 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 7 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 8 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 9 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 10 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 11 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 12 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 13 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 14 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 15 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 16 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 17 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 18 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 19 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 20 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 21 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 22 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 23 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 24 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 25 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 26 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 27 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 28 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 29 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 30 ], + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->identifier[ 31 ] ); + + byte_stream_copy_to_uint64_little_endian( + ( (vslvm_physical_volume_header_t *) &( data[ data_offset ] ) )->volume_size, + value_64bit ); + libcnotify_printf( + "%s: volume size\t\t: %" PRIu64 "\n", + function, + value_64bit ); + + libcnotify_printf( + "\n" ); + } +#endif /* defined( HAVE_DEBUG_OUTPUT ) */ + + data_offset += sizeof( vslvm_physical_volume_header_t ); + + do + { + if( data_offset >= ( data_size - sizeof( vslvm_data_area_descriptor_t ) ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid data offset value out of bounds.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: data area descriptor data:\n", + function ); + libcnotify_print_data( + &( data[ data_offset ] ), + sizeof( vslvm_data_area_descriptor_t ), + 0 ); + } +#endif + result = memory_compare( + &( data[ data_offset ] ), + vslvm_empty_data_area_descriptor, + sizeof( vslvm_data_area_descriptor_t ) ); + + if( result != 0 ) + { + byte_stream_copy_to_uint64_little_endian( + ( (vslvm_data_area_descriptor_t *) &( data[ data_offset ] ) )->offset, + offset ); + + byte_stream_copy_to_uint64_little_endian( + ( (vslvm_data_area_descriptor_t *) &( data[ data_offset ] ) )->size, + size ); + +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: data area offset\t: 0x%08" PRIx64 "\n", + function, + offset ); + + libcnotify_printf( + "%s: data area size\t: %" PRIu64 "\n", + function, + size ); + + libcnotify_printf( + "\n" ); + } +#endif /* defined( HAVE_DEBUG_OUTPUT ) */ + + if( libvslvm_data_area_descriptor_initialize( + &data_area_descriptor, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create data area descriptor.", + function ); + + goto on_error; + } + if( libvslvm_data_area_descriptor_set( + data_area_descriptor, + (off64_t) offset, + (size64_t) size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set data area descriptor.", + function ); + + goto on_error; + } + if( libcdata_array_append_entry( + internal_physical_volume->data_area_descriptors_array, + &entry_index, + (intptr_t *) data_area_descriptor, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append entry to data area descriptors array.", + function ); + + goto on_error; + } + data_area_descriptor = NULL; + } + data_offset += sizeof( vslvm_data_area_descriptor_t ); + } + while( result != 0 ); + + do + { + if( data_offset >= ( data_size - sizeof( vslvm_data_area_descriptor_t ) ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid data offset value out of bounds.", + function ); + + goto on_error; + } +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: metadata area descriptor data:\n", + function ); + libcnotify_print_data( + &( data[ data_offset ] ), + sizeof( vslvm_data_area_descriptor_t ), + 0 ); + } +#endif + result = memory_compare( + &( data[ data_offset ] ), + vslvm_empty_data_area_descriptor, + sizeof( vslvm_data_area_descriptor_t ) ); + + if( result != 0 ) + { + byte_stream_copy_to_uint64_little_endian( + ( (vslvm_data_area_descriptor_t *) &( data[ data_offset ] ) )->offset, + offset ); + + byte_stream_copy_to_uint64_little_endian( + ( (vslvm_data_area_descriptor_t *) &( data[ data_offset ] ) )->size, + size ); + +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: metadata area offset\t: 0x%08" PRIx64 "\n", + function, + offset ); + + libcnotify_printf( + "%s: metadata area size\t: %" PRIu64 "\n", + function, + size ); + + libcnotify_printf( + "\n" ); + } +#endif /* defined( HAVE_DEBUG_OUTPUT ) */ + + if( libvslvm_data_area_descriptor_initialize( + &data_area_descriptor, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create data area descriptor.", + function ); + + goto on_error; + } + if( libvslvm_data_area_descriptor_set( + data_area_descriptor, + (off64_t) offset, + (size64_t) size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set data area descriptor.", + function ); + + goto on_error; + } + if( libcdata_array_append_entry( + internal_physical_volume->metadata_area_descriptors_array, + &entry_index, + (intptr_t *) data_area_descriptor, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append entry to metadata area descriptors array.", + function ); + + goto on_error; + } + data_area_descriptor = NULL; + } + data_offset += sizeof( vslvm_data_area_descriptor_t ); + } + while( result != 0 ); + + return( 1 ); + +on_error: + if( data_area_descriptor != NULL ) + { + libvslvm_data_area_descriptor_free( + &data_area_descriptor, + NULL ); + } + libcdata_array_empty( + internal_physical_volume->metadata_area_descriptors_array, + (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_data_area_descriptor_free, + NULL ); + + libcdata_array_empty( + internal_physical_volume->data_area_descriptors_array, + (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_data_area_descriptor_free, + NULL ); + + return( -1 ); +} + +/* Reads a physical volume label + * Returns 1 if successful, 0 if not found or -1 on error + */ +int libvslvm_physical_volume_read_label_file_io_pool( + libvslvm_physical_volume_t *physical_volume, + libbfio_pool_t *file_io_pool, + int file_io_pool_entry, + off64_t file_offset, + libcerror_error_t **error ) +{ + uint8_t physical_volume_label_data[ 512 ]; + + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_read_label_file_io_pool"; + ssize_t read_count = 0; + int result = 0; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + +#if defined( HAVE_DEBUG_OUTPUT ) + if( libcnotify_verbose != 0 ) + { + libcnotify_printf( + "%s: reading physical volume label at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", + function, + file_offset, + file_offset ); + } +#endif + read_count = libbfio_pool_read_buffer_at_offset( + file_io_pool, + file_io_pool_entry, + physical_volume_label_data, + 512, + file_offset, + error ); + + if( read_count != (ssize_t) 512 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read physical volume label at offset %" PRIi64 " (0x%08" PRIx64 ").", + function, + file_offset, + file_offset ); + + return( -1 ); + } + result = libvslvm_internal_physical_volume_read_label_data( + internal_physical_volume, + physical_volume_label_data, + 512, + error ); + + if( result == -1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read physical volume label.", + function ); + + return( -1 ); + } + return( result ); +} + +/* Reads the physical volume + * Callback function for the physical volume files list + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_read_element_data( + intptr_t *data_handle LIBVSLVM_ATTRIBUTE_UNUSED, + libbfio_pool_t *file_io_pool, + libfdata_list_element_t *element, + libfdata_cache_t *cache, + int file_io_pool_entry, + off64_t physical_volume_offset, + size64_t physical_volume_size LIBVSLVM_ATTRIBUTE_UNUSED, + uint32_t element_flags LIBVSLVM_ATTRIBUTE_UNUSED, + uint8_t read_flags LIBVSLVM_ATTRIBUTE_UNUSED, + libcerror_error_t **error ) +{ + libvslvm_physical_volume_t *physical_volume = NULL; + static char *function = "libvslvm_physical_volume_read_element_data"; + off64_t label_offset = 0; + int result = 0; + + LIBVSLVM_UNREFERENCED_PARAMETER( data_handle ) + LIBVSLVM_UNREFERENCED_PARAMETER( physical_volume_size ) + LIBVSLVM_UNREFERENCED_PARAMETER( element_flags ) + LIBVSLVM_UNREFERENCED_PARAMETER( read_flags ) + + if( libvslvm_physical_volume_initialize( + &physical_volume, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create physical volume.", + function ); + + goto on_error; + } + /* The physical volume label can be stored in one of the first 4 sectors + */ + label_offset = 0; + + while( label_offset < 2048 ) + { + result = libvslvm_physical_volume_read_label_file_io_pool( + physical_volume, + file_io_pool, + file_io_pool_entry, + physical_volume_offset + label_offset, + error ); + + if( result == -1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read physical volume label at offset: %" PRIi64 ".", + function, + physical_volume_offset + label_offset ); + + goto on_error; + } + else if( result != 0 ) + { + break; + } + label_offset += 512; + } + if( result != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_IO, + LIBCERROR_IO_ERROR_READ_FAILED, + "%s: unable to read physical volume label.", + function ); + + goto on_error; + } + if( libfdata_list_element_set_element_value( + element, + (intptr_t *) file_io_pool, + cache, + (intptr_t *) physical_volume, + (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_internal_physical_volume_free, + LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_SET_FAILED, + "%s: unable to set physical volume as element value.", + function ); + + goto on_error; + } + return( 1 ); + +on_error: + if( physical_volume != NULL ) + { + libvslvm_internal_physical_volume_free( + (libvslvm_internal_physical_volume_t **) &physical_volume, + NULL ); + } + return( -1 ); +} + +/* ++ 2018/12/28 add by liu bo +*/ +/* Retrieves the pe_count + * Returns 1 if successful or -1 on error + */ +int libvslvm_physical_volume_get_pe_count( + libvslvm_physical_volume_t *physical_volume, + size64_t *size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_pe_count"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid size.", + function ); + + return( -1 ); + } + *size = internal_physical_volume->pe_count; + + return( 1 ); +} + +int libvslvm_physical_volume_get_pe_start( + libvslvm_physical_volume_t *physical_volume, + size64_t *size, + libcerror_error_t **error ) +{ + libvslvm_internal_physical_volume_t *internal_physical_volume = NULL; + static char *function = "libvslvm_physical_volume_get_pe_start"; + + if( physical_volume == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume.", + function ); + + return( -1 ); + } + internal_physical_volume = (libvslvm_internal_physical_volume_t *) physical_volume; + + if( size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid size.", + function ); + + return( -1 ); + } + *size = internal_physical_volume->pe_start; + + return( 1 ); +} +/* -- 2018/12/28 add by liu bo +*/ \ No newline at end of file diff --git a/libvslvm_physical_volume.h b/libvslvm_physical_volume.h new file mode 100644 index 0000000..11277f4 --- /dev/null +++ b/libvslvm_physical_volume.h @@ -0,0 +1,244 @@ +/* + * Physical volume functions + * + * Copyright (C) 2014-2023, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#if !defined( _LIBVSLVM_INTERNAL_PHYSICAL_VOLUME_H ) +#define _LIBVSLVM_INTERNAL_PHYSICAL_VOLUME_H + +#include +#include + +#include "libvslvm_data_area_descriptor.h" +#include "libvslvm_extern.h" +#include "libvslvm_libbfio.h" +#include "libvslvm_libcdata.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_libfdata.h" +#include "libvslvm_types.h" + +#if defined( __cplusplus ) +extern "C" { +#endif + +extern const char *vslvm_physical_volume_label_signature; + +typedef struct libvslvm_internal_physical_volume libvslvm_internal_physical_volume_t; + +struct libvslvm_internal_physical_volume +{ + /* The name + */ + char *name; + + /* The name size + */ + size_t name_size; + + /* The identfier + */ + char identifier[ 39 ]; + + /* The device path + */ + char *device_path; + + /* The device path size + */ + size_t device_path_size; + + /* The size + */ + size64_t size; + + /* The data area descriptors array + */ + libcdata_array_t *data_area_descriptors_array; + + /* The metadata area descriptors array + */ + libcdata_array_t *metadata_area_descriptors_array; + + /* 2018/12/28 add by liu bo + ++ + */ + size64_t pe_start; + size64_t pe_count; + /* + -- + */ +}; + +int libvslvm_physical_volume_initialize( + libvslvm_physical_volume_t **physical_volume, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_free( + libvslvm_physical_volume_t **physical_volume, + libcerror_error_t **error ); + +int libvslvm_internal_physical_volume_free( + libvslvm_internal_physical_volume_t **internal_physical_volume, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_name_size( + libvslvm_physical_volume_t *physical_volume, + size_t *name_size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_name( + libvslvm_physical_volume_t *physical_volume, + char *name, + size_t name_size, + libcerror_error_t **error ); + +int libvslvm_physical_volume_set_name( + libvslvm_physical_volume_t *physical_volume, + const char *name, + size_t name_size, + libcerror_error_t **error ); + +int libvslvm_physical_volume_compare_by_name( + libvslvm_physical_volume_t *physical_volume, + const char *name, + size_t name_length, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_identifier_size( + libvslvm_physical_volume_t *physical_volume, + size_t *identifier_size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_identifier( + libvslvm_physical_volume_t *physical_volume, + char *identifier, + size_t identifier_size, + libcerror_error_t **error ); + +int libvslvm_physical_volume_set_identifier( + libvslvm_physical_volume_t *physical_volume, + const char *identifier, + size_t identifier_size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_device_path_size( + libvslvm_physical_volume_t *physical_volume, + size_t *device_path_size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_device_path( + libvslvm_physical_volume_t *physical_volume, + char *device_path, + size_t device_path_size, + libcerror_error_t **error ); + +int libvslvm_physical_volume_set_device_path( + libvslvm_physical_volume_t *physical_volume, + const char *device_path, + size_t device_path_size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_size( + libvslvm_physical_volume_t *physical_volume, + size64_t *size, + libcerror_error_t **error ); + +int libvslvm_physical_volume_get_number_of_data_area_descriptors( + libvslvm_physical_volume_t *physical_volume, + int *number_of_data_area_descriptors, + libcerror_error_t **error ); + +int libvslvm_physical_volume_get_data_area_descriptor( + libvslvm_physical_volume_t *physical_volume, + int data_area_descriptor_index, + libvslvm_data_area_descriptor_t **data_area_descriptor, + libcerror_error_t **error ); + +int libvslvm_physical_volume_get_data_area_descriptor_by_offset( + libvslvm_physical_volume_t *physical_volume, + uint64_t offset, + libvslvm_data_area_descriptor_t **data_area_descriptor, + libcerror_error_t **error ); + +int libvslvm_physical_volume_get_number_of_metadata_area_descriptors( + libvslvm_physical_volume_t *physical_volume, + int *number_of_data_area_descriptors, + libcerror_error_t **error ); + +int libvslvm_physical_volume_get_metadata_area_descriptor( + libvslvm_physical_volume_t *physical_volume, + int data_area_descriptor_index, + libvslvm_data_area_descriptor_t **data_area_descriptor, + libcerror_error_t **error ); + +int libvslvm_internal_physical_volume_read_label_data( + libvslvm_internal_physical_volume_t *internal_physical_volume, + const uint8_t *data, + size_t data_size, + libcerror_error_t **error ); + +int libvslvm_physical_volume_read_label_file_io_pool( + libvslvm_physical_volume_t *physical_volume, + libbfio_pool_t *file_io_pool, + int file_io_pool_entry, + off64_t file_offset, + libcerror_error_t **error ); + +int libvslvm_physical_volume_read_element_data( + intptr_t *data_handle, + libbfio_pool_t *file_io_pool, + libfdata_list_element_t *element, + libfdata_cache_t *cache, + int file_io_pool_entry, + off64_t physical_volume_offset, + size64_t physical_volume_size, + uint32_t element_flags, + uint8_t read_flags, + libcerror_error_t **error ); + +/* ++ 2018/12/28 add by liu bo +*/ +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_pe_count( + libvslvm_physical_volume_t *physical_volume, + size64_t *size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_physical_volume_get_pe_start( + libvslvm_physical_volume_t *physical_volume, + size64_t *size, + libcerror_error_t **error ); + +/* -- 2018/12/28 add by liu bo +*/ +#if defined( __cplusplus ) +} +#endif + +#endif /* !defined( _LIBVSLVM_INTERNAL_PHYSICAL_VOLUME_H ) */ + diff --git a/libvslvm_raid.c b/libvslvm_raid.c new file mode 100644 index 0000000..f6ed075 --- /dev/null +++ b/libvslvm_raid.c @@ -0,0 +1,592 @@ +/* + * raid functions + * + */ + +#include +#include +#include + +#include "libvslvm_libcerror.h" +#include "libvslvm_raid.h" +#include "libvslvm_types.h" + + /* Creates a raid + * Make sure the value raid is referencing, is set to NULL + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_initialize( + libvslvm_raid_t **raid, + libcerror_error_t **error) +{ + libvslvm_internal_raid_t *internal_raid = NULL; + static char *function = "libvslvm_raid_initialize"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + if (*raid != NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid raid value already set.", + function); + + return(-1); + } + internal_raid = memory_allocate_structure( + libvslvm_internal_raid_t); + + if (internal_raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create raid.", + function); + + goto on_error; + } + if (memory_set( + internal_raid, + 0, + sizeof(libvslvm_internal_raid_t)) == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to clear raid.", + function); + + goto on_error; + } + *raid = (libvslvm_raid_t *)internal_raid; + + return(1); + +on_error: + if (internal_raid != NULL) + { + memory_free( + internal_raid); + } + return(-1); +} + +/* Frees a raid + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_free( + libvslvm_raid_t **raid, + libcerror_error_t **error) +{ + static char *function = "libvslvm_raid_free"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + if (*raid != NULL) + { + *raid = NULL; + } + return(1); +} + +/* Frees a raid + * Returns 1 if successful or -1 on error + */ +int libvslvm_internal_raid_free( + libvslvm_internal_raid_t **internal_raid, + libcerror_error_t **error) +{ + static char *function = "libvslvm_internal_raid_free"; + + if (internal_raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + if (*internal_raid != NULL) + { + if ((*internal_raid)->meta_name != NULL) + { + memory_free( + (*internal_raid)->meta_name); + } + if ((*internal_raid)->image_name != NULL) + { + memory_free( (*internal_raid)->image_name); + } + memory_free( + *internal_raid); + + *internal_raid = NULL; + } + return(1); +} + +/* Retrieves the size of the ASCII formatted meta name + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_get_meta_name_size( + libvslvm_raid_t *raid, + size_t *meta_name_size, + libcerror_error_t **error) +{ + libvslvm_internal_raid_t *internal_raid = NULL; + static char *function = "libvslvm_raid_get_meta_name_size"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + internal_raid = (libvslvm_internal_raid_t *)raid; + + if (meta_name_size == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid image name size.", + function); + + return(-1); + } + *meta_name_size = internal_raid->meta_name_size; + + return(1); +} + +/* Retrieves the ASCII formatted meta name + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_get_meta_name( + libvslvm_raid_t *raid, + char *meta_name, + size_t meta_name_size, + libcerror_error_t **error) +{ + libvslvm_internal_raid_t *internal_raid = NULL; + static char *function = "libvslvm_raid_get_meta_name"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + internal_raid = (libvslvm_internal_raid_t *)raid; + + if (meta_name == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid meta name.", + function); + + return(-1); + } + if (meta_name_size > (size_t)SSIZE_MAX) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid meta name size value exceeds maximum.", + function); + + return(-1); + } + if (meta_name_size < internal_raid->meta_name_size) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, + "%s: invalid meta name size value too small.", + function); + + return(-1); + } + if (memory_copy( + meta_name, + internal_raid->meta_name, + internal_raid->meta_name_size) == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy meta name.", + function); + + return(-1); + } + meta_name[internal_raid->meta_name_size - 1] = 0; + + return(1); +} + +/* Sets the physical volume name + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_set_meta_name( + libvslvm_raid_t *raid, + const char *meta_name, + size_t meta_name_size, + libcerror_error_t **error) +{ + libvslvm_internal_raid_t *internal_raid = NULL; + static char *function = "libvslvm_raid_set_meta_name"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + internal_raid = (libvslvm_internal_raid_t *)raid; + + if (meta_name == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume name.", + function); + + return(-1); + } + if (meta_name_size > (size_t)SSIZE_MAX) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: physical volume name size value exceeds maximum.", + function); + + return(-1); + } + if (internal_raid->meta_name != NULL) + { + memory_free( + internal_raid->meta_name); + + internal_raid->meta_name = NULL; + internal_raid->meta_name_size = 0; + } + internal_raid->meta_name = (char *)memory_allocate( + sizeof(char) * meta_name_size); + + if (internal_raid->meta_name == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create physical volume name.", + function); + + goto on_error; + } + if (memory_copy( + internal_raid->meta_name, + meta_name, + meta_name_size) == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy physical volume name.", + function); + + goto on_error; + } + internal_raid->meta_name[meta_name_size - 1] = 0; + + internal_raid->meta_name_size = meta_name_size; + + return(1); + +on_error: + if (internal_raid->meta_name != NULL) + { + memory_free( + internal_raid->meta_name); + + internal_raid->meta_name = NULL; + } + internal_raid->meta_name_size = 0; + + return(-1); +} + + +/* Retrieves the size of the ASCII formatted image name + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_get_image_name_size( + libvslvm_raid_t *raid, + size_t *image_name_size, + libcerror_error_t **error) +{ + libvslvm_internal_raid_t *internal_raid = NULL; + static char *function = "libvslvm_raid_get_image_name_size"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + internal_raid = (libvslvm_internal_raid_t *)raid; + + if (image_name_size == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid image name size.", + function); + + return(-1); + } + *image_name_size = internal_raid->image_name_size; + + return(1); +} + +/* Retrieves the ASCII formatted image name + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_get_image_name( + libvslvm_raid_t *raid, + char *image_name, + size_t image_name_size, + libcerror_error_t **error) +{ + libvslvm_internal_raid_t *internal_raid = NULL; + static char *function = "libvslvm_raid_get_image_name"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + internal_raid = (libvslvm_internal_raid_t *)raid; + + if (image_name == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid image name.", + function); + + return(-1); + } + if (image_name_size > (size_t)SSIZE_MAX) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: invalid image name size value exceeds maximum.", + function); + + return(-1); + } + if (image_name_size < internal_raid->image_name_size) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, + "%s: invalid image name size value too small.", + function); + + return(-1); + } + if (memory_copy( + image_name, + internal_raid->image_name, + internal_raid->image_name_size) == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy image name.", + function); + + return(-1); + } + image_name[internal_raid->image_name_size - 1] = 0; + + return(1); +} + +/* Sets the physical volume name + * Returns 1 if successful or -1 on error + */ +int libvslvm_raid_set_image_name( + libvslvm_raid_t *raid, + const char *image_name, + size_t image_name_size, + libcerror_error_t **error) +{ + libvslvm_internal_raid_t *internal_raid = NULL; + static char *function = "libvslvm_raid_set_image_name"; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + internal_raid = (libvslvm_internal_raid_t *)raid; + + if (image_name == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid physical volume name.", + function); + + return(-1); + } + if (image_name_size > (size_t)SSIZE_MAX) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, + "%s: physical volume name size value exceeds maximum.", + function); + + return(-1); + } + if (internal_raid->image_name != NULL) + { + memory_free( + internal_raid->image_name); + + internal_raid->image_name = NULL; + internal_raid->image_name_size = 0; + } + internal_raid->image_name = (char *)memory_allocate( + sizeof(char) * image_name_size); + + if (internal_raid->image_name == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create physical volume name.", + function); + + goto on_error; + } + if (memory_copy( + internal_raid->image_name, + image_name, + image_name_size) == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy physical volume name.", + function); + + goto on_error; + } + internal_raid->image_name[image_name_size - 1] = 0; + + internal_raid->image_name_size = image_name_size; + + return(1); + +on_error: + if (internal_raid->image_name != NULL) + { + memory_free( + internal_raid->image_name); + + internal_raid->image_name = NULL; + } + internal_raid->image_name_size = 0; + + return(-1); +} + diff --git a/libvslvm_raid.h b/libvslvm_raid.h new file mode 100644 index 0000000..807b969 --- /dev/null +++ b/libvslvm_raid.h @@ -0,0 +1,107 @@ +/* + * Raid functions + * + * 20190306 + * liubo + */ + +#if !defined( _LIBVSLVM_INTERNAL_RAID_H ) +#define _LIBVSLVM_INTERNAL_RAID_H + +#include +#include + +#include "libvslvm_extern.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_types.h" + +#if defined( __cplusplus ) +extern "C" { +#endif + + /* eg + raids = [ + "lv0_rmeta_0", "lv0_rimage_0", + "lv0_rmeta_1", "lv0_rimage_1", + "lv0_rmeta_2", "lv0_rimage_2", + "lv0_rmeta_3", "lv0_rimage_3" + ] + */ + + typedef struct libvslvm_internal_raid libvslvm_internal_raid_t; + + struct libvslvm_internal_raid + { + /* The meta name + */ + char *meta_name; + + /* The mata name size + */ + size_t meta_name_size; + + /* The image name + */ + char *image_name; + + /* The image name size + */ + size_t image_name_size; + }; + + int libvslvm_raid_initialize( + libvslvm_raid_t **raid, + libcerror_error_t **error); + + LIBVSLVM_EXTERN \ + int libvslvm_raid_free( + libvslvm_raid_t **raid, + libcerror_error_t **error); + + int libvslvm_internal_raid_free( + libvslvm_internal_raid_t **internal_raid, + libcerror_error_t **error); + + LIBVSLVM_EXTERN \ + int libvslvm_raid_get_meta_name_size( + libvslvm_raid_t *raid, + size_t *meta_name_size, + libcerror_error_t **error); + + LIBVSLVM_EXTERN \ + int libvslvm_raid_get_meta_name( + libvslvm_raid_t *raid, + char *meta_name, + size_t meta_name_size, + libcerror_error_t **error); + + int libvslvm_raid_set_meta_name( + libvslvm_raid_t *raid, + const char *meta_name, + size_t meta_name_size, + libcerror_error_t **error); + + LIBVSLVM_EXTERN \ + int libvslvm_raid_get_image_name_size( + libvslvm_raid_t *raid, + size_t *image_name_size, + libcerror_error_t **error); + + LIBVSLVM_EXTERN \ + int libvslvm_raid_get_image_name( + libvslvm_raid_t *raid, + char *image_name, + size_t image_name_size, + libcerror_error_t **error); + + int libvslvm_raid_set_image_name( + libvslvm_raid_t *raid, + const char *image_name, + size_t image_name_size, + libcerror_error_t **error); +#if defined( __cplusplus ) +} +#endif + +#endif /* !defined( _LIBVSLVM_INTERNAL_RAID_H ) */ + diff --git a/libvslvm_segment.c b/libvslvm_segment.c new file mode 100644 index 0000000..f7e73d2 --- /dev/null +++ b/libvslvm_segment.c @@ -0,0 +1,867 @@ +/* + * Segment functions + * + * Copyright (C) 2014-2023, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "libvslvm_libcdata.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_segment.h" +#include "libvslvm_types.h" +#include "libvslvm_stripe.h" +#include "libvslvm_raid.h" + +/* Creates a segment + * Make sure the value segment is referencing, is set to NULL + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_initialize( + libvslvm_segment_t **segment, + libcerror_error_t **error ) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_initialize"; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + if( *segment != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid segment value already set.", + function ); + + return( -1 ); + } + internal_segment = memory_allocate_structure( + libvslvm_internal_segment_t ); + + if( internal_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create segment.", + function ); + + goto on_error; + } + if( memory_set( + internal_segment, + 0, + sizeof( libvslvm_internal_segment_t ) ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to clear segment.", + function ); + + memory_free( + internal_segment ); + + return( -1 ); + } + if( libcdata_array_initialize( + &( internal_segment->stripes_array ), + 0, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create stripes array.", + function ); + + goto on_error; + } + + if (libcdata_array_initialize( + &(internal_segment->raids_array), + 0, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, + "%s: unable to create raids array.", + function); + + goto on_error; + } + *segment = (libvslvm_segment_t *) internal_segment; + + return( 1 ); + +on_error: + if( internal_segment != NULL ) + { + memory_free( + internal_segment ); + } + return( -1 ); +} + +/* Frees a segment + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_free( + libvslvm_segment_t **segment, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_segment_free"; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + if( *segment != NULL ) + { + *segment = NULL; + } + return( 1 ); +} + +/* Frees a segment + * Returns 1 if successful or -1 on error + */ +int libvslvm_internal_segment_free( + libvslvm_internal_segment_t **internal_segment, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_internal_segment_free"; + int result = 1; + + if( internal_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + if( *internal_segment != NULL ) + { + if( ( *internal_segment )->name != NULL ) + { + memory_free( + ( *internal_segment )->name ); + } + if( libcdata_array_free( + &( ( *internal_segment )->stripes_array ), + (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_internal_stripe_free, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free stripes array.", + function ); + + result = -1; + } + + if (libcdata_array_free( + &((*internal_segment)->raids_array), + (int(*)(intptr_t **, libcerror_error_t **)) &libvslvm_internal_raid_free, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, + "%s: unable to free raids array.", + function); + + result = -1; + } + + memory_free( + *internal_segment ); + + *internal_segment = NULL; + } + return( result ); +} + +/* Sets the name + * Returns 1 if successful or -1 on error + */ +int libvslvm_internal_segment_set_name( + libvslvm_internal_segment_t *internal_segment, + const char *name, + size_t name_size, + libcerror_error_t **error ) +{ + static char *function = "libvslvm_internal_segment_set_name"; + + if( internal_segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + if( internal_segment->name != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid segment - name value already set.", + function ); + + return( -1 ); + } + if( name == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid name.", + function ); + + return( -1 ); + } + if( ( name_size == 0 ) + || ( name_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid name size value out of bounds.", + function ); + + return( -1 ); + } + if( internal_segment->name != NULL ) + { + memory_free( + internal_segment->name ); + + internal_segment->name = NULL; + internal_segment->name_size = 0; + } + internal_segment->name = (char *) memory_allocate( + sizeof( char ) * name_size ); + + if( internal_segment->name == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_INSUFFICIENT, + "%s: unable to create name.", + function ); + + goto on_error; + } + if( memory_copy( + internal_segment->name, + name, + name_size ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy name.", + function ); + + goto on_error; + } + internal_segment->name[ name_size - 1 ] = 0; + + internal_segment->name_size = name_size; + + return( 1 ); + +on_error: + if( internal_segment->name != NULL ) + { + memory_free( + internal_segment->name ); + + internal_segment->name = NULL; + } + internal_segment->name_size = 0; + + return( -1 ); +} + +/* Retrieves the range + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_get_range( + libvslvm_segment_t *segment, + off64_t *offset, + size64_t *size, + libcerror_error_t **error ) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_range"; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + internal_segment = (libvslvm_internal_segment_t *) segment; + + if( offset == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid offset.", + function ); + + return( -1 ); + } + if( size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid size.", + function ); + + return( -1 ); + } + *offset = internal_segment->offset; + *size = internal_segment->size; + + return( 1 ); +} + +/* Retrieves the offset + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_get_offset( + libvslvm_segment_t *segment, + off64_t *offset, + libcerror_error_t **error ) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_offset"; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + internal_segment = (libvslvm_internal_segment_t *) segment; + + if( offset == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid offset.", + function ); + + return( -1 ); + } + *offset = internal_segment->offset; + + return( 1 ); +} + +/* Retrieves the size + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_get_size( + libvslvm_segment_t *segment, + size64_t *size, + libcerror_error_t **error ) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_size"; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + internal_segment = (libvslvm_internal_segment_t *) segment; + + if( size == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid size.", + function ); + + return( -1 ); + } + *size = internal_segment->size; + + return( 1 ); +} + +/* Retrieves the number of stripes + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_get_number_of_stripes( + libvslvm_segment_t *segment, + int *number_of_stripes, + libcerror_error_t **error ) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_number_of_stripes"; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + internal_segment = (libvslvm_internal_segment_t *) segment; + + if( libcdata_array_get_number_of_entries( + internal_segment->stripes_array, + number_of_stripes, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of elements from stripes array.", + function ); + + return( -1 ); + } + return( 1 ); +} + +/* Retrieves a specific stripe + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_get_stripe( + libvslvm_segment_t *segment, + int stripe_index, + libvslvm_stripe_t **stripe, + libcerror_error_t **error ) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_stripe"; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + internal_segment = (libvslvm_internal_segment_t *) segment; + + if( stripe == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid stripe.", + function ); + + return( -1 ); + } + if( *stripe != NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid stripe value already set.", + function ); + + return( -1 ); + } + if( libcdata_array_get_entry_by_index( + internal_segment->stripes_array, + stripe_index, + (intptr_t **) stripe, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve stripe: %d.", + function, + stripe_index ); + + return( -1 ); + } + return( 1 ); +} + +/* Appends a stripe + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_append_stripe( + libvslvm_segment_t *segment, + libvslvm_stripe_t *stripe, + libcerror_error_t **error ) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_append_stripe"; + int entry_index = 0; + + if( segment == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function ); + + return( -1 ); + } + internal_segment = (libvslvm_internal_segment_t *) segment; + + if( stripe == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid stripe.", + function ); + + return( -1 ); + } + if( libcdata_array_append_entry( + internal_segment->stripes_array, + &entry_index, + (intptr_t *) stripe, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append stripe to segment.", + function ); + + return( -1 ); + } + return( 1 ); +} + + + +/* Retrieves the number of raid + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_get_number_of_raids( + libvslvm_segment_t *segment, + int *number_of_raids, + libcerror_error_t **error) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_number_of_raids"; + + if (segment == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function); + + return(-1); + } + internal_segment = (libvslvm_internal_segment_t *)segment; + + if (libcdata_array_get_number_of_entries( + internal_segment->raids_array, + number_of_raids, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve number of elements from raids array.", + function); + + return(-1); + } + return(1); +} + +/* Retrieves a specific raid + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_get_raid( + libvslvm_segment_t *segment, + int raid_index, + libvslvm_raid_t **raid, + libcerror_error_t **error) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_raid"; + + if (segment == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function); + + return(-1); + } + internal_segment = (libvslvm_internal_segment_t *)segment; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + if (*raid != NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, + "%s: invalid raid value already set.", + function); + + return(-1); + } + if (libcdata_array_get_entry_by_index( + internal_segment->raids_array, + raid_index, + (intptr_t **)raid, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_GET_FAILED, + "%s: unable to retrieve raid: %d.", + function, + raid_index); + + return(-1); + } + return(1); +} + +/* Appends a raid + * Returns 1 if successful or -1 on error + */ +int libvslvm_segment_append_raid( + libvslvm_segment_t *segment, + libvslvm_raid_t *raid, + libcerror_error_t **error) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_append_raid"; + int entry_index = 0; + + if (segment == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function); + + return(-1); + } + internal_segment = (libvslvm_internal_segment_t *)segment; + + if (raid == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid raid.", + function); + + return(-1); + } + if (libcdata_array_append_entry( + internal_segment->raids_array, + &entry_index, + (intptr_t *)raid, + error) != 1) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_RUNTIME, + LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, + "%s: unable to append raid to segment.", + function); + + return(-1); + } + return(1); +} + +int libvslvm_segment_get_type(libvslvm_segment_t * segment, uint32_t * type, libcerror_error_t ** error) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_type"; + + if (segment == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function); + + return(-1); + } + internal_segment = (libvslvm_internal_segment_t *)segment; + + if (type == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalidt segment type.", + function); + + return(-1); + } + *type = internal_segment->type; + + return(1); +} + +int libvslvm_segment_get_stripe_size(libvslvm_segment_t * segment, uint32_t * stripe_size, libcerror_error_t ** error) +{ + libvslvm_internal_segment_t *internal_segment = NULL; + static char *function = "libvslvm_segment_get_type"; + + if (segment == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid segment.", + function); + + return(-1); + } + internal_segment = (libvslvm_internal_segment_t *)segment; + + if (stripe_size == NULL) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalidt segment stripe_size.", + function); + + return(-1); + } + *stripe_size = internal_segment->stripe_size; + + return(1); +} + diff --git a/libvslvm_segment.h b/libvslvm_segment.h new file mode 100644 index 0000000..93ff913 --- /dev/null +++ b/libvslvm_segment.h @@ -0,0 +1,198 @@ +/* + * Segment functions + * + * Copyright (C) 2014-2023, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#if !defined( _LIBVSLVM_SEGMENT_H ) +#define _LIBVSLVM_SEGMENT_H + +#include +#include + +#include "libvslvm_extern.h" +#include "libvslvm_libcdata.h" +#include "libvslvm_libcerror.h" +#include "libvslvm_types.h" + +#if defined( __cplusplus ) +extern "C" { +#endif + + /* + * 20190306 + * liubo + * 为了兼容,raid lvm情况,当前添加raid类型枚举 + */ +#define STRIPED "striped" +#define RAID1 "raid1" //RAID1 mirroring +#define RAID4 "raid4" //RAID4 dedicated parity disk +#define RAID5 "raid5" //Same as raid5_ls +#define RAID5_LA "raid5_la" //RAID5 left asymmetric. Rotating parity 0 with data continuation +#define RAID5_RA "raid5_ra" //RAID5 right asymmetric. Rotating parity N with data continuation +#define RAID5_LS "raid5_ls" //RAID5 left symmetric. Rotating parity 0 with data restart +#define RAID5_RS "raid5_rs" //RAID5 right symmetric. Rotating parity N with data restart +#define RAID6 "raid6" //Same as raid6_zr +#define RAID6_ZR "raid6_zr" //RAID6 zero restart Rotating parity zero (left-to-right) with data restart +#define RAID6_NR "raid6_nr" //RAID6 N restart Rotating parity N (left-to-right) with data restart +#define RAID6_NC "raid6_nc" //RAID6 N continue Rotating parity N (left-to-right) with data continuation +#define RAID10 "raid10" //(Red Hat Enterprise Linux 6.4 and later Striped mirrors Striping of mirror sets + + +typedef struct libvslvm_internal_segment libvslvm_internal_segment_t; + +struct libvslvm_internal_segment +{ + /* The name + */ + char *name; + + /* The name size + */ + size_t name_size; + + /* The stripes array + */ + libcdata_array_t *stripes_array; + + /* The offset + */ + off64_t offset; + + /* The size + */ + size64_t size; + + /************************************************************ + 20190306 liubo 考虑到兼容热raid的情况,做以下添加 + ****************************************************************/ + /* the type stripe or raids,use E_SEGMENT_TYPE + */ + int type; + + /*the stripe size ;only type = RAIDS ,the value makeing sense, sec; + */ + uint32_t stripe_size; + + /*the raids array + */ + libcdata_array_t* raids_array; +}; + +int libvslvm_segment_initialize( + libvslvm_segment_t **segment, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_free( + libvslvm_segment_t **segment, + libcerror_error_t **error ); + +int libvslvm_internal_segment_free( + libvslvm_internal_segment_t **internal_segment, + libcerror_error_t **error ); + +int libvslvm_internal_segment_set_name( + libvslvm_internal_segment_t *internal_segment, + const char *name, + size_t name_size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_range( + libvslvm_segment_t *segment, + off64_t *offset, + size64_t *size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_offset( + libvslvm_segment_t *segment, + off64_t *offset, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_size( + libvslvm_segment_t *segment, + size64_t *size, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_number_of_stripes( + libvslvm_segment_t *segment, + int *number_of_stripes, + libcerror_error_t **error ); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_stripe( + libvslvm_segment_t *segment, + int stripe_index, + libvslvm_stripe_t **stripe, + libcerror_error_t **error ); + +int libvslvm_segment_append_stripe( + libvslvm_segment_t *segment, + libvslvm_stripe_t *stripe, + libcerror_error_t **error ); + +/************************************************************************* +* 20190306 liubo raid +**************************************************************************/ +//int libvslvm_segment_set_type( +// libvslvm_segment_t *segment, +// const char *type, +// size_t type_size, +// libcerror_error_t **error); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_number_of_raids( + libvslvm_segment_t *segment, + int *number_of_raids, + libcerror_error_t **error); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_raid( + libvslvm_segment_t *segment, + int raid_index, + libvslvm_raid_t **raid, + libcerror_error_t **error); + +int libvslvm_segment_append_raid( + libvslvm_segment_t *segment, + libvslvm_raid_t *raid, + libcerror_error_t **error); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_type( + libvslvm_segment_t *segment, + uint32_t *type, + libcerror_error_t **error); + +LIBVSLVM_EXTERN \ +int libvslvm_segment_get_stripe_size( + libvslvm_segment_t *segment, + uint32_t *stripe_size, + libcerror_error_t **error); + + +#if defined( __cplusplus ) +} +#endif + +#endif /* !defined( _LIBVSLVM_SEGMENT_H ) */ + diff --git a/libvslvm_types.h b/libvslvm_types.h new file mode 100644 index 0000000..13f81e9 --- /dev/null +++ b/libvslvm_types.h @@ -0,0 +1,59 @@ +/* + * The internal type definitions + * + * Copyright (C) 2014-2018, Joachim Metz + * + * Refer to AUTHORS for acknowledgements. + * + * This software is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this software. If not, see . + */ + +#if !defined( _LIBVSLVM_INTERNAL_TYPES_H ) +#define _LIBVSLVM_INTERNAL_TYPES_H + +#include +#include + +/* Define HAVE_LOCAL_LIBVSLVM for local use of libvslvm + * The definitions in are copied here + * for local use of libvslvm + */ +#if defined( HAVE_LOCAL_LIBVSLVM ) + +/* The following type definitions hide internal data structures + */ +#if defined( HAVE_DEBUG_OUTPUT ) && !defined( WINAPI ) +typedef struct libvslvm_handle {} libvslvm_handle_t; +typedef struct libvslvm_logical_volume {} libvslvm_logical_volume_t; +typedef struct libvslvm_physical_volume {} libvslvm_physical_volume_t; +typedef struct libvslvm_segment {} libvslvm_segment_t; +typedef struct libvslvm_stripe {} libvslvm_stripe_t; +typedef struct libvslvm_volume_group {} libvslvm_volume_group_t; +typedef struct libvslvm_raid {} libvslvm_raid_t; + +#else +typedef intptr_t libvslvm_handle_t; +typedef intptr_t libvslvm_logical_volume_t; +typedef intptr_t libvslvm_physical_volume_t; +typedef intptr_t libvslvm_segment_t; +typedef intptr_t libvslvm_stripe_t; +typedef intptr_t libvslvm_volume_group_t; +typedef intptr_t libvslvm_raid_t; + +#endif /* defined( HAVE_DEBUG_OUTPUT ) && !defined( WINAPI ) */ + +#endif /* defined( HAVE_LOCAL_LIBVSLVM ) */ + +#endif /* !defined( _LIBVSLVM_INTERNAL_TYPES_H ) */ +