?? libewf_write.c
字號:
/* * libewf file writing * * Copyright (c) 2006-2007, Joachim Metz <forensics@hoffmannbv.nl>, * Hoffmann Investigations. All rights reserved. * * Refer to AUTHORS for acknowledgements. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the creator, related organisations, nor the names of * its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * - All advertising materials mentioning features or use of this software * must acknowledge the contribution by people stated in the acknowledgements. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER, COMPANY AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "libewf_includes.h"#include <errno.h>#ifdef HAVE_STRING_H#include <string.h>#endif#include <libewf/libewf_definitions.h>#include "libewf_char.h"#include "libewf_chunk_cache.h"#include "libewf_common.h"#include "libewf_endian.h"#include "libewf_file.h"#include "libewf_notify.h"#include "libewf_offset_table.h"#include "libewf_read.h"#include "libewf_section.h"#include "libewf_section_list.h"#include "libewf_segment_table.h"#include "libewf_string.h"#include "libewf_write.h"#include "ewf_char.h"#include "ewf_compress.h"#include "ewf_crc.h"#include "ewf_data.h"#include "ewf_definitions.h"#include "ewf_file_header.h"/* Calculates an estimate of the amount of chunks that fit within a segment file * Returns the size or 0 on error */uint32_t libewf_write_calculate_chunks_per_segment( LIBEWF_INTERNAL_HANDLE *internal_handle, uint16_t segment_number ){ int32_t available_segment_file_size = 0; int32_t maximum_chunks_per_segment = 0; int32_t chunks_per_segment = 0; int32_t remaining_amount_of_chunks = 0; int32_t required_chunk_sections = 1; if( internal_handle == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_segment: invalid handle.\n" ); return( 0 ); } if( internal_handle->media == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_segment: invalid handle - missing subhandle media.\n" ); return( 0 ); } if( internal_handle->write == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_segment: invalid handle - missing subhandle write.\n" ); return( 0 ); } if( internal_handle->write->segment_file_size > (uint32_t) INT32_MAX ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_segment: invalid segment file size only values below 2^32 are supported.\n" ); return( 0 ); } if( internal_handle->segment_table->file_offset[ segment_number ] > (off_t) INT32_MAX ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_segment: invalid segment file offset only values below 2^32 are supported.\n" ); return( 0 ); } /* If the amount of chunks already have been determined */ if( internal_handle->segment_table->amount_of_chunks[ segment_number ] > 0 ) { return( internal_handle->segment_table->amount_of_chunks[ segment_number ] ); } /* Calculate the available segment file size */ available_segment_file_size = (int32_t) internal_handle->write->segment_file_size - (int32_t) internal_handle->segment_table->file_offset[ segment_number ]; /* Leave space for the done or next section */ available_segment_file_size -= EWF_SECTION_SIZE; /* Calculate the maximum amount of chunks within this segment file */ if( internal_handle->ewf_format == EWF_FORMAT_S01 ) { /* The EWF-S01 format uses compression this will add 16 bytes on average */ maximum_chunks_per_segment = available_segment_file_size / ( internal_handle->media->chunk_size + 16 ); } else { maximum_chunks_per_segment = available_segment_file_size / ( internal_handle->media->chunk_size + EWF_CRC_SIZE ); } /* Determine the amount of required chunk sections */ if( internal_handle->write->unrestrict_offset_amount == 0 ) { required_chunk_sections = maximum_chunks_per_segment % EWF_MAXIMUM_OFFSETS_IN_TABLE; } if( internal_handle->ewf_format == EWF_FORMAT_S01 ) { /* Leave space for the chunk section starts */ available_segment_file_size -= ( required_chunk_sections * EWF_SECTION_SIZE ); /* Leave space for the table offsets */ available_segment_file_size -= ( maximum_chunks_per_segment * EWF_TABLE_OFFSET_SIZE ); } else if( internal_handle->format == LIBEWF_FORMAT_ENCASE1 ) { /* Leave space for the chunk section starts and the offset table CRC */ available_segment_file_size -= ( required_chunk_sections * ( EWF_SECTION_SIZE + EWF_CRC_SIZE ) ); /* Leave space for the table offsets */ available_segment_file_size -= ( maximum_chunks_per_segment * EWF_TABLE_OFFSET_SIZE ); } else { /* Leave space for the chunk, table and table2 section starts and the offset table CRC */ available_segment_file_size -= ( required_chunk_sections * ( ( 3 * EWF_SECTION_SIZE ) + EWF_CRC_SIZE ) ); /* Leave space for the table and table2 offsets */ available_segment_file_size -= 2 * ( maximum_chunks_per_segment * EWF_TABLE_OFFSET_SIZE ); } /* Calculate the amount of chunks within this segment file */ if( internal_handle->ewf_format == EWF_FORMAT_S01 ) { /* The EWF-S01 format uses compression this will add 16 bytes on average */ chunks_per_segment = available_segment_file_size / ( internal_handle->media->chunk_size + 16 ); } else { chunks_per_segment = available_segment_file_size / ( internal_handle->media->chunk_size + EWF_CRC_SIZE ); } /* If the input size is known */ if( internal_handle->write->input_write_size > 0 ) { /* Calculate the amount of chunks that will remain */ remaining_amount_of_chunks = (int32_t) internal_handle->media->amount_of_chunks - (int32_t) internal_handle->write->amount_of_chunks; /* Check if the less chunks remain than the amount of chunks calculated */ if( remaining_amount_of_chunks < chunks_per_segment ) { chunks_per_segment = remaining_amount_of_chunks; } } /* Make sure to return the total amount of chunks per segment */ if( internal_handle->write->segment_amount_of_chunks > 0 ) { chunks_per_segment += internal_handle->write->segment_amount_of_chunks; } return( (uint32_t) chunks_per_segment );}/* Calculates the amount of chunks that fit within a chunks section * Returns the size or 0 on error */uint32_t libewf_write_calculate_chunks_per_chunks_section( LIBEWF_INTERNAL_HANDLE *internal_handle ){ int32_t remaining_amount_of_chunks = 0; if( internal_handle == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_chunks_section: invalid handle.\n" ); return( 0 ); } if( internal_handle->media == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_chunks_section: invalid handle - missing subhandle media.\n" ); return( 0 ); } if( internal_handle->write == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_chunks_section: invalid handle - missing subhandle write.\n" ); return( 0 ); } if( internal_handle->write->chunks_per_segment > (uint32_t) INT32_MAX ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_chunks_section: invalid chunks per segment only values below 2^32 are supported.\n" ); return( 0 ); } if( internal_handle->write->segment_file_size > (uint32_t) INT32_MAX ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_chunks_section: invalid segment file size only values below 2^32 are supported.\n" ); return( 0 ); } if( internal_handle->write->chunks_section_number == 0 ) { LIBEWF_WARNING_PRINT( "libewf_write_calculate_chunks_per_chunks_section: unsupported section number: %" PRIu8 ".\n", internal_handle->write->chunks_section_number ); return( 0 ); } remaining_amount_of_chunks = (int32_t) internal_handle->write->chunks_per_segment; if( internal_handle->write->chunks_section_number > 1 ) { remaining_amount_of_chunks -= ( ( internal_handle->write->chunks_section_number - 1 ) * EWF_MAXIMUM_OFFSETS_IN_TABLE ); } if( remaining_amount_of_chunks <= 0 ) { return( 0 ); } else if( ( remaining_amount_of_chunks > EWF_MAXIMUM_OFFSETS_IN_TABLE ) && ( internal_handle->write->unrestrict_offset_amount == 0 ) ) { return( EWF_MAXIMUM_OFFSETS_IN_TABLE ); } return( (uint32_t) remaining_amount_of_chunks );}/* Tests if the current segment file is full * Returns 1 if full, 0 if not, -1 on error */int8_t libewf_write_test_segment_file_full( LIBEWF_INTERNAL_HANDLE *internal_handle, off_t segment_file_offset ){ int32_t remaining_segment_file_size = 0; if( internal_handle == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_test_segment_file_full: invalid handle.\n" ); return( -1 ); } if( internal_handle->media == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_test_segment_file_full: invalid handle - missing subhandle media.\n" ); return( -1 ); } if( internal_handle->write == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_test_segment_file_full: invalid handle - missing subhandle write.\n" ); return( -1 ); } if( segment_file_offset > (off_t) INT32_MAX ) { LIBEWF_WARNING_PRINT( "libewf_write_test_segment_file_full: invalid segment file offset only values below 2^32 are supported.\n" ); return( -1 ); } if( internal_handle->write->segment_file_size > (uint32_t) INT32_MAX ) { LIBEWF_WARNING_PRINT( "libewf_write_test_segment_file_full: invalid segment file size only values below 2^32 are supported.\n" ); return( -1 ); } /* Check if a chunks segment file has been opened */ if( segment_file_offset == 0 ) { LIBEWF_VERBOSE_PRINT( "libewf_write_test_segment_file_full: no segment file has been created.\n" ); return( 0 ); } /* Check if the maximum amount of chunks has been reached */ if( ( internal_handle->media->amount_of_chunks != 0 ) && ( internal_handle->media->amount_of_chunks == internal_handle->write->amount_of_chunks ) ) { LIBEWF_VERBOSE_PRINT( "libewf_write_test_segment_file_full: all required chunks have been written.\n" ); return( 1 ); } /* Check if the end of the input has been reached */ if( ( internal_handle->write->input_write_size != 0 ) && ( internal_handle->write->input_write_count >= (int64_t) internal_handle->write->input_write_size ) ) { LIBEWF_VERBOSE_PRINT( "libewf_write_test_segment_file_full: all required data has been written.\n" ); return( 1 ); } /* The EWF-S01 and EnCase1 format should use the pre calculated size */ if( ( internal_handle->ewf_format == EWF_FORMAT_S01 ) || ( internal_handle->format == LIBEWF_FORMAT_ENCASE1 ) ) { if( internal_handle->write->segment_amount_of_chunks >= internal_handle->write->chunks_per_segment ) { LIBEWF_VERBOSE_PRINT( "libewf_write_test_segment_file_full: no space left for additional chunk.\n" ); return( 1 ); } } else { /* Calculate the remaining segment file size */ remaining_segment_file_size = (int32_t) internal_handle->write->segment_file_size - (int32_t) segment_file_offset; /* Leave space for the done or next section */ remaining_segment_file_size -= EWF_SECTION_SIZE; /* Leave space for the table and table2 sections */ remaining_segment_file_size -= 2 * ( EWF_SECTION_SIZE + ( internal_handle->write->section_amount_of_chunks * EWF_TABLE_OFFSET_SIZE ) + EWF_CRC_SIZE ); /* Determine if a chunk would fit in the segment file */ remaining_segment_file_size -= internal_handle->media->chunk_size + EWF_CRC_SIZE; if( remaining_segment_file_size <= 0 ) { LIBEWF_VERBOSE_PRINT( "libewf_write_test_segment_file_full: no space left for additional chunk.\n" ); return( 1 ); } } LIBEWF_VERBOSE_PRINT( "libewf_write_test_segment_file_full: space left for additional chunk.\n" ); return( 0 );}/* Tests if the current chunks section is full * Returns 1 if full, 0 if not, -1 on error */int8_t libewf_write_test_chunks_section_full( LIBEWF_INTERNAL_HANDLE *internal_handle, off_t segment_file_offset ){ int32_t remaining_segment_file_size = 0; if( internal_handle == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_test_chunks_section_full: invalid handle.\n" ); return( -1 ); } if( internal_handle->media == NULL ) { LIBEWF_WARNING_PRINT( "libewf_write_test_chunks_section_full: invalid handle - missing subhandle media.\n" ); return( -1 ); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -