/* Resizes an array * Returns 1 if successful or -1 on error */ int libcdata_array_resize( libcdata_array_t *array, int number_of_entries, int (*entry_free_function)( intptr_t **entry, libcerror_error_t **error ), libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; static char *function = "libcdata_array_resize"; int result = 1; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_write( internal_array->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( libcdata_internal_array_resize( internal_array, number_of_entries, entry_free_function, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); result = -1; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_write( internal_array->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( result ); }
/* Reverses the order of the entries in the array * Returns 1 if successful or -1 on error */ int libcdata_array_reverse( libcdata_array_t *array, libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; intptr_t *entry = NULL; static char *function = "libcdata_array_reverse"; int entry_iterator = 0; int reverse_entry_iterator = 0; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; if( internal_array->entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid array - missing entries.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_write( internal_array->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( internal_array->number_of_entries > 1 ) { reverse_entry_iterator = internal_array->number_of_entries - 1; while( entry_iterator < reverse_entry_iterator ) { entry = internal_array->entries[ reverse_entry_iterator ]; internal_array->entries[ reverse_entry_iterator ] = internal_array->entries[ entry_iterator ]; internal_array->entries[ entry_iterator ] = entry; entry_iterator++; reverse_entry_iterator--; } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_write( internal_array->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( 1 ); }
/* Appends an entry * Sets the entry index to the newly appended entry * Returns 1 if successful or -1 on error */ int libcdata_array_append_entry( libcdata_array_t *array, int *entry_index, intptr_t *entry, libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; static char *function = "libcdata_array_append_entry"; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; if( entry_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry index.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_write( internal_array->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 *entry_index = internal_array->number_of_entries; if( libcdata_internal_array_resize( internal_array, internal_array->number_of_entries + 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); goto on_error; } internal_array->entries[ *entry_index ] = entry; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_write( internal_array->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( 1 ); on_error: #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) libcthreads_read_write_lock_release_for_write( internal_array->read_write_lock, NULL ); #endif return( -1 ); }
/* Inserts an entry in the array * * Uses the entry_compare_function to determine the order of the entries * The entry_compare_function should return LIBCDATA_COMPARE_LESS, * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error * * Duplicate entries are allowed by default and inserted after the last duplicate entry. * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES * * Returns 1 if successful, 0 if the node already exists or -1 on error */ int libcdata_array_insert_entry( libcdata_array_t *array, int *entry_index, intptr_t *entry, int (*entry_compare_function)( intptr_t *first_entry, intptr_t *second_entry, libcerror_error_t **error ), uint8_t insert_flags, libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; static char *function = "libcdata_tree_node_insert_node"; int compare_result = 0; int entry_iterator = 0; int result = 1; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; if( entry_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry index.", function ); return( -1 ); } if( entry_compare_function == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry compare function.", function ); return( -1 ); } if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported insert flags: 0x%02" PRIx8 ".", function, insert_flags ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_write( internal_array->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( internal_array->entries != NULL ) { for( entry_iterator = 0; entry_iterator < internal_array->number_of_entries; entry_iterator++ ) { compare_result = entry_compare_function( entry, internal_array->entries[ entry_iterator ], error ); if( compare_result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to compare entry: %d.", function, entry_iterator ); goto on_error; } else if( compare_result == LIBCDATA_COMPARE_EQUAL ) { if( ( insert_flags & LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) != 0 ) { result = 0; break; } } else if( compare_result == LIBCDATA_COMPARE_LESS ) { result = 1; break; } else if( compare_result != LIBCDATA_COMPARE_GREATER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported entry compare function return value: %d.", function, compare_result ); goto on_error; } } } if( result != 0 ) { if( ( internal_array->entries != NULL ) && ( compare_result == LIBCDATA_COMPARE_LESS ) ) { *entry_index = entry_iterator; if( libcdata_internal_array_resize( internal_array, internal_array->number_of_entries + 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); goto on_error; } for( entry_iterator = internal_array->number_of_entries - 1; entry_iterator > *entry_index; entry_iterator-- ) { internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ]; } internal_array->entries[ *entry_index ] = entry; } else { *entry_index = internal_array->number_of_entries; if( libcdata_internal_array_resize( internal_array, internal_array->number_of_entries + 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); goto on_error; } if( internal_array->entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid array - missing entries.", function ); goto on_error; } internal_array->entries[ *entry_index ] = entry; } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_write( internal_array->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( result ); on_error: #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) libcthreads_read_write_lock_release_for_write( internal_array->read_write_lock, NULL ); #endif return( -1 ); }
/* Opens a volume for reading * Returns 1 if successful or -1 on error */ int libvshadow_volume_open_read( libvshadow_internal_volume_t *internal_volume, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { libvshadow_store_descriptor_t *last_store_descriptor = NULL; libvshadow_store_descriptor_t *store_descriptor = NULL; static char *function = "libvshadow_volume_open_read"; off64_t catalog_offset = 0; int number_of_store_descriptors = 0; int store_descriptor_index = 0; if( internal_volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } if( internal_volume->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid volume - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_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 defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading NTFS volume header:\n" ); } #endif if( libvshadow_io_handle_read_ntfs_volume_header( internal_volume->io_handle, file_io_handle, &( internal_volume->size ), error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read NTFS volume header.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading VSS volume header:\n" ); } #endif if( libvshadow_io_handle_read_volume_header( internal_volume->io_handle, file_io_handle, (off64_t) 0x1e00, &catalog_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume header.", function ); goto on_error; } if( catalog_offset > 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading VSS catalog:\n" ); } #endif if( libvshadow_io_handle_read_catalog( internal_volume->io_handle, file_io_handle, catalog_offset, &( internal_volume->size ), internal_volume->store_descriptors_array, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read catalog.", function ); goto on_error; } if( libcdata_array_get_number_of_entries( internal_volume->store_descriptors_array, &number_of_store_descriptors, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of store descriptors from array.", function ); goto on_error; } for( store_descriptor_index = 0; store_descriptor_index < number_of_store_descriptors; store_descriptor_index++ ) { if( libcdata_array_get_entry_by_index( internal_volume->store_descriptors_array, store_descriptor_index, (intptr_t **) &store_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve store descriptor: %d.", function, store_descriptor_index ); goto on_error; } store_descriptor->index = store_descriptor_index; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "Reading VSS store: %02d:\n", store_descriptor->index ); } #endif if( libvshadow_store_descriptor_read_store_header( store_descriptor, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read store: %d header.", function, store_descriptor->index ); goto on_error; } store_descriptor->previous_store_descriptor = last_store_descriptor; if( last_store_descriptor != NULL ) { last_store_descriptor->next_store_descriptor = store_descriptor; } last_store_descriptor = store_descriptor; store_descriptor = NULL; } } #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_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( 1 ); on_error: internal_volume->size = 0; libcdata_array_empty( internal_volume->store_descriptors_array, (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_store_descriptor_free, NULL ); #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) libcthreads_read_write_lock_release_for_write( internal_volume->read_write_lock, NULL ); #endif return( -1 ); }
/* Sets a specific entry in the array * Returns 1 if successful or -1 on error */ int libcdata_array_set_entry_by_index( libcdata_array_t *array, int entry_index, intptr_t *entry, libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; static char *function = "libcdata_array_set_entry_by_index"; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; if( internal_array->entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid array - missing entries.", function ); return( -1 ); } if( ( entry_index < 0 ) || ( entry_index >= internal_array->number_of_entries ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid entry index value out of bounds.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_write( internal_array->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 internal_array->entries[ entry_index ] = entry; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_write( internal_array->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( 1 ); }
/* Opens a volume using a Basic File IO (bfio) handle * Returns 1 if successful or -1 on error */ int libvshadow_volume_open_file_io_handle( libvshadow_volume_t *volume, libbfio_handle_t *file_io_handle, int access_flags, libcerror_error_t **error ) { libvshadow_internal_volume_t *internal_volume = NULL; static char *function = "libvshadow_volume_open_file_io_handle"; int bfio_access_flags = 0; int file_io_handle_is_open = 0; int file_io_handle_opened_in_library = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libvshadow_internal_volume_t *) volume; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( ( access_flags & LIBVSHADOW_ACCESS_FLAG_READ ) != 0 ) { bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ; } file_io_handle_is_open = libbfio_handle_is_open( file_io_handle, error ); if( file_io_handle_is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to determine if file IO handle is open.", function ); goto on_error; } else if( file_io_handle_is_open == 0 ) { if( libbfio_handle_open( file_io_handle, bfio_access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file IO handle.", function ); goto on_error; } file_io_handle_opened_in_library = 1; } if( libvshadow_volume_open_read( internal_volume, file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from file IO handle.", function ); goto on_error; } #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_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 internal_volume->file_io_handle = file_io_handle; internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library; #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_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( 1 ); on_error: if( file_io_handle_opened_in_library != 0 ) { libbfio_handle_close( file_io_handle, NULL ); } return( -1 ); }
/* Closes a volume * Returns 0 if successful or -1 on error */ int libvshadow_volume_close( libvshadow_volume_t *volume, libcerror_error_t **error ) { libvshadow_internal_volume_t *internal_volume = NULL; static char *function = "libvshadow_volume_close"; int result = 0; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libvshadow_internal_volume_t *) volume; if( internal_volume->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid volume - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_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 defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( internal_volume->file_io_handle_created_in_library != 0 ) { if( libvshadow_debug_print_read_offsets( internal_volume->file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print the read offsets.", function ); } } } #endif if( internal_volume->file_io_handle_opened_in_library != 0 ) { if( libbfio_handle_close( internal_volume->file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file IO handle.", function ); result = -1; } internal_volume->file_io_handle_opened_in_library = 0; } if( internal_volume->file_io_handle_created_in_library != 0 ) { if( libbfio_handle_free( &( internal_volume->file_io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free file IO handle.", function ); result = -1; } internal_volume->file_io_handle_created_in_library = 0; } internal_volume->file_io_handle = NULL; internal_volume->size = 0; if( libvshadow_io_handle_clear( internal_volume->io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to clear IO handle.", function ); result = -1; } if( libcdata_array_empty( internal_volume->store_descriptors_array, (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_store_descriptor_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to empty store descriptors array.", function ); result = -1; } #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_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( result ); }
/* Opens a volume * Returns 1 if successful or -1 on error */ int libvshadow_volume_open_wide( libvshadow_volume_t *volume, const wchar_t *filename, int access_flags, libcerror_error_t **error ) { libbfio_handle_t *file_io_handle = NULL; libvshadow_internal_volume_t *internal_volume = NULL; static char *function = "libvshadow_volume_open_wide"; if( volume == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid volume.", function ); return( -1 ); } internal_volume = (libvshadow_internal_volume_t *) volume; if( filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid filename.", function ); return( -1 ); } if( ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags.", function ); return( -1 ); } if( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: write access currently not supported.", function ); return( -1 ); } if( libbfio_file_initialize( &file_io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create file IO handle.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libbfio_handle_set_track_offsets_read( file_io_handle, 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set track offsets read in file IO handle.", function ); goto on_error; } #endif if( libbfio_file_set_name_wide( file_io_handle, filename, libcstring_wide_string_length( filename ) + 1, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set filename in file IO handle.", function ); goto on_error; } if( libvshadow_volume_open_file_io_handle( volume, file_io_handle, access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open volume: %ls.", function, filename ); goto on_error; } #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_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 internal_volume->file_io_handle_created_in_library = 1; #if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_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( 1 ); on_error: if( file_io_handle != NULL ) { libbfio_handle_free( &file_io_handle, NULL ); } return( -1 ); }
/* Writes a buffer to the data chunk * It applies compression if necessary and calculated the chunk checksum * This function should be used before libewf_handle_write_data_chunk * Returns the number of bytes written, 0 when no longer data can be written or -1 on error */ ssize_t libewf_data_chunk_write_buffer( libewf_data_chunk_t *data_chunk, const void *buffer, size_t buffer_size, libcerror_error_t **error ) { libewf_internal_data_chunk_t *internal_data_chunk = NULL; static char *function = "libewf_data_chunk_write_buffer"; ssize_t write_count = 0; if( data_chunk == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data chunk.", function ); return( -1 ); } internal_data_chunk = (libewf_internal_data_chunk_t *) data_chunk; if( internal_data_chunk->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data chunk - missing IO handle.", function ); return( -1 ); } if( internal_data_chunk->write_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data chunk - missing write IO handle.", function ); return( -1 ); } #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_data_chunk->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( internal_data_chunk->chunk_data != NULL ) { if( libewf_chunk_data_free( &( internal_data_chunk->chunk_data ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free chunk data.", function ); goto on_error; } } if( libewf_chunk_data_initialize( &( internal_data_chunk->chunk_data ), internal_data_chunk->io_handle->chunk_size, 0, 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; } write_count = libewf_chunk_data_write_buffer( internal_data_chunk->chunk_data, buffer, buffer_size, error ); if( write_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write buffer to chunk data.", function ); goto on_error; } internal_data_chunk->data_size = buffer_size; if( libewf_chunk_data_pack( internal_data_chunk->chunk_data, internal_data_chunk->io_handle, internal_data_chunk->write_io_handle->compressed_zero_byte_empty_block, internal_data_chunk->write_io_handle->compressed_zero_byte_empty_block_size, internal_data_chunk->write_io_handle->pack_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to pack chunk: %" PRIu64 " data.", function, internal_data_chunk->chunk_index ); goto on_error; } #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_data_chunk->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( write_count ); on_error: #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) libcthreads_read_write_lock_release_for_write( internal_data_chunk->read_write_lock, NULL ); #endif return( -1 ); }
/* Reads a buffer from the data chunk * It applies decompression if necessary and validates the chunk checksum * This function should be used after libewf_handle_read_data_chunk * Returns the number of bytes read, 0 when no longer data can be read or -1 on error */ ssize_t libewf_data_chunk_read_buffer( libewf_data_chunk_t *data_chunk, void *buffer, size_t buffer_size, libcerror_error_t **error ) { libewf_internal_data_chunk_t *internal_data_chunk = NULL; static char *function = "libewf_data_chunk_read_buffer"; ssize_t read_count = 0; if( data_chunk == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data chunk.", function ); return( -1 ); } internal_data_chunk = (libewf_internal_data_chunk_t *) data_chunk; if( internal_data_chunk->chunk_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid data chunk - missing chunk data.", function ); return( -1 ); } #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_data_chunk->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( ( internal_data_chunk->chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_PACKED ) != 0 ) { /* TODO optimize to unpack directly to buffer */ if( libewf_chunk_data_unpack( internal_data_chunk->chunk_data, internal_data_chunk->io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to unpack chunk: %" PRIu64 " data.", function, internal_data_chunk->chunk_index ); goto on_error; } } read_count = libewf_chunk_data_read_buffer( internal_data_chunk->chunk_data, buffer, buffer_size, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read chunk: %" PRIu64 " data.", function, internal_data_chunk->chunk_index ); goto on_error; } #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_data_chunk->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_LIBEWF_MULTI_THREAD_SUPPORT ) libcthreads_read_write_lock_release_for_write( internal_data_chunk->read_write_lock, NULL ); #endif return( -1 ); }
/* Sets the chunk data in the data chunk * Returns 1 if successful or -1 on error */ int libewf_internal_data_chunk_set_chunk_data( libewf_internal_data_chunk_t *internal_data_chunk, uint64_t chunk_index, libewf_chunk_data_t *chunk_data, libcerror_error_t **error ) { static char *function = "libewf_internal_data_chunk_set_chunk_data"; if( internal_data_chunk == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data chunk.", function ); return( -1 ); } if( chunk_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid chunk data.", function ); return( -1 ); } #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_grab_for_write( internal_data_chunk->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( internal_data_chunk->chunk_data != NULL ) { if( libewf_chunk_data_free( &( internal_data_chunk->chunk_data ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free chunk data.", function ); goto on_error; } } if( libewf_chunk_data_clone( &( internal_data_chunk->chunk_data ), chunk_data, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone chunk data.", function ); goto on_error; } internal_data_chunk->chunk_index = chunk_index; #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) if( libcthreads_read_write_lock_release_for_write( internal_data_chunk->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( 1 ); on_error: #if defined( HAVE_LIBEWF_MULTI_THREAD_SUPPORT ) libcthreads_read_write_lock_release_for_write( internal_data_chunk->read_write_lock, NULL ); #endif return( -1 ); }
/* Removes an entry * Returns 1 if successful or -1 on error */ int libcdata_array_remove_entry( libcdata_array_t *array, int entry_index, intptr_t **entry, libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; static char *function = "libcdata_array_remove_entry"; int entry_iterator = 0; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; if( ( entry_index < 0 ) || ( entry_index >= internal_array->number_of_entries ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid entry index value out of bounds.", function ); return( -1 ); } if( entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_write( internal_array->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 *entry = internal_array->entries[ entry_index ]; if( entry_index == ( internal_array->number_of_entries - 1 ) ) { internal_array->entries[ entry_index ] = NULL; } else { for( entry_iterator = ( internal_array->number_of_entries - 1 ); entry_iterator > entry_index; entry_iterator-- ) { internal_array->entries[ entry_iterator - 1 ] = internal_array->entries[ entry_iterator ]; internal_array->entries[ entry_iterator ] = NULL; } } if( libcdata_internal_array_resize( internal_array, internal_array->number_of_entries - 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); goto on_error; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_write( internal_array->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( 1 ); on_error: #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) libcthreads_read_write_lock_release_for_write( internal_array->read_write_lock, NULL ); #endif return( -1 ); }