Coverage Report

Created: 2024-02-25 07:20

/src/libvshadow/libvshadow/libvshadow_volume.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Volume functions
3
 *
4
 * Copyright (C) 2011-2023, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libvshadow_debug.h"
29
#include "libvshadow_definitions.h"
30
#include "libvshadow_io_handle.h"
31
#include "libvshadow_libbfio.h"
32
#include "libvshadow_libcdata.h"
33
#include "libvshadow_libcerror.h"
34
#include "libvshadow_libcnotify.h"
35
#include "libvshadow_libcthreads.h"
36
#include "libvshadow_ntfs_volume_header.h"
37
#include "libvshadow_store.h"
38
#include "libvshadow_store_descriptor.h"
39
#include "libvshadow_volume.h"
40
41
/* Creates a volume
42
 * ake sure the value volume is referencing, is set to NULL
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libvshadow_volume_initialize(
46
     libvshadow_volume_t **volume,
47
     libcerror_error_t **error )
48
1.57k
{
49
1.57k
  libvshadow_internal_volume_t *internal_volume = NULL;
50
1.57k
  static char *function                         = "libvshadow_volume_initialize";
51
52
1.57k
  if( volume == NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58
0
     "%s: invalid volume.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
1.57k
  if( *volume != NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69
0
     "%s: invalid volume value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
1.57k
  internal_volume = memory_allocate_structure(
75
1.57k
                     libvshadow_internal_volume_t );
76
77
1.57k
  if( internal_volume == NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
82
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
83
0
     "%s: unable to create volume.",
84
0
     function );
85
86
0
    goto on_error;
87
0
  }
88
1.57k
  if( memory_set(
89
1.57k
       internal_volume,
90
1.57k
       0,
91
1.57k
       sizeof( libvshadow_internal_volume_t ) ) == NULL )
92
0
  {
93
0
    libcerror_error_set(
94
0
     error,
95
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
96
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
97
0
     "%s: unable to clear volume.",
98
0
     function );
99
100
0
    memory_free(
101
0
     internal_volume );
102
103
0
    return( -1 );
104
0
  }
105
1.57k
  if( libcdata_array_initialize(
106
1.57k
       &( internal_volume->store_descriptors_array ),
107
1.57k
       0,
108
1.57k
       error ) != 1 )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
113
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
114
0
     "%s: unable to create store descriptors array.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
1.57k
  if( libvshadow_io_handle_initialize(
120
1.57k
       &( internal_volume->io_handle ),
121
1.57k
       error ) != 1 )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
126
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
127
0
     "%s: unable to create IO handle.",
128
0
     function );
129
130
0
    goto on_error;
131
0
  }
132
1.57k
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
133
1.57k
  if( libcthreads_read_write_lock_initialize(
134
1.57k
       &( internal_volume->read_write_lock ),
135
1.57k
       error ) != 1 )
136
0
  {
137
0
    libcerror_error_set(
138
0
     error,
139
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
140
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
141
0
     "%s: unable to initialize read/write lock.",
142
0
     function );
143
144
0
    goto on_error;
145
0
  }
146
1.57k
#endif
147
1.57k
  *volume = (libvshadow_volume_t *) internal_volume;
148
149
1.57k
  return( 1 );
150
151
0
on_error:
152
0
  if( internal_volume != NULL )
153
0
  {
154
0
    if( internal_volume->store_descriptors_array != NULL )
155
0
    {
156
0
      libcdata_array_free(
157
0
       &( internal_volume->store_descriptors_array ),
158
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_store_descriptor_free,
159
0
       NULL );
160
0
    }
161
0
    memory_free(
162
0
     internal_volume );
163
0
  }
164
0
  return( -1 );
165
1.57k
}
166
167
/* Frees a volume
168
 * Returns 1 if successful or -1 on error
169
 */
170
int libvshadow_volume_free(
171
     libvshadow_volume_t **volume,
172
     libcerror_error_t **error )
173
1.57k
{
174
1.57k
  libvshadow_internal_volume_t *internal_volume = NULL;
175
1.57k
  static char *function                         = "libvshadow_volume_free";
176
1.57k
  int result                                    = 1;
177
178
1.57k
  if( volume == NULL )
179
0
  {
180
0
    libcerror_error_set(
181
0
     error,
182
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
183
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
184
0
     "%s: invalid volume.",
185
0
     function );
186
187
0
    return( -1 );
188
0
  }
189
1.57k
  if( *volume != NULL )
190
1.57k
  {
191
1.57k
    internal_volume = (libvshadow_internal_volume_t *) *volume;
192
193
1.57k
    if( internal_volume->file_io_handle != NULL )
194
0
    {
195
0
      if( libvshadow_volume_close(
196
0
           *volume,
197
0
           error ) != 0 )
198
0
      {
199
0
        libcerror_error_set(
200
0
         error,
201
0
         LIBCERROR_ERROR_DOMAIN_IO,
202
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
203
0
         "%s: unable to close volume.",
204
0
         function );
205
206
0
        result = -1;
207
0
      }
208
0
    }
209
1.57k
    *volume = NULL;
210
211
1.57k
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
212
1.57k
    if( libcthreads_read_write_lock_free(
213
1.57k
         &( internal_volume->read_write_lock ),
214
1.57k
         error ) != 1 )
215
0
    {
216
0
      libcerror_error_set(
217
0
       error,
218
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
219
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
220
0
       "%s: unable to free read/write lock.",
221
0
       function );
222
223
0
      result = -1;
224
0
    }
225
1.57k
#endif
226
1.57k
    if( libcdata_array_free(
227
1.57k
         &( internal_volume->store_descriptors_array ),
228
1.57k
         (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_store_descriptor_free,
229
1.57k
         error ) != 1 )
230
0
    {
231
0
      libcerror_error_set(
232
0
       error,
233
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
234
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
235
0
       "%s: unable to free store descriptors array.",
236
0
       function );
237
238
0
      result = -1;
239
0
    }
240
1.57k
    if( libvshadow_io_handle_free(
241
1.57k
         &( internal_volume->io_handle ),
242
1.57k
         error ) != 1 )
243
0
    {
244
0
      libcerror_error_set(
245
0
       error,
246
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
247
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
248
0
       "%s: unable to free IO handle.",
249
0
       function );
250
251
0
      result = -1;
252
0
    }
253
1.57k
    memory_free(
254
1.57k
     internal_volume );
255
1.57k
  }
256
1.57k
  return( result );
257
1.57k
}
258
259
/* Signals the volume to abort its current activity
260
 * Returns 1 if successful or -1 on error
261
 */
262
int libvshadow_volume_signal_abort(
263
     libvshadow_volume_t *volume,
264
     libcerror_error_t **error )
265
0
{
266
0
  libvshadow_internal_volume_t *internal_volume = NULL;
267
0
  static char *function                         = "libvshadow_volume_signal_abort";
268
269
0
  if( volume == NULL )
270
0
  {
271
0
    libcerror_error_set(
272
0
     error,
273
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
274
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
275
0
     "%s: invalid volume.",
276
0
     function );
277
278
0
    return( -1 );
279
0
  }
280
0
  internal_volume = (libvshadow_internal_volume_t *) volume;
281
282
0
  if( internal_volume->io_handle == NULL )
283
0
  {
284
0
    libcerror_error_set(
285
0
     error,
286
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
287
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
288
0
     "%s: invalid volume - missing IO handle.",
289
0
     function );
290
291
0
    return( -1 );
292
0
  }
293
/* TODO multi-threading ? */
294
0
  internal_volume->io_handle->abort = 1;
295
296
0
  return( 1 );
297
0
}
298
299
/* Opens a volume
300
 * Returns 1 if successful or -1 on error
301
 */
302
int libvshadow_volume_open(
303
     libvshadow_volume_t *volume,
304
     const char *filename,
305
     int access_flags,
306
     libcerror_error_t **error )
307
0
{
308
0
  libbfio_handle_t *file_io_handle              = NULL;
309
0
  libvshadow_internal_volume_t *internal_volume = NULL;
310
0
  static char *function                         = "libvshadow_volume_open";
311
312
0
  if( volume == NULL )
313
0
  {
314
0
    libcerror_error_set(
315
0
     error,
316
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
317
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
318
0
     "%s: invalid volume.",
319
0
     function );
320
321
0
    return( -1 );
322
0
  }
323
0
  internal_volume = (libvshadow_internal_volume_t *) volume;
324
325
0
  if( filename == NULL )
326
0
  {
327
0
    libcerror_error_set(
328
0
     error,
329
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
330
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
331
0
     "%s: invalid filename.",
332
0
     function );
333
334
0
    return( -1 );
335
0
  }
336
0
  if( ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_READ ) == 0 )
337
0
   && ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) == 0 ) )
338
0
  {
339
0
    libcerror_error_set(
340
0
     error,
341
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
342
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
343
0
     "%s: unsupported access flags.",
344
0
     function );
345
346
0
    return( -1 );
347
0
  }
348
0
  if( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) != 0 )
349
0
  {
350
0
    libcerror_error_set(
351
0
     error,
352
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
353
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
354
0
     "%s: write access currently not supported.",
355
0
     function );
356
357
0
    return( -1 );
358
0
  }
359
0
  if( libbfio_file_initialize(
360
0
       &file_io_handle,
361
0
       error ) != 1 )
362
0
  {
363
0
    libcerror_error_set(
364
0
     error,
365
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
366
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
367
0
     "%s: unable to create file IO handle.",
368
0
     function );
369
370
0
    goto on_error;
371
0
  }
372
#if defined( HAVE_DEBUG_OUTPUT )
373
  if( libbfio_handle_set_track_offsets_read(
374
       file_io_handle,
375
       1,
376
       error ) != 1 )
377
  {
378
    libcerror_error_set(
379
     error,
380
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
381
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
382
     "%s: unable to set track offsets read in file IO handle.",
383
     function );
384
385
    goto on_error;
386
  }
387
#endif
388
0
  if( libbfio_file_set_name(
389
0
       file_io_handle,
390
0
       filename,
391
0
       narrow_string_length(
392
0
        filename ) + 1,
393
0
       error ) != 1 )
394
0
  {
395
0
     libcerror_error_set(
396
0
      error,
397
0
      LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
0
      LIBCERROR_RUNTIME_ERROR_SET_FAILED,
399
0
      "%s: unable to set filename in file IO handle.",
400
0
      function );
401
402
0
    goto on_error;
403
0
  }
404
0
  if( libvshadow_volume_open_file_io_handle(
405
0
       volume,
406
0
       file_io_handle,
407
0
       access_flags,
408
0
       error ) != 1 )
409
0
  {
410
0
    libcerror_error_set(
411
0
     error,
412
0
     LIBCERROR_ERROR_DOMAIN_IO,
413
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
414
0
     "%s: unable to open volume: %s.",
415
0
     function,
416
0
     filename );
417
418
0
    goto on_error;
419
0
  }
420
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
421
0
  if( libcthreads_read_write_lock_grab_for_write(
422
0
       internal_volume->read_write_lock,
423
0
       error ) != 1 )
424
0
  {
425
0
    libcerror_error_set(
426
0
     error,
427
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
428
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
429
0
     "%s: unable to grab read/write lock for writing.",
430
0
     function );
431
432
0
    return( -1 );
433
0
  }
434
0
#endif
435
0
  internal_volume->file_io_handle_created_in_library = 1;
436
437
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
438
0
  if( libcthreads_read_write_lock_release_for_write(
439
0
       internal_volume->read_write_lock,
440
0
       error ) != 1 )
441
0
  {
442
0
    libcerror_error_set(
443
0
     error,
444
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
445
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
446
0
     "%s: unable to release read/write lock for writing.",
447
0
     function );
448
449
0
    return( -1 );
450
0
  }
451
0
#endif
452
0
  return( 1 );
453
454
0
on_error:
455
0
  if( file_io_handle != NULL )
456
0
  {
457
0
    libbfio_handle_free(
458
0
     &file_io_handle,
459
0
     NULL );
460
0
  }
461
0
  return( -1 );
462
0
}
463
464
#if defined( HAVE_WIDE_CHARACTER_TYPE )
465
466
/* Opens a volume
467
 * Returns 1 if successful or -1 on error
468
 */
469
int libvshadow_volume_open_wide(
470
     libvshadow_volume_t *volume,
471
     const wchar_t *filename,
472
     int access_flags,
473
     libcerror_error_t **error )
474
{
475
  libbfio_handle_t *file_io_handle              = NULL;
476
  libvshadow_internal_volume_t *internal_volume = NULL;
477
  static char *function                         = "libvshadow_volume_open_wide";
478
479
  if( volume == NULL )
480
  {
481
    libcerror_error_set(
482
     error,
483
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
484
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
485
     "%s: invalid volume.",
486
     function );
487
488
    return( -1 );
489
  }
490
  internal_volume = (libvshadow_internal_volume_t *) volume;
491
492
  if( filename == NULL )
493
  {
494
    libcerror_error_set(
495
     error,
496
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
497
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
498
     "%s: invalid filename.",
499
     function );
500
501
    return( -1 );
502
  }
503
  if( ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_READ ) == 0 )
504
   && ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) == 0 ) )
505
  {
506
    libcerror_error_set(
507
     error,
508
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
509
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
510
     "%s: unsupported access flags.",
511
     function );
512
513
    return( -1 );
514
  }
515
  if( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) != 0 )
516
  {
517
    libcerror_error_set(
518
     error,
519
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
520
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
521
     "%s: write access currently not supported.",
522
     function );
523
524
    return( -1 );
525
  }
526
  if( libbfio_file_initialize(
527
       &file_io_handle,
528
       error ) != 1 )
529
  {
530
    libcerror_error_set(
531
     error,
532
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
533
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
534
     "%s: unable to create file IO handle.",
535
     function );
536
537
    goto on_error;
538
  }
539
#if defined( HAVE_DEBUG_OUTPUT )
540
  if( libbfio_handle_set_track_offsets_read(
541
       file_io_handle,
542
       1,
543
       error ) != 1 )
544
  {
545
    libcerror_error_set(
546
     error,
547
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
548
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
549
     "%s: unable to set track offsets read in file IO handle.",
550
     function );
551
552
    goto on_error;
553
  }
554
#endif
555
  if( libbfio_file_set_name_wide(
556
       file_io_handle,
557
       filename,
558
       wide_string_length(
559
        filename ) + 1,
560
       error ) != 1 )
561
  {
562
     libcerror_error_set(
563
      error,
564
      LIBCERROR_ERROR_DOMAIN_RUNTIME,
565
      LIBCERROR_RUNTIME_ERROR_SET_FAILED,
566
      "%s: unable to set filename in file IO handle.",
567
      function );
568
569
    goto on_error;
570
  }
571
  if( libvshadow_volume_open_file_io_handle(
572
       volume,
573
       file_io_handle,
574
       access_flags,
575
       error ) != 1 )
576
  {
577
    libcerror_error_set(
578
     error,
579
     LIBCERROR_ERROR_DOMAIN_IO,
580
     LIBCERROR_IO_ERROR_OPEN_FAILED,
581
     "%s: unable to open volume: %ls.",
582
     function,
583
     filename );
584
585
    goto on_error;
586
  }
587
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
588
  if( libcthreads_read_write_lock_grab_for_write(
589
       internal_volume->read_write_lock,
590
       error ) != 1 )
591
  {
592
    libcerror_error_set(
593
     error,
594
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
595
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
596
     "%s: unable to grab read/write lock for writing.",
597
     function );
598
599
    return( -1 );
600
  }
601
#endif
602
  internal_volume->file_io_handle_created_in_library = 1;
603
604
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
605
  if( libcthreads_read_write_lock_release_for_write(
606
       internal_volume->read_write_lock,
607
       error ) != 1 )
608
  {
609
    libcerror_error_set(
610
     error,
611
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
612
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
613
     "%s: unable to release read/write lock for writing.",
614
     function );
615
616
    return( -1 );
617
  }
618
#endif
619
  return( 1 );
620
621
on_error:
622
  if( file_io_handle != NULL )
623
  {
624
    libbfio_handle_free(
625
     &file_io_handle,
626
     NULL );
627
  }
628
  return( -1 );
629
}
630
631
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
632
633
/* Opens a volume using a Basic File IO (bfio) handle
634
 * Returns 1 if successful or -1 on error
635
 */
636
int libvshadow_volume_open_file_io_handle(
637
     libvshadow_volume_t *volume,
638
     libbfio_handle_t *file_io_handle,
639
     int access_flags,
640
     libcerror_error_t **error )
641
1.57k
{
642
1.57k
  libvshadow_internal_volume_t *internal_volume = NULL;
643
1.57k
  static char *function                         = "libvshadow_volume_open_file_io_handle";
644
1.57k
  uint8_t file_io_handle_opened_in_library      = 0;
645
1.57k
  int bfio_access_flags                         = 0;
646
1.57k
  int file_io_handle_is_open                    = 0;
647
648
1.57k
  if( volume == NULL )
649
0
  {
650
0
    libcerror_error_set(
651
0
     error,
652
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
653
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
654
0
     "%s: invalid volume.",
655
0
     function );
656
657
0
    return( -1 );
658
0
  }
659
1.57k
  internal_volume = (libvshadow_internal_volume_t *) volume;
660
661
1.57k
  if( file_io_handle == NULL )
662
0
  {
663
0
    libcerror_error_set(
664
0
     error,
665
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
666
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
667
0
     "%s: invalid file IO handle.",
668
0
     function );
669
670
0
    return( -1 );
671
0
  }
672
1.57k
  if( ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_READ ) == 0 )
673
1.57k
   && ( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) == 0 ) )
674
0
  {
675
0
    libcerror_error_set(
676
0
     error,
677
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
678
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
679
0
     "%s: unsupported access flags.",
680
0
     function );
681
682
0
    return( -1 );
683
0
  }
684
1.57k
  if( ( access_flags & LIBVSHADOW_ACCESS_FLAG_WRITE ) != 0 )
685
0
  {
686
0
    libcerror_error_set(
687
0
     error,
688
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
689
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
690
0
     "%s: write access currently not supported.",
691
0
     function );
692
693
0
    return( -1 );
694
0
  }
695
1.57k
  if( ( access_flags & LIBVSHADOW_ACCESS_FLAG_READ ) != 0 )
696
1.57k
  {
697
1.57k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
698
1.57k
  }
699
1.57k
  file_io_handle_is_open = libbfio_handle_is_open(
700
1.57k
                            file_io_handle,
701
1.57k
                            error );
702
703
1.57k
  if( file_io_handle_is_open == -1 )
704
0
  {
705
0
    libcerror_error_set(
706
0
     error,
707
0
     LIBCERROR_ERROR_DOMAIN_IO,
708
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
709
0
     "%s: unable to determine if file IO handle is open.",
710
0
     function );
711
712
0
    goto on_error;
713
0
  }
714
1.57k
  else if( file_io_handle_is_open == 0 )
715
1.57k
  {
716
1.57k
    if( libbfio_handle_open(
717
1.57k
         file_io_handle,
718
1.57k
         bfio_access_flags,
719
1.57k
         error ) != 1 )
720
0
    {
721
0
      libcerror_error_set(
722
0
       error,
723
0
       LIBCERROR_ERROR_DOMAIN_IO,
724
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
725
0
       "%s: unable to open file IO handle.",
726
0
       function );
727
728
0
      goto on_error;
729
0
    }
730
1.57k
    file_io_handle_opened_in_library = 1;
731
1.57k
  }
732
1.57k
  if( libvshadow_volume_open_read(
733
1.57k
       internal_volume,
734
1.57k
       file_io_handle,
735
1.57k
       error ) != 1 )
736
1.50k
  {
737
1.50k
    libcerror_error_set(
738
1.50k
     error,
739
1.50k
     LIBCERROR_ERROR_DOMAIN_IO,
740
1.50k
     LIBCERROR_IO_ERROR_READ_FAILED,
741
1.50k
     "%s: unable to read from file IO handle.",
742
1.50k
     function );
743
744
1.50k
    goto on_error;
745
1.50k
  }
746
70
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
747
70
  if( libcthreads_read_write_lock_grab_for_write(
748
70
       internal_volume->read_write_lock,
749
70
       error ) != 1 )
750
0
  {
751
0
    libcerror_error_set(
752
0
     error,
753
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
754
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
755
0
     "%s: unable to grab read/write lock for writing.",
756
0
     function );
757
758
0
    return( -1 );
759
0
  }
760
70
#endif
761
70
  internal_volume->file_io_handle                   = file_io_handle;
762
70
  internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
763
764
70
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
765
70
  if( libcthreads_read_write_lock_release_for_write(
766
70
       internal_volume->read_write_lock,
767
70
       error ) != 1 )
768
0
  {
769
0
    libcerror_error_set(
770
0
     error,
771
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
772
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
773
0
     "%s: unable to release read/write lock for writing.",
774
0
     function );
775
776
0
    return( -1 );
777
0
  }
778
70
#endif
779
70
  return( 1 );
780
781
1.50k
on_error:
782
1.50k
  if( file_io_handle_opened_in_library != 0 )
783
1.50k
  {
784
1.50k
    libbfio_handle_close(
785
1.50k
     file_io_handle,
786
1.50k
     NULL );
787
1.50k
  }
788
1.50k
  return( -1 );
789
70
}
790
791
/* Closes a volume
792
 * Returns 0 if successful or -1 on error
793
 */
794
int libvshadow_volume_close(
795
     libvshadow_volume_t *volume,
796
     libcerror_error_t **error )
797
70
{
798
70
  libvshadow_internal_volume_t *internal_volume = NULL;
799
70
  static char *function                         = "libvshadow_volume_close";
800
70
  int result                                    = 0;
801
802
70
  if( volume == NULL )
803
0
  {
804
0
    libcerror_error_set(
805
0
     error,
806
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
807
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
808
0
     "%s: invalid volume.",
809
0
     function );
810
811
0
    return( -1 );
812
0
  }
813
70
  internal_volume = (libvshadow_internal_volume_t *) volume;
814
815
70
  if( internal_volume->file_io_handle == NULL )
816
0
  {
817
0
    libcerror_error_set(
818
0
     error,
819
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
820
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
821
0
     "%s: invalid volume - missing file IO handle.",
822
0
     function );
823
824
0
    return( -1 );
825
0
  }
826
70
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
827
70
  if( libcthreads_read_write_lock_grab_for_write(
828
70
       internal_volume->read_write_lock,
829
70
       error ) != 1 )
830
0
  {
831
0
    libcerror_error_set(
832
0
     error,
833
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
834
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
835
0
     "%s: unable to grab read/write lock for writing.",
836
0
     function );
837
838
0
    return( -1 );
839
0
  }
840
70
#endif
841
#if defined( HAVE_DEBUG_OUTPUT )
842
  if( libcnotify_verbose != 0 )
843
  {
844
    if( internal_volume->file_io_handle_created_in_library != 0 )
845
    {
846
      if( libvshadow_debug_print_read_offsets(
847
           internal_volume->file_io_handle,
848
           error ) != 1 )
849
      {
850
        libcerror_error_set(
851
         error,
852
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
853
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
854
         "%s: unable to print the read offsets.",
855
         function );
856
      }
857
    }
858
  }
859
#endif
860
70
  if( internal_volume->file_io_handle_opened_in_library != 0 )
861
70
  {
862
70
    if( libbfio_handle_close(
863
70
         internal_volume->file_io_handle,
864
70
         error ) != 0 )
865
0
    {
866
0
      libcerror_error_set(
867
0
       error,
868
0
       LIBCERROR_ERROR_DOMAIN_IO,
869
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
870
0
       "%s: unable to close file IO handle.",
871
0
       function );
872
873
0
      result = -1;
874
0
    }
875
70
    internal_volume->file_io_handle_opened_in_library = 0;
876
70
  }
877
70
  if( internal_volume->file_io_handle_created_in_library != 0 )
878
0
  {
879
0
    if( libbfio_handle_free(
880
0
         &( internal_volume->file_io_handle ),
881
0
         error ) != 1 )
882
0
    {
883
0
      libcerror_error_set(
884
0
       error,
885
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
886
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
887
0
       "%s: unable to free file IO handle.",
888
0
       function );
889
890
0
      result = -1;
891
0
    }
892
0
    internal_volume->file_io_handle_created_in_library = 0;
893
0
  }
894
70
  internal_volume->file_io_handle = NULL;
895
70
  internal_volume->size           = 0;
896
897
70
  if( libvshadow_io_handle_clear(
898
70
       internal_volume->io_handle,
899
70
       error ) != 1 )
900
0
  {
901
0
    libcerror_error_set(
902
0
     error,
903
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
904
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
905
0
     "%s: unable to clear IO handle.",
906
0
     function );
907
908
0
    result = -1;
909
0
  }
910
70
  if( libcdata_array_empty(
911
70
       internal_volume->store_descriptors_array,
912
70
       (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_store_descriptor_free,
913
70
       error ) != 1 )
914
0
  {
915
0
    libcerror_error_set(
916
0
     error,
917
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
918
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
919
0
     "%s: unable to empty store descriptors array.",
920
0
     function );
921
922
0
    result = -1;
923
0
  }
924
70
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
925
70
  if( libcthreads_read_write_lock_release_for_write(
926
70
       internal_volume->read_write_lock,
927
70
       error ) != 1 )
928
0
  {
929
0
    libcerror_error_set(
930
0
     error,
931
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
932
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
933
0
     "%s: unable to release read/write lock for writing.",
934
0
     function );
935
936
0
    return( -1 );
937
0
  }
938
70
#endif
939
70
  return( result );
940
70
}
941
942
/* Opens a volume for reading
943
 * Returns 1 if successful or -1 on error
944
 */
945
int libvshadow_volume_open_read(
946
     libvshadow_internal_volume_t *internal_volume,
947
     libbfio_handle_t *file_io_handle,
948
     libcerror_error_t **error )
949
1.57k
{
950
1.57k
  libvshadow_store_descriptor_t *last_store_descriptor = NULL;
951
1.57k
  libvshadow_store_descriptor_t *store_descriptor      = NULL;
952
1.57k
  static char *function                                = "libvshadow_volume_open_read";
953
1.57k
  off64_t catalog_offset                               = 0;
954
1.57k
  int number_of_store_descriptors                      = 0;
955
1.57k
  int store_descriptor_index                           = 0;
956
957
1.57k
  if( internal_volume == NULL )
958
0
  {
959
0
    libcerror_error_set(
960
0
     error,
961
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
962
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
963
0
     "%s: invalid volume.",
964
0
     function );
965
966
0
    return( -1 );
967
0
  }
968
1.57k
  if( internal_volume->io_handle == NULL )
969
0
  {
970
0
    libcerror_error_set(
971
0
     error,
972
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
973
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
974
0
     "%s: invalid volume - missing IO handle.",
975
0
     function );
976
977
0
    return( -1 );
978
0
  }
979
1.57k
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
980
1.57k
  if( libcthreads_read_write_lock_grab_for_write(
981
1.57k
       internal_volume->read_write_lock,
982
1.57k
       error ) != 1 )
983
0
  {
984
0
    libcerror_error_set(
985
0
     error,
986
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
987
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
988
0
     "%s: unable to grab read/write lock for writing.",
989
0
     function );
990
991
0
    return( -1 );
992
0
  }
993
1.57k
#endif
994
1.57k
  if( libbfio_handle_get_size(
995
1.57k
       file_io_handle,
996
1.57k
       &( internal_volume->io_handle->volume_size ),
997
1.57k
       error ) != 1 )
998
0
  {
999
0
    libcerror_error_set(
1000
0
     error,
1001
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1002
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1003
0
     "%s: unable to retrieve file size.",
1004
0
     function );
1005
1006
0
    goto on_error;
1007
0
  }
1008
#if defined( HAVE_DEBUG_OUTPUT )
1009
  if( libcnotify_verbose != 0 )
1010
  {
1011
    libcnotify_printf(
1012
     "Reading NTFS volume headers:\n" );
1013
  }
1014
#endif
1015
1.57k
  if( libvshadow_volume_open_read_ntfs_volume_headers(
1016
1.57k
       internal_volume,
1017
1.57k
       file_io_handle,
1018
1.57k
       error ) == -1 )
1019
586
  {
1020
586
    libcerror_error_set(
1021
586
     error,
1022
586
     LIBCERROR_ERROR_DOMAIN_IO,
1023
586
     LIBCERROR_IO_ERROR_READ_FAILED,
1024
586
     "%s: unable to read NTFS volume headers.",
1025
586
     function );
1026
1027
586
    goto on_error;
1028
586
  }
1029
#if defined( HAVE_DEBUG_OUTPUT )
1030
  if( libcnotify_verbose != 0 )
1031
  {
1032
    libcnotify_printf(
1033
     "Reading VSS volume header:\n" );
1034
  }
1035
#endif
1036
993
  if( libvshadow_io_handle_read_volume_header(
1037
993
       internal_volume->io_handle,
1038
993
       file_io_handle,
1039
993
       (off64_t) 0x1e00,
1040
993
       &catalog_offset,
1041
993
       error ) != 1 )
1042
122
  {
1043
122
    libcerror_error_set(
1044
122
     error,
1045
122
     LIBCERROR_ERROR_DOMAIN_IO,
1046
122
     LIBCERROR_IO_ERROR_READ_FAILED,
1047
122
     "%s: unable to read volume header.",
1048
122
     function );
1049
1050
122
    goto on_error;
1051
122
  }
1052
871
  if( catalog_offset > 0 )
1053
807
  {
1054
#if defined( HAVE_DEBUG_OUTPUT )
1055
    if( libcnotify_verbose != 0 )
1056
    {
1057
      libcnotify_printf(
1058
       "Reading VSS catalog:\n" );
1059
    }
1060
#endif
1061
807
    if( libvshadow_io_handle_read_catalog(
1062
807
         internal_volume->io_handle,
1063
807
         file_io_handle,
1064
807
         catalog_offset,
1065
807
         &( internal_volume->size ),
1066
807
         internal_volume->store_descriptors_array,
1067
807
         error ) != 1 )
1068
673
    {
1069
673
      libcerror_error_set(
1070
673
       error,
1071
673
       LIBCERROR_ERROR_DOMAIN_IO,
1072
673
       LIBCERROR_IO_ERROR_READ_FAILED,
1073
673
       "%s: unable to read catalog.",
1074
673
       function );
1075
1076
673
      goto on_error;
1077
673
    }
1078
134
    if( libcdata_array_get_number_of_entries(
1079
134
         internal_volume->store_descriptors_array,
1080
134
         &number_of_store_descriptors,
1081
134
         error ) != 1 )
1082
0
    {
1083
0
      libcerror_error_set(
1084
0
       error,
1085
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1086
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1087
0
       "%s: unable to retrieve number of store descriptors from array.",
1088
0
       function );
1089
1090
0
      goto on_error;
1091
0
    }
1092
134
    for( store_descriptor_index = 0;
1093
677
         store_descriptor_index < number_of_store_descriptors;
1094
543
         store_descriptor_index++ )
1095
671
    {
1096
671
      if( libcdata_array_get_entry_by_index(
1097
671
           internal_volume->store_descriptors_array,
1098
671
           store_descriptor_index,
1099
671
           (intptr_t **) &store_descriptor,
1100
671
           error ) != 1 )
1101
0
      {
1102
0
        libcerror_error_set(
1103
0
         error,
1104
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1105
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1106
0
         "%s: unable to retrieve store descriptor: %d.",
1107
0
         function,
1108
0
         store_descriptor_index );
1109
1110
0
        goto on_error;
1111
0
      }
1112
671
      if( store_descriptor == NULL )
1113
0
      {
1114
0
        libcerror_error_set(
1115
0
         error,
1116
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1117
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1118
0
         "%s: invalid store descriptor: %d.",
1119
0
         function,
1120
0
         store_descriptor_index );
1121
1122
0
        goto on_error;
1123
0
      }
1124
671
      store_descriptor->index = store_descriptor_index;
1125
1126
671
      if( store_descriptor->has_in_volume_store_data != 0 )
1127
212
      {
1128
#if defined( HAVE_DEBUG_OUTPUT )
1129
        if( libcnotify_verbose != 0 )
1130
        {
1131
          libcnotify_printf(
1132
           "Reading VSS store: %02d:\n",
1133
           store_descriptor->index );
1134
        }
1135
#endif
1136
212
        if( libvshadow_store_descriptor_read_store_header(
1137
212
             store_descriptor,
1138
212
             file_io_handle,
1139
212
             error ) != 1 )
1140
128
        {
1141
128
          libcerror_error_set(
1142
128
           error,
1143
128
           LIBCERROR_ERROR_DOMAIN_IO,
1144
128
           LIBCERROR_IO_ERROR_READ_FAILED,
1145
128
           "%s: unable to read store: %d header.",
1146
128
           function,
1147
128
           store_descriptor->index );
1148
1149
128
          goto on_error;
1150
128
        }
1151
212
      }
1152
543
      store_descriptor->previous_store_descriptor = last_store_descriptor;
1153
1154
543
      if( last_store_descriptor != NULL )
1155
447
      {
1156
447
        last_store_descriptor->next_store_descriptor = store_descriptor;
1157
447
      }
1158
543
      last_store_descriptor = store_descriptor;
1159
1160
543
      store_descriptor = NULL;
1161
543
    }
1162
134
  }
1163
70
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1164
70
  if( libcthreads_read_write_lock_release_for_write(
1165
70
       internal_volume->read_write_lock,
1166
70
       error ) != 1 )
1167
0
  {
1168
0
    libcerror_error_set(
1169
0
     error,
1170
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1171
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1172
0
     "%s: unable to release read/write lock for writing.",
1173
0
     function );
1174
1175
0
    return( -1 );
1176
0
  }
1177
70
#endif
1178
70
  return( 1 );
1179
1180
1.50k
on_error:
1181
1.50k
  internal_volume->size = 0;
1182
1183
1.50k
  libcdata_array_empty(
1184
1.50k
   internal_volume->store_descriptors_array,
1185
1.50k
   (int (*)(intptr_t **, libcerror_error_t **)) &libvshadow_store_descriptor_free,
1186
1.50k
   NULL );
1187
1188
1.50k
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1189
1.50k
  libcthreads_read_write_lock_release_for_write(
1190
1.50k
   internal_volume->read_write_lock,
1191
1.50k
   NULL );
1192
1.50k
#endif
1193
1.50k
  return( -1 );
1194
70
}
1195
1196
/* Reads the NTFS volume headers to determine the volume size
1197
 * Returns 1 if successful or -1 on error
1198
 */
1199
int libvshadow_volume_open_read_ntfs_volume_headers(
1200
     libvshadow_internal_volume_t *internal_volume,
1201
     libbfio_handle_t *file_io_handle,
1202
     libcerror_error_t **error )
1203
1.57k
{
1204
1.57k
  libvshadow_ntfs_volume_header_t *backup_ntfs_volume_header = NULL;
1205
1.57k
  libvshadow_ntfs_volume_header_t *ntfs_volume_header        = NULL;
1206
1.57k
  static char *function                                      = "libvshadow_volume_open_read_ntfs_volume_headers";
1207
1.57k
  off64_t backup_ntfs_volume_header_offset                   = 0;
1208
1209
1.57k
  if( internal_volume == NULL )
1210
0
  {
1211
0
    libcerror_error_set(
1212
0
     error,
1213
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1214
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1215
0
     "%s: invalid volume.",
1216
0
     function );
1217
1218
0
    return( -1 );
1219
0
  }
1220
1.57k
  if( libvshadow_ntfs_volume_header_initialize(
1221
1.57k
       &ntfs_volume_header,
1222
1.57k
       error ) != 1 )
1223
0
  {
1224
0
    libcerror_error_set(
1225
0
     error,
1226
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1227
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1228
0
     "%s: unable to create NTFS volume header.",
1229
0
     function );
1230
1231
0
    goto on_error;
1232
0
  }
1233
1.57k
  if( libvshadow_ntfs_volume_header_read_file_io_handle(
1234
1.57k
       ntfs_volume_header,
1235
1.57k
       file_io_handle,
1236
1.57k
       0,
1237
1.57k
       error ) == -1 )
1238
380
  {
1239
380
    libcerror_error_set(
1240
380
     error,
1241
380
     LIBCERROR_ERROR_DOMAIN_IO,
1242
380
     LIBCERROR_IO_ERROR_READ_FAILED,
1243
380
     "%s: unable to read NTFS volume header.",
1244
380
     function );
1245
1246
380
    goto on_error;
1247
380
  }
1248
1.19k
  if( libvshadow_ntfs_volume_header_initialize(
1249
1.19k
       &backup_ntfs_volume_header,
1250
1.19k
       error ) != 1 )
1251
0
  {
1252
0
    libcerror_error_set(
1253
0
     error,
1254
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1255
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1256
0
     "%s: unable to create backup NTFS volume header.",
1257
0
     function );
1258
1259
0
    goto on_error;
1260
0
  }
1261
1.19k
  backup_ntfs_volume_header_offset = ntfs_volume_header->volume_size - ntfs_volume_header->bytes_per_sector;
1262
1263
1.19k
  if( libvshadow_ntfs_volume_header_read_file_io_handle(
1264
1.19k
       backup_ntfs_volume_header,
1265
1.19k
       file_io_handle,
1266
1.19k
       backup_ntfs_volume_header_offset,
1267
1.19k
       error ) == -1 )
1268
133
  {
1269
133
    libcerror_error_set(
1270
133
     error,
1271
133
     LIBCERROR_ERROR_DOMAIN_IO,
1272
133
     LIBCERROR_IO_ERROR_READ_FAILED,
1273
133
     "%s: unable to read backup NTFS volume header.",
1274
133
     function );
1275
1276
133
    goto on_error;
1277
133
  }
1278
1.06k
  if( ntfs_volume_header->volume_size != backup_ntfs_volume_header->volume_size )
1279
73
  {
1280
73
    libcerror_error_set(
1281
73
     error,
1282
73
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1283
73
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1284
73
     "%s: mismatch of volume size between NTFS volume header and backup.",
1285
73
     function );
1286
1287
73
    goto on_error;
1288
73
  }
1289
993
  internal_volume->size = ntfs_volume_header->volume_size;
1290
1291
993
  if( libvshadow_ntfs_volume_header_free(
1292
993
       &backup_ntfs_volume_header,
1293
993
       error ) != 1 )
1294
0
  {
1295
0
    libcerror_error_set(
1296
0
     error,
1297
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1298
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1299
0
     "%s: unable to free NTFS volume header.",
1300
0
     function );
1301
1302
0
    goto on_error;
1303
0
  }
1304
993
  if( libvshadow_ntfs_volume_header_free(
1305
993
       &ntfs_volume_header,
1306
993
       error ) != 1 )
1307
0
  {
1308
0
    libcerror_error_set(
1309
0
     error,
1310
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1311
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1312
0
     "%s: unable to free NTFS volume header.",
1313
0
     function );
1314
1315
0
    goto on_error;
1316
0
  }
1317
993
  return( 1 );
1318
1319
586
on_error:
1320
586
  if( backup_ntfs_volume_header != NULL )
1321
206
  {
1322
206
    libvshadow_ntfs_volume_header_free(
1323
206
     &backup_ntfs_volume_header,
1324
206
     NULL );
1325
206
  }
1326
586
  if( ntfs_volume_header != NULL )
1327
586
  {
1328
586
    libvshadow_ntfs_volume_header_free(
1329
586
     &ntfs_volume_header,
1330
586
     NULL );
1331
586
  }
1332
586
  return( -1 );
1333
993
}
1334
1335
/* Retrieves the size
1336
 * Returns 1 if successful or -1 on error
1337
 */
1338
int libvshadow_volume_get_size(
1339
     libvshadow_volume_t *volume,
1340
     size64_t *size,
1341
     libcerror_error_t **error )
1342
0
{
1343
0
  libvshadow_internal_volume_t *internal_volume = NULL;
1344
0
  static char *function                         = "libvshadow_volume_get_size";
1345
1346
0
  if( volume == NULL )
1347
0
  {
1348
0
    libcerror_error_set(
1349
0
     error,
1350
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1351
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1352
0
     "%s: invalid volume.",
1353
0
     function );
1354
1355
0
    return( -1 );
1356
0
  }
1357
0
  internal_volume = (libvshadow_internal_volume_t *) volume;
1358
1359
0
  if( size == NULL )
1360
0
  {
1361
0
    libcerror_error_set(
1362
0
     error,
1363
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1364
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1365
0
     "%s: invalid size.",
1366
0
     function );
1367
1368
0
    return( -1 );
1369
0
  }
1370
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1371
0
  if( libcthreads_read_write_lock_grab_for_read(
1372
0
       internal_volume->read_write_lock,
1373
0
       error ) != 1 )
1374
0
  {
1375
0
    libcerror_error_set(
1376
0
     error,
1377
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1378
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1379
0
     "%s: unable to grab read/write lock for reading.",
1380
0
     function );
1381
1382
0
    return( -1 );
1383
0
  }
1384
0
#endif
1385
0
  *size = internal_volume->size;
1386
1387
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1388
0
  if( libcthreads_read_write_lock_release_for_read(
1389
0
       internal_volume->read_write_lock,
1390
0
       error ) != 1 )
1391
0
  {
1392
0
    libcerror_error_set(
1393
0
     error,
1394
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1395
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1396
0
     "%s: unable to release read/write lock for reading.",
1397
0
     function );
1398
1399
0
    return( -1 );
1400
0
  }
1401
0
#endif
1402
0
  return( 1 );
1403
0
}
1404
1405
/* Retrieves the number of stores
1406
 * Returns 1 if successful or -1 on error
1407
 */
1408
int libvshadow_volume_get_number_of_stores(
1409
     libvshadow_volume_t *volume,
1410
     int *number_of_stores,
1411
     libcerror_error_t **error )
1412
0
{
1413
0
  libvshadow_internal_volume_t *internal_volume = NULL;
1414
0
  static char *function                         = "libvshadow_volume_get_number_of_stores";
1415
0
  int result                                    = 1;
1416
1417
0
  if( volume == NULL )
1418
0
  {
1419
0
    libcerror_error_set(
1420
0
     error,
1421
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1422
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1423
0
     "%s: invalid volume.",
1424
0
     function );
1425
1426
0
    return( -1 );
1427
0
  }
1428
0
  internal_volume = (libvshadow_internal_volume_t *) volume;
1429
1430
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1431
0
  if( libcthreads_read_write_lock_grab_for_read(
1432
0
       internal_volume->read_write_lock,
1433
0
       error ) != 1 )
1434
0
  {
1435
0
    libcerror_error_set(
1436
0
     error,
1437
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1438
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1439
0
     "%s: unable to grab read/write lock for reading.",
1440
0
     function );
1441
1442
0
    return( -1 );
1443
0
  }
1444
0
#endif
1445
0
  if( libcdata_array_get_number_of_entries(
1446
0
       internal_volume->store_descriptors_array,
1447
0
       number_of_stores,
1448
0
       error ) != 1 )
1449
0
  {
1450
0
    libcerror_error_set(
1451
0
     error,
1452
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1453
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1454
0
     "%s: unable to retrieve number of store descriptors.",
1455
0
     function );
1456
1457
0
    result = -1;
1458
0
  }
1459
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1460
0
  if( libcthreads_read_write_lock_release_for_read(
1461
0
       internal_volume->read_write_lock,
1462
0
       error ) != 1 )
1463
0
  {
1464
0
    libcerror_error_set(
1465
0
     error,
1466
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1467
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1468
0
     "%s: unable to release read/write lock for reading.",
1469
0
     function );
1470
1471
0
    return( -1 );
1472
0
  }
1473
0
#endif
1474
0
  return( result );
1475
0
}
1476
1477
/* Retrieves a specific store
1478
 * Returns 1 if successful or -1 on error
1479
 */
1480
int libvshadow_volume_get_store(
1481
     libvshadow_volume_t *volume,
1482
     int store_index,
1483
     libvshadow_store_t **store,
1484
     libcerror_error_t **error )
1485
0
{
1486
0
  libvshadow_internal_volume_t *internal_volume = NULL;
1487
0
  static char *function                         = "libvshadow_volume_get_store";
1488
0
  int result                                    = 1;
1489
1490
0
  if( volume == NULL )
1491
0
  {
1492
0
    libcerror_error_set(
1493
0
     error,
1494
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1495
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1496
0
     "%s: invalid volume.",
1497
0
     function );
1498
1499
0
    return( -1 );
1500
0
  }
1501
0
  internal_volume = (libvshadow_internal_volume_t *) volume;
1502
1503
0
  if( store == NULL )
1504
0
  {
1505
0
    libcerror_error_set(
1506
0
     error,
1507
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1508
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1509
0
     "%s: invalid store.",
1510
0
     function );
1511
1512
0
    return( -1 );
1513
0
  }
1514
0
  if( *store != NULL )
1515
0
  {
1516
0
    libcerror_error_set(
1517
0
     error,
1518
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1519
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1520
0
     "%s: invalid store value already set.",
1521
0
     function );
1522
1523
0
    return( -1 );
1524
0
  }
1525
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1526
0
  if( libcthreads_read_write_lock_grab_for_read(
1527
0
       internal_volume->read_write_lock,
1528
0
       error ) != 1 )
1529
0
  {
1530
0
    libcerror_error_set(
1531
0
     error,
1532
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1533
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1534
0
     "%s: unable to grab read/write lock for reading.",
1535
0
     function );
1536
1537
0
    return( -1 );
1538
0
  }
1539
0
#endif
1540
0
  if( libvshadow_store_initialize(
1541
0
       store,
1542
0
       internal_volume->io_handle,
1543
0
       internal_volume->file_io_handle,
1544
0
       internal_volume,
1545
0
       store_index,
1546
0
       error ) != 1 )
1547
0
  {
1548
0
    libcerror_error_set(
1549
0
     error,
1550
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1551
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1552
0
     "%s: unable to create store: %d.",
1553
0
     function,
1554
0
     store_index );
1555
1556
0
    result = -1;
1557
0
  }
1558
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1559
0
  if( libcthreads_read_write_lock_release_for_read(
1560
0
       internal_volume->read_write_lock,
1561
0
       error ) != 1 )
1562
0
  {
1563
0
    libcerror_error_set(
1564
0
     error,
1565
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1566
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1567
0
     "%s: unable to release read/write lock for reading.",
1568
0
     function );
1569
1570
0
    return( -1 );
1571
0
  }
1572
0
#endif
1573
0
  return( result );
1574
0
}
1575
1576
/* Retrieves a specific store identifier
1577
 * Returns 1 if successful or -1 on error
1578
 */
1579
int libvshadow_volume_get_store_identifier(
1580
     libvshadow_volume_t *volume,
1581
     int store_index,
1582
     uint8_t *guid,
1583
     size_t size,
1584
     libcerror_error_t **error )
1585
0
{
1586
0
  libvshadow_internal_volume_t *internal_volume   = NULL;
1587
0
  libvshadow_store_descriptor_t *store_descriptor = NULL;
1588
0
  static char *function                           = "libvshadow_volume_get_store_identifier";
1589
1590
0
  if( volume == NULL )
1591
0
  {
1592
0
    libcerror_error_set(
1593
0
     error,
1594
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1595
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1596
0
     "%s: invalid volume.",
1597
0
     function );
1598
1599
0
    return( -1 );
1600
0
  }
1601
0
  internal_volume = (libvshadow_internal_volume_t *) volume;
1602
1603
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1604
0
  if( libcthreads_read_write_lock_grab_for_read(
1605
0
       internal_volume->read_write_lock,
1606
0
       error ) != 1 )
1607
0
  {
1608
0
    libcerror_error_set(
1609
0
     error,
1610
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1611
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1612
0
     "%s: unable to grab read/write lock for reading.",
1613
0
     function );
1614
1615
0
    return( -1 );
1616
0
  }
1617
0
#endif
1618
0
  if( libcdata_array_get_entry_by_index(
1619
0
       internal_volume->store_descriptors_array,
1620
0
       store_index,
1621
0
       (intptr_t **) &store_descriptor,
1622
0
       error ) != 1 )
1623
0
  {
1624
0
    libcerror_error_set(
1625
0
     error,
1626
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1627
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1628
0
     "%s: unable to retrieve store descriptor: %d.",
1629
0
     function,
1630
0
     store_index );
1631
1632
0
    goto on_error;
1633
0
  }
1634
0
  if( libvshadow_store_descriptor_get_identifier(
1635
0
       store_descriptor,
1636
0
       guid,
1637
0
       size,
1638
0
       error ) != 1 )
1639
0
  {
1640
0
    libcerror_error_set(
1641
0
     error,
1642
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1643
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1644
0
     "%s: unable to retrieve identifier from store descriptor: %d.",
1645
0
     function,
1646
0
     store_index );
1647
1648
0
    goto on_error;
1649
0
  }
1650
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1651
0
  if( libcthreads_read_write_lock_release_for_read(
1652
0
       internal_volume->read_write_lock,
1653
0
       error ) != 1 )
1654
0
  {
1655
0
    libcerror_error_set(
1656
0
     error,
1657
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1658
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1659
0
     "%s: unable to release read/write lock for reading.",
1660
0
     function );
1661
1662
0
    return( -1 );
1663
0
  }
1664
0
#endif
1665
0
  return( 1 );
1666
1667
0
on_error:
1668
0
#if defined( HAVE_LIBVSHADOW_MULTI_THREAD_SUPPORT )
1669
0
  libcthreads_read_write_lock_release_for_read(
1670
0
   internal_volume->read_write_lock,
1671
0
   NULL );
1672
0
#endif
1673
0
  return( -1 );
1674
0
}
1675