Coverage Report

Created: 2025-07-04 07:01

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