Coverage Report

Created: 2025-06-13 07:21

/src/libphdi/libphdi/libphdi_handle.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Handle functions
3
 *
4
 * Copyright (C) 2015-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 <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <system_string.h>
27
#include <wide_string.h>
28
29
#include "libphdi_block_descriptor.h"
30
#include "libphdi_data_files.h"
31
#include "libphdi_debug.h"
32
#include "libphdi_definitions.h"
33
#include "libphdi_disk_descriptor_xml_file.h"
34
#include "libphdi_disk_parameters.h"
35
#include "libphdi_extent_descriptor.h"
36
#include "libphdi_extent_table.h"
37
#include "libphdi_extent_values.h"
38
#include "libphdi_i18n.h"
39
#include "libphdi_image_values.h"
40
#include "libphdi_io_handle.h"
41
#include "libphdi_handle.h"
42
#include "libphdi_libbfio.h"
43
#include "libphdi_libcdata.h"
44
#include "libphdi_libcdirectory.h"
45
#include "libphdi_libcerror.h"
46
#include "libphdi_libcnotify.h"
47
#include "libphdi_libcpath.h"
48
#include "libphdi_libcthreads.h"
49
#include "libphdi_libfcache.h"
50
#include "libphdi_libfdata.h"
51
#include "libphdi_snapshot.h"
52
#include "libphdi_snapshot_values.h"
53
#include "libphdi_storage_image.h"
54
55
/* Creates a handle
56
 * Make sure the value handle is referencing, is set to NULL
57
 * Returns 1 if successful or -1 on error
58
 */
59
int libphdi_handle_initialize(
60
     libphdi_handle_t **handle,
61
     libcerror_error_t **error )
62
828
{
63
828
  libphdi_internal_handle_t *internal_handle = NULL;
64
828
  static char *function                      = "libphdi_handle_initialize";
65
66
828
  if( handle == NULL )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
72
0
     "%s: invalid handle.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
828
  if( *handle != NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
82
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
83
0
     "%s: invalid handle value already set.",
84
0
     function );
85
86
0
    return( -1 );
87
0
  }
88
828
  internal_handle = memory_allocate_structure(
89
828
                     libphdi_internal_handle_t );
90
91
828
  if( internal_handle == NULL )
92
0
  {
93
0
    libcerror_error_set(
94
0
     error,
95
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
96
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
97
0
     "%s: unable to create handle.",
98
0
     function );
99
100
0
    goto on_error;
101
0
  }
102
828
  if( memory_set(
103
828
       internal_handle,
104
828
       0,
105
828
       sizeof( libphdi_internal_handle_t ) ) == NULL )
106
0
  {
107
0
    libcerror_error_set(
108
0
     error,
109
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
110
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
111
0
     "%s: unable to clear handle.",
112
0
     function );
113
114
0
    memory_free(
115
0
     internal_handle );
116
117
0
    return( -1 );
118
0
  }
119
828
  if( libphdi_io_handle_initialize(
120
828
       &( internal_handle->io_handle ),
121
828
       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
828
  if( libcdata_array_initialize(
133
828
       &( internal_handle->extent_values_array ),
134
828
       0,
135
828
       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 create extent values array.",
142
0
     function );
143
144
0
    goto on_error;
145
0
  }
146
828
  if( libcdata_array_initialize(
147
828
       &( internal_handle->image_values_array ),
148
828
       0,
149
828
       error ) != 1 )
150
0
  {
151
0
    libcerror_error_set(
152
0
     error,
153
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
154
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
155
0
     "%s: unable to create image values array.",
156
0
     function );
157
158
0
    goto on_error;
159
0
  }
160
828
  if( libcdata_array_initialize(
161
828
       &( internal_handle->snapshot_values_array ),
162
828
       0,
163
828
       error ) != 1 )
164
0
  {
165
0
    libcerror_error_set(
166
0
     error,
167
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
168
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
169
0
     "%s: unable to create snapshot values array.",
170
0
     function );
171
172
0
    goto on_error;
173
0
  }
174
828
  if( libphdi_data_files_initialize(
175
828
       &( internal_handle->data_files ),
176
828
       error ) != 1 )
177
0
  {
178
0
    libcerror_error_set(
179
0
     error,
180
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
181
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
182
0
     "%s: unable to create data files.",
183
0
     function );
184
185
0
    goto on_error;
186
0
  }
187
828
  if( libphdi_i18n_initialize(
188
828
       error ) != 1 )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
193
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
194
0
     "%s: unable to initalize internationalization (i18n).",
195
0
     function );
196
197
0
    goto on_error;
198
0
  }
199
828
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
200
828
  if( libcthreads_read_write_lock_initialize(
201
828
       &( internal_handle->read_write_lock ),
202
828
       error ) != 1 )
203
0
  {
204
0
    libcerror_error_set(
205
0
     error,
206
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
207
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
208
0
     "%s: unable to initialize read/write lock.",
209
0
     function );
210
211
0
    goto on_error;
212
0
  }
213
828
#endif
214
828
  internal_handle->maximum_number_of_open_handles = LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES;
215
216
828
  *handle = (libphdi_handle_t *) internal_handle;
217
218
828
  return( 1 );
219
220
0
on_error:
221
0
  if( internal_handle != NULL )
222
0
  {
223
0
    if( internal_handle->data_files != NULL )
224
0
    {
225
0
      libphdi_data_files_free(
226
0
       &( internal_handle->data_files ),
227
0
       NULL );
228
0
    }
229
0
    if( internal_handle->snapshot_values_array != NULL )
230
0
    {
231
0
      libcdata_array_free(
232
0
       &( internal_handle->snapshot_values_array ),
233
0
       NULL,
234
0
       NULL );
235
0
    }
236
0
    if( internal_handle->image_values_array != NULL )
237
0
    {
238
0
      libcdata_array_free(
239
0
       &( internal_handle->image_values_array ),
240
0
       NULL,
241
0
       NULL );
242
0
    }
243
0
    if( internal_handle->extent_values_array != NULL )
244
0
    {
245
0
      libcdata_array_free(
246
0
       &( internal_handle->extent_values_array ),
247
0
       NULL,
248
0
       NULL );
249
0
    }
250
0
    if( internal_handle->io_handle != NULL )
251
0
    {
252
0
      libphdi_io_handle_free(
253
0
       &( internal_handle->io_handle ),
254
0
       NULL );
255
0
    }
256
0
    memory_free(
257
0
     internal_handle );
258
0
  }
259
0
  return( -1 );
260
828
}
261
262
/* Frees a handle
263
 * Returns 1 if successful or -1 on error
264
 */
265
int libphdi_handle_free(
266
     libphdi_handle_t **handle,
267
     libcerror_error_t **error )
268
828
{
269
828
  libphdi_internal_handle_t *internal_handle = NULL;
270
828
  static char *function                      = "libphdi_handle_free";
271
828
  int result                                 = 1;
272
273
828
  if( handle == NULL )
274
0
  {
275
0
    libcerror_error_set(
276
0
     error,
277
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
278
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
279
0
     "%s: invalid handle.",
280
0
     function );
281
282
0
    return( -1 );
283
0
  }
284
828
  if( *handle != NULL )
285
828
  {
286
828
    internal_handle = (libphdi_internal_handle_t *) *handle;
287
288
828
    if( ( internal_handle->extent_data_file_io_pool != NULL )
289
828
     || ( internal_handle->file_io_handle != NULL ) )
290
0
    {
291
0
      if( libphdi_handle_close(
292
0
           *handle,
293
0
           error ) != 0 )
294
0
      {
295
0
        libcerror_error_set(
296
0
         error,
297
0
         LIBCERROR_ERROR_DOMAIN_IO,
298
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
299
0
         "%s: unable to close handle.",
300
0
         function );
301
302
0
        result = -1;
303
0
      }
304
0
    }
305
828
    *handle = NULL;
306
307
828
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
308
828
    if( libcthreads_read_write_lock_free(
309
828
         &( internal_handle->read_write_lock ),
310
828
         error ) != 1 )
311
0
    {
312
0
      libcerror_error_set(
313
0
       error,
314
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
315
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
316
0
       "%s: unable to free read/write lock.",
317
0
       function );
318
319
0
      result = -1;
320
0
    }
321
828
#endif
322
828
    if( libphdi_data_files_free(
323
828
         &( internal_handle->data_files ),
324
828
         error ) != 1 )
325
0
    {
326
0
      libcerror_error_set(
327
0
       error,
328
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
330
0
       "%s: unable to free data files.",
331
0
       function );
332
333
0
      result = -1;
334
0
    }
335
828
    if( libcdata_array_free(
336
828
         &( internal_handle->snapshot_values_array ),
337
828
         (int (*)(intptr_t **, libcerror_error_t **)) &libphdi_snapshot_values_free,
338
828
         error ) != 1 )
339
0
    {
340
0
      libcerror_error_set(
341
0
       error,
342
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
343
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
344
0
       "%s: unable to free snapshot values array.",
345
0
       function );
346
347
0
      result = -1;
348
0
    }
349
828
    if( libcdata_array_free(
350
828
         &( internal_handle->image_values_array ),
351
828
         NULL,
352
828
         error ) != 1 )
353
0
    {
354
0
      libcerror_error_set(
355
0
       error,
356
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
357
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
358
0
       "%s: unable to free extent values array.",
359
0
       function );
360
361
0
      result = -1;
362
0
    }
363
828
    if( libcdata_array_free(
364
828
         &( internal_handle->extent_values_array ),
365
828
         (int (*)(intptr_t **, libcerror_error_t **)) &libphdi_extent_values_free,
366
828
         error ) != 1 )
367
0
    {
368
0
      libcerror_error_set(
369
0
       error,
370
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
371
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
372
0
       "%s: unable to free extent values array.",
373
0
       function );
374
375
0
      result = -1;
376
0
    }
377
828
    if( libphdi_io_handle_free(
378
828
         &( internal_handle->io_handle ),
379
828
         error ) != 1 )
380
0
    {
381
0
      libcerror_error_set(
382
0
       error,
383
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
384
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
385
0
       "%s: unable to free IO handle.",
386
0
       function );
387
388
0
      result = -1;
389
0
    }
390
828
    memory_free(
391
828
     internal_handle );
392
828
  }
393
828
  return( result );
394
828
}
395
396
/* Signals a handle to abort its current activity
397
 * Returns 1 if successful or -1 on error
398
 */
399
int libphdi_handle_signal_abort(
400
     libphdi_handle_t *handle,
401
     libcerror_error_t **error )
402
0
{
403
0
  libphdi_internal_handle_t *internal_handle = NULL;
404
0
  static char *function                      = "libphdi_handle_signal_abort";
405
406
0
  if( handle == NULL )
407
0
  {
408
0
    libcerror_error_set(
409
0
     error,
410
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
411
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
412
0
     "%s: invalid handle.",
413
0
     function );
414
415
0
    return( -1 );
416
0
  }
417
0
  internal_handle = (libphdi_internal_handle_t *) handle;
418
419
0
  if( internal_handle->io_handle == NULL )
420
0
  {
421
0
    libcerror_error_set(
422
0
     error,
423
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
424
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
425
0
     "%s: invalid handle - missing IO handle.",
426
0
     function );
427
428
0
    return( -1 );
429
0
  }
430
0
  internal_handle->io_handle->abort = 1;
431
432
0
  return( 1 );
433
0
}
434
435
/* Opens a handle
436
 * Returns 1 if successful or -1 on error
437
 */
438
int libphdi_handle_open(
439
     libphdi_handle_t *handle,
440
     const char *filename,
441
     int access_flags,
442
     libcerror_error_t **error )
443
0
{
444
0
  libbfio_handle_t *file_io_handle           = NULL;
445
0
  libcdirectory_directory_t *directory       = NULL;
446
0
  libphdi_internal_handle_t *internal_handle = NULL;
447
0
  char *data_files_path_end                  = NULL;
448
0
  char *disk_descriptor_xml_path             = NULL;
449
0
  static char *function                      = "libphdi_handle_open";
450
0
  size_t data_files_path_length              = 0;
451
0
  size_t disk_descriptor_xml_path_size       = 0;
452
0
  size_t filename_length                     = 0;
453
0
  int is_directory                           = 0;
454
0
  int result                                 = 1;
455
456
0
  if( handle == NULL )
457
0
  {
458
0
    libcerror_error_set(
459
0
     error,
460
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
461
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
462
0
     "%s: invalid handle.",
463
0
     function );
464
465
0
    return( -1 );
466
0
  }
467
0
  internal_handle = (libphdi_internal_handle_t *) handle;
468
469
0
  if( filename == NULL )
470
0
  {
471
0
    libcerror_error_set(
472
0
     error,
473
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
474
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
475
0
     "%s: invalid filename.",
476
0
     function );
477
478
0
    return( -1 );
479
0
  }
480
0
  if( ( ( access_flags & LIBPHDI_ACCESS_FLAG_READ ) == 0 )
481
0
   && ( ( access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) == 0 ) )
482
0
  {
483
0
    libcerror_error_set(
484
0
     error,
485
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
486
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
487
0
     "%s: unsupported access flags.",
488
0
     function );
489
490
0
    return( -1 );
491
0
  }
492
0
  if( ( access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) != 0 )
493
0
  {
494
0
    libcerror_error_set(
495
0
     error,
496
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
497
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
498
0
     "%s: write access currently not supported.",
499
0
     function );
500
501
0
    return( -1 );
502
0
  }
503
0
  if( libcdirectory_directory_initialize(
504
0
       &directory,
505
0
       error ) != 1 )
506
0
  {
507
0
    libcerror_error_set(
508
0
     error,
509
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
510
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
511
0
     "%s: unable to create directory.",
512
0
     function );
513
514
0
    goto on_error;
515
0
  }
516
0
  is_directory = libcdirectory_directory_open(
517
0
                  directory,
518
0
                  filename,
519
0
                  NULL );
520
521
0
  if( libcdirectory_directory_free(
522
0
       &directory,
523
0
       error ) != 1 )
524
0
  {
525
0
    libcerror_error_set(
526
0
     error,
527
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
528
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
529
0
     "%s: unable to free directory.",
530
0
     function );
531
532
0
    goto on_error;
533
0
  }
534
0
  if( libbfio_file_initialize(
535
0
       &file_io_handle,
536
0
       error ) != 1 )
537
0
  {
538
0
    libcerror_error_set(
539
0
     error,
540
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
541
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
542
0
     "%s: unable to create file IO handle.",
543
0
     function );
544
545
0
    goto on_error;
546
0
  }
547
#if defined( HAVE_DEBUG_OUTPUT )
548
  if( libbfio_handle_set_track_offsets_read(
549
       file_io_handle,
550
       1,
551
       error ) != 1 )
552
  {
553
    libcerror_error_set(
554
     error,
555
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
556
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
557
     "%s: unable to set track offsets read in file IO handle.",
558
     function );
559
560
    goto on_error;
561
  }
562
#endif
563
0
  if( is_directory == 1 )
564
0
  {
565
0
    filename_length = narrow_string_length(
566
0
                       filename );
567
568
0
    if( libcpath_path_join(
569
0
         &disk_descriptor_xml_path,
570
0
         &disk_descriptor_xml_path_size,
571
0
         filename,
572
0
         filename_length,
573
0
         "DiskDescriptor.xml",
574
0
         19,
575
0
         error ) != 1 )
576
0
    {
577
0
      libcerror_error_set(
578
0
       error,
579
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
581
0
       "%s: unable to create DiskDescriptor.xml path.",
582
0
       function );
583
584
0
      goto on_error;
585
0
    }
586
0
    if( libbfio_file_set_name(
587
0
         file_io_handle,
588
0
         disk_descriptor_xml_path,
589
0
         disk_descriptor_xml_path_size - 1,
590
0
         error ) != 1 )
591
0
    {
592
0
      libcerror_error_set(
593
0
       error,
594
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
595
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
596
0
       "%s: unable to set filename in file IO handle.",
597
0
       function );
598
599
0
      goto on_error;
600
0
    }
601
0
    filename        = disk_descriptor_xml_path;
602
0
    filename_length = disk_descriptor_xml_path_size - 1;
603
0
  }
604
0
  else
605
0
  {
606
0
    filename_length = narrow_string_length(
607
0
                       filename );
608
609
0
    if( libbfio_file_set_name(
610
0
         file_io_handle,
611
0
         filename,
612
0
         filename_length,
613
0
         error ) != 1 )
614
0
    {
615
0
      libcerror_error_set(
616
0
       error,
617
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
618
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
619
0
       "%s: unable to set filename in file IO handle.",
620
0
       function );
621
622
0
      goto on_error;
623
0
    }
624
0
  }
625
0
  if( libphdi_handle_open_file_io_handle(
626
0
       handle,
627
0
       file_io_handle,
628
0
       access_flags,
629
0
       error ) != 1 )
630
0
  {
631
0
    libcerror_error_set(
632
0
     error,
633
0
     LIBCERROR_ERROR_DOMAIN_IO,
634
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
635
0
     "%s: unable to open handle from file: %s.",
636
0
     function,
637
0
     filename );
638
639
0
    goto on_error;
640
0
  }
641
0
  filename_length = narrow_string_length(
642
0
                     filename );
643
644
0
  data_files_path_end = narrow_string_search_character_reverse(
645
0
                         filename,
646
0
                         (int) LIBCPATH_SEPARATOR,
647
0
                         filename_length + 1 );
648
649
0
  if( data_files_path_end != NULL )
650
0
  {
651
0
    data_files_path_length = (size_t) ( data_files_path_end - filename );
652
0
  }
653
0
  if( data_files_path_length > 0 )
654
0
  {
655
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
656
0
    if( libcthreads_read_write_lock_grab_for_write(
657
0
         internal_handle->read_write_lock,
658
0
         error ) != 1 )
659
0
    {
660
0
      libcerror_error_set(
661
0
       error,
662
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
663
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
664
0
       "%s: unable to grab read/write lock for writing.",
665
0
       function );
666
667
0
      return( -1 );
668
0
    }
669
0
#endif
670
0
    if( libphdi_data_files_set_path(
671
0
         internal_handle->data_files,
672
0
         filename,
673
0
         data_files_path_length,
674
0
         error ) != 1 )
675
0
    {
676
0
      libcerror_error_set(
677
0
       error,
678
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
679
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
680
0
       "%s: unable to set data files path.",
681
0
       function );
682
683
0
      result = -1;
684
0
    }
685
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
686
0
    if( libcthreads_read_write_lock_release_for_write(
687
0
         internal_handle->read_write_lock,
688
0
         error ) != 1 )
689
0
    {
690
0
      libcerror_error_set(
691
0
       error,
692
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
693
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
694
0
       "%s: unable to release read/write lock for writing.",
695
0
       function );
696
697
0
      return( -1 );
698
0
    }
699
0
#endif
700
0
  }
701
0
  internal_handle->file_io_handle_created_in_library = 1;
702
703
0
  if( disk_descriptor_xml_path != NULL )
704
0
  {
705
0
    memory_free(
706
0
     disk_descriptor_xml_path );
707
708
0
    disk_descriptor_xml_path = NULL;
709
0
  }
710
0
  return( result );
711
712
0
on_error:
713
0
  if( file_io_handle != NULL )
714
0
  {
715
0
    libbfio_handle_free(
716
0
     &file_io_handle,
717
0
     NULL );
718
0
  }
719
0
  if( disk_descriptor_xml_path != NULL )
720
0
  {
721
0
    memory_free(
722
0
     disk_descriptor_xml_path );
723
0
  }
724
0
  if( directory != NULL )
725
0
  {
726
0
    libcdirectory_directory_free(
727
0
     &directory,
728
0
     NULL );
729
0
  }
730
0
  return( -1 );
731
0
}
732
733
#if defined( HAVE_WIDE_CHARACTER_TYPE )
734
735
/* Opens a handle
736
 * Returns 1 if successful or -1 on error
737
 */
738
int libphdi_handle_open_wide(
739
     libphdi_handle_t *handle,
740
     const wchar_t *filename,
741
     int access_flags,
742
     libcerror_error_t **error )
743
{
744
  libbfio_handle_t *file_io_handle           = NULL;
745
  libcdirectory_directory_t *directory       = NULL;
746
  libphdi_internal_handle_t *internal_handle = NULL;
747
  wchar_t *data_files_path_end               = NULL;
748
  wchar_t *disk_descriptor_xml_path          = NULL;
749
  static char *function                      = "libphdi_handle_open_wide";
750
  size_t data_files_path_length              = 0;
751
  size_t disk_descriptor_xml_path_size       = 0;
752
  size_t filename_length                     = 0;
753
  int is_directory                           = 0;
754
  int result                                 = 1;
755
756
  if( handle == NULL )
757
  {
758
    libcerror_error_set(
759
     error,
760
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
761
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
762
     "%s: invalid handle.",
763
     function );
764
765
    return( -1 );
766
  }
767
  internal_handle = (libphdi_internal_handle_t *) handle;
768
769
  if( filename == NULL )
770
  {
771
    libcerror_error_set(
772
     error,
773
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
774
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
775
     "%s: invalid filename.",
776
     function );
777
778
    return( -1 );
779
  }
780
  if( ( ( access_flags & LIBPHDI_ACCESS_FLAG_READ ) == 0 )
781
   && ( ( access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) == 0 ) )
782
  {
783
    libcerror_error_set(
784
     error,
785
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
786
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
787
     "%s: unsupported access flags.",
788
     function );
789
790
    return( -1 );
791
  }
792
  if( ( access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) != 0 )
793
  {
794
    libcerror_error_set(
795
     error,
796
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
797
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
798
     "%s: write access currently not supported.",
799
     function );
800
801
    return( -1 );
802
  }
803
  if( libcdirectory_directory_initialize(
804
       &directory,
805
       error ) != 1 )
806
  {
807
    libcerror_error_set(
808
     error,
809
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
810
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
811
     "%s: unable to create directory.",
812
     function );
813
814
    goto on_error;
815
  }
816
  is_directory = libcdirectory_directory_open_wide(
817
                  directory,
818
                  filename,
819
                  NULL );
820
821
  if( libcdirectory_directory_free(
822
       &directory,
823
       error ) != 1 )
824
  {
825
    libcerror_error_set(
826
     error,
827
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
828
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
829
     "%s: unable to free directory.",
830
     function );
831
832
    goto on_error;
833
  }
834
  if( libbfio_file_initialize(
835
       &file_io_handle,
836
       error ) != 1 )
837
  {
838
    libcerror_error_set(
839
     error,
840
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
841
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
842
     "%s: unable to create file IO handle.",
843
     function );
844
845
    goto on_error;
846
  }
847
#if defined( HAVE_DEBUG_OUTPUT )
848
  if( libbfio_handle_set_track_offsets_read(
849
       file_io_handle,
850
       1,
851
       error ) != 1 )
852
  {
853
    libcerror_error_set(
854
     error,
855
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
856
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
857
     "%s: unable to set track offsets read in file IO handle.",
858
     function );
859
860
    goto on_error;
861
  }
862
#endif
863
  if( is_directory == 1 )
864
  {
865
    filename_length = wide_string_length(
866
                       filename );
867
868
    if( libcpath_path_join_wide(
869
         &disk_descriptor_xml_path,
870
         &disk_descriptor_xml_path_size,
871
         filename,
872
         filename_length,
873
         L"DiskDescriptor.xml",
874
         19,
875
         error ) != 1 )
876
    {
877
      libcerror_error_set(
878
       error,
879
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
880
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
881
       "%s: unable to create DiskDescriptor.xml path.",
882
       function );
883
884
      goto on_error;
885
    }
886
    if( libbfio_file_set_name_wide(
887
         file_io_handle,
888
         disk_descriptor_xml_path,
889
         disk_descriptor_xml_path_size - 1,
890
         error ) != 1 )
891
    {
892
      libcerror_error_set(
893
       error,
894
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
895
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
896
       "%s: unable to set filename in file IO handle.",
897
       function );
898
899
      goto on_error;
900
    }
901
  }
902
  else
903
  {
904
    filename_length = wide_string_length(
905
                       filename );
906
907
    if( libbfio_file_set_name_wide(
908
         file_io_handle,
909
         filename,
910
         filename_length,
911
         error ) != 1 )
912
    {
913
      libcerror_error_set(
914
       error,
915
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
916
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
917
       "%s: unable to set filename in file IO handle.",
918
       function );
919
920
      goto on_error;
921
    }
922
  }
923
  if( libphdi_handle_open_file_io_handle(
924
       handle,
925
       file_io_handle,
926
       access_flags,
927
       error ) != 1 )
928
  {
929
    libcerror_error_set(
930
     error,
931
     LIBCERROR_ERROR_DOMAIN_IO,
932
     LIBCERROR_IO_ERROR_OPEN_FAILED,
933
     "%s: unable to open handle: %ls.",
934
     function,
935
     filename );
936
937
    goto on_error;
938
  }
939
  filename_length = wide_string_length(
940
                     filename );
941
942
  data_files_path_end = wide_string_search_character_reverse(
943
                         filename,
944
                         (int) LIBCPATH_SEPARATOR,
945
                         filename_length + 1 );
946
947
  if( data_files_path_end != NULL )
948
  {
949
    data_files_path_length = (size_t) ( data_files_path_end - filename );
950
  }
951
  if( data_files_path_length > 0 )
952
  {
953
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
954
    if( libcthreads_read_write_lock_grab_for_write(
955
         internal_handle->read_write_lock,
956
         error ) != 1 )
957
    {
958
      libcerror_error_set(
959
       error,
960
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
961
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
962
       "%s: unable to grab read/write lock for writing.",
963
       function );
964
965
      return( -1 );
966
    }
967
#endif
968
    if( libphdi_data_files_set_path_wide(
969
         internal_handle->data_files,
970
         filename,
971
         data_files_path_length,
972
         error ) != 1 )
973
    {
974
      libcerror_error_set(
975
       error,
976
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
977
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
978
       "%s: unable to set data files path.",
979
       function );
980
981
      result = -1;
982
    }
983
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
984
    if( libcthreads_read_write_lock_release_for_write(
985
         internal_handle->read_write_lock,
986
         error ) != 1 )
987
    {
988
      libcerror_error_set(
989
       error,
990
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
991
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
992
       "%s: unable to release read/write lock for writing.",
993
       function );
994
995
      return( -1 );
996
    }
997
#endif
998
  }
999
  internal_handle->file_io_handle_created_in_library = 1;
1000
1001
  if( disk_descriptor_xml_path != NULL )
1002
  {
1003
    memory_free(
1004
     disk_descriptor_xml_path );
1005
1006
    disk_descriptor_xml_path = NULL;
1007
  }
1008
  return( result );
1009
1010
on_error:
1011
  if( file_io_handle != NULL )
1012
  {
1013
    libbfio_handle_free(
1014
     &file_io_handle,
1015
     NULL );
1016
  }
1017
  if( disk_descriptor_xml_path != NULL )
1018
  {
1019
    memory_free(
1020
     disk_descriptor_xml_path );
1021
  }
1022
  if( directory != NULL )
1023
  {
1024
    libcdirectory_directory_free(
1025
     &directory,
1026
     NULL );
1027
  }
1028
  return( -1 );
1029
}
1030
1031
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
1032
1033
/* Opens a handle using a Basic File IO (bfio) handle
1034
 * Returns 1 if successful or -1 on error
1035
 */
1036
int libphdi_handle_open_file_io_handle(
1037
     libphdi_handle_t *handle,
1038
     libbfio_handle_t *file_io_handle,
1039
     int access_flags,
1040
     libcerror_error_t **error )
1041
828
{
1042
828
  libphdi_internal_handle_t *internal_handle = NULL;
1043
828
  static char *function                      = "libphdi_handle_open_file_io_handle";
1044
828
  uint8_t file_io_handle_opened_in_library   = 0;
1045
828
  int bfio_access_flags                      = 0;
1046
828
  int file_io_handle_is_open                 = 0;
1047
828
  int result                                 = 1;
1048
1049
828
  if( handle == NULL )
1050
0
  {
1051
0
    libcerror_error_set(
1052
0
     error,
1053
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1054
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1055
0
     "%s: invalid handle.",
1056
0
     function );
1057
1058
0
    return( -1 );
1059
0
  }
1060
828
  internal_handle = (libphdi_internal_handle_t *) handle;
1061
1062
828
  if( file_io_handle == NULL )
1063
0
  {
1064
0
    libcerror_error_set(
1065
0
     error,
1066
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1067
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1068
0
     "%s: invalid file IO handle.",
1069
0
     function );
1070
1071
0
    return( -1 );
1072
0
  }
1073
828
  if( ( ( access_flags & LIBPHDI_ACCESS_FLAG_READ ) == 0 )
1074
828
   && ( ( access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) == 0 ) )
1075
0
  {
1076
0
    libcerror_error_set(
1077
0
     error,
1078
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1079
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1080
0
     "%s: unsupported access flags.",
1081
0
     function );
1082
1083
0
    return( -1 );
1084
0
  }
1085
828
  if( ( access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) != 0 )
1086
0
  {
1087
0
    libcerror_error_set(
1088
0
     error,
1089
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1090
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1091
0
     "%s: write access currently not supported.",
1092
0
     function );
1093
1094
0
    return( -1 );
1095
0
  }
1096
828
  if( ( access_flags & LIBPHDI_ACCESS_FLAG_READ ) != 0 )
1097
828
  {
1098
828
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
1099
828
  }
1100
828
  file_io_handle_is_open = libbfio_handle_is_open(
1101
828
                            file_io_handle,
1102
828
                            error );
1103
1104
828
  if( file_io_handle_is_open == -1 )
1105
0
  {
1106
0
    libcerror_error_set(
1107
0
     error,
1108
0
     LIBCERROR_ERROR_DOMAIN_IO,
1109
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
1110
0
     "%s: unable to determine if file IO handle is open.",
1111
0
     function );
1112
1113
0
    goto on_error;
1114
0
  }
1115
828
  else if( file_io_handle_is_open == 0 )
1116
828
  {
1117
828
    if( libbfio_handle_open(
1118
828
         file_io_handle,
1119
828
         bfio_access_flags,
1120
828
         error ) != 1 )
1121
0
    {
1122
0
      libcerror_error_set(
1123
0
       error,
1124
0
       LIBCERROR_ERROR_DOMAIN_IO,
1125
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
1126
0
       "%s: unable to open file IO handle.",
1127
0
       function );
1128
1129
0
      goto on_error;
1130
0
    }
1131
828
    file_io_handle_opened_in_library = 1;
1132
828
  }
1133
828
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1134
828
  if( libcthreads_read_write_lock_grab_for_write(
1135
828
       internal_handle->read_write_lock,
1136
828
       error ) != 1 )
1137
0
  {
1138
0
    libcerror_error_set(
1139
0
     error,
1140
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1141
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1142
0
     "%s: unable to grab read/write lock for writing.",
1143
0
     function );
1144
1145
0
    return( -1 );
1146
0
  }
1147
828
#endif
1148
828
  if( libphdi_internal_handle_open_read(
1149
828
       internal_handle,
1150
828
       file_io_handle,
1151
828
       error ) != 1 )
1152
828
  {
1153
828
    libcerror_error_set(
1154
828
     error,
1155
828
     LIBCERROR_ERROR_DOMAIN_IO,
1156
828
     LIBCERROR_IO_ERROR_READ_FAILED,
1157
828
     "%s: unable to read from file IO handle.",
1158
828
     function );
1159
1160
828
    result = -1;
1161
828
  }
1162
0
  else
1163
0
  {
1164
0
    internal_handle->file_io_handle                   = file_io_handle;
1165
0
    internal_handle->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
1166
0
    internal_handle->access_flags                     = access_flags;
1167
0
  }
1168
828
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1169
828
  if( libcthreads_read_write_lock_release_for_write(
1170
828
       internal_handle->read_write_lock,
1171
828
       error ) != 1 )
1172
0
  {
1173
0
    libcerror_error_set(
1174
0
     error,
1175
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1176
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1177
0
     "%s: unable to release read/write lock for writing.",
1178
0
     function );
1179
1180
0
    return( -1 );
1181
0
  }
1182
828
#endif
1183
828
  return( result );
1184
1185
0
on_error:
1186
0
  if( file_io_handle_opened_in_library != 0 )
1187
0
  {
1188
0
    libbfio_handle_close(
1189
0
     file_io_handle,
1190
0
     error );
1191
0
  }
1192
0
  return( -1 );
1193
828
}
1194
1195
/* Opens the extent data files
1196
 * If the extent data filenames were not set explicitly this function assumes the extent data files
1197
 * are in the same location as the descriptor file
1198
 * Returns 1 if successful or -1 on error
1199
 */
1200
int libphdi_handle_open_extent_data_files(
1201
     libphdi_handle_t *handle,
1202
     libcerror_error_t **error )
1203
0
{
1204
0
  libbfio_pool_t *file_io_pool                  = NULL;
1205
0
  libphdi_image_values_t *image_values          = NULL;
1206
0
  libphdi_internal_handle_t *internal_handle    = NULL;
1207
0
  system_character_t *extent_data_file_location = NULL;
1208
0
  static char *function                         = "libphdi_handle_open_extent_data_files";
1209
0
  size_t extent_data_file_location_size         = 0;
1210
0
  int image_index                               = 0;
1211
0
  int number_of_images                          = 0;
1212
0
  int result                                    = 0;
1213
1214
0
  if( handle == NULL )
1215
0
  {
1216
0
    libcerror_error_set(
1217
0
     error,
1218
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1219
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1220
0
     "%s: invalid handle.",
1221
0
     function );
1222
1223
0
    return( -1 );
1224
0
  }
1225
0
  internal_handle = (libphdi_internal_handle_t *) handle;
1226
1227
0
  if( ( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_READ ) == 0 )
1228
0
   && ( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) == 0 ) )
1229
0
  {
1230
0
    libcerror_error_set(
1231
0
     error,
1232
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1233
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1234
0
     "%s: unsupported access flags.",
1235
0
     function );
1236
1237
0
    return( -1 );
1238
0
  }
1239
0
  if( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) != 0 )
1240
0
  {
1241
0
    libcerror_error_set(
1242
0
     error,
1243
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1244
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1245
0
     "%s: write access currently not supported.",
1246
0
     function );
1247
1248
0
    return( -1 );
1249
0
  }
1250
0
  if( internal_handle->file_io_handle == NULL )
1251
0
  {
1252
0
    libcerror_error_set(
1253
0
     error,
1254
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1255
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1256
0
     "%s: invalid handle - missing file IO handle.",
1257
0
     function );
1258
1259
0
    return( -1 );
1260
0
  }
1261
0
  if( internal_handle->extent_data_file_io_pool != NULL )
1262
0
  {
1263
0
    libcerror_error_set(
1264
0
     error,
1265
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1266
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1267
0
     "%s: invalid handle - extent data file IO pool already exists.",
1268
0
     function );
1269
1270
0
    return( -1 );
1271
0
  }
1272
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1273
0
  if( libcthreads_read_write_lock_grab_for_write(
1274
0
       internal_handle->read_write_lock,
1275
0
       error ) != 1 )
1276
0
  {
1277
0
    libcerror_error_set(
1278
0
     error,
1279
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1280
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1281
0
     "%s: unable to grab read/write lock for writing.",
1282
0
     function );
1283
1284
0
    return( -1 );
1285
0
  }
1286
0
#endif
1287
0
  if( libcdata_array_get_number_of_entries(
1288
0
       internal_handle->image_values_array,
1289
0
       &number_of_images,
1290
0
       error ) != 1 )
1291
0
  {
1292
0
    libcerror_error_set(
1293
0
     error,
1294
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1295
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1296
0
     "%s: unable to retrieve number of extents.",
1297
0
     function );
1298
1299
0
    goto on_error;
1300
0
  }
1301
0
  if( number_of_images == 0 )
1302
0
  {
1303
0
    libcerror_error_set(
1304
0
     error,
1305
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1307
0
     "%s: invalid number of images value out of bounds.",
1308
0
     function );
1309
1310
0
    return( -1 );
1311
0
  }
1312
0
  if( libbfio_pool_initialize(
1313
0
       &file_io_pool,
1314
0
       number_of_images,
1315
0
       internal_handle->maximum_number_of_open_handles,
1316
0
       error ) != 1 )
1317
0
  {
1318
0
    libcerror_error_set(
1319
0
     error,
1320
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1321
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1322
0
     "%s: unable to create file IO pool.",
1323
0
     function );
1324
1325
0
    goto on_error;
1326
0
  }
1327
0
  for( image_index = 0;
1328
0
       image_index < number_of_images;
1329
0
       image_index++ )
1330
0
  {
1331
0
    if( libcdata_array_get_entry_by_index(
1332
0
         internal_handle->image_values_array,
1333
0
         image_index,
1334
0
         (intptr_t **) &image_values,
1335
0
         error ) != 1 )
1336
0
    {
1337
0
      libcerror_error_set(
1338
0
       error,
1339
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1340
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1341
0
       "%s: unable to retrieve image values: %d from array.",
1342
0
       function,
1343
0
       image_index );
1344
1345
0
      goto on_error;
1346
0
    }
1347
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
1348
    result = libphdi_data_files_get_extent_data_file_path_wide(
1349
              internal_handle->data_files,
1350
              image_values,
1351
              &extent_data_file_location,
1352
              &extent_data_file_location_size,
1353
              error );
1354
#else
1355
0
    result = libphdi_data_files_get_extent_data_file_path(
1356
0
              internal_handle->data_files,
1357
0
              image_values,
1358
0
              &extent_data_file_location,
1359
0
              &extent_data_file_location_size,
1360
0
              error );
1361
0
#endif
1362
0
    if( result != 1 )
1363
0
    {
1364
0
      libcerror_error_set(
1365
0
       error,
1366
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1367
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1368
0
       "%s: unable to create extent data file location.",
1369
0
       function );
1370
1371
0
      goto on_error;
1372
0
    }
1373
    /* Note that the open extent data file function will initialize extent_data_file_io_pool
1374
     */
1375
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
1376
    result = libphdi_handle_open_extent_data_file_wide(
1377
        internal_handle,
1378
        file_io_pool,
1379
        image_values->file_io_pool_entry,
1380
        extent_data_file_location,
1381
        error );
1382
#else
1383
0
    result = libphdi_handle_open_extent_data_file(
1384
0
        internal_handle,
1385
0
        file_io_pool,
1386
0
        image_values->file_io_pool_entry,
1387
0
        extent_data_file_location,
1388
0
        error );
1389
0
#endif
1390
0
    if( result != 1 )
1391
0
    {
1392
0
      libcerror_error_set(
1393
0
       error,
1394
0
       LIBCERROR_ERROR_DOMAIN_IO,
1395
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
1396
0
       "%s: unable to open extent data file: %" PRIs_SYSTEM ".",
1397
0
       function,
1398
0
       extent_data_file_location );
1399
1400
0
      goto on_error;
1401
0
    }
1402
0
    memory_free(
1403
0
     extent_data_file_location );
1404
1405
0
    extent_data_file_location = NULL;
1406
0
  }
1407
0
  if( libphdi_internal_handle_open_read_extent_data_files(
1408
0
       internal_handle,
1409
0
       file_io_pool,
1410
0
       error ) != 1 )
1411
0
  {
1412
0
                libcerror_error_set(
1413
0
                 error,
1414
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1415
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1416
0
                 "%s: unable to read extent data files.",
1417
0
                 function );
1418
1419
0
                goto on_error;
1420
0
  }
1421
0
  internal_handle->extent_data_file_io_pool                    = file_io_pool;
1422
0
  internal_handle->extent_data_file_io_pool_created_in_library = 1;
1423
1424
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1425
0
  if( libcthreads_read_write_lock_release_for_write(
1426
0
       internal_handle->read_write_lock,
1427
0
       error ) != 1 )
1428
0
  {
1429
0
    libcerror_error_set(
1430
0
     error,
1431
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1432
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1433
0
     "%s: unable to release read/write lock for writing.",
1434
0
     function );
1435
1436
0
    return( -1 );
1437
0
  }
1438
0
#endif
1439
0
  return( 1 );
1440
1441
0
on_error:
1442
0
  if( file_io_pool != NULL )
1443
0
  {
1444
0
    libbfio_pool_close_all(
1445
0
     file_io_pool,
1446
0
     NULL );
1447
0
    libbfio_pool_free(
1448
0
     &file_io_pool,
1449
0
     NULL );
1450
0
  }
1451
0
  if( extent_data_file_location != NULL )
1452
0
  {
1453
0
    memory_free(
1454
0
     extent_data_file_location );
1455
0
  }
1456
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1457
0
  libcthreads_read_write_lock_release_for_write(
1458
0
   internal_handle->read_write_lock,
1459
0
   NULL );
1460
0
#endif
1461
0
  return( -1 );
1462
0
}
1463
1464
/* Opens the extent data files using a Basic File IO (bfio) pool
1465
 * This function assumes the extent data files are in same order as defined by the descriptor file
1466
 * Returns 1 if successful or -1 on error
1467
 */
1468
int libphdi_handle_open_extent_data_files_file_io_pool(
1469
     libphdi_handle_t *handle,
1470
     libbfio_pool_t *file_io_pool,
1471
     libcerror_error_t **error )
1472
0
{
1473
0
  libphdi_internal_handle_t *internal_handle = NULL;
1474
0
  static char *function                      = "libphdi_handle_open_extent_data_files_file_io_pool";
1475
0
  int result                                 = 1;
1476
1477
0
  if( handle == NULL )
1478
0
  {
1479
0
    libcerror_error_set(
1480
0
     error,
1481
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1482
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1483
0
     "%s: invalid handle.",
1484
0
     function );
1485
1486
0
    return( -1 );
1487
0
  }
1488
0
  internal_handle = (libphdi_internal_handle_t *) handle;
1489
1490
0
  if( ( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_READ ) == 0 )
1491
0
   && ( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) == 0 ) )
1492
0
  {
1493
0
    libcerror_error_set(
1494
0
     error,
1495
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1496
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1497
0
     "%s: unsupported access flags.",
1498
0
     function );
1499
1500
0
    return( -1 );
1501
0
  }
1502
0
  if( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_WRITE ) != 0 )
1503
0
  {
1504
0
    libcerror_error_set(
1505
0
     error,
1506
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1507
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1508
0
     "%s: write access currently not supported.",
1509
0
     function );
1510
1511
0
    return( -1 );
1512
0
  }
1513
0
  if( internal_handle->file_io_handle == NULL )
1514
0
  {
1515
0
    libcerror_error_set(
1516
0
     error,
1517
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1518
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1519
0
     "%s: invalid handle - missing file IO handle.",
1520
0
     function );
1521
1522
0
    return( -1 );
1523
0
  }
1524
0
  if( internal_handle->extent_data_file_io_pool != NULL )
1525
0
  {
1526
0
    libcerror_error_set(
1527
0
     error,
1528
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1529
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1530
0
     "%s: invalid handle - extent data file IO pool already exists.",
1531
0
     function );
1532
1533
0
    return( -1 );
1534
0
  }
1535
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1536
0
  if( libcthreads_read_write_lock_grab_for_write(
1537
0
       internal_handle->read_write_lock,
1538
0
       error ) != 1 )
1539
0
  {
1540
0
    libcerror_error_set(
1541
0
     error,
1542
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1543
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1544
0
     "%s: unable to grab read/write lock for writing.",
1545
0
     function );
1546
1547
0
    return( -1 );
1548
0
  }
1549
0
#endif
1550
0
  if( libphdi_internal_handle_open_read_extent_data_files(
1551
0
       internal_handle,
1552
0
       file_io_pool,
1553
0
       error ) != 1 )
1554
0
  {
1555
0
                libcerror_error_set(
1556
0
                 error,
1557
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1558
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1559
0
                 "%s: unable to read extent data files.",
1560
0
                 function );
1561
1562
0
                result = -1;
1563
0
  }
1564
0
  else
1565
0
  {
1566
0
    internal_handle->extent_data_file_io_pool = file_io_pool;
1567
0
  }
1568
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1569
0
  if( libcthreads_read_write_lock_release_for_write(
1570
0
       internal_handle->read_write_lock,
1571
0
       error ) != 1 )
1572
0
  {
1573
0
    libcerror_error_set(
1574
0
     error,
1575
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1576
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1577
0
     "%s: unable to release read/write lock for writing.",
1578
0
     function );
1579
1580
0
    return( -1 );
1581
0
  }
1582
0
#endif
1583
0
  return( result );
1584
0
}
1585
1586
/* Opens a specific extent data file
1587
 * Returns 1 if successful or -1 on error
1588
 */
1589
int libphdi_handle_open_extent_data_file(
1590
     libphdi_internal_handle_t *internal_handle,
1591
     libbfio_pool_t *file_io_pool,
1592
     int extent_index,
1593
     const char *filename,
1594
     libcerror_error_t **error )
1595
0
{
1596
0
  libbfio_handle_t *file_io_handle = NULL;
1597
0
  static char *function            = "libphdi_handle_open_extent_data_file";
1598
0
  size_t filename_length           = 0;
1599
0
  int bfio_access_flags            = 0;
1600
1601
0
  if( internal_handle == NULL )
1602
0
  {
1603
0
    libcerror_error_set(
1604
0
     error,
1605
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1606
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1607
0
     "%s: invalid handle.",
1608
0
     function );
1609
1610
0
    return( -1 );
1611
0
  }
1612
0
  if( filename == NULL )
1613
0
  {
1614
0
    libcerror_error_set(
1615
0
     error,
1616
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1617
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1618
0
     "%s: invalid filename.",
1619
0
     function );
1620
1621
0
    return( -1 );
1622
0
  }
1623
0
  if( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_READ ) != 0 )
1624
0
  {
1625
0
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
1626
0
  }
1627
0
  if( libbfio_file_initialize(
1628
0
       &file_io_handle,
1629
0
       error ) != 1 )
1630
0
  {
1631
0
    libcerror_error_set(
1632
0
     error,
1633
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1634
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1635
0
     "%s: unable to create file IO handle.",
1636
0
     function );
1637
1638
0
    goto on_error;
1639
0
  }
1640
#if defined( HAVE_DEBUG_OUTPUT )
1641
  if( libbfio_handle_set_track_offsets_read(
1642
       file_io_handle,
1643
       1,
1644
       error ) != 1 )
1645
  {
1646
                libcerror_error_set(
1647
                 error,
1648
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1649
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1650
                 "%s: unable to set track offsets read in file IO handle.",
1651
                 function );
1652
1653
                goto on_error;
1654
  }
1655
#endif
1656
0
  filename_length = narrow_string_length(
1657
0
                     filename );
1658
1659
0
  if( libbfio_file_set_name(
1660
0
       file_io_handle,
1661
0
       filename,
1662
0
       filename_length + 1,
1663
0
       error ) != 1 )
1664
0
  {
1665
0
                libcerror_error_set(
1666
0
                 error,
1667
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1668
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1669
0
                 "%s: unable to set filename in file IO handle.",
1670
0
                 function );
1671
1672
0
                goto on_error;
1673
0
  }
1674
0
  if( libbfio_handle_open(
1675
0
       file_io_handle,
1676
0
       bfio_access_flags,
1677
0
       error ) != 1 )
1678
0
  {
1679
0
    libcerror_error_set(
1680
0
     error,
1681
0
     LIBCERROR_ERROR_DOMAIN_IO,
1682
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
1683
0
     "%s: unable to open file IO handle.",
1684
0
     function );
1685
1686
0
    goto on_error;
1687
0
  }
1688
0
  if( libbfio_pool_set_handle(
1689
0
       file_io_pool,
1690
0
       extent_index,
1691
0
       file_io_handle,
1692
0
       bfio_access_flags,
1693
0
       error ) != 1 )
1694
0
  {
1695
0
    libcerror_error_set(
1696
0
     error,
1697
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1698
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1699
0
     "%s: unable to set file IO handle: %d in pool.",
1700
0
     function,
1701
0
     extent_index );
1702
1703
0
    goto on_error;
1704
0
  }
1705
0
  return( 1 );
1706
1707
0
on_error:
1708
0
  if( file_io_handle != NULL )
1709
0
  {
1710
0
    libbfio_handle_free(
1711
0
     &file_io_handle,
1712
0
     NULL );
1713
0
  }
1714
0
  return( -1 );
1715
0
}
1716
1717
#if defined( HAVE_WIDE_CHARACTER_TYPE )
1718
1719
/* Opens a specific extent data file
1720
 * Returns 1 if successful or -1 on error
1721
 */
1722
int libphdi_handle_open_extent_data_file_wide(
1723
     libphdi_internal_handle_t *internal_handle,
1724
     libbfio_pool_t *file_io_pool,
1725
     int extent_index,
1726
     const wchar_t *filename,
1727
     libcerror_error_t **error )
1728
{
1729
  libbfio_handle_t *file_io_handle = NULL;
1730
  static char *function            = "libphdi_handle_open_extent_data_file_wide";
1731
  size_t filename_length           = 0;
1732
  int bfio_access_flags            = 0;
1733
1734
  if( internal_handle == NULL )
1735
  {
1736
    libcerror_error_set(
1737
     error,
1738
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1739
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1740
     "%s: invalid handle.",
1741
     function );
1742
1743
    return( -1 );
1744
  }
1745
  if( filename == NULL )
1746
  {
1747
    libcerror_error_set(
1748
     error,
1749
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1750
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1751
     "%s: invalid filename.",
1752
     function );
1753
1754
    return( -1 );
1755
  }
1756
  if( ( internal_handle->access_flags & LIBPHDI_ACCESS_FLAG_READ ) != 0 )
1757
  {
1758
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
1759
  }
1760
  if( libbfio_file_initialize(
1761
       &file_io_handle,
1762
       error ) != 1 )
1763
  {
1764
    libcerror_error_set(
1765
     error,
1766
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1767
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1768
     "%s: unable to create file IO handle.",
1769
     function );
1770
1771
                goto on_error;
1772
  }
1773
#if defined( HAVE_DEBUG_OUTPUT )
1774
  if( libbfio_handle_set_track_offsets_read(
1775
       file_io_handle,
1776
       1,
1777
       error ) != 1 )
1778
  {
1779
                libcerror_error_set(
1780
                 error,
1781
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1782
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1783
                 "%s: unable to set track offsets read in file IO handle.",
1784
                 function );
1785
1786
                goto on_error;
1787
  }
1788
#endif
1789
  filename_length = wide_string_length(
1790
                     filename );
1791
1792
  if( libbfio_file_set_name_wide(
1793
       file_io_handle,
1794
       filename,
1795
       filename_length + 1,
1796
       error ) != 1 )
1797
  {
1798
                libcerror_error_set(
1799
                 error,
1800
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1801
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1802
                 "%s: unable to set filename in file IO handle.",
1803
                 function );
1804
1805
                goto on_error;
1806
  }
1807
  if( libbfio_handle_open(
1808
       file_io_handle,
1809
       bfio_access_flags,
1810
       error ) != 1 )
1811
  {
1812
    libcerror_error_set(
1813
     error,
1814
     LIBCERROR_ERROR_DOMAIN_IO,
1815
     LIBCERROR_IO_ERROR_OPEN_FAILED,
1816
     "%s: unable to open file IO handle.",
1817
     function );
1818
1819
    goto on_error;
1820
  }
1821
  if( libbfio_pool_set_handle(
1822
       file_io_pool,
1823
       extent_index,
1824
       file_io_handle,
1825
       bfio_access_flags,
1826
       error ) != 1 )
1827
  {
1828
    libcerror_error_set(
1829
     error,
1830
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1831
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1832
     "%s: unable to set file IO handle: %d in pool.",
1833
     function,
1834
     extent_index );
1835
1836
    goto on_error;
1837
  }
1838
  return( 1 );
1839
1840
on_error:
1841
  if( file_io_handle != NULL )
1842
  {
1843
    libbfio_handle_free(
1844
     &file_io_handle,
1845
     NULL );
1846
  }
1847
  return( -1 );
1848
}
1849
1850
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
1851
1852
/* Closes a handle
1853
 * Returns 0 if successful or -1 on error
1854
 */
1855
int libphdi_handle_close(
1856
     libphdi_handle_t *handle,
1857
     libcerror_error_t **error )
1858
0
{
1859
0
  libphdi_internal_handle_t *internal_handle = NULL;
1860
0
  static char *function                      = "libphdi_handle_close";
1861
0
  int result                                 = 0;
1862
1863
0
  if( handle == NULL )
1864
0
  {
1865
0
    libcerror_error_set(
1866
0
     error,
1867
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1868
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1869
0
     "%s: invalid handle.",
1870
0
     function );
1871
1872
0
    return( -1 );
1873
0
  }
1874
0
  internal_handle = (libphdi_internal_handle_t *) handle;
1875
1876
0
  if( internal_handle->file_io_handle == NULL )
1877
0
  {
1878
0
    libcerror_error_set(
1879
0
     error,
1880
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1881
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1882
0
     "%s: invalid handle - missing file IO handle.",
1883
0
     function );
1884
1885
0
    return( -1 );
1886
0
  }
1887
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
1888
0
  if( libcthreads_read_write_lock_grab_for_write(
1889
0
       internal_handle->read_write_lock,
1890
0
       error ) != 1 )
1891
0
  {
1892
0
    libcerror_error_set(
1893
0
     error,
1894
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1895
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1896
0
     "%s: unable to grab read/write lock for writing.",
1897
0
     function );
1898
1899
0
    return( -1 );
1900
0
  }
1901
0
#endif
1902
#if defined( HAVE_DEBUG_OUTPUT )
1903
  if( libcnotify_verbose != 0 )
1904
  {
1905
    if( internal_handle->file_io_handle_created_in_library != 0 )
1906
    {
1907
      if( libphdi_debug_print_read_offsets(
1908
           internal_handle->file_io_handle,
1909
           error ) != 1 )
1910
      {
1911
        libcerror_error_set(
1912
         error,
1913
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1914
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
1915
         "%s: unable to print the read offsets.",
1916
         function );
1917
1918
        result = -1;
1919
      }
1920
    }
1921
  }
1922
#endif
1923
0
  if( internal_handle->file_io_handle_opened_in_library != 0 )
1924
0
  {
1925
0
    if( libbfio_handle_close(
1926
0
         internal_handle->file_io_handle,
1927
0
         error ) != 0 )
1928
0
    {
1929
0
      libcerror_error_set(
1930
0
       error,
1931
0
       LIBCERROR_ERROR_DOMAIN_IO,
1932
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
1933
0
       "%s: unable to close file IO handle.",
1934
0
       function );
1935
1936
0
      result = -1;
1937
0
    }
1938
0
    internal_handle->file_io_handle_opened_in_library = 0;
1939
0
  }
1940
0
  if( internal_handle->file_io_handle_created_in_library != 0 )
1941
0
  {
1942
0
    if( libbfio_handle_free(
1943
0
         &( internal_handle->file_io_handle ),
1944
0
         error ) != 1 )
1945
0
    {
1946
0
      libcerror_error_set(
1947
0
       error,
1948
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1949
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1950
0
       "%s: unable to free file IO handle.",
1951
0
       function );
1952
1953
0
      result = -1;
1954
0
    }
1955
0
    internal_handle->file_io_handle_created_in_library = 0;
1956
0
  }
1957
0
  internal_handle->file_io_handle = NULL;
1958
1959
0
  if( internal_handle->extent_data_file_io_pool_created_in_library != 0 )
1960
0
  {
1961
0
    if( libbfio_pool_close_all(
1962
0
         internal_handle->extent_data_file_io_pool,
1963
0
         error ) != 0 )
1964
0
    {
1965
0
      libcerror_error_set(
1966
0
       error,
1967
0
       LIBCERROR_ERROR_DOMAIN_IO,
1968
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
1969
0
       "%s: unable to close all files in extent data file IO pool.",
1970
0
       function );
1971
1972
0
      result = -1;
1973
0
    }
1974
0
    if( libbfio_pool_free(
1975
0
         &( internal_handle->extent_data_file_io_pool ),
1976
0
         error ) != 1 )
1977
0
    {
1978
0
      libcerror_error_set(
1979
0
       error,
1980
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1981
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1982
0
       "%s: unable to free extent data file IO pool.",
1983
0
       function );
1984
1985
0
      result = -1;
1986
0
    }
1987
0
    internal_handle->extent_data_file_io_pool_created_in_library = 0;
1988
0
  }
1989
0
  internal_handle->extent_data_file_io_pool = NULL;
1990
0
  internal_handle->current_offset           = 0;
1991
1992
0
  if( libphdi_io_handle_clear(
1993
0
       internal_handle->io_handle,
1994
0
       error ) != 1 )
1995
0
  {
1996
0
    libcerror_error_set(
1997
0
     error,
1998
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1999
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2000
0
     "%s: unable to clear IO handle.",
2001
0
     function );
2002
2003
0
    result = -1;
2004
0
  }
2005
0
  if( libphdi_disk_parameters_free(
2006
0
       &( internal_handle->disk_parameters ),
2007
0
       error ) != 1 )
2008
0
  {
2009
0
    libcerror_error_set(
2010
0
     error,
2011
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2012
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2013
0
     "%s: unable to free disk parameters.",
2014
0
     function );
2015
2016
0
    result = -1;
2017
0
  }
2018
0
  if( libphdi_data_files_clear(
2019
0
       internal_handle->data_files,
2020
0
       error ) != 1 )
2021
0
  {
2022
0
    libcerror_error_set(
2023
0
     error,
2024
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2025
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2026
0
     "%s: unable to clear data files.",
2027
0
     function );
2028
2029
0
    result = -1;
2030
0
  }
2031
0
  if( libfdata_vector_free(
2032
0
       &( internal_handle->data_block_vector ),
2033
0
       error ) != 1 )
2034
0
  {
2035
0
    libcerror_error_set(
2036
0
     error,
2037
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2038
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2039
0
     "%s: unable to free data block vector.",
2040
0
     function );
2041
2042
0
    result = -1;
2043
0
  }
2044
0
  if( libfcache_cache_free(
2045
0
       &( internal_handle->data_block_cache ),
2046
0
       error ) != 1 )
2047
0
  {
2048
0
    libcerror_error_set(
2049
0
     error,
2050
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2051
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2052
0
     "%s: unable to free data block cache.",
2053
0
     function );
2054
2055
0
    result = -1;
2056
0
  }
2057
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
2058
0
  if( libcthreads_read_write_lock_release_for_write(
2059
0
       internal_handle->read_write_lock,
2060
0
       error ) != 1 )
2061
0
  {
2062
0
    libcerror_error_set(
2063
0
     error,
2064
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2065
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2066
0
     "%s: unable to release read/write lock for writing.",
2067
0
     function );
2068
2069
0
    return( -1 );
2070
0
  }
2071
0
#endif
2072
0
  return( result );
2073
0
}
2074
2075
/* Opens a handle for reading
2076
 * Returns 1 if successful or -1 on error
2077
 */
2078
int libphdi_internal_handle_open_read(
2079
     libphdi_internal_handle_t *internal_handle,
2080
     libbfio_handle_t *file_io_handle,
2081
     libcerror_error_t **error )
2082
828
{
2083
828
  libphdi_disk_descriptor_xml_file_t *disk_descriptor_xml_file = NULL;
2084
828
  libphdi_extent_values_t *extent_values                       = NULL;
2085
828
  libphdi_image_values_t *image_values                         = NULL;
2086
828
  static char *function                                        = "libphdi_internal_handle_open_read";
2087
828
  int entry_index                                              = 0;
2088
828
  int extent_index                                             = 0;
2089
828
  int image_index                                              = 0;
2090
828
  int number_of_extents                                        = 0;
2091
828
  int number_of_images                                         = 0;
2092
2093
828
  if( internal_handle == NULL )
2094
0
  {
2095
0
    libcerror_error_set(
2096
0
     error,
2097
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2098
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2099
0
     "%s: invalid handle.",
2100
0
     function );
2101
2102
0
    return( -1 );
2103
0
  }
2104
828
  if( internal_handle->disk_parameters != NULL )
2105
0
  {
2106
0
    libcerror_error_set(
2107
0
     error,
2108
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2109
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2110
0
     "%s: invalid handle - disk parameters value already set.",
2111
0
     function );
2112
2113
0
    return( -1 );
2114
0
  }
2115
828
  if( internal_handle->data_block_vector != NULL )
2116
0
  {
2117
0
    libcerror_error_set(
2118
0
     error,
2119
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2120
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2121
0
     "%s: invalid handle - data block vector value already set.",
2122
0
     function );
2123
2124
0
    return( -1 );
2125
0
  }
2126
828
  if( internal_handle->data_block_cache != NULL )
2127
0
  {
2128
0
    libcerror_error_set(
2129
0
     error,
2130
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2131
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2132
0
     "%s: invalid handle - data block cache value already set.",
2133
0
     function );
2134
2135
0
    return( -1 );
2136
0
  }
2137
#if defined( HAVE_DEBUG_OUTPUT )
2138
  if( libcnotify_verbose != 0 )
2139
  {
2140
    libcnotify_printf(
2141
     "Reading Disk descriptor XML file:\n" );
2142
  }
2143
#endif
2144
828
  if( libphdi_disk_descriptor_xml_file_initialize(
2145
828
       &disk_descriptor_xml_file,
2146
828
       error ) != 1 )
2147
0
  {
2148
0
    libcerror_error_set(
2149
0
     error,
2150
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2151
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2152
0
     "%s: unable to create disk descriptor XML file.",
2153
0
     function );
2154
2155
0
    goto on_error;
2156
0
  }
2157
828
  if( libphdi_disk_descriptor_xml_file_read_file_io_handle(
2158
828
       disk_descriptor_xml_file,
2159
828
       file_io_handle,
2160
828
       error ) != 1 )
2161
750
  {
2162
750
    libcerror_error_set(
2163
750
     error,
2164
750
     LIBCERROR_ERROR_DOMAIN_IO,
2165
750
     LIBCERROR_IO_ERROR_READ_FAILED,
2166
750
     "%s: unable to read disk descriptor XML file.",
2167
750
     function );
2168
2169
750
    goto on_error;
2170
750
  }
2171
78
  if( libphdi_disk_parameters_initialize(
2172
78
       &( internal_handle->disk_parameters ),
2173
78
       error ) != 1 )
2174
0
  {
2175
0
    libcerror_error_set(
2176
0
     error,
2177
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2178
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2179
0
     "%s: unable to create disk parameters.",
2180
0
     function );
2181
2182
0
    goto on_error;
2183
0
  }
2184
78
  if( libphdi_disk_descriptor_xml_file_get_disk_parameters(
2185
78
       disk_descriptor_xml_file,
2186
78
       internal_handle->disk_parameters,
2187
78
       error ) != 1 )
2188
68
  {
2189
68
    libcerror_error_set(
2190
68
     error,
2191
68
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2192
68
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2193
68
     "%s: unable to retrieve disk parameters from disk descriptor XML file.",
2194
68
     function );
2195
2196
68
    goto on_error;
2197
68
  }
2198
10
  if( libphdi_disk_descriptor_xml_file_get_storage_data(
2199
10
       disk_descriptor_xml_file,
2200
10
       internal_handle->extent_values_array,
2201
10
       error ) != 1 )
2202
8
  {
2203
8
    libcerror_error_set(
2204
8
     error,
2205
8
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2206
8
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2207
8
     "%s: unable to retrieve storage data from disk descriptor XML file.",
2208
8
     function );
2209
2210
8
    goto on_error;
2211
8
  }
2212
2
  if( libphdi_disk_descriptor_xml_file_get_disk_type(
2213
2
       disk_descriptor_xml_file,
2214
2
       &( internal_handle->disk_type ),
2215
2
       error ) != 1 )
2216
0
  {
2217
0
    libcerror_error_set(
2218
0
     error,
2219
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2220
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2221
0
     "%s: unable to retrieve disk type from disk descriptor XML file.",
2222
0
     function );
2223
2224
0
    goto on_error;
2225
0
  }
2226
2
  if( libphdi_disk_descriptor_xml_file_get_snapshots(
2227
2
       disk_descriptor_xml_file,
2228
2
       internal_handle->snapshot_values_array,
2229
2
       error ) != 1 )
2230
1
  {
2231
1
    libcerror_error_set(
2232
1
     error,
2233
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2234
1
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2235
1
     "%s: unable to retrieve snapshots from disk descriptor XML file.",
2236
1
     function );
2237
2238
1
    goto on_error;
2239
1
  }
2240
1
  if( libphdi_disk_descriptor_xml_file_free(
2241
1
       &disk_descriptor_xml_file,
2242
1
       error ) != 1 )
2243
0
  {
2244
0
    libcerror_error_set(
2245
0
     error,
2246
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2247
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2248
0
     "%s: unable to free disk descriptor XML file.",
2249
0
     function );
2250
2251
0
    goto on_error;
2252
0
  }
2253
1
  if( libcdata_array_get_number_of_entries(
2254
1
       internal_handle->extent_values_array,
2255
1
       &number_of_extents,
2256
1
       error ) != 1 )
2257
0
  {
2258
0
    libcerror_error_set(
2259
0
     error,
2260
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2261
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2262
0
     "%s: unable to retrieve number of extents.",
2263
0
     function );
2264
2265
0
    goto on_error;
2266
0
  }
2267
1
  if( number_of_extents == 0 )
2268
1
  {
2269
1
    libcerror_error_set(
2270
1
     error,
2271
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2272
1
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2273
1
     "%s: invalid number of extents value out of bounds.",
2274
1
     function );
2275
2276
1
    goto on_error;
2277
1
  }
2278
0
  for( extent_index = 0;
2279
0
       extent_index < number_of_extents;
2280
0
       extent_index++ )
2281
0
  {
2282
0
    if( libcdata_array_get_entry_by_index(
2283
0
         internal_handle->extent_values_array,
2284
0
         extent_index,
2285
0
         (intptr_t **) &extent_values,
2286
0
         error ) != 1 )
2287
0
    {
2288
0
      libcerror_error_set(
2289
0
       error,
2290
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2291
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2292
0
       "%s: unable to retrieve extent values: %d from array.",
2293
0
       function,
2294
0
       extent_index );
2295
2296
0
      goto on_error;
2297
0
    }
2298
0
    if( libphdi_extent_values_get_number_of_images(
2299
0
         extent_values,
2300
0
         &number_of_images,
2301
0
         error ) != 1 )
2302
0
    {
2303
0
      libcerror_error_set(
2304
0
       error,
2305
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2306
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2307
0
       "%s: unable to retrieve number of extents.",
2308
0
       function );
2309
2310
0
      goto on_error;
2311
0
    }
2312
0
    if( number_of_images == 0 )
2313
0
    {
2314
0
      libcerror_error_set(
2315
0
       error,
2316
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2317
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2318
0
       "%s: invalid number of images value out of bounds.",
2319
0
       function );
2320
2321
0
      goto on_error;
2322
0
    }
2323
0
    for( image_index = 0;
2324
0
         image_index < number_of_images;
2325
0
         image_index++ )
2326
0
    {
2327
0
      if( libphdi_extent_values_get_image_values_by_index(
2328
0
           extent_values,
2329
0
           image_index,
2330
0
           &image_values,
2331
0
           error ) != 1 )
2332
0
      {
2333
0
        libcerror_error_set(
2334
0
         error,
2335
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2336
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2337
0
         "%s: unable to retrieve image values: %d from extent values.",
2338
0
         function,
2339
0
         image_index );
2340
2341
0
        goto on_error;
2342
0
      }
2343
0
      image_values->file_io_pool_entry = image_index;
2344
2345
0
      if( libcdata_array_append_entry(
2346
0
           internal_handle->image_values_array,
2347
0
           &entry_index,
2348
0
           (intptr_t *) image_values,
2349
0
           error ) != 1 )
2350
0
      {
2351
0
        libcerror_error_set(
2352
0
         error,
2353
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2354
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2355
0
         "%s: unable to append image values to array.",
2356
0
         function );
2357
2358
0
        goto on_error;
2359
0
      }
2360
0
      image_values = NULL;
2361
0
    }
2362
0
  }
2363
0
  return( 1 );
2364
2365
828
on_error:
2366
828
  if( disk_descriptor_xml_file != NULL )
2367
827
  {
2368
827
    libphdi_disk_descriptor_xml_file_free(
2369
827
     &disk_descriptor_xml_file,
2370
827
     NULL );
2371
827
  }
2372
828
  if( internal_handle->data_block_cache != NULL )
2373
0
  {
2374
0
    libfcache_cache_free(
2375
0
     &( internal_handle->data_block_cache ),
2376
0
     NULL );
2377
0
  }
2378
828
  if( internal_handle->data_block_vector != NULL )
2379
0
  {
2380
0
    libfdata_vector_free(
2381
0
     &( internal_handle->data_block_vector ),
2382
0
     NULL );
2383
0
  }
2384
828
  if( internal_handle->disk_parameters != NULL )
2385
78
  {
2386
78
    libphdi_disk_parameters_free(
2387
78
     &( internal_handle->disk_parameters ),
2388
78
     NULL );
2389
78
  }
2390
828
  return( -1 );
2391
0
}
2392
2393
/* Reads the extent data files
2394
 * Returns 1 if successful or -1 on error
2395
 */
2396
int libphdi_internal_handle_open_read_extent_data_files(
2397
     libphdi_internal_handle_t *internal_handle,
2398
     libbfio_pool_t *file_io_pool,
2399
     libcerror_error_t **error )
2400
0
{
2401
0
  libphdi_extent_values_t *extent_values            = NULL;
2402
0
  libphdi_image_values_t *image_values              = NULL;
2403
0
  libphdi_snapshot_values_t *parent_snapshot_values = NULL;
2404
0
  libphdi_snapshot_values_t *snapshot_values        = NULL;
2405
0
  libphdi_storage_image_t *storage_image            = NULL;
2406
0
  static char *function                             = "libphdi_internal_handle_open_read_extent_data_files";
2407
0
  size64_t image_file_size                          = 0;
2408
0
  int extent_index                                  = 0;
2409
0
  int image_index                                   = 0;
2410
0
  int image_type                                    = 0;
2411
0
  int number_of_extents                             = 0;
2412
0
  int number_of_file_io_handles                     = 0;
2413
0
  int number_of_images                              = 0;
2414
0
  int number_of_snapshots                           = 0;
2415
0
  int parent_snapshot_index                         = 0;
2416
0
  int snapshot_index                                = 0;
2417
2418
0
  if( internal_handle == NULL )
2419
0
  {
2420
0
    libcerror_error_set(
2421
0
     error,
2422
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2423
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2424
0
     "%s: invalid handle.",
2425
0
     function );
2426
2427
0
    return( -1 );
2428
0
  }
2429
0
  if( internal_handle->io_handle == NULL )
2430
0
  {
2431
0
    libcerror_error_set(
2432
0
     error,
2433
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2434
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2435
0
     "%s: invalid handle - missing IO handle.",
2436
0
     function );
2437
2438
0
    return( -1 );
2439
0
  }
2440
0
  if( libbfio_pool_get_number_of_handles(
2441
0
       file_io_pool,
2442
0
       &number_of_file_io_handles,
2443
0
       error ) != 1 )
2444
0
  {
2445
0
    libcerror_error_set(
2446
0
     error,
2447
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2448
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2449
0
     "%s: unable to retrieve the number of file IO handles.",
2450
0
     function );
2451
2452
0
    return( -1 );
2453
0
  }
2454
0
  if( number_of_file_io_handles == 0 )
2455
0
  {
2456
0
    libcerror_error_set(
2457
0
     error,
2458
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2459
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2460
0
     "%s: missing file IO handles.",
2461
0
     function );
2462
2463
0
    goto on_error;
2464
0
  }
2465
0
  if( libcdata_array_get_number_of_entries(
2466
0
       internal_handle->image_values_array,
2467
0
       &number_of_images,
2468
0
       error ) != 1 )
2469
0
  {
2470
0
    libcerror_error_set(
2471
0
     error,
2472
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2473
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2474
0
     "%s: unable to retrieve number of images.",
2475
0
     function );
2476
2477
0
    goto on_error;
2478
0
  }
2479
0
  if( number_of_file_io_handles != number_of_images )
2480
0
  {
2481
0
    libcerror_error_set(
2482
0
     error,
2483
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2484
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2485
0
     "%s: mismatch between number of file IO handles in pool and number of images in metadata.",
2486
0
     function );
2487
2488
0
    goto on_error;
2489
0
  }
2490
0
  if( libcdata_array_get_number_of_entries(
2491
0
       internal_handle->snapshot_values_array,
2492
0
       &number_of_snapshots,
2493
0
       error ) != 1 )
2494
0
  {
2495
0
    libcerror_error_set(
2496
0
     error,
2497
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2498
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2499
0
     "%s: unable to retrieve number of snapshots.",
2500
0
     function );
2501
2502
0
    goto on_error;
2503
0
  }
2504
0
  if( libcdata_array_get_number_of_entries(
2505
0
       internal_handle->extent_values_array,
2506
0
       &number_of_extents,
2507
0
       error ) != 1 )
2508
0
  {
2509
0
    libcerror_error_set(
2510
0
     error,
2511
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2512
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2513
0
     "%s: unable to retrieve number of extents.",
2514
0
     function );
2515
2516
0
    goto on_error;
2517
0
  }
2518
0
  for( snapshot_index = 0;
2519
0
       snapshot_index < number_of_snapshots;
2520
0
       snapshot_index++ )
2521
0
  {
2522
0
    if( libcdata_array_get_entry_by_index(
2523
0
         internal_handle->snapshot_values_array,
2524
0
         snapshot_index,
2525
0
         (intptr_t **) &snapshot_values,
2526
0
         error ) != 1 )
2527
0
    {
2528
0
      libcerror_error_set(
2529
0
       error,
2530
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2531
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2532
0
       "%s: unable to retrieve snapshot values: %d from array.",
2533
0
       function,
2534
0
       snapshot_index );
2535
2536
0
      goto on_error;
2537
0
    }
2538
0
    for( parent_snapshot_index = 0;
2539
0
         parent_snapshot_index < number_of_snapshots;
2540
0
         parent_snapshot_index++ )
2541
0
    {
2542
0
      if( libcdata_array_get_entry_by_index(
2543
0
           internal_handle->snapshot_values_array,
2544
0
           parent_snapshot_index,
2545
0
           (intptr_t **) &parent_snapshot_values,
2546
0
           error ) != 1 )
2547
0
      {
2548
0
        libcerror_error_set(
2549
0
         error,
2550
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2551
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2552
0
         "%s: unable to retrieve snapshot values: %d from array.",
2553
0
         function,
2554
0
         parent_snapshot_index );
2555
2556
0
        goto on_error;
2557
0
      }
2558
0
      if( memory_compare(
2559
0
           snapshot_values->parent_identifier,
2560
0
           parent_snapshot_values->identifier,
2561
0
           16 ) == 0 )
2562
0
      {
2563
0
        snapshot_values->parent_snapshot_values = parent_snapshot_values;
2564
2565
0
        break;
2566
0
      }
2567
0
    }
2568
0
    if( libphdi_extent_table_initialize_extents(
2569
0
         snapshot_values->extent_table,
2570
0
         internal_handle->io_handle,
2571
0
         internal_handle->disk_type,
2572
0
         error ) != 1 )
2573
0
    {
2574
0
      libcerror_error_set(
2575
0
       error,
2576
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2577
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2578
0
       "%s: unable to initialize extent table extents.",
2579
0
       function );
2580
2581
0
      goto on_error;
2582
0
    }
2583
0
    for( extent_index = 0;
2584
0
         extent_index < number_of_extents;
2585
0
         extent_index++ )
2586
0
    {
2587
0
      if( libcdata_array_get_entry_by_index(
2588
0
           internal_handle->extent_values_array,
2589
0
           extent_index,
2590
0
           (intptr_t **) &extent_values,
2591
0
           error ) != 1 )
2592
0
      {
2593
0
        libcerror_error_set(
2594
0
         error,
2595
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2596
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2597
0
         "%s: unable to retrieve extent values: %d from array.",
2598
0
         function,
2599
0
         extent_index );
2600
2601
0
        goto on_error;
2602
0
      }
2603
0
      if( libphdi_extent_values_get_number_of_images(
2604
0
           extent_values,
2605
0
           &number_of_images,
2606
0
           error ) != 1 )
2607
0
      {
2608
0
        libcerror_error_set(
2609
0
         error,
2610
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2611
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2612
0
         "%s: unable to retrieve number of images.",
2613
0
         function );
2614
2615
0
        goto on_error;
2616
0
      }
2617
0
      for( image_index = 0;
2618
0
           image_index < number_of_images;
2619
0
           image_index++ )
2620
0
      {
2621
0
        if( libphdi_extent_values_get_image_values_by_index(
2622
0
             extent_values,
2623
0
             image_index,
2624
0
             &image_values,
2625
0
             error ) != 1 )
2626
0
        {
2627
0
          libcerror_error_set(
2628
0
           error,
2629
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2630
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2631
0
           "%s: unable to retrieve image values: %d from array.",
2632
0
           function,
2633
0
           image_index );
2634
2635
0
          goto on_error;
2636
0
        }
2637
0
        if( memory_compare(
2638
0
             snapshot_values->identifier,
2639
0
             image_values->identifier,
2640
0
             16 ) == 0 )
2641
0
        {
2642
0
          if( libphdi_image_values_get_type(
2643
0
               image_values,
2644
0
               &image_type,
2645
0
               error ) != 1 )
2646
0
          {
2647
0
            libcerror_error_set(
2648
0
             error,
2649
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2650
0
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2651
0
             "%s: unable to retrieve type from image values: %d of extent values: %d.",
2652
0
             function,
2653
0
             image_index,
2654
0
             extent_index );
2655
2656
0
            goto on_error;
2657
0
          }
2658
0
          if( libbfio_pool_get_size(
2659
0
               file_io_pool,
2660
0
               image_values->file_io_pool_entry,
2661
0
               &image_file_size,
2662
0
               error ) != 1 )
2663
0
          {
2664
0
            libcerror_error_set(
2665
0
             error,
2666
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2667
0
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2668
0
             "%s: unable to retrieve size of file IO pool entry: %d.",
2669
0
             function,
2670
0
             image_values->file_io_pool_entry );
2671
2672
0
            goto on_error;
2673
0
          }
2674
0
          if( libphdi_extent_table_append_extent(
2675
0
               snapshot_values->extent_table,
2676
0
               image_type,
2677
0
               image_values->file_io_pool_entry,
2678
0
               image_file_size,
2679
0
               extent_values->offset,
2680
0
               extent_values->size,
2681
0
               error ) != 1 )
2682
0
          {
2683
0
            libcerror_error_set(
2684
0
             error,
2685
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2686
0
             LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2687
0
             "%s: unable to set extent: %d in table.",
2688
0
             function,
2689
0
             extent_index );
2690
2691
0
            goto on_error;
2692
0
          }
2693
0
        }
2694
0
      }
2695
0
    }
2696
0
    if( snapshot_index == 0 )
2697
0
    {
2698
0
         internal_handle->current_snapshot_values = snapshot_values;
2699
0
    }
2700
0
    if( internal_handle->io_handle->abort == 1 )
2701
0
    {
2702
0
      goto on_error;
2703
0
    }
2704
0
  }
2705
0
  return( 1 );
2706
2707
0
on_error:
2708
0
  if( storage_image != NULL )
2709
0
  {
2710
0
    libphdi_storage_image_free(
2711
0
     &storage_image,
2712
0
     NULL );
2713
0
  }
2714
0
  return( -1 );
2715
0
}
2716
2717
/* Reads a block of data at a specific offset into a buffer using a Basic File IO (bfio) pool
2718
 * Returns the number of bytes read or -1 on error
2719
 */
2720
ssize_t libphdi_internal_handle_read_block_from_file_io_pool(
2721
         libphdi_snapshot_values_t *snapshot_values,
2722
         libbfio_pool_t *file_io_pool,
2723
         void *buffer,
2724
         size_t buffer_size,
2725
         off64_t file_offset,
2726
         int level,
2727
         libcerror_error_t **error )
2728
0
{
2729
0
  libphdi_block_descriptor_t *block_descriptor = NULL;
2730
0
  libphdi_storage_image_t *storage_image       = NULL;
2731
0
  static char *function                        = "libphdi_internal_handle_read_block_from_file_io_pool";
2732
0
  size64_t block_size                          = 0;
2733
0
  size_t read_size                             = 0;
2734
0
  ssize_t read_count                           = 0;
2735
0
  off64_t block_offset                         = 0;
2736
0
  off64_t storage_image_data_offset            = 0;
2737
0
  int extent_number                            = 0;
2738
0
  int result                                   = 0;
2739
2740
0
  if( snapshot_values == NULL )
2741
0
  {
2742
0
    libcerror_error_set(
2743
0
     error,
2744
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2745
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2746
0
     "%s: invalid snapshot values.",
2747
0
     function );
2748
2749
0
    return( -1 );
2750
0
  }
2751
0
  if( buffer == NULL )
2752
0
  {
2753
0
    libcerror_error_set(
2754
0
     error,
2755
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2756
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2757
0
     "%s: invalid buffer.",
2758
0
     function );
2759
2760
0
    return( -1 );
2761
0
  }
2762
0
  if( buffer_size > (size_t) SSIZE_MAX )
2763
0
  {
2764
0
    libcerror_error_set(
2765
0
     error,
2766
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2767
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2768
0
     "%s: invalid element data size value exceeds maximum.",
2769
0
     function );
2770
2771
0
    return( -1 );
2772
0
  }
2773
#if defined( HAVE_DEBUG_OUTPUT )
2774
  if( libcnotify_verbose != 0 )
2775
  {
2776
    libcnotify_printf(
2777
     "%s: requested offset: %" PRIi64 " (0x%08" PRIx64 ") at level: %d\n",
2778
     function,
2779
     file_offset,
2780
     file_offset,
2781
     level );
2782
  }
2783
#endif
2784
0
  if( libphdi_extent_table_get_extent_file_at_offset(
2785
0
       snapshot_values->extent_table,
2786
0
       file_offset,
2787
0
       file_io_pool,
2788
0
       &extent_number,
2789
0
       &storage_image_data_offset,
2790
0
       &storage_image,
2791
0
       error ) != 1 )
2792
0
  {
2793
0
    libcerror_error_set(
2794
0
     error,
2795
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2796
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2797
0
     "%s: unable to retrieve extent file at offset: %" PRIi64 " (0x%08" PRIx64 ") from extent table.",
2798
0
     function,
2799
0
     file_offset,
2800
0
     file_offset );
2801
2802
0
    return( -1 );
2803
0
  }
2804
0
  if( libphdi_storage_image_get_block_size(
2805
0
       storage_image,
2806
0
       &block_size,
2807
0
       error ) != 1 )
2808
0
  {
2809
0
    libcerror_error_set(
2810
0
     error,
2811
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2812
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2813
0
     "%s: unable to retrieve block size from storage image.",
2814
0
     function );
2815
2816
0
    return( -1 );
2817
0
  }
2818
0
  result = libphdi_storage_image_get_block_descriptor_at_offset(
2819
0
            storage_image,
2820
0
            storage_image_data_offset,
2821
0
            &block_descriptor,
2822
0
            &block_offset,
2823
0
            error );
2824
2825
0
  if( result == -1 )
2826
0
  {
2827
0
    libcerror_error_set(
2828
0
     error,
2829
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2830
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2831
0
     "%s: unable to retrieve block descriptor at offset: %" PRIi64 " (0x%08" PRIx64 ") from storage image.",
2832
0
     function,
2833
0
     storage_image_data_offset,
2834
0
     storage_image_data_offset );
2835
2836
0
    return( -1 );
2837
0
  }
2838
0
  else if( result == 0 )
2839
0
  {
2840
0
    block_offset = storage_image_data_offset % block_size;
2841
0
  }
2842
0
  read_size = (size_t) ( block_size - block_offset );
2843
2844
0
  if( read_size > buffer_size )
2845
0
  {
2846
0
    read_size = buffer_size;
2847
0
  }
2848
0
  if( result != 0 )
2849
0
  {
2850
#if defined( HAVE_DEBUG_OUTPUT )
2851
    if( libcnotify_verbose != 0 )
2852
    {
2853
      libcnotify_printf(
2854
       "%s: reading block descriptor offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
2855
       function,
2856
       block_descriptor->file_offset,
2857
       block_descriptor->file_offset );
2858
2859
      libcnotify_printf(
2860
       "%s: reading block offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
2861
       function,
2862
       block_offset,
2863
       block_offset );
2864
2865
      libcnotify_printf(
2866
       "%s: reading from file IO pool entry: %d\n",
2867
       function,
2868
       block_descriptor->file_io_pool_entry );
2869
2870
      libcnotify_printf(
2871
       "%s: reading from offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
2872
       function,
2873
       block_descriptor->file_offset + block_offset,
2874
       block_descriptor->file_offset + block_offset );
2875
    }
2876
#endif
2877
0
    read_count = libbfio_pool_read_buffer_at_offset(
2878
0
                  file_io_pool,
2879
0
                  block_descriptor->file_io_pool_entry,
2880
0
                  buffer,
2881
0
                  read_size,
2882
0
                  block_descriptor->file_offset + block_offset,
2883
0
                  error );
2884
2885
0
    if( read_count == -1 )
2886
0
    {
2887
0
      libcerror_error_set(
2888
0
       error,
2889
0
       LIBCERROR_ERROR_DOMAIN_IO,
2890
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2891
0
       "%s: unable to read data from file IO pool entry: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2892
0
       function,
2893
0
       block_descriptor->file_io_pool_entry,
2894
0
       block_descriptor->file_offset + block_offset,
2895
0
       block_descriptor->file_offset + block_offset );
2896
2897
0
      return( -1 );
2898
0
    }
2899
0
  }
2900
0
  else if( snapshot_values->parent_snapshot_values != NULL )
2901
0
  {
2902
0
    read_count = libphdi_internal_handle_read_block_from_file_io_pool(
2903
0
            snapshot_values->parent_snapshot_values,
2904
0
                  file_io_pool,
2905
0
            buffer,
2906
0
            read_size,
2907
0
            file_offset,
2908
0
            level + 1,
2909
0
            error );
2910
2911
0
    if( read_count == -1 )
2912
0
    {
2913
0
      libcerror_error_set(
2914
0
       error,
2915
0
       LIBCERROR_ERROR_DOMAIN_IO,
2916
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2917
0
       "%s: unable to read buffer from parent snapshot at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2918
0
       function,
2919
0
       file_offset,
2920
0
       file_offset );
2921
2922
0
      return( -1 );
2923
0
    }
2924
0
  }
2925
0
  else
2926
0
  {
2927
0
    if( memory_set(
2928
0
         buffer,
2929
0
         0,
2930
0
         read_size ) == NULL )
2931
0
    {
2932
0
      libcerror_error_set(
2933
0
       error,
2934
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2935
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2936
0
       "%s: unable to fill buffer with sparse block.",
2937
0
       function );
2938
2939
0
      return( -1 );
2940
0
    }
2941
0
    read_count = (ssize_t) read_size;
2942
0
  }
2943
0
  return( read_count );
2944
0
}
2945
2946
/* Reads (media) data at the current offset into a buffer using a Basic File IO (bfio) pool
2947
 * This function is not multi-thread safe acquire write lock before call
2948
 * Returns the number of bytes read or -1 on error
2949
 */
2950
ssize_t libphdi_internal_handle_read_buffer_from_file_io_pool(
2951
         libphdi_internal_handle_t *internal_handle,
2952
         libbfio_pool_t *file_io_pool,
2953
         void *buffer,
2954
         size_t buffer_size,
2955
         libcerror_error_t **error )
2956
0
{
2957
0
  static char *function = "libphdi_internal_handle_read_buffer_from_file_io_pool";
2958
0
  size_t buffer_offset  = 0;
2959
0
  size_t read_size      = 0;
2960
0
  ssize_t read_count    = 0;
2961
2962
0
  if( internal_handle == NULL )
2963
0
  {
2964
0
    libcerror_error_set(
2965
0
     error,
2966
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2967
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2968
0
     "%s: invalid handle.",
2969
0
     function );
2970
2971
0
    return( -1 );
2972
0
  }
2973
0
  if( internal_handle->disk_parameters == NULL )
2974
0
  {
2975
0
    libcerror_error_set(
2976
0
     error,
2977
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2978
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2979
0
     "%s: invalid handle - missing disk parameters.",
2980
0
     function );
2981
2982
0
    return( -1 );
2983
0
  }
2984
0
  if( internal_handle->current_snapshot_values == NULL )
2985
0
  {
2986
0
    libcerror_error_set(
2987
0
     error,
2988
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2989
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2990
0
     "%s: invalid handle - missing current snapshot values.",
2991
0
     function );
2992
2993
0
    return( -1 );
2994
0
  }
2995
0
  if( internal_handle->current_offset < 0 )
2996
0
  {
2997
0
    libcerror_error_set(
2998
0
     error,
2999
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3000
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3001
0
     "%s: invalid handle - invalid IO handle - current offset value out of bounds.",
3002
0
     function );
3003
3004
0
    return( -1 );
3005
0
  }
3006
0
  if( buffer == NULL )
3007
0
  {
3008
0
    libcerror_error_set(
3009
0
     error,
3010
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3011
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3012
0
     "%s: invalid buffer.",
3013
0
     function );
3014
3015
0
    return( -1 );
3016
0
  }
3017
0
  if( buffer_size > (size_t) SSIZE_MAX )
3018
0
  {
3019
0
    libcerror_error_set(
3020
0
     error,
3021
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3022
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3023
0
     "%s: invalid element data size value exceeds maximum.",
3024
0
     function );
3025
3026
0
    return( -1 );
3027
0
  }
3028
0
  internal_handle->io_handle->abort = 0;
3029
3030
#if defined( HAVE_DEBUG_OUTPUT )
3031
  if( libcnotify_verbose != 0 )
3032
  {
3033
    libcnotify_printf(
3034
     "%s: requested offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
3035
     function,
3036
     internal_handle->current_offset,
3037
     internal_handle->current_offset );
3038
  }
3039
#endif
3040
0
  if( (size64_t) internal_handle->current_offset >= internal_handle->disk_parameters->media_size )
3041
0
  {
3042
0
    return( 0 );
3043
0
  }
3044
0
  if( internal_handle->current_snapshot_values->extent_table->extent_files_stream != NULL )
3045
0
  {
3046
0
    read_size = buffer_size;
3047
3048
0
    if( ( (size64_t) read_size > internal_handle->disk_parameters->media_size )
3049
0
     || ( (size64_t) internal_handle->current_offset > ( internal_handle->disk_parameters->media_size - read_size ) ) )
3050
0
    {
3051
0
      read_size = (size_t) ( internal_handle->disk_parameters->media_size - internal_handle->current_offset );
3052
0
    }
3053
0
    read_count = libfdata_stream_read_buffer_at_offset(
3054
0
                  internal_handle->current_snapshot_values->extent_table->extent_files_stream,
3055
0
            (intptr_t *) file_io_pool,
3056
0
            (uint8_t *) buffer,
3057
0
            read_size,
3058
0
            internal_handle->current_offset,
3059
0
            0,
3060
0
            error );
3061
3062
0
    if( read_count != (ssize_t) read_size )
3063
0
    {
3064
0
      libcerror_error_set(
3065
0
       error,
3066
0
       LIBCERROR_ERROR_DOMAIN_IO,
3067
0
       LIBCERROR_IO_ERROR_READ_FAILED,
3068
0
       "%s: unable to read buffer from extent files stream at offset: %" PRIi64 " (0x%" PRIx64 ").",
3069
0
       function,
3070
0
       internal_handle->current_offset,
3071
0
       internal_handle->current_offset );
3072
3073
0
      return( -1 );
3074
0
    }
3075
0
    buffer_offset = read_size;
3076
3077
0
    internal_handle->current_offset += (off64_t) read_size;
3078
0
  }
3079
0
  else
3080
0
  {
3081
0
    while( buffer_offset < buffer_size )
3082
0
    {
3083
0
      read_size = buffer_size - buffer_offset;
3084
3085
0
      if( ( (size64_t) read_size > internal_handle->disk_parameters->media_size )
3086
0
       || ( (size64_t) internal_handle->current_offset > ( internal_handle->disk_parameters->media_size - read_size ) ) )
3087
0
      {
3088
0
        read_size = (size_t) ( internal_handle->disk_parameters->media_size - internal_handle->current_offset );
3089
0
      }
3090
0
      read_count = libphdi_internal_handle_read_block_from_file_io_pool(
3091
0
              internal_handle->current_snapshot_values,
3092
0
                    file_io_pool,
3093
0
              &(( (uint8_t *) buffer )[ buffer_offset ] ),
3094
0
              read_size,
3095
0
              internal_handle->current_offset,
3096
0
              0,
3097
0
              error );
3098
3099
0
      if( read_count == -1 )
3100
0
      {
3101
0
        libcerror_error_set(
3102
0
         error,
3103
0
         LIBCERROR_ERROR_DOMAIN_IO,
3104
0
         LIBCERROR_IO_ERROR_READ_FAILED,
3105
0
         "%s: unable to read buffer from current snapshot.",
3106
0
         function );
3107
3108
0
        return( -1 );
3109
0
      }
3110
0
      buffer_offset += read_count;
3111
3112
0
      internal_handle->current_offset += (off64_t) read_count;
3113
3114
0
      if( (size64_t) internal_handle->current_offset >= internal_handle->disk_parameters->media_size )
3115
0
      {
3116
0
        break;
3117
0
      }
3118
0
      if( internal_handle->io_handle->abort != 0 )
3119
0
      {
3120
0
        break;
3121
0
      }
3122
0
    }
3123
0
  }
3124
0
  return( (ssize_t) buffer_offset );
3125
0
}
3126
3127
/* Reads (media) data from the current offset into a buffer
3128
 * Returns the number of bytes read or -1 on error
3129
 */
3130
ssize_t libphdi_handle_read_buffer(
3131
         libphdi_handle_t *handle,
3132
         void *buffer,
3133
         size_t buffer_size,
3134
         libcerror_error_t **error )
3135
0
{
3136
0
  libphdi_internal_handle_t *internal_handle = NULL;
3137
0
  static char *function                      = "libphdi_handle_read_buffer";
3138
0
  ssize_t read_count                         = 0;
3139
3140
0
  if( handle == NULL )
3141
0
  {
3142
0
    libcerror_error_set(
3143
0
     error,
3144
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3145
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3146
0
     "%s: invalid handle.",
3147
0
     function );
3148
3149
0
    return( -1 );
3150
0
  }
3151
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3152
3153
0
  if( internal_handle->extent_data_file_io_pool == NULL )
3154
0
  {
3155
0
    libcerror_error_set(
3156
0
     error,
3157
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3158
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3159
0
     "%s: invalid handle - missing extent data file IO pool.",
3160
0
     function );
3161
3162
0
    return( -1 );
3163
0
  }
3164
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3165
0
  if( libcthreads_read_write_lock_grab_for_write(
3166
0
       internal_handle->read_write_lock,
3167
0
       error ) != 1 )
3168
0
  {
3169
0
    libcerror_error_set(
3170
0
     error,
3171
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3172
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3173
0
     "%s: unable to grab read/write lock for writing.",
3174
0
     function );
3175
3176
0
    return( -1 );
3177
0
  }
3178
0
#endif
3179
0
  read_count = libphdi_internal_handle_read_buffer_from_file_io_pool(
3180
0
          internal_handle,
3181
0
                internal_handle->extent_data_file_io_pool,
3182
0
          buffer,
3183
0
          buffer_size,
3184
0
          error );
3185
3186
0
  if( read_count == -1 )
3187
0
  {
3188
0
    libcerror_error_set(
3189
0
     error,
3190
0
     LIBCERROR_ERROR_DOMAIN_IO,
3191
0
     LIBCERROR_IO_ERROR_READ_FAILED,
3192
0
     "%s: unable to read buffer.",
3193
0
     function );
3194
3195
0
    read_count = -1;
3196
0
  }
3197
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3198
0
  if( libcthreads_read_write_lock_release_for_write(
3199
0
       internal_handle->read_write_lock,
3200
0
       error ) != 1 )
3201
0
  {
3202
0
    libcerror_error_set(
3203
0
     error,
3204
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3205
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3206
0
     "%s: unable to release read/write lock for writing.",
3207
0
     function );
3208
3209
0
    return( -1 );
3210
0
  }
3211
0
#endif
3212
0
  return( read_count );
3213
0
}
3214
3215
/* Reads (media) data at a specific offset
3216
 * Returns the number of bytes read or -1 on error
3217
 */
3218
ssize_t libphdi_handle_read_buffer_at_offset(
3219
         libphdi_handle_t *handle,
3220
         void *buffer,
3221
         size_t buffer_size,
3222
         off64_t offset,
3223
         libcerror_error_t **error )
3224
0
{
3225
0
  libphdi_internal_handle_t *internal_handle = NULL;
3226
0
  static char *function                      = "libphdi_handle_read_buffer_at_offset";
3227
0
  ssize_t read_count                         = 0;
3228
3229
0
  if( handle == NULL )
3230
0
  {
3231
0
    libcerror_error_set(
3232
0
     error,
3233
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3234
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3235
0
     "%s: invalid handle.",
3236
0
     function );
3237
3238
0
    return( -1 );
3239
0
  }
3240
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3241
3242
0
  if( internal_handle->extent_data_file_io_pool == NULL )
3243
0
  {
3244
0
    libcerror_error_set(
3245
0
     error,
3246
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3247
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3248
0
     "%s: invalid handle - missing extent data file IO pool.",
3249
0
     function );
3250
3251
0
    return( -1 );
3252
0
  }
3253
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3254
0
  if( libcthreads_read_write_lock_grab_for_write(
3255
0
       internal_handle->read_write_lock,
3256
0
       error ) != 1 )
3257
0
  {
3258
0
    libcerror_error_set(
3259
0
     error,
3260
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3261
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3262
0
     "%s: unable to grab read/write lock for writing.",
3263
0
     function );
3264
3265
0
    return( -1 );
3266
0
  }
3267
0
#endif
3268
0
  if( libphdi_internal_handle_seek_offset(
3269
0
       internal_handle,
3270
0
       offset,
3271
0
       SEEK_SET,
3272
0
       error ) == -1 )
3273
0
  {
3274
0
    libcerror_error_set(
3275
0
     error,
3276
0
     LIBCERROR_ERROR_DOMAIN_IO,
3277
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
3278
0
     "%s: unable to seek offset.",
3279
0
     function );
3280
3281
0
    read_count = -1;
3282
0
  }
3283
0
  else
3284
0
  {
3285
0
    read_count = libphdi_internal_handle_read_buffer_from_file_io_pool(
3286
0
            internal_handle,
3287
0
                  internal_handle->extent_data_file_io_pool,
3288
0
            buffer,
3289
0
            buffer_size,
3290
0
            error );
3291
3292
0
    if( read_count == -1 )
3293
0
    {
3294
0
      libcerror_error_set(
3295
0
       error,
3296
0
       LIBCERROR_ERROR_DOMAIN_IO,
3297
0
       LIBCERROR_IO_ERROR_READ_FAILED,
3298
0
       "%s: unable to read buffer.",
3299
0
       function );
3300
3301
0
      read_count = -1;
3302
0
    }
3303
0
  }
3304
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3305
0
  if( libcthreads_read_write_lock_release_for_write(
3306
0
       internal_handle->read_write_lock,
3307
0
       error ) != 1 )
3308
0
  {
3309
0
    libcerror_error_set(
3310
0
     error,
3311
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3312
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3313
0
     "%s: unable to release read/write lock for writing.",
3314
0
     function );
3315
3316
0
    return( -1 );
3317
0
  }
3318
0
#endif
3319
0
  return( read_count );
3320
0
}
3321
3322
/* Seeks a certain offset of the (media) data
3323
 * This function is not multi-thread safe acquire write lock before call
3324
 * Returns the offset if seek is successful or -1 on error
3325
 */
3326
off64_t libphdi_internal_handle_seek_offset(
3327
         libphdi_internal_handle_t *internal_handle,
3328
         off64_t offset,
3329
         int whence,
3330
         libcerror_error_t **error )
3331
0
{
3332
0
  static char *function = "libphdi_handle_seek_offset";
3333
3334
0
  if( internal_handle == NULL )
3335
0
  {
3336
0
    libcerror_error_set(
3337
0
     error,
3338
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3339
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3340
0
     "%s: invalid handle.",
3341
0
     function );
3342
3343
0
    return( -1 );
3344
0
  }
3345
0
  if( internal_handle->disk_parameters == NULL )
3346
0
  {
3347
0
    libcerror_error_set(
3348
0
     error,
3349
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3350
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3351
0
     "%s: invalid handle - missing disk parameters.",
3352
0
     function );
3353
3354
0
    return( -1 );
3355
0
  }
3356
0
  if( ( whence != SEEK_CUR )
3357
0
   && ( whence != SEEK_END )
3358
0
   && ( whence != SEEK_SET ) )
3359
0
  {
3360
0
    libcerror_error_set(
3361
0
     error,
3362
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3363
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3364
0
     "%s: unsupported whence.",
3365
0
     function );
3366
3367
0
    return( -1 );
3368
0
  }
3369
0
  if( whence == SEEK_CUR )
3370
0
  {
3371
0
    offset += internal_handle->current_offset;
3372
0
  }
3373
0
  else if( whence == SEEK_END )
3374
0
  {
3375
0
    offset += (off64_t) internal_handle->disk_parameters->media_size;
3376
0
  }
3377
0
  if( offset < 0 )
3378
0
  {
3379
0
    libcerror_error_set(
3380
0
     error,
3381
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3382
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
3383
0
     "%s: invalid offset value out of bounds.",
3384
0
     function );
3385
3386
0
    return( -1 );
3387
0
  }
3388
0
  internal_handle->current_offset = offset;
3389
3390
0
  return( offset );
3391
0
}
3392
3393
/* Seeks a certain offset of the (media) data
3394
 * Returns the offset if seek is successful or -1 on error
3395
 */
3396
off64_t libphdi_handle_seek_offset(
3397
         libphdi_handle_t *handle,
3398
         off64_t offset,
3399
         int whence,
3400
         libcerror_error_t **error )
3401
0
{
3402
0
  libphdi_internal_handle_t *internal_handle = NULL;
3403
0
  static char *function                      = "libphdi_handle_seek_offset";
3404
3405
0
  if( handle == NULL )
3406
0
  {
3407
0
    libcerror_error_set(
3408
0
     error,
3409
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3410
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3411
0
     "%s: invalid handle.",
3412
0
     function );
3413
3414
0
    return( -1 );
3415
0
  }
3416
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3417
3418
0
  if( internal_handle->extent_data_file_io_pool == NULL )
3419
0
  {
3420
0
    libcerror_error_set(
3421
0
     error,
3422
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3423
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3424
0
     "%s: invalid handle - missing extent data file IO pool.",
3425
0
     function );
3426
3427
0
    return( -1 );
3428
0
  }
3429
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3430
0
  if( libcthreads_read_write_lock_grab_for_write(
3431
0
       internal_handle->read_write_lock,
3432
0
       error ) != 1 )
3433
0
  {
3434
0
    libcerror_error_set(
3435
0
     error,
3436
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3437
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3438
0
     "%s: unable to grab read/write lock for writing.",
3439
0
     function );
3440
3441
0
    return( -1 );
3442
0
  }
3443
0
#endif
3444
0
  offset = libphdi_internal_handle_seek_offset(
3445
0
            internal_handle,
3446
0
            offset,
3447
0
            whence,
3448
0
            error );
3449
3450
0
  if( offset == -1 )
3451
0
  {
3452
0
    libcerror_error_set(
3453
0
     error,
3454
0
     LIBCERROR_ERROR_DOMAIN_IO,
3455
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
3456
0
     "%s: unable to seek offset.",
3457
0
     function );
3458
3459
0
    offset = -1;
3460
0
  }
3461
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3462
0
  if( libcthreads_read_write_lock_release_for_write(
3463
0
       internal_handle->read_write_lock,
3464
0
       error ) != 1 )
3465
0
  {
3466
0
    libcerror_error_set(
3467
0
     error,
3468
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3469
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3470
0
     "%s: unable to release read/write lock for writing.",
3471
0
     function );
3472
3473
0
    return( -1 );
3474
0
  }
3475
0
#endif
3476
0
  return( offset );
3477
0
}
3478
3479
/* Retrieves the current offset of the (media) data
3480
 * Returns 1 if successful or -1 on error
3481
 */
3482
int libphdi_handle_get_offset(
3483
     libphdi_handle_t *handle,
3484
     off64_t *offset,
3485
     libcerror_error_t **error )
3486
0
{
3487
0
  libphdi_internal_handle_t *internal_handle = NULL;
3488
0
  static char *function                      = "libphdi_handle_get_offset";
3489
3490
0
  if( handle == NULL )
3491
0
  {
3492
0
    libcerror_error_set(
3493
0
     error,
3494
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3495
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3496
0
     "%s: invalid handle.",
3497
0
     function );
3498
3499
0
    return( -1 );
3500
0
  }
3501
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3502
3503
0
  if( internal_handle->file_io_handle == NULL )
3504
0
  {
3505
0
    libcerror_error_set(
3506
0
     error,
3507
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3508
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3509
0
     "%s: invalid handle - missing file IO handle.",
3510
0
     function );
3511
3512
0
    return( -1 );
3513
0
  }
3514
0
  if( offset == NULL )
3515
0
  {
3516
0
    libcerror_error_set(
3517
0
     error,
3518
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3519
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3520
0
     "%s: invalid offset.",
3521
0
     function );
3522
3523
0
    return( -1 );
3524
0
  }
3525
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3526
0
  if( libcthreads_read_write_lock_grab_for_read(
3527
0
       internal_handle->read_write_lock,
3528
0
       error ) != 1 )
3529
0
  {
3530
0
    libcerror_error_set(
3531
0
     error,
3532
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3533
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3534
0
     "%s: unable to grab read/write lock for reading.",
3535
0
     function );
3536
3537
0
    return( -1 );
3538
0
  }
3539
0
#endif
3540
0
  *offset = internal_handle->current_offset;
3541
3542
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3543
0
  if( libcthreads_read_write_lock_release_for_read(
3544
0
       internal_handle->read_write_lock,
3545
0
       error ) != 1 )
3546
0
  {
3547
0
    libcerror_error_set(
3548
0
     error,
3549
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3550
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3551
0
     "%s: unable to release read/write lock for reading.",
3552
0
     function );
3553
3554
0
    return( -1 );
3555
0
  }
3556
0
#endif
3557
0
  return( 1 );
3558
0
}
3559
3560
/* Sets the maximum number of (concurrent) open file handles
3561
 * Returns 1 if successful or -1 on error
3562
 */
3563
int libphdi_handle_set_maximum_number_of_open_handles(
3564
     libphdi_handle_t *handle,
3565
     int maximum_number_of_open_handles,
3566
     libcerror_error_t **error )
3567
0
{
3568
0
  libphdi_internal_handle_t *internal_handle = NULL;
3569
0
  static char *function                      = "libphdi_handle_set_maximum_number_of_open_handles";
3570
0
  int result                                 = 1;
3571
3572
0
  if( handle == NULL )
3573
0
  {
3574
0
    libcerror_error_set(
3575
0
     error,
3576
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3577
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3578
0
     "%s: invalid handle.",
3579
0
     function );
3580
3581
0
    return( -1 );
3582
0
  }
3583
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3584
3585
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3586
0
  if( libcthreads_read_write_lock_grab_for_write(
3587
0
       internal_handle->read_write_lock,
3588
0
       error ) != 1 )
3589
0
  {
3590
0
    libcerror_error_set(
3591
0
     error,
3592
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3593
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3594
0
     "%s: unable to grab read/write lock for writing.",
3595
0
     function );
3596
3597
0
    return( -1 );
3598
0
  }
3599
0
#endif
3600
0
  if( internal_handle->extent_data_file_io_pool != NULL )
3601
0
  {
3602
0
    if( libbfio_pool_set_maximum_number_of_open_handles(
3603
0
         internal_handle->extent_data_file_io_pool,
3604
0
         maximum_number_of_open_handles,
3605
0
         error ) != 1 )
3606
0
    {
3607
0
      libcerror_error_set(
3608
0
       error,
3609
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3610
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3611
0
       "%s: unable to set maximum number of open handles in extent data file IO pool.",
3612
0
       function );
3613
3614
0
      result = -1;
3615
0
    }
3616
0
  }
3617
0
  if( result == 1 )
3618
0
  {
3619
0
    internal_handle->maximum_number_of_open_handles = maximum_number_of_open_handles;
3620
0
  }
3621
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3622
0
  if( libcthreads_read_write_lock_release_for_write(
3623
0
       internal_handle->read_write_lock,
3624
0
       error ) != 1 )
3625
0
  {
3626
0
    libcerror_error_set(
3627
0
     error,
3628
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3629
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3630
0
     "%s: unable to release read/write lock for writing.",
3631
0
     function );
3632
3633
0
    return( -1 );
3634
0
  }
3635
0
#endif
3636
0
  return( result );
3637
0
}
3638
3639
/* Sets the path to the extent data files
3640
 * Returns 1 if successful or -1 on error
3641
 */
3642
int libphdi_handle_set_extent_data_files_path(
3643
     libphdi_handle_t *handle,
3644
     const char *path,
3645
     size_t path_length,
3646
     libcerror_error_t **error )
3647
0
{
3648
0
  libphdi_internal_handle_t *internal_handle = NULL;
3649
0
  static char *function                      = "libphdi_handle_set_extent_data_files_path";
3650
0
  int result                                 = 1;
3651
3652
0
  if( handle == NULL )
3653
0
  {
3654
0
    libcerror_error_set(
3655
0
     error,
3656
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3657
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3658
0
     "%s: invalid handle.",
3659
0
     function );
3660
3661
0
    return( -1 );
3662
0
  }
3663
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3664
3665
0
  if( path == NULL )
3666
0
  {
3667
0
    libcerror_error_set(
3668
0
     error,
3669
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3670
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3671
0
     "%s: invalid path.",
3672
0
     function );
3673
3674
0
    return( -1 );
3675
0
  }
3676
0
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
3677
0
  {
3678
0
    libcerror_error_set(
3679
0
     error,
3680
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3681
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3682
0
     "%s: invalid path length value exceeds maximum.",
3683
0
     function );
3684
3685
0
    return( -1 );
3686
0
  }
3687
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3688
0
  if( libcthreads_read_write_lock_grab_for_write(
3689
0
       internal_handle->read_write_lock,
3690
0
       error ) != 1 )
3691
0
  {
3692
0
    libcerror_error_set(
3693
0
     error,
3694
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3695
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3696
0
     "%s: unable to grab read/write lock for writing.",
3697
0
     function );
3698
3699
0
    return( -1 );
3700
0
  }
3701
0
#endif
3702
0
  if( libphdi_data_files_set_path(
3703
0
       internal_handle->data_files,
3704
0
       path,
3705
0
       path_length,
3706
0
       error ) != 1 )
3707
0
  {
3708
0
    libcerror_error_set(
3709
0
     error,
3710
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3711
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3712
0
     "%s: unable to set data files path.",
3713
0
     function );
3714
3715
0
    result = -1;
3716
0
  }
3717
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3718
0
  if( libcthreads_read_write_lock_release_for_write(
3719
0
       internal_handle->read_write_lock,
3720
0
       error ) != 1 )
3721
0
  {
3722
0
    libcerror_error_set(
3723
0
     error,
3724
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3725
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3726
0
     "%s: unable to release read/write lock for writing.",
3727
0
     function );
3728
3729
0
    return( -1 );
3730
0
  }
3731
0
#endif
3732
0
  return( result );
3733
0
}
3734
3735
#if defined( HAVE_WIDE_CHARACTER_TYPE )
3736
3737
/* Sets the path to the extent data files
3738
 * Returns 1 if successful or -1 on error
3739
 */
3740
int libphdi_handle_set_extent_data_files_path_wide(
3741
     libphdi_handle_t *handle,
3742
     const wchar_t *path,
3743
     size_t path_length,
3744
     libcerror_error_t **error )
3745
{
3746
  libphdi_internal_handle_t *internal_handle = NULL;
3747
  static char *function                      = "libphdi_handle_set_extent_data_files_path_wide";
3748
  int result                                 = 1;
3749
3750
  if( handle == NULL )
3751
  {
3752
    libcerror_error_set(
3753
     error,
3754
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3755
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3756
     "%s: invalid handle.",
3757
     function );
3758
3759
    return( -1 );
3760
  }
3761
  internal_handle = (libphdi_internal_handle_t *) handle;
3762
3763
  if( path == NULL )
3764
  {
3765
    libcerror_error_set(
3766
     error,
3767
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3768
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3769
     "%s: invalid path.",
3770
     function );
3771
3772
    return( -1 );
3773
  }
3774
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
3775
  {
3776
    libcerror_error_set(
3777
     error,
3778
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3779
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3780
     "%s: invalid path length value exceeds maximum.",
3781
     function );
3782
3783
    return( -1 );
3784
  }
3785
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3786
  if( libcthreads_read_write_lock_grab_for_write(
3787
       internal_handle->read_write_lock,
3788
       error ) != 1 )
3789
  {
3790
    libcerror_error_set(
3791
     error,
3792
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3793
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3794
     "%s: unable to grab read/write lock for writing.",
3795
     function );
3796
3797
    return( -1 );
3798
  }
3799
#endif
3800
  if( libphdi_data_files_set_path_wide(
3801
       internal_handle->data_files,
3802
       path,
3803
       path_length,
3804
       error ) != 1 )
3805
  {
3806
    libcerror_error_set(
3807
     error,
3808
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3809
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3810
     "%s: unable to set data files path.",
3811
     function );
3812
3813
    result = -1;
3814
  }
3815
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3816
  if( libcthreads_read_write_lock_release_for_write(
3817
       internal_handle->read_write_lock,
3818
       error ) != 1 )
3819
  {
3820
    libcerror_error_set(
3821
     error,
3822
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3823
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3824
     "%s: unable to release read/write lock for writing.",
3825
     function );
3826
3827
    return( -1 );
3828
  }
3829
#endif
3830
  return( result );
3831
}
3832
3833
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
3834
3835
/* Retrieves the number of media size
3836
 * Returns 1 if successful or -1 on error
3837
 */
3838
int libphdi_handle_get_media_size(
3839
     libphdi_handle_t *handle,
3840
     size64_t *media_size,
3841
     libcerror_error_t **error )
3842
0
{
3843
0
  libphdi_internal_handle_t *internal_handle = NULL;
3844
0
  static char *function                      = "libphdi_handle_get_media_size";
3845
0
  int result                                 = 1;
3846
3847
0
  if( handle == NULL )
3848
0
  {
3849
0
    libcerror_error_set(
3850
0
     error,
3851
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3852
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3853
0
     "%s: invalid handle.",
3854
0
     function );
3855
3856
0
    return( -1 );
3857
0
  }
3858
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3859
3860
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3861
0
  if( libcthreads_read_write_lock_grab_for_read(
3862
0
       internal_handle->read_write_lock,
3863
0
       error ) != 1 )
3864
0
  {
3865
0
    libcerror_error_set(
3866
0
     error,
3867
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3868
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3869
0
     "%s: unable to grab read/write lock for reading.",
3870
0
     function );
3871
3872
0
    return( -1 );
3873
0
  }
3874
0
#endif
3875
0
  if( libphdi_disk_parameters_get_media_size(
3876
0
       internal_handle->disk_parameters,
3877
0
       media_size,
3878
0
       error ) != 1 )
3879
0
  {
3880
0
    libcerror_error_set(
3881
0
     error,
3882
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3883
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3884
0
     "%s: unable to retrieve media size from disk parameters.",
3885
0
     function );
3886
3887
0
    result = -1;
3888
0
  }
3889
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3890
0
  if( libcthreads_read_write_lock_release_for_read(
3891
0
       internal_handle->read_write_lock,
3892
0
       error ) != 1 )
3893
0
  {
3894
0
    libcerror_error_set(
3895
0
     error,
3896
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3897
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3898
0
     "%s: unable to release read/write lock for reading.",
3899
0
     function );
3900
3901
0
    return( -1 );
3902
0
  }
3903
0
#endif
3904
0
  return( result );
3905
0
}
3906
3907
/* Retrieves the size of the UTF-8 encoded name
3908
 * The returned size includes the end of string character
3909
 * Returns 1 if successful, 0 if not available or -1 on error
3910
 */
3911
int libphdi_handle_get_utf8_name_size(
3912
     libphdi_handle_t *handle,
3913
     size_t *utf8_string_size,
3914
     libcerror_error_t **error )
3915
0
{
3916
0
  libphdi_internal_handle_t *internal_handle = NULL;
3917
0
  static char *function                      = "libphdi_handle_get_utf8_name_size";
3918
0
  int result                                 = 0;
3919
3920
0
  if( handle == NULL )
3921
0
  {
3922
0
    libcerror_error_set(
3923
0
     error,
3924
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3925
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3926
0
     "%s: invalid handle.",
3927
0
     function );
3928
3929
0
    return( -1 );
3930
0
  }
3931
0
  internal_handle = (libphdi_internal_handle_t *) handle;
3932
3933
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3934
0
  if( libcthreads_read_write_lock_grab_for_write(
3935
0
       internal_handle->read_write_lock,
3936
0
       error ) != 1 )
3937
0
  {
3938
0
    libcerror_error_set(
3939
0
     error,
3940
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3941
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3942
0
     "%s: unable to grab read/write lock for writing.",
3943
0
     function );
3944
3945
0
    return( -1 );
3946
0
  }
3947
0
#endif
3948
0
  result = libphdi_disk_parameters_get_utf8_name_size(
3949
0
            internal_handle->disk_parameters,
3950
0
            utf8_string_size,
3951
0
            error );
3952
3953
0
  if( result == -1 )
3954
0
  {
3955
0
    libcerror_error_set(
3956
0
     error,
3957
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3958
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3959
0
     "%s: unable to retrieve size of UTF-8 name from disk parameters.",
3960
0
     function );
3961
3962
0
    result = -1;
3963
0
  }
3964
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
3965
0
  if( libcthreads_read_write_lock_release_for_write(
3966
0
       internal_handle->read_write_lock,
3967
0
       error ) != 1 )
3968
0
  {
3969
0
    libcerror_error_set(
3970
0
     error,
3971
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3972
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3973
0
     "%s: unable to release read/write lock for writing.",
3974
0
     function );
3975
3976
0
    return( -1 );
3977
0
  }
3978
0
#endif
3979
0
  return( result );
3980
0
}
3981
3982
/* Retrieves the UTF-8 encoded name
3983
 * The size should include the end of string character
3984
 * Returns 1 if successful, 0 if not available or -1 on error
3985
 */
3986
int libphdi_handle_get_utf8_name(
3987
     libphdi_handle_t *handle,
3988
     uint8_t *utf8_string,
3989
     size_t utf8_string_size,
3990
     libcerror_error_t **error )
3991
0
{
3992
0
  libphdi_internal_handle_t *internal_handle = NULL;
3993
0
  static char *function                      = "libphdi_handle_get_utf8_name";
3994
0
  int result                                 = 0;
3995
3996
0
  if( handle == NULL )
3997
0
  {
3998
0
    libcerror_error_set(
3999
0
     error,
4000
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4001
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4002
0
     "%s: invalid handle.",
4003
0
     function );
4004
4005
0
    return( -1 );
4006
0
  }
4007
0
  internal_handle = (libphdi_internal_handle_t *) handle;
4008
4009
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4010
0
  if( libcthreads_read_write_lock_grab_for_write(
4011
0
       internal_handle->read_write_lock,
4012
0
       error ) != 1 )
4013
0
  {
4014
0
    libcerror_error_set(
4015
0
     error,
4016
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4017
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4018
0
     "%s: unable to grab read/write lock for writing.",
4019
0
     function );
4020
4021
0
    return( -1 );
4022
0
  }
4023
0
#endif
4024
0
  result = libphdi_disk_parameters_get_utf8_name(
4025
0
            internal_handle->disk_parameters,
4026
0
            utf8_string,
4027
0
            utf8_string_size,
4028
0
            error );
4029
4030
0
  if( result == -1 )
4031
0
  {
4032
0
    libcerror_error_set(
4033
0
     error,
4034
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4035
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4036
0
     "%s: unable to retrieve UTF-8 name from disk parameters.",
4037
0
     function );
4038
4039
0
    result = -1;
4040
0
  }
4041
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4042
0
  if( libcthreads_read_write_lock_release_for_write(
4043
0
       internal_handle->read_write_lock,
4044
0
       error ) != 1 )
4045
0
  {
4046
0
    libcerror_error_set(
4047
0
     error,
4048
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4049
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4050
0
     "%s: unable to release read/write lock for writing.",
4051
0
     function );
4052
4053
0
    return( -1 );
4054
0
  }
4055
0
#endif
4056
0
  return( result );
4057
0
}
4058
4059
/* Retrieves the size of the UTF-16 encoded name
4060
 * The returned size includes the end of string character
4061
 * Returns 1 if successful, 0 if not available or -1 on error
4062
 */
4063
int libphdi_handle_get_utf16_name_size(
4064
     libphdi_handle_t *handle,
4065
     size_t *utf16_string_size,
4066
     libcerror_error_t **error )
4067
0
{
4068
0
  libphdi_internal_handle_t *internal_handle = NULL;
4069
0
  static char *function                      = "libphdi_handle_get_utf16_name_size";
4070
0
  int result                                 = 0;
4071
4072
0
  if( handle == NULL )
4073
0
  {
4074
0
    libcerror_error_set(
4075
0
     error,
4076
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4077
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4078
0
     "%s: invalid handle.",
4079
0
     function );
4080
4081
0
    return( -1 );
4082
0
  }
4083
0
  internal_handle = (libphdi_internal_handle_t *) handle;
4084
4085
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4086
0
  if( libcthreads_read_write_lock_grab_for_write(
4087
0
       internal_handle->read_write_lock,
4088
0
       error ) != 1 )
4089
0
  {
4090
0
    libcerror_error_set(
4091
0
     error,
4092
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4093
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4094
0
     "%s: unable to grab read/write lock for writing.",
4095
0
     function );
4096
4097
0
    return( -1 );
4098
0
  }
4099
0
#endif
4100
0
  result = libphdi_disk_parameters_get_utf16_name_size(
4101
0
            internal_handle->disk_parameters,
4102
0
            utf16_string_size,
4103
0
            error );
4104
4105
0
  if( result == -1 )
4106
0
  {
4107
0
    libcerror_error_set(
4108
0
     error,
4109
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4110
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4111
0
     "%s: unable to retrieve size of UTF-16 name from disk parameters.",
4112
0
     function );
4113
4114
0
    result = -1;
4115
0
  }
4116
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4117
0
  if( libcthreads_read_write_lock_release_for_write(
4118
0
       internal_handle->read_write_lock,
4119
0
       error ) != 1 )
4120
0
  {
4121
0
    libcerror_error_set(
4122
0
     error,
4123
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4124
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4125
0
     "%s: unable to release read/write lock for writing.",
4126
0
     function );
4127
4128
0
    return( -1 );
4129
0
  }
4130
0
#endif
4131
0
  return( result );
4132
0
}
4133
4134
/* Retrieves the UTF-16 encoded name
4135
 * The size should include the end of string character
4136
 * Returns 1 if successful, 0 if not available or -1 on error
4137
 */
4138
int libphdi_handle_get_utf16_name(
4139
     libphdi_handle_t *handle,
4140
     uint16_t *utf16_string,
4141
     size_t utf16_string_size,
4142
     libcerror_error_t **error )
4143
0
{
4144
0
  libphdi_internal_handle_t *internal_handle = NULL;
4145
0
  static char *function                      = "libphdi_handle_get_utf16_name";
4146
0
  int result                                 = 0;
4147
4148
0
  if( handle == NULL )
4149
0
  {
4150
0
    libcerror_error_set(
4151
0
     error,
4152
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4153
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4154
0
     "%s: invalid handle.",
4155
0
     function );
4156
4157
0
    return( -1 );
4158
0
  }
4159
0
  internal_handle = (libphdi_internal_handle_t *) handle;
4160
4161
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4162
0
  if( libcthreads_read_write_lock_grab_for_write(
4163
0
       internal_handle->read_write_lock,
4164
0
       error ) != 1 )
4165
0
  {
4166
0
    libcerror_error_set(
4167
0
     error,
4168
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4169
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4170
0
     "%s: unable to grab read/write lock for writing.",
4171
0
     function );
4172
4173
0
    return( -1 );
4174
0
  }
4175
0
#endif
4176
0
  result = libphdi_disk_parameters_get_utf16_name(
4177
0
            internal_handle->disk_parameters,
4178
0
            utf16_string,
4179
0
            utf16_string_size,
4180
0
            error );
4181
4182
0
  if( result == -1 )
4183
0
  {
4184
0
    libcerror_error_set(
4185
0
     error,
4186
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4187
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4188
0
     "%s: unable to retrieve UTF-16 name from disk parameters.",
4189
0
     function );
4190
4191
0
    result = -1;
4192
0
  }
4193
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4194
0
  if( libcthreads_read_write_lock_release_for_write(
4195
0
       internal_handle->read_write_lock,
4196
0
       error ) != 1 )
4197
0
  {
4198
0
    libcerror_error_set(
4199
0
     error,
4200
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4201
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4202
0
     "%s: unable to release read/write lock for writing.",
4203
0
     function );
4204
4205
0
    return( -1 );
4206
0
  }
4207
0
#endif
4208
0
  return( result );
4209
0
}
4210
4211
/* Retrieves the number of extents
4212
 * Returns 1 if successful or -1 on error
4213
 */
4214
int libphdi_handle_get_number_of_extents(
4215
     libphdi_handle_t *handle,
4216
     int *number_of_extents,
4217
     libcerror_error_t **error )
4218
0
{
4219
0
  libphdi_internal_handle_t *internal_handle = NULL;
4220
0
  static char *function                      = "libphdi_handle_get_number_of_extents";
4221
0
  int result                                 = 1;
4222
4223
0
  if( handle == NULL )
4224
0
  {
4225
0
    libcerror_error_set(
4226
0
     error,
4227
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4228
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4229
0
     "%s: invalid handle.",
4230
0
     function );
4231
4232
0
    return( -1 );
4233
0
  }
4234
0
  internal_handle = (libphdi_internal_handle_t *) handle;
4235
4236
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4237
0
  if( libcthreads_read_write_lock_grab_for_read(
4238
0
       internal_handle->read_write_lock,
4239
0
       error ) != 1 )
4240
0
  {
4241
0
    libcerror_error_set(
4242
0
     error,
4243
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4244
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4245
0
     "%s: unable to grab read/write lock for reading.",
4246
0
     function );
4247
4248
0
    return( -1 );
4249
0
  }
4250
0
#endif
4251
0
  if( libcdata_array_get_number_of_entries(
4252
0
       internal_handle->extent_values_array,
4253
0
       number_of_extents,
4254
0
       error ) != 1 )
4255
0
  {
4256
0
    libcerror_error_set(
4257
0
     error,
4258
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4259
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4260
0
     "%s: unable to retrieve number of extents.",
4261
0
     function );
4262
4263
0
    result = -1;
4264
0
  }
4265
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4266
0
  if( libcthreads_read_write_lock_release_for_read(
4267
0
       internal_handle->read_write_lock,
4268
0
       error ) != 1 )
4269
0
  {
4270
0
    libcerror_error_set(
4271
0
     error,
4272
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4273
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4274
0
     "%s: unable to release read/write lock for reading.",
4275
0
     function );
4276
4277
0
    return( -1 );
4278
0
  }
4279
0
#endif
4280
0
  return( result );
4281
0
}
4282
4283
/* Retrieves a specific extent descriptor
4284
 * Returns 1 if successful or -1 on error
4285
 */
4286
int libphdi_handle_get_extent_descriptor_by_index(
4287
     libphdi_handle_t *handle,
4288
     int extent_index,
4289
     libphdi_extent_descriptor_t **extent_descriptor,
4290
     libcerror_error_t **error )
4291
0
{
4292
0
  libphdi_extent_values_t *extent_values     = NULL;
4293
0
  libphdi_internal_handle_t *internal_handle = NULL;
4294
0
  static char *function                      = "libphdi_handle_get_extent_descriptor_by_index";
4295
0
  int result                                 = 1;
4296
4297
0
  if( handle == NULL )
4298
0
  {
4299
0
    libcerror_error_set(
4300
0
     error,
4301
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4302
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4303
0
     "%s: invalid handle.",
4304
0
     function );
4305
4306
0
    return( -1 );
4307
0
  }
4308
0
  internal_handle = (libphdi_internal_handle_t *) handle;
4309
4310
0
  if( extent_descriptor == NULL )
4311
0
  {
4312
0
    libcerror_error_set(
4313
0
     error,
4314
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4315
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4316
0
     "%s: invalid extent descriptor.",
4317
0
     function );
4318
4319
0
    return( -1 );
4320
0
  }
4321
0
  if( *extent_descriptor != NULL )
4322
0
  {
4323
0
    libcerror_error_set(
4324
0
     error,
4325
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4326
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4327
0
     "%s: invalid extent descriptor value already set.",
4328
0
     function );
4329
4330
0
    return( -1 );
4331
0
  }
4332
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4333
0
  if( libcthreads_read_write_lock_grab_for_read(
4334
0
       internal_handle->read_write_lock,
4335
0
       error ) != 1 )
4336
0
  {
4337
0
    libcerror_error_set(
4338
0
     error,
4339
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4340
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4341
0
     "%s: unable to grab read/write lock for reading.",
4342
0
     function );
4343
4344
0
    return( -1 );
4345
0
  }
4346
0
#endif
4347
0
  if( libcdata_array_get_entry_by_index(
4348
0
       internal_handle->extent_values_array,
4349
0
       extent_index,
4350
0
       (intptr_t **) &extent_values,
4351
0
       error ) != 1 )
4352
0
  {
4353
0
    libcerror_error_set(
4354
0
     error,
4355
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4356
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4357
0
     "%s: unable to retrieve extent: %d from array.",
4358
0
     function,
4359
0
     extent_index );
4360
4361
0
    result = -1;
4362
0
  }
4363
0
  else if( libphdi_extent_descriptor_initialize(
4364
0
            extent_descriptor,
4365
0
            extent_values,
4366
0
            error ) != 1 )
4367
0
  {
4368
0
    libcerror_error_set(
4369
0
     error,
4370
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4371
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4372
0
     "%s: unable to create extent descriptor.",
4373
0
     function );
4374
4375
0
    result = -1;
4376
0
  }
4377
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4378
0
  if( libcthreads_read_write_lock_release_for_read(
4379
0
       internal_handle->read_write_lock,
4380
0
       error ) != 1 )
4381
0
  {
4382
0
    libcerror_error_set(
4383
0
     error,
4384
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4385
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4386
0
     "%s: unable to release read/write lock for reading.",
4387
0
     function );
4388
4389
0
    return( -1 );
4390
0
  }
4391
0
#endif
4392
0
  return( result );
4393
0
}
4394
4395
4396
/* Retrieves the number of snapshots
4397
 * Returns 1 if successful or -1 on error
4398
 */
4399
int libphdi_handle_get_number_of_snapshots(
4400
     libphdi_handle_t *handle,
4401
     int *number_of_snapshots,
4402
     libcerror_error_t **error )
4403
0
{
4404
0
  libphdi_internal_handle_t *internal_handle = NULL;
4405
0
  static char *function                      = "libphdi_handle_get_number_of_snapshots";
4406
0
  int result                                 = 1;
4407
4408
0
  if( handle == NULL )
4409
0
  {
4410
0
    libcerror_error_set(
4411
0
     error,
4412
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4413
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4414
0
     "%s: invalid handle.",
4415
0
     function );
4416
4417
0
    return( -1 );
4418
0
  }
4419
0
  internal_handle = (libphdi_internal_handle_t *) handle;
4420
4421
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4422
0
  if( libcthreads_read_write_lock_grab_for_read(
4423
0
       internal_handle->read_write_lock,
4424
0
       error ) != 1 )
4425
0
  {
4426
0
    libcerror_error_set(
4427
0
     error,
4428
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4429
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4430
0
     "%s: unable to grab read/write lock for reading.",
4431
0
     function );
4432
4433
0
    return( -1 );
4434
0
  }
4435
0
#endif
4436
0
  if( libcdata_array_get_number_of_entries(
4437
0
       internal_handle->snapshot_values_array,
4438
0
       number_of_snapshots,
4439
0
       error ) != 1 )
4440
0
  {
4441
0
    libcerror_error_set(
4442
0
     error,
4443
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4444
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4445
0
     "%s: unable to retrieve number of snapshots.",
4446
0
     function );
4447
4448
0
    result = -1;
4449
0
  }
4450
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4451
0
  if( libcthreads_read_write_lock_release_for_read(
4452
0
       internal_handle->read_write_lock,
4453
0
       error ) != 1 )
4454
0
  {
4455
0
    libcerror_error_set(
4456
0
     error,
4457
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4458
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4459
0
     "%s: unable to release read/write lock for reading.",
4460
0
     function );
4461
4462
0
    return( -1 );
4463
0
  }
4464
0
#endif
4465
0
  return( result );
4466
0
}
4467
4468
/* Retrieves a specific snapshot
4469
 * Returns 1 if successful or -1 on error
4470
 */
4471
int libphdi_handle_get_snapshot_by_index(
4472
     libphdi_handle_t *handle,
4473
     int snapshot_index,
4474
     libphdi_snapshot_t **snapshot,
4475
     libcerror_error_t **error )
4476
0
{
4477
0
  libphdi_internal_handle_t *internal_handle = NULL;
4478
0
  libphdi_snapshot_values_t *snapshot_values = NULL;
4479
0
  static char *function                      = "libphdi_handle_get_snapshot_by_index";
4480
0
  int result                                 = 1;
4481
4482
0
  if( handle == NULL )
4483
0
  {
4484
0
    libcerror_error_set(
4485
0
     error,
4486
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4487
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4488
0
     "%s: invalid handle.",
4489
0
     function );
4490
4491
0
    return( -1 );
4492
0
  }
4493
0
  internal_handle = (libphdi_internal_handle_t *) handle;
4494
4495
0
  if( snapshot == NULL )
4496
0
  {
4497
0
    libcerror_error_set(
4498
0
     error,
4499
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4500
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4501
0
     "%s: invalid snapshot.",
4502
0
     function );
4503
4504
0
    return( -1 );
4505
0
  }
4506
0
  if( *snapshot != NULL )
4507
0
  {
4508
0
    libcerror_error_set(
4509
0
     error,
4510
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4511
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4512
0
     "%s: invalid snapshot value already set.",
4513
0
     function );
4514
4515
0
    return( -1 );
4516
0
  }
4517
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4518
0
  if( libcthreads_read_write_lock_grab_for_read(
4519
0
       internal_handle->read_write_lock,
4520
0
       error ) != 1 )
4521
0
  {
4522
0
    libcerror_error_set(
4523
0
     error,
4524
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4525
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4526
0
     "%s: unable to grab read/write lock for reading.",
4527
0
     function );
4528
4529
0
    return( -1 );
4530
0
  }
4531
0
#endif
4532
0
  if( libcdata_array_get_entry_by_index(
4533
0
       internal_handle->snapshot_values_array,
4534
0
       snapshot_index,
4535
0
       (intptr_t **) &snapshot_values,
4536
0
       error ) != 1 )
4537
0
  {
4538
0
    libcerror_error_set(
4539
0
     error,
4540
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4541
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4542
0
     "%s: unable to retrieve snapshot: %d from array.",
4543
0
     function,
4544
0
     snapshot_index );
4545
4546
0
    result = -1;
4547
0
  }
4548
0
  else if( libphdi_snapshot_initialize(
4549
0
            snapshot,
4550
0
            snapshot_values,
4551
0
            error ) != 1 )
4552
0
  {
4553
0
    libcerror_error_set(
4554
0
     error,
4555
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4556
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4557
0
     "%s: unable to create snapshot.",
4558
0
     function );
4559
4560
0
    result = -1;
4561
0
  }
4562
0
#if defined( HAVE_LIBPHDI_MULTI_THREAD_SUPPORT )
4563
0
  if( libcthreads_read_write_lock_release_for_read(
4564
0
       internal_handle->read_write_lock,
4565
0
       error ) != 1 )
4566
0
  {
4567
0
    libcerror_error_set(
4568
0
     error,
4569
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4570
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4571
0
     "%s: unable to release read/write lock for reading.",
4572
0
     function );
4573
4574
0
    return( -1 );
4575
0
  }
4576
0
#endif
4577
0
  return( result );
4578
0
}
4579