Coverage Report

Created: 2026-02-19 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfvde/libfvde/libfvde_physical_volume.c
Line
Count
Source
1
/*
2
 * Physical volume 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_libcerror.h"
28
#include "libfvde_libcthreads.h"
29
#include "libfvde_physical_volume.h"
30
#include "libfvde_physical_volume_descriptor.h"
31
#include "libfvde_types.h"
32
#include "libfvde_volume_header.h"
33
34
/* Creates a physical volume
35
 * Make sure the value physical_volume is referencing, is set to NULL
36
 * Returns 1 if successful or -1 on error
37
 */
38
int libfvde_physical_volume_initialize(
39
     libfvde_physical_volume_t **physical_volume,
40
     libfvde_volume_header_t *volume_header,
41
     libfvde_physical_volume_descriptor_t *physical_volume_descriptor,
42
     libcerror_error_t **error )
43
0
{
44
0
  libfvde_internal_physical_volume_t *internal_physical_volume = NULL;
45
0
  static char *function                                        = "libfvde_physical_volume_initialize";
46
47
0
  if( physical_volume == NULL )
48
0
  {
49
0
    libcerror_error_set(
50
0
     error,
51
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53
0
     "%s: invalid physical volume.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
0
  if( *physical_volume != NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
63
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64
0
     "%s: invalid physical volume value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
0
  if( volume_header == NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
74
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
75
0
     "%s: invalid volume header.",
76
0
     function );
77
78
0
    return( -1 );
79
0
  }
80
0
  if( physical_volume_descriptor == NULL )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
85
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
86
0
     "%s: invalid physical volume descriptor.",
87
0
     function );
88
89
0
    return( -1 );
90
0
  }
91
0
  internal_physical_volume = memory_allocate_structure(
92
0
                              libfvde_internal_physical_volume_t );
93
94
0
  if( internal_physical_volume == NULL )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
99
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
100
0
     "%s: unable to create physical volume.",
101
0
     function );
102
103
0
    goto on_error;
104
0
  }
105
0
  if( memory_set(
106
0
       internal_physical_volume,
107
0
       0,
108
0
       sizeof( libfvde_internal_physical_volume_t ) ) == NULL )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
113
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
114
0
     "%s: unable to clear physical volume.",
115
0
     function );
116
117
0
    memory_free(
118
0
     internal_physical_volume );
119
120
0
    return( -1 );
121
0
  }
122
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
123
0
  if( libcthreads_read_write_lock_initialize(
124
0
       &( internal_physical_volume->read_write_lock ),
125
0
       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 initialize read/write lock.",
132
0
     function );
133
134
0
    goto on_error;
135
0
  }
136
0
#endif
137
0
  internal_physical_volume->volume_header              = volume_header;
138
0
  internal_physical_volume->physical_volume_descriptor = physical_volume_descriptor;
139
140
0
  *physical_volume = (libfvde_physical_volume_t *) internal_physical_volume;
141
142
0
  return( 1 );
143
144
0
on_error:
145
0
  if( internal_physical_volume != NULL )
146
0
  {
147
0
    memory_free(
148
0
     internal_physical_volume );
149
0
  }
150
0
  return( -1 );
151
0
}
152
153
/* Frees a physical volume
154
 * Returns 1 if successful or -1 on error
155
 */
156
int libfvde_physical_volume_free(
157
     libfvde_physical_volume_t **physical_volume,
158
     libcerror_error_t **error )
159
0
{
160
0
  libfvde_internal_physical_volume_t *internal_physical_volume = NULL;
161
0
  static char *function                                        = "libfvde_physical_volume_free";
162
0
  int result                                                   = 1;
163
164
0
  if( physical_volume == NULL )
165
0
  {
166
0
    libcerror_error_set(
167
0
     error,
168
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
169
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
170
0
     "%s: invalid physical volume.",
171
0
     function );
172
173
0
    return( -1 );
174
0
  }
175
0
  if( *physical_volume != NULL )
176
0
  {
177
0
    internal_physical_volume = (libfvde_internal_physical_volume_t *) *physical_volume;
178
0
    *physical_volume         = NULL;
179
180
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
181
0
    if( libcthreads_read_write_lock_free(
182
0
         &( internal_physical_volume->read_write_lock ),
183
0
         error ) != 1 )
184
0
    {
185
0
      libcerror_error_set(
186
0
       error,
187
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
188
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
189
0
       "%s: unable to free read/write lock.",
190
0
       function );
191
192
0
      result = -1;
193
0
    }
194
0
#endif
195
    /* The volume_header and physical_volume_descriptor references are freed elsewhere
196
     */
197
0
    memory_free(
198
0
     internal_physical_volume );
199
0
  }
200
0
  return( result );
201
0
}
202
203
/* Retrieves the physical volume identifier
204
 * The identifier is a UUID and is 16 bytes of size
205
 * Returns 1 if successful or -1 on error
206
 */
207
int libfvde_physical_volume_get_identifier(
208
     libfvde_physical_volume_t *physical_volume,
209
     uint8_t *uuid_data,
210
     size_t uuid_data_size,
211
     libcerror_error_t **error )
212
0
{
213
0
  libfvde_internal_physical_volume_t *internal_physical_volume = NULL;
214
0
  static char *function                                        = "libfvde_physical_volume_get_identifier";
215
0
  int result                                                   = 1;
216
217
0
  if( physical_volume == NULL )
218
0
  {
219
0
    libcerror_error_set(
220
0
     error,
221
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
222
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
223
0
     "%s: invalid physical volume.",
224
0
     function );
225
226
0
    return( -1 );
227
0
  }
228
0
  internal_physical_volume = (libfvde_internal_physical_volume_t *) physical_volume;
229
230
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
231
0
  if( libcthreads_read_write_lock_grab_for_read(
232
0
       internal_physical_volume->read_write_lock,
233
0
       error ) != 1 )
234
0
  {
235
0
    libcerror_error_set(
236
0
     error,
237
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
238
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
239
0
     "%s: unable to grab read/write lock for reading.",
240
0
     function );
241
242
0
    return( -1 );
243
0
  }
244
0
#endif
245
0
  if( libfvde_physical_volume_descriptor_get_identifier(
246
0
       internal_physical_volume->physical_volume_descriptor,
247
0
       uuid_data,
248
0
       uuid_data_size,
249
0
       error ) != 1 )
250
0
  {
251
0
    libcerror_error_set(
252
0
     error,
253
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
254
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
255
0
     "%s: unable to retrieve physical volume identifier from descriptor.",
256
0
     function );
257
258
0
    result = -1;
259
0
  }
260
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
261
0
  if( libcthreads_read_write_lock_release_for_read(
262
0
       internal_physical_volume->read_write_lock,
263
0
       error ) != 1 )
264
0
  {
265
0
    libcerror_error_set(
266
0
     error,
267
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
268
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
269
0
     "%s: unable to release read/write lock for reading.",
270
0
     function );
271
272
0
    return( -1 );
273
0
  }
274
0
#endif
275
0
  return( result );
276
0
}
277
278
/* Retrieves the volume encryption method
279
 * Returns 1 if successful or -1 on error
280
 */
281
int libfvde_physical_volume_get_encryption_method(
282
     libfvde_physical_volume_t *physical_volume,
283
     uint32_t *encryption_method,
284
     libcerror_error_t **error )
285
0
{
286
0
  libfvde_internal_physical_volume_t *internal_physical_volume = NULL;
287
0
  static char *function                                        = "libfvde_physical_volume_get_encryption_method";
288
0
  int result                                                   = 1;
289
290
0
  if( physical_volume == NULL )
291
0
  {
292
0
    libcerror_error_set(
293
0
     error,
294
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
295
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
296
0
     "%s: invalid physical volume.",
297
0
     function );
298
299
0
    return( -1 );
300
0
  }
301
0
  internal_physical_volume = (libfvde_internal_physical_volume_t *) physical_volume;
302
303
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
304
0
  if( libcthreads_read_write_lock_grab_for_read(
305
0
       internal_physical_volume->read_write_lock,
306
0
       error ) != 1 )
307
0
  {
308
0
    libcerror_error_set(
309
0
     error,
310
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
311
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
312
0
     "%s: unable to grab read/write lock for reading.",
313
0
     function );
314
315
0
    return( -1 );
316
0
  }
317
0
#endif
318
0
  if( libfvde_volume_header_get_physical_volume_encryption_method(
319
0
       internal_physical_volume->volume_header,
320
0
       encryption_method,
321
0
       error ) != 1 )
322
0
  {
323
0
    libcerror_error_set(
324
0
     error,
325
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
326
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
327
0
     "%s: unable to retrieve physical volume encryption method from volume header.",
328
0
     function );
329
330
0
    result = -1;
331
0
  }
332
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
333
0
  if( libcthreads_read_write_lock_release_for_read(
334
0
       internal_physical_volume->read_write_lock,
335
0
       error ) != 1 )
336
0
  {
337
0
    libcerror_error_set(
338
0
     error,
339
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
340
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
341
0
     "%s: unable to release read/write lock for reading.",
342
0
     function );
343
344
0
    return( -1 );
345
0
  }
346
0
#endif
347
0
  return( result );
348
0
}
349
350
/* Retrieves the volume size
351
 * Returns 1 if successful or -1 on error
352
 */
353
int libfvde_physical_volume_get_size(
354
     libfvde_physical_volume_t *physical_volume,
355
     size64_t *size,
356
     libcerror_error_t **error )
357
0
{
358
0
  libfvde_internal_physical_volume_t *internal_physical_volume = NULL;
359
0
  static char *function                                        = "libfvde_physical_volume_get_size";
360
0
  int result                                                   = 1;
361
362
0
  if( physical_volume == NULL )
363
0
  {
364
0
    libcerror_error_set(
365
0
     error,
366
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
367
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
368
0
     "%s: invalid physical volume.",
369
0
     function );
370
371
0
    return( -1 );
372
0
  }
373
0
  internal_physical_volume = (libfvde_internal_physical_volume_t *) physical_volume;
374
375
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
376
0
  if( libcthreads_read_write_lock_grab_for_read(
377
0
       internal_physical_volume->read_write_lock,
378
0
       error ) != 1 )
379
0
  {
380
0
    libcerror_error_set(
381
0
     error,
382
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
383
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
384
0
     "%s: unable to grab read/write lock for reading.",
385
0
     function );
386
387
0
    return( -1 );
388
0
  }
389
0
#endif
390
0
  if( libfvde_volume_header_get_physical_volume_size(
391
0
       internal_physical_volume->volume_header,
392
0
       size,
393
0
       error ) != 1 )
394
0
  {
395
0
    libcerror_error_set(
396
0
     error,
397
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
399
0
     "%s: unable to retrieve physical volume size from volume header.",
400
0
     function );
401
402
0
    result = -1;
403
0
  }
404
0
#if defined( HAVE_LIBFVDE_MULTI_THREAD_SUPPORT )
405
0
  if( libcthreads_read_write_lock_release_for_read(
406
0
       internal_physical_volume->read_write_lock,
407
0
       error ) != 1 )
408
0
  {
409
0
    libcerror_error_set(
410
0
     error,
411
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
412
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
413
0
     "%s: unable to release read/write lock for reading.",
414
0
     function );
415
416
0
    return( -1 );
417
0
  }
418
0
#endif
419
0
  return( result );
420
0
}
421