Coverage Report

Created: 2026-04-10 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfvde/libfvde/libfvde_volume_group.c
Line
Count
Source
1
/*
2
 * Volume group functions
3
 *
4
 * Copyright (C) 2011-2025, Omar Choudary <choudary.omar@gmail.com>,
5
 *                          Joachim Metz <joachim.metz@gmail.com>
6
 *
7
 * Refer to AUTHORS for acknowledgements.
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
#include <common.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libfvde_encrypted_metadata.h"
28
#include "libfvde_encryption_context_plist.h"
29
#include "libfvde_io_handle.h"
30
#include "libfvde_libcerror.h"
31
#include "libfvde_libcthreads.h"
32
#include "libfvde_logical_volume.h"
33
#include "libfvde_metadata.h"
34
#include "libfvde_physical_volume.h"
35
#include "libfvde_physical_volume_descriptor.h"
36
#include "libfvde_types.h"
37
#include "libfvde_volume_group.h"
38
#include "libfvde_volume_header.h"
39
40
/* Creates a volume group
41
 * Make sure the value volume_group is referencing, is set to NULL
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libfvde_volume_group_initialize(
45
     libfvde_volume_group_t **volume_group,
46
     libfvde_io_handle_t *io_handle,
47
     libbfio_pool_t *file_io_pool,
48
     libfvde_volume_header_t *volume_header,
49
     libfvde_metadata_t *metadata,
50
     libfvde_encrypted_metadata_t *encrypted_metadata,
51
     libfvde_encryption_context_plist_t *encrypted_root_plist,
52
     libcerror_error_t **error )
53
0
{
54
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
55
0
  static char *function                                  = "libfvde_volume_group_initialize";
56
57
0
  if( volume_group == NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
63
0
     "%s: invalid volume group.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
0
  if( *volume_group != NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
74
0
     "%s: invalid volume group value already set.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
0
  if( io_handle == NULL )
80
0
  {
81
0
    libcerror_error_set(
82
0
     error,
83
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
84
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
85
0
     "%s: invalid IO handle.",
86
0
     function );
87
88
0
    return( -1 );
89
0
  }
90
0
  if( volume_header == NULL )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
95
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
96
0
     "%s: invalid volume header.",
97
0
     function );
98
99
0
    return( -1 );
100
0
  }
101
/* TODO check if metadata is set */
102
/* TODO check if encrypted_metadata is set */
103
/* TODO check if encrypted_root_plist is set */
104
105
0
  internal_volume_group = memory_allocate_structure(
106
0
                           libfvde_internal_volume_group_t );
107
108
0
  if( internal_volume_group == NULL )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
113
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
114
0
     "%s: unable to create volume group.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
0
  if( memory_set(
120
0
       internal_volume_group,
121
0
       0,
122
0
       sizeof( libfvde_internal_volume_group_t ) ) == NULL )
123
0
  {
124
0
    libcerror_error_set(
125
0
     error,
126
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
127
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
128
0
     "%s: unable to clear volume group.",
129
0
     function );
130
131
0
    memory_free(
132
0
     internal_volume_group );
133
134
0
    return( -1 );
135
0
  }
136
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
137
0
  if( libcthreads_read_write_lock_initialize(
138
0
       &( internal_volume_group->read_write_lock ),
139
0
       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
0
#endif
151
0
  internal_volume_group->io_handle            = io_handle;
152
0
  internal_volume_group->file_io_pool         = file_io_pool;
153
0
  internal_volume_group->volume_header        = volume_header;
154
0
  internal_volume_group->metadata             = metadata;
155
0
  internal_volume_group->encrypted_metadata   = encrypted_metadata;
156
0
  internal_volume_group->encrypted_root_plist = encrypted_root_plist;
157
158
0
  *volume_group = (libfvde_volume_group_t *) internal_volume_group;
159
160
0
  return( 1 );
161
162
0
on_error:
163
0
  if( internal_volume_group != NULL )
164
0
  {
165
0
    memory_free(
166
0
     internal_volume_group );
167
0
  }
168
0
  return( -1 );
169
0
}
170
171
/* Frees a volume group
172
 * Returns 1 if successful or -1 on error
173
 */
174
int libfvde_volume_group_free(
175
     libfvde_volume_group_t **volume_group,
176
     libcerror_error_t **error )
177
0
{
178
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
179
0
  static char *function                                  = "libfvde_volume_group_free";
180
0
  int result                                             = 1;
181
182
0
  if( volume_group == NULL )
183
0
  {
184
0
    libcerror_error_set(
185
0
     error,
186
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
187
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
188
0
     "%s: invalid volume group.",
189
0
     function );
190
191
0
    return( -1 );
192
0
  }
193
0
  if( *volume_group != NULL )
194
0
  {
195
0
    internal_volume_group = (libfvde_internal_volume_group_t *) *volume_group;
196
0
    *volume_group         = NULL;
197
198
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
199
0
    if( libcthreads_read_write_lock_free(
200
0
         &( internal_volume_group->read_write_lock ),
201
0
         error ) != 1 )
202
0
    {
203
0
      libcerror_error_set(
204
0
       error,
205
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
206
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
207
0
       "%s: unable to free read/write lock.",
208
0
       function );
209
210
0
      result = -1;
211
0
    }
212
0
#endif
213
    /* The volume_header and metadata references are freed elsewhere
214
     */
215
0
    memory_free(
216
0
     internal_volume_group );
217
0
  }
218
0
  return( result );
219
0
}
220
221
/* Retrieves the (logical) volume group identifier
222
 * The identifier is a UUID and is 16 bytes of size
223
 * Returns 1 if successful or -1 on error
224
 */
225
int libfvde_volume_group_get_identifier(
226
     libfvde_volume_group_t *volume_group,
227
     uint8_t *uuid_data,
228
     size_t uuid_data_size,
229
     libcerror_error_t **error )
230
0
{
231
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
232
0
  static char *function                                  = "libfvde_volume_group_get_identifier";
233
0
  int result                                             = 1;
234
235
0
  if( volume_group == NULL )
236
0
  {
237
0
    libcerror_error_set(
238
0
     error,
239
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
241
0
     "%s: invalid volume group.",
242
0
     function );
243
244
0
    return( -1 );
245
0
  }
246
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
247
248
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
249
0
  if( libcthreads_read_write_lock_grab_for_read(
250
0
       internal_volume_group->read_write_lock,
251
0
       error ) != 1 )
252
0
  {
253
0
    libcerror_error_set(
254
0
     error,
255
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
256
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
257
0
     "%s: unable to grab read/write lock for reading.",
258
0
     function );
259
260
0
    return( -1 );
261
0
  }
262
0
#endif
263
0
  if( libfvde_volume_header_get_volume_group_identifier(
264
0
       internal_volume_group->volume_header,
265
0
       uuid_data,
266
0
       uuid_data_size,
267
0
       error ) != 1 )
268
0
  {
269
0
    libcerror_error_set(
270
0
     error,
271
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
272
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
273
0
     "%s: unable to retrieve volume group identifier from volume header.",
274
0
     function );
275
276
0
    result = -1;
277
0
  }
278
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
279
0
  if( libcthreads_read_write_lock_release_for_read(
280
0
       internal_volume_group->read_write_lock,
281
0
       error ) != 1 )
282
0
  {
283
0
    libcerror_error_set(
284
0
     error,
285
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
286
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
287
0
     "%s: unable to release read/write lock for reading.",
288
0
     function );
289
290
0
    return( -1 );
291
0
  }
292
0
#endif
293
0
  return( result );
294
0
}
295
296
/* Retrieves the size of the UTF-8 encoded name
297
 * The returned size includes the end of string character
298
 * Returns 1 if successful, 0 if not available or -1 on error
299
 */
300
int libfvde_volume_group_get_utf8_name_size(
301
     libfvde_volume_group_t *volume_group,
302
     size_t *utf8_string_size,
303
     libcerror_error_t **error )
304
0
{
305
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
306
0
  static char *function                                  = "libfvde_volume_group_get_utf8_name_size";
307
0
  int result                                             = 0;
308
309
0
  if( volume_group == 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 group.",
316
0
     function );
317
318
0
    return( -1 );
319
0
  }
320
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
321
322
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
323
0
  if( libcthreads_read_write_lock_grab_for_write(
324
0
       internal_volume_group->read_write_lock,
325
0
       error ) != 1 )
326
0
  {
327
0
    libcerror_error_set(
328
0
     error,
329
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
330
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
331
0
     "%s: unable to grab read/write lock for writing.",
332
0
     function );
333
334
0
    return( -1 );
335
0
  }
336
0
#endif
337
0
  result = libfvde_metadata_get_utf8_volume_group_name_size(
338
0
            internal_volume_group->metadata,
339
0
            utf8_string_size,
340
0
            error );
341
342
0
  if( result == -1 )
343
0
  {
344
0
    libcerror_error_set(
345
0
     error,
346
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
347
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
348
0
     "%s: unable to retrieve size of UTF-8 volume group name from metadata.",
349
0
     function );
350
351
0
    result = -1;
352
0
  }
353
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
354
0
  if( libcthreads_read_write_lock_release_for_write(
355
0
       internal_volume_group->read_write_lock,
356
0
       error ) != 1 )
357
0
  {
358
0
    libcerror_error_set(
359
0
     error,
360
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
361
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
362
0
     "%s: unable to release read/write lock for writing.",
363
0
     function );
364
365
0
    return( -1 );
366
0
  }
367
0
#endif
368
0
  return( result );
369
0
}
370
371
/* Retrieves the UTF-8 encoded name
372
 * The size should include the end of string character
373
 * Returns 1 if successful, 0 if not available or -1 on error
374
 */
375
int libfvde_volume_group_get_utf8_name(
376
     libfvde_volume_group_t *volume_group,
377
     uint8_t *utf8_string,
378
     size_t utf8_string_size,
379
     libcerror_error_t **error )
380
0
{
381
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
382
0
  static char *function                                  = "libfvde_volume_group_get_utf8_name";
383
0
  int result                                             = 0;
384
385
0
  if( volume_group == NULL )
386
0
  {
387
0
    libcerror_error_set(
388
0
     error,
389
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
390
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
391
0
     "%s: invalid volume group.",
392
0
     function );
393
394
0
    return( -1 );
395
0
  }
396
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
397
398
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
399
0
  if( libcthreads_read_write_lock_grab_for_write(
400
0
       internal_volume_group->read_write_lock,
401
0
       error ) != 1 )
402
0
  {
403
0
    libcerror_error_set(
404
0
     error,
405
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
406
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
407
0
     "%s: unable to grab read/write lock for writing.",
408
0
     function );
409
410
0
    return( -1 );
411
0
  }
412
0
#endif
413
0
  result = libfvde_metadata_get_utf8_volume_group_name(
414
0
            internal_volume_group->metadata,
415
0
            utf8_string,
416
0
            utf8_string_size,
417
0
            error );
418
419
0
  if( result == -1 )
420
0
  {
421
0
    libcerror_error_set(
422
0
     error,
423
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
424
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
425
0
     "%s: unable to retrieve UTF-8 volume group name from metadata.",
426
0
     function );
427
428
0
    result = -1;
429
0
  }
430
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
431
0
  if( libcthreads_read_write_lock_release_for_write(
432
0
       internal_volume_group->read_write_lock,
433
0
       error ) != 1 )
434
0
  {
435
0
    libcerror_error_set(
436
0
     error,
437
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
438
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
439
0
     "%s: unable to release read/write lock for writing.",
440
0
     function );
441
442
0
    return( -1 );
443
0
  }
444
0
#endif
445
0
  return( result );
446
0
}
447
448
/* Retrieves the size of the UTF-16 encoded name
449
 * The returned size includes the end of string character
450
 * Returns 1 if successful, 0 if not available or -1 on error
451
 */
452
int libfvde_volume_group_get_utf16_name_size(
453
     libfvde_volume_group_t *volume_group,
454
     size_t *utf16_string_size,
455
     libcerror_error_t **error )
456
0
{
457
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
458
0
  static char *function                                  = "libfvde_volume_group_get_utf16_name_size";
459
0
  int result                                             = 0;
460
461
0
  if( volume_group == NULL )
462
0
  {
463
0
    libcerror_error_set(
464
0
     error,
465
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
466
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
467
0
     "%s: invalid volume group.",
468
0
     function );
469
470
0
    return( -1 );
471
0
  }
472
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
473
474
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
475
0
  if( libcthreads_read_write_lock_grab_for_write(
476
0
       internal_volume_group->read_write_lock,
477
0
       error ) != 1 )
478
0
  {
479
0
    libcerror_error_set(
480
0
     error,
481
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
482
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
483
0
     "%s: unable to grab read/write lock for writing.",
484
0
     function );
485
486
0
    return( -1 );
487
0
  }
488
0
#endif
489
0
  result = libfvde_metadata_get_utf16_volume_group_name_size(
490
0
            internal_volume_group->metadata,
491
0
            utf16_string_size,
492
0
            error );
493
494
0
  if( result == -1 )
495
0
  {
496
0
    libcerror_error_set(
497
0
     error,
498
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
499
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
500
0
     "%s: unable to retrieve size of UTF-16 volume group name from metadata.",
501
0
     function );
502
503
0
    result = -1;
504
0
  }
505
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
506
0
  if( libcthreads_read_write_lock_release_for_write(
507
0
       internal_volume_group->read_write_lock,
508
0
       error ) != 1 )
509
0
  {
510
0
    libcerror_error_set(
511
0
     error,
512
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
513
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
514
0
     "%s: unable to release read/write lock for writing.",
515
0
     function );
516
517
0
    return( -1 );
518
0
  }
519
0
#endif
520
0
  return( result );
521
0
}
522
523
/* Retrieves the UTF-16 encoded name
524
 * The size should include the end of string character
525
 * Returns 1 if successful, 0 if not available or -1 on error
526
 */
527
int libfvde_volume_group_get_utf16_name(
528
     libfvde_volume_group_t *volume_group,
529
     uint16_t *utf16_string,
530
     size_t utf16_string_size,
531
     libcerror_error_t **error )
532
0
{
533
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
534
0
  static char *function                                  = "libfvde_volume_group_get_utf16_name";
535
0
  int result                                             = 0;
536
537
0
  if( volume_group == NULL )
538
0
  {
539
0
    libcerror_error_set(
540
0
     error,
541
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
542
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
543
0
     "%s: invalid volume group.",
544
0
     function );
545
546
0
    return( -1 );
547
0
  }
548
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
549
550
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
551
0
  if( libcthreads_read_write_lock_grab_for_write(
552
0
       internal_volume_group->read_write_lock,
553
0
       error ) != 1 )
554
0
  {
555
0
    libcerror_error_set(
556
0
     error,
557
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
558
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
559
0
     "%s: unable to grab read/write lock for writing.",
560
0
     function );
561
562
0
    return( -1 );
563
0
  }
564
0
#endif
565
0
  result = libfvde_metadata_get_utf16_volume_group_name(
566
0
            internal_volume_group->metadata,
567
0
            utf16_string,
568
0
            utf16_string_size,
569
0
            error );
570
571
0
  if( result == -1 )
572
0
  {
573
0
    libcerror_error_set(
574
0
     error,
575
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
576
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
577
0
     "%s: unable to retrieve UTF-16 volume group name from metadata.",
578
0
     function );
579
580
0
    result = -1;
581
0
  }
582
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
583
0
  if( libcthreads_read_write_lock_release_for_write(
584
0
       internal_volume_group->read_write_lock,
585
0
       error ) != 1 )
586
0
  {
587
0
    libcerror_error_set(
588
0
     error,
589
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
590
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
591
0
     "%s: unable to release read/write lock for writing.",
592
0
     function );
593
594
0
    return( -1 );
595
0
  }
596
0
#endif
597
0
  return( result );
598
0
}
599
600
/* Retrieves the number of physical volumes
601
 * Returns 1 if successful or -1 on error
602
 */
603
int libfvde_volume_group_get_number_of_physical_volumes(
604
     libfvde_volume_group_t *volume_group,
605
     int *number_of_physical_volumes,
606
     libcerror_error_t **error )
607
0
{
608
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
609
0
  static char *function                                  = "libfvde_volume_group_get_number_of_physical_volumes";
610
0
  int result                                             = 1;
611
612
0
  if( volume_group == NULL )
613
0
  {
614
0
    libcerror_error_set(
615
0
     error,
616
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
617
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
618
0
     "%s: invalid volume group.",
619
0
     function );
620
621
0
    return( -1 );
622
0
  }
623
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
624
625
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
626
0
  if( libcthreads_read_write_lock_grab_for_read(
627
0
       internal_volume_group->read_write_lock,
628
0
       error ) != 1 )
629
0
  {
630
0
    libcerror_error_set(
631
0
     error,
632
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
633
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
634
0
     "%s: unable to grab read/write lock for reading.",
635
0
     function );
636
637
0
    return( -1 );
638
0
  }
639
0
#endif
640
0
  if( libfvde_metadata_get_number_of_physical_volume_descriptors(
641
0
       internal_volume_group->metadata,
642
0
       number_of_physical_volumes,
643
0
       error ) != 1 )
644
0
  {
645
0
    libcerror_error_set(
646
0
     error,
647
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
648
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
649
0
     "%s: unable to retrieve number of physical volume descriptors from metadata.",
650
0
     function );
651
652
0
    result = -1;
653
0
  }
654
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
655
0
  if( libcthreads_read_write_lock_release_for_read(
656
0
       internal_volume_group->read_write_lock,
657
0
       error ) != 1 )
658
0
  {
659
0
    libcerror_error_set(
660
0
     error,
661
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
662
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
663
0
     "%s: unable to release read/write lock for reading.",
664
0
     function );
665
666
0
    return( -1 );
667
0
  }
668
0
#endif
669
0
  return( result );
670
0
}
671
672
/* Retrieves a specific physical volume
673
 * Returns 1 if successful or -1 on error
674
 */
675
int libfvde_volume_group_get_physical_volume_by_index(
676
     libfvde_volume_group_t *volume_group,
677
     int volume_index,
678
     libfvde_physical_volume_t **physical_volume,
679
     libcerror_error_t **error )
680
0
{
681
0
  libfvde_internal_volume_group_t *internal_volume_group           = NULL;
682
0
  libfvde_physical_volume_descriptor_t *physical_volume_descriptor = NULL;
683
0
  static char *function                                            = "libfvde_volume_group_get_physical_volume_by_index";
684
0
  int result                                                       = 1;
685
686
0
  if( volume_group == NULL )
687
0
  {
688
0
    libcerror_error_set(
689
0
     error,
690
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
691
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
692
0
     "%s: invalid volume group.",
693
0
     function );
694
695
0
    return( -1 );
696
0
  }
697
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
698
699
0
  if( physical_volume == NULL )
700
0
  {
701
0
    libcerror_error_set(
702
0
     error,
703
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
704
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
705
0
     "%s: invalid physical volume.",
706
0
     function );
707
708
0
    return( -1 );
709
0
  }
710
0
  if( *physical_volume != NULL )
711
0
  {
712
0
    libcerror_error_set(
713
0
     error,
714
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
715
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
716
0
     "%s: invalid physical volume value already set.",
717
0
     function );
718
719
0
    return( -1 );
720
0
  }
721
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
722
0
  if( libcthreads_read_write_lock_grab_for_read(
723
0
       internal_volume_group->read_write_lock,
724
0
       error ) != 1 )
725
0
  {
726
0
    libcerror_error_set(
727
0
     error,
728
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
729
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
730
0
     "%s: unable to grab read/write lock for reading.",
731
0
     function );
732
733
0
    return( -1 );
734
0
  }
735
0
#endif
736
0
  if( libfvde_metadata_get_physical_volume_descriptor_by_index(
737
0
       internal_volume_group->metadata,
738
0
       volume_index,
739
0
       &physical_volume_descriptor,
740
0
       error ) != 1 )
741
0
  {
742
0
    libcerror_error_set(
743
0
     error,
744
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
745
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
746
0
     "%s: unable to retrieve physical volume descriptor: %d from metadata.",
747
0
     function,
748
0
     volume_index );
749
750
0
    result = -1;
751
0
  }
752
0
  else
753
0
  {
754
0
    if( libfvde_physical_volume_initialize(
755
0
          physical_volume,
756
0
          internal_volume_group->volume_header,
757
0
          physical_volume_descriptor,
758
0
          error ) != 1 )
759
0
    {
760
0
      libcerror_error_set(
761
0
       error,
762
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
763
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
764
0
       "%s: unable to create physical volume.",
765
0
       function );
766
767
0
      result = -1;
768
0
    }
769
0
  }
770
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
771
0
  if( libcthreads_read_write_lock_release_for_read(
772
0
       internal_volume_group->read_write_lock,
773
0
       error ) != 1 )
774
0
  {
775
0
    libcerror_error_set(
776
0
     error,
777
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
778
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
779
0
     "%s: unable to release read/write lock for reading.",
780
0
     function );
781
782
0
    return( -1 );
783
0
  }
784
0
#endif
785
0
  return( result );
786
0
}
787
788
/* Retrieves the number of logical volumes
789
 * Returns 1 if successful or -1 on error
790
 */
791
int libfvde_volume_group_get_number_of_logical_volumes(
792
     libfvde_volume_group_t *volume_group,
793
     int *number_of_logical_volumes,
794
     libcerror_error_t **error )
795
0
{
796
0
  libfvde_internal_volume_group_t *internal_volume_group = NULL;
797
0
  static char *function                                  = "libfvde_volume_group_get_number_of_logical_volumes";
798
0
  int result                                             = 1;
799
800
0
  if( volume_group == NULL )
801
0
  {
802
0
    libcerror_error_set(
803
0
     error,
804
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
805
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
806
0
     "%s: invalid volume group.",
807
0
     function );
808
809
0
    return( -1 );
810
0
  }
811
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
812
813
0
  if( number_of_logical_volumes == NULL )
814
0
  {
815
0
    libcerror_error_set(
816
0
     error,
817
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
818
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
819
0
     "%s: invalid number of logical_volumes.",
820
0
     function );
821
822
0
    return( -1 );
823
0
  }
824
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
825
0
  if( libcthreads_read_write_lock_grab_for_read(
826
0
       internal_volume_group->read_write_lock,
827
0
       error ) != 1 )
828
0
  {
829
0
    libcerror_error_set(
830
0
     error,
831
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
832
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
833
0
     "%s: unable to grab read/write lock for reading.",
834
0
     function );
835
836
0
    return( -1 );
837
0
  }
838
0
#endif
839
0
  if( libfvde_encrypted_metadata_get_number_of_logical_volume_descriptors(
840
0
       internal_volume_group->encrypted_metadata,
841
0
       number_of_logical_volumes,
842
0
       error ) != 1 )
843
0
  {
844
0
    libcerror_error_set(
845
0
     error,
846
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
847
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
848
0
     "%s: unable to retrieve number of logical volume descriptors from encrypted metadata.",
849
0
     function );
850
851
0
    result = -1;
852
0
  }
853
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
854
0
  if( libcthreads_read_write_lock_release_for_read(
855
0
       internal_volume_group->read_write_lock,
856
0
       error ) != 1 )
857
0
  {
858
0
    libcerror_error_set(
859
0
     error,
860
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
861
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
862
0
     "%s: unable to release read/write lock for reading.",
863
0
     function );
864
865
0
    return( -1 );
866
0
  }
867
0
#endif
868
0
  return( result );
869
0
}
870
871
/* Retrieves a specific logical volume
872
 * Returns 1 if successful or -1 on error
873
 */
874
int libfvde_volume_group_get_logical_volume_by_index(
875
     libfvde_volume_group_t *volume_group,
876
     int volume_index,
877
     libfvde_logical_volume_t **logical_volume,
878
     libcerror_error_t **error )
879
0
{
880
0
  libfvde_internal_volume_group_t *internal_volume_group         = NULL;
881
0
  libfvde_logical_volume_descriptor_t *logical_volume_descriptor = NULL;
882
0
  static char *function                                          = "libfvde_volume_group_get_logical_volume_by_index";
883
0
  int result                                                     = 1;
884
885
0
  if( volume_group == NULL )
886
0
  {
887
0
    libcerror_error_set(
888
0
     error,
889
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
890
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
891
0
     "%s: invalid volume group.",
892
0
     function );
893
894
0
    return( -1 );
895
0
  }
896
0
  internal_volume_group = (libfvde_internal_volume_group_t *) volume_group;
897
898
0
  if( logical_volume == NULL )
899
0
  {
900
0
    libcerror_error_set(
901
0
     error,
902
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
903
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
904
0
     "%s: invalid logical volume.",
905
0
     function );
906
907
0
    return( -1 );
908
0
  }
909
0
  if( *logical_volume != NULL )
910
0
  {
911
0
    libcerror_error_set(
912
0
     error,
913
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
914
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
915
0
     "%s: invalid logical volume value already set.",
916
0
     function );
917
918
0
    return( -1 );
919
0
  }
920
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
921
0
  if( libcthreads_read_write_lock_grab_for_read(
922
0
       internal_volume_group->read_write_lock,
923
0
       error ) != 1 )
924
0
  {
925
0
    libcerror_error_set(
926
0
     error,
927
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
928
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
929
0
     "%s: unable to grab read/write lock for reading.",
930
0
     function );
931
932
0
    return( -1 );
933
0
  }
934
0
#endif
935
0
  if( libfvde_encrypted_metadata_get_logical_volume_descriptor_by_index(
936
0
       internal_volume_group->encrypted_metadata,
937
0
       volume_index,
938
0
       &logical_volume_descriptor,
939
0
       error ) != 1 )
940
0
  {
941
0
    libcerror_error_set(
942
0
     error,
943
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
944
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
945
0
     "%s: unable to retrieve logical volume descriptor: %d from encrypted metadata.",
946
0
     function,
947
0
     volume_index );
948
949
0
    result = -1;
950
0
  }
951
0
  else
952
0
  {
953
0
    if( libfvde_logical_volume_initialize(
954
0
          logical_volume,
955
0
          internal_volume_group->io_handle,
956
0
          internal_volume_group->file_io_pool,
957
0
          logical_volume_descriptor,
958
0
          internal_volume_group->encrypted_metadata,
959
0
          internal_volume_group->encrypted_root_plist,
960
0
          error ) != 1 )
961
0
    {
962
0
      libcerror_error_set(
963
0
       error,
964
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
965
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
966
0
       "%s: unable to create logical volume.",
967
0
       function );
968
969
0
      result = -1;
970
0
    }
971
0
    else if( libfvde_internal_logical_volume_open_read(
972
0
              (libfvde_internal_logical_volume_t *) *logical_volume,
973
0
              internal_volume_group->file_io_pool,
974
0
              error ) != 1 )
975
0
    {
976
0
      libcerror_error_set(
977
0
       error,
978
0
       LIBCERROR_ERROR_DOMAIN_IO,
979
0
       LIBCERROR_IO_ERROR_READ_FAILED,
980
0
       "%s: unable to read logical volume.",
981
0
       function );
982
983
0
      libfvde_logical_volume_free(
984
0
       logical_volume,
985
0
       NULL );
986
987
0
      result = -1;
988
0
    }
989
0
  }
990
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
991
0
  if( libcthreads_read_write_lock_release_for_read(
992
0
       internal_volume_group->read_write_lock,
993
0
       error ) != 1 )
994
0
  {
995
0
    libcerror_error_set(
996
0
     error,
997
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
998
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
999
0
     "%s: unable to release read/write lock for reading.",
1000
0
     function );
1001
1002
0
    return( -1 );
1003
0
  }
1004
0
#endif
1005
0
  return( result );
1006
0
}
1007