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 §ion_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 **) §ion,
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 §ion_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 **) §ion,
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 §ion_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