Coverage Report

Created: 2025-06-13 07:22

/src/libewf/libewf/libewf_error2_section.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Error2 section 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 <narrow_string.h>
26
#include <types.h>
27
28
#include "libewf_checksum.h"
29
#include "libewf_definitions.h"
30
#include "libewf_error2_section.h"
31
#include "libewf_hash_sections.h"
32
#include "libewf_io_handle.h"
33
#include "libewf_libbfio.h"
34
#include "libewf_libcdata.h"
35
#include "libewf_libcerror.h"
36
#include "libewf_libcnotify.h"
37
#include "libewf_section.h"
38
#include "libewf_section_descriptor.h"
39
40
#include "ewf_error.h"
41
42
/* Reads a version 1 error2 section or version 2 error table section
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libewf_error2_section_read_data(
46
     const uint8_t *data,
47
     size_t data_size,
48
     uint8_t format_version,
49
     libcdata_range_list_t *acquiry_errors,
50
     libcerror_error_t **error )
51
48
{
52
48
  const uint8_t *error_data       = NULL;
53
48
  const uint8_t *error_entry_data = NULL;
54
48
  static char *function           = "libewf_error2_section_read_data";
55
48
  size_t error_entries_data_size  = 0;
56
48
  size_t error_entry_data_size    = 0;
57
48
  size_t error_footer_data_size   = 0;
58
48
  size_t error_header_data_size   = 0;
59
48
  uint64_t start_sector           = 0;
60
48
  uint32_t calculated_checksum    = 0;
61
48
  uint32_t entry_index            = 0;
62
48
  uint32_t number_of_entries      = 0;
63
48
  uint32_t number_of_sectors      = 0;
64
48
  uint32_t stored_checksum        = 0;
65
48
  int result                      = 0;
66
67
48
  if( data == NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
72
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
73
0
     "%s: missing data.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
48
  if( data_size > (size_t) SSIZE_MAX )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
83
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
84
0
     "%s: invalid data size value exceeds maximum.",
85
0
     function );
86
87
0
    return( -1 );
88
0
  }
89
48
  if( format_version == 1 )
90
48
  {
91
48
    error_header_data_size = sizeof( ewf_error_header_v1_t );
92
48
    error_entry_data_size  = sizeof( ewf_error_entry_v1_t );
93
48
    error_footer_data_size = 4;
94
48
  }
95
0
  else if( format_version == 2 )
96
0
  {
97
0
    error_header_data_size = sizeof( ewf_error_header_v2_t );
98
0
    error_entry_data_size  = sizeof( ewf_error_entry_v2_t );
99
0
    error_footer_data_size = 16;
100
0
  }
101
0
  else
102
0
  {
103
0
    libcerror_error_set(
104
0
     error,
105
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
106
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
107
0
     "%s: unsupported format version.",
108
0
     function );
109
110
0
    return( -1 );
111
0
  }
112
48
  if( data_size < error_header_data_size )
113
4
  {
114
4
    libcerror_error_set(
115
4
     error,
116
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
117
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
118
4
     "%s: invalid data size value out of bounds - insufficient space for header.",
119
4
     function );
120
121
4
    return( -1 );
122
4
  }
123
44
  error_data = data;
124
125
#if defined( HAVE_DEBUG_OUTPUT )
126
  if( libcnotify_verbose != 0 )
127
  {
128
    libcnotify_printf(
129
     "%s: error header data:\n",
130
     function );
131
    libcnotify_print_data(
132
     error_data,
133
     error_header_data_size,
134
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
135
  }
136
#endif
137
44
  if( format_version == 1 )
138
44
  {
139
44
    byte_stream_copy_to_uint32_little_endian(
140
44
     ( (ewf_error_header_v1_t *) error_data )->number_of_entries,
141
44
     number_of_entries );
142
143
44
    byte_stream_copy_to_uint32_little_endian(
144
44
     ( (ewf_error_header_v1_t *) error_data )->checksum,
145
44
     stored_checksum);
146
44
  }
147
0
  else if( format_version == 2 )
148
0
  {
149
0
    byte_stream_copy_to_uint32_little_endian(
150
0
     ( (ewf_error_header_v2_t *) error_data )->number_of_entries,
151
0
     number_of_entries );
152
153
0
    byte_stream_copy_to_uint32_little_endian(
154
0
     ( (ewf_error_header_v2_t *) error_data )->checksum,
155
0
     stored_checksum);
156
0
  }
157
#if defined( HAVE_DEBUG_OUTPUT )
158
  if( libcnotify_verbose != 0 )
159
  {
160
    libcnotify_printf(
161
     "%s: number of entries\t\t\t\t: %" PRIu32 "\n",
162
     function,
163
     number_of_entries );
164
165
    libcnotify_printf(
166
     "%s: unknown1:\n",
167
     function );
168
169
    if( format_version == 1 )
170
    {
171
      libcnotify_print_data(
172
       ( (ewf_error_header_v1_t *) error_data )->unknown1,
173
       200,
174
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
175
    }
176
    else if( format_version == 1 )
177
    {
178
      libcnotify_print_data(
179
       ( (ewf_error_header_v2_t *) error_data )->unknown1,
180
       12,
181
       0 );
182
    }
183
    libcnotify_printf(
184
     "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
185
     function,
186
     stored_checksum );
187
188
    if( format_version == 1 )
189
    {
190
      libcnotify_printf(
191
       "\n" );
192
    }
193
    else if( format_version == 2 )
194
    {
195
      libcnotify_printf(
196
       "%s: padding:\n",
197
       function );
198
      libcnotify_print_data(
199
       ( (ewf_error_header_v2_t *) error_data )->padding,
200
       12,
201
       0 );
202
    }
203
  }
204
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
205
206
44
  if( format_version == 2 )
207
0
  {
208
0
    error_header_data_size -= 12;
209
0
  }
210
44
  if( libewf_checksum_calculate_adler32(
211
44
       &calculated_checksum,
212
44
       error_data,
213
44
       error_header_data_size - 4,
214
44
       1,
215
44
       error ) != 1 )
216
0
  {
217
0
    libcerror_error_set(
218
0
     error,
219
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
220
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
221
0
     "%s: unable to calculate header checksum.",
222
0
     function );
223
224
0
    goto on_error;
225
0
  }
226
44
  if( format_version == 2 )
227
0
  {
228
0
    error_header_data_size += 12;
229
0
  }
230
44
  error_data += error_header_data_size;
231
44
  data_size  -= error_header_data_size;
232
233
44
  if( stored_checksum!= calculated_checksum )
234
41
  {
235
41
    libcerror_error_set(
236
41
     error,
237
41
     LIBCERROR_ERROR_DOMAIN_INPUT,
238
41
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
239
41
     "%s: header checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").",
240
41
     function,
241
41
     stored_checksum,
242
41
     calculated_checksum );
243
244
41
    goto on_error;
245
41
  }
246
3
  if( number_of_entries > 0 )
247
2
  {
248
2
    error_entry_data = error_data;
249
250
2
    error_entries_data_size = number_of_entries * error_entry_data_size;
251
252
2
    if( error_entries_data_size > (size_t) SSIZE_MAX )
253
0
    {
254
0
      libcerror_error_set(
255
0
       error,
256
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
257
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
258
0
       "%s: invalid error entries data size value exceeds maximum.",
259
0
       function );
260
261
0
      goto on_error;
262
0
    }
263
2
    if( data_size < error_entries_data_size )
264
2
    {
265
2
      libcerror_error_set(
266
2
       error,
267
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
268
2
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
269
2
       "%s: invalid section size value out of bounds - insufficient space for entries.",
270
2
       function );
271
272
2
      goto on_error;
273
2
    }
274
#if defined( HAVE_DEBUG_OUTPUT )
275
    if( libcnotify_verbose != 0 )
276
    {
277
      libcnotify_printf(
278
       "%s: error entries data:\n",
279
       function );
280
      libcnotify_print_data(
281
       error_data,
282
       error_entries_data_size,
283
       0 );
284
    }
285
#endif
286
0
    if( libewf_checksum_calculate_adler32(
287
0
         &calculated_checksum,
288
0
         error_data,
289
0
         error_entries_data_size,
290
0
         1,
291
0
         error ) != 1 )
292
0
    {
293
0
      libcerror_error_set(
294
0
       error,
295
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
296
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
297
0
       "%s: unable to calculate entries checksum.",
298
0
       function );
299
300
0
      goto on_error;
301
0
    }
302
0
    error_data += error_entries_data_size;
303
0
    data_size  -= error_entries_data_size;
304
305
0
    if( data_size < error_footer_data_size )
306
0
    {
307
0
      libcerror_error_set(
308
0
       error,
309
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
310
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
311
0
       "%s: invalid section size value out of bounds - insufficient space for footer.",
312
0
       function );
313
314
0
      goto on_error;
315
0
    }
316
0
    byte_stream_copy_to_uint32_little_endian(
317
0
     error_data,
318
0
     stored_checksum );
319
320
#if defined( HAVE_DEBUG_OUTPUT )
321
    if( libcnotify_verbose != 0 )
322
    {
323
      libcnotify_printf(
324
       "%s: error entries checksum\t\t\t: 0x%08" PRIx32 "\n",
325
       function,
326
       stored_checksum );
327
328
      if( format_version == 1 )
329
      {
330
        libcnotify_printf(
331
         "\n" );
332
      }
333
      else if( format_version == 2 )
334
      {
335
        libcnotify_printf(
336
         "%s: padding:\n",
337
         function );
338
        libcnotify_print_data(
339
         &( error_data[ 4 ] ),
340
         12,
341
         0 );
342
      }
343
    }
344
#endif
345
0
    error_data += error_footer_data_size;
346
0
    data_size  -= error_footer_data_size;
347
348
0
    if( stored_checksum != calculated_checksum )
349
0
    {
350
0
      libcerror_error_set(
351
0
       error,
352
0
       LIBCERROR_ERROR_DOMAIN_INPUT,
353
0
       LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
354
0
       "%s: entries checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").",
355
0
       function,
356
0
       stored_checksum,
357
0
       calculated_checksum );
358
359
0
      goto on_error;
360
0
    }
361
#if defined( HAVE_VERBOSE_OUTPUT ) || defined( HAVE_DEBUG_OUTPUT )
362
    if( libcnotify_verbose != 0 )
363
    {
364
      if( data_size > 0 )
365
      {
366
#if defined( HAVE_DEBUG_OUTPUT )
367
        libcnotify_printf(
368
         "%s: trailing data:\n",
369
         function );
370
        libcnotify_print_data(
371
         error_data,
372
         data_size,
373
         0 );
374
375
#elif defined( HAVE_VERBOSE_OUTPUT )
376
        libcnotify_printf(
377
         "%s: section has trailing data.\n",
378
         function );
379
#endif
380
      }
381
    }
382
#endif
383
0
    if( libcdata_range_list_empty(
384
0
         acquiry_errors,
385
0
         NULL,
386
0
         error ) != 1 )
387
0
    {
388
0
      libcerror_error_set(
389
0
       error,
390
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
391
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
392
0
       "%s: unable to empty acquiry errors range list.",
393
0
       function );
394
395
0
      goto on_error;
396
0
    }
397
0
    for( entry_index = 0;
398
0
         entry_index < number_of_entries;
399
0
         entry_index++ )
400
0
    {
401
0
      if( format_version == 1 )
402
0
      {
403
0
        byte_stream_copy_to_uint32_little_endian(
404
0
         ( (ewf_error_entry_v1_t *) error_entry_data )->start_sector,
405
0
         start_sector );
406
407
0
        byte_stream_copy_to_uint32_little_endian(
408
0
         ( (ewf_error_entry_v1_t *) error_entry_data )->number_of_sectors,
409
0
         number_of_sectors );
410
0
      }
411
0
      else if( format_version == 2 )
412
0
      {
413
0
        byte_stream_copy_to_uint64_little_endian(
414
0
         ( (ewf_error_entry_v2_t *) error_entry_data )->start_sector,
415
0
         start_sector );
416
417
0
        byte_stream_copy_to_uint32_little_endian(
418
0
         ( (ewf_error_entry_v2_t *) error_entry_data )->number_of_sectors,
419
0
         number_of_sectors );
420
0
      }
421
422
#if defined( HAVE_DEBUG_OUTPUT )
423
      if( libcnotify_verbose != 0 )
424
      {
425
        libcnotify_printf(
426
         "%s: error entry: %02" PRIu32 " start sector\t\t\t: %" PRIu64 "\n",
427
         function,
428
         entry_index,
429
         start_sector );
430
431
        libcnotify_printf(
432
         "%s: error entry: %02" PRIu32 " number of sectors\t\t: %" PRIu32 "\n",
433
         function,
434
         entry_index,
435
         number_of_sectors );
436
437
        if( format_version == 2 )
438
        {
439
          libcnotify_printf(
440
           "%s: error entry: %02" PRIu32 " padding:\n",
441
           function,
442
           entry_index );
443
          libcnotify_print_data(
444
           ( (ewf_error_entry_v2_t *) error_entry_data )->padding,
445
           12,
446
           0 );
447
        }
448
      }
449
#endif
450
0
      result = libcdata_range_list_insert_range(
451
0
                acquiry_errors,
452
0
                start_sector,
453
0
                (uint64_t) number_of_sectors,
454
0
                NULL,
455
0
                NULL,
456
0
                NULL,
457
0
                error );
458
459
0
      if( result == -1 )
460
0
      {
461
0
        libcerror_error_set(
462
0
         error,
463
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
464
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
465
0
         "%s: unable to insert acquiry error in range list.",
466
0
         function );
467
468
0
        goto on_error;
469
0
      }
470
0
      error_entry_data += error_entry_data_size;
471
0
    }
472
0
  }
473
#if defined( HAVE_VERBOSE_OUTPUT )
474
  else if( libcnotify_verbose != 0 )
475
  {
476
    libcnotify_printf(
477
     "%s: error section contains no entries.\n",
478
     function );
479
  }
480
#endif
481
1
  return( 1 );
482
483
43
on_error:
484
43
  libcdata_range_list_empty(
485
43
   acquiry_errors,
486
43
   NULL,
487
43
   NULL );
488
489
43
  return( -1 );
490
3
}
491
492
/* Reads a version 1 error2 section or version 2 error table section
493
 * Returns the number of bytes read or -1 on error
494
 */
495
ssize_t libewf_error2_section_read_file_io_pool(
496
         libewf_section_descriptor_t *section_descriptor,
497
         libewf_io_handle_t *io_handle,
498
         libbfio_pool_t *file_io_pool,
499
         int file_io_pool_entry,
500
         uint8_t format_version,
501
         libcdata_range_list_t *acquiry_errors,
502
         libcerror_error_t **error )
503
49
{
504
49
  uint8_t *section_data    = NULL;
505
49
  static char *function    = "libewf_error2_section_read_file_io_pool";
506
49
  size_t section_data_size = 0;
507
49
  ssize_t read_count       = 0;
508
509
49
  if( section_descriptor == NULL )
510
0
  {
511
0
    libcerror_error_set(
512
0
     error,
513
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
514
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
515
0
     "%s: invalid section descriptor.",
516
0
     function );
517
518
0
    return( -1 );
519
0
  }
520
49
  read_count = libewf_section_read_data(
521
49
                section_descriptor,
522
49
                io_handle,
523
49
                file_io_pool,
524
49
                file_io_pool_entry,
525
49
                &section_data,
526
49
                &section_data_size,
527
49
                error );
528
529
49
  if( read_count == -1 )
530
1
  {
531
1
    libcerror_error_set(
532
1
     error,
533
1
     LIBCERROR_ERROR_DOMAIN_IO,
534
1
     LIBCERROR_IO_ERROR_READ_FAILED,
535
1
     "%s: unable to read section data.",
536
1
     function );
537
538
1
    goto on_error;
539
1
  }
540
48
  else if( read_count != 0 )
541
48
  {
542
48
    if( libewf_error2_section_read_data(
543
48
         section_data,
544
48
         section_data_size,
545
48
         format_version,
546
48
         acquiry_errors,
547
48
         error ) != 1 )
548
47
    {
549
47
      libcerror_error_set(
550
47
       error,
551
47
       LIBCERROR_ERROR_DOMAIN_IO,
552
47
       LIBCERROR_IO_ERROR_READ_FAILED,
553
47
       "%s: unable to read section data.",
554
47
       function );
555
556
47
      goto on_error;
557
47
    }
558
1
    memory_free(
559
1
     section_data );
560
1
  }
561
1
  return( read_count );
562
563
48
on_error:
564
48
  if( section_data != NULL )
565
47
  {
566
47
    memory_free(
567
47
     section_data );
568
47
  }
569
48
  return( -1 );
570
49
}
571
572
/* Writes a version 1 error2 section or version 2 error table section
573
 * Returns 1 if successful or -1 on error
574
 */
575
int libewf_error2_section_write_data(
576
     uint8_t *data,
577
     size_t data_size,
578
     uint8_t format_version,
579
     libcdata_range_list_t *acquiry_errors,
580
     libcerror_error_t **error )
581
0
{
582
0
  uint8_t *error_data            = NULL;
583
0
  uint8_t *error_entry_data      = NULL;
584
0
  intptr_t *value                = NULL;
585
0
  static char *function          = "libewf_error2_section_write_data";
586
0
  size_t error_entries_data_size = 0;
587
0
  size_t error_entry_data_size   = 0;
588
0
  size_t error_footer_data_size  = 0;
589
0
  size_t error_header_data_size  = 0;
590
0
  size_t required_data_size      = 0;
591
0
  uint64_t number_of_sectors     = 0;
592
0
  uint64_t start_sector          = 0;
593
0
  uint32_t calculated_checksum   = 0;
594
0
  int entry_index                = 0;
595
0
  int number_of_entries          = 0;
596
597
0
  if( data == NULL )
598
0
  {
599
0
    libcerror_error_set(
600
0
     error,
601
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
602
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
603
0
     "%s: missing data.",
604
0
     function );
605
606
0
    return( -1 );
607
0
  }
608
0
  if( data_size > (size_t) SSIZE_MAX )
609
0
  {
610
0
    libcerror_error_set(
611
0
     error,
612
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
613
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
614
0
     "%s: invalid data size value exceeds maximum.",
615
0
     function );
616
617
0
    return( -1 );
618
0
  }
619
0
  if( format_version == 1 )
620
0
  {
621
0
    error_header_data_size = sizeof( ewf_error_header_v1_t );
622
0
    error_entry_data_size  = sizeof( ewf_error_entry_v1_t );
623
0
    error_footer_data_size = 4;
624
0
  }
625
0
  else if( format_version == 2 )
626
0
  {
627
0
    error_header_data_size = sizeof( ewf_error_header_v2_t );
628
0
    error_entry_data_size  = sizeof( ewf_error_entry_v2_t );
629
0
    error_footer_data_size = 16;
630
0
  }
631
0
  else
632
0
  {
633
0
    libcerror_error_set(
634
0
     error,
635
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
636
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
637
0
     "%s: unsupported format version.",
638
0
     function );
639
640
0
    return( -1 );
641
0
  }
642
0
  if( libcdata_range_list_get_number_of_elements(
643
0
       acquiry_errors,
644
0
       &number_of_entries,
645
0
       error ) != 1 )
646
0
  {
647
0
    libcerror_error_set(
648
0
     error,
649
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
650
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
651
0
     "%s: unable to retrieve number of elements from acquiry error range list.",
652
0
     function );
653
654
0
    return( -1 );
655
0
  }
656
0
  if( data_size < error_header_data_size )
657
0
  {
658
0
    libcerror_error_set(
659
0
     error,
660
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
661
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
662
0
     "%s: invalid number of errors value out of bounds.",
663
0
     function );
664
665
0
    return( -1 );
666
0
  }
667
0
  error_entries_data_size = number_of_entries * error_entry_data_size;
668
669
0
  required_data_size = error_header_data_size
670
0
                     + error_entries_data_size
671
0
                     + error_footer_data_size;
672
673
0
  if( data_size < required_data_size )
674
0
  {
675
0
    libcerror_error_set(
676
0
     error,
677
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
678
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
679
0
     "%s: invalid data value too small.",
680
0
     function );
681
682
0
    return( -1 );
683
0
  }
684
0
  error_data = data;
685
686
0
  if( format_version == 1 )
687
0
  {
688
0
    byte_stream_copy_from_uint32_little_endian(
689
0
     ( (ewf_error_header_v1_t *) error_data )->number_of_entries,
690
0
     number_of_entries );
691
0
  }
692
0
  else if( format_version == 2 )
693
0
  {
694
0
    byte_stream_copy_from_uint32_little_endian(
695
0
     ( (ewf_error_header_v2_t *) error_data )->number_of_entries,
696
0
     number_of_entries );
697
698
0
    error_header_data_size -= 12;
699
0
  }
700
0
  if( libewf_checksum_calculate_adler32(
701
0
       &calculated_checksum,
702
0
       error_data,
703
0
       error_header_data_size - 4,
704
0
       1,
705
0
       error ) != 1 )
706
0
  {
707
0
    libcerror_error_set(
708
0
     error,
709
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
710
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
711
0
     "%s: unable to calculate header checksum.",
712
0
     function );
713
714
0
    return( -1 );
715
0
  }
716
0
  if( format_version == 1 )
717
0
  {
718
0
    byte_stream_copy_from_uint32_little_endian(
719
0
     ( (ewf_error_header_v1_t *) error_data )->checksum,
720
0
     calculated_checksum );
721
0
  }
722
0
  else if( format_version == 2 )
723
0
  {
724
0
    byte_stream_copy_from_uint32_little_endian(
725
0
     ( (ewf_error_header_v2_t *) error_data )->checksum,
726
0
     calculated_checksum );
727
728
0
    error_header_data_size += 12;
729
0
  }
730
#if defined( HAVE_DEBUG_OUTPUT )
731
  if( libcnotify_verbose != 0 )
732
  {
733
    libcnotify_printf(
734
     "%s: error header data:\n",
735
     function );
736
    libcnotify_print_data(
737
     error_data,
738
     error_header_data_size,
739
     0 );
740
  }
741
#endif
742
#if defined( HAVE_DEBUG_OUTPUT )
743
  if( libcnotify_verbose != 0 )
744
  {
745
    libcnotify_printf(
746
     "%s: number of entries\t\t\t\t: %" PRIu32 "\n",
747
     function,
748
     number_of_entries );
749
750
    libcnotify_printf(
751
     "%s: unknown1:\n",
752
     function );
753
754
    if( format_version == 1 )
755
    {
756
      libcnotify_print_data(
757
       ( (ewf_error_header_v1_t *) error_data )->unknown1,
758
       200,
759
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
760
    }
761
    else if( format_version == 1 )
762
    {
763
      libcnotify_print_data(
764
       ( (ewf_error_header_v2_t *) error_data )->unknown1,
765
       12,
766
       0 );
767
    }
768
    libcnotify_printf(
769
     "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
770
     function,
771
     calculated_checksum );
772
773
    if( format_version == 1 )
774
    {
775
      libcnotify_printf(
776
       "\n" );
777
    }
778
    else if( format_version == 2 )
779
    {
780
      libcnotify_printf(
781
       "%s: padding:\n",
782
       function );
783
      libcnotify_print_data(
784
       ( (ewf_error_header_v2_t *) error_data )->padding,
785
       12,
786
       0 );
787
    }
788
  }
789
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
790
791
0
  error_data += error_header_data_size;
792
793
/* TODO EnCase compatible way to handle > 32-bit sector values */
794
0
  error_entry_data = error_data;
795
796
0
  for( entry_index = 0;
797
0
       entry_index < number_of_entries;
798
0
       entry_index++ )
799
0
  {
800
0
    if( libcdata_range_list_get_range_by_index(
801
0
         acquiry_errors,
802
0
         entry_index,
803
0
         &start_sector,
804
0
         &number_of_sectors,
805
0
         &value,
806
0
         error ) != 1 )
807
0
    {
808
0
      libcerror_error_set(
809
0
       error,
810
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
811
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
812
0
       "%s: unable to retrieve acquiry error: %d from range list.",
813
0
       function,
814
0
       entry_index );
815
816
0
      return( -1 );
817
0
    }
818
/* TODO check bounds fo start_sector and number_of_sectors and print warning if truncation happens */
819
0
    if( format_version == 1 )
820
0
    {
821
0
      byte_stream_copy_from_uint32_little_endian(
822
0
       ( (ewf_error_entry_v1_t *) error_entry_data )->start_sector,
823
0
       (uint32_t) start_sector );
824
825
0
      byte_stream_copy_from_uint32_little_endian(
826
0
       ( (ewf_error_entry_v1_t *) error_entry_data )->number_of_sectors,
827
0
       (uint32_t) number_of_sectors );
828
0
    }
829
0
    else if( format_version == 2 )
830
0
    {
831
0
      byte_stream_copy_from_uint64_little_endian(
832
0
       ( (ewf_error_entry_v2_t *) error_entry_data )->start_sector,
833
0
       start_sector );
834
835
0
      byte_stream_copy_from_uint32_little_endian(
836
0
       ( (ewf_error_entry_v2_t *) error_entry_data )->number_of_sectors,
837
0
       (uint32_t) number_of_sectors );
838
0
    }
839
0
    error_entry_data += error_entry_data_size;
840
0
  }
841
#if defined( HAVE_DEBUG_OUTPUT )
842
  if( libcnotify_verbose != 0 )
843
  {
844
    libcnotify_printf(
845
     "%s: error entries data:\n",
846
     function );
847
    libcnotify_print_data(
848
     error_data,
849
     error_entries_data_size,
850
     0 );
851
  }
852
#endif
853
0
  if( libewf_checksum_calculate_adler32(
854
0
       &calculated_checksum,
855
0
       error_data,
856
0
       error_entries_data_size,
857
0
       1,
858
0
       error ) != 1 )
859
0
  {
860
0
    libcerror_error_set(
861
0
     error,
862
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
863
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
864
0
     "%s: unable to calculate entries checksum.",
865
0
     function );
866
867
0
    return( -1 );
868
0
  }
869
0
  error_data += error_entries_data_size;
870
871
0
  byte_stream_copy_from_uint32_little_endian(
872
0
   error_data,
873
0
   calculated_checksum );
874
875
#if defined( HAVE_DEBUG_OUTPUT )
876
  if( libcnotify_verbose != 0 )
877
  {
878
    libcnotify_printf(
879
     "%s: error footer data:\n",
880
     function );
881
    libcnotify_print_data(
882
     error_data,
883
     error_footer_data_size,
884
     0 );
885
  }
886
#endif
887
#if defined( HAVE_DEBUG_OUTPUT )
888
  if( libcnotify_verbose != 0 )
889
  {
890
    libcnotify_printf(
891
     "%s: error entries checksum\t\t\t: 0x%08" PRIx32 "\n",
892
     function,
893
     calculated_checksum );
894
895
    if( format_version == 1 )
896
    {
897
      libcnotify_printf(
898
       "\n" );
899
    }
900
    else if( format_version == 2 )
901
    {
902
      libcnotify_printf(
903
       "%s: padding:\n",
904
       function );
905
      libcnotify_print_data(
906
       &( error_data[ 4 ] ),
907
       12,
908
       0 );
909
    }
910
  }
911
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
912
913
0
  return( 1 );
914
0
}
915
916
/* Writes a version 1 error2 section or version 2 error table section
917
 * Returns the number of bytes written or -1 on error
918
 */
919
ssize_t libewf_error2_section_write_file_io_pool(
920
         libewf_section_descriptor_t *section_descriptor,
921
         libewf_io_handle_t *io_handle,
922
         libbfio_pool_t *file_io_pool,
923
         int file_io_pool_entry,
924
         uint8_t format_version,
925
         off64_t section_offset,
926
         libcdata_range_list_t *acquiry_errors,
927
         libcerror_error_t **error )
928
0
{
929
0
  uint8_t *section_data               = NULL;
930
0
  static char *function               = "libewf_error2_section_write_file_io_pool";
931
0
  size_t error_entry_data_size        = 0;
932
0
  size_t error_entries_data_size      = 0;
933
0
  size_t error_footer_data_size       = 0;
934
0
  size_t error_header_data_size       = 0;
935
0
  size_t section_data_size            = 0;
936
0
  size_t section_descriptor_data_size = 0;
937
0
  ssize_t total_write_count           = 0;
938
0
  ssize_t write_count                 = 0;
939
0
  uint32_t section_padding_size       = 0;
940
0
  int number_of_entries               = 0;
941
942
0
  if( section_descriptor == NULL )
943
0
  {
944
0
    libcerror_error_set(
945
0
     error,
946
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
947
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
948
0
     "%s: invalid section descriptor.",
949
0
     function );
950
951
0
    return( -1 );
952
0
  }
953
0
  if( format_version == 1 )
954
0
  {
955
0
    section_descriptor_data_size = sizeof( ewf_section_descriptor_v1_t );
956
0
    error_header_data_size       = sizeof( ewf_error_header_v1_t );
957
0
    error_entry_data_size        = sizeof( ewf_error_entry_v1_t );
958
0
    error_footer_data_size       = 4;
959
0
  }
960
0
  else if( format_version == 2 )
961
0
  {
962
0
    section_descriptor_data_size = sizeof( ewf_section_descriptor_v2_t );
963
0
    error_header_data_size       = sizeof( ewf_error_header_v2_t );
964
0
    error_entry_data_size        = sizeof( ewf_error_entry_v2_t );
965
0
    error_footer_data_size       = 16;
966
0
    section_padding_size         = 24;
967
0
  }
968
0
  else
969
0
  {
970
0
    libcerror_error_set(
971
0
     error,
972
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
973
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
974
0
     "%s: unsupported format version.",
975
0
     function );
976
977
0
    return( -1 );
978
0
  }
979
0
  if( libcdata_range_list_get_number_of_elements(
980
0
       acquiry_errors,
981
0
       &number_of_entries,
982
0
       error ) != 1 )
983
0
  {
984
0
    libcerror_error_set(
985
0
     error,
986
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
987
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
988
0
     "%s: unable to retrieve number of elements from acquiry error range list.",
989
0
     function );
990
991
0
    goto on_error;
992
0
  }
993
0
  if( number_of_entries <= 0 )
994
0
  {
995
0
    libcerror_error_set(
996
0
     error,
997
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
998
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
999
0
     "%s: invalid number of errors value out of bounds.",
1000
0
     function );
1001
1002
0
    goto on_error;
1003
0
  }
1004
0
  error_entries_data_size = number_of_entries * error_entry_data_size;
1005
1006
0
  section_data_size = error_header_data_size
1007
0
                    + error_entries_data_size
1008
0
                    + error_footer_data_size;
1009
1010
0
  if( libewf_section_descriptor_set(
1011
0
       section_descriptor,
1012
0
       LIBEWF_SECTION_TYPE_ERROR_TABLE,
1013
0
       (uint8_t *) "error2",
1014
0
       6,
1015
0
       section_offset,
1016
0
       (size64_t) ( section_descriptor_data_size + section_data_size ),
1017
0
       (size64_t) section_data_size,
1018
0
       section_padding_size,
1019
0
       error ) != 1 )
1020
0
  {
1021
0
    libcerror_error_set(
1022
0
     error,
1023
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1024
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1025
0
     "%s: unable to set section descriptor.",
1026
0
     function );
1027
1028
0
    goto on_error;
1029
0
  }
1030
0
  if( format_version == 1 )
1031
0
  {
1032
0
    write_count = libewf_section_descriptor_write_file_io_pool(
1033
0
             section_descriptor,
1034
0
             file_io_pool,
1035
0
             file_io_pool_entry,
1036
0
             format_version,
1037
0
             error );
1038
1039
0
    if( write_count != (ssize_t) section_descriptor_data_size )
1040
0
    {
1041
0
      libcerror_error_set(
1042
0
       error,
1043
0
       LIBCERROR_ERROR_DOMAIN_IO,
1044
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
1045
0
       "%s: unable to write section descriptor data.",
1046
0
       function );
1047
1048
0
      goto on_error;
1049
0
    }
1050
0
    total_write_count += write_count;
1051
0
  }
1052
0
  if( ( section_data_size == 0 )
1053
0
   || ( section_data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1054
0
  {
1055
0
    libcerror_error_set(
1056
0
     error,
1057
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1058
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1059
0
     "%s: invalid section data size value out of bounds.",
1060
0
     function );
1061
1062
0
    goto on_error;
1063
0
  }
1064
0
  section_data = (uint8_t *) memory_allocate(
1065
0
                              section_data_size );
1066
1067
0
  if( section_data == NULL )
1068
0
  {
1069
0
    libcerror_error_set(
1070
0
     error,
1071
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1072
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1073
0
     "%s: unable to create section data.",
1074
0
     function );
1075
1076
0
    goto on_error;
1077
0
  }
1078
0
  if( libewf_error2_section_write_data(
1079
0
       section_data,
1080
0
       section_data_size,
1081
0
       format_version,
1082
0
       acquiry_errors,
1083
0
       error ) != 1 )
1084
0
  {
1085
0
    libcerror_error_set(
1086
0
     error,
1087
0
     LIBCERROR_ERROR_DOMAIN_IO,
1088
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1089
0
     "%s: unable to write section data.",
1090
0
     function );
1091
1092
0
    goto on_error;
1093
0
  }
1094
0
  write_count = libewf_section_write_data(
1095
0
                 section_descriptor,
1096
0
                 io_handle,
1097
0
                 file_io_pool,
1098
0
                 file_io_pool_entry,
1099
0
                 section_data,
1100
0
                 section_data_size,
1101
0
                 error );
1102
1103
0
  if( write_count == -1 )
1104
0
  {
1105
0
    libcerror_error_set(
1106
0
     error,
1107
0
     LIBCERROR_ERROR_DOMAIN_IO,
1108
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
1109
0
     "%s: unable to write section data.",
1110
0
     function );
1111
1112
0
    goto on_error;
1113
0
  }
1114
0
  total_write_count += write_count;
1115
1116
0
  memory_free(
1117
0
   section_data );
1118
1119
0
  section_data = NULL;
1120
1121
0
  if( format_version == 2 )
1122
0
  {
1123
0
    write_count = libewf_section_descriptor_write_file_io_pool(
1124
0
             section_descriptor,
1125
0
             file_io_pool,
1126
0
             file_io_pool_entry,
1127
0
             format_version,
1128
0
             error );
1129
1130
0
    if( write_count != (ssize_t) section_descriptor_data_size )
1131
0
    {
1132
0
      libcerror_error_set(
1133
0
       error,
1134
0
       LIBCERROR_ERROR_DOMAIN_IO,
1135
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
1136
0
       "%s: unable to write section descriptor data.",
1137
0
       function );
1138
1139
0
      goto on_error;
1140
0
    }
1141
0
    total_write_count += write_count;
1142
0
  }
1143
0
  return( total_write_count );
1144
1145
0
on_error:
1146
0
  if( section_data != NULL )
1147
0
  {
1148
0
    memory_free(
1149
0
     section_data );
1150
0
  }
1151
0
  return( -1 );
1152
0
}
1153