Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libewf/libewf/libewf_chunk_data.c
Line
Count
Source
1
/*
2
 * Chunk data functions
3
 *
4
 * Copyright (C) 2006-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libewf_checksum.h"
28
#include "libewf_chunk_data.h"
29
#include "libewf_compression.h"
30
#include "libewf_definitions.h"
31
#include "libewf_libbfio.h"
32
#include "libewf_libcerror.h"
33
#include "libewf_libcnotify.h"
34
#include "libewf_libfdata.h"
35
#include "libewf_types.h"
36
#include "libewf_unused.h"
37
38
#if !defined( LIBEWF_ATTRIBUTE_FALLTHROUGH )
39
#if defined( __GNUC__ ) && __GNUC__ >= 7
40
#define LIBEWF_ATTRIBUTE_FALLTHROUGH  __attribute__ ((fallthrough))
41
#else
42
#define LIBEWF_ATTRIBUTE_FALLTHROUGH
43
#endif
44
#endif
45
46
/* Creates chunk data
47
 * Make sure the value chunk_data is referencing, is set to NULL
48
 * Returns 1 if successful or -1 on error
49
 */
50
int libewf_chunk_data_initialize(
51
     libewf_chunk_data_t **chunk_data,
52
     size32_t chunk_size,
53
     uint8_t clear_data,
54
     libcerror_error_t **error )
55
0
{
56
0
  static char *function      = "libewf_chunk_data_initialize";
57
0
  size_t allocated_data_size = 0;
58
59
0
  if( chunk_data == NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
64
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
65
0
     "%s: invalid chunk data.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
0
  if( *chunk_data != NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
75
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
76
0
     "%s: invalid chunk data value already set.",
77
0
     function );
78
79
0
    return( -1 );
80
0
  }
81
0
  if( ( chunk_size == 0 )
82
0
   || ( chunk_size > (size32_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 16 ) ) )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
87
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
88
0
     "%s: invalid chunk size value out of bounds.",
89
0
     function );
90
91
0
    return( -1 );
92
0
  }
93
0
  *chunk_data = memory_allocate_structure(
94
0
                 libewf_chunk_data_t );
95
96
0
  if( *chunk_data == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
102
0
     "%s: unable to create chunk data.",
103
0
     function );
104
105
0
    goto on_error;
106
0
  }
107
0
  if( memory_set(
108
0
       *chunk_data,
109
0
       0,
110
0
       sizeof( libewf_chunk_data_t ) ) == NULL )
111
0
  {
112
0
    libcerror_error_set(
113
0
     error,
114
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
115
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
116
0
     "%s: unable to clear chunk data.",
117
0
     function );
118
119
0
    memory_free(
120
0
     *chunk_data );
121
122
0
    *chunk_data = NULL;
123
124
0
    return( -1 );
125
0
  }
126
  /* Reserve 4 bytes for the chunk checksum
127
   */
128
0
  allocated_data_size = (size_t) chunk_size + 4;
129
130
  /* The allocated data size should be rounded to the next 16-byte increment
131
   */
132
0
  if( ( allocated_data_size % 16 ) != 0 )
133
0
  {
134
0
    allocated_data_size += 16;
135
0
  }
136
0
  allocated_data_size = ( allocated_data_size / 16 ) * 16;
137
138
0
  ( *chunk_data )->data = (uint8_t *) memory_allocate(
139
0
               sizeof( uint8_t ) * allocated_data_size );
140
141
0
  if( ( *chunk_data )->data == NULL )
142
0
  {
143
0
    libcerror_error_set(
144
0
     error,
145
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
146
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
147
0
     "%s: unable to create data.",
148
0
     function );
149
150
0
    goto on_error;
151
0
  }
152
0
  if( clear_data != 0 )
153
0
  {
154
0
    if( memory_set(
155
0
         ( *chunk_data )->data,
156
0
         0,
157
0
         sizeof( uint8_t ) * allocated_data_size ) == NULL )
158
0
    {
159
0
      libcerror_error_set(
160
0
       error,
161
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
162
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
163
0
       "%s: unable to clear data.",
164
0
       function );
165
166
0
      goto on_error;
167
0
    }
168
0
  }
169
0
  ( *chunk_data )->chunk_size          = chunk_size;
170
0
  ( *chunk_data )->allocated_data_size = allocated_data_size;
171
0
  ( *chunk_data )->flags               = LIBEWF_CHUNK_DATA_ITEM_FLAG_MANAGED_DATA;
172
173
0
  return( 1 );
174
175
0
on_error:
176
0
  if( *chunk_data != NULL )
177
0
  {
178
0
    if( ( *chunk_data )->data != NULL )
179
0
    {
180
0
      memory_free(
181
0
       ( *chunk_data )->data );
182
0
    }
183
0
    memory_free(
184
0
     *chunk_data );
185
186
0
    *chunk_data = NULL;
187
0
  }
188
0
  return( -1 );
189
0
}
190
191
/* Frees chunk data
192
 * Returns 1 if successful or -1 on error
193
 */
194
int libewf_chunk_data_free(
195
     libewf_chunk_data_t **chunk_data,
196
     libcerror_error_t **error )
197
0
{
198
0
  static char *function = "libewf_chunk_data_free";
199
200
0
  if( chunk_data == NULL )
201
0
  {
202
0
    libcerror_error_set(
203
0
     error,
204
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
205
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
206
0
     "%s: invalid chunk data.",
207
0
     function );
208
209
0
    return( -1 );
210
0
  }
211
0
  if( *chunk_data != NULL )
212
0
  {
213
0
    if( ( ( *chunk_data )->flags & LIBEWF_CHUNK_DATA_ITEM_FLAG_MANAGED_DATA ) != 0 )
214
0
    {
215
0
      if( ( *chunk_data )->data != NULL )
216
0
      {
217
0
        memory_free(
218
0
         ( *chunk_data )->data );
219
0
      }
220
0
    }
221
0
    if( ( *chunk_data )->compressed_data != NULL )
222
0
    {
223
0
      memory_free(
224
0
       ( *chunk_data )->compressed_data );
225
0
    }
226
0
    memory_free(
227
0
     *chunk_data );
228
229
0
    *chunk_data = NULL;
230
0
  }
231
0
  return( 1 );
232
0
}
233
234
/* Reads chunk data into a buffer
235
 * Returns the number of bytes read or -1 on error
236
 */
237
ssize_t libewf_chunk_data_read_buffer(
238
         libewf_chunk_data_t *chunk_data,
239
         uint8_t *buffer,
240
         size_t buffer_size,
241
         libcerror_error_t **error )
242
0
{
243
0
  static char *function = "libewf_chunk_data_read_buffer";
244
245
0
  if( chunk_data == NULL )
246
0
  {
247
0
    libcerror_error_set(
248
0
     error,
249
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
250
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
251
0
     "%s: invalid chunk data.",
252
0
     function );
253
254
0
    return( -1 );
255
0
  }
256
0
  if( chunk_data->data == NULL )
257
0
  {
258
0
    libcerror_error_set(
259
0
     error,
260
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
261
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
262
0
     "%s: invalid chunk data - missing data.",
263
0
     function );
264
265
0
    return( -1 );
266
0
  }
267
0
  if( buffer == NULL )
268
0
  {
269
0
    libcerror_error_set(
270
0
     error,
271
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
272
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
273
0
     "%s: invalid buffer.",
274
0
     function );
275
276
0
    return( -1 );
277
0
  }
278
0
  if( buffer_size > (size_t) SSIZE_MAX )
279
0
  {
280
0
    libcerror_error_set(
281
0
     error,
282
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
283
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
284
0
     "%s: invalid buffer size value exceeds maximum.",
285
0
     function );
286
287
0
    return( -1 );
288
0
  }
289
0
  if( buffer_size < (size_t) chunk_data->chunk_size )
290
0
  {
291
0
    libcerror_error_set(
292
0
     error,
293
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
294
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
295
0
     "%s: invalid buffer size value too small.",
296
0
     function );
297
298
0
    return( -1 );
299
0
  }
300
0
  if( memory_copy(
301
0
       buffer,
302
0
       chunk_data->data,
303
0
       chunk_data->data_size ) == NULL )
304
0
  {
305
0
    libcerror_error_set(
306
0
     error,
307
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
308
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
309
0
     "%s: unable to copy chunk data to buffer.",
310
0
     function );
311
312
0
    return( -1 );
313
0
  }
314
0
  return( (ssize_t) chunk_data->data_size );
315
0
}
316
317
/* Writes a buffer to the chunk data
318
 * Returns the number of bytes written or -1 on error
319
 */
320
ssize_t libewf_chunk_data_write_buffer(
321
         libewf_chunk_data_t *chunk_data,
322
         const uint8_t *buffer,
323
         size_t buffer_size,
324
         libcerror_error_t **error )
325
0
{
326
0
  static char *function = "libewf_chunk_data_write_buffer";
327
328
0
  if( chunk_data == NULL )
329
0
  {
330
0
    libcerror_error_set(
331
0
     error,
332
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
333
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
334
0
     "%s: invalid chunk data.",
335
0
     function );
336
337
0
    return( -1 );
338
0
  }
339
0
  if( chunk_data->data == NULL )
340
0
  {
341
0
    libcerror_error_set(
342
0
     error,
343
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
344
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
345
0
     "%s: invalid chunk data - missing data.",
346
0
     function );
347
348
0
    return( -1 );
349
0
  }
350
0
  if( buffer == NULL )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
356
0
     "%s: invalid buffer.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
0
  if( buffer_size > (size_t) SSIZE_MAX )
362
0
  {
363
0
    libcerror_error_set(
364
0
     error,
365
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
367
0
     "%s: invalid buffer size value exceeds maximum.",
368
0
     function );
369
370
0
    return( -1 );
371
0
  }
372
0
  if( buffer_size > (size_t) chunk_data->chunk_size )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
377
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_LARGE,
378
0
     "%s: invalid buffer size value too large.",
379
0
     function );
380
381
0
    return( -1 );
382
0
  }
383
0
  if( memory_copy(
384
0
       chunk_data->data,
385
0
       buffer,
386
0
       buffer_size ) == NULL )
387
0
  {
388
0
    libcerror_error_set(
389
0
     error,
390
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
391
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
392
0
     "%s: unable to copy buffer to chunk data.",
393
0
     function );
394
395
0
    return( -1 );
396
0
  }
397
0
  chunk_data->data_size = buffer_size;
398
399
0
  return( (ssize_t) buffer_size );
400
0
}
401
402
/* Determines the pack flags as part of packing the chunk data
403
 * Returns 1 if successful or -1 on error
404
 */
405
int libewf_chunk_data_pack_determine_pack_flags(
406
     libewf_chunk_data_t *chunk_data,
407
     libewf_io_handle_t *io_handle,
408
     uint8_t *pack_flags,
409
     libcerror_error_t **error )
410
0
{
411
0
  static char *function   = "libewf_chunk_data_pack_determine_pack_flags";
412
0
  uint64_t fill_pattern   = 0;
413
0
  uint8_t safe_pack_flags = 0;
414
0
  int result              = 0;
415
416
0
  if( chunk_data == NULL )
417
0
  {
418
0
    libcerror_error_set(
419
0
     error,
420
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
421
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
422
0
     "%s: invalid chunk data.",
423
0
     function );
424
425
0
    return( -1 );
426
0
  }
427
0
  if( chunk_data->data == NULL )
428
0
  {
429
0
    libcerror_error_set(
430
0
     error,
431
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
432
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
433
0
     "%s: invalid chunk data - missing data.",
434
0
     function );
435
436
0
    return( -1 );
437
0
  }
438
0
  if( chunk_data->chunk_size < 1 )
439
0
  {
440
0
    libcerror_error_set(
441
0
     error,
442
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
443
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
444
0
     "%s: chunk size value out of bounds.",
445
0
     function );
446
447
0
    return( -1 );
448
0
  }
449
0
  if( io_handle == NULL )
450
0
  {
451
0
    libcerror_error_set(
452
0
     error,
453
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
454
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
455
0
     "%s: invalid IO handle.",
456
0
     function );
457
458
0
    return( -1 );
459
0
  }
460
0
  if( pack_flags == NULL )
461
0
  {
462
0
    libcerror_error_set(
463
0
     error,
464
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
465
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
466
0
     "%s: invalid pack flags.",
467
0
     function );
468
469
0
    return( -1 );
470
0
  }
471
0
  safe_pack_flags = *pack_flags;
472
473
0
  if( ( ( io_handle->compression_flags & LIBEWF_COMPRESS_FLAG_USE_PATTERN_FILL_COMPRESSION ) != 0 )
474
0
   && ( ( chunk_data->data_size % 8 ) == 0 ) )
475
0
  {
476
0
    result = libewf_chunk_data_check_for_64_bit_pattern_fill(
477
0
        chunk_data->data,
478
0
        chunk_data->data_size,
479
0
        &fill_pattern,
480
0
        error );
481
482
0
    if( result == -1 )
483
0
    {
484
0
      libcerror_error_set(
485
0
       error,
486
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
487
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
488
0
       "%s: unable to determine if chunk data contains a fill pattern.",
489
0
       function );
490
491
0
      return( -1 );
492
0
    }
493
0
    else if( result != 0 )
494
0
    {
495
0
      safe_pack_flags &= ~( LIBEWF_PACK_FLAG_CALCULATE_CHECKSUM | LIBEWF_PACK_FLAG_ADD_ALIGNMENT_PADDING );
496
0
      safe_pack_flags |= LIBEWF_PACK_FLAG_FORCE_COMPRESSION | LIBEWF_PACK_FLAG_USE_PATTERN_FILL_COMPRESSION;
497
0
    }
498
0
  }
499
0
  else if( ( ( io_handle->compression_flags & LIBEWF_COMPRESS_FLAG_USE_EMPTY_BLOCK_COMPRESSION ) != 0 )
500
0
        || ( io_handle->compression_level != LIBEWF_COMPRESSION_LEVEL_NONE ) )
501
0
  {
502
0
    result = libewf_chunk_data_check_for_empty_block(
503
0
        chunk_data->data,
504
0
        chunk_data->data_size,
505
0
        error );
506
507
0
    if( result == -1 )
508
0
    {
509
0
      libcerror_error_set(
510
0
       error,
511
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
512
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
513
0
       "%s: unable to determine if chunk data is an empty block.",
514
0
       function );
515
516
0
      return( -1 );
517
0
    }
518
0
    else if( ( result != 0 )
519
0
          && ( chunk_data->data[ 0 ] == 0 ) )
520
0
    {
521
0
      safe_pack_flags &= ~( LIBEWF_PACK_FLAG_CALCULATE_CHECKSUM );
522
0
      safe_pack_flags |= LIBEWF_PACK_FLAG_FORCE_COMPRESSION | LIBEWF_PACK_FLAG_USE_EMPTY_BLOCK_COMPRESSION;
523
0
    }
524
0
  }
525
0
  *pack_flags = safe_pack_flags;
526
527
0
  return( 1 );
528
0
}
529
530
/* Packs the chunk data using 64-bit pattern fill
531
 * Returns 1 if successful or -1 on error
532
 */
533
int libewf_chunk_data_pack_with_64_bit_pattern_fill(
534
     libewf_chunk_data_t *chunk_data,
535
     libcerror_error_t **error )
536
0
{
537
0
  static char *function = "libewf_chunk_data_pack_with_64_bit_pattern_fill";
538
539
0
  if( chunk_data == NULL )
540
0
  {
541
0
    libcerror_error_set(
542
0
     error,
543
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
544
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
545
0
     "%s: invalid chunk data.",
546
0
     function );
547
548
0
    return( -1 );
549
0
  }
550
0
  if( chunk_data->data == NULL )
551
0
  {
552
0
    libcerror_error_set(
553
0
     error,
554
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
555
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
556
0
     "%s: invalid chunk data - missing data.",
557
0
     function );
558
559
0
    return( -1 );
560
0
  }
561
0
  if( chunk_data->compressed_data != NULL )
562
0
  {
563
0
    libcerror_error_set(
564
0
     error,
565
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
566
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
567
0
     "%s: invalid chunk data - compressed data value already set.",
568
0
     function );
569
570
0
    return( -1 );
571
0
  }
572
0
  chunk_data->compressed_data_size = 8;
573
574
0
  chunk_data->compressed_data = (uint8_t *) memory_allocate(
575
0
                                             sizeof( uint8_t ) * chunk_data->compressed_data_size );
576
577
0
  if( chunk_data->compressed_data == NULL )
578
0
  {
579
0
    libcerror_error_set(
580
0
     error,
581
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
582
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
583
0
     "%s: unable to create compressed data.",
584
0
     function );
585
586
0
    goto on_error;
587
0
  }
588
0
  if( memory_copy(
589
0
       chunk_data->compressed_data,
590
0
       chunk_data->data,
591
0
       chunk_data->compressed_data_size ) == NULL )
592
0
  {
593
0
    libcerror_error_set(
594
0
     error,
595
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
596
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
597
0
     "%s: unable to copy fill pattern to compressed chunk data.",
598
0
     function );
599
600
0
    goto on_error;
601
0
  }
602
0
  chunk_data->range_flags = LIBEWF_RANGE_FLAG_IS_COMPRESSED | LIBEWF_RANGE_FLAG_USES_PATTERN_FILL;
603
604
0
  return( 1 );
605
606
0
on_error:
607
0
  if( chunk_data->compressed_data != NULL )
608
0
  {
609
0
    memory_free(
610
0
     chunk_data->compressed_data );
611
612
0
    chunk_data->compressed_data = NULL;
613
0
  }
614
0
  chunk_data->compressed_data_size = 0;
615
616
0
  return( -1 );
617
0
}
618
619
/* Unpacks the chunk data using 64-bit pattern fill
620
 * Returns 1 if successful or -1 on error
621
 */
622
int libewf_chunk_data_unpack_with_64_bit_pattern_fill(
623
     libewf_chunk_data_t *chunk_data,
624
     libcerror_error_t **error )
625
0
{
626
0
  static char *function       = "libewf_chunk_data_unpack_with_64_bit_pattern_fill";
627
0
  size_t remaining_chunk_size = 0;
628
629
0
  if( chunk_data == NULL )
630
0
  {
631
0
    libcerror_error_set(
632
0
     error,
633
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
634
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
635
0
     "%s: invalid chunk data.",
636
0
     function );
637
638
0
    return( -1 );
639
0
  }
640
0
  if( chunk_data->data == NULL )
641
0
  {
642
0
    libcerror_error_set(
643
0
     error,
644
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
645
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
646
0
     "%s: invalid chunk data - missing data.",
647
0
     function );
648
649
0
    return( -1 );
650
0
  }
651
0
  if( chunk_data->compressed_data == NULL )
652
0
  {
653
0
    libcerror_error_set(
654
0
     error,
655
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
656
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
657
0
     "%s: invalid chunk data - missing compressed data.",
658
0
     function );
659
660
0
    return( -1 );
661
0
  }
662
0
  if( chunk_data->compressed_data_size < (size_t) 8 )
663
0
  {
664
0
    libcerror_error_set(
665
0
     error,
666
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
667
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
668
0
     "%s: invalid chunk data - compressed data size value out of bounds.",
669
0
     function );
670
671
0
    return( -1 );
672
0
  }
673
0
  remaining_chunk_size = (size_t) chunk_data->chunk_size;
674
675
0
  switch( remaining_chunk_size % 8 )
676
0
  {
677
0
    case 7:
678
0
      ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 6 ];
679
680
0
    LIBEWF_ATTRIBUTE_FALLTHROUGH;
681
0
    case 6:
682
0
      ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 5 ];
683
684
0
    LIBEWF_ATTRIBUTE_FALLTHROUGH;
685
0
    case 5:
686
0
      ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 4 ];
687
688
0
    LIBEWF_ATTRIBUTE_FALLTHROUGH;
689
0
    case 4:
690
0
      ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 3 ];
691
692
0
    LIBEWF_ATTRIBUTE_FALLTHROUGH;
693
0
    case 3:
694
0
      ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 2 ];
695
696
0
    LIBEWF_ATTRIBUTE_FALLTHROUGH;
697
0
    case 2:
698
0
      ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 1 ];
699
700
0
    LIBEWF_ATTRIBUTE_FALLTHROUGH;
701
0
    case 1:
702
0
      ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 0 ];
703
0
  }
704
0
  while( remaining_chunk_size > 0 )
705
0
  {
706
/* TODO make this memory aligned ? */
707
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 7 ];
708
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 6 ];
709
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 5 ];
710
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 4 ];
711
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 3 ];
712
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 2 ];
713
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 1 ];
714
0
    ( chunk_data->data )[ --remaining_chunk_size ] = ( chunk_data->compressed_data )[ 0 ];
715
0
  }
716
0
  chunk_data->data_size = chunk_data->chunk_size;
717
718
0
  return( 1 );
719
0
}
720
721
/* Packs the chunk data using empty block compression
722
 * Returns 1 if successful or -1 on error
723
 */
724
int libewf_chunk_data_pack_with_empty_block_compression(
725
     libewf_chunk_data_t *chunk_data,
726
     const uint8_t *compressed_zero_byte_empty_block,
727
     size_t compressed_zero_byte_empty_block_size,
728
     libcerror_error_t **error )
729
0
{
730
0
  static char *function = "libewf_chunk_data_pack_with_empty_block_compression";
731
732
0
  if( chunk_data == NULL )
733
0
  {
734
0
    libcerror_error_set(
735
0
     error,
736
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
737
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
738
0
     "%s: invalid chunk data.",
739
0
     function );
740
741
0
    return( -1 );
742
0
  }
743
0
  if( chunk_data->compressed_data != NULL )
744
0
  {
745
0
    libcerror_error_set(
746
0
     error,
747
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
748
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
749
0
     "%s: invalid chunk data - compressed data value already set.",
750
0
     function );
751
752
0
    return( -1 );
753
0
  }
754
0
  if( compressed_zero_byte_empty_block == NULL )
755
0
  {
756
0
    libcerror_error_set(
757
0
     error,
758
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
759
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
760
0
     "%s: invalid compressed zero byte empty block.",
761
0
     function );
762
763
0
    return( -1 );
764
0
  }
765
0
  if( ( compressed_zero_byte_empty_block_size < 4 )
766
0
   || ( compressed_zero_byte_empty_block_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 16 ) ) )
767
0
  {
768
0
    libcerror_error_set(
769
0
     error,
770
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
771
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
772
0
     "%s: invalid compressed zero byte empty block size value out of bounds.",
773
0
     function );
774
775
0
    return( -1 );
776
0
  }
777
0
  chunk_data->compressed_data_size = compressed_zero_byte_empty_block_size;
778
779
0
  if( ( compressed_zero_byte_empty_block_size % 16 ) != 0 )
780
0
  {
781
0
    chunk_data->compressed_data_size += 16 - ( compressed_zero_byte_empty_block_size % 16 );
782
0
  }
783
0
  chunk_data->compressed_data = (uint8_t *) memory_allocate(
784
0
                                             sizeof( uint8_t ) * chunk_data->compressed_data_size );
785
786
0
  if( chunk_data->compressed_data == NULL )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
791
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
792
0
     "%s: unable to create compressed data.",
793
0
     function );
794
795
0
    goto on_error;
796
0
  }
797
0
  if( memory_copy(
798
0
       chunk_data->compressed_data,
799
0
       compressed_zero_byte_empty_block,
800
0
       compressed_zero_byte_empty_block_size ) == NULL )
801
0
  {
802
0
    libcerror_error_set(
803
0
     error,
804
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
805
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
806
0
     "%s: unable to copy compressed 0-byte empty block to compressed chunk data.",
807
0
     function );
808
809
0
    goto on_error;
810
0
  }
811
0
  byte_stream_copy_to_uint32_little_endian(
812
0
   &( compressed_zero_byte_empty_block[ compressed_zero_byte_empty_block_size - 4 ] ),
813
0
   chunk_data->checksum );
814
815
0
  chunk_data->range_flags = LIBEWF_RANGE_FLAG_IS_COMPRESSED;
816
817
0
  return( 1 );
818
819
0
on_error:
820
0
  if( chunk_data->compressed_data != NULL )
821
0
  {
822
0
    memory_free(
823
0
     chunk_data->compressed_data );
824
825
0
    chunk_data->compressed_data = NULL;
826
0
  }
827
0
  chunk_data->compressed_data_size = 0;
828
829
0
  return( -1 );
830
0
}
831
832
/* Packs the chunk data using compression
833
 * Returns 1 on success, 0 if buffer is too small or -1 on error
834
 */
835
int libewf_chunk_data_pack_with_compression(
836
     libewf_chunk_data_t *chunk_data,
837
     libewf_io_handle_t *io_handle,
838
     libcerror_error_t **error )
839
0
{
840
0
  static char *function            = "libewf_chunk_data_pack_with_compression";
841
0
  size_t safe_compressed_data_size = 0;
842
0
  int8_t compression_level         = 0;
843
0
  int result                       = 0;
844
845
0
  if( chunk_data == NULL )
846
0
  {
847
0
    libcerror_error_set(
848
0
     error,
849
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
850
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
851
0
     "%s: invalid chunk data.",
852
0
     function );
853
854
0
    return( -1 );
855
0
  }
856
0
  if( ( chunk_data->chunk_size == 0 )
857
0
   || ( chunk_data->chunk_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE / 2 ) ) )
858
0
  {
859
0
    libcerror_error_set(
860
0
     error,
861
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
862
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
863
0
     "%s: invalid chunk data - chunk size value out of bounds.",
864
0
     function );
865
866
0
    return( -1 );
867
0
  }
868
0
  if( chunk_data->compressed_data != NULL )
869
0
  {
870
0
    libcerror_error_set(
871
0
     error,
872
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
873
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
874
0
     "%s: invalid chunk data - compressed data value already set.",
875
0
     function );
876
877
0
    return( -1 );
878
0
  }
879
0
  if( io_handle == NULL )
880
0
  {
881
0
    libcerror_error_set(
882
0
     error,
883
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
884
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
885
0
     "%s: invalid IO handle.",
886
0
     function );
887
888
0
    return( -1 );
889
0
  }
890
/* TODO add a light weight entropy test to assess if compression makes sense */
891
892
0
  chunk_data->compressed_data_size = chunk_data->chunk_size;
893
894
  /* EWF-S01 allows to have compressed chunks larger than the chunk size, a factor 2 should suffice
895
   */
896
0
  if( io_handle->segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1_SMART )
897
0
  {
898
0
    chunk_data->compressed_data_size *= 2;
899
0
  }
900
0
  chunk_data->compressed_data = (uint8_t *) memory_allocate(
901
0
                                             sizeof( uint8_t ) * chunk_data->compressed_data_size );
902
903
0
  if( chunk_data->compressed_data == NULL )
904
0
  {
905
0
    libcerror_error_set(
906
0
     error,
907
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
908
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
909
0
     "%s: unable to create compressed data.",
910
0
     function );
911
912
0
    goto on_error;
913
0
  }
914
0
  safe_compressed_data_size = chunk_data->compressed_data_size;
915
916
  /* If compression was forced but no compression level provided use the default
917
   */
918
0
  compression_level = io_handle->compression_level;
919
920
0
  if( ( io_handle->segment_file_type != LIBEWF_SEGMENT_FILE_TYPE_EWF1_SMART )
921
0
   && ( compression_level == LIBEWF_COMPRESSION_LEVEL_NONE ) )
922
0
  {
923
0
    compression_level = LIBEWF_COMPRESSION_LEVEL_DEFAULT;
924
0
  }
925
0
  result = libewf_compress_data(
926
0
      chunk_data->compressed_data,
927
0
      &safe_compressed_data_size,
928
0
      io_handle->compression_method,
929
0
      compression_level,
930
0
      chunk_data->data,
931
0
      chunk_data->data_size,
932
0
      error );
933
934
0
  if( result == -1 )
935
0
  {
936
0
    libcerror_error_set(
937
0
     error,
938
0
     LIBCERROR_ERROR_DOMAIN_COMPRESSION,
939
0
     LIBCERROR_COMPRESSION_ERROR_COMPRESS_FAILED,
940
0
     "%s: unable to compress chunk data.",
941
0
     function );
942
943
0
    goto on_error;
944
0
  }
945
0
  else if( result != 0 )
946
0
  {
947
0
    if( ( safe_compressed_data_size < 4 )
948
0
     || ( safe_compressed_data_size > chunk_data->compressed_data_size ) )
949
0
    {
950
0
      libcerror_error_set(
951
0
       error,
952
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
953
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
954
0
       "%s: compressed data size value out of bounds.",
955
0
       function );
956
957
0
      goto on_error;
958
0
    }
959
0
    if( io_handle->compression_method == LIBEWF_COMPRESSION_METHOD_DEFLATE )
960
0
    {
961
      /* Deflate has its own checksum
962
       */
963
0
      byte_stream_copy_to_uint32_little_endian(
964
0
       &( ( chunk_data->compressed_data )[ safe_compressed_data_size - 4 ] ),
965
0
       chunk_data->checksum );
966
0
    }
967
/* TODO bzip2 support */
968
#ifdef IGNORE
969
    else if( io_handle->compression_method == LIBEWF_COMPRESSION_METHOD_BZIP2 )
970
    {
971
      /* Some parts of the bzip2 compressed block are not stored
972
       */
973
      chunk_data->compressed_data_offset = 4;
974
      safe_compressed_data_size         -= 4;
975
    }
976
#endif
977
0
    chunk_data->compressed_data_size = safe_compressed_data_size;
978
0
  }
979
#if defined( HAVE_DEBUG_OUTPUT )
980
  else if( libcnotify_verbose != 0 )
981
  {
982
    libcnotify_printf(
983
     "%s: required compressed data size: %zd.\n",
984
     function,
985
     safe_compressed_data_size );
986
  }
987
#endif
988
0
  return( result );
989
990
0
on_error:
991
0
  if( chunk_data->compressed_data != NULL )
992
0
  {
993
0
    memory_free(
994
0
     chunk_data->compressed_data );
995
996
0
    chunk_data->compressed_data = NULL;
997
0
  }
998
0
  chunk_data->compressed_data_size = 0;
999
1000
0
  return( -1 );
1001
0
}
1002
1003
/* Packs the chunk data
1004
 * This function either adds the checksum or compresses the chunk data
1005
 * Returns 1 if successful or -1 on error
1006
 */
1007
int libewf_chunk_data_pack(
1008
     libewf_chunk_data_t *chunk_data,
1009
     libewf_io_handle_t *io_handle,
1010
     const uint8_t *compressed_zero_byte_empty_block,
1011
     size_t compressed_zero_byte_empty_block_size,
1012
     uint8_t pack_flags,
1013
     libcerror_error_t **error )
1014
0
{
1015
0
  static char *function = "libewf_chunk_data_pack";
1016
0
  int result            = 0;
1017
1018
0
  if( chunk_data == NULL )
1019
0
  {
1020
0
    libcerror_error_set(
1021
0
     error,
1022
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1023
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1024
0
     "%s: invalid chunk data.",
1025
0
     function );
1026
1027
0
    return( -1 );
1028
0
  }
1029
0
  if( chunk_data->data == NULL )
1030
0
  {
1031
0
    libcerror_error_set(
1032
0
     error,
1033
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1034
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1035
0
     "%s: invalid chunk data - missing data.",
1036
0
     function );
1037
1038
0
    return( -1 );
1039
0
  }
1040
0
  if( io_handle == NULL )
1041
0
  {
1042
0
    libcerror_error_set(
1043
0
     error,
1044
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1045
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1046
0
     "%s: invalid IO handle.",
1047
0
     function );
1048
1049
0
    return( -1 );
1050
0
  }
1051
0
  if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_PACKED ) != 0 )
1052
0
  {
1053
0
    return( 1 );
1054
0
  }
1055
0
  if( libewf_chunk_data_pack_determine_pack_flags(
1056
0
       chunk_data,
1057
0
       io_handle,
1058
0
       &pack_flags,
1059
0
       error ) != 1 )
1060
0
  {
1061
0
    libcerror_error_set(
1062
0
     error,
1063
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1064
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1065
0
     "%s: unable to determine pack flags.",
1066
0
     function );
1067
1068
0
    goto on_error;
1069
0
  }
1070
  /* Make sure range flags are cleared before usage.
1071
   */
1072
0
  chunk_data->range_flags = 0;
1073
1074
0
  if( ( io_handle->compression_level != LIBEWF_COMPRESSION_LEVEL_NONE )
1075
0
   || ( ( pack_flags & LIBEWF_PACK_FLAG_FORCE_COMPRESSION ) != 0 ) )
1076
0
  {
1077
0
    if( ( pack_flags & LIBEWF_PACK_FLAG_USE_PATTERN_FILL_COMPRESSION ) != 0 )
1078
0
    {
1079
0
      if( libewf_chunk_data_pack_with_64_bit_pattern_fill(
1080
0
           chunk_data,
1081
0
           error ) != 1 )
1082
0
      {
1083
0
        libcerror_error_set(
1084
0
         error,
1085
0
         LIBCERROR_ERROR_DOMAIN_COMPRESSION,
1086
0
         LIBCERROR_COMPRESSION_ERROR_COMPRESS_FAILED,
1087
0
         "%s: unable to compress chunk data using 64-bit pattern fill.",
1088
0
         function );
1089
1090
0
        goto on_error;
1091
0
      }
1092
0
    }
1093
0
    else if( ( ( pack_flags & LIBEWF_PACK_FLAG_USE_EMPTY_BLOCK_COMPRESSION ) != 0 )
1094
0
          && ( chunk_data->data_size == (size_t) chunk_data->chunk_size )
1095
0
          && ( compressed_zero_byte_empty_block != NULL ) )
1096
0
    {
1097
0
      if( libewf_chunk_data_pack_with_empty_block_compression(
1098
0
           chunk_data,
1099
0
           compressed_zero_byte_empty_block,
1100
0
           compressed_zero_byte_empty_block_size,
1101
0
           error ) != 1 )
1102
0
      {
1103
0
        libcerror_error_set(
1104
0
         error,
1105
0
         LIBCERROR_ERROR_DOMAIN_COMPRESSION,
1106
0
         LIBCERROR_COMPRESSION_ERROR_COMPRESS_FAILED,
1107
0
         "%s: unable to compress chunk data using empty block compression.",
1108
0
         function );
1109
1110
0
        goto on_error;
1111
0
      }
1112
0
    }
1113
0
    else
1114
0
    {
1115
0
      result = libewf_chunk_data_pack_with_compression(
1116
0
                chunk_data,
1117
0
                io_handle,
1118
0
                error );
1119
1120
0
      if( result == -1 )
1121
0
      {
1122
0
        libcerror_error_set(
1123
0
         error,
1124
0
         LIBCERROR_ERROR_DOMAIN_COMPRESSION,
1125
0
         LIBCERROR_COMPRESSION_ERROR_COMPRESS_FAILED,
1126
0
         "%s: unable to compress chunk data using compression.",
1127
0
         function );
1128
1129
0
        goto on_error;
1130
0
      }
1131
0
      else if( result != 0 )
1132
0
      {
1133
        /* Use the compressed data if it is smaller than the uncompressed data or when compression is forced
1134
         */
1135
0
        if( ( ( pack_flags & LIBEWF_PACK_FLAG_FORCE_COMPRESSION ) != 0 )
1136
0
         || ( chunk_data->compressed_data_size < chunk_data->data_size ) )
1137
0
        {
1138
0
          chunk_data->range_flags = LIBEWF_RANGE_FLAG_IS_COMPRESSED;
1139
0
        }
1140
0
      }
1141
0
      else if( ( pack_flags & LIBEWF_PACK_FLAG_FORCE_COMPRESSION ) != 0 )
1142
0
      {
1143
0
        libcerror_error_set(
1144
0
         error,
1145
0
         LIBCERROR_ERROR_DOMAIN_COMPRESSION,
1146
0
         LIBCERROR_COMPRESSION_ERROR_COMPRESS_FAILED,
1147
0
         "%s: unable to compress chunk data - compression was forced but compressed data is too small.",
1148
0
         function );
1149
1150
0
        goto on_error;
1151
0
      }
1152
0
    }
1153
0
  }
1154
0
  if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) != 0 )
1155
0
  {
1156
0
    if( ( chunk_data->flags & LIBEWF_CHUNK_DATA_ITEM_FLAG_MANAGED_DATA ) != 0 )
1157
0
    {
1158
0
      memory_free(
1159
0
       chunk_data->data );
1160
0
    }
1161
0
    chunk_data->data      = chunk_data->compressed_data;
1162
0
    chunk_data->data_size = chunk_data->compressed_data_size;
1163
0
    chunk_data->flags     = LIBEWF_CHUNK_DATA_ITEM_FLAG_MANAGED_DATA;
1164
1165
0
    chunk_data->compressed_data      = NULL;
1166
0
    chunk_data->compressed_data_size = 0;
1167
0
  }
1168
0
  else if( ( pack_flags & LIBEWF_PACK_FLAG_CALCULATE_CHECKSUM ) != 0 )
1169
0
  {
1170
0
    if( libewf_checksum_calculate_adler32(
1171
0
         &( chunk_data->checksum ),
1172
0
         chunk_data->data,
1173
0
         chunk_data->data_size,
1174
0
         1,
1175
0
         error ) != 1 )
1176
0
    {
1177
0
      libcerror_error_set(
1178
0
       error,
1179
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1180
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1181
0
       "%s: unable to calculate checksum.",
1182
0
       function );
1183
1184
0
      goto on_error;
1185
0
    }
1186
0
    if( ( chunk_data->data_size + 4 ) <= chunk_data->allocated_data_size )
1187
0
    {
1188
0
      byte_stream_copy_from_uint32_little_endian(
1189
0
       &( ( chunk_data->data )[ chunk_data->data_size ] ),
1190
0
       chunk_data->checksum );
1191
1192
0
      chunk_data->data_size += 4;
1193
0
    }
1194
0
    else
1195
0
    {
1196
0
      chunk_data->chunk_io_flags = LIBEWF_CHUNK_IO_FLAG_CHECKSUM_SET;
1197
0
    }
1198
0
    chunk_data->range_flags = LIBEWF_RANGE_FLAG_HAS_CHECKSUM;
1199
0
  }
1200
0
  if( ( pack_flags & LIBEWF_PACK_FLAG_ADD_ALIGNMENT_PADDING ) != 0 )
1201
0
  {
1202
0
    chunk_data->padding_size = chunk_data->data_size % 16;
1203
1204
0
    if( chunk_data->padding_size != 0 )
1205
0
    {
1206
0
      chunk_data->padding_size = 16 - chunk_data->padding_size;
1207
0
    }
1208
0
    if( ( chunk_data->padding_size > chunk_data->allocated_data_size )
1209
0
     || ( chunk_data->data_size > ( chunk_data->allocated_data_size - chunk_data->padding_size ) ) )
1210
0
    {
1211
0
      libcerror_error_set(
1212
0
       error,
1213
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1214
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1215
0
       "%s: invalid chunk data - allocated data size value too small.",
1216
0
       function );
1217
1218
0
      goto on_error;
1219
0
    }
1220
0
    if( memory_set(
1221
0
         &( ( chunk_data->data )[ chunk_data->data_size ] ),
1222
0
         0,
1223
0
         chunk_data->padding_size ) == NULL )
1224
0
    {
1225
0
      libcerror_error_set(
1226
0
       error,
1227
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1228
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
1229
0
       "%s: unable to clear alignment padding.",
1230
0
       function );
1231
1232
0
      goto on_error;
1233
0
    }
1234
0
  }
1235
0
  chunk_data->range_flags |= LIBEWF_RANGE_FLAG_IS_PACKED;
1236
1237
0
  return( 1 );
1238
1239
0
on_error:
1240
0
  if( chunk_data->compressed_data != NULL )
1241
0
  {
1242
0
    memory_free(
1243
0
     chunk_data->compressed_data );
1244
1245
0
    chunk_data->compressed_data = NULL;
1246
0
  }
1247
0
  chunk_data->compressed_data_size = 0;
1248
1249
0
  return( -1 );
1250
0
}
1251
1252
/* Unpacks the chunk data
1253
 * This function either validates the checksum or decompresses the chunk data
1254
 * Returns 1 if successful or -1 on error
1255
 */
1256
int libewf_chunk_data_unpack(
1257
     libewf_chunk_data_t *chunk_data,
1258
     libewf_io_handle_t *io_handle,
1259
     libcerror_error_t **error )
1260
0
{
1261
0
  static char *function        = "libewf_chunk_data_unpack";
1262
0
  uint32_t calculated_checksum = 0;
1263
1264
0
  if( chunk_data == NULL )
1265
0
  {
1266
0
    libcerror_error_set(
1267
0
     error,
1268
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1269
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1270
0
     "%s: invalid chunk data.",
1271
0
     function );
1272
1273
0
    return( -1 );
1274
0
  }
1275
0
  if( chunk_data->data == NULL )
1276
0
  {
1277
0
    libcerror_error_set(
1278
0
     error,
1279
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1280
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1281
0
     "%s: invalid chunk data - missing data.",
1282
0
     function );
1283
1284
0
    return( -1 );
1285
0
  }
1286
0
  if( io_handle == NULL )
1287
0
  {
1288
0
    libcerror_error_set(
1289
0
     error,
1290
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1291
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1292
0
     "%s: invalid IO handle.",
1293
0
     function );
1294
1295
0
    return( -1 );
1296
0
  }
1297
0
  if( ( chunk_data->chunk_size == 0 )
1298
0
   || ( chunk_data->chunk_size > (size32_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 16 ) ) )
1299
0
  {
1300
0
    libcerror_error_set(
1301
0
     error,
1302
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1303
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1304
0
     "%s: invalid chunk size value out of bounds.",
1305
0
     function );
1306
1307
0
    return( -1 );
1308
0
  }
1309
0
  if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_PACKED ) == 0 )
1310
0
  {
1311
0
    return( 1 );
1312
0
  }
1313
0
  if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) != 0 )
1314
0
  {
1315
0
    if( chunk_data->compressed_data != NULL )
1316
0
    {
1317
0
      libcerror_error_set(
1318
0
       error,
1319
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1320
0
       LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1321
0
       "%s: invalid chunk data - compressed data value already set.",
1322
0
       function );
1323
1324
0
      return( -1 );
1325
0
    }
1326
0
    chunk_data->compressed_data      = chunk_data->data;
1327
0
    chunk_data->compressed_data_size = chunk_data->data_size;
1328
1329
    /* Reserve 4 bytes for the checksum
1330
     */
1331
0
    chunk_data->allocated_data_size = (size_t) ( chunk_data->chunk_size + 4 );
1332
1333
    /* The allocated data size should be rounded to the next 16-byte increment
1334
     */
1335
0
    if( ( chunk_data->allocated_data_size % 16 ) != 0 )
1336
0
    {
1337
0
      chunk_data->allocated_data_size += 16;
1338
0
    }
1339
0
    chunk_data->allocated_data_size = ( chunk_data->allocated_data_size / 16 ) * 16;
1340
1341
0
    chunk_data->data = (uint8_t *) memory_allocate(
1342
0
                                    sizeof( uint8_t ) * chunk_data->allocated_data_size );
1343
1344
0
    if( chunk_data->data == NULL )
1345
0
    {
1346
0
      libcerror_error_set(
1347
0
       error,
1348
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1349
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1350
0
       "%s: unable to create data.",
1351
0
       function );
1352
1353
0
      goto on_error;
1354
0
    }
1355
0
    if( memory_set(
1356
0
         chunk_data->data,
1357
0
         0,
1358
0
         sizeof( uint8_t ) * chunk_data->allocated_data_size ) == NULL )
1359
0
    {
1360
0
      libcerror_error_set(
1361
0
       error,
1362
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1363
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
1364
0
       "%s: unable to clear data.",
1365
0
       function );
1366
1367
0
      goto on_error;
1368
0
    }
1369
0
    chunk_data->data_size = (size_t) chunk_data->chunk_size;
1370
1371
0
    if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_USES_PATTERN_FILL ) != 0 )
1372
0
    {
1373
0
      if( libewf_chunk_data_unpack_with_64_bit_pattern_fill(
1374
0
           chunk_data,
1375
0
           error ) != 1 )
1376
0
      {
1377
0
        libcerror_error_set(
1378
0
         error,
1379
0
         LIBCERROR_ERROR_DOMAIN_COMPRESSION,
1380
0
         LIBCERROR_COMPRESSION_ERROR_COMPRESS_FAILED,
1381
0
         "%s: unable to decompress chunk data using 64-bit pattern fill.",
1382
0
         function );
1383
1384
0
        goto on_error;
1385
0
      }
1386
0
    }
1387
0
    else
1388
0
    {
1389
0
      if( libewf_decompress_data(
1390
0
           chunk_data->compressed_data,
1391
0
           chunk_data->compressed_data_size,
1392
0
           io_handle->compression_method,
1393
0
           chunk_data->data,
1394
0
           &( chunk_data->data_size ),
1395
0
           error ) != 1 )
1396
0
      {
1397
0
        libcerror_error_set(
1398
0
         error,
1399
0
         LIBCERROR_ERROR_DOMAIN_COMPRESSION,
1400
0
         LIBCERROR_COMPRESSION_ERROR_DECOMPRESS_FAILED,
1401
0
         "%s: unable to decompress chunk data.",
1402
0
         function );
1403
1404
#if defined( HAVE_VERBOSE_OUTPUT )
1405
        if( libcnotify_verbose != 0 )
1406
        {
1407
          if( ( error != NULL )
1408
           && ( *error != NULL ) )
1409
          {
1410
            libcnotify_print_error_backtrace(
1411
             *error );
1412
          }
1413
        }
1414
#endif
1415
0
        libcerror_error_free(
1416
0
         error );
1417
1418
0
        chunk_data->data_size    = (size_t) chunk_data->chunk_size;
1419
0
        chunk_data->range_flags |= LIBEWF_RANGE_FLAG_IS_CORRUPTED;
1420
0
      }
1421
0
    }
1422
0
  }
1423
0
  else if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_HAS_CHECKSUM ) != 0 )
1424
0
  {
1425
0
    if( chunk_data->data_size < 4 )
1426
0
    {
1427
0
      libcerror_error_set(
1428
0
       error,
1429
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1430
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1431
0
       "%s: invalid chunk data - data size value out of bounds.",
1432
0
       function );
1433
1434
0
      goto on_error;
1435
0
    }
1436
0
    chunk_data->data_size -= 4;
1437
1438
0
    if( ( chunk_data->chunk_io_flags & LIBEWF_CHUNK_IO_FLAG_CHECKSUM_SET ) == 0 )
1439
0
    {
1440
0
      byte_stream_copy_to_uint32_little_endian(
1441
0
       &( ( chunk_data->data )[ chunk_data->data_size ] ),
1442
0
       chunk_data->checksum );
1443
0
    }
1444
0
    if( libewf_checksum_calculate_adler32(
1445
0
         &calculated_checksum,
1446
0
         chunk_data->data,
1447
0
         chunk_data->data_size,
1448
0
         1,
1449
0
         error ) != 1 )
1450
0
    {
1451
0
      libcerror_error_set(
1452
0
       error,
1453
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1454
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1455
0
       "%s: unable to calculate checksum.",
1456
0
       function );
1457
1458
0
      goto on_error;
1459
0
    }
1460
0
    if( chunk_data->checksum != calculated_checksum )
1461
0
    {
1462
0
      libcerror_error_set(
1463
0
       error,
1464
0
       LIBCERROR_ERROR_DOMAIN_INPUT,
1465
0
       LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
1466
0
       "%s: chunk data checksum does not match (stored: 0x%08" PRIx32 ", calculated: 0x%08" PRIx32 ").",
1467
0
       function,
1468
0
       chunk_data->checksum,
1469
0
       calculated_checksum );
1470
1471
#if defined( HAVE_VERBOSE_OUTPUT )
1472
      if( libcnotify_verbose != 0 )
1473
      {
1474
        if( ( error != NULL )
1475
         && ( *error != NULL ) )
1476
        {
1477
          libcnotify_print_error_backtrace(
1478
           *error );
1479
        }
1480
      }
1481
#endif /* defined( HAVE_VERBOSE_OUTPUT ) */
1482
1483
0
      libcerror_error_free(
1484
0
       error );
1485
1486
0
      chunk_data->data_size    = (size_t) chunk_data->chunk_size;
1487
0
      chunk_data->range_flags |= LIBEWF_RANGE_FLAG_IS_CORRUPTED;
1488
0
    }
1489
0
  }
1490
0
  if( ( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_CORRUPTED ) != 0 )
1491
0
   && ( io_handle->zero_on_error != 0 ) )
1492
0
  {
1493
0
    if( memory_set(
1494
0
         chunk_data->data,
1495
0
         0,
1496
0
         chunk_data->data_size ) == NULL )
1497
0
    {
1498
0
      libcerror_error_set(
1499
0
       error,
1500
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1501
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
1502
0
       "%s: unable to zero chunk data.",
1503
0
       function );
1504
1505
0
      goto on_error;
1506
0
    }
1507
0
  }
1508
0
  chunk_data->range_flags &= ~( LIBEWF_RANGE_FLAG_IS_PACKED );
1509
1510
0
  return( 1 );
1511
1512
0
on_error:
1513
0
  if( chunk_data->compressed_data != NULL )
1514
0
  {
1515
0
    if( chunk_data->data != NULL )
1516
0
    {
1517
0
      memory_free(
1518
0
       chunk_data->data );
1519
0
    }
1520
0
    chunk_data->data      = chunk_data->compressed_data;
1521
0
    chunk_data->data_size = chunk_data->compressed_data_size;
1522
1523
0
    chunk_data->compressed_data      = NULL;
1524
0
    chunk_data->compressed_data_size = 0;
1525
0
  }
1526
0
  return( -1 );
1527
0
}
1528
1529
/* Checks if a buffer containing the chunk data is filled with same value bytes (empty-block)
1530
 * Returns 1 if an empty block was found, 0 if not or -1 on error
1531
 */
1532
int libewf_chunk_data_check_for_empty_block(
1533
     const uint8_t *data,
1534
     size_t data_size,
1535
     libcerror_error_t **error )
1536
0
{
1537
0
  static char *function = "libewf_chunk_data_check_for_empty_block";
1538
1539
0
  if( data == NULL )
1540
0
  {
1541
0
    libcerror_error_set(
1542
0
     error,
1543
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1544
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1545
0
     "%s: invalid data.",
1546
0
     function );
1547
1548
0
    return( -1 );
1549
0
  }
1550
0
  if( data_size > (size_t) SSIZE_MAX )
1551
0
  {
1552
0
    libcerror_error_set(
1553
0
     error,
1554
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1555
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1556
0
     "%s: invalid data size value exceeds maximum.",
1557
0
     function );
1558
1559
0
    return( -1 );
1560
0
  }
1561
0
  if( data_size == 0 )
1562
0
  {
1563
0
    return( 0 );
1564
0
  }
1565
0
  else if( data_size == 1 )
1566
0
  {
1567
0
    return( 1 );
1568
0
  }
1569
0
  if( memory_compare(
1570
0
       data,
1571
0
       &( data[ 1 ] ),
1572
0
       data_size - 1 ) != 0 )
1573
0
  {
1574
0
    return( 0 );
1575
0
  }
1576
0
  return( 1 );
1577
0
}
1578
1579
/* Checks if a buffer containing the chunk data is filled with a 64-bit pattern
1580
 * Returns 1 if a pattern was found, 0 if not or -1 on error
1581
 */
1582
int libewf_chunk_data_check_for_64_bit_pattern_fill(
1583
     const uint8_t *data,
1584
     size_t data_size,
1585
     uint64_t *pattern,
1586
     libcerror_error_t **error )
1587
0
{
1588
0
  libewf_aligned_t *aligned_data_index = NULL;
1589
0
  libewf_aligned_t *aligned_data_start = NULL;
1590
0
  uint8_t *data_index                  = NULL;
1591
0
  uint8_t *data_start                  = NULL;
1592
0
  static char *function                = "libewf_chunk_data_check_for_64_bit_pattern_fill";
1593
1594
0
  if( data == NULL )
1595
0
  {
1596
0
    libcerror_error_set(
1597
0
     error,
1598
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1599
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1600
0
     "%s: invalid data.",
1601
0
     function );
1602
1603
0
    return( -1 );
1604
0
  }
1605
0
  if( data_size > (size_t) SSIZE_MAX )
1606
0
  {
1607
0
    libcerror_error_set(
1608
0
     error,
1609
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1610
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1611
0
     "%s: invalid data size value exceeds maximum.",
1612
0
     function );
1613
1614
0
    return( -1 );
1615
0
  }
1616
0
  if( pattern == NULL )
1617
0
  {
1618
0
    libcerror_error_set(
1619
0
     error,
1620
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1621
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1622
0
     "%s: invalid pattern.",
1623
0
     function );
1624
1625
0
    return( -1 );
1626
0
  }
1627
0
  if( ( data_size <= 8 )
1628
0
   || ( ( data_size % 8 ) != 0 ) )
1629
0
  {
1630
0
    return( 0 );
1631
0
  }
1632
0
  data_start = (uint8_t *) data;
1633
0
  data_index = (uint8_t *) data + 8;
1634
0
  data_size -= 8;
1635
1636
  /* Only optimize for data larger than the alignment
1637
   */
1638
0
  if( data_size > ( sizeof( libewf_aligned_t ) + sizeof( libewf_aligned_t ) ) )
1639
0
  {
1640
    /* Align the data start
1641
     */
1642
0
    while( ( (intptr_t) data_start % sizeof( libewf_aligned_t ) ) != 0 )
1643
0
    {
1644
0
      if( *data_start != *data_index )
1645
0
      {
1646
0
        return( 0 );
1647
0
      }
1648
0
      data_start++;
1649
0
      data_index++;
1650
0
      data_size--;
1651
0
    }
1652
    /* Align the data index
1653
     */
1654
0
    while( ( (intptr_t) data_index % sizeof( libewf_aligned_t ) ) != 0 )
1655
0
    {
1656
0
      if( *data_start != *data_index )
1657
0
      {
1658
0
        return( 0 );
1659
0
      }
1660
0
      data_index++;
1661
0
      data_size--;
1662
0
    }
1663
0
    aligned_data_start = (libewf_aligned_t *) data_start;
1664
0
    aligned_data_index = (libewf_aligned_t *) data_index;
1665
1666
0
    while( data_size > sizeof( libewf_aligned_t ) )
1667
0
    {
1668
0
      if( *aligned_data_start != *aligned_data_index )
1669
0
      {
1670
0
        return( 0 );
1671
0
      }
1672
0
      aligned_data_start++;
1673
0
      aligned_data_index++;
1674
1675
0
      data_size -= sizeof( libewf_aligned_t );
1676
0
    }
1677
0
    data_start = (uint8_t *) aligned_data_start;
1678
0
    data_index = (uint8_t *) aligned_data_index;
1679
0
  }
1680
0
  while( data_size != 0 )
1681
0
  {
1682
0
    if( *data_start != *data_index )
1683
0
    {
1684
0
      return( 0 );
1685
0
    }
1686
0
    data_start++;
1687
0
    data_index++;
1688
0
    data_size--;
1689
0
  }
1690
0
  byte_stream_copy_to_uint64_little_endian(
1691
0
   data,
1692
0
   *pattern );
1693
1694
0
  return( 1 );
1695
0
}
1696
1697
/* Writes a chunk
1698
 * Returns 1 if successful or -1 on error
1699
 */
1700
ssize_t libewf_chunk_data_write(
1701
         libewf_chunk_data_t *chunk_data,
1702
         libbfio_pool_t *file_io_pool,
1703
         int file_io_pool_entry,
1704
         libcerror_error_t **error )
1705
0
{
1706
0
  uint8_t checksum_buffer[ 4 ];
1707
1708
0
  static char *function     = "libewf_chunk_data_write";
1709
0
  size_t write_size         = 0;
1710
0
  ssize_t total_write_count = 0;
1711
0
  ssize_t write_count       = 0;
1712
1713
0
  if( chunk_data == NULL )
1714
0
  {
1715
0
    libcerror_error_set(
1716
0
     error,
1717
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1718
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1719
0
     "%s: invalid chunk data.",
1720
0
     function );
1721
1722
0
    return( -1 );
1723
0
  }
1724
0
  write_size = chunk_data->data_size + chunk_data->padding_size;
1725
1726
  /* Write the chunk data to the segment file
1727
   */
1728
0
  write_count = libbfio_pool_write_buffer(
1729
0
                 file_io_pool,
1730
0
                 file_io_pool_entry,
1731
0
                 chunk_data->data,
1732
0
                 write_size,
1733
0
                 error );
1734
1735
0
  if( write_count != (ssize_t) write_size )
1736
0
  {
1737
0
    libcerror_error_set(
1738
0
     error,
1739
0
     LIBCERROR_ERROR_DOMAIN_IO,
1740
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
1741
0
     "%s: unable to write chunk data.",
1742
0
     function );
1743
1744
0
    return( -1 );
1745
0
  }
1746
0
  total_write_count += write_count;
1747
1748
0
  if( ( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) == 0 )
1749
0
   && ( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_HAS_CHECKSUM ) != 0 ) )
1750
0
  {
1751
    /* Check if the chunk and checksum buffers are aligned
1752
     * if not the checksum needs to be written separately
1753
     */
1754
0
    if( ( chunk_data->chunk_io_flags & LIBEWF_CHUNK_IO_FLAG_CHECKSUM_SET ) != 0 )
1755
0
    {
1756
0
      byte_stream_copy_from_uint32_little_endian(
1757
0
       checksum_buffer,
1758
0
       chunk_data->checksum );
1759
1760
0
      write_count = libbfio_pool_write_buffer(
1761
0
               file_io_pool,
1762
0
               file_io_pool_entry,
1763
0
               checksum_buffer,
1764
0
               4,
1765
0
               error );
1766
1767
0
      if( write_count != (ssize_t) 4 )
1768
0
      {
1769
0
        libcerror_error_set(
1770
0
         error,
1771
0
         LIBCERROR_ERROR_DOMAIN_IO,
1772
0
         LIBCERROR_IO_ERROR_WRITE_FAILED,
1773
0
         "%s: unable to write chunk checksum.",
1774
0
         function );
1775
1776
0
        return( -1 );
1777
0
      }
1778
0
      total_write_count += write_count;
1779
0
    }
1780
0
  }
1781
0
  return( total_write_count );
1782
0
}
1783
1784
/* Retrieves the write size of the chunk
1785
 * Returns 1 if successful or -1 on error
1786
 */
1787
int libewf_chunk_data_get_write_size(
1788
     libewf_chunk_data_t *chunk_data,
1789
     uint32_t *write_size,
1790
     libcerror_error_t **error )
1791
0
{
1792
0
  static char *function  = "libewf_chunk_data_get_write_size";
1793
0
  size_t safe_write_size = 0;
1794
1795
0
  if( chunk_data == NULL )
1796
0
  {
1797
0
    libcerror_error_set(
1798
0
     error,
1799
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1800
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1801
0
     "%s: invalid chunk data.",
1802
0
     function );
1803
1804
0
    return( -1 );
1805
0
  }
1806
#if SIZEOF_SIZE_T <= 4
1807
  if( chunk_data->data_size > (size_t) SSIZE_MAX )
1808
#else
1809
0
  if( chunk_data->data_size > (size_t) UINT32_MAX )
1810
0
#endif
1811
0
  {
1812
0
    libcerror_error_set(
1813
0
     error,
1814
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1815
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1816
0
     "%s: invalid chunk data - data size value out of bounds.",
1817
0
     function );
1818
1819
0
    return( -1 );
1820
0
  }
1821
#if SIZEOF_SIZE_T <= 4
1822
  if( chunk_data->padding_size > (size_t) SSIZE_MAX )
1823
#else
1824
0
  if( chunk_data->padding_size > (size_t) UINT32_MAX )
1825
0
#endif
1826
0
  {
1827
0
    libcerror_error_set(
1828
0
     error,
1829
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1830
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1831
0
     "%s: invalid chunk data - padding size value out of bounds.",
1832
0
     function );
1833
1834
0
    return( -1 );
1835
0
  }
1836
0
  if( write_size == NULL )
1837
0
  {
1838
0
    libcerror_error_set(
1839
0
     error,
1840
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1841
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1842
0
     "%s: invalid write size.",
1843
0
     function );
1844
1845
0
    return( -1 );
1846
0
  }
1847
0
  safe_write_size = chunk_data->data_size + chunk_data->padding_size;
1848
1849
0
  if( ( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) == 0 )
1850
0
   && ( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_HAS_CHECKSUM ) != 0 ) )
1851
0
  {
1852
0
    if( ( chunk_data->chunk_io_flags & LIBEWF_CHUNK_IO_FLAG_CHECKSUM_SET ) != 0 )
1853
0
    {
1854
0
      safe_write_size += 4;
1855
0
    }
1856
0
  }
1857
#if SIZEOF_SIZE_T <= 4
1858
  if( safe_write_size > (size_t) SSIZE_MAX )
1859
#else
1860
0
  if( safe_write_size > (size_t) UINT32_MAX )
1861
0
#endif
1862
0
  {
1863
0
    libcerror_error_set(
1864
0
     error,
1865
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1866
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1867
0
     "%s: invalid write size value out of bounds.",
1868
0
     function );
1869
1870
0
    return( -1 );
1871
0
  }
1872
0
  *write_size = (uint32_t) safe_write_size;
1873
1874
0
  return( 1 );
1875
0
}
1876
1877
/* Retrieves the (stored) checksum
1878
 * Returns 1 if successful, 0 if no checksum or -1 on error
1879
 */
1880
int libewf_chunk_data_get_checksum(
1881
     libewf_chunk_data_t *chunk_data,
1882
     uint16_t compression_method,
1883
     uint32_t *checksum,
1884
     libcerror_error_t **error )
1885
0
{
1886
0
  static char *function = "libewf_chunk_data_get_checksum";
1887
0
  int result            = 0;
1888
1889
0
  if( chunk_data == NULL )
1890
0
  {
1891
0
    libcerror_error_set(
1892
0
     error,
1893
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1894
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1895
0
     "%s: invalid chunk data.",
1896
0
     function );
1897
1898
0
    return( -1 );
1899
0
  }
1900
0
  if( checksum == NULL )
1901
0
  {
1902
0
    libcerror_error_set(
1903
0
     error,
1904
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1905
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1906
0
     "%s: invalid checksum.",
1907
0
     function );
1908
1909
0
    return( -1 );
1910
0
  }
1911
0
  if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) != 0 )
1912
0
  {
1913
0
    if( chunk_data->data_size < 4 )
1914
0
    {
1915
0
      libcerror_error_set(
1916
0
       error,
1917
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1918
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1919
0
       "%s: invalid chunk data size value out of bounds.",
1920
0
       function );
1921
1922
0
      return( -1 );
1923
0
    }
1924
0
    if( compression_method == LIBEWF_COMPRESSION_METHOD_DEFLATE )
1925
0
    {
1926
0
      byte_stream_copy_to_uint32_little_endian(
1927
0
       &( ( chunk_data->data )[ chunk_data->data_size - 4 ] ),
1928
0
       *checksum );
1929
1930
0
      result = 1;
1931
0
    }
1932
0
    else if( compression_method == LIBEWF_COMPRESSION_METHOD_BZIP2 )
1933
0
    {
1934
/* TODO bzip2 support */
1935
0
    }
1936
0
  }
1937
0
  else if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_HAS_CHECKSUM ) != 0 )
1938
0
  {
1939
/* TODO chunk data rewrite:
1940
* Set LIBEWF_CHUNK_IO_FLAG_CHECKSUM_SET chunk_data->chunk_io_flags if the checksum is not provided within the chunk data
1941
*/
1942
0
    if( ( chunk_data->chunk_io_flags & LIBEWF_CHUNK_IO_FLAG_CHECKSUM_SET ) != 0 )
1943
0
    {
1944
0
      *checksum = chunk_data->checksum;
1945
1946
0
      result = 1;
1947
0
    }
1948
/* TODO chunk data rewrite */
1949
0
    else if( ( chunk_data->range_flags & LIBEWF_RANGE_FLAG_IS_PACKED ) == 0 )
1950
0
    {
1951
0
      if( ( chunk_data->data_size < 4 )
1952
0
       || ( ( chunk_data->data_size + 4 ) > chunk_data->allocated_data_size ) )
1953
0
      {
1954
0
        libcerror_error_set(
1955
0
         error,
1956
0
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1957
0
         LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1958
0
         "%s: invalid chunk data size value out of bounds.",
1959
0
         function );
1960
1961
0
        return( -1 );
1962
0
      }
1963
0
      byte_stream_copy_to_uint32_little_endian(
1964
0
       &( ( chunk_data->data )[ chunk_data->data_size ] ),
1965
0
       *checksum );
1966
1967
0
      result = 1;
1968
0
    }
1969
0
    else
1970
0
    {
1971
0
      if( ( chunk_data->data_size < 4 )
1972
0
       || ( chunk_data->data_size > chunk_data->allocated_data_size ) )
1973
0
      {
1974
0
        libcerror_error_set(
1975
0
         error,
1976
0
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1977
0
         LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1978
0
         "%s: invalid chunk data size value out of bounds.",
1979
0
         function );
1980
1981
0
        return( -1 );
1982
0
      }
1983
0
      byte_stream_copy_to_uint32_little_endian(
1984
0
       &( ( chunk_data->data )[ chunk_data->data_size - 4 ] ),
1985
0
       *checksum );
1986
1987
0
      result = 1;
1988
0
    }
1989
0
  }
1990
0
  return( result );
1991
0
}
1992
1993
/* Reads chunk data from the file IO pool
1994
 * Returns the number of bytes read, 0 when no longer data can be read or -1 on error
1995
 */
1996
ssize_t libewf_chunk_data_read_from_file_io_pool(
1997
         libewf_chunk_data_t *chunk_data,
1998
         libbfio_pool_t *file_io_pool,
1999
         int file_io_pool_entry,
2000
         off64_t chunk_data_offset,
2001
         size64_t chunk_data_size,
2002
         uint32_t chunk_data_flags,
2003
         libcerror_error_t **error )
2004
0
{
2005
0
  static char *function = "libewf_chunk_data_read_from_file_io_pool";
2006
0
  ssize_t read_count    = 0;
2007
2008
0
  if( chunk_data == NULL )
2009
0
  {
2010
0
    libcerror_error_set(
2011
0
     error,
2012
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2013
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2014
0
     "%s: invalid chunk data.",
2015
0
     function );
2016
2017
0
    return( -1 );
2018
0
  }
2019
0
  if( ( chunk_data_size == (size64_t) 0 )
2020
0
   || ( chunk_data_size > (size64_t) chunk_data->allocated_data_size ) )
2021
0
  {
2022
0
    libcerror_error_set(
2023
0
     error,
2024
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2025
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2026
0
     "%s: invalid chunk data size value out of bounds.",
2027
0
     function );
2028
2029
0
    return( -1 );
2030
0
  }
2031
0
  read_count = libbfio_pool_read_buffer_at_offset(
2032
0
          file_io_pool,
2033
0
          file_io_pool_entry,
2034
0
          chunk_data->data,
2035
0
          (size_t) chunk_data_size,
2036
0
                chunk_data_offset,
2037
0
          error );
2038
2039
0
  if( read_count != (ssize_t) chunk_data_size )
2040
0
  {
2041
0
    libcerror_error_set(
2042
0
     error,
2043
0
     LIBCERROR_ERROR_DOMAIN_IO,
2044
0
     LIBCERROR_IO_ERROR_READ_FAILED,
2045
0
     "%s: unable to read chunk data at offset: %" PRIi64 " (0x%08" PRIx64 ") in file IO pool entry: %d.",
2046
0
     function,
2047
0
     chunk_data_offset,
2048
0
     chunk_data_offset,
2049
0
     file_io_pool_entry );
2050
2051
0
    return( -1 );
2052
0
  }
2053
0
  chunk_data->data_size = (size_t) read_count;
2054
2055
0
  chunk_data->range_flags = ( chunk_data_flags | LIBEWF_RANGE_FLAG_IS_PACKED )
2056
0
                          & ~( LIBEWF_RANGE_FLAG_IS_TAINTED | LIBEWF_RANGE_FLAG_IS_CORRUPTED );
2057
2058
0
  return( read_count );
2059
0
}
2060
2061
/* Reads chunk data
2062
 * Callback function for the chunks list
2063
 * Returns 1 if successful or -1 on error
2064
 */
2065
int libewf_chunk_data_read_element_data(
2066
     libewf_io_handle_t *io_handle,
2067
     libbfio_pool_t *file_io_pool,
2068
     libfdata_list_element_t *element,
2069
     libfdata_cache_t *cache,
2070
     int file_io_pool_entry,
2071
     off64_t chunk_data_offset,
2072
     size64_t chunk_data_size,
2073
     uint32_t chunk_data_flags,
2074
     uint8_t read_flags LIBEWF_ATTRIBUTE_UNUSED,
2075
     libcerror_error_t **error )
2076
0
{
2077
0
  libewf_chunk_data_t *chunk_data = NULL;
2078
0
  static char *function           = "libewf_chunk_data_read_element_data";
2079
0
  size32_t chunk_size             = 0;
2080
0
  ssize_t read_count              = 0;
2081
2082
0
  LIBEWF_UNREFERENCED_PARAMETER( read_flags )
2083
2084
0
  if( io_handle == NULL )
2085
0
  {
2086
0
    libcerror_error_set(
2087
0
     error,
2088
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2089
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2090
0
     "%s: invalid IO handle.",
2091
0
     function );
2092
2093
0
    return( -1 );
2094
0
  }
2095
0
  if( io_handle->chunk_size == 0 )
2096
0
  {
2097
0
    libcerror_error_set(
2098
0
     error,
2099
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2100
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2101
0
     "%s: invalid IO handle - missing chunk size.",
2102
0
     function );
2103
2104
0
    return( -1 );
2105
0
  }
2106
0
  if( ( chunk_data_flags & LIBEWF_RANGE_FLAG_IS_SPARSE ) != 0 )
2107
0
  {
2108
0
    libcerror_error_set(
2109
0
     error,
2110
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2111
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2112
0
     "%s: unsupported chunk data flags.",
2113
0
     function );
2114
2115
0
    return( -1 );
2116
0
  }
2117
0
  chunk_size = io_handle->chunk_size;
2118
2119
0
  if( io_handle->segment_file_type == LIBEWF_SEGMENT_FILE_TYPE_EWF1_SMART )
2120
0
  {
2121
    /* In EWF-S01 (SMART) the size of a stored chunk can be larger than the chunk size
2122
     */
2123
0
    chunk_size *= 2;
2124
0
  }
2125
0
  if( libewf_chunk_data_initialize(
2126
0
       &chunk_data,
2127
0
       chunk_size,
2128
0
       0,
2129
0
       error ) != 1 )
2130
0
  {
2131
0
    libcerror_error_set(
2132
0
     error,
2133
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2134
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2135
0
     "%s: unable to create chunk data.",
2136
0
     function );
2137
2138
0
    goto on_error;
2139
0
  }
2140
#if defined( HAVE_DEBUG_OUTPUT )
2141
  if( libcnotify_verbose != 0 )
2142
  {
2143
    libcnotify_printf(
2144
     "%s: reading chunk at offset: 0x%08" PRIx64 " with size: %" PRIu64 " in file IO pool entry: %d.\n",
2145
     function,
2146
     chunk_data_offset,
2147
     chunk_data_size,
2148
     file_io_pool_entry );
2149
  }
2150
#endif
2151
2152
#if defined( HAVE_DEBUG_OUTPUT )
2153
  if( libcnotify_verbose != 0 )
2154
  {
2155
    libcnotify_printf(
2156
     "%s: chunk file IO pool entry\t\t: %d\n",
2157
     function,
2158
     file_io_pool_entry );
2159
2160
    libcnotify_printf(
2161
     "%s: chunk offset\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
2162
     function,
2163
     chunk_data_offset,
2164
     chunk_data_offset );
2165
2166
    libcnotify_printf(
2167
     "%s: chunk size\t\t\t\t: %" PRIu64 "\n",
2168
     function,
2169
     chunk_data_size );
2170
2171
    libcnotify_printf(
2172
     "%s: chunk flags:\n",
2173
     function );
2174
2175
    if( ( chunk_data_flags & LIBEWF_RANGE_FLAG_IS_COMPRESSED ) != 0 )
2176
    {
2177
      libcnotify_printf(
2178
       "\tIs compressed\n" );
2179
    }
2180
    if( ( chunk_data_flags & LIBEWF_RANGE_FLAG_HAS_CHECKSUM ) != 0 )
2181
    {
2182
      libcnotify_printf(
2183
       "\tHas checksum\n" );
2184
    }
2185
    libcnotify_printf(
2186
     "\n" );
2187
  }
2188
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
2189
2190
0
  read_count = libewf_chunk_data_read_from_file_io_pool(
2191
0
          chunk_data,
2192
0
          file_io_pool,
2193
0
          file_io_pool_entry,
2194
0
                chunk_data_offset,
2195
0
          chunk_data_size,
2196
0
          chunk_data_flags,
2197
0
          error );
2198
2199
0
  if( read_count < 0 )
2200
0
  {
2201
0
    libcerror_error_set(
2202
0
     error,
2203
0
     LIBCERROR_ERROR_DOMAIN_IO,
2204
0
     LIBCERROR_IO_ERROR_READ_FAILED,
2205
0
     "%s: unable to read chunk data.",
2206
0
     function );
2207
2208
0
    goto on_error;
2209
0
  }
2210
#if defined( HAVE_DEBUG_OUTPUT )
2211
  if( libcnotify_verbose != 0 )
2212
  {
2213
    if( chunk_data == NULL )
2214
    {
2215
      libcerror_error_set(
2216
       error,
2217
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2218
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2219
       "%s: missing chunk data.",
2220
       function );
2221
2222
      goto on_error;
2223
    }
2224
    if( ( ( chunk_data_flags & LIBEWF_RANGE_FLAG_HAS_CHECKSUM ) != 0 )
2225
     && ( chunk_data->data_size >= 4 ) )
2226
    {
2227
      byte_stream_copy_to_uint32_little_endian(
2228
       &( ( chunk_data->data )[ chunk_data->data_size - 4 ] ),
2229
       chunk_data->checksum );
2230
2231
      libcnotify_printf(
2232
       "%s: chunk checksum\t\t\t: 0x%08" PRIx32 "\n",
2233
       function,
2234
       chunk_data->checksum );
2235
2236
      libcnotify_printf(
2237
       "\n" );
2238
    }
2239
  }
2240
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
2241
2242
0
  if( libfdata_list_element_set_element_value(
2243
0
       element,
2244
0
       (intptr_t *) file_io_pool,
2245
0
       cache,
2246
0
       (intptr_t *) chunk_data,
2247
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libewf_chunk_data_free,
2248
0
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
2249
0
       error ) != 1 )
2250
0
  {
2251
0
    libcerror_error_set(
2252
0
     error,
2253
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2254
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2255
0
     "%s: unable to set chunk data as element value.",
2256
0
     function );
2257
2258
0
    goto on_error;
2259
0
  }
2260
0
  return( 1 );
2261
2262
0
on_error:
2263
0
  if( chunk_data != NULL )
2264
0
  {
2265
0
    libewf_chunk_data_free(
2266
0
     &chunk_data,
2267
     NULL );
2268
0
  }
2269
0
  return( -1 );
2270
0
}
2271