Coverage Report

Created: 2025-06-13 07:22

/src/libvsapm/libvsapm/libvsapm_volume.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The volume functions
3
 *
4
 * Copyright (C) 2009-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 <wide_string.h>
27
28
#include "libvsapm_debug.h"
29
#include "libvsapm_definitions.h"
30
#include "libvsapm_volume.h"
31
#include "libvsapm_io_handle.h"
32
#include "libvsapm_libbfio.h"
33
#include "libvsapm_libcerror.h"
34
#include "libvsapm_libcnotify.h"
35
#include "libvsapm_partition.h"
36
#include "libvsapm_partition_map_entry.h"
37
#include "libvsapm_types.h"
38
39
/* Creates a volume
40
 * Make sure the value volume is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libvsapm_volume_initialize(
44
     libvsapm_volume_t **volume,
45
     libcerror_error_t **error )
46
334
{
47
334
  libvsapm_internal_volume_t *internal_volume = NULL;
48
334
  static char *function                       = "libvsapm_volume_initialize";
49
50
334
  if( volume == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid volume.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
334
  if( *volume != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid volume value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
334
  internal_volume = memory_allocate_structure(
73
334
                     libvsapm_internal_volume_t );
74
75
334
  if( internal_volume == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
80
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
81
0
     "%s: unable to create volume.",
82
0
     function );
83
84
0
    goto on_error;
85
0
  }
86
334
  if( memory_set(
87
334
       internal_volume,
88
334
       0,
89
334
       sizeof( libvsapm_internal_volume_t ) ) == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
95
0
     "%s: unable to clear volume.",
96
0
     function );
97
98
0
    memory_free(
99
0
     internal_volume );
100
101
0
    return( -1 );
102
0
  }
103
334
  if( libvsapm_io_handle_initialize(
104
334
       &( internal_volume->io_handle ),
105
334
       error ) != 1 )
106
0
  {
107
0
    libcerror_error_set(
108
0
     error,
109
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
110
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
111
0
     "%s: unable to create IO handle.",
112
0
     function );
113
114
0
    goto on_error;
115
0
  }
116
334
  if( libcdata_array_initialize(
117
334
       &( internal_volume->partitions ),
118
334
       0,
119
334
       error ) != 1 )
120
0
  {
121
0
    libcerror_error_set(
122
0
     error,
123
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
124
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
125
0
     "%s: unable to create partitions array.",
126
0
     function );
127
128
0
    goto on_error;
129
0
  }
130
334
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
131
334
  if( libcthreads_read_write_lock_initialize(
132
334
       &( internal_volume->read_write_lock ),
133
334
       error ) != 1 )
134
0
  {
135
0
    libcerror_error_set(
136
0
     error,
137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
138
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
139
0
     "%s: unable to initialize read/write lock.",
140
0
     function );
141
142
0
    goto on_error;
143
0
  }
144
334
#endif
145
334
  *volume = (libvsapm_volume_t *) internal_volume;
146
147
334
  return( 1 );
148
149
0
on_error:
150
0
  if( internal_volume != NULL )
151
0
  {
152
0
    if( internal_volume->io_handle != NULL )
153
0
    {
154
0
      libvsapm_io_handle_free(
155
0
       &( internal_volume->io_handle ),
156
0
       NULL );
157
0
    }
158
0
    memory_free(
159
0
     internal_volume );
160
0
  }
161
0
  return( -1 );
162
334
}
163
164
/* Frees a volume
165
 * Returns 1 if successful or -1 on error
166
 */
167
int libvsapm_volume_free(
168
     libvsapm_volume_t **volume,
169
     libcerror_error_t **error )
170
334
{
171
334
  libvsapm_internal_volume_t *internal_volume = NULL;
172
334
  static char *function                       = "libvsapm_volume_free";
173
334
  int result                                  = 1;
174
175
334
  if( volume == NULL )
176
0
  {
177
0
    libcerror_error_set(
178
0
     error,
179
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
180
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
181
0
     "%s: invalid volume.",
182
0
     function );
183
184
0
    return( -1 );
185
0
  }
186
334
  if( *volume != NULL )
187
334
  {
188
334
    internal_volume = (libvsapm_internal_volume_t *) *volume;
189
190
334
    if( internal_volume->file_io_handle != NULL )
191
0
    {
192
0
      if( libvsapm_volume_close(
193
0
           *volume,
194
0
           error ) != 0 )
195
0
      {
196
0
        libcerror_error_set(
197
0
         error,
198
0
         LIBCERROR_ERROR_DOMAIN_IO,
199
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
200
0
         "%s: unable to close volume.",
201
0
         function );
202
203
0
        result = -1;
204
0
      }
205
0
    }
206
334
    *volume = NULL;
207
208
334
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
209
334
    if( libcthreads_read_write_lock_free(
210
334
         &( internal_volume->read_write_lock ),
211
334
         error ) != 1 )
212
0
    {
213
0
      libcerror_error_set(
214
0
       error,
215
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
216
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
217
0
       "%s: unable to free read/write lock.",
218
0
       function );
219
220
0
      result = -1;
221
0
    }
222
334
#endif
223
334
    if( libcdata_array_free(
224
334
         &( internal_volume->partitions ),
225
334
         (int (*)(intptr_t **, libcerror_error_t **)) &libvsapm_partition_map_entry_free,
226
334
         error ) != 1 )
227
0
    {
228
0
      libcerror_error_set(
229
0
       error,
230
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
231
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
232
0
       "%s: unable to free the partitions array.",
233
0
       function );
234
235
0
      result = -1;
236
0
    }
237
334
    if( libvsapm_io_handle_free(
238
334
         &( internal_volume->io_handle ),
239
334
         error ) != 1 )
240
0
    {
241
0
      libcerror_error_set(
242
0
       error,
243
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
244
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
245
0
       "%s: unable to free IO handle.",
246
0
       function );
247
248
0
      result = -1;
249
0
    }
250
334
    memory_free(
251
334
     internal_volume );
252
334
  }
253
334
  return( result );
254
334
}
255
256
/* Signals the volume to abort its current activity
257
 * Returns 1 if successful or -1 on error
258
 */
259
int libvsapm_volume_signal_abort(
260
     libvsapm_volume_t *volume,
261
     libcerror_error_t **error )
262
0
{
263
0
  libvsapm_internal_volume_t *internal_volume = NULL;
264
0
  static char *function                       = "libvsapm_volume_signal_abort";
265
266
0
  if( volume == NULL )
267
0
  {
268
0
    libcerror_error_set(
269
0
     error,
270
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
271
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
272
0
     "%s: invalid volume.",
273
0
     function );
274
275
0
    return( -1 );
276
0
  }
277
0
  internal_volume = (libvsapm_internal_volume_t *) volume;
278
279
0
  if( internal_volume->io_handle == NULL )
280
0
  {
281
0
    libcerror_error_set(
282
0
     error,
283
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
284
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
285
0
     "%s: invalid volume - missing IO handle.",
286
0
     function );
287
288
0
    return( -1 );
289
0
  }
290
0
  internal_volume->io_handle->abort = 1;
291
292
0
  return( 1 );
293
0
}
294
295
/* Opens a volume
296
 * Returns 1 if successful or -1 on error
297
 */
298
int libvsapm_volume_open(
299
     libvsapm_volume_t *volume,
300
     const char *filename,
301
     int access_flags,
302
     libcerror_error_t **error )
303
0
{
304
0
  libbfio_handle_t *file_io_handle            = NULL;
305
0
  libvsapm_internal_volume_t *internal_volume = NULL;
306
0
  static char *function                       = "libvsapm_volume_open";
307
0
  size_t filename_length                      = 0;
308
309
0
  if( volume == NULL )
310
0
  {
311
0
    libcerror_error_set(
312
0
     error,
313
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
314
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
315
0
     "%s: invalid volume.",
316
0
     function );
317
318
0
    return( -1 );
319
0
  }
320
0
  internal_volume = (libvsapm_internal_volume_t *) volume;
321
322
0
  if( filename == NULL )
323
0
  {
324
0
    libcerror_error_set(
325
0
     error,
326
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
327
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
328
0
     "%s: invalid filename.",
329
0
     function );
330
331
0
    return( -1 );
332
0
  }
333
0
  if( ( ( access_flags & LIBVSAPM_ACCESS_FLAG_READ ) == 0 )
334
0
   && ( ( access_flags & LIBVSAPM_ACCESS_FLAG_WRITE ) == 0 ) )
335
0
  {
336
0
    libcerror_error_set(
337
0
     error,
338
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
339
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
340
0
     "%s: unsupported access flags.",
341
0
     function );
342
343
0
    return( -1 );
344
0
  }
345
0
  if( ( access_flags & LIBVSAPM_ACCESS_FLAG_WRITE ) != 0 )
346
0
  {
347
0
    libcerror_error_set(
348
0
     error,
349
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
350
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
351
0
     "%s: write access currently not supported.",
352
0
     function );
353
354
0
    return( -1 );
355
0
  }
356
0
  if( libbfio_file_initialize(
357
0
       &file_io_handle,
358
0
       error ) != 1 )
359
0
  {
360
0
    libcerror_error_set(
361
0
     error,
362
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
363
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
364
0
     "%s: unable to create file IO handle.",
365
0
     function );
366
367
0
    goto on_error;
368
0
  }
369
#if defined( HAVE_DEBUG_OUTPUT )
370
  if( libbfio_handle_set_track_offsets_read(
371
       file_io_handle,
372
       1,
373
       error ) != 1 )
374
  {
375
    libcerror_error_set(
376
     error,
377
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
378
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
379
     "%s: unable to set track offsets read in file IO handle.",
380
     function );
381
382
    goto on_error;
383
  }
384
#endif
385
0
  filename_length = narrow_string_length(
386
0
                     filename );
387
388
0
  if( libbfio_file_set_name(
389
0
       file_io_handle,
390
0
       filename,
391
0
       filename_length + 1,
392
0
       error ) != 1 )
393
0
  {
394
0
    libcerror_error_set(
395
0
     error,
396
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
397
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
398
0
     "%s: unable to set filename in file IO handle.",
399
0
     function );
400
401
0
    goto on_error;
402
0
  }
403
0
  if( libvsapm_volume_open_file_io_handle(
404
0
       volume,
405
0
       file_io_handle,
406
0
       access_flags,
407
0
       error ) != 1 )
408
0
  {
409
0
    libcerror_error_set(
410
0
     error,
411
0
     LIBCERROR_ERROR_DOMAIN_IO,
412
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
413
0
     "%s: unable to open volume: %s.",
414
0
     function,
415
0
     filename );
416
417
0
    goto on_error;
418
0
  }
419
0
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
420
0
  if( libcthreads_read_write_lock_grab_for_write(
421
0
       internal_volume->read_write_lock,
422
0
       error ) != 1 )
423
0
  {
424
0
    libcerror_error_set(
425
0
     error,
426
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
427
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
428
0
     "%s: unable to grab read/write lock for writing.",
429
0
     function );
430
431
0
    return( -1 );
432
0
  }
433
0
#endif
434
0
  internal_volume->file_io_handle_created_in_library = 1;
435
436
0
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
437
0
  if( libcthreads_read_write_lock_release_for_write(
438
0
       internal_volume->read_write_lock,
439
0
       error ) != 1 )
440
0
  {
441
0
    libcerror_error_set(
442
0
     error,
443
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
444
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
445
0
     "%s: unable to release read/write lock for writing.",
446
0
     function );
447
448
0
    return( -1 );
449
0
  }
450
0
#endif
451
0
  return( 1 );
452
453
0
on_error:
454
0
  if( file_io_handle != NULL )
455
0
  {
456
0
    libbfio_handle_free(
457
0
     &file_io_handle,
458
0
     NULL );
459
0
  }
460
0
  return( -1 );
461
0
}
462
463
#if defined( HAVE_WIDE_CHARACTER_TYPE )
464
465
/* Opens a volume
466
 * Returns 1 if successful or -1 on error
467
 */
468
int libvsapm_volume_open_wide(
469
     libvsapm_volume_t *volume,
470
     const wchar_t *filename,
471
     int access_flags,
472
     libcerror_error_t **error )
473
{
474
  libbfio_handle_t *file_io_handle            = NULL;
475
  libvsapm_internal_volume_t *internal_volume = NULL;
476
  static char *function                       = "libvsapm_volume_open_wide";
477
  size_t filename_length                      = 0;
478
479
  if( volume == NULL )
480
  {
481
    libcerror_error_set(
482
     error,
483
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
484
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
485
     "%s: invalid volume.",
486
     function );
487
488
    return( -1 );
489
  }
490
  internal_volume = (libvsapm_internal_volume_t *) volume;
491
492
  if( filename == NULL )
493
  {
494
    libcerror_error_set(
495
     error,
496
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
497
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
498
     "%s: invalid filename.",
499
     function );
500
501
    return( -1 );
502
  }
503
  if( ( ( access_flags & LIBVSAPM_ACCESS_FLAG_READ ) == 0 )
504
   && ( ( access_flags & LIBVSAPM_ACCESS_FLAG_WRITE ) == 0 ) )
505
  {
506
    libcerror_error_set(
507
     error,
508
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
509
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
510
     "%s: unsupported access flags.",
511
     function );
512
513
    return( -1 );
514
  }
515
  if( ( access_flags & LIBVSAPM_ACCESS_FLAG_WRITE ) != 0 )
516
  {
517
    libcerror_error_set(
518
     error,
519
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
520
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
521
     "%s: write access currently not supported.",
522
     function );
523
524
    return( -1 );
525
  }
526
  if( libbfio_file_initialize(
527
       &file_io_handle,
528
       error ) != 1 )
529
  {
530
    libcerror_error_set(
531
     error,
532
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
533
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
534
     "%s: unable to create file IO handle.",
535
     function );
536
537
    goto on_error;
538
  }
539
#if defined( HAVE_DEBUG_OUTPUT )
540
  if( libbfio_handle_set_track_offsets_read(
541
       file_io_handle,
542
       1,
543
       error ) != 1 )
544
  {
545
    libcerror_error_set(
546
     error,
547
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
548
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
549
     "%s: unable to set track offsets read in file IO handle.",
550
     function );
551
552
    goto on_error;
553
  }
554
#endif
555
  filename_length = wide_string_length(
556
                     filename );
557
558
  if( libbfio_file_set_name_wide(
559
       file_io_handle,
560
       filename,
561
       filename_length + 1,
562
       error ) != 1 )
563
  {
564
    libcerror_error_set(
565
     error,
566
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
567
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
568
     "%s: unable to set filename in file IO handle.",
569
     function );
570
571
    goto on_error;
572
  }
573
  if( libvsapm_volume_open_file_io_handle(
574
       volume,
575
       file_io_handle,
576
       access_flags,
577
       error ) != 1 )
578
  {
579
    libcerror_error_set(
580
     error,
581
     LIBCERROR_ERROR_DOMAIN_IO,
582
     LIBCERROR_IO_ERROR_OPEN_FAILED,
583
     "%s: unable to open volume: %ls.",
584
     function,
585
     filename );
586
587
    goto on_error;
588
  }
589
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
590
  if( libcthreads_read_write_lock_grab_for_write(
591
       internal_volume->read_write_lock,
592
       error ) != 1 )
593
  {
594
    libcerror_error_set(
595
     error,
596
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
597
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
598
     "%s: unable to grab read/write lock for writing.",
599
     function );
600
601
    return( -1 );
602
  }
603
#endif
604
  internal_volume->file_io_handle_created_in_library = 1;
605
606
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
607
  if( libcthreads_read_write_lock_release_for_write(
608
       internal_volume->read_write_lock,
609
       error ) != 1 )
610
  {
611
    libcerror_error_set(
612
     error,
613
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
614
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
615
     "%s: unable to release read/write lock for writing.",
616
     function );
617
618
    return( -1 );
619
  }
620
#endif
621
  return( 1 );
622
623
on_error:
624
  if( file_io_handle != NULL )
625
  {
626
    libbfio_handle_free(
627
     &file_io_handle,
628
     NULL );
629
  }
630
  return( -1 );
631
}
632
633
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
634
635
/* Opens a volume using a Basic File IO (bfio) volume
636
 * Returns 1 if successful or -1 on error
637
 */
638
int libvsapm_volume_open_file_io_handle(
639
     libvsapm_volume_t *volume,
640
     libbfio_handle_t *file_io_handle,
641
     int access_flags,
642
     libcerror_error_t **error )
643
334
{
644
334
  libvsapm_internal_volume_t *internal_volume = NULL;
645
334
  static char *function                       = "libvsapm_volume_open_file_io_handle";
646
334
  uint8_t file_io_handle_opened_in_library    = 0;
647
334
  int bfio_access_flags                       = 0;
648
334
  int file_io_handle_is_open                  = 0;
649
650
334
  if( volume == NULL )
651
0
  {
652
0
    libcerror_error_set(
653
0
     error,
654
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
655
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
656
0
     "%s: invalid volume.",
657
0
     function );
658
659
0
    return( -1 );
660
0
  }
661
334
  internal_volume = (libvsapm_internal_volume_t *) volume;
662
663
334
  if( internal_volume->file_io_handle != NULL )
664
0
  {
665
0
    libcerror_error_set(
666
0
     error,
667
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
668
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
669
0
     "%s: invalid volume - file IO handle value already set.",
670
0
     function );
671
672
0
    return( -1 );
673
0
  }
674
334
  if( file_io_handle == NULL )
675
0
  {
676
0
    libcerror_error_set(
677
0
     error,
678
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
679
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
680
0
     "%s: invalid file IO handle.",
681
0
     function );
682
683
0
    return( -1 );
684
0
  }
685
334
  if( ( ( access_flags & LIBVSAPM_ACCESS_FLAG_READ ) == 0 )
686
334
   && ( ( access_flags & LIBVSAPM_ACCESS_FLAG_WRITE ) == 0 ) )
687
0
  {
688
0
    libcerror_error_set(
689
0
     error,
690
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
691
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
692
0
     "%s: unsupported access flags.",
693
0
     function );
694
695
0
    return( -1 );
696
0
  }
697
334
  if( ( access_flags & LIBVSAPM_ACCESS_FLAG_WRITE ) != 0 )
698
0
  {
699
0
    libcerror_error_set(
700
0
     error,
701
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
702
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
703
0
     "%s: write access currently not supported.",
704
0
     function );
705
706
0
    return( -1 );
707
0
  }
708
334
  if( ( access_flags & LIBVSAPM_ACCESS_FLAG_READ ) != 0 )
709
334
  {
710
334
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
711
334
  }
712
334
  file_io_handle_is_open = libbfio_handle_is_open(
713
334
                            file_io_handle,
714
334
                            error );
715
716
334
  if( file_io_handle_is_open == -1 )
717
0
  {
718
0
    libcerror_error_set(
719
0
     error,
720
0
     LIBCERROR_ERROR_DOMAIN_IO,
721
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
722
0
     "%s: unable to open volume.",
723
0
     function );
724
725
0
    goto on_error;
726
0
  }
727
334
  else if( file_io_handle_is_open == 0 )
728
334
  {
729
334
    if( libbfio_handle_open(
730
334
         file_io_handle,
731
334
         bfio_access_flags,
732
334
         error ) != 1 )
733
0
    {
734
0
      libcerror_error_set(
735
0
       error,
736
0
       LIBCERROR_ERROR_DOMAIN_IO,
737
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
738
0
       "%s: unable to open file IO handle.",
739
0
       function );
740
741
0
      goto on_error;
742
0
    }
743
334
    file_io_handle_opened_in_library = 1;
744
334
  }
745
334
  if( libvsapm_internal_volume_open_read(
746
334
       internal_volume,
747
334
       file_io_handle,
748
334
       error ) != 1 )
749
286
  {
750
286
    libcerror_error_set(
751
286
     error,
752
286
     LIBCERROR_ERROR_DOMAIN_IO,
753
286
     LIBCERROR_IO_ERROR_READ_FAILED,
754
286
     "%s: unable to read from file IO handle.",
755
286
     function );
756
757
286
    goto on_error;
758
286
  }
759
48
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
760
48
  if( libcthreads_read_write_lock_grab_for_write(
761
48
       internal_volume->read_write_lock,
762
48
       error ) != 1 )
763
0
  {
764
0
    libcerror_error_set(
765
0
     error,
766
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
767
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
768
0
     "%s: unable to grab read/write lock for writing.",
769
0
     function );
770
771
0
    return( -1 );
772
0
  }
773
48
#endif
774
48
  internal_volume->file_io_handle                   = file_io_handle;
775
48
  internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
776
777
48
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
778
48
  if( libcthreads_read_write_lock_release_for_write(
779
48
       internal_volume->read_write_lock,
780
48
       error ) != 1 )
781
0
  {
782
0
    libcerror_error_set(
783
0
     error,
784
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
785
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
786
0
     "%s: unable to release read/write lock for writing.",
787
0
     function );
788
789
0
    return( -1 );
790
0
  }
791
48
#endif
792
48
  return( 1 );
793
794
286
on_error:
795
286
  if( file_io_handle_opened_in_library != 0 )
796
286
  {
797
286
    libbfio_handle_close(
798
286
     file_io_handle,
799
286
     error );
800
286
  }
801
286
  return( -1 );
802
48
}
803
804
/* Closes a volume
805
 * Returns 0 if successful or -1 on error
806
 */
807
int libvsapm_volume_close(
808
     libvsapm_volume_t *volume,
809
     libcerror_error_t **error )
810
48
{
811
48
  libvsapm_internal_volume_t *internal_volume = NULL;
812
48
  static char *function                       = "libvsapm_volume_close";
813
48
  int result                                  = 0;
814
815
48
  if( volume == NULL )
816
0
  {
817
0
    libcerror_error_set(
818
0
     error,
819
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
820
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
821
0
     "%s: invalid volume.",
822
0
     function );
823
824
0
    return( -1 );
825
0
  }
826
48
  internal_volume = (libvsapm_internal_volume_t *) volume;
827
828
48
  if( internal_volume->file_io_handle == NULL )
829
0
  {
830
0
    libcerror_error_set(
831
0
     error,
832
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
833
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
834
0
     "%s: invalid volume - missing file IO handle.",
835
0
     function );
836
837
0
    return( -1 );
838
0
  }
839
48
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
840
48
  if( libcthreads_read_write_lock_grab_for_write(
841
48
       internal_volume->read_write_lock,
842
48
       error ) != 1 )
843
0
  {
844
0
    libcerror_error_set(
845
0
     error,
846
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
847
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
848
0
     "%s: unable to grab read/write lock for writing.",
849
0
     function );
850
851
0
    return( -1 );
852
0
  }
853
48
#endif
854
#if defined( HAVE_DEBUG_OUTPUT )
855
  if( libcnotify_verbose != 0 )
856
  {
857
    if( internal_volume->file_io_handle_created_in_library != 0 )
858
    {
859
      if( libvsapm_debug_print_read_offsets(
860
           internal_volume->file_io_handle,
861
           error ) != 1 )
862
      {
863
        libcerror_error_set(
864
         error,
865
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
866
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
867
         "%s: unable to print the read offsets.",
868
         function );
869
870
        result = -1;
871
      }
872
    }
873
  }
874
#endif
875
48
  if( internal_volume->file_io_handle_opened_in_library != 0 )
876
48
  {
877
48
    if( libbfio_handle_close(
878
48
         internal_volume->file_io_handle,
879
48
         error ) != 0 )
880
0
    {
881
0
      libcerror_error_set(
882
0
       error,
883
0
       LIBCERROR_ERROR_DOMAIN_IO,
884
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
885
0
       "%s: unable to close file IO handle.",
886
0
       function );
887
888
0
      result = -1;
889
0
    }
890
48
    internal_volume->file_io_handle_opened_in_library = 0;
891
48
  }
892
48
  if( internal_volume->file_io_handle_created_in_library != 0 )
893
0
  {
894
0
    if( libbfio_handle_free(
895
0
         &( internal_volume->file_io_handle ),
896
0
         error ) != 1 )
897
0
    {
898
0
      libcerror_error_set(
899
0
       error,
900
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
901
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
902
0
       "%s: unable to free file IO handle.",
903
0
       function );
904
905
0
      result = -1;
906
0
    }
907
0
    internal_volume->file_io_handle_created_in_library = 0;
908
0
  }
909
48
  internal_volume->file_io_handle = NULL;
910
911
48
  if( libvsapm_io_handle_clear(
912
48
       internal_volume->io_handle,
913
48
       error ) != 1 )
914
0
  {
915
0
    libcerror_error_set(
916
0
     error,
917
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
918
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
919
0
     "%s: unable to clear the IO handle.",
920
0
     function );
921
922
0
    result = -1;
923
0
  }
924
48
  if( libcdata_array_empty(
925
48
       internal_volume->partitions,
926
48
       (int (*)(intptr_t **, libcerror_error_t **)) &libvsapm_partition_map_entry_free,
927
48
       error ) != 1 )
928
0
  {
929
0
    libcerror_error_set(
930
0
     error,
931
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
932
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
933
0
     "%s: unable to empty the partitions array.",
934
0
     function );
935
936
0
    result = -1;
937
0
  }
938
48
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
939
48
  if( libcthreads_read_write_lock_release_for_write(
940
48
       internal_volume->read_write_lock,
941
48
       error ) != 1 )
942
0
  {
943
0
    libcerror_error_set(
944
0
     error,
945
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
946
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
947
0
     "%s: unable to release read/write lock for writing.",
948
0
     function );
949
950
0
    return( -1 );
951
0
  }
952
48
#endif
953
48
  return( result );
954
48
}
955
956
/* Opens a volume for reading
957
 * Returns 1 if successful or -1 on error
958
 */
959
int libvsapm_internal_volume_open_read(
960
     libvsapm_internal_volume_t *internal_volume,
961
     libbfio_handle_t *file_io_handle,
962
     libcerror_error_t **error )
963
334
{
964
334
  libvsapm_partition_map_entry_t *partition_map_entry = NULL;
965
334
  static char *function                               = "libvsapm_internal_volume_open_read";
966
334
  off64_t partition_map_entry_offset                  = 512;
967
334
  uint32_t partition_map_entry_index                  = 0;
968
334
  uint32_t partition_map_number_of_entries            = 0;
969
334
  int entry_index                                     = 0;
970
971
334
  if( internal_volume == NULL )
972
0
  {
973
0
    libcerror_error_set(
974
0
     error,
975
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
976
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
977
0
     "%s: invalid internal volume.",
978
0
     function );
979
980
0
    return( -1 );
981
0
  }
982
334
  if( libbfio_handle_get_size(
983
334
       file_io_handle,
984
334
       &( internal_volume->size ),
985
334
       error ) != 1 )
986
0
  {
987
0
    libcerror_error_set(
988
0
     error,
989
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
990
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
991
0
     "%s: unable to retrieve size from file IO handle.",
992
0
     function );
993
994
0
    goto on_error;
995
0
  }
996
#if defined( HAVE_DEBUG_OUTPUT )
997
  if( libcnotify_verbose != 0 )
998
  {
999
    libcnotify_printf(
1000
     "%s: reading Apple Partition Map (APM).\n",
1001
     function );
1002
  }
1003
#endif
1004
334
  do
1005
17.4k
  {
1006
17.4k
    if( libvsapm_partition_map_entry_initialize(
1007
17.4k
         &partition_map_entry,
1008
17.4k
         error ) != 1 )
1009
0
    {
1010
0
      libcerror_error_set(
1011
0
       error,
1012
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1013
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1014
0
       "%s: unable to create partition map entry: %d.",
1015
0
       function,
1016
0
       partition_map_entry_index );
1017
1018
0
      goto on_error;
1019
0
    }
1020
17.4k
    if( libvsapm_partition_map_entry_read_file_io_handle(
1021
17.4k
         partition_map_entry,
1022
17.4k
         file_io_handle,
1023
17.4k
         partition_map_entry_offset,
1024
17.4k
         error ) != 1 )
1025
109
    {
1026
109
      libcerror_error_set(
1027
109
       error,
1028
109
       LIBCERROR_ERROR_DOMAIN_IO,
1029
109
       LIBCERROR_IO_ERROR_READ_FAILED,
1030
109
       "%s: unable to read partition map entry: %d from file IO handle.",
1031
109
       function,
1032
109
       partition_map_entry_index );
1033
1034
109
      goto on_error;
1035
109
    }
1036
17.3k
    if( partition_map_entry_index == 0 )
1037
289
    {
1038
289
      if( memory_compare(
1039
289
           partition_map_entry->type,
1040
289
           "Apple_partition_map\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
1041
289
           32 ) != 0 )
1042
131
      {
1043
131
        libcerror_error_set(
1044
131
         error,
1045
131
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1046
131
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1047
131
         "%s: invalid partition map entry: %d - unsupported type.",
1048
131
         function,
1049
131
         partition_map_entry_index );
1050
1051
131
        goto on_error;
1052
131
      }
1053
158
      partition_map_number_of_entries = partition_map_entry->number_of_entries;
1054
158
    }
1055
17.0k
    else if( partition_map_entry->number_of_entries != partition_map_number_of_entries )
1056
46
    {
1057
46
      libcerror_error_set(
1058
46
       error,
1059
46
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1060
46
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1061
46
       "%s: invalid partition map entry: %d number of entries value out of bounds.",
1062
46
       function,
1063
46
       partition_map_entry_index );
1064
1065
46
      goto on_error;
1066
46
    }
1067
17.1k
    partition_map_entry_offset += 512;
1068
1069
17.1k
    if( partition_map_entry_index == 0 )
1070
158
    {
1071
158
      if( libvsapm_partition_map_entry_free(
1072
158
           &partition_map_entry,
1073
158
           error ) != 1 )
1074
0
      {
1075
0
        libcerror_error_set(
1076
0
         error,
1077
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1078
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1079
0
         "%s: unable to free partition map entry: %d.",
1080
0
         function,
1081
0
         partition_map_entry_index );
1082
1083
0
        goto on_error;
1084
0
      }
1085
158
    }
1086
16.9k
    else
1087
16.9k
    {
1088
16.9k
      if( libcdata_array_append_entry(
1089
16.9k
           internal_volume->partitions,
1090
16.9k
           &entry_index,
1091
16.9k
           (intptr_t *) partition_map_entry,
1092
16.9k
           error ) != 1 )
1093
0
      {
1094
0
        libcerror_error_set(
1095
0
         error,
1096
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1097
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1098
0
         "%s: unable to append partition map entry: %d to array.",
1099
0
         function,
1100
0
         partition_map_entry_index );
1101
1102
0
        goto on_error;
1103
0
      }
1104
16.9k
      partition_map_entry = NULL;
1105
16.9k
    }
1106
17.1k
    partition_map_entry_index++;
1107
17.1k
  }
1108
17.1k
  while( partition_map_entry_index < partition_map_number_of_entries );
1109
1110
48
  return( 1 );
1111
1112
286
on_error:
1113
286
  if( partition_map_entry != NULL )
1114
286
  {
1115
286
    libvsapm_partition_map_entry_free(
1116
286
     &partition_map_entry,
1117
286
     NULL );
1118
286
  }
1119
286
  return( -1 );
1120
334
}
1121
1122
/* Retrieves the number of bytes per sector
1123
 * Returns 1 if successful or -1 on error
1124
 */
1125
int libvsapm_volume_get_bytes_per_sector(
1126
     libvsapm_volume_t *volume,
1127
     uint32_t *bytes_per_sector,
1128
     libcerror_error_t **error )
1129
0
{
1130
0
  libvsapm_internal_volume_t *internal_volume = NULL;
1131
0
  static char *function                       = "libvsapm_volume_get_bytes_per_sector";
1132
1133
0
  if( volume == NULL )
1134
0
  {
1135
0
    libcerror_error_set(
1136
0
     error,
1137
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1138
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1139
0
     "%s: invalid volume.",
1140
0
     function );
1141
1142
0
    return( -1 );
1143
0
  }
1144
0
  internal_volume = (libvsapm_internal_volume_t *) volume;
1145
1146
0
  if( internal_volume->io_handle == NULL )
1147
0
  {
1148
0
    libcerror_error_set(
1149
0
     error,
1150
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1151
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1152
0
     "%s: invalid volume - missing IO handle.",
1153
0
     function );
1154
1155
0
    return( -1 );
1156
0
  }
1157
0
  if( bytes_per_sector == NULL )
1158
0
  {
1159
0
    libcerror_error_set(
1160
0
     error,
1161
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1162
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1163
0
     "%s: invalid bytes per sector.",
1164
0
     function );
1165
1166
0
    return( -1 );
1167
0
  }
1168
0
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1169
0
  if( libcthreads_read_write_lock_grab_for_read(
1170
0
       internal_volume->read_write_lock,
1171
0
       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 grab read/write lock for reading.",
1178
0
     function );
1179
1180
0
    return( -1 );
1181
0
  }
1182
0
#endif
1183
0
  *bytes_per_sector = internal_volume->io_handle->bytes_per_sector;
1184
1185
0
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1186
0
  if( libcthreads_read_write_lock_release_for_read(
1187
0
       internal_volume->read_write_lock,
1188
0
       error ) != 1 )
1189
0
  {
1190
0
    libcerror_error_set(
1191
0
     error,
1192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1193
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1194
0
     "%s: unable to release read/write lock for reading.",
1195
0
     function );
1196
1197
0
    return( -1 );
1198
0
  }
1199
0
#endif
1200
0
  return( 1 );
1201
0
}
1202
1203
/* Sets the number of bytes per sector
1204
 * Returns 1 if successful or -1 on error
1205
 */
1206
int libvsapm_volume_set_bytes_per_sector(
1207
     libvsapm_volume_t *volume,
1208
     uint32_t bytes_per_sector,
1209
     libcerror_error_t **error )
1210
0
{
1211
0
  libvsapm_internal_volume_t *internal_volume = NULL;
1212
0
  static char *function                       = "libvsapm_volume_set_bytes_per_sector";
1213
1214
0
  if( volume == 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 volume.",
1221
0
     function );
1222
1223
0
    return( -1 );
1224
0
  }
1225
0
  internal_volume = (libvsapm_internal_volume_t *) volume;
1226
1227
0
  if( internal_volume->io_handle == NULL )
1228
0
  {
1229
0
    libcerror_error_set(
1230
0
     error,
1231
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1232
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1233
0
     "%s: invalid volume - missing IO handle.",
1234
0
     function );
1235
1236
0
    return( -1 );
1237
0
  }
1238
0
  if( internal_volume->bytes_per_sector_set_by_library != 0 )
1239
0
  {
1240
0
    libcerror_error_set(
1241
0
     error,
1242
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1243
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1244
0
     "%s: bytes per sector value already set.",
1245
0
     function );
1246
1247
0
    return( -1 );
1248
0
  }
1249
0
  if( ( bytes_per_sector != 512 )
1250
0
   && ( bytes_per_sector != 1024 )
1251
0
   && ( bytes_per_sector != 2048 )
1252
0
   && ( bytes_per_sector != 4096 ) )
1253
0
  {
1254
0
    libcerror_error_set(
1255
0
     error,
1256
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1257
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1258
0
     "%s: unsupported bytes per sector.",
1259
0
     function );
1260
1261
0
    return( -1 );
1262
0
  }
1263
0
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1264
0
  if( libcthreads_read_write_lock_grab_for_write(
1265
0
       internal_volume->read_write_lock,
1266
0
       error ) != 1 )
1267
0
  {
1268
0
    libcerror_error_set(
1269
0
     error,
1270
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1271
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1272
0
     "%s: unable to grab read/write lock for writing.",
1273
0
     function );
1274
1275
0
    return( -1 );
1276
0
  }
1277
0
#endif
1278
0
  internal_volume->io_handle->bytes_per_sector = bytes_per_sector;
1279
1280
0
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1281
0
  if( libcthreads_read_write_lock_release_for_write(
1282
0
       internal_volume->read_write_lock,
1283
0
       error ) != 1 )
1284
0
  {
1285
0
    libcerror_error_set(
1286
0
     error,
1287
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1288
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1289
0
     "%s: unable to release read/write lock for writing.",
1290
0
     function );
1291
1292
0
    return( -1 );
1293
0
  }
1294
0
#endif
1295
0
  return( 1 );
1296
0
}
1297
1298
/* Retrieves the number of partitions
1299
 * Returns 1 if successful or -1 on error
1300
 */
1301
int libvsapm_volume_get_number_of_partitions(
1302
     libvsapm_volume_t *volume,
1303
     int *number_of_partitions,
1304
     libcerror_error_t **error )
1305
48
{
1306
48
  libvsapm_internal_volume_t *internal_volume = NULL;
1307
48
  static char *function                       = "libvsapm_volume_get_number_of_partitions";
1308
48
  int result                                  = 1;
1309
1310
48
  if( volume == NULL )
1311
0
  {
1312
0
    libcerror_error_set(
1313
0
     error,
1314
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1315
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1316
0
     "%s: invalid volume.",
1317
0
     function );
1318
1319
0
    return( -1 );
1320
0
  }
1321
48
  internal_volume = (libvsapm_internal_volume_t *) volume;
1322
1323
48
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1324
48
  if( libcthreads_read_write_lock_grab_for_read(
1325
48
       internal_volume->read_write_lock,
1326
48
       error ) != 1 )
1327
0
  {
1328
0
    libcerror_error_set(
1329
0
     error,
1330
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1331
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1332
0
     "%s: unable to grab read/write lock for reading.",
1333
0
     function );
1334
1335
0
    return( -1 );
1336
0
  }
1337
48
#endif
1338
48
  if( libcdata_array_get_number_of_entries(
1339
48
       internal_volume->partitions,
1340
48
       number_of_partitions,
1341
48
       error ) != 1 )
1342
0
  {
1343
0
    libcerror_error_set(
1344
0
     error,
1345
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1346
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1347
0
     "%s: unable to retrieve number of partitions from array.",
1348
0
     function );
1349
1350
0
    result = -1;
1351
0
  }
1352
48
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1353
48
  if( libcthreads_read_write_lock_release_for_read(
1354
48
       internal_volume->read_write_lock,
1355
48
       error ) != 1 )
1356
0
  {
1357
0
    libcerror_error_set(
1358
0
     error,
1359
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1360
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1361
0
     "%s: unable to release read/write lock for reading.",
1362
0
     function );
1363
1364
0
    return( -1 );
1365
0
  }
1366
48
#endif
1367
48
  return( result );
1368
48
}
1369
1370
/* Retrieves a specific partition
1371
 * Returns 1 if successful or -1 on error
1372
 */
1373
int libvsapm_volume_get_partition_by_index(
1374
     libvsapm_volume_t *volume,
1375
     int partition_index,
1376
     libvsapm_partition_t **partition,
1377
     libcerror_error_t **error )
1378
47
{
1379
47
  libvsapm_internal_volume_t *internal_volume         = NULL;
1380
47
  libvsapm_partition_map_entry_t *partition_map_entry = NULL;
1381
47
  static char *function                               = "libvsapm_volume_get_partition_by_index";
1382
47
  int result                                          = 1;
1383
1384
47
  if( volume == NULL )
1385
0
  {
1386
0
    libcerror_error_set(
1387
0
     error,
1388
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1389
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1390
0
     "%s: invalid volume.",
1391
0
     function );
1392
1393
0
    return( -1 );
1394
0
  }
1395
47
  internal_volume = (libvsapm_internal_volume_t *) volume;
1396
1397
47
  if( partition == NULL )
1398
0
  {
1399
0
    libcerror_error_set(
1400
0
     error,
1401
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1402
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1403
0
     "%s: invalid partition.",
1404
0
     function );
1405
1406
0
    return( -1 );
1407
0
  }
1408
47
  if( *partition != NULL )
1409
0
  {
1410
0
    libcerror_error_set(
1411
0
     error,
1412
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1413
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1414
0
     "%s: invalid partition value already set.",
1415
0
     function );
1416
1417
0
    return( -1 );
1418
0
  }
1419
47
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1420
47
  if( libcthreads_read_write_lock_grab_for_read(
1421
47
       internal_volume->read_write_lock,
1422
47
       error ) != 1 )
1423
0
  {
1424
0
    libcerror_error_set(
1425
0
     error,
1426
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1427
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1428
0
     "%s: unable to grab read/write lock for reading.",
1429
0
     function );
1430
1431
0
    return( -1 );
1432
0
  }
1433
47
#endif
1434
47
  if( libcdata_array_get_entry_by_index(
1435
47
       internal_volume->partitions,
1436
47
       partition_index,
1437
47
       (intptr_t **) &partition_map_entry,
1438
47
       error ) != 1 )
1439
0
  {
1440
0
    libcerror_error_set(
1441
0
     error,
1442
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1443
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1444
0
     "%s: unable to retrieve partition map entry: %d from array.",
1445
0
     function,
1446
0
     partition_index );
1447
1448
0
    result = -1;
1449
0
  }
1450
47
  else
1451
47
  {
1452
47
    if( libvsapm_partition_initialize(
1453
47
         partition,
1454
47
         internal_volume->io_handle,
1455
47
         internal_volume->file_io_handle,
1456
47
         partition_map_entry,
1457
47
         error ) != 1 )
1458
0
    {
1459
0
      libcerror_error_set(
1460
0
       error,
1461
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1462
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1463
0
       "%s: unable to create partition: %d.",
1464
0
       function,
1465
0
       partition_index );
1466
1467
0
      result = -1;
1468
0
    }
1469
47
  }
1470
47
#if defined( HAVE_LIBVSAPM_MULTI_THREAD_SUPPORT )
1471
47
  if( libcthreads_read_write_lock_release_for_read(
1472
47
       internal_volume->read_write_lock,
1473
47
       error ) != 1 )
1474
0
  {
1475
0
    libcerror_error_set(
1476
0
     error,
1477
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1478
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1479
0
     "%s: unable to release read/write lock for reading.",
1480
0
     function );
1481
1482
0
    return( -1 );
1483
0
  }
1484
47
#endif
1485
47
  return( result );
1486
47
}
1487