Coverage Report

Created: 2026-10-22 07:28

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-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "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
850
{
67
850
  libfsapfs_internal_volume_t *internal_volume = NULL;
68
850
  static char *function                        = "libfsapfs_volume_initialize";
69
70
850
  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
850
  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
850
  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
850
  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
850
  internal_volume = memory_allocate_structure(
115
850
                     libfsapfs_internal_volume_t );
116
117
850
  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
850
  if( memory_set(
129
850
       internal_volume,
130
850
       0,
131
850
       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
850
  internal_volume->io_handle         = io_handle;
144
850
  internal_volume->file_io_handle    = file_io_handle;
145
850
  internal_volume->container_key_bag = container_key_bag;
146
850
  internal_volume->is_locked         = 1;
147
148
850
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
149
850
  if( libcthreads_read_write_lock_initialize(
150
850
       &( internal_volume->read_write_lock ),
151
850
       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
850
#endif
163
850
  *volume = (libfsapfs_volume_t *) internal_volume;
164
165
850
  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
850
}
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
850
{
183
850
  libfsapfs_internal_volume_t *internal_volume = NULL;
184
850
  static char *function                        = "libfsapfs_volume_free";
185
850
  int result                                   = 1;
186
187
850
  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
850
  if( *volume != NULL )
199
850
  {
200
850
    internal_volume = (libfsapfs_internal_volume_t *) *volume;
201
850
    *volume         = NULL;
202
203
850
    if( internal_volume->file_io_handle != NULL )
204
850
    {
205
850
      if( libfsapfs_internal_volume_close(
206
850
           internal_volume,
207
850
           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
850
    }
219
850
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
220
850
    if( libcthreads_read_write_lock_free(
221
850
         &( internal_volume->read_write_lock ),
222
850
         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
850
#endif
234
850
    memory_free(
235
850
     internal_volume );
236
850
  }
237
850
  return( result );
238
850
}
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
850
{
249
850
  libfsapfs_container_data_handle_t *container_data_handle     = NULL;
250
850
  libfsapfs_file_system_data_handle_t *file_system_data_handle = NULL;
251
850
  libfsapfs_object_map_t *object_map                           = NULL;
252
850
  static char *function                                        = "libfsapfs_internal_volume_open_read";
253
850
  uint64_t key_bag_block_number                                = 0;
254
850
  uint64_t key_bag_number_of_blocks                            = 0;
255
850
  int element_index                                            = 0;
256
850
  int result                                                   = 0;
257
258
#if defined( HAVE_DEBUG_OUTPUT )
259
  libfsapfs_extent_reference_tree_t *extent_reference_tree     = NULL;
260
#endif
261
262
850
  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
850
  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
850
  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
850
  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
850
  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
850
  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
850
  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
850
  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
850
  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
850
  if( libfsapfs_volume_superblock_initialize(
369
850
       &( internal_volume->superblock ),
370
850
       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
850
  if( libfsapfs_volume_superblock_read_file_io_handle(
382
850
       internal_volume->superblock,
383
850
       file_io_handle,
384
850
       file_offset,
385
850
       0,
386
850
       error ) != 1 )
387
284
  {
388
284
    libcerror_error_set(
389
284
     error,
390
284
     LIBCERROR_ERROR_DOMAIN_IO,
391
284
     LIBCERROR_IO_ERROR_READ_FAILED,
392
284
     "%s: unable to read volume superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
393
284
     function,
394
284
     file_offset,
395
284
     file_offset );
396
397
284
    goto on_error;
398
284
  }
399
566
  if( libfsapfs_container_data_handle_initialize(
400
566
       &container_data_handle,
401
566
       internal_volume->io_handle,
402
566
       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
566
  if( libfdata_vector_initialize(
414
566
       &( internal_volume->container_data_block_vector ),
415
566
       (size64_t) internal_volume->io_handle->block_size,
416
566
       (intptr_t *) container_data_handle,
417
566
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_container_data_handle_free,
418
566
       NULL,
419
566
       (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
566
       NULL,
421
566
       LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
422
566
       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
566
  internal_volume->container_data_handle = container_data_handle;
434
566
  container_data_handle                  = NULL;
435
436
566
  if( libfdata_vector_append_segment(
437
566
       internal_volume->container_data_block_vector,
438
566
       &element_index,
439
566
       0,
440
566
       0,
441
566
       internal_volume->io_handle->container_size,
442
566
       0,
443
566
       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
566
  if( internal_volume->superblock->object_map_block_number == 0 )
456
1
  {
457
1
    libcerror_error_set(
458
1
     error,
459
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
460
1
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
461
1
     "%s: missing object map block number.",
462
1
     function );
463
464
1
    goto on_error;
465
1
  }
466
#if defined( HAVE_DEBUG_OUTPUT )
467
  if( libcnotify_verbose != 0 )
468
  {
469
    libcnotify_printf(
470
     "Reading object map:\n" );
471
  }
472
#endif
473
565
  file_offset = internal_volume->superblock->object_map_block_number * internal_volume->io_handle->block_size;
474
475
565
  if( libfsapfs_object_map_initialize(
476
565
       &object_map,
477
565
       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
565
  if( libfsapfs_object_map_read_file_io_handle(
489
565
       object_map,
490
565
       file_io_handle,
491
565
       file_offset,
492
565
       error ) != 1 )
493
8
  {
494
8
    libcerror_error_set(
495
8
     error,
496
8
     LIBCERROR_ERROR_DOMAIN_IO,
497
8
     LIBCERROR_IO_ERROR_READ_FAILED,
498
8
     "%s: unable to read object map at offset: %" PRIi64 " (0x%08" PRIx64 ").",
499
8
     function,
500
8
     file_offset,
501
8
     file_offset );
502
503
8
    goto on_error;
504
8
  }
505
557
  if( object_map->btree_block_number == 0 )
506
1
  {
507
1
    libcerror_error_set(
508
1
     error,
509
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
510
1
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
511
1
     "%s: missing object map B-tree block number.",
512
1
     function );
513
514
1
    goto on_error;
515
1
  }
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
556
  if( libfsapfs_object_map_btree_initialize(
524
556
       &( internal_volume->object_map_btree ),
525
556
       internal_volume->io_handle,
526
556
       internal_volume->container_data_block_vector,
527
556
       object_map->btree_block_number,
528
556
       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
556
  if( libfsapfs_object_map_free(
540
556
       &object_map,
541
556
       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
556
  internal_volume->is_locked = 0;
553
554
556
  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
556
  if( libcdata_array_initialize(
695
556
       &( internal_volume->snapshots ),
696
556
       0,
697
556
       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
556
  if( internal_volume->superblock->snapshot_metadata_tree_block_number != 0 )
709
555
  {
710
555
    if( libfsapfs_snapshot_metadata_tree_initialize(
711
555
         &( internal_volume->snapshot_metadata_tree ),
712
555
         internal_volume->io_handle,
713
555
         internal_volume->container_data_block_vector,
714
555
         internal_volume->object_map_btree,
715
555
         internal_volume->superblock->snapshot_metadata_tree_block_number,
716
555
         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
555
    if( libfsapfs_snapshot_metadata_tree_get_snapshots(
728
555
         internal_volume->snapshot_metadata_tree,
729
555
         internal_volume->file_io_handle,
730
555
         internal_volume->superblock->transaction_identifier,
731
555
         internal_volume->snapshots,
732
555
         error ) == -1 )
733
530
    {
734
530
      libcerror_error_set(
735
530
       error,
736
530
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
737
530
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
738
530
       "%s: unable to retrieve snapshots.",
739
530
       function );
740
741
530
      goto on_error;
742
530
    }
743
555
  }
744
26
  if( internal_volume->superblock->file_system_root_object_identifier == 0 )
745
0
  {
746
0
    libcerror_error_set(
747
0
     error,
748
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
749
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
750
0
     "%s: invalid file system root object identifier - value out of bounds.",
751
0
     function );
752
753
0
    goto on_error;
754
0
  }
755
26
  if( libfsapfs_file_system_data_handle_initialize(
756
26
       &file_system_data_handle,
757
26
       internal_volume->io_handle,
758
26
       internal_volume->encryption_context,
759
26
       NULL,
760
26
       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
26
  if( libfdata_vector_initialize(
772
26
       &( internal_volume->file_system_data_block_vector ),
773
26
       (size64_t) internal_volume->io_handle->block_size,
774
26
       (intptr_t *) file_system_data_handle,
775
26
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_system_data_handle_free,
776
26
       NULL,
777
26
       (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
26
       NULL,
779
26
       LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
780
26
       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
26
  internal_volume->file_system_data_handle = file_system_data_handle;
792
26
  file_system_data_handle                  = NULL;
793
794
26
  if( libfdata_vector_append_segment(
795
26
       internal_volume->file_system_data_block_vector,
796
26
       &element_index,
797
26
       0,
798
26
       0,
799
26
       internal_volume->io_handle->container_size,
800
26
       0,
801
26
       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
26
  return( 1 );
813
814
824
on_error:
815
824
  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
824
  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
824
  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
824
  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
824
  if( internal_volume->snapshot_metadata_tree != NULL )
840
530
  {
841
530
    libcdata_array_free(
842
530
     &( internal_volume->snapshots ),
843
530
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
844
530
     NULL );
845
530
  }
846
824
  if( internal_volume->snapshot_metadata_tree != NULL )
847
530
  {
848
530
    libfsapfs_snapshot_metadata_tree_free(
849
530
     &( internal_volume->snapshot_metadata_tree ),
850
530
     NULL );
851
530
  }
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
824
  if( internal_volume->object_map_btree != NULL )
861
530
  {
862
530
    libfsapfs_object_map_btree_free(
863
530
     &( internal_volume->object_map_btree ),
864
530
     NULL );
865
530
  }
866
824
  if( object_map != NULL )
867
9
  {
868
9
    libfsapfs_object_map_free(
869
9
     &object_map,
870
9
     NULL );
871
9
  }
872
824
  if( internal_volume->container_data_block_vector != NULL )
873
540
  {
874
540
    libfdata_vector_free(
875
540
     &( internal_volume->container_data_block_vector ),
876
540
     NULL );
877
540
  }
878
824
  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
824
  if( internal_volume->superblock != NULL )
885
824
  {
886
824
    libfsapfs_volume_superblock_free(
887
824
     &( internal_volume->superblock ),
888
824
     NULL );
889
824
  }
890
824
  return( -1 );
891
26
}
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
850
{
900
850
  static char *function = "libfsapfs_internal_volume_close";
901
850
  int result            = 0;
902
903
850
  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
850
  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
850
  internal_volume->file_io_handle = NULL;
926
850
  internal_volume->is_locked      = 1;
927
928
850
  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
850
  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
850
  if( internal_volume->superblock != NULL )
973
26
  {
974
26
    if( libfsapfs_volume_superblock_free(
975
26
         &( internal_volume->superblock ),
976
26
         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
26
  }
988
850
  if( libfdata_vector_free(
989
850
       &( internal_volume->container_data_block_vector ),
990
850
       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
850
  if( internal_volume->object_map_btree != NULL )
1002
26
  {
1003
26
    if( libfsapfs_object_map_btree_free(
1004
26
         &( internal_volume->object_map_btree ),
1005
26
         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
26
  }
1017
850
  if( internal_volume->snapshot_metadata_tree != NULL )
1018
25
  {
1019
25
    if( libfsapfs_snapshot_metadata_tree_free(
1020
25
         &( internal_volume->snapshot_metadata_tree ),
1021
25
         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
25
  }
1033
850
  if( internal_volume->snapshots != NULL )
1034
26
  {
1035
26
    if( libcdata_array_free(
1036
26
         &( internal_volume->snapshots ),
1037
26
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
1038
26
         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
26
  }
1050
850
  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
850
  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
850
  if( libfdata_vector_free(
1083
850
       &( internal_volume->file_system_data_block_vector ),
1084
850
       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
850
  if( internal_volume->file_system != NULL )
1096
0
  {
1097
0
    if( libfsapfs_file_system_free(
1098
0
         &( internal_volume->file_system ),
1099
0
         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
0
  }
1111
850
  return( result );
1112
850
}
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
  size_t recovery_password_length = 0;
1126
0
  size_t user_password_length     = 0;
1127
0
  int result                      = 0;
1128
1129
0
  if( internal_volume == NULL )
1130
0
  {
1131
0
    libcerror_error_set(
1132
0
     error,
1133
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1134
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1135
0
     "%s: invalid volume.",
1136
0
     function );
1137
1138
0
    return( -1 );
1139
0
  }
1140
0
  if( internal_volume->superblock == NULL )
1141
0
  {
1142
0
    libcerror_error_set(
1143
0
     error,
1144
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1145
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1146
0
     "%s: invalid volume - missing superblock.",
1147
0
     function );
1148
1149
0
    return( -1 );
1150
0
  }
1151
0
  if( internal_volume->key_bag == NULL )
1152
0
  {
1153
0
    result = 1;
1154
0
  }
1155
0
  else
1156
0
  {
1157
0
    if( internal_volume->user_password_size > 0 )
1158
0
    {
1159
0
      user_password_length = internal_volume->user_password_size - 1;
1160
0
    }
1161
0
    if( internal_volume->recovery_password_size > 0 )
1162
0
    {
1163
0
      recovery_password_length = internal_volume->recovery_password_size - 1;
1164
0
    }
1165
0
    result = libfsapfs_volume_key_bag_get_volume_key(
1166
0
              internal_volume->key_bag,
1167
0
              internal_volume->user_password,
1168
0
              user_password_length,
1169
0
              internal_volume->recovery_password,
1170
0
              recovery_password_length,
1171
0
              volume_key,
1172
0
              256,
1173
0
              error );
1174
1175
0
    if( result == -1 )
1176
0
    {
1177
0
      libcerror_error_set(
1178
0
       error,
1179
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1180
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1181
0
       "%s: unable to retrieve volume key using password.",
1182
0
       function );
1183
1184
0
      goto on_error;
1185
0
    }
1186
0
    else if( result != 0 )
1187
0
    {
1188
0
      if( libfsapfs_container_key_bag_get_volume_master_key_by_identifier(
1189
0
           internal_volume->container_key_bag,
1190
0
           internal_volume->superblock->volume_identifier,
1191
0
           volume_key,
1192
0
           256,
1193
0
           volume_master_key,
1194
0
           256,
1195
0
           error ) != 1 )
1196
0
      {
1197
0
        libcerror_error_set(
1198
0
         error,
1199
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1200
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1201
0
         "%s: unable to retrieve volume master key.",
1202
0
         function );
1203
1204
0
        goto on_error;
1205
0
      }
1206
0
      memory_set(
1207
0
       volume_key,
1208
0
       0,
1209
0
       32 );
1210
1211
0
      if( libfsapfs_encryption_context_set_keys(
1212
0
           internal_volume->encryption_context,
1213
0
           volume_master_key,
1214
0
           16,
1215
0
           &( volume_master_key[ 16 ] ),
1216
0
           16,
1217
0
           error ) != 1 )
1218
0
      {
1219
0
        libcerror_error_set(
1220
0
         error,
1221
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1222
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1223
0
         "%s: unable to set keys in encryption context.",
1224
0
         function );
1225
1226
0
        goto on_error;
1227
0
      }
1228
0
      memory_set(
1229
0
       volume_master_key,
1230
0
       0,
1231
0
       32 );
1232
0
    }
1233
0
  }
1234
0
  if( result != 0 )
1235
0
  {
1236
0
    internal_volume->is_locked = 0;
1237
0
  }
1238
0
  return( result );
1239
1240
0
on_error:
1241
0
  memory_set(
1242
0
   volume_master_key,
1243
0
   0,
1244
0
   32 );
1245
1246
0
  memory_set(
1247
0
   volume_key,
1248
0
   0,
1249
0
   32 );
1250
1251
0
  return( -1 );
1252
0
}
1253
1254
/* Unlocks the volume
1255
 * Returns 1 if the volume is unlocked, 0 if not or -1 on error
1256
 */
1257
int libfsapfs_volume_unlock(
1258
     libfsapfs_volume_t *volume,
1259
     libcerror_error_t **error )
1260
0
{
1261
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1262
0
  static char *function                        = "libfsapfs_volume_unlock";
1263
0
  int result                                   = 1;
1264
1265
0
  if( volume == NULL )
1266
0
  {
1267
0
    libcerror_error_set(
1268
0
     error,
1269
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1270
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1271
0
     "%s: invalid volume.",
1272
0
     function );
1273
1274
0
    return( -1 );
1275
0
  }
1276
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1277
1278
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1279
0
  if( libcthreads_read_write_lock_grab_for_write(
1280
0
       internal_volume->read_write_lock,
1281
0
       error ) != 1 )
1282
0
  {
1283
0
    libcerror_error_set(
1284
0
     error,
1285
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1286
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1287
0
     "%s: unable to grab read/write lock for writing.",
1288
0
     function );
1289
1290
0
    return( -1 );
1291
0
  }
1292
0
#endif
1293
0
  if( internal_volume->is_locked != 0 )
1294
0
  {
1295
0
    result = libfsapfs_internal_volume_unlock(
1296
0
              internal_volume,
1297
0
              error );
1298
1299
0
    if( result == -1 )
1300
0
    {
1301
0
      libcerror_error_set(
1302
0
       error,
1303
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1304
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1305
0
       "%s: unable to unlock volume.",
1306
0
       function );
1307
1308
0
      result = -1;
1309
0
    }
1310
0
  }
1311
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1312
0
  if( libcthreads_read_write_lock_release_for_write(
1313
0
       internal_volume->read_write_lock,
1314
0
       error ) != 1 )
1315
0
  {
1316
0
    libcerror_error_set(
1317
0
     error,
1318
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1319
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1320
0
     "%s: unable to release read/write lock for writing.",
1321
0
     function );
1322
1323
0
    return( -1 );
1324
0
  }
1325
0
#endif
1326
0
  return( result );
1327
0
}
1328
1329
/* Retrieves the feature flags
1330
 * Returns 1 if successful or -1 on error
1331
 */
1332
int libfsapfs_volume_get_features_flags(
1333
     libfsapfs_volume_t *volume,
1334
     uint64_t *compatible_features_flags,
1335
     uint64_t *incompatible_features_flags,
1336
     uint64_t *read_only_compatible_features_flags,
1337
     libcerror_error_t **error )
1338
26
{
1339
26
  libfsapfs_internal_volume_t *internal_volume = NULL;
1340
26
  static char *function                        = "libfsapfs_volume_get_features_flags";
1341
1342
26
  if( volume == NULL )
1343
0
  {
1344
0
    libcerror_error_set(
1345
0
     error,
1346
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1347
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1348
0
     "%s: invalid volume.",
1349
0
     function );
1350
1351
0
    return( -1 );
1352
0
  }
1353
26
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1354
1355
26
  if( internal_volume->superblock == NULL )
1356
0
  {
1357
0
    libcerror_error_set(
1358
0
     error,
1359
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1360
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1361
0
     "%s: invalid volume - missing superblock.",
1362
0
     function );
1363
1364
0
    return( -1 );
1365
0
  }
1366
26
  if( compatible_features_flags == NULL )
1367
0
  {
1368
0
    libcerror_error_set(
1369
0
     error,
1370
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1371
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1372
0
     "%s: invalid compatible features flags.",
1373
0
     function );
1374
1375
0
    return( -1 );
1376
0
  }
1377
26
  if( incompatible_features_flags == NULL )
1378
0
  {
1379
0
    libcerror_error_set(
1380
0
     error,
1381
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1382
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1383
0
     "%s: invalid incompatible features flags.",
1384
0
     function );
1385
1386
0
    return( -1 );
1387
0
  }
1388
26
  if( read_only_compatible_features_flags == NULL )
1389
0
  {
1390
0
    libcerror_error_set(
1391
0
     error,
1392
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1393
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1394
0
     "%s: invalid read-only compatible features flags.",
1395
0
     function );
1396
1397
0
    return( -1 );
1398
0
  }
1399
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1400
26
  if( libcthreads_read_write_lock_grab_for_read(
1401
26
       internal_volume->read_write_lock,
1402
26
       error ) != 1 )
1403
0
  {
1404
0
    libcerror_error_set(
1405
0
     error,
1406
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1407
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1408
0
     "%s: unable to grab read/write lock for reading.",
1409
0
     function );
1410
1411
0
    return( -1 );
1412
0
  }
1413
26
#endif
1414
26
  *compatible_features_flags           = internal_volume->superblock->compatible_features_flags;
1415
26
  *incompatible_features_flags         = internal_volume->superblock->incompatible_features_flags;
1416
26
  *read_only_compatible_features_flags = internal_volume->superblock->read_only_compatible_features_flags;
1417
1418
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1419
26
  if( libcthreads_read_write_lock_release_for_read(
1420
26
       internal_volume->read_write_lock,
1421
26
       error ) != 1 )
1422
0
  {
1423
0
    libcerror_error_set(
1424
0
     error,
1425
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1426
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1427
0
     "%s: unable to release read/write lock for reading.",
1428
0
     function );
1429
1430
0
    return( -1 );
1431
0
  }
1432
26
#endif
1433
26
  return( 1 );
1434
26
}
1435
1436
/* Retrieves the size
1437
 * Returns 1 if successful or -1 on error
1438
 */
1439
int libfsapfs_volume_get_size(
1440
     libfsapfs_volume_t *volume,
1441
     size64_t *size,
1442
     libcerror_error_t **error )
1443
26
{
1444
26
  libfsapfs_internal_volume_t *internal_volume = NULL;
1445
26
  static char *function                        = "libfsapfs_volume_get_size";
1446
1447
26
  if( volume == NULL )
1448
0
  {
1449
0
    libcerror_error_set(
1450
0
     error,
1451
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1452
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1453
0
     "%s: invalid volume.",
1454
0
     function );
1455
1456
0
    return( -1 );
1457
0
  }
1458
26
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1459
1460
26
  if( internal_volume->superblock == NULL )
1461
0
  {
1462
0
    libcerror_error_set(
1463
0
     error,
1464
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1465
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1466
0
     "%s: invalid volume - missing superblock.",
1467
0
     function );
1468
1469
0
    return( -1 );
1470
0
  }
1471
26
  if( size == NULL )
1472
0
  {
1473
0
    libcerror_error_set(
1474
0
     error,
1475
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1476
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1477
0
     "%s: invalid size.",
1478
0
     function );
1479
1480
0
    return( -1 );
1481
0
  }
1482
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1483
26
  if( libcthreads_read_write_lock_grab_for_read(
1484
26
       internal_volume->read_write_lock,
1485
26
       error ) != 1 )
1486
0
  {
1487
0
    libcerror_error_set(
1488
0
     error,
1489
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1490
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1491
0
     "%s: unable to grab read/write lock for reading.",
1492
0
     function );
1493
1494
0
    return( -1 );
1495
0
  }
1496
26
#endif
1497
/* TODO implement */
1498
26
  *size = (size64_t) 0;
1499
1500
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1501
26
  if( libcthreads_read_write_lock_release_for_read(
1502
26
       internal_volume->read_write_lock,
1503
26
       error ) != 1 )
1504
0
  {
1505
0
    libcerror_error_set(
1506
0
     error,
1507
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1508
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1509
0
     "%s: unable to release read/write lock for reading.",
1510
0
     function );
1511
1512
0
    return( -1 );
1513
0
  }
1514
26
#endif
1515
26
  return( -1 );
1516
26
}
1517
1518
/* Retrieves the identifier
1519
 * The identifier is an UUID stored in big-endian and is 16 bytes of size
1520
 * Returns 1 if successful or -1 on error
1521
 */
1522
int libfsapfs_volume_get_identifier(
1523
     libfsapfs_volume_t *volume,
1524
     uint8_t *uuid_data,
1525
     size_t uuid_data_size,
1526
     libcerror_error_t **error )
1527
26
{
1528
26
  libfsapfs_internal_volume_t *internal_volume = NULL;
1529
26
  static char *function                        = "libfsapfs_volume_get_identifier";
1530
26
  int result                                   = 1;
1531
1532
26
  if( volume == NULL )
1533
0
  {
1534
0
    libcerror_error_set(
1535
0
     error,
1536
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1537
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1538
0
     "%s: invalid volume.",
1539
0
     function );
1540
1541
0
    return( -1 );
1542
0
  }
1543
26
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1544
1545
26
  if( internal_volume->superblock == NULL )
1546
0
  {
1547
0
    libcerror_error_set(
1548
0
     error,
1549
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1550
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1551
0
     "%s: invalid volume - missing superblock.",
1552
0
     function );
1553
1554
0
    return( -1 );
1555
0
  }
1556
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1557
26
  if( libcthreads_read_write_lock_grab_for_read(
1558
26
       internal_volume->read_write_lock,
1559
26
       error ) != 1 )
1560
0
  {
1561
0
    libcerror_error_set(
1562
0
     error,
1563
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1564
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1565
0
     "%s: unable to grab read/write lock for reading.",
1566
0
     function );
1567
1568
0
    return( -1 );
1569
0
  }
1570
26
#endif
1571
26
  if( libfsapfs_volume_superblock_get_volume_identifier(
1572
26
       internal_volume->superblock,
1573
26
       uuid_data,
1574
26
       uuid_data_size,
1575
26
       error ) != 1 )
1576
0
  {
1577
0
    libcerror_error_set(
1578
0
     error,
1579
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1580
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1581
0
     "%s: unable to retrieve volume identifier.",
1582
0
     function );
1583
1584
0
    result = -1;
1585
0
  }
1586
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1587
26
  if( libcthreads_read_write_lock_release_for_read(
1588
26
       internal_volume->read_write_lock,
1589
26
       error ) != 1 )
1590
0
  {
1591
0
    libcerror_error_set(
1592
0
     error,
1593
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1594
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1595
0
     "%s: unable to release read/write lock for reading.",
1596
0
     function );
1597
1598
0
    return( -1 );
1599
0
  }
1600
26
#endif
1601
26
  return( result );
1602
26
}
1603
1604
/* Retrieves the size of the UTF-8 encoded name
1605
 * The returned size includes the end of string character
1606
 * Returns 1 if successful or -1 on error
1607
 */
1608
int libfsapfs_volume_get_utf8_name_size(
1609
     libfsapfs_volume_t *volume,
1610
     size_t *utf8_string_size,
1611
     libcerror_error_t **error )
1612
26
{
1613
26
  libfsapfs_internal_volume_t *internal_volume = NULL;
1614
26
  static char *function                        = "libfsapfs_volume_get_utf8_name_size";
1615
26
  int result                                   = 1;
1616
1617
26
  if( volume == NULL )
1618
0
  {
1619
0
    libcerror_error_set(
1620
0
     error,
1621
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1622
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1623
0
     "%s: invalid volume.",
1624
0
     function );
1625
1626
0
    return( -1 );
1627
0
  }
1628
26
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1629
1630
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1631
26
  if( libcthreads_read_write_lock_grab_for_read(
1632
26
       internal_volume->read_write_lock,
1633
26
       error ) != 1 )
1634
0
  {
1635
0
    libcerror_error_set(
1636
0
     error,
1637
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1638
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1639
0
     "%s: unable to grab read/write lock for reading.",
1640
0
     function );
1641
1642
0
    return( -1 );
1643
0
  }
1644
26
#endif
1645
26
  if( libfsapfs_volume_superblock_get_utf8_volume_name_size(
1646
26
       internal_volume->superblock,
1647
26
       utf8_string_size,
1648
26
       error ) != 1 )
1649
4
  {
1650
4
    libcerror_error_set(
1651
4
     error,
1652
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1653
4
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1654
4
     "%s: unable to retrieve UTF-8 string size.",
1655
4
     function );
1656
1657
4
    result = -1;
1658
4
  }
1659
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1660
26
  if( libcthreads_read_write_lock_release_for_read(
1661
26
       internal_volume->read_write_lock,
1662
26
       error ) != 1 )
1663
0
  {
1664
0
    libcerror_error_set(
1665
0
     error,
1666
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1667
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1668
0
     "%s: unable to release read/write lock for reading.",
1669
0
     function );
1670
1671
0
    return( -1 );
1672
0
  }
1673
26
#endif
1674
26
  return( result );
1675
26
}
1676
1677
/* Retrieves the UTF-8 encoded name
1678
 * The size should include the end of string character
1679
 * Returns 1 if successful or -1 on error
1680
 */
1681
int libfsapfs_volume_get_utf8_name(
1682
     libfsapfs_volume_t *volume,
1683
     uint8_t *utf8_string,
1684
     size_t utf8_string_size,
1685
     libcerror_error_t **error )
1686
26
{
1687
26
  libfsapfs_internal_volume_t *internal_volume = NULL;
1688
26
  static char *function                        = "libfsapfs_volume_get_utf8_name";
1689
26
  int result                                   = 1;
1690
1691
26
  if( volume == NULL )
1692
0
  {
1693
0
    libcerror_error_set(
1694
0
     error,
1695
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1696
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1697
0
     "%s: invalid volume.",
1698
0
     function );
1699
1700
0
    return( -1 );
1701
0
  }
1702
26
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1703
1704
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1705
26
  if( libcthreads_read_write_lock_grab_for_read(
1706
26
       internal_volume->read_write_lock,
1707
26
       error ) != 1 )
1708
0
  {
1709
0
    libcerror_error_set(
1710
0
     error,
1711
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1712
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1713
0
     "%s: unable to grab read/write lock for reading.",
1714
0
     function );
1715
1716
0
    return( -1 );
1717
0
  }
1718
26
#endif
1719
26
  if( libfsapfs_volume_superblock_get_utf8_volume_name(
1720
26
       internal_volume->superblock,
1721
26
       utf8_string,
1722
26
       utf8_string_size,
1723
26
       error ) != 1 )
1724
4
  {
1725
4
    libcerror_error_set(
1726
4
     error,
1727
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1728
4
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1729
4
     "%s: unable to retrieve UTF-8 string.",
1730
4
     function );
1731
1732
4
    result = -1;
1733
4
  }
1734
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1735
26
  if( libcthreads_read_write_lock_release_for_read(
1736
26
       internal_volume->read_write_lock,
1737
26
       error ) != 1 )
1738
0
  {
1739
0
    libcerror_error_set(
1740
0
     error,
1741
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1742
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1743
0
     "%s: unable to release read/write lock for reading.",
1744
0
     function );
1745
1746
0
    return( -1 );
1747
0
  }
1748
26
#endif
1749
26
  return( result );
1750
26
}
1751
1752
/* Retrieves the size of the UTF-16 encoded name
1753
 * The returned size includes the end of string character
1754
 * Returns 1 if successful or -1 on error
1755
 */
1756
int libfsapfs_volume_get_utf16_name_size(
1757
     libfsapfs_volume_t *volume,
1758
     size_t *utf16_string_size,
1759
     libcerror_error_t **error )
1760
0
{
1761
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1762
0
  static char *function                        = "libfsapfs_volume_get_utf16_name_size";
1763
0
  int result                                   = 1;
1764
1765
0
  if( volume == NULL )
1766
0
  {
1767
0
    libcerror_error_set(
1768
0
     error,
1769
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1770
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1771
0
     "%s: invalid volume.",
1772
0
     function );
1773
1774
0
    return( -1 );
1775
0
  }
1776
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1777
1778
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1779
0
  if( libcthreads_read_write_lock_grab_for_read(
1780
0
       internal_volume->read_write_lock,
1781
0
       error ) != 1 )
1782
0
  {
1783
0
    libcerror_error_set(
1784
0
     error,
1785
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1786
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1787
0
     "%s: unable to grab read/write lock for reading.",
1788
0
     function );
1789
1790
0
    return( -1 );
1791
0
  }
1792
0
#endif
1793
0
  if( libfsapfs_volume_superblock_get_utf16_volume_name_size(
1794
0
       internal_volume->superblock,
1795
0
       utf16_string_size,
1796
0
       error ) != 1 )
1797
0
  {
1798
0
    libcerror_error_set(
1799
0
     error,
1800
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1801
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1802
0
     "%s: unable to retrieve UTF-16 string size.",
1803
0
     function );
1804
1805
0
    result = -1;
1806
0
  }
1807
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1808
0
  if( libcthreads_read_write_lock_release_for_read(
1809
0
       internal_volume->read_write_lock,
1810
0
       error ) != 1 )
1811
0
  {
1812
0
    libcerror_error_set(
1813
0
     error,
1814
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1815
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1816
0
     "%s: unable to release read/write lock for reading.",
1817
0
     function );
1818
1819
0
    return( -1 );
1820
0
  }
1821
0
#endif
1822
0
  return( result );
1823
0
}
1824
1825
/* Retrieves the UTF-16 encoded name
1826
 * The size should include the end of string character
1827
 * Returns 1 if successful or -1 on error
1828
 */
1829
int libfsapfs_volume_get_utf16_name(
1830
     libfsapfs_volume_t *volume,
1831
     uint16_t *utf16_string,
1832
     size_t utf16_string_size,
1833
     libcerror_error_t **error )
1834
0
{
1835
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1836
0
  static char *function                        = "libfsapfs_volume_get_utf16_name";
1837
0
  int result                                   = 1;
1838
1839
0
  if( volume == NULL )
1840
0
  {
1841
0
    libcerror_error_set(
1842
0
     error,
1843
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1844
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1845
0
     "%s: invalid volume.",
1846
0
     function );
1847
1848
0
    return( -1 );
1849
0
  }
1850
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1851
1852
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1853
0
  if( libcthreads_read_write_lock_grab_for_read(
1854
0
       internal_volume->read_write_lock,
1855
0
       error ) != 1 )
1856
0
  {
1857
0
    libcerror_error_set(
1858
0
     error,
1859
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1860
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1861
0
     "%s: unable to grab read/write lock for reading.",
1862
0
     function );
1863
1864
0
    return( -1 );
1865
0
  }
1866
0
#endif
1867
0
  if( libfsapfs_volume_superblock_get_utf16_volume_name(
1868
0
       internal_volume->superblock,
1869
0
       utf16_string,
1870
0
       utf16_string_size,
1871
0
       error ) != 1 )
1872
0
  {
1873
0
    libcerror_error_set(
1874
0
     error,
1875
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1876
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1877
0
     "%s: unable to retrieve UTF-16 string.",
1878
0
     function );
1879
1880
0
    result = -1;
1881
0
  }
1882
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1883
0
  if( libcthreads_read_write_lock_release_for_read(
1884
0
       internal_volume->read_write_lock,
1885
0
       error ) != 1 )
1886
0
  {
1887
0
    libcerror_error_set(
1888
0
     error,
1889
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1890
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1891
0
     "%s: unable to release read/write lock for reading.",
1892
0
     function );
1893
1894
0
    return( -1 );
1895
0
  }
1896
0
#endif
1897
0
  return( result );
1898
0
}
1899
1900
/* Determines if the volume is locked
1901
 * Returns 1 if locked, 0 if not or -1 on error
1902
 */
1903
int libfsapfs_volume_is_locked(
1904
     libfsapfs_volume_t *volume,
1905
     libcerror_error_t **error )
1906
26
{
1907
26
  libfsapfs_internal_volume_t *internal_volume = NULL;
1908
26
  static char *function                        = "libfsapfs_volume_is_locked";
1909
26
  uint8_t is_locked                            = 0;
1910
1911
26
  if( volume == NULL )
1912
0
  {
1913
0
    libcerror_error_set(
1914
0
     error,
1915
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1916
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1917
0
     "%s: invalid volume.",
1918
0
     function );
1919
1920
0
    return( -1 );
1921
0
  }
1922
26
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1923
1924
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1925
26
  if( libcthreads_read_write_lock_grab_for_read(
1926
26
       internal_volume->read_write_lock,
1927
26
       error ) != 1 )
1928
0
  {
1929
0
    libcerror_error_set(
1930
0
     error,
1931
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1932
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1933
0
     "%s: unable to grab read/write lock for reading.",
1934
0
     function );
1935
1936
0
    return( -1 );
1937
0
  }
1938
26
#endif
1939
26
  is_locked = internal_volume->is_locked;
1940
1941
26
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1942
26
  if( libcthreads_read_write_lock_release_for_read(
1943
26
       internal_volume->read_write_lock,
1944
26
       error ) != 1 )
1945
0
  {
1946
0
    libcerror_error_set(
1947
0
     error,
1948
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1949
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1950
0
     "%s: unable to release read/write lock for reading.",
1951
0
     function );
1952
1953
0
    return( -1 );
1954
0
  }
1955
26
#endif
1956
26
  return( is_locked );
1957
26
}
1958
1959
/* Sets an UTF-8 formatted password
1960
 * This function needs to be used before one of the open or unlock functions
1961
 * Returns 1 if successful, 0 if password is invalid or -1 on error
1962
 */
1963
int libfsapfs_volume_set_utf8_password(
1964
     libfsapfs_volume_t *volume,
1965
     const uint8_t *utf8_string,
1966
     size_t utf8_string_length,
1967
     libcerror_error_t **error )
1968
0
{
1969
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
1970
0
  static char *function                        = "libfsapfs_volume_set_utf8_password";
1971
1972
0
  if( volume == NULL )
1973
0
  {
1974
0
    libcerror_error_set(
1975
0
     error,
1976
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1977
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1978
0
     "%s: invalid volume.",
1979
0
     function );
1980
1981
0
    return( -1 );
1982
0
  }
1983
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
1984
1985
0
  if( utf8_string == NULL )
1986
0
  {
1987
0
    libcerror_error_set(
1988
0
     error,
1989
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1990
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1991
0
     "%s: invalid UTF-8 string.",
1992
0
     function );
1993
1994
0
    return( -1 );
1995
0
  }
1996
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1997
0
  if( libcthreads_read_write_lock_grab_for_write(
1998
0
       internal_volume->read_write_lock,
1999
0
       error ) != 1 )
2000
0
  {
2001
0
    libcerror_error_set(
2002
0
     error,
2003
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2004
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2005
0
     "%s: unable to grab read/write lock for writing.",
2006
0
     function );
2007
2008
0
    return( -1 );
2009
0
  }
2010
0
#endif
2011
0
  if( internal_volume->user_password != NULL )
2012
0
  {
2013
0
    if( memory_set(
2014
0
         internal_volume->user_password,
2015
0
         0,
2016
0
         internal_volume->user_password_size ) == NULL )
2017
0
    {
2018
0
      libcerror_error_set(
2019
0
       error,
2020
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2021
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2022
0
       "%s: unable to clear user password.",
2023
0
       function );
2024
2025
0
      goto on_error;
2026
0
    }
2027
0
    memory_free(
2028
0
     internal_volume->user_password );
2029
2030
0
    internal_volume->user_password      = NULL;
2031
0
    internal_volume->user_password_size = 0;
2032
0
  }
2033
0
  internal_volume->user_password_size = narrow_string_length(
2034
0
                                         (char *) utf8_string );
2035
2036
0
  if( ( internal_volume->user_password_size == 0 )
2037
0
   || ( internal_volume->user_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2038
0
  {
2039
0
    libcerror_error_set(
2040
0
     error,
2041
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2042
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2043
0
     "%s: invalid volume - user password size value out of bounds.",
2044
0
     function );
2045
2046
0
    goto on_error;
2047
0
  }
2048
0
  internal_volume->user_password_size += 1;
2049
2050
0
  internal_volume->user_password = (uint8_t *) memory_allocate(
2051
0
                                                sizeof( uint8_t ) * internal_volume->user_password_size );
2052
2053
0
  if( internal_volume->user_password == NULL )
2054
0
  {
2055
0
    libcerror_error_set(
2056
0
     error,
2057
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2058
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2059
0
     "%s: unable to create user password.",
2060
0
     function );
2061
2062
0
    goto on_error;
2063
0
  }
2064
0
  if( memory_copy(
2065
0
       internal_volume->user_password,
2066
0
       utf8_string,
2067
0
       utf8_string_length ) == NULL )
2068
0
  {
2069
0
    libcerror_error_set(
2070
0
     error,
2071
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2072
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2073
0
     "%s: unable to copy user password.",
2074
0
     function );
2075
2076
0
    goto on_error;
2077
0
  }
2078
0
  internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
2079
2080
#if defined( HAVE_DEBUG_OUTPUT )
2081
  if( libcnotify_verbose != 0 )
2082
  {
2083
    libcnotify_printf(
2084
     "%s: user password: %s\n",
2085
     function,
2086
     internal_volume->user_password );
2087
  }
2088
#endif
2089
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2090
0
  if( libcthreads_read_write_lock_release_for_write(
2091
0
       internal_volume->read_write_lock,
2092
0
       error ) != 1 )
2093
0
  {
2094
0
    libcerror_error_set(
2095
0
     error,
2096
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2097
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2098
0
     "%s: unable to release read/write lock for writing.",
2099
0
     function );
2100
2101
0
    return( -1 );
2102
0
  }
2103
0
#endif
2104
0
  return( 1 );
2105
2106
0
on_error:
2107
0
  if( internal_volume->user_password != NULL )
2108
0
  {
2109
0
    memory_set(
2110
0
     internal_volume->user_password,
2111
0
     0,
2112
0
     internal_volume->user_password_size );
2113
0
    memory_free(
2114
0
     internal_volume->user_password );
2115
2116
0
    internal_volume->user_password = NULL;
2117
0
  }
2118
0
  internal_volume->user_password_size = 0;
2119
2120
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2121
0
  libcthreads_read_write_lock_release_for_write(
2122
0
   internal_volume->read_write_lock,
2123
0
   NULL );
2124
0
#endif
2125
0
  return( -1 );
2126
0
}
2127
2128
/* Sets an UTF-16 formatted password
2129
 * This function needs to be used before one of the open or unlock functions
2130
 * Returns 1 if successful, 0 if password is invalid or -1 on error
2131
 */
2132
int libfsapfs_volume_set_utf16_password(
2133
     libfsapfs_volume_t *volume,
2134
     const uint16_t *utf16_string,
2135
     size_t utf16_string_length,
2136
     libcerror_error_t **error )
2137
0
{
2138
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2139
0
  static char *function                        = "libfsapfs_volume_set_utf16_password";
2140
2141
0
  if( volume == NULL )
2142
0
  {
2143
0
    libcerror_error_set(
2144
0
     error,
2145
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2146
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2147
0
     "%s: invalid volume.",
2148
0
     function );
2149
2150
0
    return( -1 );
2151
0
  }
2152
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2153
2154
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2155
0
  if( libcthreads_read_write_lock_grab_for_write(
2156
0
       internal_volume->read_write_lock,
2157
0
       error ) != 1 )
2158
0
  {
2159
0
    libcerror_error_set(
2160
0
     error,
2161
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2162
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2163
0
     "%s: unable to grab read/write lock for writing.",
2164
0
     function );
2165
2166
0
    return( -1 );
2167
0
  }
2168
0
#endif
2169
0
  if( internal_volume->user_password != NULL )
2170
0
  {
2171
0
    if( memory_set(
2172
0
         internal_volume->user_password,
2173
0
         0,
2174
0
         internal_volume->user_password_size ) == NULL )
2175
0
    {
2176
0
      libcerror_error_set(
2177
0
       error,
2178
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2179
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2180
0
       "%s: unable to clear user password.",
2181
0
       function );
2182
2183
0
      goto on_error;
2184
0
    }
2185
0
    memory_free(
2186
0
     internal_volume->user_password );
2187
2188
0
    internal_volume->user_password      = NULL;
2189
0
    internal_volume->user_password_size = 0;
2190
0
  }
2191
0
  if( libuna_utf8_string_size_from_utf16(
2192
0
       utf16_string,
2193
0
       utf16_string_length,
2194
0
       &( internal_volume->user_password_size ),
2195
0
       error ) != 1 )
2196
0
  {
2197
0
    libcerror_error_set(
2198
0
     error,
2199
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2200
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2201
0
     "%s: unable to set password size.",
2202
0
     function );
2203
2204
0
    goto on_error;
2205
0
  }
2206
0
  if( ( internal_volume->user_password_size == 0 )
2207
0
   || ( internal_volume->user_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2208
0
  {
2209
0
    libcerror_error_set(
2210
0
     error,
2211
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2212
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2213
0
     "%s: invalid volume - user password size value out of bounds.",
2214
0
     function );
2215
2216
0
    goto on_error;
2217
0
  }
2218
0
  internal_volume->user_password_size += 1;
2219
2220
0
  internal_volume->user_password = (uint8_t *) memory_allocate(
2221
0
                                                sizeof( uint8_t ) * internal_volume->user_password_size );
2222
2223
0
  if( internal_volume->user_password == NULL )
2224
0
  {
2225
0
    libcerror_error_set(
2226
0
     error,
2227
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2228
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2229
0
     "%s: unable to create user password.",
2230
0
     function );
2231
2232
0
    goto on_error;
2233
0
  }
2234
0
  if( libuna_utf8_string_copy_from_utf16(
2235
0
       internal_volume->user_password,
2236
0
       internal_volume->user_password_size,
2237
0
       utf16_string,
2238
0
       utf16_string_length,
2239
0
       error ) != 1 )
2240
0
  {
2241
0
    libcerror_error_set(
2242
0
     error,
2243
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2244
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2245
0
     "%s: unable to copy user password.",
2246
0
     function );
2247
2248
0
    goto on_error;
2249
0
  }
2250
0
  internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
2251
2252
#if defined( HAVE_DEBUG_OUTPUT )
2253
  if( libcnotify_verbose != 0 )
2254
  {
2255
    libcnotify_printf(
2256
     "%s: user password: %s\n",
2257
     function,
2258
     internal_volume->user_password );
2259
  }
2260
#endif
2261
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2262
0
  if( libcthreads_read_write_lock_release_for_write(
2263
0
       internal_volume->read_write_lock,
2264
0
       error ) != 1 )
2265
0
  {
2266
0
    libcerror_error_set(
2267
0
     error,
2268
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2269
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2270
0
     "%s: unable to release read/write lock for writing.",
2271
0
     function );
2272
2273
0
    return( -1 );
2274
0
  }
2275
0
#endif
2276
0
  return( 1 );
2277
2278
0
on_error:
2279
0
  if( internal_volume->user_password != NULL )
2280
0
  {
2281
0
    memory_set(
2282
0
     internal_volume->user_password,
2283
0
     0,
2284
0
     internal_volume->user_password_size );
2285
0
    memory_free(
2286
0
     internal_volume->user_password );
2287
2288
0
    internal_volume->user_password = NULL;
2289
0
  }
2290
0
  internal_volume->user_password_size = 0;
2291
2292
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2293
0
  libcthreads_read_write_lock_release_for_write(
2294
0
   internal_volume->read_write_lock,
2295
0
   NULL );
2296
0
#endif
2297
0
  return( -1 );
2298
0
}
2299
2300
/* Sets an UTF-8 formatted recovery password
2301
 * This function needs to be used before one of the open or unlock functions
2302
 * Returns 1 if successful, 0 if recovery password is invalid or -1 on error
2303
 */
2304
int libfsapfs_volume_set_utf8_recovery_password(
2305
     libfsapfs_volume_t *volume,
2306
     const uint8_t *utf8_string,
2307
     size_t utf8_string_length,
2308
     libcerror_error_t **error )
2309
0
{
2310
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2311
0
  static char *function                        = "libfsapfs_volume_set_utf8_recovery_password";
2312
2313
0
  if( volume == NULL )
2314
0
  {
2315
0
    libcerror_error_set(
2316
0
     error,
2317
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2318
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2319
0
     "%s: invalid volume.",
2320
0
     function );
2321
2322
0
    return( -1 );
2323
0
  }
2324
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2325
2326
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2327
0
  if( libcthreads_read_write_lock_grab_for_write(
2328
0
       internal_volume->read_write_lock,
2329
0
       error ) != 1 )
2330
0
  {
2331
0
    libcerror_error_set(
2332
0
     error,
2333
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2334
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2335
0
     "%s: unable to grab read/write lock for writing.",
2336
0
     function );
2337
2338
0
    return( -1 );
2339
0
  }
2340
0
#endif
2341
0
  if( internal_volume->recovery_password != NULL )
2342
0
  {
2343
0
    if( memory_set(
2344
0
         internal_volume->recovery_password,
2345
0
         0,
2346
0
         internal_volume->recovery_password_size ) == NULL )
2347
0
    {
2348
0
      libcerror_error_set(
2349
0
       error,
2350
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2351
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2352
0
       "%s: unable to clear recovery password.",
2353
0
       function );
2354
2355
0
      goto on_error;
2356
0
    }
2357
0
    memory_free(
2358
0
     internal_volume->recovery_password );
2359
2360
0
    internal_volume->recovery_password      = NULL;
2361
0
    internal_volume->recovery_password_size = 0;
2362
0
  }
2363
0
  internal_volume->recovery_password_size = narrow_string_length(
2364
0
                                             (char *) utf8_string );
2365
2366
0
  if( ( internal_volume->recovery_password_size == 0 )
2367
0
   || ( internal_volume->recovery_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2368
0
  {
2369
0
    libcerror_error_set(
2370
0
     error,
2371
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2372
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2373
0
     "%s: invalid volume - user recovery password size value out of bounds.",
2374
0
     function );
2375
2376
0
    goto on_error;
2377
0
  }
2378
0
  internal_volume->recovery_password_size += 1;
2379
2380
0
  internal_volume->recovery_password = (uint8_t *) memory_allocate(
2381
0
                                                    sizeof( uint8_t ) * internal_volume->recovery_password_size );
2382
2383
0
  if( internal_volume->recovery_password == NULL )
2384
0
  {
2385
0
    libcerror_error_set(
2386
0
     error,
2387
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2388
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2389
0
     "%s: unable to create recovery password.",
2390
0
     function );
2391
2392
0
    goto on_error;
2393
0
  }
2394
0
  if( memory_copy(
2395
0
       internal_volume->recovery_password,
2396
0
       utf8_string,
2397
0
       utf8_string_length ) == NULL )
2398
0
  {
2399
0
    libcerror_error_set(
2400
0
     error,
2401
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2402
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2403
0
     "%s: unable to copy recovery password.",
2404
0
     function );
2405
2406
0
    goto on_error;
2407
0
  }
2408
0
  internal_volume->recovery_password[ internal_volume->recovery_password_size - 1 ] = 0;
2409
2410
#if defined( HAVE_DEBUG_OUTPUT )
2411
  if( libcnotify_verbose != 0 )
2412
  {
2413
    libcnotify_printf(
2414
     "%s: recovery password: %s\n",
2415
     function,
2416
     internal_volume->recovery_password );
2417
  }
2418
#endif
2419
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2420
0
  if( libcthreads_read_write_lock_release_for_write(
2421
0
       internal_volume->read_write_lock,
2422
0
       error ) != 1 )
2423
0
  {
2424
0
    libcerror_error_set(
2425
0
     error,
2426
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2427
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2428
0
     "%s: unable to release read/write lock for writing.",
2429
0
     function );
2430
2431
0
    return( -1 );
2432
0
  }
2433
0
#endif
2434
0
  return( 1 );
2435
2436
0
on_error:
2437
0
  if( internal_volume->recovery_password != NULL )
2438
0
  {
2439
0
    memory_set(
2440
0
     internal_volume->recovery_password,
2441
0
     0,
2442
0
     internal_volume->recovery_password_size );
2443
0
    memory_free(
2444
0
     internal_volume->recovery_password );
2445
2446
0
    internal_volume->recovery_password = NULL;
2447
0
  }
2448
0
  internal_volume->recovery_password_size = 0;
2449
2450
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2451
0
  libcthreads_read_write_lock_release_for_write(
2452
0
   internal_volume->read_write_lock,
2453
0
   NULL );
2454
0
#endif
2455
0
  return( -1 );
2456
0
}
2457
2458
/* Sets an UTF-16 formatted recovery password
2459
 * This function needs to be used before one of the open or unlock functions
2460
 * Returns 1 if successful, 0 if recovery password is invalid or -1 on error
2461
 */
2462
int libfsapfs_volume_set_utf16_recovery_password(
2463
     libfsapfs_volume_t *volume,
2464
     const uint16_t *utf16_string,
2465
     size_t utf16_string_length,
2466
     libcerror_error_t **error )
2467
0
{
2468
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2469
0
  static char *function                        = "libfsapfs_volume_set_utf16_recovery_password";
2470
2471
0
  if( volume == NULL )
2472
0
  {
2473
0
    libcerror_error_set(
2474
0
     error,
2475
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2476
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2477
0
     "%s: invalid volume.",
2478
0
     function );
2479
2480
0
    return( -1 );
2481
0
  }
2482
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2483
2484
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2485
0
  if( libcthreads_read_write_lock_grab_for_write(
2486
0
       internal_volume->read_write_lock,
2487
0
       error ) != 1 )
2488
0
  {
2489
0
    libcerror_error_set(
2490
0
     error,
2491
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2492
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2493
0
     "%s: unable to grab read/write lock for writing.",
2494
0
     function );
2495
2496
0
    return( -1 );
2497
0
  }
2498
0
#endif
2499
0
  if( internal_volume->recovery_password != NULL )
2500
0
  {
2501
0
    if( memory_set(
2502
0
         internal_volume->recovery_password,
2503
0
         0,
2504
0
         internal_volume->recovery_password_size ) == NULL )
2505
0
    {
2506
0
      libcerror_error_set(
2507
0
       error,
2508
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2509
0
       LIBCERROR_MEMORY_ERROR_SET_FAILED,
2510
0
       "%s: unable to clear recovery password.",
2511
0
       function );
2512
2513
0
      goto on_error;
2514
0
    }
2515
0
    memory_free(
2516
0
     internal_volume->recovery_password );
2517
2518
0
    internal_volume->recovery_password      = NULL;
2519
0
    internal_volume->recovery_password_size = 0;
2520
0
  }
2521
0
  if( libuna_utf8_string_size_from_utf16(
2522
0
       utf16_string,
2523
0
       utf16_string_length,
2524
0
       &( internal_volume->recovery_password_size ),
2525
0
       error ) != 1 )
2526
0
  {
2527
0
    libcerror_error_set(
2528
0
     error,
2529
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2530
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2531
0
     "%s: unable to set password size.",
2532
0
     function );
2533
2534
0
    goto on_error;
2535
0
  }
2536
0
  if( ( internal_volume->recovery_password_size == 0 )
2537
0
   || ( internal_volume->recovery_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2538
0
  {
2539
0
    libcerror_error_set(
2540
0
     error,
2541
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2542
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2543
0
     "%s: invalid volume - user recovery password size value out of bounds.",
2544
0
     function );
2545
2546
0
    goto on_error;
2547
0
  }
2548
0
  internal_volume->recovery_password_size += 1;
2549
2550
0
  internal_volume->recovery_password = (uint8_t *) memory_allocate(
2551
0
                                                    sizeof( uint8_t ) * internal_volume->recovery_password_size );
2552
2553
0
  if( internal_volume->recovery_password == NULL )
2554
0
  {
2555
0
    libcerror_error_set(
2556
0
     error,
2557
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2558
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2559
0
     "%s: unable to create recovery password.",
2560
0
     function );
2561
2562
0
    goto on_error;
2563
0
  }
2564
0
  if( libuna_utf8_string_copy_from_utf16(
2565
0
       internal_volume->recovery_password,
2566
0
       internal_volume->recovery_password_size,
2567
0
       utf16_string,
2568
0
       utf16_string_length,
2569
0
       error ) != 1 )
2570
0
  {
2571
0
    libcerror_error_set(
2572
0
     error,
2573
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2574
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2575
0
     "%s: unable to copy recovery password.",
2576
0
     function );
2577
2578
0
    goto on_error;
2579
0
  }
2580
0
  internal_volume->recovery_password[ internal_volume->recovery_password_size - 1 ] = 0;
2581
2582
#if defined( HAVE_DEBUG_OUTPUT )
2583
  if( libcnotify_verbose != 0 )
2584
  {
2585
    libcnotify_printf(
2586
     "%s: recovery password: %s\n",
2587
     function,
2588
     internal_volume->recovery_password );
2589
  }
2590
#endif
2591
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2592
0
  if( libcthreads_read_write_lock_release_for_write(
2593
0
       internal_volume->read_write_lock,
2594
0
       error ) != 1 )
2595
0
  {
2596
0
    libcerror_error_set(
2597
0
     error,
2598
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2599
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2600
0
     "%s: unable to release read/write lock for writing.",
2601
0
     function );
2602
2603
0
    return( -1 );
2604
0
  }
2605
0
#endif
2606
0
  return( 1 );
2607
2608
0
on_error:
2609
0
  if( internal_volume->recovery_password != NULL )
2610
0
  {
2611
0
    memory_set(
2612
0
     internal_volume->recovery_password,
2613
0
     0,
2614
0
     internal_volume->recovery_password_size );
2615
0
    memory_free(
2616
0
     internal_volume->recovery_password );
2617
2618
0
    internal_volume->recovery_password = NULL;
2619
0
  }
2620
0
  internal_volume->recovery_password_size = 0;
2621
2622
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2623
0
  libcthreads_read_write_lock_release_for_write(
2624
0
   internal_volume->read_write_lock,
2625
0
   NULL );
2626
0
#endif
2627
0
  return( -1 );
2628
0
}
2629
2630
/* Retrieves the root directory file entry
2631
 * Returns 1 if successful, or 0 if not available or -1 on error
2632
 */
2633
int libfsapfs_volume_get_root_directory(
2634
     libfsapfs_volume_t *volume,
2635
     libfsapfs_file_entry_t **file_entry,
2636
     libcerror_error_t **error )
2637
0
{
2638
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2639
0
  static char *function                        = "libfsapfs_volume_get_root_directory";
2640
0
  int result                                   = 1;
2641
2642
0
  if( volume == NULL )
2643
0
  {
2644
0
    libcerror_error_set(
2645
0
     error,
2646
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2647
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2648
0
     "%s: invalid volume.",
2649
0
     function );
2650
2651
0
    return( -1 );
2652
0
  }
2653
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2654
2655
0
  if( internal_volume->superblock == NULL )
2656
0
  {
2657
0
    libcerror_error_set(
2658
0
     error,
2659
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2660
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2661
0
     "%s: invalid volume - missing superblock.",
2662
0
     function );
2663
2664
0
    return( -1 );
2665
0
  }
2666
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2667
0
  if( libcthreads_read_write_lock_grab_for_write(
2668
0
       internal_volume->read_write_lock,
2669
0
       error ) != 1 )
2670
0
  {
2671
0
    libcerror_error_set(
2672
0
     error,
2673
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2674
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2675
0
     "%s: unable to grab read/write lock for writing.",
2676
0
     function );
2677
2678
0
    return( -1 );
2679
0
  }
2680
0
#endif
2681
0
  if( internal_volume->file_system == NULL )
2682
0
  {
2683
0
    if( libfsapfs_internal_volume_get_file_system(
2684
0
         internal_volume,
2685
0
         error ) != 1 )
2686
0
    {
2687
0
      libcerror_error_set(
2688
0
       error,
2689
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2690
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2691
0
       "%s: unable to determine file system.",
2692
0
       function );
2693
2694
0
      result = -1;
2695
0
    }
2696
0
  }
2697
0
  if( result != -1 )
2698
0
  {
2699
0
    result = libfsapfs_file_system_get_file_entry_by_identifier(
2700
0
              internal_volume->file_system,
2701
0
              internal_volume->file_io_handle,
2702
0
              2,
2703
0
              internal_volume->superblock->transaction_identifier,
2704
0
              file_entry,
2705
0
              error );
2706
2707
0
    if( result == -1 )
2708
0
    {
2709
0
      libcerror_error_set(
2710
0
       error,
2711
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2712
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2713
0
       "%s: unable to retrieve root directory inode: 2 from file system B-tree.",
2714
0
       function );
2715
2716
0
      result = -1;
2717
0
    }
2718
0
  }
2719
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2720
0
  if( libcthreads_read_write_lock_release_for_write(
2721
0
       internal_volume->read_write_lock,
2722
0
       error ) != 1 )
2723
0
  {
2724
0
    libcerror_error_set(
2725
0
     error,
2726
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2727
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2728
0
     "%s: unable to release read/write lock for writing.",
2729
0
     function );
2730
2731
0
    return( -1 );
2732
0
  }
2733
0
#endif
2734
0
  return( result );
2735
0
}
2736
2737
/* Retrieves the next file entry identifier
2738
 * Returns 1 if successful or -1 on error
2739
 */
2740
int libfsapfs_volume_get_next_file_entry_identifier(
2741
     libfsapfs_volume_t *volume,
2742
     uint64_t *identifier,
2743
     libcerror_error_t **error )
2744
0
{
2745
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2746
0
  static char *function                        = "libfsapfs_volume_get_next_file_entry_identifier";
2747
2748
0
  if( volume == NULL )
2749
0
  {
2750
0
    libcerror_error_set(
2751
0
     error,
2752
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2753
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2754
0
     "%s: invalid volume.",
2755
0
     function );
2756
2757
0
    return( -1 );
2758
0
  }
2759
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
2760
2761
0
  if( identifier == NULL )
2762
0
  {
2763
0
    libcerror_error_set(
2764
0
     error,
2765
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2766
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2767
0
     "%s: invalid identifier.",
2768
0
     function );
2769
2770
0
    return( -1 );
2771
0
  }
2772
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2773
0
  if( libcthreads_read_write_lock_grab_for_read(
2774
0
       internal_volume->read_write_lock,
2775
0
       error ) != 1 )
2776
0
  {
2777
0
    libcerror_error_set(
2778
0
     error,
2779
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2780
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2781
0
     "%s: unable to grab read/write lock for reading.",
2782
0
     function );
2783
2784
0
    return( -1 );
2785
0
  }
2786
0
#endif
2787
0
  *identifier = internal_volume->superblock->next_file_system_object_identifier;
2788
2789
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2790
0
  if( libcthreads_read_write_lock_release_for_read(
2791
0
       internal_volume->read_write_lock,
2792
0
       error ) != 1 )
2793
0
  {
2794
0
    libcerror_error_set(
2795
0
     error,
2796
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2797
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2798
0
     "%s: unable to release read/write lock for reading.",
2799
0
     function );
2800
2801
0
    return( -1 );
2802
0
  }
2803
0
#endif
2804
0
  return( 1 );
2805
0
}
2806
2807
/* Determines the file system
2808
 * Returns 1 if successful or -1 on error
2809
 */
2810
int libfsapfs_internal_volume_get_file_system(
2811
     libfsapfs_internal_volume_t *internal_volume,
2812
     libcerror_error_t **error )
2813
0
{
2814
0
  libfsapfs_file_system_btree_t *file_system_btree         = NULL;
2815
0
  libfsapfs_object_map_descriptor_t *object_map_descriptor = NULL;
2816
0
  static char *function                                    = "libfsapfs_internal_volume_get_file_system";
2817
0
  uint8_t use_case_folding                                 = 0;
2818
0
  int result                                               = 0;
2819
2820
0
  if( internal_volume == NULL )
2821
0
  {
2822
0
    libcerror_error_set(
2823
0
     error,
2824
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2825
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2826
0
     "%s: invalid volume.",
2827
0
     function );
2828
2829
0
    return( -1 );
2830
0
  }
2831
0
  if( internal_volume->superblock == NULL )
2832
0
  {
2833
0
    libcerror_error_set(
2834
0
     error,
2835
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2836
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2837
0
     "%s: invalid volume - missing superblock.",
2838
0
     function );
2839
2840
0
    return( -1 );
2841
0
  }
2842
0
  if( internal_volume->is_locked != 0 )
2843
0
  {
2844
0
    result = libfsapfs_internal_volume_unlock(
2845
0
              internal_volume,
2846
0
              error );
2847
2848
0
    if( result == -1 )
2849
0
    {
2850
0
      libcerror_error_set(
2851
0
       error,
2852
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2853
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2854
0
       "%s: unable to unlock volume.",
2855
0
       function );
2856
2857
0
      goto on_error;
2858
0
    }
2859
0
  }
2860
0
  if( libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
2861
0
       internal_volume->object_map_btree,
2862
0
       internal_volume->file_io_handle,
2863
0
       internal_volume->superblock->file_system_root_object_identifier,
2864
0
       internal_volume->superblock->transaction_identifier,
2865
0
       &object_map_descriptor,
2866
0
       error ) != 1 )
2867
0
  {
2868
0
    if( result == 0 )
2869
0
    {
2870
/* TODO check if this fails on a T2 encrypted image */
2871
0
      libcerror_error_set(
2872
0
       error,
2873
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2874
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2875
0
       "%s: unable to unlock volume.",
2876
0
       function );
2877
0
    }
2878
0
    else
2879
0
    {
2880
0
      libcerror_error_set(
2881
0
       error,
2882
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2883
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2884
0
       "%s: unable to retrieve object map descriptor for file system root object identifier: %" PRIu64 ".",
2885
0
       function,
2886
0
       internal_volume->superblock->file_system_root_object_identifier );
2887
0
    }
2888
0
    goto on_error;
2889
0
  }
2890
0
  if( object_map_descriptor == NULL )
2891
0
  {
2892
0
    libcerror_error_set(
2893
0
     error,
2894
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2895
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2896
0
     "%s: invalid object map descriptor.",
2897
0
     function );
2898
2899
0
    goto on_error;
2900
0
  }
2901
0
  if( ( internal_volume->superblock->incompatible_features_flags & 0x00000000000000001ULL ) != 0 )
2902
0
  {
2903
0
    use_case_folding = 1;
2904
0
  }
2905
0
  if( libfsapfs_file_system_btree_initialize(
2906
0
       &file_system_btree,
2907
0
       internal_volume->io_handle,
2908
0
       internal_volume->encryption_context,
2909
0
       internal_volume->file_system_data_block_vector,
2910
0
       internal_volume->object_map_btree,
2911
0
       object_map_descriptor->physical_address,
2912
0
       use_case_folding,
2913
0
       error ) != 1 )
2914
0
  {
2915
0
    libcerror_error_set(
2916
0
     error,
2917
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2918
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2919
0
     "%s: unable to create file system B-tree.",
2920
0
     function );
2921
2922
0
    goto on_error;
2923
0
  }
2924
0
  if( libfsapfs_file_system_initialize(
2925
0
       &( internal_volume->file_system ),
2926
0
       internal_volume->io_handle,
2927
0
       internal_volume->encryption_context,
2928
0
       file_system_btree,
2929
0
       error ) != 1 )
2930
0
  {
2931
0
    libcerror_error_set(
2932
0
     error,
2933
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2934
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2935
0
     "%s: unable to create file system.",
2936
0
     function );
2937
2938
0
    goto on_error;
2939
0
  }
2940
0
  if( libfsapfs_object_map_descriptor_free(
2941
0
       &object_map_descriptor,
2942
0
       error ) != 1 )
2943
0
  {
2944
0
    libcerror_error_set(
2945
0
     error,
2946
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2947
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2948
0
     "%s: unable to free object map descriptor.",
2949
0
     function );
2950
2951
0
    goto on_error;
2952
0
  }
2953
0
  return( 1 );
2954
2955
0
on_error:
2956
0
  if( object_map_descriptor != NULL )
2957
0
  {
2958
0
    libfsapfs_object_map_descriptor_free(
2959
0
     &object_map_descriptor,
2960
0
     NULL );
2961
0
  }
2962
0
  if( file_system_btree != NULL )
2963
0
  {
2964
0
    libfsapfs_file_system_btree_free(
2965
0
     &file_system_btree,
2966
0
     NULL );
2967
0
  }
2968
0
  if( internal_volume->file_system != NULL )
2969
0
  {
2970
0
    libfsapfs_file_system_free(
2971
0
     &( internal_volume->file_system ),
2972
0
     NULL );
2973
0
  }
2974
0
  return( -1 );
2975
0
}
2976
2977
/* Retrieves the file entry for a specific identifier
2978
 * Returns 1 if successful, 0 if not available or -1 on error
2979
 */
2980
int libfsapfs_volume_get_file_entry_by_identifier(
2981
     libfsapfs_volume_t *volume,
2982
     uint64_t identifier,
2983
     libfsapfs_file_entry_t **file_entry,
2984
     libcerror_error_t **error )
2985
0
{
2986
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
2987
0
  static char *function                        = "libfsapfs_volume_get_file_entry_by_identifier";
2988
0
  int result                                   = 1;
2989
2990
0
  if( volume == NULL )
2991
0
  {
2992
0
    libcerror_error_set(
2993
0
     error,
2994
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2995
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2996
0
     "%s: invalid volume.",
2997
0
     function );
2998
2999
0
    return( -1 );
3000
0
  }
3001
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3002
3003
0
  if( internal_volume->superblock == NULL )
3004
0
  {
3005
0
    libcerror_error_set(
3006
0
     error,
3007
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3008
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3009
0
     "%s: invalid volume - missing superblock.",
3010
0
     function );
3011
3012
0
    return( -1 );
3013
0
  }
3014
0
  if( internal_volume->is_locked != 0 )
3015
0
  {
3016
0
    libcerror_error_set(
3017
0
     error,
3018
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3019
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3020
0
     "%s: invalid volume - volume is locked.",
3021
0
     function );
3022
3023
0
    return( -1 );
3024
0
  }
3025
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3026
0
  if( libcthreads_read_write_lock_grab_for_write(
3027
0
       internal_volume->read_write_lock,
3028
0
       error ) != 1 )
3029
0
  {
3030
0
    libcerror_error_set(
3031
0
     error,
3032
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3033
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3034
0
     "%s: unable to grab read/write lock for writing.",
3035
0
     function );
3036
3037
0
    return( -1 );
3038
0
  }
3039
0
#endif
3040
0
  if( internal_volume->file_system == NULL )
3041
0
  {
3042
0
    if( libfsapfs_internal_volume_get_file_system(
3043
0
         internal_volume,
3044
0
         error ) != 1 )
3045
0
    {
3046
0
      libcerror_error_set(
3047
0
       error,
3048
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3049
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3050
0
       "%s: unable to determine file system.",
3051
0
       function );
3052
3053
0
      result = -1;
3054
0
    }
3055
0
  }
3056
0
  if( result != -1 )
3057
0
  {
3058
0
    result = libfsapfs_file_system_get_file_entry_by_identifier(
3059
0
              internal_volume->file_system,
3060
0
              internal_volume->file_io_handle,
3061
0
              identifier,
3062
0
              internal_volume->superblock->transaction_identifier,
3063
0
              file_entry,
3064
0
              error );
3065
3066
0
    if( result == -1 )
3067
0
    {
3068
0
      libcerror_error_set(
3069
0
       error,
3070
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3071
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3072
0
       "%s: unable to retrieve inode: %" PRIu64 " from file system B-tree.",
3073
0
       function,
3074
0
       identifier );
3075
3076
0
      result = -1;
3077
0
    }
3078
0
  }
3079
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3080
0
  if( libcthreads_read_write_lock_release_for_write(
3081
0
       internal_volume->read_write_lock,
3082
0
       error ) != 1 )
3083
0
  {
3084
0
    libcerror_error_set(
3085
0
     error,
3086
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3087
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3088
0
     "%s: unable to release read/write lock for writing.",
3089
0
     function );
3090
3091
0
    return( -1 );
3092
0
  }
3093
0
#endif
3094
0
  return( result );
3095
0
}
3096
3097
/* Retrieves the file entry for an UTF-8 encoded path
3098
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3099
 */
3100
int libfsapfs_volume_get_file_entry_by_utf8_path(
3101
     libfsapfs_volume_t *volume,
3102
     const uint8_t *utf8_string,
3103
     size_t utf8_string_length,
3104
     libfsapfs_file_entry_t **file_entry,
3105
     libcerror_error_t **error )
3106
0
{
3107
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
3108
0
  static char *function                        = "libfsapfs_volume_get_file_entry_by_utf8_path";
3109
0
  int result                                   = 1;
3110
3111
0
  if( volume == NULL )
3112
0
  {
3113
0
    libcerror_error_set(
3114
0
     error,
3115
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3116
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3117
0
     "%s: invalid volume.",
3118
0
     function );
3119
3120
0
    return( -1 );
3121
0
  }
3122
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3123
3124
0
  if( internal_volume->superblock == NULL )
3125
0
  {
3126
0
    libcerror_error_set(
3127
0
     error,
3128
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3129
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3130
0
     "%s: invalid volume - missing superblock.",
3131
0
     function );
3132
3133
0
    return( -1 );
3134
0
  }
3135
0
  if( internal_volume->is_locked != 0 )
3136
0
  {
3137
0
    libcerror_error_set(
3138
0
     error,
3139
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3140
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3141
0
     "%s: invalid volume - volume is locked.",
3142
0
     function );
3143
3144
0
    return( -1 );
3145
0
  }
3146
0
  if( file_entry == NULL )
3147
0
  {
3148
0
    libcerror_error_set(
3149
0
     error,
3150
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3151
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3152
0
     "%s: invalid file entry.",
3153
0
     function );
3154
3155
0
    return( -1 );
3156
0
  }
3157
0
  if( *file_entry != NULL )
3158
0
  {
3159
0
    libcerror_error_set(
3160
0
     error,
3161
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3162
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3163
0
     "%s: invalid file entry value already set.",
3164
0
     function );
3165
3166
0
    return( -1 );
3167
0
  }
3168
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3169
0
  if( libcthreads_read_write_lock_grab_for_write(
3170
0
       internal_volume->read_write_lock,
3171
0
       error ) != 1 )
3172
0
  {
3173
0
    libcerror_error_set(
3174
0
     error,
3175
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3176
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3177
0
     "%s: unable to grab read/write lock for writing.",
3178
0
     function );
3179
3180
0
    return( -1 );
3181
0
  }
3182
0
#endif
3183
0
  if( internal_volume->file_system == NULL )
3184
0
  {
3185
0
    if( libfsapfs_internal_volume_get_file_system(
3186
0
         internal_volume,
3187
0
         error ) != 1 )
3188
0
    {
3189
0
      libcerror_error_set(
3190
0
       error,
3191
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3192
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3193
0
       "%s: unable to determine file system.",
3194
0
       function );
3195
3196
0
      result = -1;
3197
0
    }
3198
0
  }
3199
0
  if( result != -1 )
3200
0
  {
3201
0
    result = libfsapfs_file_system_get_file_entry_by_utf8_path(
3202
0
              internal_volume->file_system,
3203
0
              internal_volume->file_io_handle,
3204
0
              utf8_string,
3205
0
              utf8_string_length,
3206
0
              internal_volume->superblock->transaction_identifier,
3207
0
              file_entry,
3208
0
              error );
3209
3210
0
    if( result == -1 )
3211
0
    {
3212
0
      libcerror_error_set(
3213
0
       error,
3214
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3215
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3216
0
       "%s: unable to retrieve file entry from file system by UTF-8 path.",
3217
0
       function );
3218
3219
0
      result = -1;
3220
0
    }
3221
0
  }
3222
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3223
0
  if( libcthreads_read_write_lock_release_for_write(
3224
0
       internal_volume->read_write_lock,
3225
0
       error ) != 1 )
3226
0
  {
3227
0
    libcerror_error_set(
3228
0
     error,
3229
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3230
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3231
0
     "%s: unable to release read/write lock for writing.",
3232
0
     function );
3233
3234
0
    return( -1 );
3235
0
  }
3236
0
#endif
3237
0
  return( result );
3238
0
}
3239
3240
/* Retrieves the file entry for an UTF-16 encoded path
3241
 * Returns 1 if successful, 0 if no such file entry or -1 on error
3242
 */
3243
int libfsapfs_volume_get_file_entry_by_utf16_path(
3244
     libfsapfs_volume_t *volume,
3245
     const uint16_t *utf16_string,
3246
     size_t utf16_string_length,
3247
     libfsapfs_file_entry_t **file_entry,
3248
     libcerror_error_t **error )
3249
0
{
3250
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
3251
0
  static char *function                        = "libfsapfs_volume_get_file_entry_by_utf16_path";
3252
0
  int result                                   = 1;
3253
3254
0
  if( volume == NULL )
3255
0
  {
3256
0
    libcerror_error_set(
3257
0
     error,
3258
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3259
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3260
0
     "%s: invalid volume.",
3261
0
     function );
3262
3263
0
    return( -1 );
3264
0
  }
3265
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3266
3267
0
  if( internal_volume->superblock == NULL )
3268
0
  {
3269
0
    libcerror_error_set(
3270
0
     error,
3271
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3272
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3273
0
     "%s: invalid volume - missing superblock.",
3274
0
     function );
3275
3276
0
    return( -1 );
3277
0
  }
3278
0
  if( internal_volume->is_locked != 0 )
3279
0
  {
3280
0
    libcerror_error_set(
3281
0
     error,
3282
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3283
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3284
0
     "%s: invalid volume - volume is locked.",
3285
0
     function );
3286
3287
0
    return( -1 );
3288
0
  }
3289
0
  if( file_entry == NULL )
3290
0
  {
3291
0
    libcerror_error_set(
3292
0
     error,
3293
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3294
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3295
0
     "%s: invalid file entry.",
3296
0
     function );
3297
3298
0
    return( -1 );
3299
0
  }
3300
0
  if( *file_entry != NULL )
3301
0
  {
3302
0
    libcerror_error_set(
3303
0
     error,
3304
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3305
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3306
0
     "%s: invalid file entry value already set.",
3307
0
     function );
3308
3309
0
    return( -1 );
3310
0
  }
3311
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3312
0
  if( libcthreads_read_write_lock_grab_for_write(
3313
0
       internal_volume->read_write_lock,
3314
0
       error ) != 1 )
3315
0
  {
3316
0
    libcerror_error_set(
3317
0
     error,
3318
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3319
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3320
0
     "%s: unable to grab read/write lock for writing.",
3321
0
     function );
3322
3323
0
    return( -1 );
3324
0
  }
3325
0
#endif
3326
0
  if( internal_volume->file_system == NULL )
3327
0
  {
3328
0
    if( libfsapfs_internal_volume_get_file_system(
3329
0
         internal_volume,
3330
0
         error ) != 1 )
3331
0
    {
3332
0
      libcerror_error_set(
3333
0
       error,
3334
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3335
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3336
0
       "%s: unable to determine file system.",
3337
0
       function );
3338
3339
0
      result = -1;
3340
0
    }
3341
0
  }
3342
0
  if( result != -1 )
3343
0
  {
3344
0
    result = libfsapfs_file_system_get_file_entry_by_utf16_path(
3345
0
              internal_volume->file_system,
3346
0
              internal_volume->file_io_handle,
3347
0
              utf16_string,
3348
0
              utf16_string_length,
3349
0
              internal_volume->superblock->transaction_identifier,
3350
0
              file_entry,
3351
0
              error );
3352
3353
0
    if( result == -1 )
3354
0
    {
3355
0
      libcerror_error_set(
3356
0
       error,
3357
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3358
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3359
0
       "%s: unable to retrieve file entry from file system by UTF-16 path.",
3360
0
       function );
3361
3362
0
      result = -1;
3363
0
    }
3364
0
  }
3365
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3366
0
  if( libcthreads_read_write_lock_release_for_write(
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 release read/write lock for writing.",
3375
0
     function );
3376
3377
0
    return( -1 );
3378
0
  }
3379
0
#endif
3380
0
  return( result );
3381
0
}
3382
3383
/* Retrieves the number of snapshots
3384
 * Returns 1 if successful or -1 on error
3385
 */
3386
int libfsapfs_volume_get_number_of_snapshots(
3387
     libfsapfs_volume_t *volume,
3388
     int *number_of_snapshots,
3389
     libcerror_error_t **error )
3390
0
{
3391
0
  libfsapfs_internal_volume_t *internal_volume = NULL;
3392
0
  static char *function                        = "libfsapfs_volume_get_number_of_snapshots";
3393
0
  int result                                   = 1;
3394
3395
0
  if( volume == NULL )
3396
0
  {
3397
0
    libcerror_error_set(
3398
0
     error,
3399
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3400
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3401
0
     "%s: invalid volume.",
3402
0
     function );
3403
3404
0
    return( -1 );
3405
0
  }
3406
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3407
3408
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3409
0
  if( libcthreads_read_write_lock_grab_for_read(
3410
0
       internal_volume->read_write_lock,
3411
0
       error ) != 1 )
3412
0
  {
3413
0
    libcerror_error_set(
3414
0
     error,
3415
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3416
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3417
0
     "%s: unable to grab read/write lock for reading.",
3418
0
     function );
3419
3420
0
    return( -1 );
3421
0
  }
3422
0
#endif
3423
0
  if( libcdata_array_get_number_of_entries(
3424
0
       internal_volume->snapshots,
3425
0
       number_of_snapshots,
3426
0
       error ) != 1 )
3427
0
  {
3428
0
    libcerror_error_set(
3429
0
     error,
3430
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3431
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3432
0
     "%s: unable to retrieve number of entries from snapshots array.",
3433
0
     function );
3434
3435
0
    result = -1;
3436
0
  }
3437
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3438
0
  if( libcthreads_read_write_lock_release_for_read(
3439
0
       internal_volume->read_write_lock,
3440
0
       error ) != 1 )
3441
0
  {
3442
0
    libcerror_error_set(
3443
0
     error,
3444
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3445
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3446
0
     "%s: unable to release read/write lock for reading.",
3447
0
     function );
3448
3449
0
    return( -1 );
3450
0
  }
3451
0
#endif
3452
0
  return( result );
3453
0
}
3454
3455
/* Retrieves a specific of snapshot
3456
 * The snapshot reference must be freed after use with libfsapfs_snapshot_free
3457
 * Returns 1 if successful or -1 on error
3458
 */
3459
int libfsapfs_volume_get_snapshot_by_index(
3460
     libfsapfs_volume_t *volume,
3461
     int snapshot_index,
3462
     libfsapfs_snapshot_t **snapshot,
3463
     libcerror_error_t **error )
3464
0
{
3465
0
  libfsapfs_internal_volume_t *internal_volume     = NULL;
3466
0
  libfsapfs_snapshot_metadata_t *snapshot_metadata = NULL;
3467
0
  static char *function                            = "libfsapfs_volume_get_snapshot_by_index";
3468
0
  off64_t file_offset                              = 0;
3469
3470
0
  if( volume == NULL )
3471
0
  {
3472
0
    libcerror_error_set(
3473
0
     error,
3474
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3475
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3476
0
     "%s: invalid volume.",
3477
0
     function );
3478
3479
0
    return( -1 );
3480
0
  }
3481
0
  internal_volume = (libfsapfs_internal_volume_t *) volume;
3482
3483
0
  if( snapshot == NULL )
3484
0
  {
3485
0
    libcerror_error_set(
3486
0
     error,
3487
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3488
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3489
0
     "%s: invalid snapshot.",
3490
0
     function );
3491
3492
0
    return( -1 );
3493
0
  }
3494
0
  if( *snapshot != NULL )
3495
0
  {
3496
0
    libcerror_error_set(
3497
0
     error,
3498
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3499
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3500
0
     "%s: invalid snapshot value already set.",
3501
0
     function );
3502
3503
0
    return( -1 );
3504
0
  }
3505
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3506
0
  if( libcthreads_read_write_lock_grab_for_read(
3507
0
       internal_volume->read_write_lock,
3508
0
       error ) != 1 )
3509
0
  {
3510
0
    libcerror_error_set(
3511
0
     error,
3512
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3513
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3514
0
     "%s: unable to grab read/write lock for reading.",
3515
0
     function );
3516
3517
0
    return( -1 );
3518
0
  }
3519
0
#endif
3520
0
  if( libcdata_array_get_entry_by_index(
3521
0
       internal_volume->snapshots,
3522
0
       snapshot_index,
3523
0
       (intptr_t **) &snapshot_metadata,
3524
0
       error ) != 1 )
3525
0
  {
3526
0
    libcerror_error_set(
3527
0
     error,
3528
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3529
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3530
0
     "%s: unable to retrieve snapshot metadata: %d.",
3531
0
     function,
3532
0
     snapshot_index );
3533
3534
0
    return( -1 );
3535
0
  }
3536
0
  if( snapshot_metadata == NULL )
3537
0
  {
3538
0
    libcerror_error_set(
3539
0
     error,
3540
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3541
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3542
0
     "%s: invalid snapshot metadata: %d.",
3543
0
     function,
3544
0
     snapshot_index );
3545
3546
0
    goto on_error;
3547
0
  }
3548
0
  if( libfsapfs_snapshot_initialize(
3549
0
       snapshot,
3550
0
       internal_volume->io_handle,
3551
0
       internal_volume->file_io_handle,
3552
0
       snapshot_metadata,
3553
0
       error ) != 1 )
3554
0
  {
3555
0
    libcerror_error_set(
3556
0
     error,
3557
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3558
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3559
0
     "%s: unable to create snapshot.",
3560
0
     function );
3561
3562
0
    goto on_error;
3563
0
  }
3564
0
  file_offset = (off64_t) ( snapshot_metadata->volume_superblock_block_number * internal_volume->io_handle->block_size );
3565
3566
0
  if( libfsapfs_internal_snapshot_open_read(
3567
0
       (libfsapfs_internal_snapshot_t *) *snapshot,
3568
0
       internal_volume->file_io_handle,
3569
0
       file_offset,
3570
0
       error ) != 1 )
3571
0
  {
3572
0
    libcerror_error_set(
3573
0
     error,
3574
0
     LIBCERROR_ERROR_DOMAIN_IO,
3575
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
3576
0
     "%s: unable to open snapshot: %d.",
3577
0
     function,
3578
0
     snapshot_index );
3579
3580
0
    goto on_error;
3581
0
  }
3582
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3583
0
  if( libcthreads_read_write_lock_release_for_read(
3584
0
       internal_volume->read_write_lock,
3585
0
       error ) != 1 )
3586
0
  {
3587
0
    libcerror_error_set(
3588
0
     error,
3589
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3590
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3591
0
     "%s: unable to release read/write lock for reading.",
3592
0
     function );
3593
3594
0
    return( -1 );
3595
0
  }
3596
0
#endif
3597
0
  return( 1 );
3598
3599
0
on_error:
3600
0
  if( *snapshot != NULL )
3601
0
  {
3602
0
    libfsapfs_snapshot_free(
3603
0
     snapshot,
3604
0
     NULL );
3605
0
  }
3606
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3607
0
  libcthreads_read_write_lock_release_for_read(
3608
0
   internal_volume->read_write_lock,
3609
   NULL );
3610
0
#endif
3611
0
  return( -1 );
3612
0
}
3613