Coverage Report

Created: 2026-03-05 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsapfs/libfsapfs/libfsapfs_volume.c
Line
Count
Source
1
/*
2
 * Volume functions
3
 *
4
 * Copyright (C) 2018-2025, 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 "libfsapfs_container_data_handle.h"
29
#include "libfsapfs_container_key_bag.h"
30
#include "libfsapfs_debug.h"
31
#include "libfsapfs_definitions.h"
32
#include "libfsapfs_encryption_context.h"
33
#include "libfsapfs_extent_reference_tree.h"
34
#include "libfsapfs_file_entry.h"
35
#include "libfsapfs_file_system.h"
36
#include "libfsapfs_file_system_btree.h"
37
#include "libfsapfs_file_system_data_handle.h"
38
#include "libfsapfs_inode.h"
39
#include "libfsapfs_io_handle.h"
40
#include "libfsapfs_libbfio.h"
41
#include "libfsapfs_libcerror.h"
42
#include "libfsapfs_libcnotify.h"
43
#include "libfsapfs_libcthreads.h"
44
#include "libfsapfs_libfdata.h"
45
#include "libfsapfs_libuna.h"
46
#include "libfsapfs_object_map.h"
47
#include "libfsapfs_object_map_btree.h"
48
#include "libfsapfs_object_map_descriptor.h"
49
#include "libfsapfs_snapshot.h"
50
#include "libfsapfs_snapshot_metadata.h"
51
#include "libfsapfs_snapshot_metadata_tree.h"
52
#include "libfsapfs_volume.h"
53
#include "libfsapfs_volume_key_bag.h"
54
#include "libfsapfs_volume_superblock.h"
55
56
/* Creates a volume
57
 * Make sure the value volume is referencing, is set to NULL
58
 * Returns 1 if successful or -1 on error
59
 */
60
int libfsapfs_volume_initialize(
61
     libfsapfs_volume_t **volume,
62
     libfsapfs_io_handle_t *io_handle,
63
     libbfio_handle_t *file_io_handle,
64
     libfsapfs_container_key_bag_t *container_key_bag,
65
     libcerror_error_t **error )
66
5.20k
{
67
5.20k
  libfsapfs_internal_volume_t *internal_volume = NULL;
68
5.20k
  static char *function                        = "libfsapfs_volume_initialize";
69
70
5.20k
  if( volume == NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
75
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
76
0
     "%s: invalid volume.",
77
0
     function );
78
79
0
    return( -1 );
80
0
  }
81
5.20k
  if( *volume != NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
86
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
87
0
     "%s: invalid volume value already set.",
88
0
     function );
89
90
0
    return( -1 );
91
0
  }
92
5.20k
  if( io_handle == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
97
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
98
0
     "%s: invalid IO handle.",
99
0
     function );
100
101
0
    return( -1 );
102
0
  }
103
5.20k
  if( file_io_handle == NULL )
104
0
  {
105
0
    libcerror_error_set(
106
0
     error,
107
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
108
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
109
0
     "%s: invalid file IO handle.",
110
0
     function );
111
112
0
    return( -1 );
113
0
  }
114
5.20k
  internal_volume = memory_allocate_structure(
115
5.20k
                     libfsapfs_internal_volume_t );
116
117
5.20k
  if( internal_volume == NULL )
118
0
  {
119
0
    libcerror_error_set(
120
0
     error,
121
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
122
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
123
0
     "%s: unable to create volume.",
124
0
     function );
125
126
0
    goto on_error;
127
0
  }
128
5.20k
  if( memory_set(
129
5.20k
       internal_volume,
130
5.20k
       0,
131
5.20k
       sizeof( libfsapfs_internal_volume_t ) ) == NULL )
132
0
  {
133
0
    libcerror_error_set(
134
0
     error,
135
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
136
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
137
0
     "%s: unable to clear volume.",
138
0
     function );
139
140
0
    goto on_error;
141
0
  }
142
/* TODO clone file_io_handle? */
143
5.20k
  internal_volume->io_handle         = io_handle;
144
5.20k
  internal_volume->file_io_handle    = file_io_handle;
145
5.20k
  internal_volume->container_key_bag = container_key_bag;
146
5.20k
  internal_volume->is_locked         = 1;
147
148
5.20k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
149
5.20k
  if( libcthreads_read_write_lock_initialize(
150
5.20k
       &( internal_volume->read_write_lock ),
151
5.20k
       error ) != 1 )
152
0
  {
153
0
    libcerror_error_set(
154
0
     error,
155
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
156
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
157
0
     "%s: unable to initialize read/write lock.",
158
0
     function );
159
160
0
    goto on_error;
161
0
  }
162
5.20k
#endif
163
5.20k
  *volume = (libfsapfs_volume_t *) internal_volume;
164
165
5.20k
  return( 1 );
166
167
0
on_error:
168
0
  if( internal_volume != NULL )
169
0
  {
170
0
    memory_free(
171
0
     internal_volume );
172
0
  }
173
0
  return( -1 );
174
5.20k
}
175
176
/* Frees a volume
177
 * Returns 1 if successful or -1 on error
178
 */
179
int libfsapfs_volume_free(
180
     libfsapfs_volume_t **volume,
181
     libcerror_error_t **error )
182
5.20k
{
183
5.20k
  libfsapfs_internal_volume_t *internal_volume = NULL;
184
5.20k
  static char *function                        = "libfsapfs_volume_free";
185
5.20k
  int result                                   = 1;
186
187
5.20k
  if( volume == NULL )
188
0
  {
189
0
    libcerror_error_set(
190
0
     error,
191
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
192
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
193
0
     "%s: invalid volume.",
194
0
     function );
195
196
0
    return( -1 );
197
0
  }
198
5.20k
  if( *volume != NULL )
199
5.20k
  {
200
5.20k
    internal_volume = (libfsapfs_internal_volume_t *) *volume;
201
5.20k
    *volume         = NULL;
202
203
5.20k
    if( internal_volume->file_io_handle != NULL )
204
5.20k
    {
205
5.20k
      if( libfsapfs_internal_volume_close(
206
5.20k
           internal_volume,
207
5.20k
           error ) != 0 )
208
0
      {
209
0
        libcerror_error_set(
210
0
         error,
211
0
         LIBCERROR_ERROR_DOMAIN_IO,
212
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
213
0
         "%s: unable to close volume.",
214
0
         function );
215
216
0
        result = -1;
217
0
      }
218
5.20k
    }
219
5.20k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
220
5.20k
    if( libcthreads_read_write_lock_free(
221
5.20k
         &( internal_volume->read_write_lock ),
222
5.20k
         error ) != 1 )
223
0
    {
224
0
      libcerror_error_set(
225
0
       error,
226
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
227
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
228
0
       "%s: unable to free read/write lock.",
229
0
       function );
230
231
0
      result = -1;
232
0
    }
233
5.20k
#endif
234
5.20k
    memory_free(
235
5.20k
     internal_volume );
236
5.20k
  }
237
5.20k
  return( result );
238
5.20k
}
239
240
/* Opens a volume for reading
241
 * Returns 1 if successful or -1 on error
242
 */
243
int libfsapfs_internal_volume_open_read(
244
     libfsapfs_internal_volume_t *internal_volume,
245
     libbfio_handle_t *file_io_handle,
246
     off64_t file_offset,
247
     libcerror_error_t **error )
248
5.20k
{
249
5.20k
  libfsapfs_container_data_handle_t *container_data_handle     = NULL;
250
5.20k
  libfsapfs_file_system_data_handle_t *file_system_data_handle = NULL;
251
5.20k
  libfsapfs_object_map_t *object_map                           = NULL;
252
5.20k
  static char *function                                        = "libfsapfs_internal_volume_open_read";
253
5.20k
  uint64_t key_bag_block_number                                = 0;
254
5.20k
  uint64_t key_bag_number_of_blocks                            = 0;
255
5.20k
  int element_index                                            = 0;
256
5.20k
  int result                                                   = 0;
257
258
#if defined( HAVE_DEBUG_OUTPUT )
259
  libfsapfs_extent_reference_tree_t *extent_reference_tree     = NULL;
260
#endif
261
262
5.20k
  if( internal_volume == NULL )
263
0
  {
264
0
    libcerror_error_set(
265
0
     error,
266
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
267
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
268
0
     "%s: invalid volume.",
269
0
     function );
270
271
0
    return( -1 );
272
0
  }
273
5.20k
  if( internal_volume->io_handle == NULL )
274
0
  {
275
0
    libcerror_error_set(
276
0
     error,
277
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
278
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
279
0
     "%s: invalid volume - missing IO handle.",
280
0
     function );
281
282
0
    return( -1 );
283
0
  }
284
5.20k
  if( internal_volume->superblock != NULL )
285
0
  {
286
0
    libcerror_error_set(
287
0
     error,
288
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
289
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
290
0
     "%s: invalid volume - superblock map value already set.",
291
0
     function );
292
293
0
    return( -1 );
294
0
  }
295
5.20k
  if( internal_volume->container_data_block_vector != NULL )
296
0
  {
297
0
    libcerror_error_set(
298
0
     error,
299
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
300
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
301
0
     "%s: invalid volume - container data block vector value already set.",
302
0
     function );
303
304
0
    return( -1 );
305
0
  }
306
5.20k
  if( internal_volume->object_map_btree != NULL )
307
0
  {
308
0
    libcerror_error_set(
309
0
     error,
310
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
311
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
312
0
     "%s: invalid volume - object map B-tree value already set.",
313
0
     function );
314
315
0
    return( -1 );
316
0
  }
317
5.20k
  if( internal_volume->snapshot_metadata_tree != NULL )
318
0
  {
319
0
    libcerror_error_set(
320
0
     error,
321
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
322
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
323
0
     "%s: invalid volume - snapshot metadata tree value already set.",
324
0
     function );
325
326
0
    return( -1 );
327
0
  }
328
5.20k
  if( internal_volume->key_bag != NULL )
329
0
  {
330
0
    libcerror_error_set(
331
0
     error,
332
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
334
0
     "%s: invalid volume - key bag value already set.",
335
0
     function );
336
337
0
    return( -1 );
338
0
  }
339
5.20k
  if( internal_volume->encryption_context != NULL )
340
0
  {
341
0
    libcerror_error_set(
342
0
     error,
343
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
344
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
345
0
     "%s: invalid volume - encryption context value already set.",
346
0
     function );
347
348
0
    return( -1 );
349
0
  }
350
5.20k
  if( internal_volume->file_system_data_block_vector != NULL )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
355
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
356
0
     "%s: invalid volume - file system data block vector value already set.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
#if defined( HAVE_DEBUG_OUTPUT )
362
  if( libcnotify_verbose != 0 )
363
  {
364
    libcnotify_printf(
365
     "Reading volume superblock:\n" );
366
  }
367
#endif
368
5.20k
  if( libfsapfs_volume_superblock_initialize(
369
5.20k
       &( internal_volume->superblock ),
370
5.20k
       error ) != 1 )
371
0
  {
372
0
    libcerror_error_set(
373
0
     error,
374
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
375
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
376
0
     "%s: unable to create volume superblock.",
377
0
     function );
378
379
0
    goto on_error;
380
0
  }
381
5.20k
  if( libfsapfs_volume_superblock_read_file_io_handle(
382
5.20k
       internal_volume->superblock,
383
5.20k
       file_io_handle,
384
5.20k
       file_offset,
385
5.20k
       0,
386
5.20k
       error ) != 1 )
387
808
  {
388
808
    libcerror_error_set(
389
808
     error,
390
808
     LIBCERROR_ERROR_DOMAIN_IO,
391
808
     LIBCERROR_IO_ERROR_READ_FAILED,
392
808
     "%s: unable to read volume superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
393
808
     function,
394
808
     file_offset,
395
808
     file_offset );
396
397
808
    goto on_error;
398
808
  }
399
4.40k
  if( libfsapfs_container_data_handle_initialize(
400
4.40k
       &container_data_handle,
401
4.40k
       internal_volume->io_handle,
402
4.40k
       error ) != 1 )
403
0
  {
404
0
    libcerror_error_set(
405
0
     error,
406
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
407
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
408
0
     "%s: unable to create container data handle.",
409
0
     function );
410
411
0
    goto on_error;
412
0
  }
413
4.40k
  if( libfdata_vector_initialize(
414
4.40k
       &( internal_volume->container_data_block_vector ),
415
4.40k
       (size64_t) internal_volume->io_handle->block_size,
416
4.40k
       (intptr_t *) container_data_handle,
417
4.40k
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_container_data_handle_free,
418
4.40k
       NULL,
419
4.40k
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsapfs_container_data_handle_read_data_block,
420
4.40k
       NULL,
421
4.40k
       LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
422
4.40k
       error ) != 1 )
423
0
  {
424
0
    libcerror_error_set(
425
0
     error,
426
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
427
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
428
0
     "%s: unable to create container data block vector.",
429
0
     function );
430
431
0
    goto on_error;
432
0
  }
433
4.40k
  internal_volume->container_data_handle = container_data_handle;
434
4.40k
  container_data_handle                  = NULL;
435
436
4.40k
  if( libfdata_vector_append_segment(
437
4.40k
       internal_volume->container_data_block_vector,
438
4.40k
       &element_index,
439
4.40k
       0,
440
4.40k
       0,
441
4.40k
       internal_volume->io_handle->container_size,
442
4.40k
       0,
443
4.40k
       error ) != 1 )
444
0
  {
445
0
    libcerror_error_set(
446
0
     error,
447
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
448
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
449
0
     "%s: unable to append segment to container data block vector.",
450
0
     function );
451
452
0
    goto on_error;
453
0
  }
454
/* TODO refactor into function to read object map */
455
4.40k
  if( internal_volume->superblock->object_map_block_number == 0 )
456
3
  {
457
3
    libcerror_error_set(
458
3
     error,
459
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
460
3
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
461
3
     "%s: missing object map block number.",
462
3
     function );
463
464
3
    goto on_error;
465
3
  }
466
#if defined( HAVE_DEBUG_OUTPUT )
467
  if( libcnotify_verbose != 0 )
468
  {
469
    libcnotify_printf(
470
     "Reading object map:\n" );
471
  }
472
#endif
473
4.39k
  file_offset = internal_volume->superblock->object_map_block_number * internal_volume->io_handle->block_size;
474
475
4.39k
  if( libfsapfs_object_map_initialize(
476
4.39k
       &object_map,
477
4.39k
       error ) != 1 )
478
0
  {
479
0
    libcerror_error_set(
480
0
     error,
481
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
482
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
483
0
     "%s: unable to create object map.",
484
0
     function );
485
486
0
    goto on_error;
487
0
  }
488
4.39k
  if( libfsapfs_object_map_read_file_io_handle(
489
4.39k
       object_map,
490
4.39k
       file_io_handle,
491
4.39k
       file_offset,
492
4.39k
       error ) != 1 )
493
22
  {
494
22
    libcerror_error_set(
495
22
     error,
496
22
     LIBCERROR_ERROR_DOMAIN_IO,
497
22
     LIBCERROR_IO_ERROR_READ_FAILED,
498
22
     "%s: unable to read object map at offset: %" PRIi64 " (0x%08" PRIx64 ").",
499
22
     function,
500
22
     file_offset,
501
22
     file_offset );
502
503
22
    goto on_error;
504
22
  }
505
4.37k
  if( object_map->btree_block_number == 0 )
506
3
  {
507
3
    libcerror_error_set(
508
3
     error,
509
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
510
3
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
511
3
     "%s: missing object map B-tree block number.",
512
3
     function );
513
514
3
    goto on_error;
515
3
  }
516
#if defined( HAVE_DEBUG_OUTPUT )
517
  if( libcnotify_verbose != 0 )
518
  {
519
    libcnotify_printf(
520
     "Reading object map B-tree:\n" );
521
  }
522
#endif
523
4.37k
  if( libfsapfs_object_map_btree_initialize(
524
4.37k
       &( internal_volume->object_map_btree ),
525
4.37k
       internal_volume->io_handle,
526
4.37k
       internal_volume->container_data_block_vector,
527
4.37k
       object_map->btree_block_number,
528
4.37k
       error ) != 1 )
529
0
  {
530
0
    libcerror_error_set(
531
0
     error,
532
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
533
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
534
0
     "%s: unable to create object map B-tree.",
535
0
     function );
536
537
0
    goto on_error;
538
0
  }
539
4.37k
  if( libfsapfs_object_map_free(
540
4.37k
       &object_map,
541
4.37k
       error ) != 1 )
542
0
  {
543
0
    libcerror_error_set(
544
0
     error,
545
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
546
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
547
0
     "%s: unable to free object map.",
548
0
     function );
549
550
0
    goto on_error;
551
0
  }
552
4.37k
  internal_volume->is_locked = 0;
553
554
4.37k
  if( ( internal_volume->container_key_bag != NULL )
555
0
   && ( ( internal_volume->superblock->volume_flags & 0x00000001UL ) == 0 ) )
556
0
  {
557
0
    internal_volume->is_locked = internal_volume->container_key_bag->is_locked;
558
559
0
    result = libfsapfs_container_key_bag_get_volume_key_bag_extent_by_identifier(
560
0
              internal_volume->container_key_bag,
561
0
              internal_volume->superblock->volume_identifier,
562
0
              &key_bag_block_number,
563
0
              &key_bag_number_of_blocks,
564
0
              error );
565
566
0
    if( result == -1 )
567
0
    {
568
0
      libcerror_error_set(
569
0
       error,
570
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
571
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
572
0
       "%s: unable to retrieve volume key bag extent.",
573
0
       function );
574
575
0
      goto on_error;
576
0
    }
577
0
    else if( result != 0 )
578
0
    {
579
0
      if( ( key_bag_block_number == 0 )
580
0
       || ( key_bag_number_of_blocks == 0 ) )
581
0
      {
582
0
        libcerror_error_set(
583
0
         error,
584
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
585
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
586
0
         "%s: invalid volume key bag extent.",
587
0
         function );
588
589
0
        goto on_error;
590
0
      }
591
0
      if( libfsapfs_volume_key_bag_initialize(
592
0
           &( internal_volume->key_bag ),
593
0
           error ) != 1 )
594
0
      {
595
0
        libcerror_error_set(
596
0
         error,
597
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
598
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
599
0
         "%s: unable to create volume key bag.",
600
0
         function );
601
602
0
        goto on_error;
603
0
      }
604
0
      file_offset = key_bag_block_number * internal_volume->io_handle->block_size;
605
606
0
      if( libfsapfs_volume_key_bag_read_file_io_handle(
607
0
           internal_volume->key_bag,
608
0
           internal_volume->io_handle,
609
0
           file_io_handle,
610
0
           file_offset,
611
0
           (size64_t) key_bag_number_of_blocks * internal_volume->io_handle->block_size,
612
0
           internal_volume->superblock->volume_identifier,
613
0
           error ) != 1 )
614
0
      {
615
0
        libcerror_error_set(
616
0
         error,
617
0
         LIBCERROR_ERROR_DOMAIN_IO,
618
0
         LIBCERROR_IO_ERROR_READ_FAILED,
619
0
         "%s: unable to read volume key bag at offset: %" PRIi64 " (0x%08" PRIx64 ").",
620
0
         function,
621
0
         file_offset,
622
0
         file_offset );
623
624
0
        goto on_error;
625
0
      }
626
0
      if( libfsapfs_encryption_context_initialize(
627
0
           &( internal_volume->encryption_context ),
628
0
           LIBFSAPFS_ENCRYPTION_METHOD_AES_128_XTS,
629
0
           error ) != 1 )
630
0
      {
631
0
        libcerror_error_set(
632
0
         error,
633
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
634
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
635
0
         "%s: unable to initialize encryption context.",
636
0
         function );
637
638
0
        goto on_error;
639
0
      }
640
0
      internal_volume->is_locked = 1;
641
0
    }
642
0
  }
643
#if defined( HAVE_DEBUG_OUTPUT )
644
  if( internal_volume->superblock->extent_reference_tree_block_number != 0 )
645
  {
646
    if( libfsapfs_extent_reference_tree_initialize(
647
         &extent_reference_tree,
648
         error ) != 1 )
649
    {
650
      libcerror_error_set(
651
       error,
652
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
653
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
654
       "%s: unable to create extent reference tree.",
655
       function );
656
657
      goto on_error;
658
    }
659
    file_offset = internal_volume->superblock->extent_reference_tree_block_number * internal_volume->io_handle->block_size;
660
661
    if( libfsapfs_extent_reference_tree_read_file_io_handle(
662
         extent_reference_tree,
663
         file_io_handle,
664
         file_offset,
665
         error ) != 1 )
666
    {
667
      libcerror_error_set(
668
       error,
669
       LIBCERROR_ERROR_DOMAIN_IO,
670
       LIBCERROR_IO_ERROR_READ_FAILED,
671
       "%s: unable to read extent reference tree at offset: %" PRIi64 " (0x%08" PRIx64 ").",
672
       function,
673
       file_offset,
674
       file_offset );
675
676
      goto on_error;
677
    }
678
    if( libfsapfs_extent_reference_tree_free(
679
         &extent_reference_tree,
680
         error ) != 1 )
681
    {
682
      libcerror_error_set(
683
       error,
684
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
685
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
686
       "%s: unable to free extent reference tree.",
687
       function );
688
689
      goto on_error;
690
    }
691
  }
692
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
693
694
4.37k
  if( libcdata_array_initialize(
695
4.37k
       &( internal_volume->snapshots ),
696
4.37k
       0,
697
4.37k
       error ) != 1 )
698
0
  {
699
0
    libcerror_error_set(
700
0
     error,
701
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
703
0
     "%s: unable to create snapshots array.",
704
0
     function );
705
706
0
    goto on_error;
707
0
  }
708
4.37k
  if( internal_volume->superblock->snapshot_metadata_tree_block_number != 0 )
709
4.36k
  {
710
4.36k
    if( libfsapfs_snapshot_metadata_tree_initialize(
711
4.36k
         &( internal_volume->snapshot_metadata_tree ),
712
4.36k
         internal_volume->io_handle,
713
4.36k
         internal_volume->container_data_block_vector,
714
4.36k
         internal_volume->object_map_btree,
715
4.36k
         internal_volume->superblock->snapshot_metadata_tree_block_number,
716
4.36k
         error ) != 1 )
717
0
    {
718
0
      libcerror_error_set(
719
0
       error,
720
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
721
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
722
0
       "%s: unable to create snapshot metadata tree.",
723
0
       function );
724
725
0
      goto on_error;
726
0
    }
727
4.36k
    if( libfsapfs_snapshot_metadata_tree_get_snapshots(
728
4.36k
         internal_volume->snapshot_metadata_tree,
729
4.36k
         internal_volume->file_io_handle,
730
4.36k
         internal_volume->superblock->transaction_identifier,
731
4.36k
         internal_volume->snapshots,
732
4.36k
         error ) == -1 )
733
1.65k
    {
734
1.65k
      libcerror_error_set(
735
1.65k
       error,
736
1.65k
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
737
1.65k
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
738
1.65k
       "%s: unable to retrieve snapshots.",
739
1.65k
       function );
740
741
1.65k
      goto on_error;
742
1.65k
    }
743
4.36k
  }
744
2.72k
  if( internal_volume->superblock->file_system_root_object_identifier == 0 )
745
2
  {
746
2
    libcerror_error_set(
747
2
     error,
748
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
749
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
750
2
     "%s: invalid file system root object identifier - value out of bounds.",
751
2
     function );
752
753
2
    goto on_error;
754
2
  }
755
2.71k
  if( libfsapfs_file_system_data_handle_initialize(
756
2.71k
       &file_system_data_handle,
757
2.71k
       internal_volume->io_handle,
758
2.71k
       internal_volume->encryption_context,
759
2.71k
       NULL,
760
2.71k
       error ) != 1 )
761
0
  {
762
0
    libcerror_error_set(
763
0
     error,
764
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
765
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
766
0
     "%s: unable to create file system data handle.",
767
0
     function );
768
769
0
    goto on_error;
770
0
  }
771
2.71k
  if( libfdata_vector_initialize(
772
2.71k
       &( internal_volume->file_system_data_block_vector ),
773
2.71k
       (size64_t) internal_volume->io_handle->block_size,
774
2.71k
       (intptr_t *) file_system_data_handle,
775
2.71k
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_system_data_handle_free,
776
2.71k
       NULL,
777
2.71k
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsapfs_file_system_data_handle_read_data_block,
778
2.71k
       NULL,
779
2.71k
       LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
780
2.71k
       error ) != 1 )
781
0
  {
782
0
    libcerror_error_set(
783
0
     error,
784
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
785
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
786
0
     "%s: unable to create file system data block vector.",
787
0
     function );
788
789
0
    goto on_error;
790
0
  }
791
2.71k
  internal_volume->file_system_data_handle = file_system_data_handle;
792
2.71k
  file_system_data_handle                  = NULL;
793
794
2.71k
  if( libfdata_vector_append_segment(
795
2.71k
       internal_volume->file_system_data_block_vector,
796
2.71k
       &element_index,
797
2.71k
       0,
798
2.71k
       0,
799
2.71k
       internal_volume->io_handle->container_size,
800
2.71k
       0,
801
2.71k
       error ) != 1 )
802
0
  {
803
0
    libcerror_error_set(
804
0
     error,
805
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
806
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
807
0
     "%s: unable to append segment to file system data block vector.",
808
0
     function );
809
810
0
    goto on_error;
811
0
  }
812
2.71k
  return( 1 );
813
814
2.49k
on_error:
815
2.49k
  if( internal_volume->file_system_data_block_vector != NULL )
816
0
  {
817
0
    libfdata_vector_free(
818
0
     &( internal_volume->file_system_data_block_vector ),
819
0
     NULL );
820
0
  }
821
2.49k
  if( file_system_data_handle != NULL )
822
0
  {
823
0
    libfsapfs_file_system_data_handle_free(
824
0
     &file_system_data_handle,
825
0
     NULL );
826
0
  }
827
2.49k
  if( internal_volume->encryption_context != NULL )
828
0
  {
829
0
    libfsapfs_encryption_context_free(
830
0
     &( internal_volume->encryption_context ),
831
0
     NULL );
832
0
  }
833
2.49k
  if( internal_volume->key_bag != NULL )
834
0
  {
835
0
    libfsapfs_volume_key_bag_free(
836
0
     &( internal_volume->key_bag ),
837
0
     NULL );
838
0
  }
839
2.49k
  if( internal_volume->snapshot_metadata_tree != NULL )
840
1.65k
  {
841
1.65k
    libcdata_array_free(
842
1.65k
     &( internal_volume->snapshots ),
843
1.65k
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
844
1.65k
     NULL );
845
1.65k
  }
846
2.49k
  if( internal_volume->snapshot_metadata_tree != NULL )
847
1.65k
  {
848
1.65k
    libfsapfs_snapshot_metadata_tree_free(
849
1.65k
     &( internal_volume->snapshot_metadata_tree ),
850
1.65k
     NULL );
851
1.65k
  }
852
#if defined( HAVE_DEBUG_OUTPUT )
853
  if( extent_reference_tree != NULL )
854
  {
855
    libfsapfs_extent_reference_tree_free(
856
     &extent_reference_tree,
857
     NULL );
858
  }
859
#endif
860
2.49k
  if( internal_volume->object_map_btree != NULL )
861
1.65k
  {
862
1.65k
    libfsapfs_object_map_btree_free(
863
1.65k
     &( internal_volume->object_map_btree ),
864
1.65k
     NULL );
865
1.65k
  }
866
2.49k
  if( object_map != NULL )
867
25
  {
868
25
    libfsapfs_object_map_free(
869
25
     &object_map,
870
25
     NULL );
871
25
  }
872
2.49k
  if( internal_volume->container_data_block_vector != NULL )
873
1.68k
  {
874
1.68k
    libfdata_vector_free(
875
1.68k
     &( internal_volume->container_data_block_vector ),
876
1.68k
     NULL );
877
1.68k
  }
878
2.49k
  if( container_data_handle != NULL )
879
0
  {
880
0
    libfsapfs_container_data_handle_free(
881
0
     &container_data_handle,
882
0
     NULL );
883
0
  }
884
2.49k
  if( internal_volume->superblock != NULL )
885
2.49k
  {
886
2.49k
    libfsapfs_volume_superblock_free(
887
2.49k
     &( internal_volume->superblock ),
888
2.49k
     NULL );
889
2.49k
  }
890
2.49k
  return( -1 );
891
2.71k
}
892
893
/* Closes a volume
894
 * Returns 0 if successful or -1 on error
895
 */
896
int libfsapfs_internal_volume_close(
897
     libfsapfs_internal_volume_t *internal_volume,
898
     libcerror_error_t **error )
899
5.20k
{
900
5.20k
  static char *function = "libfsapfs_internal_volume_close";
901
5.20k
  int result            = 0;
902
903
5.20k
  if( internal_volume == NULL )
904
0
  {
905
0
    libcerror_error_set(
906
0
     error,
907
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
908
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
909
0
     "%s: invalid volume.",
910
0
     function );
911
912
0
    return( -1 );
913
0
  }
914
5.20k
  if( internal_volume->io_handle == NULL )
915
0
  {
916
0
    libcerror_error_set(
917
0
     error,
918
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
919
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
920
0
     "%s: invalid volume - missing IO handle.",
921
0
     function );
922
923
0
    return( -1 );
924
0
  }
925
5.20k
  internal_volume->file_io_handle = NULL;
926
5.20k
  internal_volume->is_locked      = 1;
927
928
5.20k
  if( internal_volume->user_password != NULL )
929
0
  {
930
0
    if( memory_set(
931
0
         internal_volume->user_password,
932
0
         0,
933
0
         internal_volume->user_password_size ) == NULL )
934
0
    {
935
0
      libcerror_error_set(
936
0
       error,
937
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
938
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
939
0
       "%s: unable to clear user password.",
940
0
       function );
941
942
0
      result = -1;
943
0
    }
944
0
    memory_free(
945
0
     internal_volume->user_password );
946
947
0
    internal_volume->user_password      = NULL;
948
0
    internal_volume->user_password_size = 0;
949
0
  }
950
5.20k
  if( internal_volume->recovery_password != NULL )
951
0
  {
952
0
    if( memory_set(
953
0
         internal_volume->recovery_password,
954
0
         0,
955
0
         internal_volume->recovery_password_size ) == NULL )
956
0
    {
957
0
      libcerror_error_set(
958
0
       error,
959
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
960
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
961
0
       "%s: unable to clear recovery password.",
962
0
       function );
963
964
0
      result = -1;
965
0
    }
966
0
    memory_free(
967
0
     internal_volume->recovery_password );
968
969
0
    internal_volume->recovery_password      = NULL;
970
0
    internal_volume->recovery_password_size = 0;
971
0
  }
972
5.20k
  if( internal_volume->superblock != NULL )
973
2.71k
  {
974
2.71k
    if( libfsapfs_volume_superblock_free(
975
2.71k
         &( internal_volume->superblock ),
976
2.71k
         error ) != 1 )
977
0
    {
978
0
      libcerror_error_set(
979
0
       error,
980
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
981
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
982
0
       "%s: unable to free superblock.",
983
0
       function );
984
985
0
      result = -1;
986
0
    }
987
2.71k
  }
988
5.20k
  if( libfdata_vector_free(
989
5.20k
       &( internal_volume->container_data_block_vector ),
990
5.20k
       error ) != 1 )
991
0
  {
992
0
    libcerror_error_set(
993
0
     error,
994
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
995
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
996
0
     "%s: unable to free container data block vector.",
997
0
     function );
998
999
0
    result = -1;
1000
0
  }
1001
5.20k
  if( internal_volume->object_map_btree != NULL )
1002
2.71k
  {
1003
2.71k
    if( libfsapfs_object_map_btree_free(
1004
2.71k
         &( internal_volume->object_map_btree ),
1005
2.71k
         error ) != 1 )
1006
0
    {
1007
0
      libcerror_error_set(
1008
0
       error,
1009
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1010
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1011
0
       "%s: unable to free object map B-tree.",
1012
0
       function );
1013
1014
0
      result = -1;
1015
0
    }
1016
2.71k
  }
1017
5.20k
  if( internal_volume->snapshot_metadata_tree != NULL )
1018
2.71k
  {
1019
2.71k
    if( libfsapfs_snapshot_metadata_tree_free(
1020
2.71k
         &( internal_volume->snapshot_metadata_tree ),
1021
2.71k
         error ) != 1 )
1022
0
    {
1023
0
      libcerror_error_set(
1024
0
       error,
1025
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1026
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1027
0
       "%s: unable to free snapshot metadata tree.",
1028
0
       function );
1029
1030
0
      result = -1;
1031
0
    }
1032
2.71k
  }
1033
5.20k
  if( internal_volume->snapshots != NULL )
1034
2.71k
  {
1035
2.71k
    if( libcdata_array_free(
1036
2.71k
         &( internal_volume->snapshots ),
1037
2.71k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
1038
2.71k
         error ) != 1 )
1039
0
    {
1040
0
      libcerror_error_set(
1041
0
       error,
1042
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1043
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1044
0
       "%s: unable to free snapshots array.",
1045
0
       function );
1046
1047
0
      result = -1;
1048
0
    }
1049
2.71k
  }
1050
5.20k
  if( internal_volume->key_bag != NULL )
1051
0
  {
1052
0
    if( libfsapfs_volume_key_bag_free(
1053
0
         &( internal_volume->key_bag ),
1054
0
         error ) != 1 )
1055
0
    {
1056
0
      libcerror_error_set(
1057
0
       error,
1058
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1059
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1060
0
       "%s: unable to free key bag.",
1061
0
       function );
1062
1063
0
      result = -1;
1064
0
    }
1065
0
  }
1066
5.20k
  if( internal_volume->encryption_context != NULL )
1067
0
  {
1068
0
    if( libfsapfs_encryption_context_free(
1069
0
         &( internal_volume->encryption_context ),
1070
0
         error ) != 1 )
1071
0
    {
1072
0
      libcerror_error_set(
1073
0
       error,
1074
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1075
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1076
0
       "%s: unable to free encryption context.",
1077
0
       function );
1078
1079
0
      result = -1;
1080
0
    }
1081
0
  }
1082
5.20k
  if( libfdata_vector_free(
1083
5.20k
       &( internal_volume->file_system_data_block_vector ),
1084
5.20k
       error ) != 1 )
1085
0
  {
1086
0
    libcerror_error_set(
1087
0
     error,
1088
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1089
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1090
0
     "%s: unable to free file system data block vector.",
1091
0
     function );
1092
1093
0
    result = -1;
1094
0
  }
1095
5.20k
  if( internal_volume->file_system != NULL )
1096
2.56k
  {
1097
2.56k
    if( libfsapfs_file_system_free(
1098
2.56k
         &( internal_volume->file_system ),
1099
2.56k
         error ) != 1 )
1100
0
    {
1101
0
      libcerror_error_set(
1102
0
       error,
1103
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1104
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1105
0
       "%s: unable to free file system.",
1106
0
       function );
1107
1108
0
      result = -1;
1109
0
    }
1110
2.56k
  }
1111
5.20k
  return( result );
1112
5.20k
}
1113
1114
/* Unlocks an encrypted volume
1115
 * Returns 1 if the volume is unlocked, 0 if not or -1 on error
1116
 */
1117
int libfsapfs_internal_volume_unlock(
1118
     libfsapfs_internal_volume_t *internal_volume,
1119
     libcerror_error_t **error )
1120
0
{
1121
0
  uint8_t volume_key[ 32 ];
1122
0
  uint8_t volume_master_key[ 32 ];
1123
1124
0
  static char *function = "libfsapfs_internal_volume_unlock";
1125
0
  int result            = 0;
1126
1127
0
  if( internal_volume == NULL )
1128
0
  {
1129
0
    libcerror_error_set(
1130
0
     error,
1131
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1132
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1133
0
     "%s: invalid volume.",
1134
0
     function );
1135
1136
0
    return( -1 );
1137
0
  }
1138
0
  if( internal_volume->superblock == NULL )
1139
0
  {
1140
0
    libcerror_error_set(
1141
0
     error,
1142
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1143
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1144
0
     "%s: invalid volume - missing superblock.",
1145
0
     function );
1146
1147
0
    return( -1 );
1148
0
  }
1149
0
  if( internal_volume->key_bag == NULL )
1150
0
  {
1151
0
    result = 1;
1152
0
  }
1153
0
  else
1154
0
  {
1155
0
    result = libfsapfs_volume_key_bag_get_volume_key(
1156
0
              internal_volume->key_bag,
1157
0
              internal_volume->user_password,
1158
0
              internal_volume->user_password_size - 1,
1159
0
              internal_volume->recovery_password,
1160
0
              internal_volume->recovery_password_size - 1,
1161
0
              volume_key,
1162
0
              256,
1163
0
              error );
1164
1165
0
    if( result == -1 )
1166
0
    {
1167
0
      libcerror_error_set(
1168
0
       error,
1169
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1170
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1171
0
       "%s: unable to retrieve volume key using password.",
1172
0
       function );
1173
1174
0
      goto on_error;
1175
0
    }
1176
0
    else if( result != 0 )
1177
0
    {
1178
0
      if( libfsapfs_container_key_bag_get_volume_master_key_by_identifier(
1179
0
           internal_volume->container_key_bag,
1180
0
           internal_volume->superblock->volume_identifier,
1181
0
           volume_key,
1182
0
           256,
1183
0
           volume_master_key,
1184
0
           256,
1185
0
           error ) != 1 )
1186
0
      {
1187
0
        libcerror_error_set(
1188
0
         error,
1189
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1190
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1191
0
         "%s: unable to retrieve volume master key.",
1192
0
         function );
1193
1194
0
        goto on_error;
1195
0
      }
1196
0
      memory_set(
1197
0
       volume_key,
1198
0
       0,
1199
0
       32 );
1200
1201
0
      if( libfsapfs_encryption_context_set_keys(
1202
0
           internal_volume->encryption_context,
1203
0
           volume_master_key,
1204
0
           16,
1205
0
           &( volume_master_key[ 16 ] ),
1206
0
           16,
1207
0
           error ) != 1 )
1208
0
      {
1209
0
        libcerror_error_set(
1210
0
         error,
1211
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1212
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1213
0
         "%s: unable to set keys in encryption context.",
1214
0
         function );
1215
1216
0
        goto on_error;
1217
0
      }
1218
0
      memory_set(
1219
0
       volume_master_key,
1220
0
       0,
1221
0
       32 );
1222
0
    }
1223
0
  }
1224
0
  if( result != 0 )
1225
0
  {
1226
0
    internal_volume->is_locked = 0;
1227
0
  }
1228
0
  return( result );
1229
1230
0
on_error:
1231
0
  memory_set(
1232
0
   volume_master_key,
1233
0
   0,
1234
0
   32 );
1235
1236
0
  memory_set(
1237
0
   volume_key,
1238
0
   0,
1239
0
   32 );
1240
1241
0
  return( -1 );
1242
0
}
1243
1244
/* Unlocks the volume
1245
 * Returns 1 if the volume is unlocked, 0 if not or -1 on error
1246
 */
1247
int libfsapfs_volume_unlock(
1248
     libfsapfs_volume_t *volume,
1249
     libcerror_error_t **error )
1250
0
{
1251
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1252
0
  static char *function                        = "libfsapfs_volume_unlock";
1253
0
  int result                                   = 1;
1254
1255
0
  if( volume == NULL )
1256
0
  {
1257
0
    libcerror_error_set(
1258
0
     error,
1259
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1260
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1261
0
     "%s: invalid volume.",
1262
0
     function );
1263
1264
0
    return( -1 );
1265
0
  }
1266
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1267
1268
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1269
0
  if( libcthreads_read_write_lock_grab_for_write(
1270
0
       internal_volume->read_write_lock,
1271
0
       error ) != 1 )
1272
0
  {
1273
0
    libcerror_error_set(
1274
0
     error,
1275
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1276
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1277
0
     "%s: unable to grab read/write lock for writing.",
1278
0
     function );
1279
1280
0
    return( -1 );
1281
0
  }
1282
0
#endif
1283
0
  if( internal_volume->is_locked != 0 )
1284
0
  {
1285
0
    result = libfsapfs_internal_volume_unlock(
1286
0
              internal_volume,
1287
0
              error );
1288
1289
0
    if( result == -1 )
1290
0
    {
1291
0
      libcerror_error_set(
1292
0
       error,
1293
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1294
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1295
0
       "%s: unable to unlock volume.",
1296
0
       function );
1297
1298
0
      result = -1;
1299
0
    }
1300
0
  }
1301
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1302
0
  if( libcthreads_read_write_lock_release_for_write(
1303
0
       internal_volume->read_write_lock,
1304
0
       error ) != 1 )
1305
0
  {
1306
0
    libcerror_error_set(
1307
0
     error,
1308
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1309
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1310
0
     "%s: unable to release read/write lock for writing.",
1311
0
     function );
1312
1313
0
    return( -1 );
1314
0
  }
1315
0
#endif
1316
0
  return( result );
1317
0
}
1318
1319
/* Retrieves the feature flags
1320
 * Returns 1 if successful or -1 on error
1321
 */
1322
int libfsapfs_volume_get_features_flags(
1323
     libfsapfs_volume_t *volume,
1324
     uint64_t *compatible_features_flags,
1325
     uint64_t *incompatible_features_flags,
1326
     uint64_t *read_only_compatible_features_flags,
1327
     libcerror_error_t **error )
1328
27
{
1329
27
  libfsapfs_internal_volume_t *internal_volume = NULL;
1330
27
  static char *function                        = "libfsapfs_volume_get_features_flags";
1331
1332
27
  if( volume == NULL )
1333
0
  {
1334
0
    libcerror_error_set(
1335
0
     error,
1336
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1337
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1338
0
     "%s: invalid volume.",
1339
0
     function );
1340
1341
0
    return( -1 );
1342
0
  }
1343
27
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1344
1345
27
  if( internal_volume->superblock == NULL )
1346
0
  {
1347
0
    libcerror_error_set(
1348
0
     error,
1349
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1350
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1351
0
     "%s: invalid volume - missing superblock.",
1352
0
     function );
1353
1354
0
    return( -1 );
1355
0
  }
1356
27
  if( compatible_features_flags == NULL )
1357
0
  {
1358
0
    libcerror_error_set(
1359
0
     error,
1360
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1361
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1362
0
     "%s: invalid compatible features flags.",
1363
0
     function );
1364
1365
0
    return( -1 );
1366
0
  }
1367
27
  if( incompatible_features_flags == NULL )
1368
0
  {
1369
0
    libcerror_error_set(
1370
0
     error,
1371
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1372
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1373
0
     "%s: invalid incompatible features flags.",
1374
0
     function );
1375
1376
0
    return( -1 );
1377
0
  }
1378
27
  if( read_only_compatible_features_flags == NULL )
1379
0
  {
1380
0
    libcerror_error_set(
1381
0
     error,
1382
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1383
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1384
0
     "%s: invalid read-only compatible features flags.",
1385
0
     function );
1386
1387
0
    return( -1 );
1388
0
  }
1389
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1390
27
  if( libcthreads_read_write_lock_grab_for_read(
1391
27
       internal_volume->read_write_lock,
1392
27
       error ) != 1 )
1393
0
  {
1394
0
    libcerror_error_set(
1395
0
     error,
1396
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1397
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1398
0
     "%s: unable to grab read/write lock for reading.",
1399
0
     function );
1400
1401
0
    return( -1 );
1402
0
  }
1403
27
#endif
1404
27
  *compatible_features_flags           = internal_volume->superblock->compatible_features_flags;
1405
27
  *incompatible_features_flags         = internal_volume->superblock->incompatible_features_flags;
1406
27
  *read_only_compatible_features_flags = internal_volume->superblock->read_only_compatible_features_flags;
1407
1408
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1409
27
  if( libcthreads_read_write_lock_release_for_read(
1410
27
       internal_volume->read_write_lock,
1411
27
       error ) != 1 )
1412
0
  {
1413
0
    libcerror_error_set(
1414
0
     error,
1415
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1416
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1417
0
     "%s: unable to release read/write lock for reading.",
1418
0
     function );
1419
1420
0
    return( -1 );
1421
0
  }
1422
27
#endif
1423
27
  return( 1 );
1424
27
}
1425
1426
/* Retrieves the size
1427
 * Returns 1 if successful or -1 on error
1428
 */
1429
int libfsapfs_volume_get_size(
1430
     libfsapfs_volume_t *volume,
1431
     size64_t *size,
1432
     libcerror_error_t **error )
1433
27
{
1434
27
  libfsapfs_internal_volume_t *internal_volume = NULL;
1435
27
  static char *function                        = "libfsapfs_volume_get_size";
1436
1437
27
  if( volume == NULL )
1438
0
  {
1439
0
    libcerror_error_set(
1440
0
     error,
1441
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1442
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1443
0
     "%s: invalid volume.",
1444
0
     function );
1445
1446
0
    return( -1 );
1447
0
  }
1448
27
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1449
1450
27
  if( internal_volume->superblock == NULL )
1451
0
  {
1452
0
    libcerror_error_set(
1453
0
     error,
1454
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1455
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1456
0
     "%s: invalid volume - missing superblock.",
1457
0
     function );
1458
1459
0
    return( -1 );
1460
0
  }
1461
27
  if( size == NULL )
1462
0
  {
1463
0
    libcerror_error_set(
1464
0
     error,
1465
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1466
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1467
0
     "%s: invalid size.",
1468
0
     function );
1469
1470
0
    return( -1 );
1471
0
  }
1472
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1473
27
  if( libcthreads_read_write_lock_grab_for_read(
1474
27
       internal_volume->read_write_lock,
1475
27
       error ) != 1 )
1476
0
  {
1477
0
    libcerror_error_set(
1478
0
     error,
1479
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1480
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1481
0
     "%s: unable to grab read/write lock for reading.",
1482
0
     function );
1483
1484
0
    return( -1 );
1485
0
  }
1486
27
#endif
1487
/* TODO implement */
1488
27
  *size = (size64_t) 0;
1489
1490
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1491
27
  if( libcthreads_read_write_lock_release_for_read(
1492
27
       internal_volume->read_write_lock,
1493
27
       error ) != 1 )
1494
0
  {
1495
0
    libcerror_error_set(
1496
0
     error,
1497
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1498
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1499
0
     "%s: unable to release read/write lock for reading.",
1500
0
     function );
1501
1502
0
    return( -1 );
1503
0
  }
1504
27
#endif
1505
27
  return( -1 );
1506
27
}
1507
1508
/* Retrieves the identifier
1509
 * The identifier is an UUID stored in big-endian and is 16 bytes of size
1510
 * Returns 1 if successful or -1 on error
1511
 */
1512
int libfsapfs_volume_get_identifier(
1513
     libfsapfs_volume_t *volume,
1514
     uint8_t *uuid_data,
1515
     size_t uuid_data_size,
1516
     libcerror_error_t **error )
1517
27
{
1518
27
  libfsapfs_internal_volume_t *internal_volume = NULL;
1519
27
  static char *function                        = "libfsapfs_volume_get_identifier";
1520
27
  int result                                   = 1;
1521
1522
27
  if( volume == NULL )
1523
0
  {
1524
0
    libcerror_error_set(
1525
0
     error,
1526
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1527
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1528
0
     "%s: invalid volume.",
1529
0
     function );
1530
1531
0
    return( -1 );
1532
0
  }
1533
27
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1534
1535
27
  if( internal_volume->superblock == NULL )
1536
0
  {
1537
0
    libcerror_error_set(
1538
0
     error,
1539
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1540
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1541
0
     "%s: invalid volume - missing superblock.",
1542
0
     function );
1543
1544
0
    return( -1 );
1545
0
  }
1546
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1547
27
  if( libcthreads_read_write_lock_grab_for_read(
1548
27
       internal_volume->read_write_lock,
1549
27
       error ) != 1 )
1550
0
  {
1551
0
    libcerror_error_set(
1552
0
     error,
1553
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1554
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1555
0
     "%s: unable to grab read/write lock for reading.",
1556
0
     function );
1557
1558
0
    return( -1 );
1559
0
  }
1560
27
#endif
1561
27
  if( libfsapfs_volume_superblock_get_volume_identifier(
1562
27
       internal_volume->superblock,
1563
27
       uuid_data,
1564
27
       uuid_data_size,
1565
27
       error ) != 1 )
1566
0
  {
1567
0
    libcerror_error_set(
1568
0
     error,
1569
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1570
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1571
0
     "%s: unable to retrieve volume identifier.",
1572
0
     function );
1573
1574
0
    result = -1;
1575
0
  }
1576
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1577
27
  if( libcthreads_read_write_lock_release_for_read(
1578
27
       internal_volume->read_write_lock,
1579
27
       error ) != 1 )
1580
0
  {
1581
0
    libcerror_error_set(
1582
0
     error,
1583
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1584
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1585
0
     "%s: unable to release read/write lock for reading.",
1586
0
     function );
1587
1588
0
    return( -1 );
1589
0
  }
1590
27
#endif
1591
27
  return( result );
1592
27
}
1593
1594
/* Retrieves the size of the UTF-8 encoded name
1595
 * The returned size includes the end of string character
1596
 * Returns 1 if successful or -1 on error
1597
 */
1598
int libfsapfs_volume_get_utf8_name_size(
1599
     libfsapfs_volume_t *volume,
1600
     size_t *utf8_string_size,
1601
     libcerror_error_t **error )
1602
27
{
1603
27
  libfsapfs_internal_volume_t *internal_volume = NULL;
1604
27
  static char *function                        = "libfsapfs_volume_get_utf8_name_size";
1605
27
  int result                                   = 1;
1606
1607
27
  if( volume == NULL )
1608
0
  {
1609
0
    libcerror_error_set(
1610
0
     error,
1611
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1612
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1613
0
     "%s: invalid volume.",
1614
0
     function );
1615
1616
0
    return( -1 );
1617
0
  }
1618
27
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1619
1620
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1621
27
  if( libcthreads_read_write_lock_grab_for_read(
1622
27
       internal_volume->read_write_lock,
1623
27
       error ) != 1 )
1624
0
  {
1625
0
    libcerror_error_set(
1626
0
     error,
1627
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1628
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1629
0
     "%s: unable to grab read/write lock for reading.",
1630
0
     function );
1631
1632
0
    return( -1 );
1633
0
  }
1634
27
#endif
1635
27
  if( libfsapfs_volume_superblock_get_utf8_volume_name_size(
1636
27
       internal_volume->superblock,
1637
27
       utf8_string_size,
1638
27
       error ) != 1 )
1639
4
  {
1640
4
    libcerror_error_set(
1641
4
     error,
1642
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1643
4
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1644
4
     "%s: unable to retrieve UTF-8 string size.",
1645
4
     function );
1646
1647
4
    result = -1;
1648
4
  }
1649
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1650
27
  if( libcthreads_read_write_lock_release_for_read(
1651
27
       internal_volume->read_write_lock,
1652
27
       error ) != 1 )
1653
0
  {
1654
0
    libcerror_error_set(
1655
0
     error,
1656
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1657
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1658
0
     "%s: unable to release read/write lock for reading.",
1659
0
     function );
1660
1661
0
    return( -1 );
1662
0
  }
1663
27
#endif
1664
27
  return( result );
1665
27
}
1666
1667
/* Retrieves the UTF-8 encoded name
1668
 * The size should include the end of string character
1669
 * Returns 1 if successful or -1 on error
1670
 */
1671
int libfsapfs_volume_get_utf8_name(
1672
     libfsapfs_volume_t *volume,
1673
     uint8_t *utf8_string,
1674
     size_t utf8_string_size,
1675
     libcerror_error_t **error )
1676
27
{
1677
27
  libfsapfs_internal_volume_t *internal_volume = NULL;
1678
27
  static char *function                        = "libfsapfs_volume_get_utf8_name";
1679
27
  int result                                   = 1;
1680
1681
27
  if( volume == NULL )
1682
0
  {
1683
0
    libcerror_error_set(
1684
0
     error,
1685
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1686
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1687
0
     "%s: invalid volume.",
1688
0
     function );
1689
1690
0
    return( -1 );
1691
0
  }
1692
27
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1693
1694
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1695
27
  if( libcthreads_read_write_lock_grab_for_read(
1696
27
       internal_volume->read_write_lock,
1697
27
       error ) != 1 )
1698
0
  {
1699
0
    libcerror_error_set(
1700
0
     error,
1701
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1702
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1703
0
     "%s: unable to grab read/write lock for reading.",
1704
0
     function );
1705
1706
0
    return( -1 );
1707
0
  }
1708
27
#endif
1709
27
  if( libfsapfs_volume_superblock_get_utf8_volume_name(
1710
27
       internal_volume->superblock,
1711
27
       utf8_string,
1712
27
       utf8_string_size,
1713
27
       error ) != 1 )
1714
4
  {
1715
4
    libcerror_error_set(
1716
4
     error,
1717
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1718
4
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1719
4
     "%s: unable to retrieve UTF-8 string.",
1720
4
     function );
1721
1722
4
    result = -1;
1723
4
  }
1724
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1725
27
  if( libcthreads_read_write_lock_release_for_read(
1726
27
       internal_volume->read_write_lock,
1727
27
       error ) != 1 )
1728
0
  {
1729
0
    libcerror_error_set(
1730
0
     error,
1731
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1732
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1733
0
     "%s: unable to release read/write lock for reading.",
1734
0
     function );
1735
1736
0
    return( -1 );
1737
0
  }
1738
27
#endif
1739
27
  return( result );
1740
27
}
1741
1742
/* Retrieves the size of the UTF-16 encoded name
1743
 * The returned size includes the end of string character
1744
 * Returns 1 if successful or -1 on error
1745
 */
1746
int libfsapfs_volume_get_utf16_name_size(
1747
     libfsapfs_volume_t *volume,
1748
     size_t *utf16_string_size,
1749
     libcerror_error_t **error )
1750
0
{
1751
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1752
0
  static char *function                        = "libfsapfs_volume_get_utf16_name_size";
1753
0
  int result                                   = 1;
1754
1755
0
  if( volume == NULL )
1756
0
  {
1757
0
    libcerror_error_set(
1758
0
     error,
1759
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1760
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1761
0
     "%s: invalid volume.",
1762
0
     function );
1763
1764
0
    return( -1 );
1765
0
  }
1766
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1767
1768
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1769
0
  if( libcthreads_read_write_lock_grab_for_read(
1770
0
       internal_volume->read_write_lock,
1771
0
       error ) != 1 )
1772
0
  {
1773
0
    libcerror_error_set(
1774
0
     error,
1775
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1776
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1777
0
     "%s: unable to grab read/write lock for reading.",
1778
0
     function );
1779
1780
0
    return( -1 );
1781
0
  }
1782
0
#endif
1783
0
  if( libfsapfs_volume_superblock_get_utf16_volume_name_size(
1784
0
       internal_volume->superblock,
1785
0
       utf16_string_size,
1786
0
       error ) != 1 )
1787
0
  {
1788
0
    libcerror_error_set(
1789
0
     error,
1790
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1791
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1792
0
     "%s: unable to retrieve UTF-16 string size.",
1793
0
     function );
1794
1795
0
    result = -1;
1796
0
  }
1797
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1798
0
  if( libcthreads_read_write_lock_release_for_read(
1799
0
       internal_volume->read_write_lock,
1800
0
       error ) != 1 )
1801
0
  {
1802
0
    libcerror_error_set(
1803
0
     error,
1804
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1805
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1806
0
     "%s: unable to release read/write lock for reading.",
1807
0
     function );
1808
1809
0
    return( -1 );
1810
0
  }
1811
0
#endif
1812
0
  return( result );
1813
0
}
1814
1815
/* Retrieves the UTF-16 encoded name
1816
 * The size should include the end of string character
1817
 * Returns 1 if successful or -1 on error
1818
 */
1819
int libfsapfs_volume_get_utf16_name(
1820
     libfsapfs_volume_t *volume,
1821
     uint16_t *utf16_string,
1822
     size_t utf16_string_size,
1823
     libcerror_error_t **error )
1824
0
{
1825
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1826
0
  static char *function                        = "libfsapfs_volume_get_utf16_name";
1827
0
  int result                                   = 1;
1828
1829
0
  if( volume == NULL )
1830
0
  {
1831
0
    libcerror_error_set(
1832
0
     error,
1833
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1834
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1835
0
     "%s: invalid volume.",
1836
0
     function );
1837
1838
0
    return( -1 );
1839
0
  }
1840
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1841
1842
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1843
0
  if( libcthreads_read_write_lock_grab_for_read(
1844
0
       internal_volume->read_write_lock,
1845
0
       error ) != 1 )
1846
0
  {
1847
0
    libcerror_error_set(
1848
0
     error,
1849
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1850
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1851
0
     "%s: unable to grab read/write lock for reading.",
1852
0
     function );
1853
1854
0
    return( -1 );
1855
0
  }
1856
0
#endif
1857
0
  if( libfsapfs_volume_superblock_get_utf16_volume_name(
1858
0
       internal_volume->superblock,
1859
0
       utf16_string,
1860
0
       utf16_string_size,
1861
0
       error ) != 1 )
1862
0
  {
1863
0
    libcerror_error_set(
1864
0
     error,
1865
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1866
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1867
0
     "%s: unable to retrieve UTF-16 string.",
1868
0
     function );
1869
1870
0
    result = -1;
1871
0
  }
1872
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1873
0
  if( libcthreads_read_write_lock_release_for_read(
1874
0
       internal_volume->read_write_lock,
1875
0
       error ) != 1 )
1876
0
  {
1877
0
    libcerror_error_set(
1878
0
     error,
1879
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1880
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1881
0
     "%s: unable to release read/write lock for reading.",
1882
0
     function );
1883
1884
0
    return( -1 );
1885
0
  }
1886
0
#endif
1887
0
  return( result );
1888
0
}
1889
1890
/* Determines if the volume is locked
1891
 * Returns 1 if locked, 0 if not or -1 on error
1892
 */
1893
int libfsapfs_volume_is_locked(
1894
     libfsapfs_volume_t *volume,
1895
     libcerror_error_t **error )
1896
27
{
1897
27
  libfsapfs_internal_volume_t *internal_volume = NULL;
1898
27
  static char *function                        = "libfsapfs_volume_is_locked";
1899
27
  uint8_t is_locked                            = 0;
1900
1901
27
  if( volume == NULL )
1902
0
  {
1903
0
    libcerror_error_set(
1904
0
     error,
1905
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1906
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1907
0
     "%s: invalid volume.",
1908
0
     function );
1909
1910
0
    return( -1 );
1911
0
  }
1912
27
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1913
1914
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1915
27
  if( libcthreads_read_write_lock_grab_for_read(
1916
27
       internal_volume->read_write_lock,
1917
27
       error ) != 1 )
1918
0
  {
1919
0
    libcerror_error_set(
1920
0
     error,
1921
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1922
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1923
0
     "%s: unable to grab read/write lock for reading.",
1924
0
     function );
1925
1926
0
    return( -1 );
1927
0
  }
1928
27
#endif
1929
27
  is_locked = internal_volume->is_locked;
1930
1931
27
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1932
27
  if( libcthreads_read_write_lock_release_for_read(
1933
27
       internal_volume->read_write_lock,
1934
27
       error ) != 1 )
1935
0
  {
1936
0
    libcerror_error_set(
1937
0
     error,
1938
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1939
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1940
0
     "%s: unable to release read/write lock for reading.",
1941
0
     function );
1942
1943
0
    return( -1 );
1944
0
  }
1945
27
#endif
1946
27
  return( is_locked );
1947
27
}
1948
1949
/* Sets an UTF-8 formatted password
1950
 * This function needs to be used before one of the open or unlock functions
1951
 * Returns 1 if successful, 0 if password is invalid or -1 on error
1952
 */
1953
int libfsapfs_volume_set_utf8_password(
1954
     libfsapfs_volume_t *volume,
1955
     const uint8_t *utf8_string,
1956
     size_t utf8_string_length,
1957
     libcerror_error_t **error )
1958
0
{
1959
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1960
0
  static char *function                        = "libfsapfs_volume_set_utf8_password";
1961
1962
0
  if( volume == NULL )
1963
0
  {
1964
0
    libcerror_error_set(
1965
0
     error,
1966
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1967
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1968
0
     "%s: invalid volume.",
1969
0
     function );
1970
1971
0
    return( -1 );
1972
0
  }
1973
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1974
1975
0
  if( utf8_string == NULL )
1976
0
  {
1977
0
    libcerror_error_set(
1978
0
     error,
1979
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1980
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1981
0
     "%s: invalid UTF-8 string.",
1982
0
     function );
1983
1984
0
    return( -1 );
1985
0
  }
1986
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1987
0
  if( libcthreads_read_write_lock_grab_for_write(
1988
0
       internal_volume->read_write_lock,
1989
0
       error ) != 1 )
1990
0
  {
1991
0
    libcerror_error_set(
1992
0
     error,
1993
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1994
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1995
0
     "%s: unable to grab read/write lock for writing.",
1996
0
     function );
1997
1998
0
    return( -1 );
1999
0
  }
2000
0
#endif
2001
0
  if( internal_volume->user_password != NULL )
2002
0
  {
2003
0
    if( memory_set(
2004
0
         internal_volume->user_password,
2005
0
         0,
2006
0
         internal_volume->user_password_size ) == NULL )
2007
0
    {
2008
0
      libcerror_error_set(
2009
0
       error,
2010
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2011
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2012
0
       "%s: unable to clear user password.",
2013
0
       function );
2014
2015
0
      goto on_error;
2016
0
    }
2017
0
    memory_free(
2018
0
     internal_volume->user_password );
2019
2020
0
    internal_volume->user_password      = NULL;
2021
0
    internal_volume->user_password_size = 0;
2022
0
  }
2023
0
  internal_volume->user_password_size = narrow_string_length(
2024
0
                                         (char *) utf8_string );
2025
2026
0
  if( ( internal_volume->user_password_size == 0 )
2027
0
   || ( internal_volume->user_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2028
0
  {
2029
0
    libcerror_error_set(
2030
0
     error,
2031
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2032
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2033
0
     "%s: invalid volume - user password size value out of bounds.",
2034
0
     function );
2035
2036
0
    goto on_error;
2037
0
  }
2038
0
  internal_volume->user_password_size += 1;
2039
2040
0
  internal_volume->user_password = (uint8_t *) memory_allocate(
2041
0
                                                sizeof( uint8_t ) * internal_volume->user_password_size );
2042
2043
0
  if( internal_volume->user_password == NULL )
2044
0
  {
2045
0
    libcerror_error_set(
2046
0
     error,
2047
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2048
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2049
0
     "%s: unable to create user password.",
2050
0
     function );
2051
2052
0
    goto on_error;
2053
0
  }
2054
0
  if( memory_copy(
2055
0
       internal_volume->user_password,
2056
0
       utf8_string,
2057
0
       utf8_string_length ) == NULL )
2058
0
  {
2059
0
    libcerror_error_set(
2060
0
     error,
2061
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2062
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2063
0
     "%s: unable to copy user password.",
2064
0
     function );
2065
2066
0
    goto on_error;
2067
0
  }
2068
0
  internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
2069
2070
#if defined( HAVE_DEBUG_OUTPUT )
2071
  if( libcnotify_verbose != 0 )
2072
  {
2073
    libcnotify_printf(
2074
     "%s: user password: %s\n",
2075
     function,
2076
     internal_volume->user_password );
2077
  }
2078
#endif
2079
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2080
0
  if( libcthreads_read_write_lock_release_for_write(
2081
0
       internal_volume->read_write_lock,
2082
0
       error ) != 1 )
2083
0
  {
2084
0
    libcerror_error_set(
2085
0
     error,
2086
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2087
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2088
0
     "%s: unable to release read/write lock for writing.",
2089
0
     function );
2090
2091
0
    return( -1 );
2092
0
  }
2093
0
#endif
2094
0
  return( 1 );
2095
2096
0
on_error:
2097
0
  if( internal_volume->user_password != NULL )
2098
0
  {
2099
0
    memory_set(
2100
0
     internal_volume->user_password,
2101
0
     0,
2102
0
     internal_volume->user_password_size );
2103
0
    memory_free(
2104
0
     internal_volume->user_password );
2105
2106
0
    internal_volume->user_password = NULL;
2107
0
  }
2108
0
  internal_volume->user_password_size = 0;
2109
2110
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2111
0
  libcthreads_read_write_lock_release_for_write(
2112
0
   internal_volume->read_write_lock,
2113
0
   NULL );
2114
0
#endif
2115
0
  return( -1 );
2116
0
}
2117
2118
/* Sets an UTF-16 formatted password
2119
 * This function needs to be used before one of the open or unlock functions
2120
 * Returns 1 if successful, 0 if password is invalid or -1 on error
2121
 */
2122
int libfsapfs_volume_set_utf16_password(
2123
     libfsapfs_volume_t *volume,
2124
     const uint16_t *utf16_string,
2125
     size_t utf16_string_length,
2126
     libcerror_error_t **error )
2127
0
{
2128
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2129
0
  static char *function                        = "libfsapfs_volume_set_utf16_password";
2130
2131
0
  if( volume == NULL )
2132
0
  {
2133
0
    libcerror_error_set(
2134
0
     error,
2135
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2136
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2137
0
     "%s: invalid volume.",
2138
0
     function );
2139
2140
0
    return( -1 );
2141
0
  }
2142
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2143
2144
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2145
0
  if( libcthreads_read_write_lock_grab_for_write(
2146
0
       internal_volume->read_write_lock,
2147
0
       error ) != 1 )
2148
0
  {
2149
0
    libcerror_error_set(
2150
0
     error,
2151
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2152
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2153
0
     "%s: unable to grab read/write lock for writing.",
2154
0
     function );
2155
2156
0
    return( -1 );
2157
0
  }
2158
0
#endif
2159
0
  if( internal_volume->user_password != NULL )
2160
0
  {
2161
0
    if( memory_set(
2162
0
         internal_volume->user_password,
2163
0
         0,
2164
0
         internal_volume->user_password_size ) == NULL )
2165
0
    {
2166
0
      libcerror_error_set(
2167
0
       error,
2168
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2169
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2170
0
       "%s: unable to clear user password.",
2171
0
       function );
2172
2173
0
      goto on_error;
2174
0
    }
2175
0
    memory_free(
2176
0
     internal_volume->user_password );
2177
2178
0
    internal_volume->user_password      = NULL;
2179
0
    internal_volume->user_password_size = 0;
2180
0
  }
2181
0
  if( libuna_utf8_string_size_from_utf16(
2182
0
       utf16_string,
2183
0
       utf16_string_length,
2184
0
       &( internal_volume->user_password_size ),
2185
0
       error ) != 1 )
2186
0
  {
2187
0
    libcerror_error_set(
2188
0
     error,
2189
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2190
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2191
0
     "%s: unable to set password size.",
2192
0
     function );
2193
2194
0
    goto on_error;
2195
0
  }
2196
0
  if( ( internal_volume->user_password_size == 0 )
2197
0
   || ( internal_volume->user_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2198
0
  {
2199
0
    libcerror_error_set(
2200
0
     error,
2201
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2202
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2203
0
     "%s: invalid volume - user password size value out of bounds.",
2204
0
     function );
2205
2206
0
    goto on_error;
2207
0
  }
2208
0
  internal_volume->user_password_size += 1;
2209
2210
0
  internal_volume->user_password = (uint8_t *) memory_allocate(
2211
0
                                                sizeof( uint8_t ) * internal_volume->user_password_size );
2212
2213
0
  if( internal_volume->user_password == NULL )
2214
0
  {
2215
0
    libcerror_error_set(
2216
0
     error,
2217
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2218
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2219
0
     "%s: unable to create user password.",
2220
0
     function );
2221
2222
0
    goto on_error;
2223
0
  }
2224
0
  if( libuna_utf8_string_copy_from_utf16(
2225
0
       internal_volume->user_password,
2226
0
       internal_volume->user_password_size,
2227
0
       utf16_string,
2228
0
       utf16_string_length,
2229
0
       error ) != 1 )
2230
0
  {
2231
0
    libcerror_error_set(
2232
0
     error,
2233
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2234
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2235
0
     "%s: unable to copy user password.",
2236
0
     function );
2237
2238
0
    goto on_error;
2239
0
  }
2240
0
  internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
2241
2242
#if defined( HAVE_DEBUG_OUTPUT )
2243
  if( libcnotify_verbose != 0 )
2244
  {
2245
    libcnotify_printf(
2246
     "%s: user password: %s\n",
2247
     function,
2248
     internal_volume->user_password );
2249
  }
2250
#endif
2251
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2252
0
  if( libcthreads_read_write_lock_release_for_write(
2253
0
       internal_volume->read_write_lock,
2254
0
       error ) != 1 )
2255
0
  {
2256
0
    libcerror_error_set(
2257
0
     error,
2258
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2259
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2260
0
     "%s: unable to release read/write lock for writing.",
2261
0
     function );
2262
2263
0
    return( -1 );
2264
0
  }
2265
0
#endif
2266
0
  return( 1 );
2267
2268
0
on_error:
2269
0
  if( internal_volume->user_password != NULL )
2270
0
  {
2271
0
    memory_set(
2272
0
     internal_volume->user_password,
2273
0
     0,
2274
0
     internal_volume->user_password_size );
2275
0
    memory_free(
2276
0
     internal_volume->user_password );
2277
2278
0
    internal_volume->user_password = NULL;
2279
0
  }
2280
0
  internal_volume->user_password_size = 0;
2281
2282
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2283
0
  libcthreads_read_write_lock_release_for_write(
2284
0
   internal_volume->read_write_lock,
2285
0
   NULL );
2286
0
#endif
2287
0
  return( -1 );
2288
0
}
2289
2290
/* Sets an UTF-8 formatted recovery password
2291
 * This function needs to be used before one of the open or unlock functions
2292
 * Returns 1 if successful, 0 if recovery password is invalid or -1 on error
2293
 */
2294
int libfsapfs_volume_set_utf8_recovery_password(
2295
     libfsapfs_volume_t *volume,
2296
     const uint8_t *utf8_string,
2297
     size_t utf8_string_length,
2298
     libcerror_error_t **error )
2299
0
{
2300
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2301
0
  static char *function                        = "libfsapfs_volume_set_utf8_recovery_password";
2302
2303
0
  if( volume == NULL )
2304
0
  {
2305
0
    libcerror_error_set(
2306
0
     error,
2307
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2308
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2309
0
     "%s: invalid volume.",
2310
0
     function );
2311
2312
0
    return( -1 );
2313
0
  }
2314
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2315
2316
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2317
0
  if( libcthreads_read_write_lock_grab_for_write(
2318
0
       internal_volume->read_write_lock,
2319
0
       error ) != 1 )
2320
0
  {
2321
0
    libcerror_error_set(
2322
0
     error,
2323
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2324
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2325
0
     "%s: unable to grab read/write lock for writing.",
2326
0
     function );
2327
2328
0
    return( -1 );
2329
0
  }
2330
0
#endif
2331
0
  if( internal_volume->recovery_password != NULL )
2332
0
  {
2333
0
    if( memory_set(
2334
0
         internal_volume->recovery_password,
2335
0
         0,
2336
0
         internal_volume->recovery_password_size ) == NULL )
2337
0
    {
2338
0
      libcerror_error_set(
2339
0
       error,
2340
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2341
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2342
0
       "%s: unable to clear recovery password.",
2343
0
       function );
2344
2345
0
      goto on_error;
2346
0
    }
2347
0
    memory_free(
2348
0
     internal_volume->recovery_password );
2349
2350
0
    internal_volume->recovery_password      = NULL;
2351
0
    internal_volume->recovery_password_size = 0;
2352
0
  }
2353
0
  internal_volume->recovery_password_size = narrow_string_length(
2354
0
                                             (char *) utf8_string );
2355
2356
0
  if( ( internal_volume->recovery_password_size == 0 )
2357
0
   || ( internal_volume->recovery_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2358
0
  {
2359
0
    libcerror_error_set(
2360
0
     error,
2361
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2362
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2363
0
     "%s: invalid volume - user recovery password size value out of bounds.",
2364
0
     function );
2365
2366
0
    goto on_error;
2367
0
  }
2368
0
  internal_volume->recovery_password_size += 1;
2369
2370
0
  internal_volume->recovery_password = (uint8_t *) memory_allocate(
2371
0
                                                    sizeof( uint8_t ) * internal_volume->recovery_password_size );
2372
2373
0
  if( internal_volume->recovery_password == NULL )
2374
0
  {
2375
0
    libcerror_error_set(
2376
0
     error,
2377
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2378
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2379
0
     "%s: unable to create recovery password.",
2380
0
     function );
2381
2382
0
    goto on_error;
2383
0
  }
2384
0
  if( memory_copy(
2385
0
       internal_volume->recovery_password,
2386
0
       utf8_string,
2387
0
       utf8_string_length ) == NULL )
2388
0
  {
2389
0
    libcerror_error_set(
2390
0
     error,
2391
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2392
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2393
0
     "%s: unable to copy recovery password.",
2394
0
     function );
2395
2396
0
    goto on_error;
2397
0
  }
2398
0
  internal_volume->recovery_password[ internal_volume->recovery_password_size - 1 ] = 0;
2399
2400
#if defined( HAVE_DEBUG_OUTPUT )
2401
  if( libcnotify_verbose != 0 )
2402
  {
2403
    libcnotify_printf(
2404
     "%s: recovery password: %s\n",
2405
     function,
2406
     internal_volume->recovery_password );
2407
  }
2408
#endif
2409
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2410
0
  if( libcthreads_read_write_lock_release_for_write(
2411
0
       internal_volume->read_write_lock,
2412
0
       error ) != 1 )
2413
0
  {
2414
0
    libcerror_error_set(
2415
0
     error,
2416
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2417
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2418
0
     "%s: unable to release read/write lock for writing.",
2419
0
     function );
2420
2421
0
    return( -1 );
2422
0
  }
2423
0
#endif
2424
0
  return( 1 );
2425
2426
0
on_error:
2427
0
  if( internal_volume->recovery_password != NULL )
2428
0
  {
2429
0
    memory_set(
2430
0
     internal_volume->recovery_password,
2431
0
     0,
2432
0
     internal_volume->recovery_password_size );
2433
0
    memory_free(
2434
0
     internal_volume->recovery_password );
2435
2436
0
    internal_volume->recovery_password = NULL;
2437
0
  }
2438
0
  internal_volume->recovery_password_size = 0;
2439
2440
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2441
0
  libcthreads_read_write_lock_release_for_write(
2442
0
   internal_volume->read_write_lock,
2443
0
   NULL );
2444
0
#endif
2445
0
  return( -1 );
2446
0
}
2447
2448
/* Sets an UTF-16 formatted recovery password
2449
 * This function needs to be used before one of the open or unlock functions
2450
 * Returns 1 if successful, 0 if recovery password is invalid or -1 on error
2451
 */
2452
int libfsapfs_volume_set_utf16_recovery_password(
2453
     libfsapfs_volume_t *volume,
2454
     const uint16_t *utf16_string,
2455
     size_t utf16_string_length,
2456
     libcerror_error_t **error )
2457
0
{
2458
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2459
0
  static char *function                        = "libfsapfs_volume_set_utf16_recovery_password";
2460
2461
0
  if( volume == NULL )
2462
0
  {
2463
0
    libcerror_error_set(
2464
0
     error,
2465
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2466
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2467
0
     "%s: invalid volume.",
2468
0
     function );
2469
2470
0
    return( -1 );
2471
0
  }
2472
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2473
2474
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2475
0
  if( libcthreads_read_write_lock_grab_for_write(
2476
0
       internal_volume->read_write_lock,
2477
0
       error ) != 1 )
2478
0
  {
2479
0
    libcerror_error_set(
2480
0
     error,
2481
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2482
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2483
0
     "%s: unable to grab read/write lock for writing.",
2484
0
     function );
2485
2486
0
    return( -1 );
2487
0
  }
2488
0
#endif
2489
0
  if( internal_volume->recovery_password != NULL )
2490
0
  {
2491
0
    if( memory_set(
2492
0
         internal_volume->recovery_password,
2493
0
         0,
2494
0
         internal_volume->recovery_password_size ) == NULL )
2495
0
    {
2496
0
      libcerror_error_set(
2497
0
       error,
2498
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2499
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2500
0
       "%s: unable to clear recovery password.",
2501
0
       function );
2502
2503
0
      goto on_error;
2504
0
    }
2505
0
    memory_free(
2506
0
     internal_volume->recovery_password );
2507
2508
0
    internal_volume->recovery_password      = NULL;
2509
0
    internal_volume->recovery_password_size = 0;
2510
0
  }
2511
0
  if( libuna_utf8_string_size_from_utf16(
2512
0
       utf16_string,
2513
0
       utf16_string_length,
2514
0
       &( internal_volume->recovery_password_size ),
2515
0
       error ) != 1 )
2516
0
  {
2517
0
    libcerror_error_set(
2518
0
     error,
2519
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2520
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2521
0
     "%s: unable to set password size.",
2522
0
     function );
2523
2524
0
    goto on_error;
2525
0
  }
2526
0
  if( ( internal_volume->recovery_password_size == 0 )
2527
0
   || ( internal_volume->recovery_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2528
0
  {
2529
0
    libcerror_error_set(
2530
0
     error,
2531
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2532
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2533
0
     "%s: invalid volume - user recovery password size value out of bounds.",
2534
0
     function );
2535
2536
0
    goto on_error;
2537
0
  }
2538
0
  internal_volume->recovery_password_size += 1;
2539
2540
0
  internal_volume->recovery_password = (uint8_t *) memory_allocate(
2541
0
                                                    sizeof( uint8_t ) * internal_volume->recovery_password_size );
2542
2543
0
  if( internal_volume->recovery_password == NULL )
2544
0
  {
2545
0
    libcerror_error_set(
2546
0
     error,
2547
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2548
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2549
0
     "%s: unable to create recovery password.",
2550
0
     function );
2551
2552
0
    goto on_error;
2553
0
  }
2554
0
  if( libuna_utf8_string_copy_from_utf16(
2555
0
       internal_volume->recovery_password,
2556
0
       internal_volume->recovery_password_size,
2557
0
       utf16_string,
2558
0
       utf16_string_length,
2559
0
       error ) != 1 )
2560
0
  {
2561
0
    libcerror_error_set(
2562
0
     error,
2563
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2564
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2565
0
     "%s: unable to copy recovery password.",
2566
0
     function );
2567
2568
0
    goto on_error;
2569
0
  }
2570
0
  internal_volume->recovery_password[ internal_volume->recovery_password_size - 1 ] = 0;
2571
2572
#if defined( HAVE_DEBUG_OUTPUT )
2573
  if( libcnotify_verbose != 0 )
2574
  {
2575
    libcnotify_printf(
2576
     "%s: recovery password: %s\n",
2577
     function,
2578
     internal_volume->recovery_password );
2579
  }
2580
#endif
2581
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2582
0
  if( libcthreads_read_write_lock_release_for_write(
2583
0
       internal_volume->read_write_lock,
2584
0
       error ) != 1 )
2585
0
  {
2586
0
    libcerror_error_set(
2587
0
     error,
2588
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2589
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2590
0
     "%s: unable to release read/write lock for writing.",
2591
0
     function );
2592
2593
0
    return( -1 );
2594
0
  }
2595
0
#endif
2596
0
  return( 1 );
2597
2598
0
on_error:
2599
0
  if( internal_volume->recovery_password != NULL )
2600
0
  {
2601
0
    memory_set(
2602
0
     internal_volume->recovery_password,
2603
0
     0,
2604
0
     internal_volume->recovery_password_size );
2605
0
    memory_free(
2606
0
     internal_volume->recovery_password );
2607
2608
0
    internal_volume->recovery_password = NULL;
2609
0
  }
2610
0
  internal_volume->recovery_password_size = 0;
2611
2612
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2613
0
  libcthreads_read_write_lock_release_for_write(
2614
0
   internal_volume->read_write_lock,
2615
0
   NULL );
2616
0
#endif
2617
0
  return( -1 );
2618
0
}
2619
2620
/* Retrieves the root directory file entry
2621
 * Returns 1 if successful, or 0 if not available or -1 on error
2622
 */
2623
int libfsapfs_volume_get_root_directory(
2624
     libfsapfs_volume_t *volume,
2625
     libfsapfs_file_entry_t **file_entry,
2626
     libcerror_error_t **error )
2627
1.46k
{
2628
1.46k
  libfsapfs_internal_volume_t *internal_volume = NULL;
2629
1.46k
  static char *function                        = "libfsapfs_volume_get_root_directory";
2630
1.46k
  int result                                   = 1;
2631
2632
1.46k
  if( volume == NULL )
2633
0
  {
2634
0
    libcerror_error_set(
2635
0
     error,
2636
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2637
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2638
0
     "%s: invalid volume.",
2639
0
     function );
2640
2641
0
    return( -1 );
2642
0
  }
2643
1.46k
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2644
2645
1.46k
  if( internal_volume->superblock == NULL )
2646
0
  {
2647
0
    libcerror_error_set(
2648
0
     error,
2649
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2650
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2651
0
     "%s: invalid volume - missing superblock.",
2652
0
     function );
2653
2654
0
    return( -1 );
2655
0
  }
2656
1.46k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2657
1.46k
  if( libcthreads_read_write_lock_grab_for_write(
2658
1.46k
       internal_volume->read_write_lock,
2659
1.46k
       error ) != 1 )
2660
0
  {
2661
0
    libcerror_error_set(
2662
0
     error,
2663
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2664
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2665
0
     "%s: unable to grab read/write lock for writing.",
2666
0
     function );
2667
2668
0
    return( -1 );
2669
0
  }
2670
1.46k
#endif
2671
1.46k
  if( internal_volume->file_system == NULL )
2672
1.46k
  {
2673
1.46k
    if( libfsapfs_internal_volume_get_file_system(
2674
1.46k
         internal_volume,
2675
1.46k
         error ) != 1 )
2676
98
    {
2677
98
      libcerror_error_set(
2678
98
       error,
2679
98
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2680
98
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2681
98
       "%s: unable to determine file system.",
2682
98
       function );
2683
2684
98
      result = -1;
2685
98
    }
2686
1.46k
  }
2687
1.46k
  if( result != -1 )
2688
1.36k
  {
2689
1.36k
    result = libfsapfs_file_system_get_file_entry_by_identifier(
2690
1.36k
              internal_volume->file_system,
2691
1.36k
              internal_volume->file_io_handle,
2692
1.36k
              2,
2693
1.36k
              internal_volume->superblock->transaction_identifier,
2694
1.36k
              file_entry,
2695
1.36k
              error );
2696
2697
1.36k
    if( result == -1 )
2698
494
    {
2699
494
      libcerror_error_set(
2700
494
       error,
2701
494
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2702
494
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2703
494
       "%s: unable to retrieve root directory inode: 2 from file system B-tree.",
2704
494
       function );
2705
2706
494
      result = -1;
2707
494
    }
2708
1.36k
  }
2709
1.46k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2710
1.46k
  if( libcthreads_read_write_lock_release_for_write(
2711
1.46k
       internal_volume->read_write_lock,
2712
1.46k
       error ) != 1 )
2713
0
  {
2714
0
    libcerror_error_set(
2715
0
     error,
2716
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2717
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2718
0
     "%s: unable to release read/write lock for writing.",
2719
0
     function );
2720
2721
0
    return( -1 );
2722
0
  }
2723
1.46k
#endif
2724
1.46k
  return( result );
2725
1.46k
}
2726
2727
/* Retrieves the next file entry identifier
2728
 * Returns 1 if successful or -1 on error
2729
 */
2730
int libfsapfs_volume_get_next_file_entry_identifier(
2731
     libfsapfs_volume_t *volume,
2732
     uint64_t *identifier,
2733
     libcerror_error_t **error )
2734
0
{
2735
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2736
0
  static char *function                        = "libfsapfs_volume_get_next_file_entry_identifier";
2737
2738
0
  if( volume == NULL )
2739
0
  {
2740
0
    libcerror_error_set(
2741
0
     error,
2742
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2743
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2744
0
     "%s: invalid volume.",
2745
0
     function );
2746
2747
0
    return( -1 );
2748
0
  }
2749
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2750
2751
0
  if( identifier == NULL )
2752
0
  {
2753
0
    libcerror_error_set(
2754
0
     error,
2755
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2756
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2757
0
     "%s: invalid identifier.",
2758
0
     function );
2759
2760
0
    return( -1 );
2761
0
  }
2762
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2763
0
  if( libcthreads_read_write_lock_grab_for_read(
2764
0
       internal_volume->read_write_lock,
2765
0
       error ) != 1 )
2766
0
  {
2767
0
    libcerror_error_set(
2768
0
     error,
2769
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2770
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2771
0
     "%s: unable to grab read/write lock for reading.",
2772
0
     function );
2773
2774
0
    return( -1 );
2775
0
  }
2776
0
#endif
2777
0
  *identifier = internal_volume->superblock->next_file_system_object_identifier;
2778
2779
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2780
0
  if( libcthreads_read_write_lock_release_for_read(
2781
0
       internal_volume->read_write_lock,
2782
0
       error ) != 1 )
2783
0
  {
2784
0
    libcerror_error_set(
2785
0
     error,
2786
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2787
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2788
0
     "%s: unable to release read/write lock for reading.",
2789
0
     function );
2790
2791
0
    return( -1 );
2792
0
  }
2793
0
#endif
2794
0
  return( 1 );
2795
0
}
2796
2797
/* Determines the file system
2798
 * Returns 1 if successful or -1 on error
2799
 */
2800
int libfsapfs_internal_volume_get_file_system(
2801
     libfsapfs_internal_volume_t *internal_volume,
2802
     libcerror_error_t **error )
2803
2.69k
{
2804
2.69k
  libfsapfs_file_system_btree_t *file_system_btree         = NULL;
2805
2.69k
  libfsapfs_object_map_descriptor_t *object_map_descriptor = NULL;
2806
2.69k
  static char *function                                    = "libfsapfs_internal_volume_get_file_system";
2807
2.69k
  uint8_t use_case_folding                                 = 0;
2808
2.69k
  int result                                               = 0;
2809
2810
2.69k
  if( internal_volume == NULL )
2811
0
  {
2812
0
    libcerror_error_set(
2813
0
     error,
2814
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2815
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2816
0
     "%s: invalid volume.",
2817
0
     function );
2818
2819
0
    return( -1 );
2820
0
  }
2821
2.69k
  if( internal_volume->superblock == NULL )
2822
0
  {
2823
0
    libcerror_error_set(
2824
0
     error,
2825
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2826
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2827
0
     "%s: invalid volume - missing superblock.",
2828
0
     function );
2829
2830
0
    return( -1 );
2831
0
  }
2832
2.69k
  if( internal_volume->is_locked != 0 )
2833
0
  {
2834
0
    result = libfsapfs_internal_volume_unlock(
2835
0
              internal_volume,
2836
0
              error );
2837
2838
0
    if( result == -1 )
2839
0
    {
2840
0
      libcerror_error_set(
2841
0
       error,
2842
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2843
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2844
0
       "%s: unable to unlock volume.",
2845
0
       function );
2846
2847
0
      goto on_error;
2848
0
    }
2849
0
  }
2850
2.69k
  if( libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
2851
2.69k
       internal_volume->object_map_btree,
2852
2.69k
       internal_volume->file_io_handle,
2853
2.69k
       internal_volume->superblock->file_system_root_object_identifier,
2854
2.69k
       internal_volume->superblock->transaction_identifier,
2855
2.69k
       &object_map_descriptor,
2856
2.69k
       error ) != 1 )
2857
130
  {
2858
130
    if( result == 0 )
2859
130
    {
2860
/* TODO check if this fails on a T2 encrypted image */
2861
130
      libcerror_error_set(
2862
130
       error,
2863
130
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2864
130
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2865
130
       "%s: unable to unlock volume.",
2866
130
       function );
2867
130
    }
2868
0
    else
2869
0
    {
2870
0
      libcerror_error_set(
2871
0
       error,
2872
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2873
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2874
0
       "%s: unable to retrieve object map descriptor for file system root object identifier: %" PRIu64 ".",
2875
0
       function,
2876
0
       internal_volume->superblock->file_system_root_object_identifier );
2877
0
    }
2878
130
    goto on_error;
2879
130
  }
2880
2.56k
  if( object_map_descriptor == NULL )
2881
0
  {
2882
0
    libcerror_error_set(
2883
0
     error,
2884
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2885
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2886
0
     "%s: invalid object map descriptor.",
2887
0
     function );
2888
2889
0
    goto on_error;
2890
0
  }
2891
2.56k
  if( ( internal_volume->superblock->incompatible_features_flags & 0x00000000000000001ULL ) != 0 )
2892
2.55k
  {
2893
2.55k
    use_case_folding = 1;
2894
2.55k
  }
2895
2.56k
  if( libfsapfs_file_system_btree_initialize(
2896
2.56k
       &file_system_btree,
2897
2.56k
       internal_volume->io_handle,
2898
2.56k
       internal_volume->encryption_context,
2899
2.56k
       internal_volume->file_system_data_block_vector,
2900
2.56k
       internal_volume->object_map_btree,
2901
2.56k
       object_map_descriptor->physical_address,
2902
2.56k
       use_case_folding,
2903
2.56k
       error ) != 1 )
2904
0
  {
2905
0
    libcerror_error_set(
2906
0
     error,
2907
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2908
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2909
0
     "%s: unable to create file system B-tree.",
2910
0
     function );
2911
2912
0
    goto on_error;
2913
0
  }
2914
2.56k
  if( libfsapfs_file_system_initialize(
2915
2.56k
       &( internal_volume->file_system ),
2916
2.56k
       internal_volume->io_handle,
2917
2.56k
       internal_volume->encryption_context,
2918
2.56k
       file_system_btree,
2919
2.56k
       error ) != 1 )
2920
0
  {
2921
0
    libcerror_error_set(
2922
0
     error,
2923
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2924
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2925
0
     "%s: unable to create file system.",
2926
0
     function );
2927
2928
0
    goto on_error;
2929
0
  }
2930
2.56k
  if( libfsapfs_object_map_descriptor_free(
2931
2.56k
       &object_map_descriptor,
2932
2.56k
       error ) != 1 )
2933
0
  {
2934
0
    libcerror_error_set(
2935
0
     error,
2936
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2937
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2938
0
     "%s: unable to free object map descriptor.",
2939
0
     function );
2940
2941
0
    goto on_error;
2942
0
  }
2943
2.56k
  return( 1 );
2944
2945
130
on_error:
2946
130
  if( object_map_descriptor != NULL )
2947
0
  {
2948
0
    libfsapfs_object_map_descriptor_free(
2949
0
     &object_map_descriptor,
2950
0
     NULL );
2951
0
  }
2952
130
  if( file_system_btree != NULL )
2953
0
  {
2954
0
    libfsapfs_file_system_btree_free(
2955
0
     &file_system_btree,
2956
0
     NULL );
2957
0
  }
2958
130
  if( internal_volume->file_system != NULL )
2959
0
  {
2960
0
    libfsapfs_file_system_free(
2961
0
     &( internal_volume->file_system ),
2962
0
     NULL );
2963
0
  }
2964
130
  return( -1 );
2965
2.56k
}
2966
2967
/* Retrieves the file entry for a specific identifier
2968
 * Returns 1 if successful, 0 if not available or -1 on error
2969
 */
2970
int libfsapfs_volume_get_file_entry_by_identifier(
2971
     libfsapfs_volume_t *volume,
2972
     uint64_t identifier,
2973
     libfsapfs_file_entry_t **file_entry,
2974
     libcerror_error_t **error )
2975
0
{
2976
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2977
0
  static char *function                        = "libfsapfs_volume_get_file_entry_by_identifier";
2978
0
  int result                                   = 1;
2979
2980
0
  if( volume == NULL )
2981
0
  {
2982
0
    libcerror_error_set(
2983
0
     error,
2984
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2985
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2986
0
     "%s: invalid volume.",
2987
0
     function );
2988
2989
0
    return( -1 );
2990
0
  }
2991
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2992
2993
0
  if( internal_volume->superblock == NULL )
2994
0
  {
2995
0
    libcerror_error_set(
2996
0
     error,
2997
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2998
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2999
0
     "%s: invalid volume - missing superblock.",
3000
0
     function );
3001
3002
0
    return( -1 );
3003
0
  }
3004
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3005
0
  if( libcthreads_read_write_lock_grab_for_write(
3006
0
       internal_volume->read_write_lock,
3007
0
       error ) != 1 )
3008
0
  {
3009
0
    libcerror_error_set(
3010
0
     error,
3011
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3012
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3013
0
     "%s: unable to grab read/write lock for writing.",
3014
0
     function );
3015
3016
0
    return( -1 );
3017
0
  }
3018
0
#endif
3019
0
  if( internal_volume->file_system == NULL )
3020
0
  {
3021
0
    if( libfsapfs_internal_volume_get_file_system(
3022
0
         internal_volume,
3023
0
         error ) != 1 )
3024
0
    {
3025
0
      libcerror_error_set(
3026
0
       error,
3027
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3028
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3029
0
       "%s: unable to determine file system.",
3030
0
       function );
3031
3032
0
      result = -1;
3033
0
    }
3034
0
  }
3035
0
  if( result != -1 )
3036
0
  {
3037
0
    result = libfsapfs_file_system_get_file_entry_by_identifier(
3038
0
              internal_volume->file_system,
3039
0
              internal_volume->file_io_handle,
3040
0
              identifier,
3041
0
              internal_volume->superblock->transaction_identifier,
3042
0
              file_entry,
3043
0
              error );
3044
3045
0
    if( result == -1 )
3046
0
    {
3047
0
      libcerror_error_set(
3048
0
       error,
3049
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3050
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3051
0
       "%s: unable to retrieve inode: %" PRIu64 " from file system B-tree.",
3052
0
       function,
3053
0
       identifier );
3054
3055
0
      result = -1;
3056
0
    }
3057
0
  }
3058
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3059
0
  if( libcthreads_read_write_lock_release_for_write(
3060
0
       internal_volume->read_write_lock,
3061
0
       error ) != 1 )
3062
0
  {
3063
0
    libcerror_error_set(
3064
0
     error,
3065
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3066
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3067
0
     "%s: unable to release read/write lock for writing.",
3068
0
     function );
3069
3070
0
    return( -1 );
3071
0
  }
3072
0
#endif
3073
0
  return( result );
3074
0
}
3075
3076
/* Retrieves the file entry for an UTF-8 encoded path
3077
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3078
 */
3079
int libfsapfs_volume_get_file_entry_by_utf8_path(
3080
     libfsapfs_volume_t *volume,
3081
     const uint8_t *utf8_string,
3082
     size_t utf8_string_length,
3083
     libfsapfs_file_entry_t **file_entry,
3084
     libcerror_error_t **error )
3085
1.22k
{
3086
1.22k
  libfsapfs_internal_volume_t *internal_volume = NULL;
3087
1.22k
  static char *function                        = "libfsapfs_volume_get_file_entry_by_utf8_path";
3088
1.22k
  int result                                   = 1;
3089
3090
1.22k
  if( volume == NULL )
3091
0
  {
3092
0
    libcerror_error_set(
3093
0
     error,
3094
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3095
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3096
0
     "%s: invalid volume.",
3097
0
     function );
3098
3099
0
    return( -1 );
3100
0
  }
3101
1.22k
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3102
3103
1.22k
  if( internal_volume->superblock == NULL )
3104
0
  {
3105
0
    libcerror_error_set(
3106
0
     error,
3107
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3108
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3109
0
     "%s: invalid volume - missing superblock.",
3110
0
     function );
3111
3112
0
    return( -1 );
3113
0
  }
3114
1.22k
  if( file_entry == NULL )
3115
0
  {
3116
0
    libcerror_error_set(
3117
0
     error,
3118
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3119
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3120
0
     "%s: invalid file entry.",
3121
0
     function );
3122
3123
0
    return( -1 );
3124
0
  }
3125
1.22k
  if( *file_entry != NULL )
3126
0
  {
3127
0
    libcerror_error_set(
3128
0
     error,
3129
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3130
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3131
0
     "%s: invalid file entry value already set.",
3132
0
     function );
3133
3134
0
    return( -1 );
3135
0
  }
3136
1.22k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3137
1.22k
  if( libcthreads_read_write_lock_grab_for_write(
3138
1.22k
       internal_volume->read_write_lock,
3139
1.22k
       error ) != 1 )
3140
0
  {
3141
0
    libcerror_error_set(
3142
0
     error,
3143
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3144
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3145
0
     "%s: unable to grab read/write lock for writing.",
3146
0
     function );
3147
3148
0
    return( -1 );
3149
0
  }
3150
1.22k
#endif
3151
1.22k
  if( internal_volume->file_system == NULL )
3152
1.22k
  {
3153
1.22k
    if( libfsapfs_internal_volume_get_file_system(
3154
1.22k
         internal_volume,
3155
1.22k
         error ) != 1 )
3156
32
    {
3157
32
      libcerror_error_set(
3158
32
       error,
3159
32
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3160
32
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3161
32
       "%s: unable to determine file system.",
3162
32
       function );
3163
3164
32
      result = -1;
3165
32
    }
3166
1.22k
  }
3167
1.22k
  if( result != -1 )
3168
1.19k
  {
3169
1.19k
    result = libfsapfs_file_system_get_file_entry_by_utf8_path(
3170
1.19k
              internal_volume->file_system,
3171
1.19k
              internal_volume->file_io_handle,
3172
1.19k
              utf8_string,
3173
1.19k
              utf8_string_length,
3174
1.19k
              internal_volume->superblock->transaction_identifier,
3175
1.19k
              file_entry,
3176
1.19k
              error );
3177
3178
1.19k
    if( result == -1 )
3179
784
    {
3180
784
      libcerror_error_set(
3181
784
       error,
3182
784
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3183
784
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3184
784
       "%s: unable to retrieve file entry from file system by UTF-8 path.",
3185
784
       function );
3186
3187
784
      result = -1;
3188
784
    }
3189
1.19k
  }
3190
1.22k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3191
1.22k
  if( libcthreads_read_write_lock_release_for_write(
3192
1.22k
       internal_volume->read_write_lock,
3193
1.22k
       error ) != 1 )
3194
0
  {
3195
0
    libcerror_error_set(
3196
0
     error,
3197
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3198
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3199
0
     "%s: unable to release read/write lock for writing.",
3200
0
     function );
3201
3202
0
    return( -1 );
3203
0
  }
3204
1.22k
#endif
3205
1.22k
  return( result );
3206
1.22k
}
3207
3208
/* Retrieves the file entry for an UTF-16 encoded path
3209
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3210
 */
3211
int libfsapfs_volume_get_file_entry_by_utf16_path(
3212
     libfsapfs_volume_t *volume,
3213
     const uint16_t *utf16_string,
3214
     size_t utf16_string_length,
3215
     libfsapfs_file_entry_t **file_entry,
3216
     libcerror_error_t **error )
3217
0
{
3218
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
3219
0
  static char *function                        = "libfsapfs_volume_get_file_entry_by_utf16_path";
3220
0
  int result                                   = 1;
3221
3222
0
  if( volume == NULL )
3223
0
  {
3224
0
    libcerror_error_set(
3225
0
     error,
3226
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3227
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3228
0
     "%s: invalid volume.",
3229
0
     function );
3230
3231
0
    return( -1 );
3232
0
  }
3233
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3234
3235
0
  if( internal_volume->superblock == NULL )
3236
0
  {
3237
0
    libcerror_error_set(
3238
0
     error,
3239
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3240
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3241
0
     "%s: invalid volume - missing superblock.",
3242
0
     function );
3243
3244
0
    return( -1 );
3245
0
  }
3246
0
  if( file_entry == NULL )
3247
0
  {
3248
0
    libcerror_error_set(
3249
0
     error,
3250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3251
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3252
0
     "%s: invalid file entry.",
3253
0
     function );
3254
3255
0
    return( -1 );
3256
0
  }
3257
0
  if( *file_entry != NULL )
3258
0
  {
3259
0
    libcerror_error_set(
3260
0
     error,
3261
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3262
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3263
0
     "%s: invalid file entry value already set.",
3264
0
     function );
3265
3266
0
    return( -1 );
3267
0
  }
3268
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3269
0
  if( libcthreads_read_write_lock_grab_for_write(
3270
0
       internal_volume->read_write_lock,
3271
0
       error ) != 1 )
3272
0
  {
3273
0
    libcerror_error_set(
3274
0
     error,
3275
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3276
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3277
0
     "%s: unable to grab read/write lock for writing.",
3278
0
     function );
3279
3280
0
    return( -1 );
3281
0
  }
3282
0
#endif
3283
0
  if( internal_volume->file_system == NULL )
3284
0
  {
3285
0
    if( libfsapfs_internal_volume_get_file_system(
3286
0
         internal_volume,
3287
0
         error ) != 1 )
3288
0
    {
3289
0
      libcerror_error_set(
3290
0
       error,
3291
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3292
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3293
0
       "%s: unable to determine file system.",
3294
0
       function );
3295
3296
0
      result = -1;
3297
0
    }
3298
0
  }
3299
0
  if( result != -1 )
3300
0
  {
3301
0
    result = libfsapfs_file_system_get_file_entry_by_utf16_path(
3302
0
              internal_volume->file_system,
3303
0
              internal_volume->file_io_handle,
3304
0
              utf16_string,
3305
0
              utf16_string_length,
3306
0
              internal_volume->superblock->transaction_identifier,
3307
0
              file_entry,
3308
0
              error );
3309
3310
0
    if( result == -1 )
3311
0
    {
3312
0
      libcerror_error_set(
3313
0
       error,
3314
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3315
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3316
0
       "%s: unable to retrieve file entry from file system by UTF-16 path.",
3317
0
       function );
3318
3319
0
      result = -1;
3320
0
    }
3321
0
  }
3322
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3323
0
  if( libcthreads_read_write_lock_release_for_write(
3324
0
       internal_volume->read_write_lock,
3325
0
       error ) != 1 )
3326
0
  {
3327
0
    libcerror_error_set(
3328
0
     error,
3329
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3330
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3331
0
     "%s: unable to release read/write lock for writing.",
3332
0
     function );
3333
3334
0
    return( -1 );
3335
0
  }
3336
0
#endif
3337
0
  return( result );
3338
0
}
3339
3340
/* Retrieves the number of snapshots
3341
 * Returns 1 if successful or -1 on error
3342
 */
3343
int libfsapfs_volume_get_number_of_snapshots(
3344
     libfsapfs_volume_t *volume,
3345
     int *number_of_snapshots,
3346
     libcerror_error_t **error )
3347
0
{
3348
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
3349
0
  static char *function                        = "libfsapfs_volume_get_number_of_snapshots";
3350
0
  int result                                   = 1;
3351
3352
0
  if( volume == NULL )
3353
0
  {
3354
0
    libcerror_error_set(
3355
0
     error,
3356
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3357
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3358
0
     "%s: invalid volume.",
3359
0
     function );
3360
3361
0
    return( -1 );
3362
0
  }
3363
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3364
3365
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3366
0
  if( libcthreads_read_write_lock_grab_for_read(
3367
0
       internal_volume->read_write_lock,
3368
0
       error ) != 1 )
3369
0
  {
3370
0
    libcerror_error_set(
3371
0
     error,
3372
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3373
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3374
0
     "%s: unable to grab read/write lock for reading.",
3375
0
     function );
3376
3377
0
    return( -1 );
3378
0
  }
3379
0
#endif
3380
0
  if( libcdata_array_get_number_of_entries(
3381
0
       internal_volume->snapshots,
3382
0
       number_of_snapshots,
3383
0
       error ) != 1 )
3384
0
  {
3385
0
    libcerror_error_set(
3386
0
     error,
3387
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3388
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3389
0
     "%s: unable to retrieve number of entries from snapshots array.",
3390
0
     function );
3391
3392
0
    result = -1;
3393
0
  }
3394
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3395
0
  if( libcthreads_read_write_lock_release_for_read(
3396
0
       internal_volume->read_write_lock,
3397
0
       error ) != 1 )
3398
0
  {
3399
0
    libcerror_error_set(
3400
0
     error,
3401
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3402
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3403
0
     "%s: unable to release read/write lock for reading.",
3404
0
     function );
3405
3406
0
    return( -1 );
3407
0
  }
3408
0
#endif
3409
0
  return( result );
3410
0
}
3411
3412
/* Retrieves a specific of snapshot
3413
 * The snapshot reference must be freed after use with libfsapfs_snapshot_free
3414
 * Returns 1 if successful or -1 on error
3415
 */
3416
int libfsapfs_volume_get_snapshot_by_index(
3417
     libfsapfs_volume_t *volume,
3418
     int snapshot_index,
3419
     libfsapfs_snapshot_t **snapshot,
3420
     libcerror_error_t **error )
3421
0
{
3422
0
  libfsapfs_internal_volume_t *internal_volume     = NULL;
3423
0
  libfsapfs_snapshot_metadata_t *snapshot_metadata = NULL;
3424
0
  static char *function                            = "libfsapfs_volume_get_snapshot_by_index";
3425
0
  off64_t file_offset                              = 0;
3426
3427
0
  if( volume == NULL )
3428
0
  {
3429
0
    libcerror_error_set(
3430
0
     error,
3431
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3432
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3433
0
     "%s: invalid volume.",
3434
0
     function );
3435
3436
0
    return( -1 );
3437
0
  }
3438
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3439
3440
0
  if( snapshot == NULL )
3441
0
  {
3442
0
    libcerror_error_set(
3443
0
     error,
3444
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3445
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3446
0
     "%s: invalid snapshot.",
3447
0
     function );
3448
3449
0
    return( -1 );
3450
0
  }
3451
0
  if( *snapshot != NULL )
3452
0
  {
3453
0
    libcerror_error_set(
3454
0
     error,
3455
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3456
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3457
0
     "%s: invalid snapshot value already set.",
3458
0
     function );
3459
3460
0
    return( -1 );
3461
0
  }
3462
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3463
0
  if( libcthreads_read_write_lock_grab_for_read(
3464
0
       internal_volume->read_write_lock,
3465
0
       error ) != 1 )
3466
0
  {
3467
0
    libcerror_error_set(
3468
0
     error,
3469
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3470
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3471
0
     "%s: unable to grab read/write lock for reading.",
3472
0
     function );
3473
3474
0
    return( -1 );
3475
0
  }
3476
0
#endif
3477
0
  if( libcdata_array_get_entry_by_index(
3478
0
       internal_volume->snapshots,
3479
0
       snapshot_index,
3480
0
       (intptr_t **) &snapshot_metadata,
3481
0
       error ) != 1 )
3482
0
  {
3483
0
    libcerror_error_set(
3484
0
     error,
3485
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3486
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3487
0
     "%s: unable to retrieve snapshot metadata: %d.",
3488
0
     function,
3489
0
     snapshot_index );
3490
3491
0
    return( -1 );
3492
0
  }
3493
0
  if( snapshot_metadata == NULL )
3494
0
  {
3495
0
    libcerror_error_set(
3496
0
     error,
3497
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3498
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3499
0
     "%s: invalid snapshot metadata: %d.",
3500
0
     function,
3501
0
     snapshot_index );
3502
3503
0
    goto on_error;
3504
0
  }
3505
0
  if( libfsapfs_snapshot_initialize(
3506
0
       snapshot,
3507
0
       internal_volume->io_handle,
3508
0
       internal_volume->file_io_handle,
3509
0
       snapshot_metadata,
3510
0
       error ) != 1 )
3511
0
  {
3512
0
    libcerror_error_set(
3513
0
     error,
3514
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3515
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3516
0
     "%s: unable to create snapshot.",
3517
0
     function );
3518
3519
0
    goto on_error;
3520
0
  }
3521
0
  file_offset = (off64_t) ( snapshot_metadata->volume_superblock_block_number * internal_volume->io_handle->block_size );
3522
3523
0
  if( libfsapfs_internal_snapshot_open_read(
3524
0
       (libfsapfs_internal_snapshot_t *) *snapshot,
3525
0
       internal_volume->file_io_handle,
3526
0
       file_offset,
3527
0
       error ) != 1 )
3528
0
  {
3529
0
    libcerror_error_set(
3530
0
     error,
3531
0
     LIBCERROR_ERROR_DOMAIN_IO,
3532
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
3533
0
     "%s: unable to open snapshot: %d.",
3534
0
     function,
3535
0
     snapshot_index );
3536
3537
0
    goto on_error;
3538
0
  }
3539
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3540
0
  if( libcthreads_read_write_lock_release_for_read(
3541
0
       internal_volume->read_write_lock,
3542
0
       error ) != 1 )
3543
0
  {
3544
0
    libcerror_error_set(
3545
0
     error,
3546
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3547
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3548
0
     "%s: unable to release read/write lock for reading.",
3549
0
     function );
3550
3551
0
    return( -1 );
3552
0
  }
3553
0
#endif
3554
0
  return( 1 );
3555
3556
0
on_error:
3557
0
  if( *snapshot != NULL )
3558
0
  {
3559
0
    libfsapfs_snapshot_free(
3560
0
     snapshot,
3561
0
     NULL );
3562
0
  }
3563
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3564
0
  libcthreads_read_write_lock_release_for_read(
3565
0
   internal_volume->read_write_lock,
3566
   NULL );
3567
0
#endif
3568
0
  return( -1 );
3569
0
}
3570