Coverage Report

Created: 2023-06-07 06:53

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