Coverage Report

Created: 2023-06-07 06:53

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