/* * The handle functions * * Copyright (C) 2009-2022, 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 #if defined( HAVE_UNISTD_H ) #include #endif #include "libbfio_definitions.h" #include "libbfio_handle.h" #include "libbfio_libcdata.h" #include "libbfio_libcerror.h" /* Creates a handle * Make sure the value handle is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libbfio_handle_initialize( libbfio_handle_t **handle, intptr_t *io_handle, int (*free_io_handle)( intptr_t **io_handle, libcerror_error_t **error ), int (*clone_io_handle)( intptr_t **destination_io_handle, intptr_t *source_io_handle, libcerror_error_t **error ), int (*open)( intptr_t *io_handle, int access_flags, libcerror_error_t **error ), int (*close)( intptr_t *io_handle, libcerror_error_t **error ), ssize_t (*read)( intptr_t *io_handle, uint8_t *buffer, size_t size, libcerror_error_t **error ), ssize_t (*write)( intptr_t *io_handle, const uint8_t *buffer, size_t size, libcerror_error_t **error ), off64_t (*seek_offset)( intptr_t *io_handle, off64_t offset, int whence, libcerror_error_t **error ), int (*exists)( intptr_t *io_handle, libcerror_error_t **error ), int (*is_open)( intptr_t *io_handle, libcerror_error_t **error ), int (*get_size)( intptr_t *io_handle, size64_t *size, libcerror_error_t **error ), uint8_t flags, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_initialize"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } if( *handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid handle value already set.", function ); return( -1 ); } internal_handle = memory_allocate_structure( libbfio_internal_handle_t ); if( internal_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create handle.", function ); goto on_error; } if( memory_set( internal_handle, 0, sizeof( libbfio_internal_handle_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear handle.", function ); memory_free( internal_handle ); return( -1 ); } if( libcdata_range_list_initialize( &( internal_handle->offsets_read ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create read offsets list.", function ); goto on_error; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_initialize( &( internal_handle->read_write_lock ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to intialize read/write lock.", function ); goto on_error; } #endif internal_handle->io_handle = io_handle; internal_handle->flags = flags; internal_handle->free_io_handle = free_io_handle; internal_handle->clone_io_handle = clone_io_handle; internal_handle->open = open; internal_handle->close = close; internal_handle->read = read; internal_handle->write = write; internal_handle->seek_offset = seek_offset; internal_handle->exists = exists; internal_handle->is_open = is_open; internal_handle->get_size = get_size; *handle = (libbfio_handle_t *) internal_handle; return( 1 ); on_error: if( internal_handle != NULL ) { if( internal_handle->offsets_read != NULL ) { libcdata_range_list_free( &( internal_handle->offsets_read ), NULL, NULL ); } memory_free( internal_handle ); } return( -1 ); } /* Frees a handle * Returns 1 if successful or -1 on error */ int libbfio_handle_free( libbfio_handle_t **handle, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_free"; int is_open = 0; int result = 1; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } if( *handle != NULL ) { internal_handle = (libbfio_internal_handle_t *) *handle; *handle = NULL; if( internal_handle->is_open != NULL ) { is_open = internal_handle->is_open( internal_handle->io_handle, error ); if( is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to determine if handle is open.", function ); result = -1; } } if( is_open != 0 ) { if( internal_handle->close != NULL ) { if( internal_handle->close( internal_handle->io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close handle.", function ); result = -1; } } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_free( &( internal_handle->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 if( ( internal_handle->flags & LIBBFIO_FLAG_IO_HANDLE_MANAGED ) != 0 ) { if( internal_handle->io_handle != NULL ) { if( internal_handle->free_io_handle == NULL ) { memory_free( internal_handle->io_handle ); } else if( internal_handle->free_io_handle( &( internal_handle->io_handle ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free IO handle.", function ); result = -1; } } } if( internal_handle->offsets_read != NULL ) { if( libcdata_range_list_free( &( internal_handle->offsets_read ), NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free read offsets list.", function ); result = -1; } } memory_free( internal_handle ); } return( result ); } /* Clones (duplicates) the handle * The values in the offsets read list are not duplicated * Returns 1 if successful or -1 on error */ int libbfio_handle_clone( libbfio_handle_t **destination_handle, libbfio_handle_t *source_handle, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_source_handle = NULL; intptr_t *destination_io_handle = NULL; static char *function = "libbfio_handle_clone"; uint8_t destination_flags = 0; if( destination_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid destination handle.", function ); return( -1 ); } if( *destination_handle != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: destination handle already set.", function ); return( -1 ); } if( source_handle == NULL ) { *destination_handle = NULL; return( 1 ); } internal_source_handle = (libbfio_internal_handle_t *) source_handle; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_source_handle->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( internal_source_handle->io_handle != NULL ) { if( ( internal_source_handle->flags & LIBBFIO_FLAG_IO_HANDLE_CLONE_BY_REFERENCE ) != 0 ) { destination_io_handle = internal_source_handle->io_handle; destination_flags = LIBBFIO_FLAG_IO_HANDLE_CLONE_BY_REFERENCE; } else { if( internal_source_handle->clone_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing clone IO handle function.", function ); goto on_error; } if( internal_source_handle->clone_io_handle( &destination_io_handle, internal_source_handle->io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to clone IO handle.", function ); goto on_error; } destination_flags = LIBBFIO_FLAG_IO_HANDLE_MANAGED; } } if( libbfio_handle_initialize( destination_handle, destination_io_handle, internal_source_handle->free_io_handle, internal_source_handle->clone_io_handle, internal_source_handle->open, internal_source_handle->close, internal_source_handle->read, internal_source_handle->write, internal_source_handle->seek_offset, internal_source_handle->exists, internal_source_handle->is_open, internal_source_handle->get_size, destination_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create destination handle.", function ); goto on_error; } destination_io_handle = NULL; if( internal_source_handle->access_flags != 0 ) { if( libbfio_handle_open( *destination_handle, internal_source_handle->access_flags, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open destination handle.", function ); goto on_error; } if( libbfio_handle_seek_offset( *destination_handle, internal_source_handle->current_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset in destination handle.", function ); goto on_error; } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_source_handle->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 ); libbfio_handle_free( destination_handle, NULL ); return( -1 ); } #endif return( 1 ); on_error: if( ( destination_io_handle != NULL ) && ( ( destination_flags & LIBBFIO_FLAG_IO_HANDLE_MANAGED ) != 0 ) ) { if( internal_source_handle->free_io_handle == NULL ) { memory_free( destination_io_handle ); } else { internal_source_handle->free_io_handle( &destination_io_handle, NULL ); } } if( destination_handle != NULL ) { libbfio_handle_free( destination_handle, NULL ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) libcthreads_read_write_lock_release_for_read( internal_source_handle->read_write_lock, NULL ); #endif return( -1 ); } /* Opens the handle * Returns 1 if successful or -1 on error */ int libbfio_handle_open( libbfio_handle_t *handle, int access_flags, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_open"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } if( internal_handle->open == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing open function.", function ); return( -1 ); } if( ( ( access_flags & LIBBFIO_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBBFIO_ACCESS_FLAG_WRITE ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported access flags: 0x%02x.", function, access_flags ); return( -1 ); } if( ( internal_handle->open_on_demand != 0 ) && ( ( access_flags & LIBBFIO_ACCESS_FLAG_WRITE ) != 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: open on demand cannot be used in combination with write access.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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_handle->open_on_demand == 0 ) { if( internal_handle->open( internal_handle->io_handle, access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open handle.", function ); goto on_error; } } internal_handle->access_flags = access_flags; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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_LIBBFIO ) libcthreads_read_write_lock_release_for_write( internal_handle->read_write_lock, NULL ); #endif return( -1 ); } /* Reopens the handle * Returns 1 if successful or -1 on error */ int libbfio_handle_reopen( libbfio_handle_t *handle, int access_flags, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_reopen"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } if( internal_handle->close == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing close function.", function ); return( -1 ); } if( internal_handle->open == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing open function.", function ); return( -1 ); } if( internal_handle->seek_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing seek offset function.", function ); return( -1 ); } if( ( ( access_flags & LIBBFIO_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBBFIO_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 defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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 /* Only reopen if the access flags have changed */ if( internal_handle->access_flags != access_flags ) { if( internal_handle->close( internal_handle->io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close handle.", function ); goto on_error; } if( internal_handle->open_on_demand == 0 ) { if( internal_handle->open( internal_handle->io_handle, access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open handle.", function ); goto on_error; } } internal_handle->access_flags = access_flags; if( internal_handle->open_on_demand == 0 ) { /* Seek the previous file offset only when at least reading the file */ if( ( internal_handle->access_flags & LIBBFIO_ACCESS_FLAG_READ ) != 0 ) { if( internal_handle->seek_offset( internal_handle->io_handle, internal_handle->current_offset, SEEK_CUR, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset in handle.", function ); goto on_error; } } } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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_LIBBFIO ) libcthreads_read_write_lock_release_for_write( internal_handle->read_write_lock, NULL ); #endif return( -1 ); } /* Closes the handle * Returns 0 if successful or -1 on error */ int libbfio_handle_close( libbfio_handle_t *handle, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_close"; int is_open = 1; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } if( internal_handle->close == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing close function.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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_handle->open_on_demand != 0 ) { if( internal_handle->is_open == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing is open function.", function ); goto on_error; } is_open = internal_handle->is_open( internal_handle->io_handle, error ); if( is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to determine if handle is open.", function ); goto on_error; } } if( is_open != 0 ) { if( internal_handle->close( internal_handle->io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close handle.", function ); goto on_error; } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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( 0 ); on_error: #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) libcthreads_read_write_lock_release_for_write( internal_handle->read_write_lock, NULL ); #endif return( -1 ); } /* Reads data at the current offset into the buffer * This function is not multi-thread safe acquire write lock before call * Returns the number of bytes read if successful, or -1 on error */ ssize_t libbfio_internal_handle_read_buffer( libbfio_internal_handle_t *internal_handle, uint8_t *buffer, size_t size, libcerror_error_t **error ) { static char *function = "libbfio_internal_handle_read_buffer"; ssize_t read_count = 0; int is_open = 0; int result = 0; if( internal_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } if( internal_handle->read == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing read function.", function ); return( -1 ); } if( buffer == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid buffer.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } if( internal_handle->open_on_demand != 0 ) { if( internal_handle->is_open == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing is open function.", function ); return( -1 ); } if( internal_handle->open == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing open function.", function ); return( -1 ); } if( internal_handle->seek_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing seek offset function.", function ); return( -1 ); } is_open = internal_handle->is_open( internal_handle->io_handle, error ); if( is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to determine if handle is open.", function ); return( -1 ); } else if( is_open == 0 ) { if( internal_handle->open( internal_handle->io_handle, internal_handle->access_flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open handle on demand.", function ); return( -1 ); } if( internal_handle->seek_offset( internal_handle->io_handle, internal_handle->current_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek current offset: %" PRIi64 " in handle.", function, internal_handle->current_offset ); return( -1 ); } } } read_count = internal_handle->read( internal_handle->io_handle, buffer, size, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read from handle.", function ); return( -1 ); } if( internal_handle->track_offsets_read != 0 ) { result = libcdata_range_list_insert_range( internal_handle->offsets_read, (uint64_t) internal_handle->current_offset, (uint64_t) read_count, NULL, NULL, NULL, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to insert offset range to offsets read table.", function ); return( -1 ); } } internal_handle->current_offset += (off64_t) read_count; if( internal_handle->open_on_demand != 0 ) { if( internal_handle->close == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing close function.", function ); return( -1 ); } if( internal_handle->close( internal_handle->io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to close handle on demand.", function ); return( -1 ); } } return( read_count ); } /* Reads data at the current offset into the buffer * Returns the number of bytes read if successful, or -1 on error */ ssize_t libbfio_handle_read_buffer( libbfio_handle_t *handle, uint8_t *buffer, size_t size, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_read_buffer"; ssize_t read_count = 0; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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 = libbfio_internal_handle_read_buffer( internal_handle, buffer, size, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read buffer.", function ); read_count = -1; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 data at a specific offset into the buffer * Returns the number of bytes read if successful, or -1 on error */ ssize_t libbfio_handle_read_buffer_at_offset( libbfio_handle_t *handle, uint8_t *buffer, size_t size, off64_t offset, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_read_buffer_at_offset"; ssize_t read_count = 0; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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( libbfio_internal_handle_seek_offset( internal_handle, offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset: %" PRIi64 " (0x%08" PRIx64 ") in handle.", function, offset, offset ); read_count = -1; } else { read_count = libbfio_internal_handle_read_buffer( internal_handle, buffer, size, error ); if( read_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read buffer.", function ); read_count = -1; } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 ); } /* Writes data at the current offset from the buffer * This function is not multi-thread safe acquire write lock before call * Returns the number of bytes written if successful, or -1 on error */ ssize_t libbfio_internal_handle_write_buffer( libbfio_internal_handle_t *internal_handle, const uint8_t *buffer, size_t size, libcerror_error_t **error ) { static char *function = "libbfio_internal_handle_write_buffer"; ssize_t write_count = 0; if( internal_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } if( internal_handle->write == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing write function.", function ); return( -1 ); } if( buffer == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid buffer.", function ); return( -1 ); } if( size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } write_count = internal_handle->write( internal_handle->io_handle, buffer, size, error ); if( write_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write to handle.", function ); return( -1 ); } internal_handle->current_offset += (off64_t) write_count; if( (size64_t) internal_handle->current_offset > internal_handle->size ) { internal_handle->size = (size64_t) internal_handle->current_offset; } return( write_count ); } /* Writes data at the current offset from the buffer * Returns the number of bytes written if successful, or -1 on error */ ssize_t libbfio_handle_write_buffer( libbfio_handle_t *handle, const uint8_t *buffer, size_t size, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_write_buffer"; ssize_t write_count = 0; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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 write_count = libbfio_internal_handle_write_buffer( internal_handle, buffer, size, error ); if( write_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write to handle.", function ); write_count = -1; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 ); } /* Writes data at a specific offset from the buffer * Returns the number of bytes written if successful, or -1 on error */ ssize_t libbfio_handle_write_buffer_at_offset( libbfio_handle_t *handle, const uint8_t *buffer, size_t size, off64_t offset, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_write_buffer_at_offset"; ssize_t write_count = 0; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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( libbfio_internal_handle_seek_offset( internal_handle, offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset: %" PRIi64 " (0x%08" PRIx64 ") in handle.", function, offset, offset ); write_count = -1; } else { write_count = libbfio_internal_handle_write_buffer( internal_handle, buffer, size, error ); if( write_count < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_WRITE_FAILED, "%s: unable to write to handle.", function ); write_count = -1; } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 ); } /* Seeks a certain offset within the handle * This function is not multi-thread safe acquire write lock before call * Returns the offset if the seek is successful or -1 on error */ off64_t libbfio_internal_handle_seek_offset( libbfio_internal_handle_t *internal_handle, off64_t offset, int whence, libcerror_error_t **error ) { static char *function = "libbfio_internal_handle_seek_offset"; if( internal_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } if( internal_handle->seek_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing seek offset function.", 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 ); } offset = internal_handle->seek_offset( internal_handle->io_handle, offset, whence, error ); if( offset == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset in handle.", function ); return( -1 ); } internal_handle->current_offset = offset; return( offset ); } /* Seeks a certain offset within the handle * Returns the offset if the seek is successful or -1 on error */ off64_t libbfio_handle_seek_offset( libbfio_handle_t *handle, off64_t offset, int whence, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_seek_offset"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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 = libbfio_internal_handle_seek_offset( internal_handle, offset, whence, error ); if( offset == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset in handle.", function ); offset = -1; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 ); } /* Function to determine if a file object exists * Returns 1 if file object exists, 0 if not or -1 on error */ int libbfio_handle_exists( libbfio_handle_t *handle, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_exists"; int result = 0; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } if( internal_handle->exists == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing exists function.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_handle->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 result = internal_handle->exists( internal_handle->io_handle, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if handle exists.", function ); goto on_error; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_handle->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 ); on_error: #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) libcthreads_read_write_lock_release_for_read( internal_handle->read_write_lock, NULL ); #endif return( -1 ); } /* Check if the handle is open * Returns 1 if open, 0 if not or -1 on error */ int libbfio_handle_is_open( libbfio_handle_t *handle, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_is_open"; int result = 0; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", function ); return( -1 ); } if( internal_handle->is_open == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing is open function.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_handle->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 result = internal_handle->is_open( internal_handle->io_handle, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if handle is open.", function ); goto on_error; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_handle->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 ); on_error: #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) libcthreads_read_write_lock_release_for_read( internal_handle->read_write_lock, NULL ); #endif return( -1 ); } /* Retrieves the IO handle * Returns 1 if successful or -1 on error */ int libbfio_handle_get_io_handle( libbfio_handle_t *handle, intptr_t **io_handle, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_get_io_handle"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_handle->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 *io_handle = internal_handle->io_handle; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_handle->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 access flags * Returns 1 if successful or -1 on error */ int libbfio_handle_get_access_flags( libbfio_handle_t *handle, int *access_flags, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_get_access_flags"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( access_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid access flags.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_handle->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 *access_flags = internal_handle->access_flags; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_handle->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 ); } /* Sets the access flags * Returns 1 if successful or -1 on error */ int libbfio_handle_set_access_flags( libbfio_handle_t *handle, int access_flags, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_set_access_flags"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( ( ( access_flags & LIBBFIO_ACCESS_FLAG_READ ) == 0 ) && ( ( access_flags & LIBBFIO_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 defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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_handle->access_flags = access_flags; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 ); } /* Retrieves the current offset * Returns 1 if successful or -1 on error */ int libbfio_handle_get_offset( libbfio_handle_t *handle, off64_t *offset, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_get_offset"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; 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 ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_handle->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_handle->current_offset; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_handle->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 ); } /* Returns the size of the data of the handle * Returns 1 if successful or -1 on error */ int libbfio_handle_get_size( libbfio_handle_t *handle, size64_t *size, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_get_size"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( internal_handle->io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing IO handle.", 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 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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_handle->size_set == 0 ) { if( internal_handle->get_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid handle - missing get size function.", function ); goto on_error; } if( internal_handle->get_size( internal_handle->io_handle, &( internal_handle->size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size.", function ); goto on_error; } internal_handle->size_set = 1; } *size = internal_handle->size; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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_LIBBFIO ) libcthreads_read_write_lock_release_for_write( internal_handle->read_write_lock, NULL ); #endif return( -1 ); } /* Sets the value to have the library open and close * the systems file descriptor or handle on demand * 0 disables open on demand any other value enables it * Returns 1 if successful or -1 on error */ int libbfio_handle_set_open_on_demand( libbfio_handle_t *handle, uint8_t open_on_demand, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_set_open_on_demand"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; if( ( ( internal_handle->access_flags & LIBBFIO_ACCESS_FLAG_WRITE ) != 0 ) && ( open_on_demand != 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: open on demand cannot be used in combination with write access.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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_handle->open_on_demand = open_on_demand; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 ); } /* Sets the value to have the library track the offsets read * 0 disables tracking any other value enables it * Returns 1 if successful or -1 on error */ int libbfio_handle_set_track_offsets_read( libbfio_handle_t *handle, uint8_t track_offsets_read, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_set_track_offsets_read"; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_write( internal_handle->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_handle->track_offsets_read = track_offsets_read; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_write( internal_handle->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 ); } /* Retrieves the number of offsets read * Returns 1 if successful or -1 on error */ int libbfio_handle_get_number_of_offsets_read( libbfio_handle_t *handle, int *number_of_read_offsets, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; static char *function = "libbfio_handle_get_number_of_offsets_read"; int result = 1; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_handle->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( libcdata_range_list_get_number_of_elements( internal_handle->offsets_read, number_of_read_offsets, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of read offsets.", function ); result = -1; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_handle->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 information of an offset read * Returns 1 if successful or -1 on error */ int libbfio_handle_get_offset_read( libbfio_handle_t *handle, int index, off64_t *offset, size64_t *size, libcerror_error_t **error ) { libbfio_internal_handle_t *internal_handle = NULL; intptr_t *value = NULL; static char *function = "libbfio_handle_get_offset_read"; int result = 1; if( handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid handle.", function ); return( -1 ); } internal_handle = (libbfio_internal_handle_t *) handle; #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_grab_for_read( internal_handle->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( libcdata_range_list_get_range_by_index( internal_handle->offsets_read, index, (uint64_t *) offset, (uint64_t *) size, &value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve read offset range: %d.", function, index ); result = -1; } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBBFIO ) if( libcthreads_read_write_lock_release_for_read( internal_handle->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 ); }