1 /*
2  * Low level writing functions
3  *
4  * Copyright (c) 2006-2014, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #if defined( TIME_WITH_SYS_TIME )
28 #include <sys/time.h>
29 #include <time.h>
30 #elif defined( HAVE_SYS_TIME_H )
31 #include <sys/time.h>
32 #else
33 #include <time.h>
34 #endif
35 
36 #include "libewf_checksum.h"
37 #include "libewf_chunk_data.h"
38 #include "libewf_chunk_table.h"
39 #include "libewf_compression.h"
40 #include "libewf_definitions.h"
41 #include "libewf_empty_block.h"
42 #include "libewf_filename.h"
43 #include "libewf_header_values.h"
44 #include "libewf_libbfio.h"
45 #include "libewf_libcdata.h"
46 #include "libewf_libcerror.h"
47 #include "libewf_libcnotify.h"
48 #include "libewf_libfvalue.h"
49 #include "libewf_libfcache.h"
50 #include "libewf_libmfdata.h"
51 #include "libewf_media_values.h"
52 #include "libewf_read_io_handle.h"
53 #include "libewf_section.h"
54 #include "libewf_segment_file.h"
55 #include "libewf_segment_table.h"
56 #include "libewf_unused.h"
57 #include "libewf_write_io_handle.h"
58 
59 #include "ewf_data.h"
60 #include "ewf_definitions.h"
61 #include "ewf_section.h"
62 #include "ewf_table.h"
63 #include "ewfx_delta_chunk.h"
64 
65 /* Initialize the write IO handle
66  * Returns 1 if successful or -1 on error
67  */
libewf_write_io_handle_initialize(libewf_write_io_handle_t ** write_io_handle,libcerror_error_t ** error)68 int libewf_write_io_handle_initialize(
69      libewf_write_io_handle_t **write_io_handle,
70      libcerror_error_t **error )
71 {
72 	static char *function = "libewf_write_io_handle_initialize";
73 
74 	if( write_io_handle == NULL )
75 	{
76 		libcerror_error_set(
77 		 error,
78 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
79 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
80 		 "%s: invalid write IO handle.",
81 		 function );
82 
83 		return( -1 );
84 	}
85 	if( *write_io_handle != NULL )
86 	{
87 		libcerror_error_set(
88 		 error,
89 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
90 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
91 		 "%s: invalid write IO handle value already set.",
92 		 function );
93 
94 		return( -1 );
95 	}
96 	*write_io_handle = memory_allocate_structure(
97 	                    libewf_write_io_handle_t );
98 
99 	if( *write_io_handle == NULL )
100 	{
101 		libcerror_error_set(
102 		 error,
103 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
104 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
105 		 "%s: unable to create write IO handle.",
106 		 function );
107 
108 		goto on_error;
109 	}
110 	if( memory_set(
111 	     *write_io_handle,
112 	     0,
113 	     sizeof( libewf_write_io_handle_t ) ) == NULL )
114 	{
115 		libcerror_error_set(
116 		 error,
117 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
118 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
119 		 "%s: unable to clear write IO handle.",
120 		 function );
121 
122 		goto on_error;
123 	}
124 	( *write_io_handle )->maximum_segment_file_size   = INT32_MAX;
125 	( *write_io_handle )->remaining_segment_file_size = LIBEWF_DEFAULT_SEGMENT_FILE_SIZE;
126 	( *write_io_handle )->maximum_chunks_per_section  = EWF_MAXIMUM_OFFSETS_IN_TABLE;
127 
128 	/* 'Z' - 'E' + 1 = 22
129 	 * ( ( 22 * 26 * 26 ) + 99 ) = 14971
130 	 */
131 	( *write_io_handle )->maximum_number_of_segments = (uint16_t) 14971;
132 
133 	return( 1 );
134 
135 on_error:
136 	if( *write_io_handle != NULL )
137 	{
138 		memory_free(
139 		 *write_io_handle );
140 
141 		*write_io_handle = NULL;
142 	}
143 	return( -1 );
144 }
145 
146 /* Frees the write IO handle including elements
147  * Returns 1 if successful or -1 on error
148  */
libewf_write_io_handle_free(libewf_write_io_handle_t ** write_io_handle,libcerror_error_t ** error)149 int libewf_write_io_handle_free(
150      libewf_write_io_handle_t **write_io_handle,
151      libcerror_error_t **error )
152 {
153 	static char *function = "libewf_write_io_handle_free";
154 
155 	if( write_io_handle == NULL )
156 	{
157 		libcerror_error_set(
158 		 error,
159 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
160 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
161 		 "%s: invalid write IO handle.",
162 		 function );
163 
164 		return( -1 );
165 	}
166 	if( *write_io_handle != NULL )
167 	{
168 		if( ( *write_io_handle )->data_section != NULL )
169 		{
170 			memory_free(
171 			 ( *write_io_handle )->data_section );
172 		}
173 		if( ( *write_io_handle )->table_offsets != NULL )
174 		{
175 			memory_free(
176 			 ( *write_io_handle )->table_offsets );
177 		}
178 		if( ( *write_io_handle )->compressed_zero_byte_empty_block != NULL )
179 		{
180 			memory_free(
181 			 ( *write_io_handle )->compressed_zero_byte_empty_block );
182 		}
183 		memory_free(
184 		 *write_io_handle );
185 
186 		*write_io_handle = NULL;
187 	}
188 	return( 1 );
189 }
190 
191 /* Clones the write IO handle
192  * Returns 1 if successful or -1 on error
193  */
libewf_write_io_handle_clone(libewf_write_io_handle_t ** destination_write_io_handle,libewf_write_io_handle_t * source_write_io_handle,libcerror_error_t ** error)194 int libewf_write_io_handle_clone(
195      libewf_write_io_handle_t **destination_write_io_handle,
196      libewf_write_io_handle_t *source_write_io_handle,
197      libcerror_error_t **error )
198 {
199 	static char *function = "libewf_write_io_handle_clone";
200 	size_t offsets_size   = 0;
201 
202 	if( destination_write_io_handle == NULL )
203 	{
204 		libcerror_error_set(
205 		 error,
206 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
207 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
208 		 "%s: invalid destination write IO handle.",
209 		 function );
210 
211 		return( -1 );
212 	}
213 	if( *destination_write_io_handle != NULL )
214 	{
215 		libcerror_error_set(
216 		 error,
217 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
218 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
219 		 "%s: invalid destination write IO handle value already set.",
220 		 function );
221 
222 		return( -1 );
223 	}
224 	if( source_write_io_handle == NULL )
225 	{
226 		*destination_write_io_handle = NULL;
227 
228 		return( 1 );
229 	}
230 	*destination_write_io_handle = memory_allocate_structure(
231 	                                libewf_write_io_handle_t );
232 
233 	if( *destination_write_io_handle == NULL )
234 	{
235 		libcerror_error_set(
236 		 error,
237 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
238 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
239 		 "%s: unable to create destination write IO handle.",
240 		 function );
241 
242 		goto on_error;
243 	}
244 	if( memory_copy(
245 	     *destination_write_io_handle,
246 	     source_write_io_handle,
247 	     sizeof( libewf_write_io_handle_t ) ) == NULL )
248 	{
249 		libcerror_error_set(
250 		 error,
251 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
252 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
253 		 "%s: unable to copy source to destination write IO handle.",
254 		 function );
255 
256 		memory_free(
257 		 *destination_write_io_handle );
258 
259 		*destination_write_io_handle = NULL;
260 
261 		return( -1 );
262 	}
263 	( *destination_write_io_handle )->data_section            = NULL;
264 	( *destination_write_io_handle )->table_offsets           = NULL;
265 	( *destination_write_io_handle )->number_of_table_offsets = 0;
266 
267 	if( source_write_io_handle->data_section != NULL )
268 	{
269 		( *destination_write_io_handle )->data_section = memory_allocate_structure(
270 		                                                  ewf_data_t );
271 
272 		if( ( *destination_write_io_handle )->data_section == NULL )
273 		{
274 			libcerror_error_set(
275 			 error,
276 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
277 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
278 			 "%s: unable to create destination data section.",
279 			 function );
280 
281 			goto on_error;
282 		}
283 		if( memory_copy(
284 		     ( *destination_write_io_handle )->data_section,
285 		     source_write_io_handle->data_section,
286 		     sizeof( ewf_data_t ) ) == NULL )
287 		{
288 			libcerror_error_set(
289 			 error,
290 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
291 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
292 			 "%s: unable to copy source to destination data section.",
293 			 function );
294 
295 			goto on_error;
296 		}
297 	}
298 	if( source_write_io_handle->table_offsets != NULL )
299 	{
300 		offsets_size = sizeof( ewf_table_offset_t ) * source_write_io_handle->number_of_table_offsets;
301 
302 		( *destination_write_io_handle )->table_offsets = (ewf_table_offset_t *) memory_allocate(
303 		                                                                          offsets_size );
304 
305 		if( ( *destination_write_io_handle )->table_offsets == NULL )
306 		{
307 			libcerror_error_set(
308 			 error,
309 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
310 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
311 			 "%s: unable to create destination table offsets.",
312 			 function );
313 
314 			goto on_error;
315 		}
316 		if( memory_copy(
317 		     ( *destination_write_io_handle )->table_offsets,
318 		     source_write_io_handle->table_offsets,
319 		     offsets_size ) == NULL )
320 		{
321 			libcerror_error_set(
322 			 error,
323 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
324 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
325 			 "%s: unable to copy source to destination table offsets.",
326 			 function );
327 
328 			goto on_error;
329 		}
330 	}
331 	return( 1 );
332 
333 on_error:
334 	if( *destination_write_io_handle != NULL )
335 	{
336 		if( ( *destination_write_io_handle )->table_offsets != NULL )
337 		{
338 			memory_free(
339 			 ( *destination_write_io_handle )->table_offsets );
340 		}
341 		if( ( *destination_write_io_handle )->data_section != NULL )
342 		{
343 			memory_free(
344 			 ( *destination_write_io_handle )->data_section );
345 		}
346 		memory_free(
347 		 *destination_write_io_handle );
348 
349 		*destination_write_io_handle = NULL;
350 	}
351 	return( -1 );
352 }
353 
354 /* Initializes the write IO handle value to start writing
355  * Returns 1 if successful or -1 on error
356  */
libewf_write_io_handle_initialize_values(libewf_write_io_handle_t * write_io_handle,libewf_io_handle_t * io_handle,libewf_media_values_t * media_values,libewf_segment_table_t * segment_table,libcerror_error_t ** error)357 int libewf_write_io_handle_initialize_values(
358      libewf_write_io_handle_t *write_io_handle,
359      libewf_io_handle_t *io_handle,
360      libewf_media_values_t *media_values,
361      libewf_segment_table_t *segment_table,
362      libcerror_error_t **error )
363 {
364 	static char *function               = "libewf_write_io_handle_initialize_values";
365 	int64_t required_number_of_segments = 0;
366 
367 	if( write_io_handle == NULL )
368 	{
369 		libcerror_error_set(
370 		 error,
371 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
372 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
373 		 "%s: invalid write IO handle.",
374 		 function );
375 
376 		return( -1 );
377 	}
378 	if( write_io_handle->values_initialized != 0 )
379 	{
380 		libcerror_error_set(
381 		 error,
382 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
383 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
384 		 "%s: write values were initialized and cannot be initialized anymore.",
385 		 function );
386 
387 		return( -1 );
388 	}
389 	if( io_handle == NULL )
390 	{
391 		libcerror_error_set(
392 		 error,
393 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
394 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
395 		 "%s: invalid IO handle.",
396 		 function );
397 
398 		return( -1 );
399 	}
400 	if( media_values == NULL )
401 	{
402 		libcerror_error_set(
403 		 error,
404 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
405 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
406 		 "%s: invalid media values.",
407 		 function );
408 
409 		return( -1 );
410 	}
411 	if( segment_table == NULL )
412 	{
413 		libcerror_error_set(
414 		 error,
415 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
416 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
417 		 "%s: invalid segment table.",
418 		 function );
419 
420 		return( -1 );
421 	}
422 	/* Determine the EWF file format
423 	 */
424 	if( io_handle->format == LIBEWF_FORMAT_LVF )
425 	{
426 		libcerror_error_set(
427 		 error,
428 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
429 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
430 		 "%s: writing format LVF currently not supported.",
431 		 function );
432 
433 		return( -1 );
434 	}
435 	if( segment_table->maximum_segment_size == 0 )
436 	{
437 		segment_table->maximum_segment_size = write_io_handle->maximum_segment_file_size;
438 	}
439 	/* If no input write size was provided check if EWF file format allows for streaming
440 	 */
441 	if( media_values->media_size == 0 )
442 	{
443 		if( ( io_handle->format != LIBEWF_FORMAT_ENCASE2 )
444 		 && ( io_handle->format != LIBEWF_FORMAT_ENCASE3 )
445 		 && ( io_handle->format != LIBEWF_FORMAT_ENCASE4 )
446 		 && ( io_handle->format != LIBEWF_FORMAT_ENCASE5 )
447 		 && ( io_handle->format != LIBEWF_FORMAT_ENCASE6 )
448 		 && ( io_handle->format != LIBEWF_FORMAT_LINEN5 )
449 		 && ( io_handle->format != LIBEWF_FORMAT_LINEN6 )
450 		 && ( io_handle->format != LIBEWF_FORMAT_FTK )
451 		 && ( io_handle->format != LIBEWF_FORMAT_EWFX ) )
452 		{
453 			libcerror_error_set(
454 			 error,
455 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
456 			 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
457 			 "%s: EWF file format does not allow for streaming write.",
458 			 function );
459 
460 			return( -1 );
461 		}
462 	}
463 	else
464 	{
465 		/* Determine the required number of segments allowed to write
466 		 */
467 		required_number_of_segments = (int64_t) media_values->media_size / (int64_t) segment_table->maximum_segment_size;
468 
469 		if( required_number_of_segments > (int64_t) write_io_handle->maximum_number_of_segments )
470 		{
471 			libcerror_error_set(
472 			 error,
473 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
474 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
475 			 "%s: the maximum number of allowed segment files will be exceeded with the segment file size: %" PRIu64 ".",
476 			 function,
477 			 segment_table->maximum_segment_size );
478 
479 			return( -1 );
480 		}
481 	}
482 	if( media_values->media_size > LIBEWF_2_TIB )
483 	{
484 		if( ( io_handle->format != LIBEWF_FORMAT_ENCASE6 )
485 		 && ( io_handle->format != LIBEWF_FORMAT_EWFX ) )
486 		{
487 			libcerror_error_set(
488 			 error,
489 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
490 			 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
491 			 "%s: EWF file format does not allow for a media size greater than 2 TiB.",
492 			 function );
493 
494 			return( -1 );
495 		}
496 	}
497 	/* Flag that the write values were initialized
498 	 */
499 	write_io_handle->values_initialized = 1;
500 
501 	return( 1 );
502 }
503 
504 /* Initializes the write IO handle to resume writing
505  * Returns 1 if successful or -1 on error
506  */
libewf_write_io_handle_initialize_resume(libewf_write_io_handle_t * write_io_handle,libewf_io_handle_t * io_handle,libbfio_pool_t * file_io_pool,libewf_media_values_t * media_values,libmfdata_file_list_t * segment_files_list,libfcache_cache_t * segment_files_cache,libmfdata_list_t * chunk_table_list,libewf_chunk_table_t * chunk_table,libewf_segment_table_t * segment_table,libcerror_error_t ** error)507 int libewf_write_io_handle_initialize_resume(
508      libewf_write_io_handle_t *write_io_handle,
509      libewf_io_handle_t *io_handle,
510      libbfio_pool_t *file_io_pool,
511      libewf_media_values_t *media_values,
512      libmfdata_file_list_t *segment_files_list,
513      libfcache_cache_t *segment_files_cache,
514      libmfdata_list_t *chunk_table_list,
515      libewf_chunk_table_t *chunk_table,
516      libewf_segment_table_t *segment_table,
517      libcerror_error_t **error )
518 {
519 	libcdata_list_element_t *previous_section_list_element = NULL;
520 	libcdata_list_element_t *section_list_element          = NULL;
521 	libewf_section_t *previous_section                     = NULL;
522 	libewf_section_t *section                              = NULL;
523 	libewf_segment_file_t *segment_file                    = NULL;
524 	static char *function                                  = "libewf_write_io_handle_initialize_resume";
525 	uint8_t backtrace_to_last_chunks_sections              = 0;
526 	uint8_t reopen_segment_file                            = 0;
527 	int file_io_pool_entry                                 = 0;
528 	int number_of_chunks                                   = 0;
529 	int number_of_segment_files                            = 0;
530 	int number_of_unusable_chunks                          = 0;
531 	int segment_files_list_index                           = 0;
532 	int supported_section                                  = 0;
533 
534 	if( write_io_handle == NULL )
535 	{
536 		libcerror_error_set(
537 		 error,
538 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
539 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
540 		 "%s: invalid write IO handle.",
541 		 function );
542 
543 		return( -1 );
544 	}
545 	if( io_handle == NULL )
546 	{
547 		libcerror_error_set(
548 		 error,
549 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
550 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
551 		 "%s: invalid IO handle.",
552 		 function );
553 
554 		return( -1 );
555 	}
556 	if( media_values == NULL )
557 	{
558 		libcerror_error_set(
559 		 error,
560 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
561 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
562 		 "%s: invalid media values.",
563 		 function );
564 
565 		return( -1 );
566 	}
567 	if( libmfdata_file_list_get_number_of_files(
568 	     segment_files_list,
569 	     &number_of_segment_files,
570 	     error ) != 1 )
571 	{
572 		libcerror_error_set(
573 		 error,
574 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
575 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
576 		 "%s: unable to retrieve number of segment files.",
577 		 function );
578 
579 		return( -1 );
580 	}
581 	if( ( number_of_segment_files <= 0 )
582 	 || ( number_of_segment_files > (int) UINT16_MAX ) )
583 	{
584 		libcerror_error_set(
585 		 error,
586 	 	 LIBCERROR_ERROR_DOMAIN_RUNTIME,
587 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
588 		 "%s: invalid number of segment files value out of bounds.",
589 		 function );
590 
591 		return( -1 );
592 	}
593 	segment_files_list_index = number_of_segment_files - 1;
594 
595 	if( libmfdata_file_list_get_file_value_by_index(
596 	     segment_files_list,
597 	     file_io_pool,
598 	     segment_files_cache,
599 	     segment_files_list_index,
600 	     (intptr_t **) &segment_file,
601 	     0,
602 	     error ) != 1 )
603 	{
604 		libcerror_error_set(
605 		 error,
606 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
607 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
608 		 "%s: unable to retrieve segment file: %d from list.",
609 		 function,
610 		 segment_files_list_index + 1 );
611 
612 		return( -1 );
613 	}
614 	if( segment_file == NULL )
615 	{
616 		libcerror_error_set(
617 		 error,
618 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
619 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
620 		 "%s: missing segment file.",
621 		 function );
622 
623 		return( -1 );
624 	}
625 	if( segment_file->section_list == NULL )
626 	{
627 		libcerror_error_set(
628 		 error,
629 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
630 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
631 		 "%s: invalid segment file - missing section list.",
632 		 function );
633 
634 		return( -1 );
635 	}
636 	if( libcdata_list_get_last_element(
637 	     segment_file->section_list,
638 	     &section_list_element,
639 	     error ) != 1 )
640 	{
641 		libcerror_error_set(
642 		 error,
643 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
644 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
645 		 "%s: unable to retrieve last element from section list.",
646 		 function );
647 
648 		return( -1 );
649 	}
650 	if( libcdata_list_element_get_value(
651 	     section_list_element,
652 	     (intptr_t **) &section,
653 	     error ) != 1 )
654 	{
655 		libcerror_error_set(
656 		 error,
657 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
658 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
659 		 "%s: unable to retrieve value from section list element.",
660 		 function );
661 
662 		return( -1 );
663 	}
664 	if( section == NULL )
665 	{
666 		libcerror_error_set(
667 		 error,
668 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
669 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
670 		 "%s: missing last section.",
671 		 function );
672 
673 		return( -1 );
674 	}
675 	if( section->type_length == 4 )
676 	{
677 		if( memory_compare(
678 		     (void *) section->type,
679 		     (void *) "data",
680 		     4 ) == 0 )
681 		{
682 			if( segment_files_list_index == 0 )
683 			{
684 				backtrace_to_last_chunks_sections = 1;
685 			}
686 		}
687 		else if( memory_compare(
688 			  (void *) section->type,
689 			  (void *) "hash",
690 			  4 ) == 0 )
691 		{
692 			backtrace_to_last_chunks_sections = 1;
693 		}
694 	}
695 	else if( section->type_length == 5 )
696 	{
697 		if( memory_compare(
698 		     (void *) section->type,
699 		     (void *) "xhash",
700 		     6 ) == 0 )
701 		{
702 			backtrace_to_last_chunks_sections = 1;
703 		}
704 	}
705 	else if( section->type_length == 5 )
706 	{
707 		if( memory_compare(
708 		     (void *) section->type,
709 		     (void *) "digest",
710 		     7 ) == 0 )
711 		{
712 			backtrace_to_last_chunks_sections = 1;
713 		}
714 		else if( memory_compare(
715 			  (void *) section->type,
716 			  (void *) "error2",
717 			  7 ) == 0 )
718 		{
719 			backtrace_to_last_chunks_sections = 1;
720 		}
721 	}
722 	else if( section->type_length == 7 )
723 	{
724 		if( memory_compare(
725 		     (void *) section->type,
726 		     (void *) "session",
727 		     8 ) == 0 )
728 		{
729 			backtrace_to_last_chunks_sections = 1;
730 		}
731 	}
732 	if( backtrace_to_last_chunks_sections != 0 )
733 	{
734 		if( libcdata_list_element_get_previous_element(
735 		     section_list_element,
736 		     &section_list_element,
737 		     error ) != 1 )
738 		{
739 			libcerror_error_set(
740 			 error,
741 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
742 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
743 			 "%s: unable to retrieve previous element from section list element.",
744 			 function );
745 
746 			return( -1 );
747 		}
748 		while( section_list_element != NULL )
749 		{
750 			if( libcdata_list_element_get_value(
751 			     section_list_element,
752 			     (intptr_t **) &section,
753 			     error ) != 1 )
754 			{
755 				libcerror_error_set(
756 				 error,
757 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
758 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
759 				 "%s: unable to retrieve value from section list element.",
760 				 function );
761 
762 				return( -1 );
763 			}
764 			if( section == NULL )
765 			{
766 				libcerror_error_set(
767 				 error,
768 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
769 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
770 				 "%s: missing section.",
771 				 function );
772 
773 				return( -1 );
774 			}
775 			if( memory_compare(
776 			     (void *) section->type,
777 			     (void *) "table",
778 			     5 ) == 0 )
779 			{
780 				break;
781 			}
782 			if( libcdata_list_element_get_previous_element(
783 			     section_list_element,
784 			     &section_list_element,
785 			     error ) != 1 )
786 			{
787 				libcerror_error_set(
788 				 error,
789 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
790 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
791 				 "%s: unable to retrieve previous element from section list element.",
792 				 function );
793 
794 				return( -1 );
795 			}
796 		}
797 		if( section_list_element == NULL )
798 		{
799 			libcerror_error_set(
800 			 error,
801 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
802 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
803 			 "%s: missing last chunks section.",
804 			 function );
805 
806 			return( -1 );
807 		}
808 	}
809 	if( section->type_length == 4 )
810 	{
811 		if( memory_compare(
812 		     (void *) section->type,
813 		     (void *) "data",
814 		     4 ) == 0 )
815 		{
816 			/* The sections containing the chunks and offsets were read entirely
817 			 * in the previous segment file
818 			 */
819 			supported_section                           = 1;
820 			reopen_segment_file                         = 1;
821 			write_io_handle->resume_segment_file_offset = section->end_offset;
822 			write_io_handle->create_chunks_section      = 1;
823 		}
824 		else if( memory_compare(
825 			  (void *) section->type,
826 			  (void *) "done",
827 			  4 ) == 0 )
828 		{
829 			/* The segment file was read entirely
830 			 */
831 			supported_section = 1;
832 		}
833 		else if( memory_compare(
834 			  (void *) section->type,
835 			  (void *) "next",
836 			  4 ) == 0 )
837 		{
838 			/* The segment file was read entirely
839 			 */
840 			supported_section = 1;
841 		}
842 	}
843 	else if( section->type_length == 5 )
844 	{
845 		if( memory_compare(
846 		     (void *) section->type,
847 		     (void *) "table",
848 		     6 ) == 0 )
849 		{
850 			/* Determine if the table section also contains chunks
851 			 */
852 			if( libcdata_list_element_get_previous_element(
853 			     section_list_element,
854 			     &previous_section_list_element,
855 			     error ) != 1 )
856 			{
857 				libcerror_error_set(
858 				 error,
859 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
860 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
861 				 "%s: unable to retrieve previous element from section list element.",
862 				 function );
863 
864 				return( -1 );
865 			}
866 			if( libcdata_list_element_get_value(
867 			     previous_section_list_element,
868 			     (intptr_t **) &previous_section,
869 			     error ) != 1 )
870 			{
871 				libcerror_error_set(
872 				 error,
873 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
874 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
875 				 "%s: unable to retrieve value from previous section list element.",
876 				 function );
877 
878 				return( -1 );
879 			}
880 			if( previous_section == NULL )
881 			{
882 				libcerror_error_set(
883 				 error,
884 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
885 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
886 				 "%s: missing previous section.",
887 				 function );
888 
889 				return( -1 );
890 			}
891 			if( memory_compare(
892 			     (void *) previous_section->type,
893 			     (void *) "sectors",
894 			     8 ) != 0 )
895 			{
896 				libcerror_error_set(
897 				 error,
898 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
899 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
900 				 "%s: unsupported previous section: %s.",
901 				 function,
902 				 previous_section->type );
903 
904 				return( -1 );
905 			}
906 			if( chunk_table->previous_last_chunk_filled > chunk_table->last_chunk_filled )
907 			{
908 				libcerror_error_set(
909 				 error,
910 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
911 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
912 				 "%s: previous last chunk offset filled cannot be greater than current.",
913 				 function );
914 
915 				return( -1 );
916 			}
917 			number_of_unusable_chunks = chunk_table->last_chunk_filled - chunk_table->previous_last_chunk_filled;
918 
919 			if( libmfdata_list_get_number_of_elements(
920 			     chunk_table_list,
921 			     &number_of_chunks,
922 			     error ) != 1 )
923 			{
924 				libcerror_error_set(
925 				 error,
926 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
927 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
928 				 "%s: unable to retrieve the number of chunks in the chunk table list.",
929 				 function );
930 
931 				return( -1 );
932 			}
933 			if( number_of_unusable_chunks > number_of_chunks )
934 			{
935 				libcerror_error_set(
936 				 error,
937 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
938 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
939 				 "%s: number of unusable chunks cannot be greater than number of chunks.",
940 				 function );
941 
942 				return( -1 );
943 			}
944 			/* The sections containing the chunks and offsets were read partially
945 			 */
946 			section_list_element = previous_section_list_element;
947 			section              = previous_section;
948 
949 			if( libmfdata_list_resize(
950 			     chunk_table_list,
951 			     number_of_chunks - number_of_unusable_chunks,
952 			     error ) != 1 )
953 			{
954 				libcerror_error_set(
955 				 error,
956 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
957 				 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
958 				 "%s: unable to resize chunk table list.",
959 				 function );
960 
961 				return( -1 );
962 			}
963 			chunk_table->last_chunk_filled   = chunk_table->previous_last_chunk_filled;
964 			chunk_table->last_chunk_compared = chunk_table->previous_last_chunk_filled;
965 
966 			supported_section                           = 1;
967 			reopen_segment_file                         = 1;
968 			write_io_handle->resume_segment_file_offset = section->start_offset;
969 			write_io_handle->create_chunks_section      = 1;
970 		}
971 	}
972 	else if( section->type_length == 6 )
973 	{
974 		if( memory_compare(
975 		     (void *) section->type,
976 		     (void *) "table2",
977 		     6 ) == 0 )
978 		{
979 			/* Determine if the table section also contains chunks
980 			 */
981 			if( libcdata_list_element_get_previous_element(
982 			     section_list_element,
983 			     &previous_section_list_element,
984 			     error ) != 1 )
985 			{
986 				libcerror_error_set(
987 				 error,
988 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
989 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
990 				 "%s: unable to retrieve previous element from section list element.",
991 				 function );
992 
993 				return( -1 );
994 			}
995 			if( libcdata_list_element_get_value(
996 			     previous_section_list_element,
997 			     (intptr_t **) &previous_section,
998 			     error ) != 1 )
999 			{
1000 				libcerror_error_set(
1001 				 error,
1002 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1003 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1004 				 "%s: unable to retrieve value from previous section list element.",
1005 				 function );
1006 
1007 				return( -1 );
1008 			}
1009 			if( previous_section == NULL )
1010 			{
1011 				libcerror_error_set(
1012 				 error,
1013 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1014 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1015 				 "%s: missing previous section.",
1016 				 function );
1017 
1018 				return( -1 );
1019 			}
1020 			if( memory_compare(
1021 			     (void *) previous_section->type,
1022 			     (void *) "table",
1023 			     6 ) != 0 )
1024 			{
1025 				libcerror_error_set(
1026 				 error,
1027 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1028 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1029 				 "%s: unsupported previous section: %s.",
1030 				 function,
1031 				 previous_section->type );
1032 
1033 				return( -1 );
1034 			}
1035 			if( libcdata_list_element_get_previous_element(
1036 			     previous_section_list_element,
1037 			     &previous_section_list_element,
1038 			     error ) != 1 )
1039 			{
1040 				libcerror_error_set(
1041 				 error,
1042 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1043 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1044 				 "%s: unable to retrieve previous element from previous section list element.",
1045 				 function );
1046 
1047 				return( -1 );
1048 			}
1049 			if( libcdata_list_element_get_value(
1050 			     previous_section_list_element,
1051 			     (intptr_t **) &previous_section,
1052 			     error ) != 1 )
1053 			{
1054 				libcerror_error_set(
1055 				 error,
1056 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1057 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1058 				 "%s: unable to retrieve value from second previous section list element.",
1059 				 function );
1060 
1061 				return( -1 );
1062 			}
1063 			if( previous_section == NULL )
1064 			{
1065 				libcerror_error_set(
1066 				 error,
1067 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1068 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1069 				 "%s: missing second previous section.",
1070 				 function );
1071 
1072 				return( -1 );
1073 			}
1074 			if( memory_compare(
1075 			     (void *) previous_section->type,
1076 			     (void *) "sectors",
1077 			     8 ) != 0 )
1078 			{
1079 				libcerror_error_set(
1080 				 error,
1081 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1082 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1083 				 "%s: unsupported second previous section: %s.",
1084 				 function,
1085 				 previous_section->type );
1086 
1087 				return( -1 );
1088 			}
1089 			if( chunk_table->previous_last_chunk_filled > chunk_table->last_chunk_filled )
1090 			{
1091 				libcerror_error_set(
1092 				 error,
1093 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1094 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1095 				 "%s: previous last chunk offset filled cannot be greater than current.",
1096 				 function );
1097 
1098 				return( -1 );
1099 			}
1100 			number_of_unusable_chunks = chunk_table->last_chunk_filled - chunk_table->previous_last_chunk_filled;
1101 
1102 			if( libmfdata_list_get_number_of_elements(
1103 			     chunk_table_list,
1104 			     &number_of_chunks,
1105 			     error ) != 1 )
1106 			{
1107 				libcerror_error_set(
1108 				 error,
1109 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1110 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1111 				 "%s: unable to retrieve the number of chunks in the chunk table list.",
1112 				 function );
1113 
1114 				return( -1 );
1115 			}
1116 			if( number_of_unusable_chunks > number_of_chunks )
1117 			{
1118 				libcerror_error_set(
1119 				 error,
1120 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1121 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1122 				 "%s: number of unusable chunks cannot be greater than number of chunks.",
1123 				 function );
1124 
1125 				return( -1 );
1126 			}
1127 			/* The sections containing the chunks and offsets were read partially
1128 			 */
1129 			section_list_element = previous_section_list_element;
1130 			section              = previous_section;
1131 
1132 			if( libmfdata_list_resize(
1133 			     chunk_table_list,
1134 			     number_of_chunks - number_of_unusable_chunks,
1135 			     error ) != 1 )
1136 			{
1137 				libcerror_error_set(
1138 				 error,
1139 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1140 				 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1141 				 "%s: unable to resize chunk table list.",
1142 				 function );
1143 
1144 				return( -1 );
1145 			}
1146 			chunk_table->last_chunk_filled   = chunk_table->previous_last_chunk_filled;
1147 			chunk_table->last_chunk_compared = chunk_table->previous_last_chunk_filled;
1148 
1149 			supported_section                           = 1;
1150 			reopen_segment_file                         = 1;
1151 			write_io_handle->resume_segment_file_offset = section->start_offset;
1152 			write_io_handle->create_chunks_section      = 1;
1153 		}
1154 	}
1155 	else if( section->type_length == 7 )
1156 	{
1157 		if( memory_compare(
1158 		     (void *) section->type,
1159 		     (void *) "sectors",
1160 		     7 ) == 0 )
1161 		{
1162 			/* Uncertain if the sections containing the chunks was read entirely
1163 			 * the offsets to the chunks are missing so the chunks need to be rewritten anyway
1164 			 */
1165 			supported_section                           = 1;
1166 			reopen_segment_file                         = 1;
1167 			write_io_handle->resume_segment_file_offset = section->start_offset;
1168 			write_io_handle->create_chunks_section      = 1;
1169 		}
1170 	}
1171 	if( supported_section == 0 )
1172 	{
1173 		libcerror_error_set(
1174 		 error,
1175 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1176 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1177 		 "%s: write resume from section: %s not supported.",
1178 		 function,
1179 		 (char *) section->type );
1180 
1181 		return( -1 );
1182 	}
1183 	/* Set offset into media data
1184 	 */
1185 	io_handle->current_offset = (off64_t) chunk_table->last_chunk_compared * media_values->chunk_size;
1186 
1187 	/* Set write IO handle values
1188 	 */
1189 	write_io_handle->input_write_count        = (ssize64_t) io_handle->current_offset;
1190 	write_io_handle->number_of_chunks_written = chunk_table->last_chunk_compared;
1191 	write_io_handle->write_finalized          = 0;
1192 
1193 	if( reopen_segment_file != 0 )
1194 	{
1195 		if( write_io_handle->resume_segment_file_offset > (off64_t) segment_table->maximum_segment_size )
1196 		{
1197 			libcerror_error_set(
1198 			 error,
1199 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1200 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1201 			 "%s: resume segment file offset cannot be greater than segment file size.",
1202 			 function );
1203 
1204 			return( -1 );
1205 		}
1206 		write_io_handle->remaining_segment_file_size = segment_table->maximum_segment_size
1207 		                                             - write_io_handle->resume_segment_file_offset;
1208 
1209 		write_io_handle->number_of_chunks_written_to_segment = segment_file->number_of_chunks
1210 		                                                     - number_of_unusable_chunks;
1211 
1212 		if( libmfdata_file_list_get_file_by_index(
1213 		     segment_files_list,
1214 		     segment_files_list_index,
1215 		     &file_io_pool_entry,
1216 		     error ) != 1 )
1217 		{
1218 			libcerror_error_set(
1219 			 error,
1220 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1221 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1222 			 "%s: unable to retrieve segment file: %d from list.",
1223 			 function,
1224 			 segment_files_list_index + 1 );
1225 
1226 			return( -1 );
1227 		}
1228 		if( libbfio_pool_reopen(
1229 		     file_io_pool,
1230 		     file_io_pool_entry,
1231 		     LIBBFIO_OPEN_READ_WRITE,
1232 		     error ) != 1 )
1233 		{
1234 			libcerror_error_set(
1235 			 error,
1236 			 LIBCERROR_ERROR_DOMAIN_IO,
1237 			 LIBCERROR_IO_ERROR_OPEN_FAILED,
1238 			 "%s: unable to reopen segment file: %d.",
1239 			 function,
1240 			 segment_files_list_index + 1 );
1241 
1242 			return( -1 );
1243 		}
1244 		segment_file->flags |= LIBEWF_SEGMENT_FILE_FLAG_WRITE_OPEN;
1245 	}
1246 	return( 1 );
1247 }
1248 
1249 /* Sets the compressed zero byte empty block
1250  * Returns 1 if successful or -1 on error
1251  */
libewf_write_io_handle_set_compressed_zero_byte_empty_block(libewf_write_io_handle_t * write_io_handle,libewf_io_handle_t * io_handle,libewf_media_values_t * media_values,libcerror_error_t ** error)1252 int libewf_write_io_handle_set_compressed_zero_byte_empty_block(
1253      libewf_write_io_handle_t *write_io_handle,
1254      libewf_io_handle_t *io_handle,
1255      libewf_media_values_t *media_values,
1256      libcerror_error_t **error )
1257 {
1258 	uint8_t *compressed_zero_byte_empty_block = NULL;
1259 	uint8_t *zero_byte_empty_block            = NULL;
1260 	static char *function                     = "libewf_write_io_handle_set_compressed_zero_byte_empty_block";
1261 	void *reallocation                        = NULL;
1262 	int result                                = 0;
1263 	int compression_level                     = 0;
1264 
1265 	if( write_io_handle == NULL )
1266 	{
1267 		libcerror_error_set(
1268 		 error,
1269 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1270 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1271 		 "%s: invalid write IO handle.",
1272 		 function );
1273 
1274 		return( -1 );
1275 	}
1276 	if( write_io_handle->values_initialized != 0 )
1277 	{
1278 		libcerror_error_set(
1279 		 error,
1280 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1281 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1282 		 "%s: write values were initialized and cannot be initialized anymore.",
1283 		 function );
1284 
1285 		return( -1 );
1286 	}
1287 	if( io_handle == NULL )
1288 	{
1289 		libcerror_error_set(
1290 		 error,
1291 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1292 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1293 		 "%s: invalid IO handle.",
1294 		 function );
1295 
1296 		return( -1 );
1297 	}
1298 	if( media_values == NULL )
1299 	{
1300 		libcerror_error_set(
1301 		 error,
1302 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1303 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1304 		 "%s: invalid media values.",
1305 		 function );
1306 
1307 		return( -1 );
1308 	}
1309 	if( write_io_handle->compressed_zero_byte_empty_block != NULL )
1310 	{
1311 		memory_free(
1312 		 write_io_handle->compressed_zero_byte_empty_block );
1313 
1314 		write_io_handle->compressed_zero_byte_empty_block = NULL;
1315 	}
1316 	zero_byte_empty_block = (uint8_t *) memory_allocate(
1317 	                                     sizeof( uint8_t ) * (size_t) media_values->chunk_size );
1318 
1319 	if( zero_byte_empty_block == NULL )
1320 	{
1321 		libcerror_error_set(
1322 		 error,
1323 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1324 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1325 		 "%s: unable to create zero byte empty block.",
1326 		 function );
1327 
1328 		goto on_error;
1329 	}
1330 	if( memory_set(
1331 	     zero_byte_empty_block,
1332 	     0,
1333 	     sizeof( uint8_t ) * (size_t) media_values->chunk_size ) == NULL )
1334 	{
1335 		libcerror_error_set(
1336 		 error,
1337 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1338 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1339 		 "%s: unable to clear zero byte empty block.",
1340 		 function );
1341 
1342 		goto on_error;
1343 	}
1344 	write_io_handle->compressed_zero_byte_empty_block_size = 512;
1345 
1346 	compressed_zero_byte_empty_block = (uint8_t *) memory_allocate(
1347 			                                sizeof( uint8_t ) * write_io_handle->compressed_zero_byte_empty_block_size );
1348 
1349 	if( compressed_zero_byte_empty_block == NULL )
1350 	{
1351 		libcerror_error_set(
1352 		 error,
1353 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1354 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1355 		 "%s: unable to create compressed zero byte empty block.",
1356 		 function );
1357 
1358 		goto on_error;
1359 	}
1360 	compression_level = io_handle->compression_level;
1361 
1362 	if( compression_level == EWF_COMPRESSION_NONE )
1363 	{
1364 		compression_level = EWF_COMPRESSION_DEFAULT;
1365 	}
1366 	result = libewf_compress_data(
1367 		  compressed_zero_byte_empty_block,
1368 		  &( write_io_handle->compressed_zero_byte_empty_block_size ),
1369 		  compression_level,
1370 		  zero_byte_empty_block,
1371 		  (size_t) media_values->chunk_size,
1372 		  error );
1373 
1374 	/* Check if the compressed buffer was too small
1375 	 * and a new compressed data size buffer was passed back
1376 	 */
1377 	if( ( result == -1 )
1378 	 && ( write_io_handle->compressed_zero_byte_empty_block_size > 0 ) )
1379 	{
1380 #if !defined( HAVE_COMPRESS_BOUND ) && !defined( WINAPI )
1381 		/* The some version of zlib require a fairly large buffer
1382 		 * if compressBound() was not used but 2 x 512 then assume
1383 		 * the chunk size + 16 is sufficient
1384 		 */
1385 		write_io_handle->compressed_zero_byte_empty_block_size = media_values->chunk_size + 16;
1386 #endif
1387 
1388 		libcerror_error_free(
1389 		 error );
1390 
1391 		reallocation = memory_reallocate(
1392 		                compressed_zero_byte_empty_block,
1393 		                sizeof( uint8_t ) * write_io_handle->compressed_zero_byte_empty_block_size );
1394 
1395 		if( reallocation == NULL )
1396 		{
1397 			libcerror_error_set(
1398 			 error,
1399 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1400 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1401 			 "%s: unable to resize compressed zero byte empty block.",
1402 			 function );
1403 
1404 			return( -1 );
1405 		}
1406 		compressed_zero_byte_empty_block = (uint8_t *) reallocation;
1407 
1408 		result = libewf_compress_data(
1409 		          compressed_zero_byte_empty_block,
1410 		          &( write_io_handle->compressed_zero_byte_empty_block_size ),
1411 		          io_handle->compression_level,
1412 		          zero_byte_empty_block,
1413 		          (size_t) media_values->chunk_size,
1414 		          error );
1415 	}
1416 	if( result != 1 )
1417 	{
1418 		libcerror_error_free(
1419 		 error );
1420 
1421 		memory_free(
1422 		 compressed_zero_byte_empty_block );
1423 
1424 		write_io_handle->compressed_zero_byte_empty_block_size = 0;
1425 	}
1426 	else
1427 	{
1428 		write_io_handle->compressed_zero_byte_empty_block = compressed_zero_byte_empty_block;
1429 	}
1430 	compressed_zero_byte_empty_block = NULL;
1431 
1432 	memory_free(
1433 	 zero_byte_empty_block );
1434 
1435 	zero_byte_empty_block = NULL;
1436 
1437 	return( 1 );
1438 
1439 on_error:
1440 	if( compressed_zero_byte_empty_block != NULL )
1441 	{
1442 		memory_free(
1443 		 compressed_zero_byte_empty_block );
1444 	}
1445 	if( zero_byte_empty_block != NULL )
1446 	{
1447 		memory_free(
1448 		 zero_byte_empty_block );
1449 	}
1450 	return( -1 );
1451 }
1452 
1453 /* Calculates an estimate of the number of chunks that fit within a segment file
1454  * Returns 1 if successful or -1 on error
1455  */
libewf_write_io_handle_calculate_chunks_per_segment_file(uint32_t * chunks_per_segment_file,size64_t remaining_segment_file_size,uint32_t maximum_chunks_per_section,uint32_t number_of_chunks_written_to_segment,uint32_t number_of_chunks_written,libewf_media_values_t * media_values,uint8_t format,uint8_t ewf_format,uint8_t unrestrict_offset_table,libcerror_error_t ** error)1456 int libewf_write_io_handle_calculate_chunks_per_segment_file(
1457      uint32_t *chunks_per_segment_file,
1458      size64_t remaining_segment_file_size,
1459      uint32_t maximum_chunks_per_section,
1460      uint32_t number_of_chunks_written_to_segment,
1461      uint32_t number_of_chunks_written,
1462      libewf_media_values_t *media_values,
1463      uint8_t format,
1464      uint8_t ewf_format,
1465      uint8_t unrestrict_offset_table,
1466      libcerror_error_t **error )
1467 {
1468 	static char *function                      = "libewf_write_io_handle_calculate_chunks_per_segment_file";
1469 	int64_t calculated_chunks_per_segment_file = 0;
1470 	int64_t maximum_chunks_per_segment_file    = 0;
1471 	int64_t remaining_number_of_chunks         = 0;
1472 	int64_t required_chunk_sections            = 0;
1473 
1474 	if( chunks_per_segment_file == NULL )
1475 	{
1476 		libcerror_error_set(
1477 		 error,
1478 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1479 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1480 		 "%s: invalid chunks per segment file.",
1481 		 function );
1482 
1483 		return( -1 );
1484 	}
1485 	if( maximum_chunks_per_section == 0 )
1486 	{
1487 		libcerror_error_set(
1488 		 error,
1489 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1490 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1491 		 "%s: invalid maximum chunks per section.",
1492 		 function );
1493 
1494 		return( -1 );
1495 	}
1496 	if( media_values == NULL )
1497 	{
1498 		libcerror_error_set(
1499 		 error,
1500 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1501 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1502 		 "%s: invalid media values.",
1503 		 function );
1504 
1505 		return( -1 );
1506 	}
1507 	/* Calculate the maximum number of chunks within this segment file
1508 	 */
1509 	maximum_chunks_per_segment_file = remaining_segment_file_size;
1510 
1511 	if( ewf_format == EWF_FORMAT_S01 )
1512 	{
1513 		/* The EWF-S01 format uses compression this will add 16 bytes on average
1514 		 */
1515 		maximum_chunks_per_segment_file /= media_values->chunk_size + 16;
1516 	}
1517 	else
1518 	{
1519 		maximum_chunks_per_segment_file /= media_values->chunk_size + sizeof( uint32_t );
1520 	}
1521 	/* Determine the number of required chunk sections
1522 	 */
1523 	if( unrestrict_offset_table == 0 )
1524 	{
1525 		required_chunk_sections = maximum_chunks_per_segment_file
1526 		                        % maximum_chunks_per_section;
1527 	}
1528 	else
1529 	{
1530 		required_chunk_sections = 1;
1531 	}
1532 	calculated_chunks_per_segment_file = remaining_segment_file_size;
1533 
1534 	if( ewf_format == EWF_FORMAT_S01 )
1535 	{
1536 		/* Leave space for the chunk section starts
1537 		 */
1538 		calculated_chunks_per_segment_file -= required_chunk_sections
1539 		                                    * sizeof( ewf_section_start_t );
1540 
1541 		/* Leave space for the table offsets
1542 		 */
1543 		calculated_chunks_per_segment_file -= maximum_chunks_per_segment_file
1544 		                                    * sizeof( ewf_table_offset_t );
1545 	}
1546 	else if( format == LIBEWF_FORMAT_ENCASE1 )
1547 	{
1548 		/* Leave space for the chunk section starts and the offset table checksum
1549 		 */
1550 		calculated_chunks_per_segment_file -= required_chunk_sections
1551 		                                    * ( sizeof( ewf_section_start_t ) + sizeof( uint32_t ) );
1552 
1553 		/* Leave space for the table offsets
1554 		 */
1555 		calculated_chunks_per_segment_file -= maximum_chunks_per_segment_file
1556 		                                    * sizeof( ewf_table_offset_t );
1557 	}
1558 	else
1559 	{
1560 		/* Leave space for the chunk, table and table2 section starts and the table and table2 offset table checksums
1561 		 */
1562 		calculated_chunks_per_segment_file -= required_chunk_sections
1563 		                                    * ( ( 3 * sizeof( ewf_section_start_t ) ) + ( 2 * sizeof( uint32_t ) ) );
1564 
1565 		/* Leave space for the table and table2 offsets
1566 		 */
1567 		calculated_chunks_per_segment_file -= 2 * maximum_chunks_per_segment_file
1568 		                                    * sizeof( ewf_table_offset_t );
1569 	}
1570 	/* Calculate the number of chunks within this segment file
1571 	 */
1572 	if( ewf_format == EWF_FORMAT_S01 )
1573 	{
1574 		/* The EWF-S01 format uses compression this will add 16 bytes on average
1575 		 */
1576 		calculated_chunks_per_segment_file /= media_values->chunk_size + 16;
1577 	}
1578 	else
1579 	{
1580 		calculated_chunks_per_segment_file /= media_values->chunk_size + sizeof( uint32_t );
1581 	}
1582 	/* If the input size is known determine the remaining number of chunks
1583 	 */
1584 	if( media_values->media_size > 0 )
1585 	{
1586 		remaining_number_of_chunks = (int64_t) media_values->number_of_chunks
1587 		                           - (int64_t) number_of_chunks_written;
1588 
1589 		/* Check if less chunks remain than the number of chunks calculated
1590 		 */
1591 		if( remaining_number_of_chunks < calculated_chunks_per_segment_file )
1592 		{
1593 			calculated_chunks_per_segment_file = remaining_number_of_chunks;
1594 		}
1595 	}
1596 	/* Make sure to return the total number of chunks per segment file
1597 	 */
1598 	if( number_of_chunks_written_to_segment > 0 )
1599 	{
1600 		calculated_chunks_per_segment_file += number_of_chunks_written_to_segment;
1601 	}
1602 	/* Fail safe segment should contain at least 1 chunk
1603 	 */
1604 	if( calculated_chunks_per_segment_file <= 0 )
1605 	{
1606 		calculated_chunks_per_segment_file = 1;
1607 	}
1608 	/* Fail safe no more than 2^32 values are allowed
1609 	 */
1610 	else if( calculated_chunks_per_segment_file > (int64_t) UINT32_MAX )
1611 	{
1612 		calculated_chunks_per_segment_file = UINT32_MAX;
1613 	}
1614 	*chunks_per_segment_file = (uint32_t) calculated_chunks_per_segment_file;
1615 
1616 	return( 1 );
1617 }
1618 
1619 /* Calculates the number of chunks that fit within a (chunks) section
1620  * Returns 1 if successful or -1 on error
1621  */
libewf_write_io_handle_calculate_chunks_per_section(uint32_t * chunks_per_section,uint32_t maximum_chunks_per_section,uint32_t number_of_chunks_written_to_segment,uint32_t chunks_per_segment_file,uint8_t unrestrict_offset_table,libcerror_error_t ** error)1622 int libewf_write_io_handle_calculate_chunks_per_section(
1623      uint32_t *chunks_per_section,
1624      uint32_t maximum_chunks_per_section,
1625      uint32_t number_of_chunks_written_to_segment,
1626      uint32_t chunks_per_segment_file,
1627      uint8_t unrestrict_offset_table,
1628      libcerror_error_t **error )
1629 {
1630 	static char *function               = "libewf_write_io_handle_calculate_chunks_per_section";
1631 	uint32_t remaining_number_of_chunks = 0;
1632 
1633 	if( chunks_per_section == NULL )
1634 	{
1635 		libcerror_error_set(
1636 		 error,
1637 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1638 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1639 		 "%s: invalid chunks per section.",
1640 		 function );
1641 
1642 		return( -1 );
1643 	}
1644 	if( maximum_chunks_per_section == 0 )
1645 	{
1646 		libcerror_error_set(
1647 		 error,
1648 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1649 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1650 		 "%s: invalid maximum chunks per section.",
1651 		 function );
1652 
1653 		return( -1 );
1654 	}
1655 	if( number_of_chunks_written_to_segment > chunks_per_segment_file )
1656 	{
1657 		libcerror_error_set(
1658 		 error,
1659 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1660 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1661 		 "%s: number of chunks written to segment exceeds number of chunks per segment file.",
1662 		 function );
1663 
1664 		return( -1 );
1665 	}
1666         remaining_number_of_chunks = chunks_per_segment_file - number_of_chunks_written_to_segment;
1667 
1668 	if( ( unrestrict_offset_table == 0 )
1669 	 && ( remaining_number_of_chunks > (int64_t) maximum_chunks_per_section ) )
1670 	{
1671 		remaining_number_of_chunks = (int64_t) maximum_chunks_per_section;
1672 	}
1673 	/* Fail safe no more than 2^31 values are allowed
1674 	 */
1675 	if( remaining_number_of_chunks > (int64_t) INT32_MAX )
1676 	{
1677 		remaining_number_of_chunks = INT32_MAX;
1678 	}
1679 	*chunks_per_section = (uint32_t) remaining_number_of_chunks;
1680 
1681 	return( 1 );
1682 }
1683 
1684 /* Tests if the current segment file is full
1685  * Returns 1 if full, 0 if not or -1 on error
1686  */
libewf_write_io_handle_test_segment_file_full(ssize64_t remaining_segment_file_size,uint32_t number_of_chunks_written_to_segment,libewf_media_values_t * media_values,ssize64_t input_write_count,uint32_t chunks_per_segment_file,uint32_t number_of_chunks_written,uint8_t format,uint8_t ewf_format,libcerror_error_t ** error)1687 int libewf_write_io_handle_test_segment_file_full(
1688      ssize64_t remaining_segment_file_size,
1689      uint32_t number_of_chunks_written_to_segment,
1690      libewf_media_values_t *media_values,
1691      ssize64_t input_write_count,
1692      uint32_t chunks_per_segment_file,
1693      uint32_t number_of_chunks_written,
1694      uint8_t format,
1695      uint8_t ewf_format,
1696      libcerror_error_t **error )
1697 {
1698 	static char *function = "libewf_write_io_handle_test_segment_file_full";
1699 
1700 	if( media_values == NULL )
1701 	{
1702 		libcerror_error_set(
1703 		 error,
1704 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1705 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1706 		 "%s: invalid media values.",
1707 		 function );
1708 
1709 		return( -1 );
1710 	}
1711 	/* Check if the maximum number of chunks has been reached
1712 	 */
1713 	if( ( media_values->number_of_chunks != 0 )
1714 	 && ( media_values->number_of_chunks == number_of_chunks_written ) )
1715 	{
1716 #if defined( HAVE_DEBUG_OUTPUT )
1717 		if( libcnotify_verbose != 0 )
1718 		{
1719 			libcnotify_printf(
1720 			 "%s: all required chunks have been written.\n",
1721 			 function );
1722 		}
1723 #endif
1724 
1725 		return( 1 );
1726 	}
1727 	/* Check if the end of the input has been reached
1728 	*/
1729 	if( ( media_values->media_size != 0 )
1730 	 && ( input_write_count >= (ssize64_t) media_values->media_size ) )
1731 	{
1732 #if defined( HAVE_DEBUG_OUTPUT )
1733 		if( libcnotify_verbose != 0 )
1734 		{
1735 			libcnotify_printf(
1736 			 "%s: all required data has been written.\n",
1737 			 function );
1738 		}
1739 #endif
1740 
1741 		return( 1 );
1742 	}
1743 	/* The EWF-S01 and EnCase1 format should use the pre calculated size
1744 	 */
1745 	if( ( ewf_format == EWF_FORMAT_S01 )
1746 	 || ( format == LIBEWF_FORMAT_ENCASE1 ) )
1747 	{
1748 		if( number_of_chunks_written_to_segment >= chunks_per_segment_file )
1749 		{
1750 #if defined( HAVE_DEBUG_OUTPUT )
1751 			if( libcnotify_verbose != 0 )
1752 			{
1753 				libcnotify_printf(
1754 			 	"%s: no space left for additional chunk.\n",
1755 				 function );
1756 			}
1757 #endif
1758 
1759 			return( 1 );
1760 		}
1761 	}
1762 	/* Determine if a chunk would fit in the segment file
1763 	 */
1764 	else if( remaining_segment_file_size < (ssize64_t) ( media_values->chunk_size + sizeof( uint32_t ) ) )
1765 	{
1766 #if defined( HAVE_DEBUG_OUTPUT )
1767 		if( libcnotify_verbose != 0 )
1768 		{
1769 			libcnotify_printf(
1770 			 "%s: no space left for additional chunk - file size exceeded.\n",
1771 			 function );
1772 		}
1773 #endif
1774 
1775 		return( 1 );
1776 	}
1777 #if defined( HAVE_DEBUG_OUTPUT )
1778 	if( libcnotify_verbose != 0 )
1779 	{
1780 		libcnotify_printf(
1781 		 "%s: space left for additional chunk.\n",
1782 		 function );
1783 	}
1784 #endif
1785 
1786 	return( 0 );
1787 }
1788 
1789 /* Tests if the current chunks section is full
1790  * Returns 1 if full, 0 if not or -1 on error
1791  */
libewf_write_io_handle_test_chunks_section_full(off64_t chunks_section_offset,ssize64_t remaining_segment_file_size,libewf_media_values_t * media_values,ssize64_t input_write_count,off64_t segment_file_offset,uint32_t maximum_chunks_per_section,uint32_t number_of_chunks_written_to_section,uint32_t number_of_chunks_written,uint32_t chunks_per_section,uint8_t format,uint8_t ewf_format,uint8_t unrestrict_offset_table,libcerror_error_t ** error)1792 int libewf_write_io_handle_test_chunks_section_full(
1793      off64_t chunks_section_offset,
1794      ssize64_t remaining_segment_file_size,
1795      libewf_media_values_t *media_values,
1796      ssize64_t input_write_count,
1797      off64_t segment_file_offset,
1798      uint32_t maximum_chunks_per_section,
1799      uint32_t number_of_chunks_written_to_section,
1800      uint32_t number_of_chunks_written,
1801      uint32_t chunks_per_section,
1802      uint8_t format,
1803      uint8_t ewf_format,
1804      uint8_t unrestrict_offset_table,
1805      libcerror_error_t **error )
1806 {
1807 	static char *function = "libewf_write_io_handle_test_chunks_section_full";
1808 
1809 	if( media_values == NULL )
1810 	{
1811 		libcerror_error_set(
1812 		 error,
1813 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1814 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1815 		 "%s: invalid media values.",
1816 		 function );
1817 
1818 		return( -1 );
1819 	}
1820 	if( segment_file_offset > (off64_t) INT64_MAX )
1821 	{
1822 		libcerror_error_set(
1823 		 error,
1824 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1825 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1826 		 "%s: invalid segment file offset value exceeds maximum.",
1827 		 function );
1828 
1829 		return( -1 );
1830 	}
1831 	if( maximum_chunks_per_section == 0 )
1832 	{
1833 		libcerror_error_set(
1834 		 error,
1835 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1836 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1837 		 "%s: invalid maximum chunks per section.",
1838 		 function );
1839 
1840 		return( -1 );
1841 	}
1842 	/* Check if a chunks section has been opened
1843 	 */
1844 	if( chunks_section_offset == 0 )
1845 	{
1846 #if defined( HAVE_DEBUG_OUTPUT )
1847 		if( libcnotify_verbose != 0 )
1848 		{
1849 			libcnotify_printf(
1850 			 "%s: no chunks section has been created.\n",
1851 			 function );
1852 		}
1853 #endif
1854 
1855 		return( 0 );
1856 	}
1857 	/* Check if the maximum number of chunks has been reached
1858 	 */
1859 	if( ( media_values->number_of_chunks != 0 )
1860 	 && ( media_values->number_of_chunks == number_of_chunks_written ) )
1861 	{
1862 #if defined( HAVE_DEBUG_OUTPUT )
1863 		if( libcnotify_verbose != 0 )
1864 		{
1865 			libcnotify_printf(
1866 			 "%s: all required chunks have been written.\n",
1867 			 function );
1868 		}
1869 #endif
1870 
1871 		return( 1 );
1872 	}
1873 	/* Check if the end of the input has been reached
1874 	*/
1875 	if( ( media_values->media_size != 0 )
1876 	 && ( input_write_count >= (ssize64_t) media_values->media_size ) )
1877 	{
1878 #if defined( HAVE_DEBUG_OUTPUT )
1879 		if( libcnotify_verbose != 0 )
1880 		{
1881 			libcnotify_printf(
1882 			 "%s: all required data has been written.\n",
1883 			 function );
1884 		}
1885 #endif
1886 		return( 1 );
1887 	}
1888 	/* Check if the maximum number of chunks restriction should apply
1889 	 */
1890 	if( ( unrestrict_offset_table == 0 )
1891 	 && ( number_of_chunks_written_to_section >= maximum_chunks_per_section ) )
1892 	{
1893 #if defined( HAVE_DEBUG_OUTPUT )
1894 		if( libcnotify_verbose != 0 )
1895 		{
1896 			libcnotify_printf(
1897 			 "%s: no space left for additional chunk - maximum reached.\n",
1898 			 function );
1899 		}
1900 #endif
1901 		return( 1 );
1902 	}
1903 	/* Fail safe no more than 2^31 chunks are allowed
1904 	 */
1905 	if( number_of_chunks_written_to_section > (uint32_t) INT32_MAX )
1906 	{
1907 #if defined( HAVE_DEBUG_OUTPUT )
1908 		if( libcnotify_verbose != 0 )
1909 		{
1910 			libcnotify_printf(
1911 			 "%s: no space left for additional chunk - preventing chunk overflow.\n",
1912 			 function );
1913 		}
1914 #endif
1915 		return( 1 );
1916 	}
1917 	/* Prevent offset overflow
1918 	 */
1919 	if( ( segment_file_offset - chunks_section_offset ) > (off64_t) INT32_MAX )
1920 	{
1921 #if defined( HAVE_DEBUG_OUTPUT )
1922 		if( libcnotify_verbose != 0 )
1923 		{
1924 			libcnotify_printf(
1925 			 "%s: no space left for additional chunk - preventing offset overflow.\n",
1926 			 function );
1927 		}
1928 #endif
1929 		return( 1 );
1930 	}
1931 	/* The EWF-S01 and EnCase1 format do not allow for a growth of the offset table
1932 	 */
1933 	if( ( ewf_format == EWF_FORMAT_S01 )
1934 	 || ( format == LIBEWF_FORMAT_ENCASE1 ) )
1935 	{
1936 		if( number_of_chunks_written_to_section >= chunks_per_section )
1937 		{
1938 #if defined( HAVE_DEBUG_OUTPUT )
1939 			if( libcnotify_verbose != 0 )
1940 			{
1941 				libcnotify_printf(
1942 				 "%s: no space left for additional chunk.\n",
1943 				 function );
1944 			}
1945 #endif
1946 
1947 			return( 1 );
1948 		}
1949 	}
1950 	/* Determine if a chunk would fit in the segment file
1951 	 */
1952 	else if( remaining_segment_file_size < (ssize64_t) ( media_values->chunk_size + sizeof( uint32_t ) ) )
1953 	{
1954 #if defined( HAVE_DEBUG_OUTPUT )
1955 		if( libcnotify_verbose != 0 )
1956 		{
1957 			libcnotify_printf(
1958 		 	"%s: no space left for additional chunk - file size exceeded.\n",
1959 			 function );
1960 		}
1961 #endif
1962 
1963 		return( 1 );
1964 	}
1965 #if defined( HAVE_DEBUG_OUTPUT )
1966 	if( libcnotify_verbose != 0 )
1967 	{
1968 		libcnotify_printf(
1969 	 	"%s: space left for additional chunk.\n",
1970 		 function );
1971 	}
1972 #endif
1973 
1974 	return( 0 );
1975 }
1976 
1977 /* Creates a new segment file and opens it for writing
1978  * The necessary sections at the start of the segment file are written
1979  * Returns 1 if successful or -1 on error
1980  */
libewf_write_io_handle_create_segment_file(libewf_io_handle_t * io_handle,libbfio_pool_t * file_io_pool,libmfdata_file_list_t * segment_files_list,libfcache_cache_t * segment_files_cache,libewf_segment_table_t * segment_table,uint16_t segment_number,uint16_t maximum_number_of_segments,uint8_t segment_file_type,libewf_segment_file_t ** segment_file,int * segment_files_list_index,int * file_io_pool_entry,libcerror_error_t ** error)1981 int libewf_write_io_handle_create_segment_file(
1982      libewf_io_handle_t *io_handle,
1983      libbfio_pool_t *file_io_pool,
1984      libmfdata_file_list_t *segment_files_list,
1985      libfcache_cache_t *segment_files_cache,
1986      libewf_segment_table_t *segment_table,
1987      uint16_t segment_number,
1988      uint16_t maximum_number_of_segments,
1989      uint8_t segment_file_type,
1990      libewf_segment_file_t **segment_file,
1991      int *segment_files_list_index,
1992      int *file_io_pool_entry,
1993      libcerror_error_t **error )
1994 {
1995 	libbfio_handle_t *file_io_handle = NULL;
1996 	system_character_t *filename     = NULL;
1997 	static char *function            = "libewf_write_io_handle_create_segment_file";
1998 	size_t filename_size             = 0;
1999 	int bfio_access_flags            = 0;
2000 
2001 	if( segment_table == NULL )
2002 	{
2003 		libcerror_error_set(
2004 		 error,
2005 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2006 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2007 		 "%s: invalid segment table.",
2008 		 function );
2009 
2010 		return( -1 );
2011 	}
2012 	if( io_handle == NULL )
2013 	{
2014 		libcerror_error_set(
2015 		 error,
2016 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2017 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2018 		 "%s: invalid IO handle.",
2019 		 function );
2020 
2021 		return( -1 );
2022 	}
2023 	if( segment_file == NULL )
2024 	{
2025 		libcerror_error_set(
2026 		 error,
2027 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2028 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2029 		 "%s: invalid segment file.",
2030 		 function );
2031 
2032 		return( -1 );
2033 	}
2034 	if( *segment_file != NULL )
2035 	{
2036 		libcerror_error_set(
2037 		 error,
2038 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2039 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2040 		 "%s: invalid segment file - value already set.",
2041 		 function );
2042 
2043 		return( -1 );
2044 	}
2045 	if( segment_files_list_index == NULL )
2046 	{
2047 		libcerror_error_set(
2048 		 error,
2049 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2050 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2051 		 "%s: invalid segment files list index.",
2052 		 function );
2053 
2054 		return( -1 );
2055 	}
2056 	if( file_io_pool_entry == NULL )
2057 	{
2058 		libcerror_error_set(
2059 		 error,
2060 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2061 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2062 		 "%s: invalid file IO pool entry.",
2063 		 function );
2064 
2065 		return( -1 );
2066 	}
2067 	if( libewf_filename_create(
2068 	     &filename,
2069 	     &filename_size,
2070 	     segment_table->basename,
2071 	     segment_table->basename_size - 1,
2072 	     segment_number,
2073 	     maximum_number_of_segments,
2074 	     segment_file_type,
2075 	     io_handle->format,
2076 	     io_handle->ewf_format,
2077 	     error ) != 1 )
2078 	{
2079 		libcerror_error_set(
2080 		 error,
2081 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2082 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2083 		 "%s: unable to create segment file: %" PRIu16 " filename.",
2084 		 function,
2085 		 segment_number );
2086 
2087 		goto on_error;
2088 	}
2089 	if( filename == NULL )
2090 	{
2091 		libcerror_error_set(
2092 		 error,
2093 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2094 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2095 		 "%s: missing filename.",
2096 		 function );
2097 
2098 		goto on_error;
2099 	}
2100 #if defined( HAVE_DEBUG_OUTPUT )
2101 	if( libcnotify_verbose != 0 )
2102 	{
2103 		libcnotify_printf(
2104 		 "%s: creating segment file: %" PRIu16 " with filename: %" PRIs_SYSTEM ".\n",
2105 		 function,
2106 		 segment_number,
2107 		 filename );
2108 	}
2109 #endif
2110 	if( libbfio_file_initialize(
2111 	     &file_io_handle,
2112 	     error ) != 1 )
2113 	{
2114 		libcerror_error_set(
2115 		 error,
2116 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2117 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2118 		 "%s: unable to create file IO handle.",
2119 		 function );
2120 
2121 		goto on_error;
2122 	}
2123 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
2124 	if( libbfio_file_set_name_wide(
2125 	     file_io_handle,
2126 	     filename,
2127 	     filename_size,
2128 	     error ) != 1 )
2129 #else
2130 	if( libbfio_file_set_name(
2131 	     file_io_handle,
2132 	     filename,
2133 	     filename_size,
2134 	     error ) != 1 )
2135 #endif
2136 	{
2137 		libcerror_error_set(
2138 		 error,
2139 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2140 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2141 		 "%s: unable to set filename in file IO handle.",
2142 		 function );
2143 
2144 		goto on_error;
2145 	}
2146 	memory_free(
2147 	 filename );
2148 
2149 	filename = NULL;
2150 
2151 	if( segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_DWF )
2152 	{
2153 		bfio_access_flags = LIBBFIO_OPEN_READ_WRITE_TRUNCATE;
2154 	}
2155 	else
2156 	{
2157 		bfio_access_flags = LIBBFIO_OPEN_WRITE_TRUNCATE;
2158 	}
2159 	if( libbfio_pool_append_handle(
2160 	     file_io_pool,
2161 	     file_io_pool_entry,
2162 	     file_io_handle,
2163 	     bfio_access_flags,
2164 	     error ) != 1 )
2165 	{
2166 		libcerror_error_set(
2167 		 error,
2168 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2169 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2170 		 "%s: unable to append file IO handle to pool.",
2171 		 function );
2172 
2173 		goto on_error;
2174 	}
2175 	file_io_handle = NULL;
2176 
2177 	if( libbfio_pool_open(
2178 	     file_io_pool,
2179 	     *file_io_pool_entry,
2180 	     bfio_access_flags,
2181 	     error ) != 1 )
2182 	{
2183 		libcerror_error_set(
2184 		 error,
2185 		 LIBCERROR_ERROR_DOMAIN_IO,
2186 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
2187 		 "%s: unable to open file IO pool entry: %d.",
2188 		 function,
2189 		 *file_io_pool_entry );
2190 
2191 		goto on_error;
2192 	}
2193 	if( libewf_segment_file_initialize(
2194 	     segment_file,
2195 	     error ) != 1 )
2196 	{
2197 		libcerror_error_set(
2198 		 error,
2199 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2200 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2201 		 "%s: unable to create segment file.",
2202 		 function );
2203 
2204 		goto on_error;
2205 	}
2206 	( *segment_file )->type           = segment_file_type;
2207 	( *segment_file )->segment_number = segment_number;
2208 	( *segment_file )->flags         |= LIBEWF_SEGMENT_FILE_FLAG_WRITE_OPEN;
2209 
2210 	if( libmfdata_file_list_append_file(
2211 	     segment_files_list,
2212 	     segment_files_list_index,
2213 	     *file_io_pool_entry,
2214 	     error ) != 1 )
2215 	{
2216 		libcerror_error_set(
2217 		 error,
2218 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2219 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2220 		 "%s: unable to set segment file: %" PRIu16 " in list.",
2221 		 function,
2222 		 segment_number );
2223 
2224 		goto on_error;
2225 	}
2226 	if( libmfdata_file_list_set_file_value_by_index(
2227 	     segment_files_list,
2228 	     segment_files_cache,
2229 	     *segment_files_list_index,
2230 	     (intptr_t *) *segment_file,
2231 	     (int (*)(intptr_t **, libcerror_error_t **)) &libewf_segment_file_free,
2232 	     LIBMFDATA_FILE_VALUE_FLAG_MANAGED,
2233 	     error ) != 1 )
2234 	{
2235 		libcerror_error_set(
2236 		 error,
2237 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2238 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2239 		 "%s: unable to set segment file: %" PRIu16 " value in list.",
2240 		 function,
2241 		 segment_number );
2242 
2243 		*segment_file = NULL;
2244 
2245 		goto on_error;
2246 	}
2247 	return( 1 );
2248 
2249 on_error:
2250 	if( *segment_file != NULL )
2251 	{
2252 		libewf_segment_file_free(
2253 		 segment_file,
2254 		 NULL );
2255 	}
2256 	if( file_io_handle != NULL )
2257 	{
2258 		libbfio_handle_free(
2259 		 &file_io_handle,
2260 		 NULL );
2261 	}
2262 	if( filename != NULL )
2263 	{
2264 		memory_free(
2265 		 filename );
2266 	}
2267 	return( -1 );
2268 
2269 }
2270 
2271 /* Writes a new chunk of data in EWF format at the current offset
2272  * The necessary settings of the write values must have been made
2273  * Returns the number of bytes written, 0 when no longer bytes can be written or -1 on error
2274  */
libewf_write_io_handle_write_new_chunk(libewf_write_io_handle_t * write_io_handle,libewf_io_handle_t * io_handle,libbfio_pool_t * file_io_pool,libewf_media_values_t * media_values,libmfdata_file_list_t * segment_files_list,libfcache_cache_t * segment_files_cache,libewf_segment_table_t * segment_table,libmfdata_list_t * chunk_table_list,libfvalue_table_t * header_values,libfvalue_table_t * hash_values,libewf_header_sections_t * header_sections,libewf_hash_sections_t * hash_sections,libcdata_array_t * sessions,libcdata_array_t * tracks,libcdata_range_list_t * acquiry_errors,int chunk_index,uint8_t * chunk_buffer,size_t chunk_buffer_size,size_t chunk_data_size,int8_t is_compressed,uint8_t * checksum_buffer,uint32_t chunk_checksum,int8_t write_checksum,libcerror_error_t ** error)2275 ssize_t libewf_write_io_handle_write_new_chunk(
2276          libewf_write_io_handle_t *write_io_handle,
2277          libewf_io_handle_t *io_handle,
2278          libbfio_pool_t *file_io_pool,
2279          libewf_media_values_t *media_values,
2280          libmfdata_file_list_t *segment_files_list,
2281          libfcache_cache_t *segment_files_cache,
2282          libewf_segment_table_t *segment_table,
2283          libmfdata_list_t *chunk_table_list,
2284          libfvalue_table_t *header_values,
2285          libfvalue_table_t *hash_values,
2286          libewf_header_sections_t *header_sections,
2287          libewf_hash_sections_t *hash_sections,
2288          libcdata_array_t *sessions,
2289          libcdata_array_t *tracks,
2290          libcdata_range_list_t *acquiry_errors,
2291          int chunk_index,
2292          uint8_t *chunk_buffer,
2293          size_t chunk_buffer_size,
2294          size_t chunk_data_size,
2295          int8_t is_compressed,
2296          uint8_t *checksum_buffer,
2297          uint32_t chunk_checksum,
2298          int8_t write_checksum,
2299          libcerror_error_t **error )
2300 {
2301 	libewf_segment_file_t *segment_file = NULL;
2302 	void *reallocation                  = NULL;
2303 	static char *function               = "libewf_write_io_handle_write_new_chunk";
2304 	off64_t segment_file_offset         = 0;
2305 	ssize_t total_write_count           = 0;
2306 	ssize_t write_count                 = 0;
2307 	int chunk_exists                    = 0;
2308 	int file_io_pool_entry              = -1;
2309 	int insufficient_output_space       = 0;
2310 	int number_of_chunks                = 0;
2311 	int number_of_segment_files         = 0;
2312 	int result                          = 0;
2313 	int segment_files_list_index        = 0;
2314 
2315 	if( write_io_handle == NULL )
2316 	{
2317 		libcerror_error_set(
2318 		 error,
2319 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2320 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2321 		 "%s: invalid write IO handle.",
2322 		 function );
2323 
2324 		return( -1 );
2325 	}
2326 	if( io_handle == NULL )
2327 	{
2328 		libcerror_error_set(
2329 		 error,
2330 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2331 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2332 		 "%s: invalid IO handle.",
2333 		 function );
2334 
2335 		return( -1 );
2336 	}
2337 	if( media_values == NULL )
2338 	{
2339 		libcerror_error_set(
2340 		 error,
2341 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2342 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2343 		 "%s: invalid media values.",
2344 		 function );
2345 
2346 		return( -1 );
2347 	}
2348 	if( segment_table == NULL )
2349 	{
2350 		libcerror_error_set(
2351 		 error,
2352 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2353 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2354 		 "%s: invalid segment table.",
2355 		 function );
2356 
2357 		return( -1 );
2358 	}
2359 	chunk_exists = libmfdata_list_is_set(
2360 			chunk_table_list,
2361 			chunk_index,
2362 			error );
2363 
2364 	if( chunk_exists == -1 )
2365 	{
2366 		libcerror_error_set(
2367 		 error,
2368 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2369 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2370 		 "%s: unable to determine if the chunk: %d exists in the chunk table.",
2371 		 function,
2372 		 chunk_index );
2373 
2374 		return( -1 );
2375 	}
2376 	else if( chunk_exists != 0 )
2377 	{
2378 		libcerror_error_set(
2379 		 error,
2380 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2381 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2382 		 "%s: invalid chunk: %d already exists.",
2383 		 function,
2384 		 chunk_index );
2385 
2386 		return( -1 );
2387 	}
2388 	/* Check if the write was already finalized
2389 	 */
2390 	if( write_io_handle->write_finalized != 0 )
2391 	{
2392 		return( 0 );
2393 	}
2394 	if( libmfdata_list_get_number_of_elements(
2395 	     chunk_table_list,
2396 	     &number_of_chunks,
2397 	     error ) != 1 )
2398 	{
2399 		libcerror_error_set(
2400 		 error,
2401 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2402 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2403 		 "%s: unable to retrieve the number of chunks in the chunk table.",
2404 		 function );
2405 
2406 		return( -1 );
2407 	}
2408 	/* Allocate the necessary number of chunk offsets
2409 	 * this reduces the number of reallocations
2410 	 */
2411 	if( (uint32_t) number_of_chunks < media_values->number_of_chunks )
2412         {
2413 		if( libmfdata_list_resize(
2414 		     chunk_table_list,
2415 		     (int) media_values->number_of_chunks,
2416 		     error ) != 1 )
2417 		{
2418 			libcerror_error_set(
2419 			 error,
2420 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2421 			 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
2422 			 "%s: unable to resize chunk table.",
2423 			 function );
2424 
2425 			return( -1 );
2426 		}
2427 	}
2428 	if( chunk_buffer == NULL )
2429 	{
2430 		libcerror_error_set(
2431 		 error,
2432 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2433 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2434 		 "%s: invalid chunk buffer.",
2435 		 function );
2436 
2437 		return( -1 );
2438 	}
2439 	if( ( chunk_buffer_size == 0 )
2440 	 || ( chunk_buffer_size > (size_t) SSIZE_MAX ) )
2441 	{
2442 		libcerror_error_set(
2443 		 error,
2444 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2445 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2446 		 "%s: invalid chunk size value out of bounds.",
2447 		 function );
2448 
2449 		return( -1 );
2450 	}
2451 	/* Check if the number of bytes as specified have been written
2452 	 */
2453 	if( ( media_values->media_size != 0 )
2454 	 && ( write_io_handle->input_write_count >= (ssize64_t) media_values->media_size ) )
2455 	{
2456 		return( 0 );
2457 	}
2458 #if defined( HAVE_DEBUG_OUTPUT )
2459 	if( libcnotify_verbose != 0 )
2460 	{
2461 		libcnotify_printf(
2462 	 	"%s: writing chunk: %d with size: %" PRIzd " (data size: %" PRIzd ").\n",
2463 		 function,
2464 		 chunk_index,
2465 		 chunk_buffer_size,
2466 		 chunk_data_size );
2467 	}
2468 #endif
2469 	if( libmfdata_file_list_get_number_of_files(
2470 	     segment_files_list,
2471 	     &number_of_segment_files,
2472 	     error ) != 1 )
2473 	{
2474 		libcerror_error_set(
2475 		 error,
2476 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2477 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2478 		 "%s: unable to retrieve number of segment files.",
2479 		 function );
2480 
2481 		return( -1 );
2482 	}
2483 	if( ( number_of_segment_files < 0 )
2484 	 || ( number_of_segment_files > (int) UINT16_MAX ) )
2485 	{
2486 		libcerror_error_set(
2487 		 error,
2488 	 	 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2489 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2490 		 "%s: invalid number of segment files value out of bounds.",
2491 		 function );
2492 
2493 		return( -1 );
2494 	}
2495 	if( number_of_segment_files != 0 )
2496 	{
2497 		segment_files_list_index = number_of_segment_files - 1;
2498 
2499 		if( libmfdata_file_list_get_file_value_by_index(
2500 		     segment_files_list,
2501 		     file_io_pool,
2502 		     segment_files_cache,
2503 		     segment_files_list_index,
2504 		     (intptr_t **) &segment_file,
2505 		     0,
2506 		     error ) != 1 )
2507 		{
2508 			libcerror_error_set(
2509 			 error,
2510 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2511 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2512 			 "%s: unable to retrieve segment file: %" PRIu16 " from list.",
2513 			 function,
2514 			 segment_files_list_index + 1 );
2515 
2516 			return( -1 );
2517 		}
2518 		if( segment_file == NULL )
2519 		{
2520 			libcerror_error_set(
2521 			 error,
2522 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2523 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2524 			 "%s: missing segment file: %" PRIu16 ".",
2525 			 function,
2526 			 segment_files_list_index + 1 );
2527 
2528 			return( -1 );
2529 		}
2530 		if( ( segment_file->flags & LIBEWF_SEGMENT_FILE_FLAG_WRITE_OPEN ) == 0 )
2531 		{
2532 			segment_file = NULL;
2533 
2534 			segment_files_list_index += 1;
2535 		}
2536 	}
2537 	if( segment_file == NULL )
2538 	{
2539 		if( header_sections == NULL )
2540 		{
2541 			libcerror_error_set(
2542 			 error,
2543 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2544 			 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2545 			 "%s: invalid header sections.",
2546 			 function );
2547 
2548 			return( -1 );
2549 		}
2550 		if( ( header_sections->header == NULL )
2551 		 && ( header_sections->header2 == NULL )
2552 		 && ( header_sections->xheader == NULL ) )
2553 		{
2554 			if( libewf_header_sections_generate(
2555 			     header_sections,
2556 			     header_values,
2557 			     time( NULL ),
2558 			     io_handle->compression_level,
2559 			     io_handle->format,
2560 			     io_handle->header_codepage,
2561 			     error ) == -1 )
2562 			{
2563 				libcerror_error_set(
2564 				 error,
2565 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2566 				 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2567 				 "%s: unable to create header(s).",
2568 				 function );
2569 
2570 				return( -1 );
2571 			}
2572 		}
2573 		write_io_handle->create_chunks_section               = 1;
2574 		write_io_handle->chunks_per_section                  = 0;
2575 		write_io_handle->number_of_chunks_written_to_segment = 0;
2576 
2577 #if defined( HAVE_DEBUG_OUTPUT )
2578 		if( libcnotify_verbose != 0 )
2579 		{
2580 			libcnotify_printf(
2581 			 "%s: creating segment file with segment number: %" PRIu16 ".\n",
2582 			 function,
2583 			 segment_files_list_index + 1 );
2584 		}
2585 #endif
2586 		if( libewf_write_io_handle_create_segment_file(
2587 		     io_handle,
2588 		     file_io_pool,
2589 		     segment_files_list,
2590 		     segment_files_cache,
2591 		     segment_table,
2592 		     (uint16_t) ( segment_files_list_index + 1 ),
2593 		     write_io_handle->maximum_number_of_segments,
2594 		     LIBEWF_SEGMENT_FILE_TYPE_EWF,
2595 		     &segment_file,
2596 		     &segment_files_list_index,
2597 		     &file_io_pool_entry,
2598 		     error ) != 1 )
2599 		{
2600 			libcerror_error_set(
2601 			 error,
2602 			 LIBCERROR_ERROR_DOMAIN_IO,
2603 			 LIBCERROR_IO_ERROR_OPEN_FAILED,
2604 			 "%s: unable to create segment file: %" PRIu16 ".",
2605 			 function,
2606 			 segment_files_list_index + 1 );
2607 
2608 			return( -1 );
2609 		}
2610 		/* Reserve space for the done or next section
2611 		 */
2612 		write_io_handle->remaining_segment_file_size = segment_table->maximum_segment_size
2613 		                                             - sizeof( ewf_section_start_t );
2614 
2615 		/* Write the start of the segment file
2616 		 * like the file header, the header, volume and/or data section, etc.
2617 		 */
2618 		write_count = libewf_segment_file_write_start(
2619 		               segment_file,
2620 		               io_handle,
2621 		               file_io_pool,
2622 		               file_io_pool_entry,
2623 		               media_values,
2624 		               header_sections,
2625 		               &( write_io_handle->data_section ),
2626 		               error );
2627 
2628 		if( write_count == -1 )
2629 		{
2630 			libcerror_error_set(
2631 			 error,
2632 			 LIBCERROR_ERROR_DOMAIN_IO,
2633 			 LIBCERROR_IO_ERROR_WRITE_FAILED,
2634 			 "%s: unable to write segment file start.",
2635 			 function );
2636 
2637 			return( -1 );
2638 		}
2639 		total_write_count                            += write_count;
2640 		write_io_handle->remaining_segment_file_size -= write_count;
2641 
2642 		/* Determine the number of chunks per segment file
2643 		 */
2644 		if( segment_file->number_of_chunks == 0 )
2645 		{
2646 			if( libewf_write_io_handle_calculate_chunks_per_segment_file(
2647 			     &( write_io_handle->chunks_per_segment_file ),
2648 			     write_io_handle->remaining_segment_file_size,
2649 			     write_io_handle->maximum_chunks_per_section,
2650 			     write_io_handle->number_of_chunks_written_to_segment,
2651 			     write_io_handle->number_of_chunks_written,
2652 			     media_values,
2653 			     io_handle->format,
2654 			     io_handle->ewf_format,
2655 			     write_io_handle->unrestrict_offset_table,
2656 			     error ) != 1 )
2657 			{
2658 				libcerror_error_set(
2659 				 error,
2660 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2661 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2662 				 "%s: unable to determine the number of chunks per segment file.",
2663 				 function );
2664 
2665 				return( -1 );
2666 			}
2667 #if defined( HAVE_DEBUG_OUTPUT )
2668 			if( libcnotify_verbose != 0 )
2669 			{
2670 				libcnotify_printf(
2671 				 "%s: calculated number of chunks per segment file: %" PRIu32 ".\n",
2672 				 function,
2673 				 write_io_handle->chunks_per_segment_file );
2674 			}
2675 #endif
2676 		}
2677 		else
2678 		{
2679 			write_io_handle->chunks_per_segment_file = segment_file->number_of_chunks;
2680 		}
2681 	}
2682 	else
2683 	{
2684 		if( libmfdata_file_list_get_file_by_index(
2685 		     segment_files_list,
2686 		     segment_files_list_index,
2687 		     &file_io_pool_entry,
2688 		     error ) != 1 )
2689 		{
2690 			libcerror_error_set(
2691 			 error,
2692 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2693 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2694 			 "%s: unable to retrieve segment file: %d from list.",
2695 			 function,
2696 			 segment_files_list_index + 1 );
2697 
2698 			return( -1 );
2699 		}
2700 	}
2701 	/* Set segment file to the correct offset if write is resumed
2702 	 */
2703 	if( write_io_handle->resume_segment_file_offset > 0 )
2704 	{
2705 		if( libbfio_pool_seek_offset(
2706 		     file_io_pool,
2707 		     file_io_pool_entry,
2708 		     write_io_handle->resume_segment_file_offset,
2709 		     SEEK_SET,
2710 		     error ) == -1 )
2711 		{
2712 			libcerror_error_set(
2713 			 error,
2714 			 LIBCERROR_ERROR_DOMAIN_IO,
2715 			 LIBCERROR_IO_ERROR_OPEN_FAILED,
2716 			 "%s: unable to seek resume segment file offset: %" PRIi64 " in segment file: %d.",
2717 			 function,
2718 			 write_io_handle->resume_segment_file_offset,
2719 			 segment_files_list_index + 1 );
2720 
2721 			return( -1 );
2722 		}
2723 		write_io_handle->resume_segment_file_offset = 0;
2724 	}
2725 	/* Check if a chunk section should be created
2726 	 */
2727 	if( write_io_handle->create_chunks_section == 1 )
2728 	{
2729 #if defined( HAVE_DEBUG_OUTPUT )
2730 		if( libcnotify_verbose != 0 )
2731 		{
2732 			libcnotify_printf(
2733 		 	"%s: creating chunks section.\n",
2734 			 function );
2735 		}
2736 #endif
2737 		write_io_handle->create_chunks_section               = 0;
2738 		write_io_handle->number_of_chunks_written_to_section = 0;
2739 		write_io_handle->chunks_section_write_count          = 0;
2740 
2741 		if( io_handle->ewf_format == EWF_FORMAT_S01 )
2742 		{
2743 			/* Leave space for the chunk section start
2744 			 */
2745 			write_io_handle->remaining_segment_file_size -= sizeof( ewf_section_start_t );
2746 		}
2747 		else if( io_handle->format == LIBEWF_FORMAT_ENCASE1 )
2748 		{
2749 			/* Leave space for the chunk section start and the offset table checksum
2750 			 */
2751 			write_io_handle->remaining_segment_file_size -= sizeof( ewf_section_start_t ) + sizeof( uint32_t );
2752 		}
2753 		else
2754 		{
2755 			/* Leave space for the chunk, table and table2 section starts and the table and table2 offset table checksums
2756 			 */
2757 			write_io_handle->remaining_segment_file_size -= ( 3 * sizeof( ewf_section_start_t ) ) + ( 2 * sizeof( uint32_t ) );
2758 		}
2759 		if( libbfio_pool_get_offset(
2760 		     file_io_pool,
2761 		     file_io_pool_entry,
2762 		     &( write_io_handle->chunks_section_offset ),
2763 		     error ) != 1 )
2764 		{
2765 			libcerror_error_set(
2766 			 error,
2767 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2768 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2769 			 "%s: unable to retrieve current offset in segment file.",
2770 			 function );
2771 
2772 			return( -1 );
2773 		}
2774 		/* Recalculate the number of chunks per segment file for a better segment file fill when compression is used
2775 		 */
2776 		if( segment_file->number_of_chunks == 0 )
2777 		{
2778 			if( libewf_write_io_handle_calculate_chunks_per_segment_file(
2779 			     &( write_io_handle->chunks_per_segment_file ),
2780 			     write_io_handle->remaining_segment_file_size,
2781 			     write_io_handle->maximum_chunks_per_section,
2782 			     write_io_handle->number_of_chunks_written_to_segment,
2783 			     write_io_handle->number_of_chunks_written,
2784 			     media_values,
2785 			     io_handle->format,
2786 			     io_handle->ewf_format,
2787 			     write_io_handle->unrestrict_offset_table,
2788 			     error ) != 1 )
2789 			{
2790 				libcerror_error_set(
2791 				 error,
2792 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2793 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2794 				 "%s: unable to determine the number of chunks per segment file.",
2795 				 function );
2796 
2797 				return( -1 );
2798 			}
2799 #if defined( HAVE_DEBUG_OUTPUT )
2800 			if( libcnotify_verbose != 0 )
2801 			{
2802 				libcnotify_printf(
2803 				 "%s: calculated number of chunks per segment file: %" PRIu32 ".\n",
2804 				 function,
2805 				 write_io_handle->chunks_per_segment_file );
2806 			}
2807 #endif
2808 		}
2809 		else
2810 		{
2811 			write_io_handle->chunks_per_segment_file = segment_file->number_of_chunks;
2812 		}
2813 		if( libewf_write_io_handle_calculate_chunks_per_section(
2814 		     &( write_io_handle->chunks_per_section ),
2815 		     write_io_handle->maximum_chunks_per_section,
2816 		     write_io_handle->number_of_chunks_written_to_segment,
2817 		     write_io_handle->chunks_per_segment_file,
2818 		     write_io_handle->unrestrict_offset_table,
2819 		     error ) != 1 )
2820 		{
2821 			libcerror_error_set(
2822 			 error,
2823 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2824 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2825 			 "%s: unable to determine the number of chunks per chunks section.",
2826 			 function );
2827 
2828 			return( -1 );
2829 		}
2830 #if defined( HAVE_DEBUG_OUTPUT )
2831 		if( libcnotify_verbose != 0 )
2832 		{
2833 			libcnotify_printf(
2834 		 	"%s: calculated number of chunks per section: %" PRIu32 ".\n",
2835 			 function,
2836 			 write_io_handle->chunks_per_section );
2837 		}
2838 #endif
2839 		if( write_io_handle->number_of_table_offsets < write_io_handle->chunks_per_section )
2840 		{
2841 			reallocation = memory_reallocate(
2842 			                write_io_handle->table_offsets,
2843 			                sizeof( ewf_table_offset_t ) * write_io_handle->chunks_per_section );
2844 
2845 			if( reallocation == NULL )
2846 			{
2847 				libcerror_error_set(
2848 				 error,
2849 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
2850 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2851 				 "%s: unable to create table offsets.",
2852 				 function );
2853 
2854 				return( -1 );
2855 			}
2856 			write_io_handle->table_offsets           = (ewf_table_offset_t *) reallocation;
2857 			write_io_handle->number_of_table_offsets = write_io_handle->chunks_per_section;
2858 		}
2859 		/* Write the section start of the chunks section
2860 		 */
2861 		write_count = libewf_segment_file_write_chunks_section_start(
2862 		               segment_file,
2863 		               io_handle,
2864 		               file_io_pool,
2865 		               file_io_pool_entry,
2866 		               write_io_handle->chunks_section_offset,
2867 		               chunk_table_list,
2868 		               write_io_handle->table_offsets,
2869 		               write_io_handle->number_of_table_offsets,
2870 		               write_io_handle->number_of_chunks_written,
2871 		               write_io_handle->chunks_per_section,
2872 		               error );
2873 
2874 		if( write_count == -1 )
2875 		{
2876 #if defined( HAVE_DEBUG_OUTPUT )
2877 			if( libcnotify_verbose != 0 )
2878 			{
2879 				libcnotify_printf(
2880 				 "%s: unable to write section start for chunks.\n",
2881 				 function );
2882 			}
2883 #endif
2884 
2885 			return( -1 );
2886 		}
2887 		total_write_count                            += write_count;
2888 		write_io_handle->remaining_segment_file_size -= write_count;
2889 	}
2890 	if( libbfio_pool_get_offset(
2891 	     file_io_pool,
2892 	     file_io_pool_entry,
2893 	     &segment_file_offset,
2894 	     error ) != 1 )
2895 	{
2896 		libcerror_error_set(
2897 		 error,
2898 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2899 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2900 		 "%s: unable to retrieve current offset in segment file.",
2901 		 function );
2902 
2903 		return( -1 );
2904 	}
2905 	/* Write the chunk data
2906 	 */
2907 #if defined( HAVE_DEBUG_OUTPUT )
2908 	if( libcnotify_verbose != 0 )
2909 	{
2910 		libcnotify_printf(
2911 	 	"%s: writing %" PRIzd " bytes to segment file: %d.\n",
2912 		 function,
2913 		 chunk_buffer_size,
2914 		 segment_files_list_index + 1 );
2915 	}
2916 #endif
2917 	write_count = libewf_segment_file_write_chunk(
2918 		       segment_file,
2919 		       io_handle,
2920 		       file_io_pool,
2921 		       file_io_pool_entry,
2922 		       chunk_table_list,
2923 		       chunk_index,
2924 		       chunk_buffer,
2925 		       chunk_buffer_size,
2926 		       chunk_data_size,
2927 		       is_compressed,
2928 		       checksum_buffer,
2929 		       &chunk_checksum,
2930 		       write_checksum,
2931 	               error );
2932 
2933 	if( write_count <= -1 )
2934 	{
2935 		libcerror_error_set(
2936 		 error,
2937 		 LIBCERROR_ERROR_DOMAIN_IO,
2938 		 LIBCERROR_IO_ERROR_WRITE_FAILED,
2939 		 "%s: unable to write chunk data.",
2940 		 function );
2941 
2942 		if( ( error != NULL )
2943 		 && ( libcerror_error_matches(
2944 		       *error,
2945 		       LIBCERROR_ERROR_DOMAIN_OUTPUT,
2946 		       LIBCERROR_OUTPUT_ERROR_INSUFFICIENT_SPACE ) == 0 ) )
2947 		{
2948 			return( -1 );
2949 		}
2950 		insufficient_output_space = 1;
2951 	}
2952 	else
2953 	{
2954 		insufficient_output_space = 0;
2955 	}
2956 	if( insufficient_output_space == 0 )
2957 	{
2958 		total_write_count                                    += write_count;
2959 		write_io_handle->input_write_count                   += chunk_data_size;
2960 		write_io_handle->chunks_section_write_count          += write_count;
2961 		write_io_handle->remaining_segment_file_size         -= write_count;
2962 		write_io_handle->number_of_chunks_written_to_segment += 1;
2963 		write_io_handle->number_of_chunks_written_to_section += 1;
2964 		write_io_handle->number_of_chunks_written            += 1;
2965 
2966 		if( ( io_handle->ewf_format == EWF_FORMAT_S01 )
2967 		 || ( io_handle->format == LIBEWF_FORMAT_ENCASE1 ) )
2968 		{
2969 			/* Leave space for the chunk offset in the offset table
2970 			 */
2971 			write_io_handle->remaining_segment_file_size -= 2 * sizeof( ewf_table_offset_t );
2972 		}
2973 		else
2974 		{
2975 			/* Leave space for the chunk offset in the table and table2 sections
2976 			 */
2977 			write_io_handle->remaining_segment_file_size -= 2 * sizeof( ewf_table_offset_t );
2978 		}
2979 		if( libbfio_pool_get_offset(
2980 		     file_io_pool,
2981 		     file_io_pool_entry,
2982 		     &segment_file_offset,
2983 		     error ) != 1 )
2984 		{
2985 			libcerror_error_set(
2986 			 error,
2987 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2988 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2989 			 "%s: unable to retrieve current offset in segment file.",
2990 			 function );
2991 
2992 			return( -1 );
2993 		}
2994 		/* Check if the current chunks section is full, if so close the current section
2995 		 */
2996 		result = libewf_write_io_handle_test_chunks_section_full(
2997 			  write_io_handle->chunks_section_offset,
2998 			  write_io_handle->remaining_segment_file_size,
2999 			  media_values,
3000 			  write_io_handle->input_write_count,
3001 			  segment_file_offset,
3002 			  write_io_handle->maximum_chunks_per_section,
3003 			  write_io_handle->number_of_chunks_written_to_section,
3004 			  write_io_handle->number_of_chunks_written,
3005 			  write_io_handle->chunks_per_section,
3006 			  io_handle->format,
3007 			  io_handle->ewf_format,
3008 			  write_io_handle->unrestrict_offset_table,
3009 			  error );
3010 
3011 		if( result == -1 )
3012 		{
3013 			libcerror_error_set(
3014 			 error,
3015 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3016 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3017 			 "%s: unable to determine if chunks section is full.",
3018 			 function );
3019 
3020 			return( -1 );
3021 		}
3022 	}
3023 	else
3024 	{
3025 		if( libbfio_pool_seek_offset(
3026 		     file_io_pool,
3027 		     file_io_pool_entry,
3028 		     segment_file_offset,
3029 		     SEEK_SET,
3030 		     error ) == -1 )
3031 		{
3032 			libcerror_error_set(
3033 			 error,
3034 			 LIBCERROR_ERROR_DOMAIN_IO,
3035 			 LIBCERROR_IO_ERROR_SEEK_FAILED,
3036 			 "%s: cannot find offset: %" PRIi64 ".",
3037 			 function,
3038 			 segment_file_offset );
3039 
3040 			return( -1 );
3041 		}
3042 		result = 0;
3043 	}
3044 	if( ( insufficient_output_space == 1 )
3045 	 || ( result == 1 ) )
3046 	{
3047 #if defined( HAVE_DEBUG_OUTPUT )
3048 		if( libcnotify_verbose != 0 )
3049 		{
3050 			libcnotify_printf(
3051 			 "%s: closing chunks section number of bytes written: %" PRIi64 ".\n",
3052 			 function,
3053 			 write_io_handle->chunks_section_write_count );
3054 		}
3055 #endif
3056 		if( write_io_handle->number_of_table_offsets < write_io_handle->number_of_chunks_written_to_section )
3057 		{
3058 			reallocation = memory_reallocate(
3059 			                write_io_handle->table_offsets,
3060 			                sizeof( ewf_table_offset_t ) * write_io_handle->number_of_chunks_written_to_section );
3061 
3062 			if( reallocation == NULL )
3063 			{
3064 				libcerror_error_set(
3065 				 error,
3066 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
3067 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
3068 				 "%s: unable to create table offsets.",
3069 				 function );
3070 
3071 				return( -1 );
3072 			}
3073 			write_io_handle->table_offsets           = (ewf_table_offset_t *) reallocation;
3074 			write_io_handle->number_of_table_offsets = write_io_handle->number_of_chunks_written_to_section;
3075 		}
3076 
3077 		/* Correct the offset, size in the chunks section
3078 		 */
3079 		write_count = libewf_segment_file_write_chunks_section_correction(
3080 		               segment_file,
3081 		               io_handle,
3082 		               file_io_pool,
3083 		               file_io_pool_entry,
3084 		               segment_file_offset,
3085 		               chunk_table_list,
3086 		               write_io_handle->table_offsets,
3087 		               write_io_handle->number_of_table_offsets,
3088 		               write_io_handle->chunks_section_offset,
3089 		               (size64_t) write_io_handle->chunks_section_write_count,
3090 		               write_io_handle->number_of_chunks_written,
3091 		               write_io_handle->number_of_chunks_written_to_section,
3092 		               error );
3093 
3094 		if( write_count == -1 )
3095 		{
3096 			libcerror_error_set(
3097 			 error,
3098 			 LIBCERROR_ERROR_DOMAIN_IO,
3099 			 LIBCERROR_IO_ERROR_WRITE_FAILED,
3100 			 "%s: unable to correct chunks section.",
3101 			 function );
3102 
3103 			return( -1 );
3104 		}
3105 		segment_file_offset                   += write_count;
3106 		total_write_count                     += write_count;
3107 		write_io_handle->create_chunks_section = 1;
3108 		write_io_handle->chunks_section_offset = 0;
3109 
3110 		if( insufficient_output_space == 0 )
3111 		{
3112 			/* Check if the current segment file is full, if so close the current segment file
3113 			 */
3114 			result = libewf_write_io_handle_test_segment_file_full(
3115 				  write_io_handle->remaining_segment_file_size,
3116 				  write_io_handle->number_of_chunks_written_to_segment,
3117 				  media_values,
3118 				  write_io_handle->input_write_count,
3119 				  write_io_handle->chunks_per_segment_file,
3120 				  write_io_handle->number_of_chunks_written,
3121 				  io_handle->format,
3122 				  io_handle->ewf_format,
3123 				  error );
3124 
3125 			if( result == -1 )
3126 			{
3127 				libcerror_error_set(
3128 				 error,
3129 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3130 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3131 				 "%s: unable to determine if segment file is full.",
3132 				 function );
3133 
3134 				return( -1 );
3135 			}
3136 		}
3137 		else
3138 		{
3139 			result = 0;
3140 		}
3141 		if( ( insufficient_output_space == 1 )
3142 		 || ( result == 1 ) )
3143 		{
3144 			/* Check if this is not the last segment file
3145 			 */
3146 			if( ( media_values->media_size == 0 )
3147 			 || ( write_io_handle->input_write_count < (ssize64_t) media_values->media_size ) )
3148 			{
3149 #if defined( HAVE_DEBUG_OUTPUT )
3150 				if( libcnotify_verbose != 0 )
3151 				{
3152 					libcnotify_printf(
3153 				 	"%s: closing segment file with segment number: %d.\n",
3154 					 function,
3155 					 segment_files_list_index + 1 );
3156 				}
3157 #endif
3158 				/* Finish and close the segment file
3159 				 */
3160 				write_count = libewf_segment_file_write_close(
3161 					       segment_file,
3162 					       io_handle,
3163 					       file_io_pool,
3164 					       file_io_pool_entry,
3165 					       segment_file_offset,
3166 					       write_io_handle->number_of_chunks_written_to_segment,
3167 					       0,
3168 					       hash_sections,
3169 					       hash_values,
3170 					       media_values,
3171 					       sessions,
3172 					       tracks,
3173 					       acquiry_errors,
3174 					       &( write_io_handle->data_section ),
3175 				               error );
3176 
3177 				if( write_count == -1 )
3178 				{
3179 					libcerror_error_set(
3180 					 error,
3181 					 LIBCERROR_ERROR_DOMAIN_IO,
3182 					 LIBCERROR_IO_ERROR_WRITE_FAILED,
3183 					 "%s: unable to close segment file.",
3184 					 function );
3185 
3186 					return( -1 );
3187 				}
3188 				segment_file_offset += write_count;
3189 				total_write_count   += write_count;
3190 			}
3191 		}
3192 	}
3193 	if( insufficient_output_space == 1 )
3194 	{
3195 		return( -1 );
3196 	}
3197 	return( total_write_count );
3198 }
3199 
3200 /* Writes an existing chunk of data in EWF format at the current offset
3201  * The necessary settings of the write values must have been made
3202  * Returns the number of data bytes written, 0 when no longer bytes can be written or -1 on error
3203  */
libewf_write_io_handle_write_existing_chunk(libewf_write_io_handle_t * write_io_handle,libewf_io_handle_t * io_handle,libbfio_pool_t * file_io_pool,libewf_media_values_t * media_values,libmfdata_file_list_t * delta_segment_files_list,libfcache_cache_t * segment_files_cache,libewf_segment_table_t * delta_segment_table,libmfdata_list_t * chunk_table_list,libewf_header_sections_t * header_sections,int chunk_index,uint8_t * chunk_buffer,size_t chunk_buffer_size,size_t chunk_data_size LIBEWF_ATTRIBUTE_UNUSED,int8_t is_compressed,uint8_t * checksum_buffer,uint32_t chunk_checksum,int8_t write_checksum,libcerror_error_t ** error)3204 ssize_t libewf_write_io_handle_write_existing_chunk(
3205          libewf_write_io_handle_t *write_io_handle,
3206          libewf_io_handle_t *io_handle,
3207          libbfio_pool_t *file_io_pool,
3208          libewf_media_values_t *media_values,
3209          libmfdata_file_list_t *delta_segment_files_list,
3210          libfcache_cache_t *segment_files_cache,
3211          libewf_segment_table_t *delta_segment_table,
3212          libmfdata_list_t *chunk_table_list,
3213          libewf_header_sections_t *header_sections,
3214          int chunk_index,
3215          uint8_t *chunk_buffer,
3216          size_t chunk_buffer_size,
3217          size_t chunk_data_size LIBEWF_ATTRIBUTE_UNUSED,
3218          int8_t is_compressed,
3219          uint8_t *checksum_buffer,
3220          uint32_t chunk_checksum,
3221          int8_t write_checksum,
3222          libcerror_error_t **error )
3223 {
3224 	libcdata_list_element_t *last_list_element = NULL;
3225 	libewf_section_t *last_section             = NULL;
3226 	libewf_segment_file_t *segment_file        = NULL;
3227 	static char *function                      = "libewf_write_io_handle_write_existing_chunk";
3228 	off64_t existing_chunk_offset              = 0;
3229 	off64_t segment_file_offset                = 0;
3230 	size64_t existing_chunk_size               = 0;
3231 	size64_t required_segment_file_size        = 0;
3232 	ssize_t total_write_count                  = 0;
3233 	ssize_t write_count                        = 0;
3234 	uint32_t existing_chunk_flags              = 0;
3235 	uint8_t no_section_append                  = 0;
3236 	int file_io_pool_entry                     = -1;
3237 	int number_of_segment_files                = 0;
3238 	int segment_files_list_index               = 0;
3239 
3240 	LIBEWF_UNREFERENCED_PARAMETER( chunk_data_size )
3241 
3242 	if( write_io_handle == NULL )
3243 	{
3244 		libcerror_error_set(
3245 		 error,
3246 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3247 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3248 		 "%s: invalid write IO handle.",
3249 		 function );
3250 
3251 		return( -1 );
3252 	}
3253 	if( io_handle == NULL )
3254 	{
3255 		libcerror_error_set(
3256 		 error,
3257 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3258 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3259 		 "%s: invalid IO handle.",
3260 		 function );
3261 
3262 		return( -1 );
3263 	}
3264 	if( media_values == NULL )
3265 	{
3266 		libcerror_error_set(
3267 		 error,
3268 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3269 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3270 		 "%s: invalid media values.",
3271 		 function );
3272 
3273 		return( -1 );
3274 	}
3275 	if( delta_segment_table == NULL )
3276 	{
3277 		libcerror_error_set(
3278 		 error,
3279 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3280 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3281 		 "%s: invalid delta segment table.",
3282 		 function );
3283 
3284 		return( -1 );
3285 	}
3286 	if( chunk_buffer == NULL )
3287 	{
3288 		libcerror_error_set(
3289 		 error,
3290 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3291 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3292 		 "%s: invalid chunk buffer.",
3293 		 function );
3294 
3295 		return( -1 );
3296 	}
3297 	if( ( chunk_buffer_size == 0 )
3298 	 || ( chunk_buffer_size > (size_t) SSIZE_MAX ) )
3299 	{
3300 		libcerror_error_set(
3301 		 error,
3302 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3303 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
3304 		 "%s: invalid chunk size value out of bounds.",
3305 		 function );
3306 
3307 		return( -1 );
3308 	}
3309 	if( is_compressed != 0 )
3310 	{
3311 		libcerror_error_set(
3312 		 error,
3313 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3314 		 LIBCERROR_ARGUMENT_ERROR_CONFLICTING_VALUE,
3315 		 "%s: chunk compression cannot be used.",
3316 		 function );
3317 
3318 		return( -1 );
3319 	}
3320 	if( libmfdata_list_get_data_range_by_index(
3321 	     chunk_table_list,
3322 	     chunk_index,
3323 	     &file_io_pool_entry,
3324 	     &existing_chunk_offset,
3325 	     &existing_chunk_size,
3326 	     &existing_chunk_flags,
3327 	     error ) != 1 )
3328 	{
3329 		libcerror_error_set(
3330 		 error,
3331 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3332 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3333 		 "%s: unable to retrieve data range of chunk: %d.",
3334 		 function,
3335 		 chunk_index );
3336 
3337 		return( -1 );
3338 	}
3339 #if defined( HAVE_DEBUG_OUTPUT )
3340 	if( libcnotify_verbose != 0 )
3341 	{
3342 		libcnotify_printf(
3343 		 "%s: writing delta chunk: %d with size: %" PRIzd ".\n",
3344 		 function,
3345 		 chunk_index,
3346 		 chunk_buffer_size );
3347 	}
3348 #endif
3349 	if( ( existing_chunk_flags & LIBEWF_RANGE_FLAG_IS_DELTA ) == 0 )
3350 	{
3351 		if( libmfdata_file_list_get_number_of_files(
3352 		     delta_segment_files_list,
3353 		     &number_of_segment_files,
3354 		     error ) != 1 )
3355 		{
3356 			libcerror_error_set(
3357 			 error,
3358 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3359 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3360 			 "%s: unable to retrieve number of delta segment files.",
3361 			 function );
3362 
3363 			return( -1 );
3364 		}
3365 		if( ( number_of_segment_files < 0 )
3366 		 || ( number_of_segment_files > (int) UINT16_MAX ) )
3367 		{
3368 			libcerror_error_set(
3369 			 error,
3370 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3371 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3372 			 "%s: invalid number of segment files value out of bounds.",
3373 			 function );
3374 
3375 			return( -1 );
3376 		}
3377 		if( number_of_segment_files != 0 )
3378 		{
3379 			segment_files_list_index = number_of_segment_files - 1;
3380 
3381 			/* Check if a new delta segment file should be created
3382 			 */
3383 			if( libmfdata_file_list_get_file_by_index(
3384 			     delta_segment_files_list,
3385 			     segment_files_list_index,
3386 			     &file_io_pool_entry,
3387 			     error ) != 1 )
3388 			{
3389 				libcerror_error_set(
3390 				 error,
3391 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3392 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3393 				 "%s: unable to retrieve delta segment file: %d from list.",
3394 				 function,
3395 				 segment_files_list_index + 1 );
3396 
3397 				return( -1 );
3398 			}
3399 			if( libmfdata_file_list_get_file_value_by_index(
3400 			     delta_segment_files_list,
3401 			     file_io_pool,
3402 			     segment_files_cache,
3403 			     segment_files_list_index,
3404 			     (intptr_t **) &segment_file,
3405 			     0,
3406 			     error ) != 1 )
3407 			{
3408 				libcerror_error_set(
3409 				 error,
3410 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3411 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3412 				 "%s: unable to retrieve delta segment file: %d value from list.",
3413 				 function,
3414 				 segment_files_list_index + 1 );
3415 
3416 				return( -1 );
3417 			}
3418 			if( segment_file == NULL )
3419 			{
3420 				libcerror_error_set(
3421 				 error,
3422 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3423 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3424 				 "%s: missing delta segment file: %d.",
3425 				 function,
3426 				 segment_files_list_index + 1 );
3427 
3428 				return( -1 );
3429 			}
3430 			if( segment_file->section_list == NULL )
3431 			{
3432 				libcerror_error_set(
3433 				 error,
3434 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3435 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3436 				 "%s: invalid segment file - missing section list.",
3437 				 function );
3438 
3439 				return( -1 );
3440 			}
3441 			if( libcdata_list_get_last_element(
3442 			     segment_file->section_list,
3443 			     &last_list_element,
3444 			     error ) != 1 )
3445 			{
3446 				libcerror_error_set(
3447 				 error,
3448 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3449 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3450 				 "%s: unable to retrieve last element from section list.",
3451 				 function );
3452 
3453 				return( -1 );
3454 			}
3455 			if( libcdata_list_element_get_value(
3456 			     last_list_element,
3457 			     (intptr_t **) &last_section,
3458 			     error ) != 1 )
3459 			{
3460 				libcerror_error_set(
3461 				 error,
3462 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3463 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3464 				 "%s: unable to retrieve value from last section list element.",
3465 				 function );
3466 
3467 				return( -1 );
3468 			}
3469 			if( last_section == NULL )
3470 			{
3471 				libcerror_error_set(
3472 				 error,
3473 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3474 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3475 				 "%s: missing last section.",
3476 				 function );
3477 
3478 				return( -1 );
3479 			}
3480 			if( libbfio_pool_get_offset(
3481 			     file_io_pool,
3482 			     file_io_pool_entry,
3483 			     &segment_file_offset,
3484 			     error ) != 1 )
3485 			{
3486 				libcerror_error_set(
3487 				 error,
3488 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3489 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3490 				 "%s: unable to retrieve current offset in segment file.",
3491 				 function );
3492 
3493 				return( -1 );
3494 			}
3495 			/* Make sure the current segment file offset points to the start of the last section
3496 			 */
3497 			if( segment_file_offset != last_section->start_offset )
3498 			{
3499 				if( libbfio_pool_seek_offset(
3500 				     file_io_pool,
3501 				     file_io_pool_entry,
3502 				     last_section->start_offset,
3503 				     SEEK_SET,
3504 				     error ) == -1 )
3505 				{
3506 					libcerror_error_set(
3507 					 error,
3508 					 LIBCERROR_ERROR_DOMAIN_IO,
3509 					 LIBCERROR_IO_ERROR_SEEK_FAILED,
3510 					 "%s: unable to seek offset: %" PRIi64 " in delta segment file: %d.",
3511 					 function,
3512 					 last_section->start_offset,
3513 					 segment_files_list_index + 1 );
3514 
3515 					return( -1 );
3516 				}
3517 				segment_file_offset = last_section->start_offset;
3518 			}
3519 			required_segment_file_size = (size64_t) last_section->start_offset
3520 					           + chunk_buffer_size
3521 					           + sizeof( uint32_t )
3522 					           + sizeof( ewf_section_start_t );
3523 
3524 			/* Check if chunk fits in exisiting delta segment file
3525 			 */
3526 			if( required_segment_file_size > delta_segment_table->maximum_segment_size )
3527 			{
3528 				/* Make sure to write a next section in the the previous delta segment file
3529 				 * The segment file offset is updated by the function
3530 				 */
3531 				write_count = libewf_segment_file_write_last_section(
3532 					       segment_file,
3533 					       io_handle,
3534 					       file_io_pool,
3535 					       file_io_pool_entry,
3536 				               segment_file_offset,
3537 					       0,
3538 					       error );
3539 
3540 				if( write_count == -1 )
3541 				{
3542 					libcerror_error_set(
3543 					 error,
3544 					 LIBCERROR_ERROR_DOMAIN_IO,
3545 					 LIBCERROR_IO_ERROR_WRITE_FAILED,
3546 					 "%s: unable to write last section.",
3547 					 function );
3548 
3549 					return( -1 );
3550 				}
3551 				segment_file_offset += write_count;
3552 				total_write_count   += write_count;
3553 
3554 				segment_file = NULL;
3555 			}
3556 			else
3557 			{
3558 				if( libcdata_list_remove_element(
3559 				     segment_file->section_list,
3560 				     last_list_element,
3561 				     error ) != 1 )
3562 				{
3563 					libcerror_error_set(
3564 					 error,
3565 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3566 					 LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
3567 					 "%s: unable to remove last section from list.",
3568 					 function );
3569 
3570 					return( -1 );
3571 				}
3572 				if( libcdata_list_element_free(
3573 				     &last_list_element,
3574 				     (int (*)(intptr_t **, libcerror_error_t **)) &libewf_section_free,
3575 				     error ) != 1 )
3576 				{
3577 					libcerror_error_set(
3578 					 error,
3579 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3580 					 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3581 					 "%s: unable to free last list element.",
3582 					 function );
3583 
3584 					return( -1 );
3585 				}
3586 			}
3587 		}
3588 		if( segment_file == NULL )
3589 		{
3590 			if( libewf_write_io_handle_create_segment_file(
3591 			     io_handle,
3592 			     file_io_pool,
3593 			     delta_segment_files_list,
3594 			     segment_files_cache,
3595 			     delta_segment_table,
3596 			     (uint16_t) ( segment_files_list_index + 1 ),
3597 			     write_io_handle->maximum_number_of_segments,
3598 			     LIBEWF_SEGMENT_FILE_TYPE_DWF,
3599 			     &segment_file,
3600 			     &segment_files_list_index,
3601 			     &file_io_pool_entry,
3602 			     error ) != 1 )
3603 			{
3604 				libcerror_error_set(
3605 				 error,
3606 				 LIBCERROR_ERROR_DOMAIN_IO,
3607 				 LIBCERROR_IO_ERROR_OPEN_FAILED,
3608 				 "%s: unable to create delta segment file: %d.",
3609 				 function,
3610 				 segment_files_list_index + 1 );
3611 
3612 				return( -1 );
3613 			}
3614 			/* Write the start of the segment file
3615 			 * like the file header, the header, volume and/or data section, etc.
3616 			 */
3617 			write_count = libewf_segment_file_write_start(
3618 				       segment_file,
3619 				       io_handle,
3620 				       file_io_pool,
3621 				       file_io_pool_entry,
3622 				       media_values,
3623 				       header_sections,
3624 			               &( write_io_handle->data_section ),
3625 			               error );
3626 
3627 			if( write_count == -1 )
3628 			{
3629 				libcerror_error_set(
3630 				 error,
3631 				 LIBCERROR_ERROR_DOMAIN_IO,
3632 				 LIBCERROR_IO_ERROR_WRITE_FAILED,
3633 				 "%s: unable to write segment file start.",
3634 				 function );
3635 
3636 				return( -1 );
3637 			}
3638 			segment_file_offset = write_count;
3639 			total_write_count  += write_count;
3640 		}
3641 	}
3642 	else
3643 	{
3644 		if( libmfdata_file_list_get_file_value_by_index(
3645 		     delta_segment_files_list,
3646 		     file_io_pool,
3647 		     segment_files_cache,
3648 		     segment_files_list_index,
3649 		     (intptr_t **) &segment_file,
3650 		     0,
3651 		     error ) != 1 )
3652 		{
3653 			libcerror_error_set(
3654 			 error,
3655 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3656 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3657 			 "%s: unable to retrieve delta segment file: %d value from list.",
3658 			 function,
3659 			 segment_files_list_index + 1 );
3660 
3661 			return( -1 );
3662 		}
3663 		if( segment_file == NULL )
3664 		{
3665 			libcerror_error_set(
3666 			 error,
3667 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3668 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3669 			 "%s: missing segment file: %d.",
3670 			 function,
3671 			 segment_files_list_index + 1 );
3672 
3673 			return( -1 );
3674 		}
3675 		segment_file_offset = existing_chunk_offset
3676 		                    - sizeof( ewf_section_start_t )
3677 		                    - sizeof( ewfx_delta_chunk_header_t );
3678 
3679 		if( libbfio_pool_seek_offset(
3680 		     file_io_pool,
3681 		     file_io_pool_entry,
3682 		     segment_file_offset,
3683 		     SEEK_SET,
3684 		     error ) == -1 )
3685 		{
3686 			libcerror_error_set(
3687 			 error,
3688 			 LIBCERROR_ERROR_DOMAIN_IO,
3689 			 LIBCERROR_IO_ERROR_SEEK_FAILED,
3690 			 "%s: unable to seek chunk offset: %" PRIi64 ".",
3691 			 function,
3692 			 segment_file_offset );
3693 
3694 			return( -1 );
3695 		}
3696 		no_section_append = 1;
3697 	}
3698 #if defined( HAVE_DEBUG_OUTPUT )
3699 	if( libcnotify_verbose != 0 )
3700 	{
3701 		libcnotify_printf(
3702 		 "%s: writing delta chunk section at offset: %" PRIi64 ".\n",
3703 		 function,
3704 		 segment_file_offset );
3705 	}
3706 #endif
3707 	write_count = libewf_segment_file_write_delta_chunk(
3708 		       segment_file,
3709 		       file_io_pool,
3710 		       file_io_pool_entry,
3711 		       segment_file_offset,
3712 		       chunk_table_list,
3713 		       chunk_index,
3714 		       chunk_buffer,
3715 		       chunk_buffer_size,
3716 		       checksum_buffer,
3717 		       &chunk_checksum,
3718 	               write_checksum,
3719 	               no_section_append,
3720 	               error );
3721 
3722 	if( write_count == -1 )
3723 	{
3724 		libcerror_error_set(
3725 		 error,
3726 		 LIBCERROR_ERROR_DOMAIN_IO,
3727 		 LIBCERROR_IO_ERROR_WRITE_FAILED,
3728 		 "%s: unable to write delta chunk section.",
3729 		 function );
3730 
3731 		return( -1 );
3732 	}
3733 	segment_file_offset += write_count;
3734 	total_write_count   += write_count;
3735 
3736 	if( no_section_append == 0 )
3737 	{
3738 		write_count = libewf_segment_file_write_last_section(
3739 			       segment_file,
3740 			       io_handle,
3741 			       file_io_pool,
3742 			       file_io_pool_entry,
3743 			       segment_file_offset,
3744 			       1,
3745 		               error );
3746 
3747 		if( write_count == -1 )
3748 		{
3749 			libcerror_error_set(
3750 			 error,
3751 			 LIBCERROR_ERROR_DOMAIN_IO,
3752 			 LIBCERROR_IO_ERROR_WRITE_FAILED,
3753 			 "%s: unable to write last section.",
3754 			 function );
3755 
3756 			return( -1 );
3757 		}
3758 		segment_file_offset += write_count;
3759 		total_write_count   += write_count;
3760 	}
3761 	return( total_write_count );
3762 }
3763 
3764 /* Corrects sections after streamed write
3765  * Returns 1 if successful or -1 on error
3766  */
libewf_write_io_handle_finalize_write_sections_corrections(libewf_io_handle_t * io_handle,libbfio_pool_t * file_io_pool,uint32_t number_of_chunks_written_to_last_segment,libewf_media_values_t * media_values,libmfdata_file_list_t * segment_files_list,libfcache_cache_t * segment_files_cache,libfvalue_table_t * hash_values,libewf_hash_sections_t * hash_sections,libcdata_array_t * sessions,libcdata_array_t * tracks,libcdata_range_list_t * acquiry_errors,ewf_data_t ** cached_data_section,libcerror_error_t ** error)3767 int libewf_write_io_handle_finalize_write_sections_corrections(
3768      libewf_io_handle_t *io_handle,
3769      libbfio_pool_t *file_io_pool,
3770      uint32_t number_of_chunks_written_to_last_segment,
3771      libewf_media_values_t *media_values,
3772      libmfdata_file_list_t *segment_files_list,
3773      libfcache_cache_t *segment_files_cache,
3774      libfvalue_table_t *hash_values,
3775      libewf_hash_sections_t *hash_sections,
3776      libcdata_array_t *sessions,
3777      libcdata_array_t *tracks,
3778      libcdata_range_list_t *acquiry_errors,
3779      ewf_data_t **cached_data_section,
3780      libcerror_error_t **error )
3781 {
3782 	libewf_segment_file_t *segment_file = NULL;
3783 	static char *function               = "libewf_write_io_handle_finalize_write_sections_corrections";
3784 	int file_io_pool_entry              = 0;
3785 	int number_of_segment_files         = 0;
3786 	int last_segment_file               = 0;
3787 	int segment_files_list_index        = 0;
3788 
3789 	if( libmfdata_file_list_get_number_of_files(
3790 	     segment_files_list,
3791 	     &number_of_segment_files,
3792 	     error ) != 1 )
3793 	{
3794 		libcerror_error_set(
3795 		 error,
3796 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3797 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3798 		 "%s: unable to retrieve number of segment files.",
3799 		 function );
3800 
3801 		return( -1 );
3802 	}
3803 	if( ( number_of_segment_files < 0 )
3804 	 || ( number_of_segment_files > (int) UINT16_MAX ) )
3805 	{
3806 		libcerror_error_set(
3807 		 error,
3808 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3809 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3810 		 "%s: invalid number of segment files value out of bounds.",
3811 		 function );
3812 
3813 		return( -1 );
3814 	}
3815 	for( segment_files_list_index = 0;
3816 	     segment_files_list_index < number_of_segment_files;
3817 	     segment_files_list_index++ )
3818 	{
3819 		if( segment_files_list_index == ( number_of_segment_files - 1 ) )
3820 		{
3821 			last_segment_file = 1;
3822 		}
3823 		segment_file = NULL;
3824 
3825 		if( libmfdata_file_list_get_file_by_index(
3826 		     segment_files_list,
3827 		     segment_files_list_index,
3828 		     &file_io_pool_entry,
3829 		     error ) != 1 )
3830 		{
3831 			libcerror_error_set(
3832 			 error,
3833 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3834 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3835 			 "%s: unable to retrieve segment file: %d from list.",
3836 			 function,
3837 			 segment_files_list_index + 1 );
3838 
3839 			return( -1 );
3840 		}
3841 		if( libmfdata_file_list_get_file_value_by_index(
3842 		     segment_files_list,
3843 		     file_io_pool,
3844 		     segment_files_cache,
3845 		     segment_files_list_index,
3846 		     (intptr_t **) &segment_file,
3847 		     0,
3848 		     error ) != 1 )
3849 		{
3850 			libcerror_error_set(
3851 			 error,
3852 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3853 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3854 			 "%s: unable to retrieve segment file: %d from list.",
3855 			 function,
3856 			 segment_files_list_index + 1 );
3857 
3858 			return( -1 );
3859 		}
3860 		if( segment_file == NULL )
3861 		{
3862 			libcerror_error_set(
3863 			 error,
3864 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3865 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3866 			 "%s: missing segment file: %d.",
3867 			 function,
3868 			 segment_files_list_index + 1 );
3869 
3870 			return( -1 );
3871 		}
3872 		if( libewf_segment_file_write_sections_correction(
3873 		     segment_file,
3874 		     io_handle,
3875 		     file_io_pool,
3876 		     file_io_pool_entry,
3877 		     number_of_chunks_written_to_last_segment,
3878 		     last_segment_file,
3879 		     media_values,
3880 		     hash_values,
3881 		     hash_sections,
3882 		     sessions,
3883 		     tracks,
3884 		     acquiry_errors,
3885 		     cached_data_section,
3886 		     error ) != 1 )
3887 		{
3888 			libcerror_error_set(
3889 			 error,
3890 			 LIBCERROR_ERROR_DOMAIN_IO,
3891 			 LIBCERROR_IO_ERROR_WRITE_FAILED,
3892 			 "%s: unable to write sections correction to segment file: %d.",
3893 			 function,
3894 			 segment_files_list_index + 1 );
3895 
3896 			return( -1 );
3897 		}
3898 	}
3899 	return( 1 );
3900 }
3901 
3902