Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvsgpt/libvsgpt/libvsgpt_volume.c
Line
Count
Source
1
/*
2
 * The volume functions
3
 *
4
 * Copyright (C) 2019-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libvsgpt_boot_record.h"
29
#include "libvsgpt_debug.h"
30
#include "libvsgpt_definitions.h"
31
#include "libvsgpt_volume.h"
32
#include "libvsgpt_io_handle.h"
33
#include "libvsgpt_libbfio.h"
34
#include "libvsgpt_libcerror.h"
35
#include "libvsgpt_libcnotify.h"
36
#include "libvsgpt_libcthreads.h"
37
#include "libvsgpt_mbr_partition_entry.h"
38
#include "libvsgpt_partition.h"
39
#include "libvsgpt_partition_entry.h"
40
#include "libvsgpt_partition_table_header.h"
41
#include "libvsgpt_partition_values.h"
42
#include "libvsgpt_section_values.h"
43
#include "libvsgpt_types.h"
44
45
/* Creates a volume
46
 * Make sure the value volume is referencing, is set to NULL
47
 * Returns 1 if successful or -1 on error
48
 */
49
int libvsgpt_volume_initialize(
50
     libvsgpt_volume_t **volume,
51
     libcerror_error_t **error )
52
2.06k
{
53
2.06k
  libvsgpt_internal_volume_t *internal_volume = NULL;
54
2.06k
  static char *function                       = "libvsgpt_volume_initialize";
55
56
2.06k
  if( volume == NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62
0
     "%s: invalid volume.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
2.06k
  if( *volume != NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
72
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
73
0
     "%s: invalid volume value already set.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
2.06k
  internal_volume = memory_allocate_structure(
79
2.06k
                     libvsgpt_internal_volume_t );
80
81
2.06k
  if( internal_volume == NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
86
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
87
0
     "%s: unable to create volume.",
88
0
     function );
89
90
0
    goto on_error;
91
0
  }
92
2.06k
  if( memory_set(
93
2.06k
       internal_volume,
94
2.06k
       0,
95
2.06k
       sizeof( libvsgpt_internal_volume_t ) ) == NULL )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
100
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
101
0
     "%s: unable to clear volume.",
102
0
     function );
103
104
0
    memory_free(
105
0
     internal_volume );
106
107
0
    return( -1 );
108
0
  }
109
2.06k
  if( libvsgpt_io_handle_initialize(
110
2.06k
       &( internal_volume->io_handle ),
111
2.06k
       error ) != 1 )
112
0
  {
113
0
    libcerror_error_set(
114
0
     error,
115
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
116
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
117
0
     "%s: unable to create IO handle.",
118
0
     function );
119
120
0
    goto on_error;
121
0
  }
122
2.06k
  if( libcdata_array_initialize(
123
2.06k
       &( internal_volume->partitions ),
124
2.06k
       0,
125
2.06k
       error ) != 1 )
126
0
  {
127
0
    libcerror_error_set(
128
0
     error,
129
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
130
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
131
0
     "%s: unable to create partitions array.",
132
0
     function );
133
134
0
    goto on_error;
135
0
  }
136
2.06k
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
137
2.06k
  if( libcthreads_read_write_lock_initialize(
138
2.06k
       &( internal_volume->read_write_lock ),
139
2.06k
       error ) != 1 )
140
0
  {
141
0
    libcerror_error_set(
142
0
     error,
143
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
144
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
145
0
     "%s: unable to initialize read/write lock.",
146
0
     function );
147
148
0
    goto on_error;
149
0
  }
150
2.06k
#endif
151
2.06k
  *volume = (libvsgpt_volume_t *) internal_volume;
152
153
2.06k
  return( 1 );
154
155
0
on_error:
156
0
  if( internal_volume != NULL )
157
0
  {
158
0
    if( internal_volume->io_handle != NULL )
159
0
    {
160
0
      libvsgpt_io_handle_free(
161
0
       &( internal_volume->io_handle ),
162
0
       NULL );
163
0
    }
164
0
    memory_free(
165
0
     internal_volume );
166
0
  }
167
0
  return( -1 );
168
2.06k
}
169
170
/* Frees a volume
171
 * Returns 1 if successful or -1 on error
172
 */
173
int libvsgpt_volume_free(
174
     libvsgpt_volume_t **volume,
175
     libcerror_error_t **error )
176
2.06k
{
177
2.06k
  libvsgpt_internal_volume_t *internal_volume = NULL;
178
2.06k
  static char *function                       = "libvsgpt_volume_free";
179
2.06k
  int result                                  = 1;
180
181
2.06k
  if( volume == NULL )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
187
0
     "%s: invalid volume.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
2.06k
  if( *volume != NULL )
193
2.06k
  {
194
2.06k
    internal_volume = (libvsgpt_internal_volume_t *) *volume;
195
196
2.06k
    if( internal_volume->file_io_handle != NULL )
197
0
    {
198
0
      if( libvsgpt_volume_close(
199
0
           *volume,
200
0
           error ) != 0 )
201
0
      {
202
0
        libcerror_error_set(
203
0
         error,
204
0
         LIBCERROR_ERROR_DOMAIN_IO,
205
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
206
0
         "%s: unable to close volume.",
207
0
         function );
208
209
0
        result = -1;
210
0
      }
211
0
    }
212
2.06k
    *volume = NULL;
213
214
2.06k
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
215
2.06k
    if( libcthreads_read_write_lock_free(
216
2.06k
         &( internal_volume->read_write_lock ),
217
2.06k
         error ) != 1 )
218
0
    {
219
0
      libcerror_error_set(
220
0
       error,
221
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
222
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
223
0
       "%s: unable to free read/write lock.",
224
0
       function );
225
226
0
      result = -1;
227
0
    }
228
2.06k
#endif
229
2.06k
    if( libcdata_array_free(
230
2.06k
         &( internal_volume->partitions ),
231
2.06k
         (int (*)(intptr_t **, libcerror_error_t **)) &libvsgpt_partition_values_free,
232
2.06k
         error ) != 1 )
233
0
    {
234
0
      libcerror_error_set(
235
0
       error,
236
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
237
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
238
0
       "%s: unable to free the partitions array.",
239
0
       function );
240
241
0
      result = -1;
242
0
    }
243
2.06k
    if( libvsgpt_io_handle_free(
244
2.06k
         &( internal_volume->io_handle ),
245
2.06k
         error ) != 1 )
246
0
    {
247
0
      libcerror_error_set(
248
0
       error,
249
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
251
0
       "%s: unable to free IO handle.",
252
0
       function );
253
254
0
      result = -1;
255
0
    }
256
2.06k
    memory_free(
257
2.06k
     internal_volume );
258
2.06k
  }
259
2.06k
  return( result );
260
2.06k
}
261
262
/* Signals the volume to abort its current activity
263
 * Returns 1 if successful or -1 on error
264
 */
265
int libvsgpt_volume_signal_abort(
266
     libvsgpt_volume_t *volume,
267
     libcerror_error_t **error )
268
0
{
269
0
  libvsgpt_internal_volume_t *internal_volume = NULL;
270
0
  static char *function                       = "libvsgpt_volume_signal_abort";
271
272
0
  if( volume == NULL )
273
0
  {
274
0
    libcerror_error_set(
275
0
     error,
276
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
277
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
278
0
     "%s: invalid volume.",
279
0
     function );
280
281
0
    return( -1 );
282
0
  }
283
0
  internal_volume = (libvsgpt_internal_volume_t *) volume;
284
285
0
  if( internal_volume->io_handle == NULL )
286
0
  {
287
0
    libcerror_error_set(
288
0
     error,
289
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
290
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
291
0
     "%s: invalid volume - missing IO handle.",
292
0
     function );
293
294
0
    return( -1 );
295
0
  }
296
0
  internal_volume->io_handle->abort = 1;
297
298
0
  return( 1 );
299
0
}
300
301
/* Opens a volume
302
 * Returns 1 if successful or -1 on error
303
 */
304
int libvsgpt_volume_open(
305
     libvsgpt_volume_t *volume,
306
     const char *filename,
307
     int access_flags,
308
     libcerror_error_t **error )
309
0
{
310
0
  libbfio_handle_t *file_io_handle            = NULL;
311
0
  libvsgpt_internal_volume_t *internal_volume = NULL;
312
0
  static char *function                       = "libvsgpt_volume_open";
313
0
  size_t filename_length                      = 0;
314
315
0
  if( volume == NULL )
316
0
  {
317
0
    libcerror_error_set(
318
0
     error,
319
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
320
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
321
0
     "%s: invalid volume.",
322
0
     function );
323
324
0
    return( -1 );
325
0
  }
326
0
  internal_volume = (libvsgpt_internal_volume_t *) volume;
327
328
0
  if( filename == NULL )
329
0
  {
330
0
    libcerror_error_set(
331
0
     error,
332
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
333
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
334
0
     "%s: invalid filename.",
335
0
     function );
336
337
0
    return( -1 );
338
0
  }
339
0
  if( ( ( access_flags & LIBVSGPT_ACCESS_FLAG_READ ) == 0 )
340
0
   && ( ( access_flags & LIBVSGPT_ACCESS_FLAG_WRITE ) == 0 ) )
341
0
  {
342
0
    libcerror_error_set(
343
0
     error,
344
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
345
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
346
0
     "%s: unsupported access flags.",
347
0
     function );
348
349
0
    return( -1 );
350
0
  }
351
0
  if( ( access_flags & LIBVSGPT_ACCESS_FLAG_WRITE ) != 0 )
352
0
  {
353
0
    libcerror_error_set(
354
0
     error,
355
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
356
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
357
0
     "%s: write access currently not supported.",
358
0
     function );
359
360
0
    return( -1 );
361
0
  }
362
0
  if( libbfio_file_initialize(
363
0
       &file_io_handle,
364
0
       error ) != 1 )
365
0
  {
366
0
    libcerror_error_set(
367
0
     error,
368
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
369
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
370
0
     "%s: unable to create file IO handle.",
371
0
     function );
372
373
0
    goto on_error;
374
0
  }
375
#if defined( HAVE_DEBUG_OUTPUT )
376
  if( libbfio_handle_set_track_offsets_read(
377
       file_io_handle,
378
       1,
379
       error ) != 1 )
380
  {
381
    libcerror_error_set(
382
     error,
383
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
384
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
385
     "%s: unable to set track offsets read in file IO handle.",
386
     function );
387
388
    goto on_error;
389
  }
390
#endif
391
0
  filename_length = narrow_string_length(
392
0
                     filename );
393
394
0
  if( libbfio_file_set_name(
395
0
       file_io_handle,
396
0
       filename,
397
0
       filename_length + 1,
398
0
       error ) != 1 )
399
0
  {
400
0
    libcerror_error_set(
401
0
     error,
402
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
403
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
404
0
     "%s: unable to set filename in file IO handle.",
405
0
     function );
406
407
0
    goto on_error;
408
0
  }
409
0
  if( libvsgpt_volume_open_file_io_handle(
410
0
       volume,
411
0
       file_io_handle,
412
0
       access_flags,
413
0
       error ) != 1 )
414
0
  {
415
0
    libcerror_error_set(
416
0
     error,
417
0
     LIBCERROR_ERROR_DOMAIN_IO,
418
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
419
0
     "%s: unable to open volume: %s.",
420
0
     function,
421
0
     filename );
422
423
0
    goto on_error;
424
0
  }
425
0
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
426
0
  if( libcthreads_read_write_lock_grab_for_write(
427
0
       internal_volume->read_write_lock,
428
0
       error ) != 1 )
429
0
  {
430
0
    libcerror_error_set(
431
0
     error,
432
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
433
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
434
0
     "%s: unable to grab read/write lock for writing.",
435
0
     function );
436
437
0
    return( -1 );
438
0
  }
439
0
#endif
440
0
  internal_volume->file_io_handle_created_in_library = 1;
441
442
0
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
443
0
  if( libcthreads_read_write_lock_release_for_write(
444
0
       internal_volume->read_write_lock,
445
0
       error ) != 1 )
446
0
  {
447
0
    libcerror_error_set(
448
0
     error,
449
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
450
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
451
0
     "%s: unable to release read/write lock for writing.",
452
0
     function );
453
454
0
    return( -1 );
455
0
  }
456
0
#endif
457
0
  return( 1 );
458
459
0
on_error:
460
0
  if( file_io_handle != NULL )
461
0
  {
462
0
    libbfio_handle_free(
463
0
     &file_io_handle,
464
0
     NULL );
465
0
  }
466
0
  return( -1 );
467
0
}
468
469
#if defined( HAVE_WIDE_CHARACTER_TYPE )
470
471
/* Opens a volume
472
 * Returns 1 if successful or -1 on error
473
 */
474
int libvsgpt_volume_open_wide(
475
     libvsgpt_volume_t *volume,
476
     const wchar_t *filename,
477
     int access_flags,
478
     libcerror_error_t **error )
479
{
480
  libbfio_handle_t *file_io_handle            = NULL;
481
  libvsgpt_internal_volume_t *internal_volume = NULL;
482
  static char *function                       = "libvsgpt_volume_open_wide";
483
  size_t filename_length                      = 0;
484
485
  if( volume == NULL )
486
  {
487
    libcerror_error_set(
488
     error,
489
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
490
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
491
     "%s: invalid volume.",
492
     function );
493
494
    return( -1 );
495
  }
496
  internal_volume = (libvsgpt_internal_volume_t *) volume;
497
498
  if( filename == NULL )
499
  {
500
    libcerror_error_set(
501
     error,
502
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
503
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
504
     "%s: invalid filename.",
505
     function );
506
507
    return( -1 );
508
  }
509
  if( ( ( access_flags & LIBVSGPT_ACCESS_FLAG_READ ) == 0 )
510
   && ( ( access_flags & LIBVSGPT_ACCESS_FLAG_WRITE ) == 0 ) )
511
  {
512
    libcerror_error_set(
513
     error,
514
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
515
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
516
     "%s: unsupported access flags.",
517
     function );
518
519
    return( -1 );
520
  }
521
  if( ( access_flags & LIBVSGPT_ACCESS_FLAG_WRITE ) != 0 )
522
  {
523
    libcerror_error_set(
524
     error,
525
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
526
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
527
     "%s: write access currently not supported.",
528
     function );
529
530
    return( -1 );
531
  }
532
  if( libbfio_file_initialize(
533
       &file_io_handle,
534
       error ) != 1 )
535
  {
536
    libcerror_error_set(
537
     error,
538
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
539
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
540
     "%s: unable to create file IO handle.",
541
     function );
542
543
    goto on_error;
544
  }
545
#if defined( HAVE_DEBUG_OUTPUT )
546
  if( libbfio_handle_set_track_offsets_read(
547
       file_io_handle,
548
       1,
549
       error ) != 1 )
550
  {
551
    libcerror_error_set(
552
     error,
553
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
554
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
555
     "%s: unable to set track offsets read in file IO handle.",
556
     function );
557
558
    goto on_error;
559
  }
560
#endif
561
  filename_length = wide_string_length(
562
                     filename );
563
564
  if( libbfio_file_set_name_wide(
565
       file_io_handle,
566
       filename,
567
       filename_length + 1,
568
       error ) != 1 )
569
  {
570
    libcerror_error_set(
571
     error,
572
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
573
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
574
     "%s: unable to set filename in file IO handle.",
575
     function );
576
577
    goto on_error;
578
  }
579
  if( libvsgpt_volume_open_file_io_handle(
580
       volume,
581
       file_io_handle,
582
       access_flags,
583
       error ) != 1 )
584
  {
585
    libcerror_error_set(
586
     error,
587
     LIBCERROR_ERROR_DOMAIN_IO,
588
     LIBCERROR_IO_ERROR_OPEN_FAILED,
589
     "%s: unable to open volume: %ls.",
590
     function,
591
     filename );
592
593
    goto on_error;
594
  }
595
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
596
  if( libcthreads_read_write_lock_grab_for_write(
597
       internal_volume->read_write_lock,
598
       error ) != 1 )
599
  {
600
    libcerror_error_set(
601
     error,
602
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
603
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
604
     "%s: unable to grab read/write lock for writing.",
605
     function );
606
607
    return( -1 );
608
  }
609
#endif
610
  internal_volume->file_io_handle_created_in_library = 1;
611
612
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
613
  if( libcthreads_read_write_lock_release_for_write(
614
       internal_volume->read_write_lock,
615
       error ) != 1 )
616
  {
617
    libcerror_error_set(
618
     error,
619
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
620
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
621
     "%s: unable to release read/write lock for writing.",
622
     function );
623
624
    return( -1 );
625
  }
626
#endif
627
  return( 1 );
628
629
on_error:
630
  if( file_io_handle != NULL )
631
  {
632
    libbfio_handle_free(
633
     &file_io_handle,
634
     NULL );
635
  }
636
  return( -1 );
637
}
638
639
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
640
641
/* Opens a volume using a Basic File IO (bfio) volume
642
 * Returns 1 if successful or -1 on error
643
 */
644
int libvsgpt_volume_open_file_io_handle(
645
     libvsgpt_volume_t *volume,
646
     libbfio_handle_t *file_io_handle,
647
     int access_flags,
648
     libcerror_error_t **error )
649
2.06k
{
650
2.06k
  libvsgpt_internal_volume_t *internal_volume = NULL;
651
2.06k
  static char *function                       = "libvsgpt_volume_open_file_io_handle";
652
2.06k
  uint8_t file_io_handle_opened_in_library    = 0;
653
2.06k
  int bfio_access_flags                       = 0;
654
2.06k
  int file_io_handle_is_open                  = 0;
655
656
2.06k
  if( volume == NULL )
657
0
  {
658
0
    libcerror_error_set(
659
0
     error,
660
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
661
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
662
0
     "%s: invalid volume.",
663
0
     function );
664
665
0
    return( -1 );
666
0
  }
667
2.06k
  internal_volume = (libvsgpt_internal_volume_t *) volume;
668
669
2.06k
  if( internal_volume->file_io_handle != NULL )
670
0
  {
671
0
    libcerror_error_set(
672
0
     error,
673
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
674
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
675
0
     "%s: invalid volume - file IO handle value already set.",
676
0
     function );
677
678
0
    return( -1 );
679
0
  }
680
2.06k
  if( file_io_handle == NULL )
681
0
  {
682
0
    libcerror_error_set(
683
0
     error,
684
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
685
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
686
0
     "%s: invalid file IO handle.",
687
0
     function );
688
689
0
    return( -1 );
690
0
  }
691
2.06k
  if( ( ( access_flags & LIBVSGPT_ACCESS_FLAG_READ ) == 0 )
692
0
   && ( ( access_flags & LIBVSGPT_ACCESS_FLAG_WRITE ) == 0 ) )
693
0
  {
694
0
    libcerror_error_set(
695
0
     error,
696
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
697
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
698
0
     "%s: unsupported access flags.",
699
0
     function );
700
701
0
    return( -1 );
702
0
  }
703
2.06k
  if( ( access_flags & LIBVSGPT_ACCESS_FLAG_WRITE ) != 0 )
704
0
  {
705
0
    libcerror_error_set(
706
0
     error,
707
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
708
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
709
0
     "%s: write access currently not supported.",
710
0
     function );
711
712
0
    return( -1 );
713
0
  }
714
2.06k
  if( ( access_flags & LIBVSGPT_ACCESS_FLAG_READ ) != 0 )
715
2.06k
  {
716
2.06k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
717
2.06k
  }
718
2.06k
  file_io_handle_is_open = libbfio_handle_is_open(
719
2.06k
                            file_io_handle,
720
2.06k
                            error );
721
722
2.06k
  if( file_io_handle_is_open == -1 )
723
0
  {
724
0
    libcerror_error_set(
725
0
     error,
726
0
     LIBCERROR_ERROR_DOMAIN_IO,
727
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
728
0
     "%s: unable to open volume.",
729
0
     function );
730
731
0
    goto on_error;
732
0
  }
733
2.06k
  else if( file_io_handle_is_open == 0 )
734
2.06k
  {
735
2.06k
    if( libbfio_handle_open(
736
2.06k
         file_io_handle,
737
2.06k
         bfio_access_flags,
738
2.06k
         error ) != 1 )
739
0
    {
740
0
      libcerror_error_set(
741
0
       error,
742
0
       LIBCERROR_ERROR_DOMAIN_IO,
743
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
744
0
       "%s: unable to open file IO handle.",
745
0
       function );
746
747
0
      goto on_error;
748
0
    }
749
2.06k
    file_io_handle_opened_in_library = 1;
750
2.06k
  }
751
2.06k
  if( libvsgpt_internal_volume_open_read(
752
2.06k
       internal_volume,
753
2.06k
       file_io_handle,
754
2.06k
       error ) != 1 )
755
1.86k
  {
756
1.86k
    libcerror_error_set(
757
1.86k
     error,
758
1.86k
     LIBCERROR_ERROR_DOMAIN_IO,
759
1.86k
     LIBCERROR_IO_ERROR_READ_FAILED,
760
1.86k
     "%s: unable to read from file IO handle.",
761
1.86k
     function );
762
763
1.86k
    goto on_error;
764
1.86k
  }
765
201
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
766
201
  if( libcthreads_read_write_lock_grab_for_write(
767
201
       internal_volume->read_write_lock,
768
201
       error ) != 1 )
769
0
  {
770
0
    libcerror_error_set(
771
0
     error,
772
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
773
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
774
0
     "%s: unable to grab read/write lock for writing.",
775
0
     function );
776
777
0
    return( -1 );
778
0
  }
779
201
#endif
780
201
  internal_volume->file_io_handle                   = file_io_handle;
781
201
  internal_volume->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
782
783
201
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
784
201
  if( libcthreads_read_write_lock_release_for_write(
785
201
       internal_volume->read_write_lock,
786
201
       error ) != 1 )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
791
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
792
0
     "%s: unable to release read/write lock for writing.",
793
0
     function );
794
795
0
    return( -1 );
796
0
  }
797
201
#endif
798
201
  return( 1 );
799
800
1.86k
on_error:
801
1.86k
  if( file_io_handle_opened_in_library != 0 )
802
1.86k
  {
803
1.86k
    libbfio_handle_close(
804
1.86k
     file_io_handle,
805
1.86k
     error );
806
1.86k
  }
807
1.86k
  return( -1 );
808
201
}
809
810
/* Closes a volume
811
 * Returns 0 if successful or -1 on error
812
 */
813
int libvsgpt_volume_close(
814
     libvsgpt_volume_t *volume,
815
     libcerror_error_t **error )
816
201
{
817
201
  libvsgpt_internal_volume_t *internal_volume = NULL;
818
201
  static char *function                       = "libvsgpt_volume_close";
819
201
  int result                                  = 0;
820
821
201
  if( volume == NULL )
822
0
  {
823
0
    libcerror_error_set(
824
0
     error,
825
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
826
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
827
0
     "%s: invalid volume.",
828
0
     function );
829
830
0
    return( -1 );
831
0
  }
832
201
  internal_volume = (libvsgpt_internal_volume_t *) volume;
833
834
201
  if( internal_volume->file_io_handle == NULL )
835
0
  {
836
0
    libcerror_error_set(
837
0
     error,
838
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
839
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
840
0
     "%s: invalid volume - missing file IO handle.",
841
0
     function );
842
843
0
    return( -1 );
844
0
  }
845
201
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
846
201
  if( libcthreads_read_write_lock_grab_for_write(
847
201
       internal_volume->read_write_lock,
848
201
       error ) != 1 )
849
0
  {
850
0
    libcerror_error_set(
851
0
     error,
852
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
853
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
854
0
     "%s: unable to grab read/write lock for writing.",
855
0
     function );
856
857
0
    return( -1 );
858
0
  }
859
201
#endif
860
#if defined( HAVE_DEBUG_OUTPUT )
861
  if( libcnotify_verbose != 0 )
862
  {
863
    if( internal_volume->file_io_handle_created_in_library != 0 )
864
    {
865
      if( libvsgpt_debug_print_read_offsets(
866
           internal_volume->file_io_handle,
867
           error ) != 1 )
868
      {
869
        libcerror_error_set(
870
         error,
871
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
872
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
873
         "%s: unable to print the read offsets.",
874
         function );
875
876
        result = -1;
877
      }
878
    }
879
  }
880
#endif
881
201
  if( internal_volume->file_io_handle_opened_in_library != 0 )
882
201
  {
883
201
    if( libbfio_handle_close(
884
201
         internal_volume->file_io_handle,
885
201
         error ) != 0 )
886
0
    {
887
0
      libcerror_error_set(
888
0
       error,
889
0
       LIBCERROR_ERROR_DOMAIN_IO,
890
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
891
0
       "%s: unable to close file IO handle.",
892
0
       function );
893
894
0
      result = -1;
895
0
    }
896
201
    internal_volume->file_io_handle_opened_in_library = 0;
897
201
  }
898
201
  if( internal_volume->file_io_handle_created_in_library != 0 )
899
0
  {
900
0
    if( libbfio_handle_free(
901
0
         &( internal_volume->file_io_handle ),
902
0
         error ) != 1 )
903
0
    {
904
0
      libcerror_error_set(
905
0
       error,
906
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
907
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
908
0
       "%s: unable to free file IO handle.",
909
0
       function );
910
911
0
      result = -1;
912
0
    }
913
0
    internal_volume->file_io_handle_created_in_library = 0;
914
0
  }
915
201
  internal_volume->file_io_handle = NULL;
916
917
201
  if( libvsgpt_io_handle_clear(
918
201
       internal_volume->io_handle,
919
201
       error ) != 1 )
920
0
  {
921
0
    libcerror_error_set(
922
0
     error,
923
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
924
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
925
0
     "%s: unable to clear the IO handle.",
926
0
     function );
927
928
0
    result = -1;
929
0
  }
930
201
  if( libvsgpt_partition_table_header_free(
931
201
       &( internal_volume->partition_table_header ),
932
201
       error ) != 1 )
933
0
  {
934
0
    libcerror_error_set(
935
0
     error,
936
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
937
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
938
0
     "%s: unable to free partition table header.",
939
0
     function );
940
941
0
    result = -1;
942
0
  }
943
201
  if( libcdata_array_empty(
944
201
       internal_volume->partitions,
945
201
       (int (*)(intptr_t **, libcerror_error_t **)) &libvsgpt_partition_values_free,
946
201
       error ) != 1 )
947
0
  {
948
0
    libcerror_error_set(
949
0
     error,
950
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
951
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
952
0
     "%s: unable to empty the partitions array.",
953
0
     function );
954
955
0
    result = -1;
956
0
  }
957
201
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
958
201
  if( libcthreads_read_write_lock_release_for_write(
959
201
       internal_volume->read_write_lock,
960
201
       error ) != 1 )
961
0
  {
962
0
    libcerror_error_set(
963
0
     error,
964
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
965
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
966
0
     "%s: unable to release read/write lock for writing.",
967
0
     function );
968
969
0
    return( -1 );
970
0
  }
971
201
#endif
972
201
  return( result );
973
201
}
974
975
/* Opens a volume for reading
976
 * Returns 1 if successful or -1 on error
977
 */
978
int libvsgpt_internal_volume_open_read(
979
     libvsgpt_internal_volume_t *internal_volume,
980
     libbfio_handle_t *file_io_handle,
981
     libcerror_error_t **error )
982
2.06k
{
983
2.06k
  libvsgpt_boot_record_t *master_boot_record = NULL;
984
2.06k
  static char *function                      = "libvsgpt_internal_volume_open_read";
985
2.06k
  off64_t file_offset                        = 0;
986
987
2.06k
  if( internal_volume == NULL )
988
0
  {
989
0
    libcerror_error_set(
990
0
     error,
991
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
992
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
993
0
     "%s: invalid internal volume.",
994
0
     function );
995
996
0
    return( -1 );
997
0
  }
998
2.06k
  if( libbfio_handle_get_size(
999
2.06k
       file_io_handle,
1000
2.06k
       &( internal_volume->size ),
1001
2.06k
       error ) != 1 )
1002
0
  {
1003
0
    libcerror_error_set(
1004
0
     error,
1005
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1006
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1007
0
     "%s: unable to retrieve size from file IO handle.",
1008
0
     function );
1009
1010
0
    goto on_error;
1011
0
  }
1012
2.06k
  if( libvsgpt_internal_volume_read_partition_table_headers(
1013
2.06k
       internal_volume,
1014
2.06k
       file_io_handle,
1015
2.06k
       error ) != 1 )
1016
553
  {
1017
553
    libcerror_error_set(
1018
553
     error,
1019
553
     LIBCERROR_ERROR_DOMAIN_IO,
1020
553
     LIBCERROR_IO_ERROR_READ_FAILED,
1021
553
     "%s: unable to read partition table header and backup.",
1022
553
     function );
1023
1024
553
    goto on_error;
1025
553
  }
1026
1.51k
  if( internal_volume->partition_table_header == NULL )
1027
0
  {
1028
0
    libcerror_error_set(
1029
0
     error,
1030
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1031
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1032
0
     "%s: invalid volume - missing partition table header.",
1033
0
     function );
1034
1035
0
    goto on_error;
1036
0
  }
1037
#if defined( HAVE_DEBUG_OUTPUT )
1038
  if( libcnotify_verbose != 0 )
1039
  {
1040
    libcnotify_printf(
1041
     "%s: reading GUID Partition Table (GPT) entries.\n",
1042
     function );
1043
  }
1044
#endif
1045
1.51k
  file_offset = internal_volume->partition_table_header->partition_entries_start_block_number * internal_volume->io_handle->bytes_per_sector;
1046
1047
1.51k
  if( libvsgpt_internal_volume_read_partition_entries(
1048
1.51k
       internal_volume,
1049
1.51k
       file_io_handle,
1050
1.51k
       file_offset,
1051
1.51k
       error ) != 1 )
1052
1.07k
  {
1053
1.07k
    libcerror_error_set(
1054
1.07k
     error,
1055
1.07k
     LIBCERROR_ERROR_DOMAIN_IO,
1056
1.07k
     LIBCERROR_IO_ERROR_READ_FAILED,
1057
1.07k
     "%s: unable to read partition entries.",
1058
1.07k
     function );
1059
1060
1.07k
    goto on_error;
1061
1.07k
  }
1062
#if defined( HAVE_DEBUG_OUTPUT )
1063
  if( libcnotify_verbose != 0 )
1064
  {
1065
    libcnotify_printf(
1066
     "%s: reading Master Boot Record (MBR).\n",
1067
     function );
1068
  }
1069
#endif
1070
442
  if( libvsgpt_boot_record_initialize(
1071
442
       &master_boot_record,
1072
442
       error ) != 1 )
1073
0
  {
1074
0
    libcerror_error_set(
1075
0
     error,
1076
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1077
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1078
0
     "%s: unable to create master boot record.",
1079
0
     function );
1080
1081
0
    goto on_error;
1082
0
  }
1083
442
  if( libvsgpt_boot_record_read_file_io_handle(
1084
442
       master_boot_record,
1085
442
       file_io_handle,
1086
442
       0,
1087
442
       error ) != 1 )
1088
34
  {
1089
34
    libcerror_error_set(
1090
34
     error,
1091
34
     LIBCERROR_ERROR_DOMAIN_IO,
1092
34
     LIBCERROR_IO_ERROR_READ_FAILED,
1093
34
     "%s: unable to read master boot record.",
1094
34
     function );
1095
1096
34
    goto on_error;
1097
34
  }
1098
408
  if( libvsgpt_internal_volume_read_mbr_partition_entries(
1099
408
       internal_volume,
1100
408
       file_io_handle,
1101
408
       0,
1102
408
       master_boot_record,
1103
408
       1,
1104
408
       0,
1105
408
       0,
1106
408
       error ) != 1 )
1107
207
  {
1108
207
    libcerror_error_set(
1109
207
     error,
1110
207
     LIBCERROR_ERROR_DOMAIN_IO,
1111
207
     LIBCERROR_IO_ERROR_READ_FAILED,
1112
207
     "%s: unable to read partition entries.",
1113
207
     function );
1114
1115
207
    goto on_error;
1116
207
  }
1117
201
  if( libvsgpt_boot_record_free(
1118
201
       &master_boot_record,
1119
201
       error ) != 1 )
1120
0
  {
1121
0
    libcerror_error_set(
1122
0
     error,
1123
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1124
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1125
0
     "%s: unable to free master boot record.",
1126
0
     function );
1127
1128
0
    goto on_error;
1129
0
  }
1130
201
  return( 1 );
1131
1132
1.86k
on_error:
1133
1.86k
  if( master_boot_record != NULL )
1134
241
  {
1135
241
    libvsgpt_boot_record_free(
1136
241
     &master_boot_record,
1137
241
     NULL );
1138
241
  }
1139
1.86k
  if( internal_volume->partition_table_header != NULL )
1140
1.31k
  {
1141
1.31k
    libvsgpt_partition_table_header_free(
1142
1.31k
     &( internal_volume->partition_table_header ),
1143
1.31k
     NULL );
1144
1.31k
  }
1145
1.86k
  return( -1 );
1146
201
}
1147
1148
/* Reads the partition table header and the backup
1149
 * Returns 1 if successful or -1 on error
1150
 */
1151
int libvsgpt_internal_volume_read_partition_table_headers(
1152
     libvsgpt_internal_volume_t *internal_volume,
1153
     libbfio_handle_t *file_io_handle,
1154
     libcerror_error_t **error )
1155
2.06k
{
1156
2.06k
  libvsgpt_partition_table_header_t *backup_partition_table_header = NULL;
1157
2.06k
  libvsgpt_partition_table_header_t *partition_table_header        = NULL;
1158
2.06k
  static char *function                                            = "libvsgpt_internal_volume_read_partition_table_headers";
1159
2.06k
  off64_t file_offset                                              = 0;
1160
2.06k
  int result                                                       = 0;
1161
1162
2.06k
  if( internal_volume == NULL )
1163
0
  {
1164
0
    libcerror_error_set(
1165
0
     error,
1166
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1167
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1168
0
     "%s: invalid internal volume.",
1169
0
     function );
1170
1171
0
    return( -1 );
1172
0
  }
1173
2.06k
  if( internal_volume->partition_table_header != NULL )
1174
0
  {
1175
0
    libcerror_error_set(
1176
0
     error,
1177
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1178
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1179
0
     "%s: invalid volume - partition table header already set.",
1180
0
     function );
1181
1182
0
    return( -1 );
1183
0
  }
1184
#if defined( HAVE_DEBUG_OUTPUT )
1185
  if( libcnotify_verbose != 0 )
1186
  {
1187
    libcnotify_printf(
1188
     "%s: reading GUID Partition Table (GPT) header.\n",
1189
     function );
1190
  }
1191
#endif
1192
2.06k
  if( libvsgpt_partition_table_header_initialize(
1193
2.06k
       &partition_table_header,
1194
2.06k
       error ) != 1 )
1195
0
  {
1196
0
    libcerror_error_set(
1197
0
     error,
1198
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1199
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1200
0
     "%s: unable to create partition table header.",
1201
0
     function );
1202
1203
0
    goto on_error;
1204
0
  }
1205
2.06k
  internal_volume->io_handle->bytes_per_sector = 512;
1206
1207
2.06k
  result = libvsgpt_partition_table_header_read_file_io_handle(
1208
2.06k
            partition_table_header,
1209
2.06k
            file_io_handle,
1210
2.06k
            (off64_t) internal_volume->io_handle->bytes_per_sector,
1211
2.06k
            error );
1212
1213
2.24k
  while( ( result == 0 )
1214
189
      && ( internal_volume->io_handle->bytes_per_sector < 4096 ) )
1215
180
  {
1216
180
    internal_volume->io_handle->bytes_per_sector *= 2;
1217
1218
180
    result = libvsgpt_partition_table_header_read_file_io_handle(
1219
180
              partition_table_header,
1220
180
              file_io_handle,
1221
180
              (off64_t) internal_volume->io_handle->bytes_per_sector,
1222
180
              error );
1223
180
  }
1224
2.06k
  if( result != 1 )
1225
188
  {
1226
188
    libcerror_error_set(
1227
188
     error,
1228
188
     LIBCERROR_ERROR_DOMAIN_IO,
1229
188
     LIBCERROR_IO_ERROR_READ_FAILED,
1230
188
     "%s: unable to read partition table header.",
1231
188
     function );
1232
1233
188
    goto on_error;
1234
188
  }
1235
#if defined( HAVE_DEBUG_OUTPUT )
1236
  if( libcnotify_verbose != 0 )
1237
  {
1238
    libcnotify_printf(
1239
     "%s: bytes per sector\t: %" PRIzd ".\n",
1240
     function,
1241
     internal_volume->io_handle->bytes_per_sector );
1242
1243
    libcnotify_printf(
1244
     "\n" );
1245
  }
1246
#endif
1247
1.87k
  if( partition_table_header->partition_header_block_number != 1 )
1248
194
  {
1249
194
    libcerror_error_set(
1250
194
     error,
1251
194
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1252
194
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1253
194
     "%s: unsupported partition table header block number: %" PRIu64 ".",
1254
194
     function,
1255
194
     partition_table_header->partition_header_block_number );
1256
1257
194
    goto on_error;
1258
194
  }
1259
#if defined( HAVE_DEBUG_OUTPUT )
1260
  if( libcnotify_verbose != 0 )
1261
  {
1262
    libcnotify_printf(
1263
     "%s: reading backup GUID Partition Table (GPT) header.\n",
1264
     function );
1265
  }
1266
#endif
1267
1.68k
  if( libvsgpt_partition_table_header_initialize(
1268
1.68k
       &backup_partition_table_header,
1269
1.68k
       error ) != 1 )
1270
0
  {
1271
0
    libcerror_error_set(
1272
0
     error,
1273
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1274
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1275
0
     "%s: unable to create backup partition table header.",
1276
0
     function );
1277
1278
0
    goto on_error;
1279
0
  }
1280
1.68k
  result      = 0;
1281
1.68k
  file_offset = partition_table_header->backup_partition_header_block_number * internal_volume->io_handle->bytes_per_sector;
1282
1283
1.68k
  if( file_offset > 0 )
1284
741
  {
1285
741
    result = libvsgpt_partition_table_header_read_file_io_handle(
1286
741
              backup_partition_table_header,
1287
741
              file_io_handle,
1288
741
              file_offset,
1289
741
              error );
1290
741
  }
1291
1.68k
  if( ( result == 0 )
1292
735
   || ( file_offset == 0 ) )
1293
950
  {
1294
#if defined( HAVE_DEBUG_OUTPUT )
1295
    if( libcnotify_verbose != 0 )
1296
    {
1297
      libcnotify_printf(
1298
       "%s: invalid backup partition header block number fallback to last block.\n",
1299
       function );
1300
    }
1301
#endif
1302
950
    file_offset = internal_volume->size - internal_volume->io_handle->bytes_per_sector;
1303
1304
950
    result = libvsgpt_partition_table_header_read_file_io_handle(
1305
950
              backup_partition_table_header,
1306
950
              file_io_handle,
1307
950
              file_offset,
1308
950
              error );
1309
950
  }
1310
1.68k
  if( result != 1 )
1311
143
  {
1312
143
    libcerror_error_set(
1313
143
     error,
1314
143
     LIBCERROR_ERROR_DOMAIN_IO,
1315
143
     LIBCERROR_IO_ERROR_READ_FAILED,
1316
143
     "%s: unable to read backup partition table header.",
1317
143
     function );
1318
1319
143
    goto on_error;
1320
143
  }
1321
1.54k
  if( ( partition_table_header->is_corrupt != 0 )
1322
105
   && ( backup_partition_table_header->is_corrupt != 0 ) )
1323
28
  {
1324
28
    libcerror_error_set(
1325
28
     error,
1326
28
     LIBCERROR_ERROR_DOMAIN_INPUT,
1327
28
     LIBCERROR_INPUT_ERROR_INVALID_DATA,
1328
28
     "%s: partition table header and backup are both corrupt.",
1329
28
     function );
1330
1331
28
    goto on_error;
1332
28
  }
1333
1.51k
  if( ( partition_table_header->is_corrupt != 0 )
1334
1.43k
   || ( backup_partition_table_header->is_corrupt != 0 ) )
1335
110
  {
1336
110
    internal_volume->is_corrupt = 1;
1337
110
  }
1338
1.40k
  else
1339
1.40k
  {
1340
1.40k
    if( partition_table_header->partition_header_block_number != backup_partition_table_header->backup_partition_header_block_number )
1341
1.26k
    {
1342
#if defined( HAVE_DEBUG_OUTPUT )
1343
      if( libcnotify_verbose != 0 )
1344
      {
1345
        libcnotify_printf(
1346
         "%s: mismatch of partition table header block number.\n",
1347
         function );
1348
      }
1349
#endif
1350
1.26k
      internal_volume->is_corrupt = 1;
1351
1.26k
    }
1352
1.40k
    if( partition_table_header->backup_partition_header_block_number != backup_partition_table_header->partition_header_block_number )
1353
1.26k
    {
1354
#if defined( HAVE_DEBUG_OUTPUT )
1355
      if( libcnotify_verbose != 0 )
1356
      {
1357
        libcnotify_printf(
1358
         "%s: mismatch of backup partition table header block number.\n",
1359
         function );
1360
      }
1361
#endif
1362
1.26k
      internal_volume->is_corrupt = 1;
1363
1.26k
    }
1364
1.40k
    if( partition_table_header->partition_area_start_block_number != backup_partition_table_header->partition_area_start_block_number )
1365
391
    {
1366
#if defined( HAVE_DEBUG_OUTPUT )
1367
      if( libcnotify_verbose != 0 )
1368
      {
1369
        libcnotify_printf(
1370
         "%s: mismatch of partition area start block number.\n",
1371
         function );
1372
      }
1373
#endif
1374
391
      internal_volume->is_corrupt = 1;
1375
391
    }
1376
1.40k
    if( partition_table_header->partition_area_end_block_number != backup_partition_table_header->partition_area_end_block_number )
1377
420
    {
1378
#if defined( HAVE_DEBUG_OUTPUT )
1379
      if( libcnotify_verbose != 0 )
1380
      {
1381
        libcnotify_printf(
1382
         "%s: mismatch of partition area end block number.\n",
1383
         function );
1384
      }
1385
#endif
1386
420
      internal_volume->is_corrupt = 1;
1387
420
    }
1388
1.40k
    if( memory_compare(
1389
1.40k
         partition_table_header->disk_identifier,
1390
1.40k
         backup_partition_table_header->disk_identifier,
1391
1.40k
         16 ) != 0 )
1392
432
    {
1393
#if defined( HAVE_DEBUG_OUTPUT )
1394
      if( libcnotify_verbose != 0 )
1395
      {
1396
        libcnotify_printf(
1397
         "%s: mismatch of disk identifier.\n",
1398
         function );
1399
      }
1400
#endif
1401
432
      internal_volume->is_corrupt = 1;
1402
432
    }
1403
    /* The partition entries start block number will be different
1404
     */
1405
1.40k
    if( partition_table_header->number_of_partition_entries != backup_partition_table_header->number_of_partition_entries )
1406
409
    {
1407
#if defined( HAVE_DEBUG_OUTPUT )
1408
      if( libcnotify_verbose != 0 )
1409
      {
1410
        libcnotify_printf(
1411
         "%s: mismatch of number of partition entries.\n",
1412
         function );
1413
      }
1414
#endif
1415
409
      internal_volume->is_corrupt = 1;
1416
409
    }
1417
1.40k
    if( partition_table_header->partition_entry_data_size != backup_partition_table_header->partition_entry_data_size )
1418
387
    {
1419
#if defined( HAVE_DEBUG_OUTPUT )
1420
      if( libcnotify_verbose != 0 )
1421
      {
1422
        libcnotify_printf(
1423
         "%s: mismatch of partition entry data size.\n",
1424
         function );
1425
      }
1426
#endif
1427
387
      internal_volume->is_corrupt = 1;
1428
387
    }
1429
1.40k
    if( partition_table_header->partition_entries_data_checksum != backup_partition_table_header->partition_entries_data_checksum )
1430
395
    {
1431
#if defined( HAVE_DEBUG_OUTPUT )
1432
      if( libcnotify_verbose != 0 )
1433
      {
1434
        libcnotify_printf(
1435
         "%s: mismatch of partition entries data checksum.\n",
1436
         function );
1437
      }
1438
#endif
1439
395
      internal_volume->is_corrupt = 1;
1440
395
    }
1441
1.40k
  }
1442
1.51k
  if( partition_table_header->is_corrupt != 0 )
1443
77
  {
1444
77
    if( libvsgpt_partition_table_header_free(
1445
77
         &partition_table_header,
1446
77
         error ) != 1 )
1447
0
    {
1448
0
      libcerror_error_set(
1449
0
       error,
1450
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1451
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1452
0
       "%s: unable to free partition table header.",
1453
0
       function );
1454
1455
0
      goto on_error;
1456
0
    }
1457
77
    internal_volume->partition_table_header = backup_partition_table_header;
1458
77
  }
1459
1.43k
  else
1460
1.43k
  {
1461
1.43k
    if( libvsgpt_partition_table_header_free(
1462
1.43k
         &backup_partition_table_header,
1463
1.43k
         error ) != 1 )
1464
0
    {
1465
0
      libcerror_error_set(
1466
0
       error,
1467
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1468
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1469
0
       "%s: unable to free backup partition table header.",
1470
0
       function );
1471
1472
0
      goto on_error;
1473
0
    }
1474
1.43k
    internal_volume->partition_table_header = partition_table_header;
1475
1.43k
  }
1476
1.51k
  return( 1 );
1477
1478
553
on_error:
1479
553
  if( backup_partition_table_header != NULL )
1480
171
  {
1481
171
    libvsgpt_partition_table_header_free(
1482
171
     &backup_partition_table_header,
1483
171
     NULL );
1484
171
  }
1485
553
  if( partition_table_header != NULL )
1486
553
  {
1487
553
    libvsgpt_partition_table_header_free(
1488
553
     &partition_table_header,
1489
553
     NULL );
1490
553
  }
1491
553
  return( -1 );
1492
1.51k
}
1493
1494
/* Reads partition entries
1495
 * Returns 1 if successful or -1 on error
1496
 */
1497
int libvsgpt_internal_volume_read_partition_entries(
1498
     libvsgpt_internal_volume_t *internal_volume,
1499
     libbfio_handle_t *file_io_handle,
1500
     off64_t file_offset,
1501
     libcerror_error_t **error )
1502
1.51k
{
1503
1.51k
  uint8_t *empty_partition_type[ 16 ]           = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1504
1.51k
  libvsgpt_partition_entry_t *partition_entry   = NULL;
1505
1.51k
  libvsgpt_partition_values_t *partition_values = NULL;
1506
1.51k
  uint8_t *partition_entries_data               = NULL;
1507
1.51k
  static char *function                         = "libvsgpt_internal_volume_read_partition_entries";
1508
1.51k
  size_t data_offset                            = 0;
1509
1.51k
  size_t partition_entries_data_size            = 0;
1510
1.51k
  ssize_t read_count                            = 0;
1511
1.51k
  uint32_t partition_entry_index                = 0;
1512
1.51k
  int entry_index                               = 0;
1513
1514
1.51k
  if( internal_volume == NULL )
1515
0
  {
1516
0
    libcerror_error_set(
1517
0
     error,
1518
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1519
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1520
0
     "%s: invalid internal volume.",
1521
0
     function );
1522
1523
0
    return( -1 );
1524
0
  }
1525
1.51k
  if( internal_volume->partition_table_header == NULL )
1526
0
  {
1527
0
    libcerror_error_set(
1528
0
     error,
1529
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1530
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1531
0
     "%s: invalid volume - missing partition table header.",
1532
0
     function );
1533
1534
0
    return( -1 );
1535
0
  }
1536
#if ( SIZEOF_SIZE_T <= 4 )
1537
  if( ( internal_volume->partition_table_header->partition_entry_data_size < 128 )
1538
   || ( internal_volume->partition_table_header->partition_entry_data_size > (size_t) SSIZE_MAX ) )
1539
#else
1540
1.51k
  if( internal_volume->partition_table_header->partition_entry_data_size < 128 )
1541
105
#endif
1542
105
  {
1543
105
    libcerror_error_set(
1544
105
     error,
1545
105
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1546
105
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1547
105
     "%s: invalid volume - invalid partition table table header - partition entry data size value out of bounds.",
1548
105
     function );
1549
1550
105
    return( -1 );
1551
105
  }
1552
1.40k
  if( internal_volume->partition_table_header->number_of_partition_entries > 256 )
1553
266
  {
1554
266
    libcerror_error_set(
1555
266
     error,
1556
266
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1557
266
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1558
266
     "%s: invalid volume - invalid partition table table header - number of partition entries value out of bounds.",
1559
266
     function );
1560
1561
266
    return( -1 );
1562
266
  }
1563
1.14k
  partition_entries_data_size = (size_t) internal_volume->partition_table_header->partition_entry_data_size * (size_t) internal_volume->partition_table_header->number_of_partition_entries;
1564
1565
1.14k
  if( partition_entries_data_size > (size_t) SSIZE_MAX )
1566
0
  {
1567
0
    libcerror_error_set(
1568
0
     error,
1569
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1570
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1571
0
     "%s: invalid partition entries data size value out of bounds.",
1572
0
     function );
1573
1574
0
    return( -1 );
1575
0
  }
1576
1.14k
  partition_entries_data = (uint8_t *) memory_allocate(
1577
1.14k
                                        sizeof( uint8_t ) * partition_entries_data_size );
1578
1579
1.14k
  if( partition_entries_data == NULL )
1580
0
  {
1581
0
    libcerror_error_set(
1582
0
     error,
1583
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1584
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1585
0
     "%s: unable to create partition entries data.",
1586
0
     function );
1587
1588
0
    goto on_error;
1589
0
  }
1590
#if defined( HAVE_DEBUG_OUTPUT )
1591
  if( libcnotify_verbose != 0 )
1592
  {
1593
    libcnotify_printf(
1594
     "%s: reading partition entries at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1595
     function,
1596
     file_offset,
1597
     file_offset );
1598
  }
1599
#endif
1600
1.14k
  read_count = libbfio_handle_read_buffer_at_offset(
1601
1.14k
                file_io_handle,
1602
1.14k
                partition_entries_data,
1603
1.14k
                partition_entries_data_size,
1604
1.14k
                file_offset,
1605
1.14k
                error );
1606
1607
1.14k
  if( read_count != (ssize_t) partition_entries_data_size )
1608
209
  {
1609
209
    libcerror_error_set(
1610
209
     error,
1611
209
     LIBCERROR_ERROR_DOMAIN_IO,
1612
209
     LIBCERROR_IO_ERROR_READ_FAILED,
1613
209
     "%s: unable to read partition entries data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1614
209
     function,
1615
209
     file_offset,
1616
209
     file_offset );
1617
1618
209
    goto on_error;
1619
209
  }
1620
#if defined( HAVE_DEBUG_OUTPUT )
1621
  if( libcnotify_verbose != 0 )
1622
  {
1623
    libcnotify_printf(
1624
     "%s: partition entries data:\n",
1625
     function );
1626
    libcnotify_print_data(
1627
     partition_entries_data,
1628
     partition_entries_data_size,
1629
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1630
  }
1631
#endif
1632
934
  if( libvsgpt_partition_entry_initialize(
1633
934
       &partition_entry,
1634
934
       error ) != 1 )
1635
0
  {
1636
0
    libcerror_error_set(
1637
0
     error,
1638
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1639
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1640
0
     "%s: unable to create partition entry.",
1641
0
     function );
1642
1643
0
    goto on_error;
1644
0
  }
1645
934
  for( partition_entry_index = 0;
1646
9.29k
       partition_entry_index < internal_volume->partition_table_header->number_of_partition_entries;
1647
8.36k
       partition_entry_index++ )
1648
8.85k
  {
1649
8.85k
    if( libvsgpt_partition_entry_read_data(
1650
8.85k
         partition_entry,
1651
8.85k
         &( partition_entries_data[ data_offset ] ),
1652
8.85k
         internal_volume->partition_table_header->partition_entry_data_size,
1653
8.85k
         error ) != 1 )
1654
0
    {
1655
0
      libcerror_error_set(
1656
0
       error,
1657
0
       LIBCERROR_ERROR_DOMAIN_IO,
1658
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1659
0
       "%s: unable to read partition entry data.",
1660
0
       function );
1661
1662
0
      goto on_error;
1663
0
    }
1664
8.85k
    data_offset += internal_volume->partition_table_header->partition_entry_data_size;
1665
1666
    /* Ignore empty partition entries
1667
     */
1668
8.85k
    if( memory_compare(
1669
8.85k
         partition_entry->type_identifier,
1670
8.85k
         empty_partition_type,
1671
8.85k
         16 ) == 0 )
1672
2.61k
    {
1673
2.61k
      continue;
1674
2.61k
    }
1675
6.24k
    if( libvsgpt_partition_values_initialize(
1676
6.24k
         &partition_values,
1677
6.24k
         error ) != 1 )
1678
0
    {
1679
0
      libcerror_error_set(
1680
0
       error,
1681
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1682
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1683
0
       "%s: unable to create partition values.",
1684
0
       function );
1685
1686
0
      goto on_error;
1687
0
    }
1688
/* TODO refactor to libvsgtp_partition_values_copy_from_partition_entry */
1689
6.24k
    if( memory_copy(
1690
6.24k
         partition_values->type_identifier,
1691
6.24k
         partition_entry->type_identifier,
1692
6.24k
         16 ) == NULL )
1693
0
    {
1694
0
      libcerror_error_set(
1695
0
       error,
1696
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1697
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
1698
0
       "%s: unable to copy type identifier.",
1699
0
       function );
1700
1701
0
      goto on_error;
1702
0
    }
1703
6.24k
    if( memory_copy(
1704
6.24k
         partition_values->identifier,
1705
6.24k
         partition_entry->identifier,
1706
6.24k
         16 ) == NULL )
1707
0
    {
1708
0
      libcerror_error_set(
1709
0
       error,
1710
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1711
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
1712
0
       "%s: unable to copy identifier.",
1713
0
       function );
1714
1715
0
      goto on_error;
1716
0
    }
1717
6.24k
    if( ( partition_entry->start_block_number < internal_volume->partition_table_header->partition_area_start_block_number )
1718
6.22k
     || ( partition_entry->start_block_number >= (uint64_t) ( internal_volume->size / internal_volume->io_handle->bytes_per_sector ) ) )
1719
270
    {
1720
270
      libcerror_error_set(
1721
270
       error,
1722
270
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1723
270
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1724
270
       "%s: invalid partition entry - start block number value out of bounds.",
1725
270
       function );
1726
1727
270
      goto on_error;
1728
270
    }
1729
5.97k
    if( ( partition_entry->end_block_number < partition_entry->start_block_number )
1730
5.97k
     || ( partition_entry->end_block_number > (uint64_t) ( internal_volume->size / internal_volume->io_handle->bytes_per_sector ) ) )
1731
222
    {
1732
222
      libcerror_error_set(
1733
222
       error,
1734
222
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1735
222
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1736
222
       "%s: invalid partition entry - end block number value out of bounds.",
1737
222
       function );
1738
1739
222
      goto on_error;
1740
222
    }
1741
5.75k
    partition_values->entry_index = partition_entry_index;
1742
5.75k
    partition_values->offset      = (off64_t) ( partition_entry->start_block_number * internal_volume->io_handle->bytes_per_sector );
1743
5.75k
    partition_values->size        = (size64_t) ( ( partition_entry->end_block_number - partition_entry->start_block_number + 1 ) * internal_volume->io_handle->bytes_per_sector );
1744
1745
5.75k
    if( libcdata_array_append_entry(
1746
5.75k
         internal_volume->partitions,
1747
5.75k
         &entry_index,
1748
5.75k
         (intptr_t *) partition_values,
1749
5.75k
         error ) != 1 )
1750
0
    {
1751
0
      libcerror_error_set(
1752
0
       error,
1753
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1754
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1755
0
       "%s: unable to append partition to array.",
1756
0
       function );
1757
1758
0
      goto on_error;
1759
0
    }
1760
5.75k
    partition_values = NULL;
1761
5.75k
  }
1762
442
  if( libvsgpt_partition_entry_free(
1763
442
       &partition_entry,
1764
442
       error ) != 1 )
1765
0
  {
1766
0
    libcerror_error_set(
1767
0
     error,
1768
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1769
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1770
0
     "%s: unable to free partition entry.",
1771
0
     function );
1772
1773
0
    goto on_error;
1774
0
  }
1775
442
  memory_free(
1776
442
   partition_entries_data );
1777
1778
442
  return( 1 );
1779
1780
701
on_error:
1781
701
  if( partition_values != NULL )
1782
492
  {
1783
492
    libvsgpt_partition_values_free(
1784
492
     &partition_values,
1785
492
     NULL );
1786
492
  }
1787
701
  if( partition_entry != NULL )
1788
492
  {
1789
492
    libvsgpt_partition_entry_free(
1790
492
     &partition_entry,
1791
492
     NULL );
1792
492
  }
1793
701
  if( partition_entries_data != NULL )
1794
701
  {
1795
701
    memory_free(
1796
701
     partition_entries_data );
1797
701
  }
1798
701
  return( -1 );
1799
442
}
1800
1801
/* Reads partition entries in a master boot record or extended partition record
1802
 * Returns 1 if successful or -1 on error
1803
 */
1804
int libvsgpt_internal_volume_read_mbr_partition_entries(
1805
     libvsgpt_internal_volume_t *internal_volume,
1806
     libbfio_handle_t *file_io_handle,
1807
     off64_t file_offset,
1808
     libvsgpt_boot_record_t *boot_record,
1809
     uint8_t is_master_boot_record,
1810
     off64_t first_extended_boot_record_offset,
1811
     int recursion_depth,
1812
     libcerror_error_t **error )
1813
3.72k
{
1814
3.72k
  libvsgpt_boot_record_t *extended_partition_record = NULL;
1815
3.72k
  libvsgpt_mbr_partition_entry_t *partition_entry   = NULL;
1816
3.72k
  libvsgpt_partition_values_t *partition_values     = NULL;
1817
3.72k
  static char *function                             = "libvsgpt_internal_volume_read_mbr_partition_entries";
1818
3.72k
  off64_t extended_partition_record_offset          = 0;
1819
3.72k
  int partition_entry_index                         = 0;
1820
3.72k
  int result                                        = 0;
1821
1822
3.72k
  if( internal_volume == NULL )
1823
0
  {
1824
0
    libcerror_error_set(
1825
0
     error,
1826
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1827
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1828
0
     "%s: invalid internal volume.",
1829
0
     function );
1830
1831
0
    return( -1 );
1832
0
  }
1833
3.72k
  if( ( recursion_depth < 0 )
1834
3.72k
   || ( recursion_depth > LIBVSGPT_MAXIMUM_RECURSION_DEPTH ) )
1835
11
  {
1836
11
    libcerror_error_set(
1837
11
     error,
1838
11
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1839
11
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1840
11
     "%s: invalid recursion depth value out of bounds.",
1841
11
     function );
1842
1843
11
    return( -1 );
1844
11
  }
1845
3.71k
  for( partition_entry_index = 0;
1846
18.1k
       partition_entry_index < 4;
1847
14.4k
       partition_entry_index++ )
1848
14.5k
  {
1849
14.5k
    if( libvsgpt_boot_record_get_partition_entry_by_index(
1850
14.5k
         boot_record,
1851
14.5k
         partition_entry_index,
1852
14.5k
         &partition_entry,
1853
14.5k
         error ) != 1 )
1854
0
    {
1855
0
      libcerror_error_set(
1856
0
       error,
1857
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1858
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1859
0
       "%s: unable to retrieve partition entry: %d.",
1860
0
       function,
1861
0
       partition_entry_index );
1862
1863
0
      goto on_error;
1864
0
    }
1865
14.5k
    if( partition_entry == NULL )
1866
0
    {
1867
0
      libcerror_error_set(
1868
0
       error,
1869
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1870
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1871
0
       "%s: missing partition entry: %" PRIu8 ".",
1872
0
       function,
1873
0
       partition_entry_index );
1874
1875
0
      goto on_error;
1876
0
    }
1877
    /* Ignore empty partition entries
1878
     */
1879
14.5k
    if( partition_entry->type == 0 )
1880
6.16k
    {
1881
6.16k
      continue;
1882
6.16k
    }
1883
8.42k
    if( ( partition_entry->type == 0x05 )
1884
4.91k
     || ( ( is_master_boot_record != 0 )
1885
488
      &&  ( partition_entry->type == 0x0f ) ) )
1886
3.53k
    {
1887
3.53k
      if( extended_partition_record != NULL )
1888
22
      {
1889
22
        libcerror_error_set(
1890
22
         error,
1891
22
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1892
22
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1893
22
         "%s: more than 1 extended partition entry per table is not supported.",
1894
22
         function );
1895
1896
22
        goto on_error;
1897
22
      }
1898
3.51k
      extended_partition_record_offset = first_extended_boot_record_offset + ( (off64_t) partition_entry->start_address_lba * internal_volume->io_handle->bytes_per_sector );
1899
1900
#if defined( HAVE_DEBUG_OUTPUT )
1901
      if( libcnotify_verbose != 0 )
1902
      {
1903
        libcnotify_printf(
1904
         "%s: reading Extended Partition Record (EPR) at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1905
         function,
1906
         extended_partition_record_offset,
1907
         extended_partition_record_offset );
1908
      }
1909
#endif
1910
3.51k
      if( libvsgpt_boot_record_initialize(
1911
3.51k
           &extended_partition_record,
1912
3.51k
           error ) != 1 )
1913
0
      {
1914
0
        libcerror_error_set(
1915
0
         error,
1916
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1917
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1918
0
         "%s: unable to create extended partition record.",
1919
0
         function );
1920
1921
0
        goto on_error;
1922
0
      }
1923
3.51k
      result = libvsgpt_boot_record_read_file_io_handle(
1924
3.51k
          extended_partition_record,
1925
3.51k
          file_io_handle,
1926
3.51k
          extended_partition_record_offset,
1927
3.51k
          error );
1928
1929
      /* Linux fdisk supports sector sizes of: 512, 1024, 2048, 4096
1930
       */
1931
3.99k
      while( ( result != 1 )
1932
627
          && ( is_master_boot_record != 0 )
1933
595
          && ( internal_volume->io_handle->bytes_per_sector <= 4096 ) )
1934
482
      {
1935
482
        libcerror_error_free(
1936
482
         error );
1937
1938
482
        internal_volume->io_handle->bytes_per_sector *= 2;
1939
1940
482
        extended_partition_record_offset = (off64_t) partition_entry->start_address_lba * internal_volume->io_handle->bytes_per_sector;
1941
1942
#if defined( HAVE_DEBUG_OUTPUT )
1943
        if( libcnotify_verbose != 0 )
1944
        {
1945
          libcnotify_printf(
1946
           "%s: reading Extended Partition Record (EPR) at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
1947
           function,
1948
           extended_partition_record_offset,
1949
           extended_partition_record_offset );
1950
        }
1951
#endif
1952
482
        result = libvsgpt_boot_record_read_file_io_handle(
1953
482
            extended_partition_record,
1954
482
            file_io_handle,
1955
482
            extended_partition_record_offset,
1956
482
            error );
1957
482
      }
1958
3.51k
      if( result != 1 )
1959
145
      {
1960
145
        libcerror_error_set(
1961
145
         error,
1962
145
         LIBCERROR_ERROR_DOMAIN_IO,
1963
145
         LIBCERROR_IO_ERROR_READ_FAILED,
1964
145
         "%s: unable to read extended partition record.",
1965
145
         function );
1966
1967
145
        goto on_error;
1968
145
      }
1969
3.51k
    }
1970
4.88k
    else
1971
4.88k
    {
1972
/* TODO do bytes per sector check for known volume types and GPT */
1973
1974
#ifdef TODO
1975
      if( libvsgpt_partition_values_initialize(
1976
           &partition_values,
1977
           error ) != 1 )
1978
      {
1979
        libcerror_error_set(
1980
         error,
1981
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1982
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1983
         "%s: unable to create partition values.",
1984
         function );
1985
1986
        goto on_error;
1987
      }
1988
      partition_values->type = partition_entry->type;
1989
1990
      partition_values->offset = first_extended_boot_record_offset + ( (off64_t) partition_entry->start_address_lba * internal_volume->io_handle->bytes_per_sector );
1991
      partition_values->size   = partition_entry->number_of_sectors * internal_volume->io_handle->bytes_per_sector;
1992
1993
/* TODO offset and size sanity check */
1994
1995
      if( libcdata_array_append_entry(
1996
           internal_volume->partitions,
1997
           &entry_index,
1998
           (intptr_t *) partition_values,
1999
           error ) != 1 )
2000
      {
2001
        libcerror_error_set(
2002
         error,
2003
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2004
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2005
         "%s: unable to append partition to array.",
2006
         function );
2007
2008
        goto on_error;
2009
      }
2010
      partition_values = NULL;
2011
#endif /* TODO */
2012
4.88k
    }
2013
8.42k
  }
2014
3.54k
  if( extended_partition_record != NULL )
2015
3.34k
  {
2016
3.34k
    if( ( extended_partition_record_offset == 0 )
2017
3.33k
     || ( extended_partition_record_offset == file_offset ) )
2018
29
    {
2019
29
      libcerror_error_set(
2020
29
       error,
2021
29
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2022
29
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2023
29
       "%s: unsupported extended partition record offset.",
2024
29
       function );
2025
2026
29
      goto on_error;
2027
29
    }
2028
3.31k
    if( is_master_boot_record != 0 )
2029
138
    {
2030
138
      first_extended_boot_record_offset = extended_partition_record_offset;
2031
138
    }
2032
3.31k
    if( libvsgpt_internal_volume_read_mbr_partition_entries(
2033
3.31k
         internal_volume,
2034
3.31k
         file_io_handle,
2035
3.31k
         extended_partition_record_offset,
2036
3.31k
         extended_partition_record,
2037
3.31k
         0,
2038
3.31k
         first_extended_boot_record_offset,
2039
3.31k
         recursion_depth + 1,
2040
3.31k
         error ) != 1 )
2041
3.14k
    {
2042
3.14k
      libcerror_error_set(
2043
3.14k
       error,
2044
3.14k
       LIBCERROR_ERROR_DOMAIN_IO,
2045
3.14k
       LIBCERROR_IO_ERROR_READ_FAILED,
2046
3.14k
       "%s: unable to read partition entries.",
2047
3.14k
       function );
2048
2049
3.14k
      goto on_error;
2050
3.14k
    }
2051
174
    if( libvsgpt_boot_record_free(
2052
174
         &extended_partition_record,
2053
174
         error ) != 1 )
2054
0
    {
2055
0
      libcerror_error_set(
2056
0
       error,
2057
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2058
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2059
0
       "%s: unable to free extended partition record.",
2060
0
       function );
2061
2062
0
      goto on_error;
2063
0
    }
2064
174
  }
2065
375
  return( 1 );
2066
2067
3.33k
on_error:
2068
3.33k
  if( partition_values != NULL )
2069
0
  {
2070
0
    libvsgpt_partition_values_free(
2071
0
     &partition_values,
2072
0
     NULL );
2073
0
  }
2074
3.33k
  if( extended_partition_record != NULL )
2075
3.33k
  {
2076
3.33k
    libvsgpt_boot_record_free(
2077
3.33k
     &extended_partition_record,
2078
3.33k
     NULL );
2079
3.33k
  }
2080
3.33k
  return( -1 );
2081
3.54k
}
2082
2083
/* Retrieves the number of bytes per sector
2084
 * Returns 1 if successful or -1 on error
2085
 */
2086
int libvsgpt_volume_get_bytes_per_sector(
2087
     libvsgpt_volume_t *volume,
2088
     uint32_t *bytes_per_sector,
2089
     libcerror_error_t **error )
2090
47
{
2091
47
  libvsgpt_internal_volume_t *internal_volume = NULL;
2092
47
  static char *function                       = "libvsgpt_volume_get_bytes_per_sector";
2093
2094
47
  if( volume == NULL )
2095
0
  {
2096
0
    libcerror_error_set(
2097
0
     error,
2098
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2099
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2100
0
     "%s: invalid volume.",
2101
0
     function );
2102
2103
0
    return( -1 );
2104
0
  }
2105
47
  internal_volume = (libvsgpt_internal_volume_t *) volume;
2106
2107
47
  if( internal_volume->io_handle == NULL )
2108
0
  {
2109
0
    libcerror_error_set(
2110
0
     error,
2111
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2112
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2113
0
     "%s: invalid volume - missing IO handle.",
2114
0
     function );
2115
2116
0
    return( -1 );
2117
0
  }
2118
47
  if( bytes_per_sector == NULL )
2119
0
  {
2120
0
    libcerror_error_set(
2121
0
     error,
2122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2124
0
     "%s: invalid bytes per sector.",
2125
0
     function );
2126
2127
0
    return( -1 );
2128
0
  }
2129
47
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2130
47
  if( libcthreads_read_write_lock_grab_for_read(
2131
47
       internal_volume->read_write_lock,
2132
47
       error ) != 1 )
2133
0
  {
2134
0
    libcerror_error_set(
2135
0
     error,
2136
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2137
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2138
0
     "%s: unable to grab read/write lock for reading.",
2139
0
     function );
2140
2141
0
    return( -1 );
2142
0
  }
2143
47
#endif
2144
47
  *bytes_per_sector = internal_volume->io_handle->bytes_per_sector;
2145
2146
47
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2147
47
  if( libcthreads_read_write_lock_release_for_read(
2148
47
       internal_volume->read_write_lock,
2149
47
       error ) != 1 )
2150
0
  {
2151
0
    libcerror_error_set(
2152
0
     error,
2153
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2154
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2155
0
     "%s: unable to release read/write lock for reading.",
2156
0
     function );
2157
2158
0
    return( -1 );
2159
0
  }
2160
47
#endif
2161
47
  return( 1 );
2162
47
}
2163
2164
/* Retrieves the disk identifier
2165
 * The identifier is a GUID stored in little-endian and is 16 bytes of size
2166
 * Returns 1 if successful or -1 on error
2167
 */
2168
int libvsgpt_volume_get_disk_identifier(
2169
     libvsgpt_volume_t *volume,
2170
     uint8_t *guid_data,
2171
     size_t guid_data_size,
2172
     libcerror_error_t **error )
2173
47
{
2174
47
  libvsgpt_internal_volume_t *internal_volume = NULL;
2175
47
  static char *function                       = "libvsgpt_volume_get_disk_identifier";
2176
47
  int result                                  = 1;
2177
2178
47
  if( volume == NULL )
2179
0
  {
2180
0
    libcerror_error_set(
2181
0
     error,
2182
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2183
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2184
0
     "%s: invalid volume.",
2185
0
     function );
2186
2187
0
    return( -1 );
2188
0
  }
2189
47
  internal_volume = (libvsgpt_internal_volume_t *) volume;
2190
2191
47
  if( internal_volume->partition_table_header == NULL )
2192
0
  {
2193
0
    libcerror_error_set(
2194
0
     error,
2195
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2196
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2197
0
     "%s: invalid volume - missing partition table header.",
2198
0
     function );
2199
2200
0
    return( -1 );
2201
0
  }
2202
47
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2203
47
  if( libcthreads_read_write_lock_grab_for_read(
2204
47
       internal_volume->read_write_lock,
2205
47
       error ) != 1 )
2206
0
  {
2207
0
    libcerror_error_set(
2208
0
     error,
2209
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2210
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2211
0
     "%s: unable to grab read/write lock for reading.",
2212
0
     function );
2213
2214
0
    return( -1 );
2215
0
  }
2216
47
#endif
2217
47
  if( libvsgpt_partition_table_header_get_disk_identifier(
2218
47
       internal_volume->partition_table_header,
2219
47
       guid_data,
2220
47
       guid_data_size,
2221
47
       error ) != 1 )
2222
0
  {
2223
0
    libcerror_error_set(
2224
0
     error,
2225
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2226
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2227
0
     "%s: unable to retrieve disk identifier.",
2228
0
     function );
2229
2230
0
    result = -1;
2231
0
  }
2232
47
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2233
47
  if( libcthreads_read_write_lock_release_for_read(
2234
47
       internal_volume->read_write_lock,
2235
47
       error ) != 1 )
2236
0
  {
2237
0
    libcerror_error_set(
2238
0
     error,
2239
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2240
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2241
0
     "%s: unable to release read/write lock for reading.",
2242
0
     function );
2243
2244
0
    return( -1 );
2245
0
  }
2246
47
#endif
2247
47
  return( result );
2248
47
}
2249
2250
/* Retrieves the number of partitions
2251
 * Returns 1 if successful or -1 on error
2252
 */
2253
int libvsgpt_volume_get_number_of_partitions(
2254
     libvsgpt_volume_t *volume,
2255
     int *number_of_partitions,
2256
     libcerror_error_t **error )
2257
201
{
2258
201
  libvsgpt_internal_volume_t *internal_volume = NULL;
2259
201
  static char *function                       = "libvsgpt_volume_get_number_of_partitions";
2260
201
  int result                                  = 1;
2261
2262
201
  if( volume == NULL )
2263
0
  {
2264
0
    libcerror_error_set(
2265
0
     error,
2266
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2267
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2268
0
     "%s: invalid volume.",
2269
0
     function );
2270
2271
0
    return( -1 );
2272
0
  }
2273
201
  internal_volume = (libvsgpt_internal_volume_t *) volume;
2274
2275
201
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2276
201
  if( libcthreads_read_write_lock_grab_for_read(
2277
201
       internal_volume->read_write_lock,
2278
201
       error ) != 1 )
2279
0
  {
2280
0
    libcerror_error_set(
2281
0
     error,
2282
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2283
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2284
0
     "%s: unable to grab read/write lock for reading.",
2285
0
     function );
2286
2287
0
    return( -1 );
2288
0
  }
2289
201
#endif
2290
201
  if( libcdata_array_get_number_of_entries(
2291
201
       internal_volume->partitions,
2292
201
       number_of_partitions,
2293
201
       error ) != 1 )
2294
0
  {
2295
0
    libcerror_error_set(
2296
0
     error,
2297
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2298
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2299
0
     "%s: unable to retrieve number of partitions from array.",
2300
0
     function );
2301
2302
0
    result = -1;
2303
0
  }
2304
201
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2305
201
  if( libcthreads_read_write_lock_release_for_read(
2306
201
       internal_volume->read_write_lock,
2307
201
       error ) != 1 )
2308
0
  {
2309
0
    libcerror_error_set(
2310
0
     error,
2311
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2312
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2313
0
     "%s: unable to release read/write lock for reading.",
2314
0
     function );
2315
2316
0
    return( -1 );
2317
0
  }
2318
201
#endif
2319
201
  return( result );
2320
201
}
2321
2322
/* Retrieves a specific partition
2323
 * Returns 1 if successful or -1 on error
2324
 */
2325
int libvsgpt_volume_get_partition_by_index(
2326
     libvsgpt_volume_t *volume,
2327
     int partition_index,
2328
     libvsgpt_partition_t **partition,
2329
     libcerror_error_t **error )
2330
140
{
2331
140
  libvsgpt_internal_volume_t *internal_volume   = NULL;
2332
140
  libvsgpt_partition_values_t *partition_values = NULL;
2333
140
  static char *function                         = "libvsgpt_volume_get_partition_by_index";
2334
140
  int result                                    = 1;
2335
2336
140
  if( volume == NULL )
2337
0
  {
2338
0
    libcerror_error_set(
2339
0
     error,
2340
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2341
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2342
0
     "%s: invalid volume.",
2343
0
     function );
2344
2345
0
    return( -1 );
2346
0
  }
2347
140
  internal_volume = (libvsgpt_internal_volume_t *) volume;
2348
2349
140
  if( partition == NULL )
2350
0
  {
2351
0
    libcerror_error_set(
2352
0
     error,
2353
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2354
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2355
0
     "%s: invalid partition.",
2356
0
     function );
2357
2358
0
    return( -1 );
2359
0
  }
2360
140
  if( *partition != NULL )
2361
0
  {
2362
0
    libcerror_error_set(
2363
0
     error,
2364
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2365
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2366
0
     "%s: invalid partition value already set.",
2367
0
     function );
2368
2369
0
    return( -1 );
2370
0
  }
2371
140
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2372
140
  if( libcthreads_read_write_lock_grab_for_read(
2373
140
       internal_volume->read_write_lock,
2374
140
       error ) != 1 )
2375
0
  {
2376
0
    libcerror_error_set(
2377
0
     error,
2378
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2379
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2380
0
     "%s: unable to grab read/write lock for reading.",
2381
0
     function );
2382
2383
0
    return( -1 );
2384
0
  }
2385
140
#endif
2386
140
  if( libcdata_array_get_entry_by_index(
2387
140
       internal_volume->partitions,
2388
140
       partition_index,
2389
140
       (intptr_t **) &partition_values,
2390
140
       error ) != 1 )
2391
0
  {
2392
0
    libcerror_error_set(
2393
0
     error,
2394
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2395
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2396
0
     "%s: unable to retrieve partition values: %d from array.",
2397
0
     function,
2398
0
     partition_index );
2399
2400
0
    result = -1;
2401
0
  }
2402
140
  else
2403
140
  {
2404
140
    if( libvsgpt_partition_initialize(
2405
140
         partition,
2406
140
         internal_volume->file_io_handle,
2407
140
         partition_values,
2408
140
         error ) != 1 )
2409
0
    {
2410
0
      libcerror_error_set(
2411
0
       error,
2412
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2413
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2414
0
       "%s: unable to create partition: %d.",
2415
0
       function,
2416
0
       partition_index );
2417
2418
0
      result = -1;
2419
0
    }
2420
140
  }
2421
140
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2422
140
  if( libcthreads_read_write_lock_release_for_read(
2423
140
       internal_volume->read_write_lock,
2424
140
       error ) != 1 )
2425
0
  {
2426
0
    libcerror_error_set(
2427
0
     error,
2428
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2429
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2430
0
     "%s: unable to release read/write lock for reading.",
2431
0
     function );
2432
2433
0
    result = -1;
2434
0
  }
2435
140
#endif
2436
140
  if( result == -1 )
2437
0
  {
2438
0
    goto on_error;
2439
0
  }
2440
140
  return( 1 );
2441
2442
0
on_error:
2443
0
  if( *partition != NULL )
2444
0
  {
2445
0
    libvsgpt_partition_free(
2446
0
     partition,
2447
0
     NULL );
2448
0
  }
2449
0
  return( -1 );
2450
140
}
2451
2452
/* Retrieves the partition values with the corresponding (partition) entry index
2453
 * This function is not multi-thread safe acquire read lock before call
2454
 * Returns 1 if successful, 0 if not found or -1 on error
2455
 */
2456
int libvsgpt_internal_volume_get_partition_values_by_identifier(
2457
     libvsgpt_internal_volume_t *internal_volume,
2458
     uint32_t entry_index,
2459
     libvsgpt_partition_values_t **partition_values,
2460
     libcerror_error_t **error )
2461
0
{
2462
0
  libvsgpt_partition_values_t *safe_partition_values = NULL;
2463
0
  static char *function                              = "libvsgpt_internal_volume_get_partition_values_by_identifier";
2464
0
  uint32_t safe_entry_index                          = 0;
2465
0
  int number_of_partitions                           = 0;
2466
0
  int partition_index                                = 0;
2467
2468
0
  if( internal_volume == NULL )
2469
0
  {
2470
0
    libcerror_error_set(
2471
0
     error,
2472
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2473
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2474
0
     "%s: invalid volume.",
2475
0
     function );
2476
2477
0
    return( -1 );
2478
0
  }
2479
0
  if( partition_values == NULL )
2480
0
  {
2481
0
    libcerror_error_set(
2482
0
     error,
2483
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2484
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2485
0
     "%s: invalid partition values.",
2486
0
     function );
2487
2488
0
    return( -1 );
2489
0
  }
2490
0
  if( libcdata_array_get_number_of_entries(
2491
0
       internal_volume->partitions,
2492
0
       &number_of_partitions,
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 partitions from array.",
2500
0
     function );
2501
2502
0
    return( -1 );
2503
0
  }
2504
0
  for( partition_index = 0;
2505
0
       partition_index < number_of_partitions;
2506
0
       partition_index++ )
2507
0
  {
2508
0
    if( libcdata_array_get_entry_by_index(
2509
0
         internal_volume->partitions,
2510
0
         partition_index,
2511
0
         (intptr_t **) &safe_partition_values,
2512
0
         error ) != 1 )
2513
0
    {
2514
0
      libcerror_error_set(
2515
0
       error,
2516
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2517
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2518
0
       "%s: unable to retrieve partition values: %d from array.",
2519
0
       function,
2520
0
       partition_index );
2521
2522
0
      return( -1 );
2523
0
    }
2524
0
    if( libvsgpt_partition_values_get_entry_index(
2525
0
         safe_partition_values,
2526
0
         &safe_entry_index,
2527
0
         error ) != 1 )
2528
0
    {
2529
0
      libcerror_error_set(
2530
0
       error,
2531
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2532
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2533
0
       "%s: unable to retrieve entry index from partition values: %d.",
2534
0
       function,
2535
0
       partition_index );
2536
2537
0
      return( -1 );
2538
0
    }
2539
0
    if( safe_entry_index == entry_index )
2540
0
    {
2541
0
      *partition_values = safe_partition_values;
2542
2543
0
      return( 1 );
2544
0
    }
2545
0
  }
2546
0
  return( 0 );
2547
0
}
2548
2549
/* Determines if the volume contains a partition with the corresponding (partition) entry index
2550
 * Returns 1 if the volume contains such a partition, 0 if not or -1 on error
2551
 */
2552
int libvsgpt_volume_has_partition_with_identifier(
2553
     libvsgpt_volume_t *volume,
2554
     uint32_t entry_index,
2555
     libcerror_error_t **error )
2556
0
{
2557
0
  libvsgpt_internal_volume_t *internal_volume   = NULL;
2558
0
  libvsgpt_partition_values_t *partition_values = NULL;
2559
0
  static char *function                         = "libvsgpt_volume_has_partition_with_identifier";
2560
0
  int result                                    = 0;
2561
2562
0
  if( volume == NULL )
2563
0
  {
2564
0
    libcerror_error_set(
2565
0
     error,
2566
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2567
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2568
0
     "%s: invalid volume.",
2569
0
     function );
2570
2571
0
    return( -1 );
2572
0
  }
2573
0
  internal_volume = (libvsgpt_internal_volume_t *) volume;
2574
2575
0
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2576
0
  if( libcthreads_read_write_lock_grab_for_read(
2577
0
       internal_volume->read_write_lock,
2578
0
       error ) != 1 )
2579
0
  {
2580
0
    libcerror_error_set(
2581
0
     error,
2582
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2583
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2584
0
     "%s: unable to grab read/write lock for reading.",
2585
0
     function );
2586
2587
0
    return( -1 );
2588
0
  }
2589
0
#endif
2590
0
  result = libvsgpt_internal_volume_get_partition_values_by_identifier(
2591
0
            internal_volume,
2592
0
            entry_index,
2593
0
            &partition_values,
2594
0
            error );
2595
2596
0
  if( result == -1 )
2597
0
  {
2598
0
    libcerror_error_set(
2599
0
     error,
2600
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2601
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2602
0
     "%s: unable to retrieve partition values.",
2603
0
     function );
2604
2605
0
    result = -1;
2606
0
  }
2607
0
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2608
0
  if( libcthreads_read_write_lock_release_for_read(
2609
0
       internal_volume->read_write_lock,
2610
0
       error ) != 1 )
2611
0
  {
2612
0
    libcerror_error_set(
2613
0
     error,
2614
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2615
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2616
0
     "%s: unable to release read/write lock for reading.",
2617
0
     function );
2618
2619
0
    return( -1 );
2620
0
  }
2621
0
#endif
2622
0
  return( result );
2623
0
}
2624
2625
/* Retrieves the partition with the corresponding (partition) entry index
2626
 * Returns 1 if successful, 0 if not found or -1 on error
2627
 */
2628
int libvsgpt_volume_get_partition_by_identifier(
2629
     libvsgpt_volume_t *volume,
2630
     uint32_t entry_index,
2631
     libvsgpt_partition_t **partition,
2632
     libcerror_error_t **error )
2633
0
{
2634
0
  libvsgpt_internal_volume_t *internal_volume   = NULL;
2635
0
  libvsgpt_partition_values_t *partition_values = NULL;
2636
0
  static char *function                         = "libvsgpt_volume_get_partition_by_identifier";
2637
0
  int result                                    = 1;
2638
2639
0
  if( volume == NULL )
2640
0
  {
2641
0
    libcerror_error_set(
2642
0
     error,
2643
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2644
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2645
0
     "%s: invalid volume.",
2646
0
     function );
2647
2648
0
    return( -1 );
2649
0
  }
2650
0
  internal_volume = (libvsgpt_internal_volume_t *) volume;
2651
2652
0
  if( partition == NULL )
2653
0
  {
2654
0
    libcerror_error_set(
2655
0
     error,
2656
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2657
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2658
0
     "%s: invalid partition.",
2659
0
     function );
2660
2661
0
    return( -1 );
2662
0
  }
2663
0
  if( *partition != NULL )
2664
0
  {
2665
0
    libcerror_error_set(
2666
0
     error,
2667
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2668
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2669
0
     "%s: invalid partition value already set.",
2670
0
     function );
2671
2672
0
    return( -1 );
2673
0
  }
2674
0
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2675
0
  if( libcthreads_read_write_lock_grab_for_read(
2676
0
       internal_volume->read_write_lock,
2677
0
       error ) != 1 )
2678
0
  {
2679
0
    libcerror_error_set(
2680
0
     error,
2681
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2682
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2683
0
     "%s: unable to grab read/write lock for reading.",
2684
0
     function );
2685
2686
0
    return( -1 );
2687
0
  }
2688
0
#endif
2689
0
  result = libvsgpt_internal_volume_get_partition_values_by_identifier(
2690
0
            internal_volume,
2691
0
            entry_index,
2692
0
            &partition_values,
2693
0
            error );
2694
2695
0
  if( result == -1 )
2696
0
  {
2697
0
    libcerror_error_set(
2698
0
     error,
2699
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2700
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2701
0
     "%s: unable to retrieve partition values.",
2702
0
     function );
2703
2704
0
    result = -1;
2705
0
  }
2706
0
  else if( result != 0 )
2707
0
  {
2708
0
    if( libvsgpt_partition_initialize(
2709
0
         partition,
2710
0
         internal_volume->file_io_handle,
2711
0
         partition_values,
2712
0
         error ) != 1 )
2713
0
    {
2714
0
      libcerror_error_set(
2715
0
       error,
2716
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2717
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2718
0
       "%s: unable to create partition.",
2719
0
       function );
2720
2721
0
      result = -1;
2722
0
    }
2723
0
  }
2724
0
#if defined( HAVE_LIBVSGPT_MULTI_THREAD_SUPPORT )
2725
0
  if( libcthreads_read_write_lock_release_for_read(
2726
0
       internal_volume->read_write_lock,
2727
0
       error ) != 1 )
2728
0
  {
2729
0
    libcerror_error_set(
2730
0
     error,
2731
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2732
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2733
0
     "%s: unable to release read/write lock for reading.",
2734
0
     function );
2735
2736
0
    result = -1;
2737
0
  }
2738
0
#endif
2739
0
  if( result == -1 )
2740
0
  {
2741
0
    goto on_error;
2742
0
  }
2743
0
  return( result );
2744
2745
0
on_error:
2746
0
  if( *partition != NULL )
2747
0
  {
2748
0
    libvsgpt_partition_free(
2749
0
     partition,
2750
     NULL );
2751
0
  }
2752
0
  return( -1 );
2753
0
}
2754