Coverage Report

Created: 2025-10-14 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvshadow/libvshadow/libvshadow_io_handle.c
Line
Count
Source
1
/*
2
 * Input/Output (IO) handle functions
3
 *
4
 * Copyright (C) 2011-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 <types.h>
26
27
#include "libvshadow_block_descriptor.h"
28
#include "libvshadow_block_tree.h"
29
#include "libvshadow_block_tree_node.h"
30
#include "libvshadow_debug.h"
31
#include "libvshadow_definitions.h"
32
#include "libvshadow_io_handle.h"
33
#include "libvshadow_libbfio.h"
34
#include "libvshadow_libcdata.h"
35
#include "libvshadow_libcerror.h"
36
#include "libvshadow_libcnotify.h"
37
#include "libvshadow_libfdatetime.h"
38
#include "libvshadow_libfguid.h"
39
#include "libvshadow_store_descriptor.h"
40
41
#include "vshadow_catalog.h"
42
#include "vshadow_volume.h"
43
44
const uint8_t vshadow_vss_identifier[ 16 ] = {
45
  0x6b, 0x87, 0x08, 0x38, 0x76, 0xc1, 0x48, 0x4e, 0xb7, 0xae, 0x04, 0x04, 0x6e, 0x6c, 0xc7, 0x52 };
46
47
/* Creates an IO handle
48
 * Make sure the value io_handle is referencing, is set to NULL
49
 * Returns 1 if successful or -1 on error
50
 */
51
int libvshadow_io_handle_initialize(
52
     libvshadow_io_handle_t **io_handle,
53
     libcerror_error_t **error )
54
1.61k
{
55
1.61k
  static char *function = "libvshadow_io_handle_initialize";
56
57
1.61k
  if( io_handle == NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
63
0
     "%s: invalid IO handle.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
1.61k
  if( *io_handle != NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
74
0
     "%s: invalid IO handle value already set.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
1.61k
  *io_handle = memory_allocate_structure(
80
1.61k
                libvshadow_io_handle_t );
81
82
1.61k
  if( *io_handle == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
87
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
88
0
     "%s: unable to create IO handle.",
89
0
     function );
90
91
0
    goto on_error;
92
0
  }
93
1.61k
  if( memory_set(
94
1.61k
       *io_handle,
95
1.61k
       0,
96
1.61k
       sizeof( libvshadow_io_handle_t ) ) == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
102
0
     "%s: unable to clear IO handle.",
103
0
     function );
104
105
0
    goto on_error;
106
0
  }
107
1.61k
  ( *io_handle )->block_size = 0x4000;
108
109
1.61k
  return( 1 );
110
111
0
on_error:
112
0
  if( *io_handle != NULL )
113
0
  {
114
0
    memory_free(
115
0
     *io_handle );
116
117
0
    *io_handle = NULL;
118
0
  }
119
0
  return( -1 );
120
1.61k
}
121
122
/* Frees an IO handle
123
 * Returns 1 if successful or -1 on error
124
 */
125
int libvshadow_io_handle_free(
126
     libvshadow_io_handle_t **io_handle,
127
     libcerror_error_t **error )
128
1.61k
{
129
1.61k
  static char *function = "libvshadow_io_handle_free";
130
131
1.61k
  if( io_handle == NULL )
132
0
  {
133
0
    libcerror_error_set(
134
0
     error,
135
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
136
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
137
0
     "%s: invalid IO handle.",
138
0
     function );
139
140
0
    return( -1 );
141
0
  }
142
1.61k
  if( *io_handle != NULL )
143
1.61k
  {
144
1.61k
    memory_free(
145
1.61k
     *io_handle );
146
147
1.61k
    *io_handle = NULL;
148
1.61k
  }
149
1.61k
  return( 1 );
150
1.61k
}
151
152
/* Clears the IO handle
153
 * Returns 1 if successful or -1 on error
154
 */
155
int libvshadow_io_handle_clear(
156
     libvshadow_io_handle_t *io_handle,
157
     libcerror_error_t **error )
158
60
{
159
60
  static char *function = "libvshadow_io_handle_clear";
160
161
60
  if( io_handle == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
167
0
     "%s: invalid IO handle.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
60
  if( memory_set(
173
60
       io_handle,
174
60
       0,
175
60
       sizeof( libvshadow_io_handle_t ) ) == NULL )
176
0
  {
177
0
    libcerror_error_set(
178
0
     error,
179
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
180
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
181
0
     "%s: unable to clear IO handle.",
182
0
     function );
183
184
0
    return( -1 );
185
0
  }
186
60
  io_handle->block_size = 0x4000;
187
188
60
  return( 1 );
189
60
}
190
191
/* Checks if this is the first time the block is being read
192
 * Returns 1 if successful or -1 on error
193
 */
194
int libvshadow_io_handle_check_if_block_first_read(
195
     libvshadow_io_handle_t *io_handle,
196
     libvshadow_block_tree_t *block_tree,
197
     off64_t block_offset,
198
     libcerror_error_t **error )
199
866
{
200
866
  libvshadow_block_descriptor_t *existing_block_descriptor = NULL;
201
866
  libvshadow_block_descriptor_t *new_block_descriptor      = NULL;
202
866
  libvshadow_block_tree_node_t *leaf_block_tree_node       = NULL;
203
866
  static char *function                                    = "libvshadow_io_handle_check_if_block_first_read";
204
866
  int leaf_value_index                                     = 0;
205
866
  int result                                               = 0;
206
207
866
  if( io_handle == NULL )
208
0
  {
209
0
    libcerror_error_set(
210
0
     error,
211
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
212
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
213
0
     "%s: invalid IO handle.",
214
0
     function );
215
216
0
    return( -1 );
217
0
  }
218
866
  if( libvshadow_block_descriptor_initialize(
219
866
       &new_block_descriptor,
220
866
       error ) != 1 )
221
0
  {
222
0
    libcerror_error_set(
223
0
     error,
224
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
225
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
226
0
     "%s: unable to create block descriptor.",
227
0
     function );
228
229
0
    goto on_error;
230
0
  }
231
866
  new_block_descriptor->offset = block_offset;
232
233
866
  result = libvshadow_block_tree_insert_block_descriptor_by_offset(
234
866
            block_tree,
235
866
            block_offset,
236
866
            new_block_descriptor,
237
866
            &leaf_value_index,
238
866
            &leaf_block_tree_node,
239
866
            &existing_block_descriptor,
240
866
            error );
241
242
866
  if( result == -1 )
243
114
  {
244
114
    libcerror_error_set(
245
114
     error,
246
114
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
247
114
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
248
114
     "%s: unable to insert block descriptor in block tree.",
249
114
     function );
250
251
114
    goto on_error;
252
114
  }
253
752
  else if( result == 0 )
254
2
  {
255
2
    libcerror_error_set(
256
2
     error,
257
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
258
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
259
2
     "%s: invalid block offset: %" PRIi64 " (0x%08" PRIx64 ") value already exists.",
260
2
     function,
261
2
     block_offset,
262
2
     block_offset );
263
264
2
    goto on_error;
265
2
  }
266
750
  new_block_descriptor = NULL;
267
268
750
  return( 1 );
269
270
116
on_error:
271
116
  if( new_block_descriptor != NULL )
272
116
  {
273
116
    libvshadow_block_descriptor_free(
274
116
     &new_block_descriptor,
275
116
     NULL );
276
116
  }
277
116
  return( -1 );
278
866
}
279
280
/* Reads the volume header
281
 * Returns 1 if successful or -1 on error
282
 */
283
int libvshadow_io_handle_read_volume_header(
284
     libvshadow_io_handle_t *io_handle,
285
     libbfio_handle_t *file_io_handle,
286
     off64_t file_offset,
287
     off64_t *catalog_offset,
288
     libcerror_error_t **error )
289
1.01k
{
290
1.01k
  vshadow_volume_header_t volume_header;
291
292
1.01k
  static char *function = "libvshadow_io_handle_read_volume_header";
293
1.01k
  ssize_t read_count    = 0;
294
295
1.01k
  if( io_handle == NULL )
296
0
  {
297
0
    libcerror_error_set(
298
0
     error,
299
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
300
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
301
0
     "%s: invalid IO handle.",
302
0
     function );
303
304
0
    return( -1 );
305
0
  }
306
#if defined( HAVE_DEBUG_OUTPUT )
307
  if( libcnotify_verbose != 0 )
308
  {
309
    libcnotify_printf(
310
     "%s: reading volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
311
     function,
312
     file_offset,
313
     file_offset );
314
  }
315
#endif
316
1.01k
  read_count = libbfio_handle_read_buffer_at_offset(
317
1.01k
                file_io_handle,
318
1.01k
                (uint8_t *) &volume_header,
319
1.01k
                sizeof( vshadow_volume_header_t ),
320
1.01k
                file_offset,
321
1.01k
                error );
322
323
1.01k
  if( read_count != (ssize_t) sizeof( vshadow_volume_header_t ) )
324
34
  {
325
34
    libcerror_error_set(
326
34
     error,
327
34
     LIBCERROR_ERROR_DOMAIN_IO,
328
34
     LIBCERROR_IO_ERROR_READ_FAILED,
329
34
     "%s: unable to read volume header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
330
34
     function,
331
34
     file_offset,
332
34
     file_offset );
333
334
34
    return( -1 );
335
34
  }
336
985
  if( libvshadow_io_handle_read_volume_header_data(
337
985
       io_handle,
338
985
       (uint8_t *) &volume_header,
339
985
       sizeof( vshadow_volume_header_t ),
340
985
       catalog_offset,
341
985
       error ) != 1 )
342
80
  {
343
80
    libcerror_error_set(
344
80
     error,
345
80
     LIBCERROR_ERROR_DOMAIN_IO,
346
80
     LIBCERROR_IO_ERROR_READ_FAILED,
347
80
     "%s: unable to read volume header.",
348
80
     function );
349
350
80
    return( -1 );
351
80
  }
352
905
  return( 1 );
353
985
}
354
355
/* Reads the volume header
356
 * Returns 1 if successful or -1 on error
357
 */
358
int libvshadow_io_handle_read_volume_header_data(
359
     libvshadow_io_handle_t *io_handle,
360
     const uint8_t *data,
361
     size_t data_size,
362
     off64_t *catalog_offset,
363
     libcerror_error_t **error )
364
985
{
365
985
  static char *function        = "libvshadow_io_handle_read_volume_header_data";
366
985
  uint64_t safe_catalog_offset = 0;
367
985
  uint32_t record_type         = 0;
368
985
  uint32_t version             = 0;
369
370
#if defined( HAVE_DEBUG_OUTPUT )
371
  uint64_t value_64bit         = 0;
372
  uint32_t value_32bit         = 0;
373
#endif
374
375
985
  if( io_handle == NULL )
376
0
  {
377
0
    libcerror_error_set(
378
0
     error,
379
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
380
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
381
0
     "%s: invalid IO handle.",
382
0
     function );
383
384
0
    return( -1 );
385
0
  }
386
985
  if( data == NULL )
387
0
  {
388
0
    libcerror_error_set(
389
0
     error,
390
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
391
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
392
0
     "%s: invalid data.",
393
0
     function );
394
395
0
    return( -1 );
396
0
  }
397
985
  if( ( data_size < sizeof( vshadow_volume_header_t ) )
398
985
   || ( data_size > (size_t) SSIZE_MAX ) )
399
0
  {
400
0
    libcerror_error_set(
401
0
     error,
402
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
403
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
404
0
     "%s: invalid data size value out of bounds.",
405
0
     function );
406
407
0
    return( -1 );
408
0
  }
409
985
  if( catalog_offset == NULL )
410
0
  {
411
0
    libcerror_error_set(
412
0
     error,
413
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
414
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
415
0
     "%s: invalid catalog offset.",
416
0
     function );
417
418
0
    return( -1 );
419
0
  }
420
#if defined( HAVE_DEBUG_OUTPUT )
421
  if( libcnotify_verbose != 0 )
422
  {
423
    libcnotify_printf(
424
     "%s: volume header data:\n",
425
     function );
426
    libcnotify_print_data(
427
     data,
428
     data_size,
429
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
430
  }
431
#endif
432
985
  if( memory_compare(
433
985
       ( (vshadow_volume_header_t *) data )->identifier,
434
985
       vshadow_vss_identifier,
435
985
       8 ) != 0 )
436
1
  {
437
1
    libcerror_error_set(
438
1
     error,
439
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
440
1
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
441
1
     "%s: invalid volume identifier.",
442
1
     function );
443
444
1
    return( -1 );
445
1
  }
446
984
  byte_stream_copy_to_uint32_little_endian(
447
984
   ( (vshadow_volume_header_t *) data )->version,
448
984
   version );
449
450
984
  byte_stream_copy_to_uint32_little_endian(
451
984
   ( (vshadow_volume_header_t *) data )->record_type,
452
984
   record_type );
453
454
984
  byte_stream_copy_to_uint64_little_endian(
455
984
   ( (vshadow_volume_header_t *) data )->catalog_offset,
456
984
   safe_catalog_offset );
457
458
#if defined( HAVE_DEBUG_OUTPUT )
459
  if( libcnotify_verbose != 0 )
460
  {
461
    if( libvshadow_debug_print_guid_value(
462
         function,
463
         "identifier\t\t",
464
         ( (vshadow_volume_header_t *) data )->identifier,
465
         16,
466
         LIBFGUID_ENDIAN_LITTLE,
467
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
468
         error ) != 1 )
469
    {
470
      libcerror_error_set(
471
       error,
472
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
473
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
474
       "%s: unable to print GUID value.",
475
       function );
476
477
      return( -1 );
478
    }
479
    libcnotify_printf(
480
     "%s: version\t\t\t: %" PRIu32 "\n",
481
     function,
482
     version );
483
484
    libcnotify_printf(
485
     "%s: record type\t\t: %" PRIu32 "\n",
486
     function,
487
     record_type );
488
489
    byte_stream_copy_to_uint64_little_endian(
490
     ( (vshadow_volume_header_t *) data )->offset,
491
     value_64bit );
492
    libcnotify_printf(
493
     "%s: offset\t\t\t: 0x%08" PRIx64 "\n",
494
     function,
495
     value_64bit );
496
497
    byte_stream_copy_to_uint64_little_endian(
498
     ( (vshadow_volume_header_t *) data )->unknown1,
499
     value_64bit );
500
    libcnotify_printf(
501
     "%s: unknown1\t\t\t: 0x%08" PRIx64 "\n",
502
     function,
503
     value_64bit );
504
505
    byte_stream_copy_to_uint64_little_endian(
506
     ( (vshadow_volume_header_t *) data )->unknown2,
507
     value_64bit );
508
    libcnotify_printf(
509
     "%s: unknown2\t\t\t: 0x%08" PRIx64 "\n",
510
     function,
511
     value_64bit );
512
513
    libcnotify_printf(
514
     "%s: catalog offset\t\t: 0x%08" PRIx64 "\n",
515
     function,
516
     safe_catalog_offset );
517
518
    byte_stream_copy_to_uint64_little_endian(
519
     ( (vshadow_volume_header_t *) data )->maximum_size,
520
     value_64bit );
521
    libcnotify_printf(
522
     "%s: maximum size\t\t: %" PRIu64 "\n",
523
     function,
524
     value_64bit );
525
526
    if( libvshadow_debug_print_guid_value(
527
         function,
528
         "volume identifier\t\t",
529
         ( (vshadow_volume_header_t *) data )->volume_identifier,
530
         16,
531
         LIBFGUID_ENDIAN_LITTLE,
532
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
533
         error ) != 1 )
534
    {
535
      libcerror_error_set(
536
       error,
537
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
538
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
539
       "%s: unable to print GUID value.",
540
       function );
541
542
      return( -1 );
543
    }
544
    if( libvshadow_debug_print_guid_value(
545
         function,
546
         "store volume identifier\t",
547
         ( (vshadow_volume_header_t *) data )->store_volume_identifier,
548
         16,
549
         LIBFGUID_ENDIAN_LITTLE,
550
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
551
         error ) != 1 )
552
    {
553
      libcerror_error_set(
554
       error,
555
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
556
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
557
       "%s: unable to print GUID value.",
558
       function );
559
560
      return( -1 );
561
    }
562
    byte_stream_copy_to_uint32_little_endian(
563
     ( (vshadow_volume_header_t *) data )->unknown3,
564
     value_32bit );
565
    libcnotify_printf(
566
     "%s: unknown3\t\t\t: 0x%08" PRIx64 "\n",
567
     function,
568
     value_32bit );
569
570
    libcnotify_printf(
571
     "%s: unknown4:\n",
572
     function );
573
    libcnotify_print_data(
574
     ( (vshadow_volume_header_t *) data )->unknown4,
575
     412,
576
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
577
  }
578
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
579
580
984
  if( ( version != 1 )
581
942
   && ( version != 2 ) )
582
40
  {
583
40
    libcerror_error_set(
584
40
     error,
585
40
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
586
40
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
587
40
     "%s: unsupported version: %" PRIu32 ".",
588
40
     function,
589
40
     version );
590
591
40
    return( -1 );
592
40
  }
593
944
  if( record_type != LIBVSHADOW_RECORD_TYPE_VOLUME_HEADER )
594
39
  {
595
39
    libcerror_error_set(
596
39
     error,
597
39
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
598
39
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
599
39
     "%s: unsupported record type: %" PRIu32 ".",
600
39
     function,
601
39
     version );
602
603
39
    return( -1 );
604
39
  }
605
905
  *catalog_offset = (off64_t) safe_catalog_offset;
606
607
905
  return( 1 );
608
944
}
609
610
/* Reads the catalog
611
 * Returns 1 if successful or -1 on error
612
 */
613
int libvshadow_io_handle_read_catalog(
614
     libvshadow_io_handle_t *io_handle,
615
     libbfio_handle_t *file_io_handle,
616
     off64_t file_offset,
617
     size64_t *volume_size,
618
     libcdata_array_t *store_descriptors_array,
619
     libcerror_error_t **error )
620
858
{
621
858
  libvshadow_block_tree_t *catalog_block_tree          = NULL;
622
858
  libvshadow_store_descriptor_t *last_store_descriptor = NULL;
623
858
  libvshadow_store_descriptor_t *store_descriptor      = NULL;
624
858
  uint8_t *catalog_block_data                          = NULL;
625
858
  static char *function                                = "libvshadow_io_handle_read_catalog";
626
858
  size64_t safe_volume_size                            = 0;
627
858
  size_t catalog_block_offset                          = 0;
628
858
  ssize_t read_count                                   = 0;
629
858
  off64_t next_offset                                  = 0;
630
858
  uint64_t catalog_entry_type                          = 0;
631
858
  int result                                           = 0;
632
858
  int store_descriptor_index                           = 0;
633
634
858
  if( io_handle == NULL )
635
0
  {
636
0
    libcerror_error_set(
637
0
     error,
638
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
639
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
640
0
     "%s: invalid IO handle.",
641
0
     function );
642
643
0
    return( -1 );
644
0
  }
645
858
  if( volume_size == NULL )
646
0
  {
647
0
    libcerror_error_set(
648
0
     error,
649
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
650
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
651
0
     "%s: invalid volume size.",
652
0
     function );
653
654
0
    return( -1 );
655
0
  }
656
858
  catalog_block_data = (uint8_t *) memory_allocate(
657
858
                                    sizeof( uint8_t ) * io_handle->block_size );
658
659
858
  if( catalog_block_data == NULL )
660
0
  {
661
0
    libcerror_error_set(
662
0
     error,
663
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
664
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
665
0
     "%s: unable to catalog block data.",
666
0
     function );
667
668
0
    goto on_error;
669
0
  }
670
858
  if( libvshadow_block_tree_initialize(
671
858
       &catalog_block_tree,
672
858
       io_handle->volume_size,
673
858
       io_handle->block_size,
674
858
       error ) != 1 )
675
0
  {
676
0
    libcerror_error_set(
677
0
     error,
678
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
679
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
680
0
     "%s: unable to create catalog block tree.",
681
0
     function );
682
683
0
    goto on_error;
684
0
  }
685
858
  do
686
866
  {
687
#if defined( HAVE_DEBUG_OUTPUT )
688
    if( libcnotify_verbose != 0 )
689
    {
690
      libcnotify_printf(
691
       "%s: reading catalog block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
692
       function,
693
       file_offset,
694
       file_offset );
695
    }
696
#endif
697
866
    if( libvshadow_io_handle_check_if_block_first_read(
698
866
         io_handle,
699
866
         catalog_block_tree,
700
866
         file_offset,
701
866
         error ) != 1 )
702
116
    {
703
116
      libcerror_error_set(
704
116
       error,
705
116
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
706
116
       LIBCERROR_RUNTIME_ERROR_GENERIC,
707
116
       "%s: unable to check if first read of catalog block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
708
116
       function,
709
116
       file_offset,
710
116
       file_offset );
711
712
116
      goto on_error;
713
116
    }
714
750
    read_count = libbfio_handle_read_buffer_at_offset(
715
750
            file_io_handle,
716
750
            catalog_block_data,
717
750
            io_handle->block_size,
718
750
            file_offset,
719
750
            error );
720
721
750
    if( read_count != (ssize_t) io_handle->block_size )
722
40
    {
723
40
      libcerror_error_set(
724
40
       error,
725
40
       LIBCERROR_ERROR_DOMAIN_IO,
726
40
       LIBCERROR_IO_ERROR_READ_FAILED,
727
40
       "%s: unable to read catalog block data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
728
40
       function,
729
40
       file_offset,
730
40
       file_offset );
731
732
40
      goto on_error;
733
40
    }
734
710
    if( libvshadow_io_handle_read_catalog_header_data(
735
710
         io_handle,
736
710
         catalog_block_data,
737
710
         io_handle->block_size,
738
710
         &next_offset,
739
710
         error ) != 1 )
740
138
    {
741
138
      libcerror_error_set(
742
138
       error,
743
138
       LIBCERROR_ERROR_DOMAIN_IO,
744
138
       LIBCERROR_IO_ERROR_READ_FAILED,
745
138
       "%s: unable to read catalog block header.",
746
138
       function );
747
748
138
      goto on_error;
749
138
    }
750
572
    catalog_block_offset = sizeof( vshadow_catalog_header_t );
751
752
27.4k
    while( catalog_block_offset < io_handle->block_size )
753
27.2k
    {
754
27.2k
      if( store_descriptor == NULL )
755
5.25k
      {
756
5.25k
        if( libvshadow_store_descriptor_initialize(
757
5.25k
             &store_descriptor,
758
5.25k
             error ) != 1 )
759
0
        {
760
0
          libcerror_error_set(
761
0
           error,
762
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
763
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
764
0
           "%s: unable to create store descriptor.",
765
0
           function );
766
767
0
          goto on_error;
768
0
        }
769
5.25k
      }
770
27.2k
      result = libvshadow_store_descriptor_read_catalog_entry(
771
27.2k
                store_descriptor,
772
27.2k
                &( catalog_block_data[ catalog_block_offset ] ),
773
27.2k
                io_handle->block_size - catalog_block_offset,
774
27.2k
                &catalog_entry_type,
775
27.2k
                error );
776
777
27.2k
      if( result == -1 )
778
406
      {
779
406
        libcerror_error_set(
780
406
         error,
781
406
         LIBCERROR_ERROR_DOMAIN_IO,
782
406
         LIBCERROR_IO_ERROR_READ_FAILED,
783
406
         "%s: unable to read catalog entry.",
784
406
         function );
785
786
406
        goto on_error;
787
406
      }
788
26.8k
      if( catalog_entry_type == 2 )
789
4.73k
      {
790
4.73k
        if( libcdata_array_insert_entry(
791
4.73k
             store_descriptors_array,
792
4.73k
             &store_descriptor_index,
793
4.73k
             (intptr_t *) store_descriptor,
794
4.73k
             (int(*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libvshadow_store_descriptor_compare_by_creation_time,
795
4.73k
             LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
796
4.73k
             error ) != 1 )
797
1
        {
798
1
          libcerror_error_set(
799
1
           error,
800
1
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
801
1
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
802
1
           "%s: unable to append store descriptor to array.",
803
1
           function );
804
805
1
          goto on_error;
806
1
        }
807
4.73k
        if( ( safe_volume_size == 0 )
808
991
         && ( store_descriptor_index == 0 ) )
809
580
        {
810
580
          safe_volume_size = store_descriptor->volume_size;
811
580
        }
812
#if defined( HAVE_DEBUG_OUTPUT )
813
        else if( libcnotify_verbose != 0 )
814
        {
815
          if( safe_volume_size != store_descriptor->volume_size )
816
          {
817
            libcnotify_printf(
818
             "%s: store descriptor: %d - mismatch in volume size: %" PRIu64 " (expected: %" PRIu64 ").",
819
             function,
820
             store_descriptor_index,
821
             store_descriptor->volume_size,
822
             safe_volume_size );
823
          }
824
        }
825
#endif
826
4.73k
        last_store_descriptor = store_descriptor;
827
4.73k
        store_descriptor      = NULL;
828
4.73k
      }
829
22.0k
      else if( catalog_entry_type == 3 )
830
2.21k
      {
831
2.21k
        if( ( last_store_descriptor != NULL )
832
1.95k
         && ( memory_compare(
833
1.95k
               store_descriptor->identifier,
834
1.95k
               last_store_descriptor->identifier,
835
1.95k
               16 ) != 0 ) )
836
1.36k
        {
837
1.36k
          result = libcdata_array_get_entry_by_value(
838
1.36k
                    store_descriptors_array,
839
1.36k
                    (intptr_t *) store_descriptor,
840
1.36k
                    (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libvshadow_store_descriptor_compare_by_identifier,
841
1.36k
                    (intptr_t **) &last_store_descriptor,
842
1.36k
                    error );
843
844
1.36k
          if( result == -1 )
845
0
          {
846
0
            libcerror_error_set(
847
0
             error,
848
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
849
0
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
850
0
             "%s: unable to retrieve store descriptors by identifier.",
851
0
             function );
852
853
0
            goto on_error;
854
0
          }
855
1.36k
        }
856
/* TODO look for the last store decriptor ? */
857
2.21k
        if( last_store_descriptor != NULL )
858
1.95k
        {
859
1.95k
          last_store_descriptor->store_block_list_offset       = store_descriptor->store_block_list_offset;
860
1.95k
          last_store_descriptor->store_header_offset           = store_descriptor->store_header_offset;
861
1.95k
          last_store_descriptor->store_block_range_list_offset = store_descriptor->store_block_range_list_offset;
862
1.95k
          last_store_descriptor->store_bitmap_offset           = store_descriptor->store_bitmap_offset;
863
1.95k
          last_store_descriptor->store_previous_bitmap_offset  = store_descriptor->store_previous_bitmap_offset;
864
1.95k
          last_store_descriptor->has_in_volume_store_data      = 1;
865
1.95k
        }
866
#if defined( HAVE_DEBUG_OUTPUT )
867
        else
868
        {
869
          libcnotify_printf(
870
           "%s: missing last store descriptor.\n",
871
           function );
872
        }
873
#endif
874
2.21k
      }
875
26.8k
      catalog_block_offset += (size_t) 128;
876
26.8k
    }
877
165
    file_offset = next_offset;
878
165
  }
879
858
  while( file_offset != 0 );
880
881
157
  if( store_descriptor != NULL )
882
117
  {
883
117
    if( libvshadow_store_descriptor_free(
884
117
         &store_descriptor,
885
117
         error ) != 1 )
886
0
    {
887
0
      libcerror_error_set(
888
0
       error,
889
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
890
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
891
0
       "%s: unable to free store descriptor.",
892
0
       function );
893
894
0
      goto on_error;
895
0
    }
896
117
  }
897
157
  if( libvshadow_block_tree_free(
898
157
       &catalog_block_tree,
899
157
       (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_block_descriptor_free,
900
157
       error ) != 1 )
901
0
  {
902
0
    libcerror_error_set(
903
0
     error,
904
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
905
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
906
0
     "%s: unable to free catalog block tree.",
907
0
     function );
908
909
0
    goto on_error;
910
0
  }
911
157
  memory_free(
912
157
   catalog_block_data );
913
914
157
  *volume_size = safe_volume_size;
915
916
157
  return( 1 );
917
918
701
on_error:
919
701
  if( store_descriptor != NULL )
920
412
  {
921
412
    libvshadow_store_descriptor_free(
922
412
     &store_descriptor,
923
412
     NULL );
924
412
  }
925
701
  if( catalog_block_tree != NULL )
926
701
  {
927
701
    libvshadow_block_tree_free(
928
701
     &catalog_block_tree,
929
701
     (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_block_descriptor_free,
930
701
     NULL );
931
701
  }
932
701
  if( catalog_block_data != NULL )
933
701
  {
934
701
    memory_free(
935
701
     catalog_block_data );
936
701
  }
937
701
  return( -1 );
938
157
}
939
940
/* Reads the catalog header
941
 * Returns 1 if successful or -1 on error
942
 */
943
int libvshadow_io_handle_read_catalog_header_data(
944
     libvshadow_io_handle_t *io_handle,
945
     const uint8_t *data,
946
     size_t data_size,
947
     off64_t *next_offset,
948
     libcerror_error_t **error )
949
710
{
950
710
  static char *function     = "libvshadow_io_handle_read_catalog_header_data";
951
710
  uint64_t safe_next_offset = 0;
952
710
  uint32_t record_type      = 0;
953
710
  uint32_t version          = 0;
954
955
#if defined( HAVE_DEBUG_OUTPUT )
956
  uint64_t value_64bit      = 0;
957
#endif
958
959
710
  if( io_handle == NULL )
960
0
  {
961
0
    libcerror_error_set(
962
0
     error,
963
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
964
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
965
0
     "%s: invalid IO handle.",
966
0
     function );
967
968
0
    return( -1 );
969
0
  }
970
710
  if( data == NULL )
971
0
  {
972
0
    libcerror_error_set(
973
0
     error,
974
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
975
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
976
0
     "%s: invalid data.",
977
0
     function );
978
979
0
    return( -1 );
980
0
  }
981
710
  if( data_size < sizeof( vshadow_catalog_header_t ) )
982
0
  {
983
0
    libcerror_error_set(
984
0
     error,
985
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
986
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
987
0
     "%s: invalid data size value too small.",
988
0
     function );
989
990
0
    return( -1 );
991
0
  }
992
710
  if( data_size > (size_t) SSIZE_MAX )
993
0
  {
994
0
    libcerror_error_set(
995
0
     error,
996
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
997
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
998
0
     "%s: invalid data size value exceeds maximum.",
999
0
     function );
1000
1001
0
    return( -1 );
1002
0
  }
1003
710
  if( next_offset == NULL )
1004
0
  {
1005
0
    libcerror_error_set(
1006
0
     error,
1007
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1008
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1009
0
     "%s: invalid next offset.",
1010
0
     function );
1011
1012
0
    return( -1 );
1013
0
  }
1014
#if defined( HAVE_DEBUG_OUTPUT )
1015
  if( libcnotify_verbose != 0 )
1016
  {
1017
    libcnotify_printf(
1018
     "%s: catalog header data:\n",
1019
     function );
1020
    libcnotify_print_data(
1021
     data,
1022
     data_size,
1023
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1024
  }
1025
#endif
1026
710
  if( memory_compare(
1027
710
       ( (vshadow_catalog_header_t *) data )->identifier,
1028
710
       vshadow_vss_identifier,
1029
710
       8 ) != 0 )
1030
13
  {
1031
13
    libcerror_error_set(
1032
13
     error,
1033
13
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1034
13
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1035
13
     "%s: invalid catalog header identifier.",
1036
13
     function );
1037
1038
13
    return( -1 );
1039
13
  }
1040
697
  byte_stream_copy_to_uint32_little_endian(
1041
697
   ( (vshadow_catalog_header_t *) data )->version,
1042
697
   version );
1043
1044
697
  byte_stream_copy_to_uint32_little_endian(
1045
697
   ( (vshadow_catalog_header_t *) data )->record_type,
1046
697
   record_type );
1047
1048
697
  byte_stream_copy_to_uint64_little_endian(
1049
697
   ( (vshadow_catalog_header_t *) data )->next_offset,
1050
697
   safe_next_offset );
1051
1052
#if defined( HAVE_DEBUG_OUTPUT )
1053
  if( libcnotify_verbose != 0 )
1054
  {
1055
    if( libvshadow_debug_print_guid_value(
1056
         function,
1057
         "identifier\t\t",
1058
         ( (vshadow_catalog_header_t *) data )->identifier,
1059
         16,
1060
         LIBFGUID_ENDIAN_LITTLE,
1061
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
1062
         error ) != 1 )
1063
    {
1064
      libcerror_error_set(
1065
       error,
1066
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1067
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
1068
       "%s: unable to print GUID value.",
1069
       function );
1070
1071
      return( -1 );
1072
    }
1073
    libcnotify_printf(
1074
     "%s: version\t\t\t: %" PRIu32 "\n",
1075
     function,
1076
     version );
1077
1078
    libcnotify_printf(
1079
     "%s: record type\t\t: %" PRIu32 "\n",
1080
     function,
1081
     record_type );
1082
1083
    byte_stream_copy_to_uint64_little_endian(
1084
     ( (vshadow_catalog_header_t *) data )->relative_offset,
1085
     value_64bit );
1086
    libcnotify_printf(
1087
     "%s: relative offset\t\t: 0x%08" PRIx64 "\n",
1088
     function,
1089
     value_64bit );
1090
1091
    byte_stream_copy_to_uint64_little_endian(
1092
     ( (vshadow_catalog_header_t *) data )->offset,
1093
     value_64bit );
1094
    libcnotify_printf(
1095
     "%s: offset\t\t\t: 0x%08" PRIx64 "\n",
1096
     function,
1097
     value_64bit );
1098
1099
    libcnotify_printf(
1100
     "%s: next offset\t\t: 0x%08" PRIx64 "\n",
1101
     function,
1102
     safe_next_offset );
1103
1104
    libcnotify_printf(
1105
     "%s: unknown1:\n",
1106
     function );
1107
    libcnotify_print_data(
1108
     ( (vshadow_catalog_header_t *) data )->unknown1,
1109
     80,
1110
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1111
  }
1112
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1113
1114
697
  if( version != 1 )
1115
37
  {
1116
37
    libcerror_error_set(
1117
37
     error,
1118
37
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1119
37
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1120
37
     "%s: unsupported version: %" PRIu32 ".",
1121
37
     function,
1122
37
     version );
1123
1124
37
    return( -1 );
1125
37
  }
1126
660
  if( record_type != LIBVSHADOW_RECORD_TYPE_CATALOG )
1127
35
  {
1128
35
    libcerror_error_set(
1129
35
     error,
1130
35
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1131
35
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1132
35
     "%s: unsupported record type: %" PRIu32 ".",
1133
35
     function,
1134
35
     version );
1135
1136
35
    return( -1 );
1137
35
  }
1138
625
  if( safe_next_offset > (uint64_t) INT64_MAX )
1139
53
  {
1140
53
    libcerror_error_set(
1141
53
     error,
1142
53
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1143
53
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1144
53
     "%s: invalid next offset value out of bounds.",
1145
53
     function,
1146
53
     version );
1147
1148
53
    return( -1 );
1149
53
  }
1150
572
  *next_offset = (off64_t) safe_next_offset;
1151
1152
572
  return( 1 );
1153
625
}
1154