Coverage Report

Created: 2025-06-13 07:21

/src/libfsapfs/libfsapfs/libfsapfs_container.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Container functions
3
 *
4
 * Copyright (C) 2018-2024, 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_checkpoint_map.h"
29
#include "libfsapfs_container.h"
30
#include "libfsapfs_container_data_handle.h"
31
#include "libfsapfs_container_key_bag.h"
32
#include "libfsapfs_container_reaper.h"
33
#include "libfsapfs_space_manager.h"
34
#include "libfsapfs_container_superblock.h"
35
#include "libfsapfs_debug.h"
36
#include "libfsapfs_definitions.h"
37
#include "libfsapfs_fusion_middle_tree.h"
38
#include "libfsapfs_io_handle.h"
39
#include "libfsapfs_libbfio.h"
40
#include "libfsapfs_libcerror.h"
41
#include "libfsapfs_libcnotify.h"
42
#include "libfsapfs_libcthreads.h"
43
#include "libfsapfs_libfdata.h"
44
#include "libfsapfs_object.h"
45
#include "libfsapfs_object_map.h"
46
#include "libfsapfs_object_map_btree.h"
47
#include "libfsapfs_object_map_descriptor.h"
48
#include "libfsapfs_volume.h"
49
50
/* Creates a container
51
 * Make sure the value container is referencing, is set to NULL
52
 * Returns 1 if successful or -1 on error
53
 */
54
int libfsapfs_container_initialize(
55
     libfsapfs_container_t **container,
56
     libcerror_error_t **error )
57
1.44k
{
58
1.44k
  libfsapfs_internal_container_t *internal_container = NULL;
59
1.44k
  static char *function                              = "libfsapfs_container_initialize";
60
61
1.44k
  if( container == NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
66
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
67
0
     "%s: invalid container.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
1.44k
  if( *container != NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
77
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
78
0
     "%s: invalid container value already set.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
1.44k
  internal_container = memory_allocate_structure(
84
1.44k
                        libfsapfs_internal_container_t );
85
86
1.44k
  if( internal_container == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
92
0
     "%s: unable to create container.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
1.44k
  if( memory_set(
98
1.44k
       internal_container,
99
1.44k
       0,
100
1.44k
       sizeof( libfsapfs_internal_container_t ) ) == NULL )
101
0
  {
102
0
    libcerror_error_set(
103
0
     error,
104
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
105
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
106
0
     "%s: unable to clear container.",
107
0
     function );
108
109
0
    goto on_error;
110
0
  }
111
1.44k
  if( libfsapfs_io_handle_initialize(
112
1.44k
       &( internal_container->io_handle ),
113
1.44k
       error ) != 1 )
114
0
  {
115
0
    libcerror_error_set(
116
0
     error,
117
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
118
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
119
0
     "%s: unable to create IO handle.",
120
0
     function );
121
122
0
    goto on_error;
123
0
  }
124
1.44k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
125
1.44k
  if( libcthreads_read_write_lock_initialize(
126
1.44k
       &( internal_container->read_write_lock ),
127
1.44k
       error ) != 1 )
128
0
  {
129
0
    libcerror_error_set(
130
0
     error,
131
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
132
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
133
0
     "%s: unable to initialize read/write lock.",
134
0
     function );
135
136
0
    goto on_error;
137
0
  }
138
1.44k
#endif
139
1.44k
  *container = (libfsapfs_container_t *) internal_container;
140
141
1.44k
  return( 1 );
142
143
0
on_error:
144
0
  if( internal_container != NULL )
145
0
  {
146
0
    memory_free(
147
0
     internal_container );
148
0
  }
149
0
  return( -1 );
150
1.44k
}
151
152
/* Frees a container
153
 * Returns 1 if successful or -1 on error
154
 */
155
int libfsapfs_container_free(
156
     libfsapfs_container_t **container,
157
     libcerror_error_t **error )
158
1.44k
{
159
1.44k
  libfsapfs_internal_container_t *internal_container = NULL;
160
1.44k
  static char *function                              = "libfsapfs_container_free";
161
1.44k
  int result                                         = 1;
162
163
1.44k
  if( container == NULL )
164
0
  {
165
0
    libcerror_error_set(
166
0
     error,
167
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
168
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
169
0
     "%s: invalid container.",
170
0
     function );
171
172
0
    return( -1 );
173
0
  }
174
1.44k
  if( *container != NULL )
175
1.44k
  {
176
1.44k
    internal_container = (libfsapfs_internal_container_t *) *container;
177
178
1.44k
    if( internal_container->file_io_handle != NULL )
179
0
    {
180
0
      if( libfsapfs_container_close(
181
0
           *container,
182
0
           error ) != 0 )
183
0
      {
184
0
        libcerror_error_set(
185
0
         error,
186
0
         LIBCERROR_ERROR_DOMAIN_IO,
187
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
188
0
         "%s: unable to close container.",
189
0
         function );
190
191
0
        result = -1;
192
0
      }
193
0
    }
194
1.44k
    *container = NULL;
195
196
1.44k
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
197
1.44k
    if( libcthreads_read_write_lock_free(
198
1.44k
         &( internal_container->read_write_lock ),
199
1.44k
         error ) != 1 )
200
0
    {
201
0
      libcerror_error_set(
202
0
       error,
203
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
204
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
205
0
       "%s: unable to free read/write lock.",
206
0
       function );
207
208
0
      result = -1;
209
0
    }
210
1.44k
#endif
211
1.44k
    if( libfsapfs_io_handle_free(
212
1.44k
         &( internal_container->io_handle ),
213
1.44k
         error ) != 1 )
214
0
    {
215
0
      libcerror_error_set(
216
0
       error,
217
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
218
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
219
0
       "%s: unable to free IO handle.",
220
0
       function );
221
222
0
      result = -1;
223
0
    }
224
1.44k
    memory_free(
225
1.44k
     internal_container );
226
1.44k
  }
227
1.44k
  return( result );
228
1.44k
}
229
230
/* Signals the container to abort its current activity
231
 * Returns 1 if successful or -1 on error
232
 */
233
int libfsapfs_container_signal_abort(
234
     libfsapfs_container_t *container,
235
     libcerror_error_t **error )
236
0
{
237
0
  libfsapfs_internal_container_t *internal_container = NULL;
238
0
  static char *function                              = "libfsapfs_container_signal_abort";
239
240
0
  if( container == NULL )
241
0
  {
242
0
    libcerror_error_set(
243
0
     error,
244
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
245
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
246
0
     "%s: invalid container.",
247
0
     function );
248
249
0
    return( -1 );
250
0
  }
251
0
  internal_container = (libfsapfs_internal_container_t *) container;
252
253
0
  if( internal_container->io_handle == NULL )
254
0
  {
255
0
    libcerror_error_set(
256
0
     error,
257
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
258
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
259
0
     "%s: invalid container - missing IO handle.",
260
0
     function );
261
262
0
    return( -1 );
263
0
  }
264
0
  internal_container->io_handle->abort = 1;
265
266
0
  return( 1 );
267
0
}
268
269
/* Opens a container
270
 * Returns 1 if successful or -1 on error
271
 */
272
int libfsapfs_container_open(
273
     libfsapfs_container_t *container,
274
     const char *filename,
275
     int access_flags,
276
     libcerror_error_t **error )
277
0
{
278
0
  libbfio_handle_t *file_io_handle                   = NULL;
279
0
  libfsapfs_internal_container_t *internal_container = NULL;
280
0
  static char *function                              = "libfsapfs_container_open";
281
0
  size_t filename_length                             = 0;
282
283
0
  if( container == NULL )
284
0
  {
285
0
    libcerror_error_set(
286
0
     error,
287
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
288
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
289
0
     "%s: invalid container.",
290
0
     function );
291
292
0
    return( -1 );
293
0
  }
294
0
  internal_container = (libfsapfs_internal_container_t *) container;
295
296
0
  if( filename == NULL )
297
0
  {
298
0
    libcerror_error_set(
299
0
     error,
300
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
301
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
302
0
     "%s: invalid filename.",
303
0
     function );
304
305
0
    return( -1 );
306
0
  }
307
0
  if( ( ( access_flags & LIBFSAPFS_ACCESS_FLAG_READ ) == 0 )
308
0
   && ( ( access_flags & LIBFSAPFS_ACCESS_FLAG_WRITE ) == 0 ) )
309
0
  {
310
0
    libcerror_error_set(
311
0
     error,
312
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
313
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
314
0
     "%s: unsupported access flags.",
315
0
     function );
316
317
0
    return( -1 );
318
0
  }
319
0
  if( ( access_flags & LIBFSAPFS_ACCESS_FLAG_WRITE ) != 0 )
320
0
  {
321
0
    libcerror_error_set(
322
0
     error,
323
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
324
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
325
0
     "%s: write access currently not supported.",
326
0
     function );
327
328
0
    return( -1 );
329
0
  }
330
0
  if( libbfio_file_initialize(
331
0
       &file_io_handle,
332
0
       error ) != 1 )
333
0
  {
334
0
    libcerror_error_set(
335
0
     error,
336
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
337
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
338
0
     "%s: unable to create file IO handle.",
339
0
     function );
340
341
0
    goto on_error;
342
0
  }
343
#if defined( HAVE_DEBUG_OUTPUT )
344
  if( libbfio_handle_set_track_offsets_read(
345
       file_io_handle,
346
       1,
347
       error ) != 1 )
348
  {
349
                libcerror_error_set(
350
                 error,
351
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
352
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
353
                 "%s: unable to set track offsets read in file IO handle.",
354
                 function );
355
356
    goto on_error;
357
  }
358
#endif
359
0
  filename_length = narrow_string_length(
360
0
                     filename );
361
362
0
  if( libbfio_file_set_name(
363
0
       file_io_handle,
364
0
       filename,
365
0
       filename_length + 1,
366
0
       error ) != 1 )
367
0
  {
368
0
                libcerror_error_set(
369
0
                 error,
370
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
371
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
372
0
                 "%s: unable to set filename in file IO handle.",
373
0
                 function );
374
375
0
    goto on_error;
376
0
  }
377
0
  if( libfsapfs_container_open_file_io_handle(
378
0
       container,
379
0
       file_io_handle,
380
0
       access_flags,
381
0
       error ) != 1 )
382
0
  {
383
0
    libcerror_error_set(
384
0
     error,
385
0
     LIBCERROR_ERROR_DOMAIN_IO,
386
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
387
0
     "%s: unable to open container: %s.",
388
0
     function,
389
0
     filename );
390
391
0
    goto on_error;
392
0
  }
393
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
394
0
  if( libcthreads_read_write_lock_grab_for_write(
395
0
       internal_container->read_write_lock,
396
0
       error ) != 1 )
397
0
  {
398
0
    libcerror_error_set(
399
0
     error,
400
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
401
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
402
0
     "%s: unable to grab read/write lock for writing.",
403
0
     function );
404
405
0
    goto on_error;
406
0
  }
407
0
#endif
408
0
  internal_container->file_io_handle_created_in_library = 1;
409
410
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
411
0
  if( libcthreads_read_write_lock_release_for_write(
412
0
       internal_container->read_write_lock,
413
0
       error ) != 1 )
414
0
  {
415
0
    libcerror_error_set(
416
0
     error,
417
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
418
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
419
0
     "%s: unable to release read/write lock for writing.",
420
0
     function );
421
422
0
    internal_container->file_io_handle_created_in_library = 0;
423
424
0
    goto on_error;
425
0
  }
426
0
#endif
427
0
  return( 1 );
428
429
0
on_error:
430
0
  if( file_io_handle != NULL )
431
0
  {
432
0
    libbfio_handle_free(
433
0
     &file_io_handle,
434
0
     NULL );
435
0
  }
436
0
        return( -1 );
437
0
}
438
439
#if defined( HAVE_WIDE_CHARACTER_TYPE )
440
441
/* Opens a container
442
 * Returns 1 if successful or -1 on error
443
 */
444
int libfsapfs_container_open_wide(
445
     libfsapfs_container_t *container,
446
     const wchar_t *filename,
447
     int access_flags,
448
     libcerror_error_t **error )
449
{
450
  libbfio_handle_t *file_io_handle                   = NULL;
451
  libfsapfs_internal_container_t *internal_container = NULL;
452
  static char *function                              = "libfsapfs_container_open_wide";
453
  size_t filename_length                             = 0;
454
455
  if( container == NULL )
456
  {
457
    libcerror_error_set(
458
     error,
459
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
460
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
461
     "%s: invalid container.",
462
     function );
463
464
    return( -1 );
465
  }
466
  internal_container = (libfsapfs_internal_container_t *) container;
467
468
  if( filename == NULL )
469
  {
470
    libcerror_error_set(
471
     error,
472
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
473
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
474
     "%s: invalid filename.",
475
     function );
476
477
    return( -1 );
478
  }
479
  if( ( ( access_flags & LIBFSAPFS_ACCESS_FLAG_READ ) == 0 )
480
   && ( ( access_flags & LIBFSAPFS_ACCESS_FLAG_WRITE ) == 0 ) )
481
  {
482
    libcerror_error_set(
483
     error,
484
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
485
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
486
     "%s: unsupported access flags.",
487
     function );
488
489
    return( -1 );
490
  }
491
  if( ( access_flags & LIBFSAPFS_ACCESS_FLAG_WRITE ) != 0 )
492
  {
493
    libcerror_error_set(
494
     error,
495
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
496
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
497
     "%s: write access currently not supported.",
498
     function );
499
500
    return( -1 );
501
  }
502
  if( libbfio_file_initialize(
503
       &file_io_handle,
504
       error ) != 1 )
505
  {
506
    libcerror_error_set(
507
     error,
508
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
509
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
510
     "%s: unable to create file IO handle.",
511
     function );
512
513
    goto on_error;
514
  }
515
#if defined( HAVE_DEBUG_OUTPUT )
516
  if( libbfio_handle_set_track_offsets_read(
517
       file_io_handle,
518
       1,
519
       error ) != 1 )
520
  {
521
                libcerror_error_set(
522
                 error,
523
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
524
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
525
                 "%s: unable to set track offsets read in file IO handle.",
526
                 function );
527
528
    goto on_error;
529
  }
530
#endif
531
  filename_length = wide_string_length(
532
                     filename );
533
534
  if( libbfio_file_set_name_wide(
535
       file_io_handle,
536
       filename,
537
       filename_length + 1,
538
       error ) != 1 )
539
  {
540
                libcerror_error_set(
541
                 error,
542
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
543
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
544
                 "%s: unable to set filename in file IO handle.",
545
                 function );
546
547
    goto on_error;
548
  }
549
  if( libfsapfs_container_open_file_io_handle(
550
       container,
551
       file_io_handle,
552
       access_flags,
553
       error ) != 1 )
554
  {
555
    libcerror_error_set(
556
     error,
557
     LIBCERROR_ERROR_DOMAIN_IO,
558
     LIBCERROR_IO_ERROR_OPEN_FAILED,
559
     "%s: unable to open container: %ls.",
560
     function,
561
     filename );
562
563
    goto on_error;
564
  }
565
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
566
  if( libcthreads_read_write_lock_grab_for_write(
567
       internal_container->read_write_lock,
568
       error ) != 1 )
569
  {
570
    libcerror_error_set(
571
     error,
572
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
573
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
574
     "%s: unable to grab read/write lock for writing.",
575
     function );
576
577
    goto on_error;
578
  }
579
#endif
580
  internal_container->file_io_handle_created_in_library = 1;
581
582
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
583
  if( libcthreads_read_write_lock_release_for_write(
584
       internal_container->read_write_lock,
585
       error ) != 1 )
586
  {
587
    libcerror_error_set(
588
     error,
589
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
590
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
591
     "%s: unable to release read/write lock for writing.",
592
     function );
593
594
    internal_container->file_io_handle_created_in_library = 0;
595
596
    goto on_error;
597
  }
598
#endif
599
  return( 1 );
600
601
on_error:
602
  if( file_io_handle != NULL )
603
  {
604
    libbfio_handle_free(
605
     &file_io_handle,
606
     NULL );
607
  }
608
        return( -1 );
609
}
610
611
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
612
613
/* Opens a container using a Basic File IO (bfio) handle
614
 * Returns 1 if successful or -1 on error
615
 */
616
int libfsapfs_container_open_file_io_handle(
617
     libfsapfs_container_t *container,
618
     libbfio_handle_t *file_io_handle,
619
     int access_flags,
620
     libcerror_error_t **error )
621
1.44k
{
622
1.44k
  libfsapfs_internal_container_t *internal_container = NULL;
623
1.44k
  static char *function                              = "libfsapfs_container_open_file_io_handle";
624
1.44k
  int bfio_access_flags                              = 0;
625
1.44k
  int file_io_handle_is_open                         = 0;
626
1.44k
  uint8_t file_io_handle_opened_in_library           = 0;
627
628
1.44k
  if( container == NULL )
629
0
  {
630
0
    libcerror_error_set(
631
0
     error,
632
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
633
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
634
0
     "%s: invalid container.",
635
0
     function );
636
637
0
    return( -1 );
638
0
  }
639
1.44k
  internal_container = (libfsapfs_internal_container_t *) container;
640
641
1.44k
  if( internal_container->file_io_handle != NULL )
642
0
  {
643
0
    libcerror_error_set(
644
0
     error,
645
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
646
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
647
0
     "%s: invalid container - file IO handle already set.",
648
0
     function );
649
650
0
    return( -1 );
651
0
  }
652
1.44k
  if( file_io_handle == NULL )
653
0
  {
654
0
    libcerror_error_set(
655
0
     error,
656
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
657
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
658
0
     "%s: invalid file IO handle.",
659
0
     function );
660
661
0
    return( -1 );
662
0
  }
663
1.44k
  if( ( ( access_flags & LIBFSAPFS_ACCESS_FLAG_READ ) == 0 )
664
1.44k
   && ( ( access_flags & LIBFSAPFS_ACCESS_FLAG_WRITE ) == 0 ) )
665
0
  {
666
0
    libcerror_error_set(
667
0
     error,
668
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
669
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
670
0
     "%s: unsupported access flags.",
671
0
     function );
672
673
0
    return( -1 );
674
0
  }
675
1.44k
  if( ( access_flags & LIBFSAPFS_ACCESS_FLAG_WRITE ) != 0 )
676
0
  {
677
0
    libcerror_error_set(
678
0
     error,
679
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
680
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
681
0
     "%s: write access currently not supported.",
682
0
     function );
683
684
0
    return( -1 );
685
0
  }
686
1.44k
  if( ( access_flags & LIBFSAPFS_ACCESS_FLAG_READ ) != 0 )
687
1.44k
  {
688
1.44k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
689
1.44k
  }
690
1.44k
  file_io_handle_is_open = libbfio_handle_is_open(
691
1.44k
                            file_io_handle,
692
1.44k
                            error );
693
694
1.44k
  if( file_io_handle_is_open == -1 )
695
0
  {
696
0
    libcerror_error_set(
697
0
     error,
698
0
     LIBCERROR_ERROR_DOMAIN_IO,
699
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
700
0
     "%s: unable to open container.",
701
0
     function );
702
703
0
    goto on_error;
704
0
  }
705
1.44k
  else if( file_io_handle_is_open == 0 )
706
1.44k
  {
707
1.44k
    if( libbfio_handle_open(
708
1.44k
         file_io_handle,
709
1.44k
         bfio_access_flags,
710
1.44k
         error ) != 1 )
711
0
    {
712
0
      libcerror_error_set(
713
0
       error,
714
0
       LIBCERROR_ERROR_DOMAIN_IO,
715
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
716
0
       "%s: unable to open file IO handle.",
717
0
       function );
718
719
0
      goto on_error;
720
0
    }
721
1.44k
    file_io_handle_opened_in_library = 1;
722
1.44k
  }
723
1.44k
  if( libfsapfs_internal_container_open_read(
724
1.44k
       internal_container,
725
1.44k
       file_io_handle,
726
1.44k
       0,
727
1.44k
       error ) != 1 )
728
1.38k
  {
729
1.38k
    libcerror_error_set(
730
1.38k
     error,
731
1.38k
     LIBCERROR_ERROR_DOMAIN_IO,
732
1.38k
     LIBCERROR_IO_ERROR_READ_FAILED,
733
1.38k
     "%s: unable to read from file IO handle.",
734
1.38k
     function );
735
736
1.38k
    goto on_error;
737
1.38k
  }
738
51
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
739
51
  if( libcthreads_read_write_lock_grab_for_write(
740
51
       internal_container->read_write_lock,
741
51
       error ) != 1 )
742
0
  {
743
0
    libcerror_error_set(
744
0
     error,
745
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
746
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
747
0
     "%s: unable to grab read/write lock for writing.",
748
0
     function );
749
750
0
    goto on_error;
751
0
  }
752
51
#endif
753
51
  internal_container->file_io_handle                   = file_io_handle;
754
51
  internal_container->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
755
756
51
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
757
51
  if( libcthreads_read_write_lock_release_for_write(
758
51
       internal_container->read_write_lock,
759
51
       error ) != 1 )
760
0
  {
761
0
    libcerror_error_set(
762
0
     error,
763
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
764
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
765
0
     "%s: unable to release read/write lock for writing.",
766
0
     function );
767
768
0
    internal_container->file_io_handle                   = NULL;
769
0
    internal_container->file_io_handle_opened_in_library = 0;
770
771
0
    goto on_error;
772
0
  }
773
51
#endif
774
51
  return( 1 );
775
776
1.38k
on_error:
777
1.38k
  if( file_io_handle_opened_in_library != 0 )
778
1.38k
  {
779
1.38k
    libbfio_handle_close(
780
1.38k
     file_io_handle,
781
1.38k
     error );
782
1.38k
  }
783
1.38k
  return( -1 );
784
51
}
785
786
/* Closes a container
787
 * Returns 0 if successful or -1 on error
788
 */
789
int libfsapfs_container_close(
790
     libfsapfs_container_t *container,
791
     libcerror_error_t **error )
792
51
{
793
51
  libfsapfs_internal_container_t *internal_container = NULL;
794
51
  static char *function                              = "libfsapfs_container_close";
795
51
  int result                                         = 0;
796
797
51
  if( container == NULL )
798
0
  {
799
0
    libcerror_error_set(
800
0
     error,
801
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
802
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
803
0
     "%s: invalid container.",
804
0
     function );
805
806
0
    return( -1 );
807
0
  }
808
51
  internal_container = (libfsapfs_internal_container_t *) container;
809
810
51
  if( internal_container->file_io_handle == NULL )
811
0
  {
812
0
    libcerror_error_set(
813
0
     error,
814
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
815
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
816
0
     "%s: invalid container - missing file IO handle.",
817
0
     function );
818
819
0
    return( -1 );
820
0
  }
821
51
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
822
51
  if( libcthreads_read_write_lock_grab_for_write(
823
51
       internal_container->read_write_lock,
824
51
       error ) != 1 )
825
0
  {
826
0
    libcerror_error_set(
827
0
     error,
828
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
829
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
830
0
     "%s: unable to grab read/write lock for writing.",
831
0
     function );
832
833
0
    return( -1 );
834
0
  }
835
51
#endif
836
#if defined( HAVE_DEBUG_OUTPUT )
837
  if( libcnotify_verbose != 0 )
838
  {
839
    if( internal_container->file_io_handle_created_in_library != 0 )
840
    {
841
      if( libfsapfs_debug_print_read_offsets(
842
           internal_container->file_io_handle,
843
           error ) != 1 )
844
      {
845
        libcerror_error_set(
846
         error,
847
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
848
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
849
         "%s: unable to print the read offsets.",
850
         function );
851
852
        result = -1;
853
      }
854
    }
855
  }
856
#endif
857
51
  if( internal_container->file_io_handle_opened_in_library != 0 )
858
51
  {
859
51
    if( libbfio_handle_close(
860
51
         internal_container->file_io_handle,
861
51
         error ) != 0 )
862
0
    {
863
0
      libcerror_error_set(
864
0
       error,
865
0
       LIBCERROR_ERROR_DOMAIN_IO,
866
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
867
0
       "%s: unable to close file IO handle.",
868
0
       function );
869
870
0
      result = -1;
871
0
    }
872
51
    internal_container->file_io_handle_opened_in_library = 0;
873
51
  }
874
51
  if( internal_container->file_io_handle_created_in_library != 0 )
875
0
  {
876
0
    if( libbfio_handle_free(
877
0
         &( internal_container->file_io_handle ),
878
0
         error ) != 1 )
879
0
    {
880
0
      libcerror_error_set(
881
0
       error,
882
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
883
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
884
0
       "%s: unable to free file IO handle.",
885
0
       function );
886
887
0
      result = -1;
888
0
    }
889
0
    internal_container->file_io_handle_created_in_library = 0;
890
0
  }
891
51
  internal_container->file_io_handle = NULL;
892
893
51
  if( libfsapfs_io_handle_clear(
894
51
       internal_container->io_handle,
895
51
       error ) != 1 )
896
0
  {
897
0
    libcerror_error_set(
898
0
     error,
899
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
900
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
901
0
     "%s: unable to clear IO handle.",
902
0
     function );
903
904
0
    result = -1;
905
0
  }
906
51
  if( internal_container->superblock != NULL )
907
51
  {
908
51
    if( libfsapfs_container_superblock_free(
909
51
         &( internal_container->superblock ),
910
51
         error ) != 1 )
911
0
    {
912
0
      libcerror_error_set(
913
0
       error,
914
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
915
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
916
0
       "%s: unable to free container superblock.",
917
0
       function );
918
919
0
      result = -1;
920
0
    }
921
51
  }
922
51
  if( internal_container->fusion_middle_tree != NULL )
923
0
  {
924
0
    if( libfsapfs_fusion_middle_tree_free(
925
0
         &( internal_container->fusion_middle_tree ),
926
0
         error ) != 1 )
927
0
    {
928
0
      libcerror_error_set(
929
0
       error,
930
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
931
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
932
0
       "%s: unable to free Fusion middle tree.",
933
0
       function );
934
935
0
      result = -1;
936
0
    }
937
0
  }
938
51
  if( internal_container->checkpoint_map != NULL )
939
51
  {
940
51
    if( libfsapfs_checkpoint_map_free(
941
51
         &( internal_container->checkpoint_map ),
942
51
         error ) != 1 )
943
0
    {
944
0
      libcerror_error_set(
945
0
       error,
946
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
947
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
948
0
       "%s: unable to free checkpoint map.",
949
0
       function );
950
951
0
      result = -1;
952
0
    }
953
51
  }
954
51
  if( libfdata_vector_free(
955
51
       &( internal_container->data_block_vector ),
956
51
       error ) != 1 )
957
0
  {
958
0
    libcerror_error_set(
959
0
     error,
960
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
961
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
962
0
     "%s: unable to free data block vector.",
963
0
     function );
964
965
0
    result = -1;
966
0
  }
967
51
  if( internal_container->object_map_btree != NULL )
968
51
  {
969
51
    if( libfsapfs_object_map_btree_free(
970
51
         &( internal_container->object_map_btree ),
971
51
         error ) != 1 )
972
0
    {
973
0
      libcerror_error_set(
974
0
       error,
975
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
976
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
977
0
       "%s: unable to free object map B-tree.",
978
0
       function );
979
980
0
      result = -1;
981
0
    }
982
51
  }
983
51
  if( internal_container->key_bag != NULL )
984
44
  {
985
44
    if( libfsapfs_container_key_bag_free(
986
44
         &( internal_container->key_bag ),
987
44
         error ) != 1 )
988
0
    {
989
0
      libcerror_error_set(
990
0
       error,
991
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
992
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
993
0
       "%s: unable to free key bag.",
994
0
       function );
995
996
0
      result = -1;
997
0
    }
998
44
  }
999
51
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1000
51
  if( libcthreads_read_write_lock_release_for_write(
1001
51
       internal_container->read_write_lock,
1002
51
       error ) != 1 )
1003
0
  {
1004
0
    libcerror_error_set(
1005
0
     error,
1006
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1007
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1008
0
     "%s: unable to release read/write lock for writing.",
1009
0
     function );
1010
1011
0
    return( -1 );
1012
0
  }
1013
51
#endif
1014
51
  return( result );
1015
51
}
1016
1017
/* Opens a container for reading
1018
 * Returns 1 if successful or -1 on error
1019
 */
1020
int libfsapfs_internal_container_open_read(
1021
     libfsapfs_internal_container_t *internal_container,
1022
     libbfio_handle_t *file_io_handle,
1023
     off64_t file_offset,
1024
     libcerror_error_t **error )
1025
1.44k
{
1026
1.44k
  libfsapfs_container_data_handle_t *container_data_handle    = NULL;
1027
1.44k
  libfsapfs_container_superblock_t *container_superblock      = NULL;
1028
1.44k
  libfsapfs_container_superblock_t *container_superblock_swap = NULL;
1029
1.44k
  libfsapfs_object_t *object                                  = NULL;
1030
1.44k
  libfsapfs_object_map_t *object_map                          = NULL;
1031
1.44k
  static char *function                                       = "libfsapfs_internal_container_open_read";
1032
1.44k
  uint64_t checkpoint_map_block_number                        = 0;
1033
1.44k
  uint64_t checkpoint_map_transaction_identifier              = 0;
1034
1.44k
  uint64_t metadata_block_index                               = 0;
1035
1.44k
  int element_index                                           = 0;
1036
1.44k
  int result                                                  = 0;
1037
1038
#if defined( HAVE_DEBUG_OUTPUT )
1039
  libfsapfs_checkpoint_map_t *checkpoint_map                  = NULL;
1040
  libfsapfs_container_reaper_t *container_reaper              = NULL;
1041
  libfsapfs_space_manager_t *space_manager                    = NULL;
1042
  uint64_t reaper_block_number                                = 0;
1043
  uint64_t space_manager_block_number                         = 0;
1044
#endif
1045
1046
1.44k
  if( internal_container == NULL )
1047
0
  {
1048
0
    libcerror_error_set(
1049
0
     error,
1050
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1051
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1052
0
     "%s: invalid container.",
1053
0
     function );
1054
1055
0
    return( -1 );
1056
0
  }
1057
1.44k
  if( internal_container->io_handle == NULL )
1058
0
  {
1059
0
    libcerror_error_set(
1060
0
     error,
1061
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1062
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1063
0
     "%s: invalid container - missing IO handle.",
1064
0
     function );
1065
1066
0
    return( -1 );
1067
0
  }
1068
1.44k
  if( internal_container->superblock != NULL )
1069
0
  {
1070
0
    libcerror_error_set(
1071
0
     error,
1072
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1073
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1074
0
     "%s: invalid container - superblock map value already set.",
1075
0
     function );
1076
1077
0
    return( -1 );
1078
0
  }
1079
1.44k
  if( internal_container->fusion_middle_tree != NULL )
1080
0
  {
1081
0
    libcerror_error_set(
1082
0
     error,
1083
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1084
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1085
0
     "%s: invalid container - Fusion middle tree value already set.",
1086
0
     function );
1087
1088
0
    return( -1 );
1089
0
  }
1090
1.44k
  if( internal_container->checkpoint_map != NULL )
1091
0
  {
1092
0
    libcerror_error_set(
1093
0
     error,
1094
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1095
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1096
0
     "%s: invalid container - checkpoint map value already set.",
1097
0
     function );
1098
1099
0
    return( -1 );
1100
0
  }
1101
1.44k
  if( internal_container->data_block_vector != NULL )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1107
0
     "%s: invalid container - data block vector already set.",
1108
0
     function );
1109
1110
0
    return( -1 );
1111
0
  }
1112
1.44k
  if( internal_container->object_map_btree != NULL )
1113
0
  {
1114
0
    libcerror_error_set(
1115
0
     error,
1116
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1117
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1118
0
     "%s: invalid container - object map B-tree value already set.",
1119
0
     function );
1120
1121
0
    return( -1 );
1122
0
  }
1123
1.44k
  if( internal_container->key_bag != NULL )
1124
0
  {
1125
0
    libcerror_error_set(
1126
0
     error,
1127
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1128
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1129
0
     "%s: invalid container - key bag value already set.",
1130
0
     function );
1131
1132
0
    return( -1 );
1133
0
  }
1134
#if defined( HAVE_DEBUG_OUTPUT )
1135
  if( libcnotify_verbose != 0 )
1136
  {
1137
    libcnotify_printf(
1138
     "Reading container superblock:\n" );
1139
  }
1140
#endif
1141
1.44k
  if( libfsapfs_container_superblock_initialize(
1142
1.44k
       &( internal_container->superblock ),
1143
1.44k
       error ) != 1 )
1144
0
  {
1145
0
    libcerror_error_set(
1146
0
     error,
1147
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1148
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1149
0
     "%s: unable to create container superblock.",
1150
0
     function );
1151
1152
0
    goto on_error;
1153
0
  }
1154
1.44k
  if( libfsapfs_container_superblock_read_file_io_handle(
1155
1.44k
       internal_container->superblock,
1156
1.44k
       file_io_handle,
1157
1.44k
       file_offset,
1158
1.44k
       error ) != 1 )
1159
354
  {
1160
354
    libcerror_error_set(
1161
354
     error,
1162
354
     LIBCERROR_ERROR_DOMAIN_IO,
1163
354
     LIBCERROR_IO_ERROR_READ_FAILED,
1164
354
     "%s: unable to read container superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1165
354
     function,
1166
354
     file_offset,
1167
354
     file_offset );
1168
1169
354
    goto on_error;
1170
354
  }
1171
1.08k
  internal_container->io_handle->block_size     = internal_container->superblock->block_size;
1172
1.08k
  internal_container->io_handle->container_size = (size64_t) internal_container->superblock->number_of_blocks * (size64_t) internal_container->io_handle->block_size;
1173
1174
1.08k
#if !defined( HAVE_DEBUG_OUTPUT )
1175
1.08k
  if( ( internal_container->superblock->incompatible_features_flags & 0x0000000000000100UL ) != 0 )
1176
1
  {
1177
1
    libcerror_error_set(
1178
1
     error,
1179
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1180
1
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1181
1
     "%s: Fusion drive not supported.",
1182
1
     function );
1183
1184
1
    goto on_error;
1185
1
  }
1186
1.08k
#endif
1187
#if defined( HAVE_DEBUG_OUTPUT )
1188
  if( libcnotify_verbose != 0 )
1189
  {
1190
    libcnotify_printf(
1191
     "Scanning checkpoint descriptor area:\n" );
1192
  }
1193
#endif
1194
1.08k
  if( libfsapfs_object_initialize(
1195
1.08k
       &object,
1196
1.08k
       error ) != 1 )
1197
0
  {
1198
0
    libcerror_error_set(
1199
0
     error,
1200
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1201
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1202
0
     "%s: unable to create object.",
1203
0
     function );
1204
1205
0
    goto on_error;
1206
0
  }
1207
1.08k
  file_offset = (off64_t) internal_container->superblock->checkpoint_descriptor_area_block_number * internal_container->io_handle->block_size;
1208
1209
1.08k
  for( metadata_block_index = 0;
1210
5.24k
       metadata_block_index <= internal_container->superblock->checkpoint_descriptor_area_number_of_blocks;
1211
4.15k
       metadata_block_index++ )
1212
4.56k
  {
1213
4.56k
    if( libfsapfs_object_read_file_io_handle(
1214
4.56k
         object,
1215
4.56k
         file_io_handle,
1216
4.56k
         file_offset,
1217
4.56k
         error ) != 1 )
1218
390
    {
1219
390
      libcerror_error_set(
1220
390
       error,
1221
390
       LIBCERROR_ERROR_DOMAIN_IO,
1222
390
       LIBCERROR_IO_ERROR_READ_FAILED,
1223
390
       "%s: unable to read object at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1224
390
       function,
1225
390
       file_offset,
1226
390
       file_offset );
1227
1228
390
      goto on_error;
1229
390
    }
1230
4.17k
    switch( object->type )
1231
4.17k
    {
1232
817
      case 0x4000000c:
1233
#if defined( HAVE_DEBUG_OUTPUT )
1234
        if( libcnotify_verbose != 0 )
1235
        {
1236
          libcnotify_printf(
1237
           "Reading checkpoint map:\n" );
1238
1239
          if( libfsapfs_checkpoint_map_initialize(
1240
               &checkpoint_map,
1241
               error ) != 1 )
1242
          {
1243
            libcerror_error_set(
1244
             error,
1245
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1246
             LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1247
             "%s: unable to create backup checkpoint map.",
1248
             function );
1249
1250
            goto on_error;
1251
          }
1252
          if( libfsapfs_checkpoint_map_read_file_io_handle(
1253
               checkpoint_map,
1254
               file_io_handle,
1255
               file_offset,
1256
               error ) != 1 )
1257
          {
1258
            libcerror_error_set(
1259
             error,
1260
             LIBCERROR_ERROR_DOMAIN_IO,
1261
             LIBCERROR_IO_ERROR_READ_FAILED,
1262
             "%s: unable to read backup checkpoint map at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1263
             function,
1264
             file_offset,
1265
             file_offset );
1266
1267
            goto on_error;
1268
          }
1269
          if( libfsapfs_checkpoint_map_free(
1270
               &checkpoint_map,
1271
               error ) != 1 )
1272
          {
1273
            libcerror_error_set(
1274
             error,
1275
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
1276
             LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1277
             "%s: unable to free backup checkpoint map.",
1278
             function );
1279
1280
            goto on_error;
1281
          }
1282
        }
1283
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1284
817
        if( object->transaction_identifier > checkpoint_map_transaction_identifier )
1285
749
        {
1286
749
          checkpoint_map_block_number           = internal_container->superblock->checkpoint_descriptor_area_block_number + metadata_block_index;
1287
749
          checkpoint_map_transaction_identifier = object->transaction_identifier;
1288
749
        }
1289
817
        break;
1290
1291
2.18k
      case 0x80000001:
1292
#if defined( HAVE_DEBUG_OUTPUT )
1293
        if( libcnotify_verbose != 0 )
1294
        {
1295
          libcnotify_printf(
1296
           "Reading container superblock:\n" );
1297
        }
1298
#endif
1299
2.18k
        if( libfsapfs_container_superblock_initialize(
1300
2.18k
             &container_superblock,
1301
2.18k
             error ) != 1 )
1302
0
        {
1303
0
          libcerror_error_set(
1304
0
           error,
1305
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1307
0
           "%s: unable to create backup container superblock.",
1308
0
           function );
1309
1310
0
          goto on_error;
1311
0
        }
1312
2.18k
        if( libfsapfs_container_superblock_read_file_io_handle(
1313
2.18k
             container_superblock,
1314
2.18k
             file_io_handle,
1315
2.18k
             file_offset,
1316
2.18k
             error ) != 1 )
1317
20
        {
1318
20
          libcerror_error_set(
1319
20
           error,
1320
20
           LIBCERROR_ERROR_DOMAIN_IO,
1321
20
           LIBCERROR_IO_ERROR_READ_FAILED,
1322
20
           "%s: unable to read backup container superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1323
20
           function,
1324
20
           file_offset,
1325
20
           file_offset );
1326
1327
20
          goto on_error;
1328
20
        }
1329
2.16k
        if( container_superblock->object_transaction_identifier > internal_container->superblock->object_transaction_identifier )
1330
479
        {
1331
479
          container_superblock_swap      = internal_container->superblock;
1332
479
          internal_container->superblock = container_superblock;
1333
479
          container_superblock           = container_superblock_swap;
1334
479
        }
1335
2.16k
        if( libfsapfs_container_superblock_free(
1336
2.16k
             &container_superblock,
1337
2.16k
             error ) != 1 )
1338
0
        {
1339
0
          libcerror_error_set(
1340
0
           error,
1341
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1342
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1343
0
           "%s: unable to free backup container superblock.",
1344
0
           function );
1345
1346
0
          goto on_error;
1347
0
        }
1348
2.16k
        break;
1349
1350
2.16k
      default:
1351
1.17k
        break;
1352
4.17k
    }
1353
4.15k
    file_offset += internal_container->io_handle->block_size;
1354
4.15k
  }
1355
675
  if( libfsapfs_object_free(
1356
675
       &object,
1357
675
       error ) != 1 )
1358
0
  {
1359
0
    libcerror_error_set(
1360
0
     error,
1361
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1362
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1363
0
     "%s: unable to free object.",
1364
0
     function );
1365
1366
0
    goto on_error;
1367
0
  }
1368
675
  if( checkpoint_map_block_number == 0 )
1369
25
  {
1370
25
    libcerror_error_set(
1371
25
     error,
1372
25
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1373
25
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1374
25
     "%s: missing checkpoint map block number.",
1375
25
     function );
1376
1377
25
    goto on_error;
1378
25
  }
1379
#if defined( HAVE_DEBUG_OUTPUT )
1380
  if( libcnotify_verbose != 0 )
1381
  {
1382
    libcnotify_printf(
1383
     "Reading checkpoint map:\n" );
1384
  }
1385
#endif
1386
650
  if( libfsapfs_checkpoint_map_initialize(
1387
650
       &( internal_container->checkpoint_map ),
1388
650
       error ) != 1 )
1389
0
  {
1390
0
    libcerror_error_set(
1391
0
     error,
1392
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1393
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1394
0
     "%s: unable to create checkpoint map.",
1395
0
     function );
1396
1397
0
    goto on_error;
1398
0
  }
1399
650
  file_offset = checkpoint_map_block_number * internal_container->io_handle->block_size;
1400
1401
650
  if( libfsapfs_checkpoint_map_read_file_io_handle(
1402
650
       internal_container->checkpoint_map,
1403
650
       file_io_handle,
1404
650
       file_offset,
1405
650
       error ) != 1 )
1406
237
  {
1407
237
    libcerror_error_set(
1408
237
     error,
1409
237
     LIBCERROR_ERROR_DOMAIN_IO,
1410
237
     LIBCERROR_IO_ERROR_READ_FAILED,
1411
237
     "%s: unable to read checkpoint map at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1412
237
     function,
1413
237
     file_offset,
1414
237
     file_offset );
1415
1416
237
    goto on_error;
1417
237
  }
1418
#if defined( HAVE_DEBUG_OUTPUT )
1419
  if( libcnotify_verbose != 0 )
1420
  {
1421
    if( internal_container->superblock->fusion_middle_tree_block_number != 0 )
1422
    {
1423
      libcnotify_printf(
1424
       "Reading Fusion middle tree:\n" );
1425
1426
      file_offset = internal_container->superblock->fusion_middle_tree_block_number * internal_container->io_handle->block_size;
1427
1428
      if( libfsapfs_fusion_middle_tree_initialize(
1429
           &( internal_container->fusion_middle_tree ),
1430
           error ) != 1 )
1431
      {
1432
        libcerror_error_set(
1433
         error,
1434
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1435
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1436
         "%s: unable to create Fusion middle tree.",
1437
         function );
1438
1439
        goto on_error;
1440
      }
1441
      if( libfsapfs_fusion_middle_tree_read_file_io_handle(
1442
           internal_container->fusion_middle_tree,
1443
           file_io_handle,
1444
           file_offset,
1445
           error ) != 1 )
1446
      {
1447
        libcerror_error_set(
1448
         error,
1449
         LIBCERROR_ERROR_DOMAIN_IO,
1450
         LIBCERROR_IO_ERROR_READ_FAILED,
1451
         "%s: unable to read Fusion middle tree at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1452
         function,
1453
         file_offset,
1454
         file_offset );
1455
1456
        goto on_error;
1457
      }
1458
    }
1459
    if( internal_container->superblock->space_manager_object_identifier > 0 )
1460
    {
1461
      libcnotify_printf(
1462
       "Reading space manager:\n" );
1463
1464
      if( libfsapfs_checkpoint_map_get_physical_address_by_object_identifier(
1465
           internal_container->checkpoint_map,
1466
           internal_container->superblock->space_manager_object_identifier,
1467
           &space_manager_block_number,
1468
           error ) != 1 )
1469
      {
1470
        libcerror_error_set(
1471
         error,
1472
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1473
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1474
         "%s: unable to determine space manager block number from object identifier: 0x08%" PRIx64 ".",
1475
         function,
1476
         internal_container->superblock->space_manager_object_identifier );
1477
1478
        goto on_error;
1479
      }
1480
      file_offset = space_manager_block_number * internal_container->io_handle->block_size;
1481
1482
      if( libfsapfs_space_manager_initialize(
1483
           &space_manager,
1484
           error ) != 1 )
1485
      {
1486
        libcerror_error_set(
1487
         error,
1488
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1489
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1490
         "%s: unable to create space manager.",
1491
         function );
1492
1493
        goto on_error;
1494
      }
1495
      if( libfsapfs_space_manager_read_file_io_handle(
1496
           space_manager,
1497
           file_io_handle,
1498
           file_offset,
1499
           error ) != 1 )
1500
      {
1501
        libcerror_error_set(
1502
         error,
1503
         LIBCERROR_ERROR_DOMAIN_IO,
1504
         LIBCERROR_IO_ERROR_READ_FAILED,
1505
         "%s: unable to read space manager at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1506
         function,
1507
         file_offset,
1508
         file_offset );
1509
1510
        goto on_error;
1511
      }
1512
      if( libfsapfs_space_manager_free(
1513
           &space_manager,
1514
           error ) != 1 )
1515
      {
1516
        libcerror_error_set(
1517
         error,
1518
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1519
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1520
         "%s: unable to free space manager.",
1521
         function );
1522
1523
        goto on_error;
1524
      }
1525
    }
1526
    if( internal_container->superblock->reaper_object_identifier > 0 )
1527
    {
1528
      libcnotify_printf(
1529
       "Reading reaper:\n" );
1530
1531
      if( libfsapfs_checkpoint_map_get_physical_address_by_object_identifier(
1532
           internal_container->checkpoint_map,
1533
           internal_container->superblock->reaper_object_identifier,
1534
           &reaper_block_number,
1535
           error ) != 1 )
1536
      {
1537
        libcerror_error_set(
1538
         error,
1539
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1540
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1541
         "%s: unable to determine reaper block number from object identifier: 0x08%" PRIx64 ".",
1542
         function,
1543
         internal_container->superblock->reaper_object_identifier );
1544
1545
        goto on_error;
1546
      }
1547
      file_offset = reaper_block_number * internal_container->io_handle->block_size;
1548
1549
      if( libfsapfs_container_reaper_initialize(
1550
           &container_reaper,
1551
           error ) != 1 )
1552
      {
1553
        libcerror_error_set(
1554
         error,
1555
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1556
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1557
         "%s: unable to create container reaper.",
1558
         function );
1559
1560
        goto on_error;
1561
      }
1562
      if( libfsapfs_container_reaper_read_file_io_handle(
1563
           container_reaper,
1564
           file_io_handle,
1565
           file_offset,
1566
           error ) != 1 )
1567
      {
1568
        libcerror_error_set(
1569
         error,
1570
         LIBCERROR_ERROR_DOMAIN_IO,
1571
         LIBCERROR_IO_ERROR_READ_FAILED,
1572
         "%s: unable to read container reaper at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1573
         function,
1574
         file_offset,
1575
         file_offset );
1576
1577
        goto on_error;
1578
      }
1579
      if( libfsapfs_container_reaper_free(
1580
           &container_reaper,
1581
           error ) != 1 )
1582
      {
1583
        libcerror_error_set(
1584
         error,
1585
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1586
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1587
         "%s: unable to free container reaper.",
1588
         function );
1589
1590
        goto on_error;
1591
      }
1592
    }
1593
  }
1594
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1595
1596
413
  if( libfsapfs_container_data_handle_initialize(
1597
413
       &container_data_handle,
1598
413
       internal_container->io_handle,
1599
413
       error ) != 1 )
1600
0
  {
1601
0
    libcerror_error_set(
1602
0
     error,
1603
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1604
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1605
0
     "%s: unable to create container data handle.",
1606
0
     function );
1607
1608
0
    goto on_error;
1609
0
  }
1610
413
  if( libfdata_vector_initialize(
1611
413
       &( internal_container->data_block_vector ),
1612
413
       (size64_t) internal_container->io_handle->block_size,
1613
413
       (intptr_t *) container_data_handle,
1614
413
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_container_data_handle_free,
1615
413
       NULL,
1616
413
       (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,
1617
413
       NULL,
1618
413
       LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
1619
413
       error ) != 1 )
1620
0
  {
1621
0
    libcerror_error_set(
1622
0
     error,
1623
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1624
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1625
0
     "%s: unable to create data block vector.",
1626
0
     function );
1627
1628
0
    goto on_error;
1629
0
  }
1630
413
  internal_container->container_data_handle = container_data_handle;
1631
413
  container_data_handle                     = NULL;
1632
1633
413
  if( libfdata_vector_append_segment(
1634
413
       internal_container->data_block_vector,
1635
413
       &element_index,
1636
413
       0,
1637
413
       0,
1638
413
       internal_container->io_handle->container_size,
1639
413
       0,
1640
413
       error ) != 1 )
1641
40
  {
1642
40
    libcerror_error_set(
1643
40
     error,
1644
40
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1645
40
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1646
40
     "%s: unable to append segment to data block vector.",
1647
40
     function );
1648
1649
40
    goto on_error;
1650
40
  }
1651
/* TODO refactor into function to read object map */
1652
373
  if( internal_container->superblock->object_map_block_number == 0 )
1653
5
  {
1654
5
    libcerror_error_set(
1655
5
     error,
1656
5
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1657
5
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1658
5
     "%s: missing object map block number.",
1659
5
     function );
1660
1661
5
    goto on_error;
1662
5
  }
1663
#if defined( HAVE_DEBUG_OUTPUT )
1664
  if( libcnotify_verbose != 0 )
1665
  {
1666
    libcnotify_printf(
1667
     "Reading object map:\n" );
1668
  }
1669
#endif
1670
368
  file_offset = internal_container->superblock->object_map_block_number * internal_container->io_handle->block_size;
1671
1672
368
  if( libfsapfs_object_map_initialize(
1673
368
       &object_map,
1674
368
       error ) != 1 )
1675
0
  {
1676
0
    libcerror_error_set(
1677
0
     error,
1678
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1679
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1680
0
     "%s: unable to create object map.",
1681
0
     function );
1682
1683
0
    goto on_error;
1684
0
  }
1685
368
  if( libfsapfs_object_map_read_file_io_handle(
1686
368
       object_map,
1687
368
       file_io_handle,
1688
368
       file_offset,
1689
368
       error ) != 1 )
1690
173
  {
1691
173
    libcerror_error_set(
1692
173
     error,
1693
173
     LIBCERROR_ERROR_DOMAIN_IO,
1694
173
     LIBCERROR_IO_ERROR_READ_FAILED,
1695
173
     "%s: unable to read object map at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1696
173
     function,
1697
173
     file_offset,
1698
173
     file_offset );
1699
1700
173
    goto on_error;
1701
173
  }
1702
195
  if( object_map->btree_block_number == 0 )
1703
1
  {
1704
1
    libcerror_error_set(
1705
1
     error,
1706
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1707
1
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1708
1
     "%s: missing object map B-tree block number.",
1709
1
     function );
1710
1711
1
    goto on_error;
1712
1
  }
1713
#if defined( HAVE_DEBUG_OUTPUT )
1714
  if( libcnotify_verbose != 0 )
1715
  {
1716
    libcnotify_printf(
1717
     "Reading object map B-tree:\n" );
1718
  }
1719
#endif
1720
194
  if( libfsapfs_object_map_btree_initialize(
1721
194
       &( internal_container->object_map_btree ),
1722
194
       internal_container->io_handle,
1723
194
       internal_container->data_block_vector,
1724
194
       object_map->btree_block_number,
1725
194
       error ) != 1 )
1726
0
  {
1727
0
    libcerror_error_set(
1728
0
     error,
1729
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1730
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1731
0
     "%s: unable to create object map B-tree.",
1732
0
     function );
1733
1734
0
    goto on_error;
1735
0
  }
1736
194
  if( libfsapfs_object_map_free(
1737
194
       &object_map,
1738
194
       error ) != 1 )
1739
0
  {
1740
0
    libcerror_error_set(
1741
0
     error,
1742
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1743
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1744
0
     "%s: unable to free object map.",
1745
0
     function );
1746
1747
0
    goto on_error;
1748
0
  }
1749
194
  if( ( internal_container->superblock->key_bag_block_number > 0 )
1750
194
   && ( internal_container->superblock->key_bag_number_of_blocks > 0 ) )
1751
187
  {
1752
187
    if( libfsapfs_container_key_bag_initialize(
1753
187
         &( internal_container->key_bag ),
1754
187
         error ) != 1 )
1755
0
    {
1756
0
      libcerror_error_set(
1757
0
       error,
1758
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1759
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1760
0
       "%s: unable to create container key bag.",
1761
0
       function );
1762
1763
0
      goto on_error;
1764
0
    }
1765
187
    file_offset = internal_container->superblock->key_bag_block_number * internal_container->io_handle->block_size;
1766
1767
187
    result = libfsapfs_container_key_bag_read_file_io_handle(
1768
187
              internal_container->key_bag,
1769
187
              internal_container->io_handle,
1770
187
              file_io_handle,
1771
187
              file_offset,
1772
187
              (size64_t) internal_container->superblock->key_bag_number_of_blocks * internal_container->io_handle->block_size,
1773
187
              internal_container->superblock->container_identifier,
1774
187
              error );
1775
1776
187
    if( result == -1 )
1777
143
    {
1778
143
      libcerror_error_set(
1779
143
       error,
1780
143
       LIBCERROR_ERROR_DOMAIN_IO,
1781
143
       LIBCERROR_IO_ERROR_READ_FAILED,
1782
143
       "%s: unable to read container key bag at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1783
143
       function,
1784
143
       file_offset,
1785
143
       file_offset );
1786
1787
143
      goto on_error;
1788
143
    }
1789
44
    else if( result == 0 )
1790
44
    {
1791
44
      internal_container->key_bag->is_locked = 1;
1792
44
    }
1793
187
  }
1794
51
  return( 1 );
1795
1796
1.38k
on_error:
1797
1.38k
  if( internal_container->key_bag != NULL )
1798
143
  {
1799
143
    libfsapfs_container_key_bag_free(
1800
143
     &( internal_container->key_bag ),
1801
143
     NULL );
1802
143
  }
1803
1.38k
  if( internal_container->object_map_btree != NULL )
1804
143
  {
1805
143
    libfsapfs_object_map_btree_free(
1806
143
     &( internal_container->object_map_btree ),
1807
143
     NULL );
1808
143
  }
1809
1.38k
  if( object_map != NULL )
1810
174
  {
1811
174
    libfsapfs_object_map_free(
1812
174
     &object_map,
1813
174
     NULL );
1814
174
  }
1815
1.38k
  if( internal_container->data_block_vector != NULL )
1816
362
  {
1817
362
    libfdata_vector_free(
1818
362
     &( internal_container->data_block_vector ),
1819
362
     NULL );
1820
362
  }
1821
1.38k
  if( container_data_handle != NULL )
1822
0
  {
1823
0
    libfsapfs_container_data_handle_free(
1824
0
     &container_data_handle,
1825
0
     NULL );
1826
0
  }
1827
#if defined( HAVE_DEBUG_OUTPUT )
1828
  if( container_reaper != NULL )
1829
  {
1830
    libfsapfs_container_reaper_free(
1831
     &container_reaper,
1832
     NULL );
1833
  }
1834
  if( space_manager != NULL )
1835
  {
1836
    libfsapfs_space_manager_free(
1837
     &space_manager,
1838
     NULL );
1839
  }
1840
#endif
1841
1.38k
  if( internal_container->checkpoint_map != NULL )
1842
599
  {
1843
599
    libfsapfs_checkpoint_map_free(
1844
599
     &( internal_container->checkpoint_map ),
1845
599
     NULL );
1846
599
  }
1847
#if defined( HAVE_DEBUG_OUTPUT )
1848
  if( checkpoint_map != NULL )
1849
  {
1850
    libfsapfs_checkpoint_map_free(
1851
     &checkpoint_map,
1852
     NULL );
1853
  }
1854
#endif
1855
1.38k
  if( container_superblock != NULL )
1856
20
  {
1857
20
    libfsapfs_container_superblock_free(
1858
20
     &container_superblock,
1859
20
     NULL );
1860
20
  }
1861
1.38k
  if( internal_container->fusion_middle_tree != NULL )
1862
0
  {
1863
0
    libfsapfs_fusion_middle_tree_free(
1864
0
     &( internal_container->fusion_middle_tree ),
1865
0
     NULL );
1866
0
  }
1867
1.38k
  if( object != NULL )
1868
410
  {
1869
410
    libfsapfs_object_free(
1870
410
     &object,
1871
410
     NULL );
1872
410
  }
1873
1.38k
  if( internal_container->superblock != NULL )
1874
1.38k
  {
1875
1.38k
    libfsapfs_container_superblock_free(
1876
1.38k
     &( internal_container->superblock ),
1877
1.38k
     NULL );
1878
1.38k
  }
1879
1.38k
  return( -1 );
1880
194
}
1881
1882
/* Retrieves the size
1883
 * Returns 1 if successful or -1 on error
1884
 */
1885
int libfsapfs_container_get_size(
1886
     libfsapfs_container_t *container,
1887
     size64_t *size,
1888
     libcerror_error_t **error )
1889
0
{
1890
0
  libfsapfs_internal_container_t *internal_container = NULL;
1891
0
  static char *function                              = "libfsapfs_container_get_size";
1892
1893
0
  if( container == NULL )
1894
0
  {
1895
0
    libcerror_error_set(
1896
0
     error,
1897
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1898
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1899
0
     "%s: invalid container.",
1900
0
     function );
1901
1902
0
    return( -1 );
1903
0
  }
1904
0
  internal_container = (libfsapfs_internal_container_t *) container;
1905
1906
0
  if( internal_container->io_handle == NULL )
1907
0
  {
1908
0
    libcerror_error_set(
1909
0
     error,
1910
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1911
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1912
0
     "%s: invalid container - missing IO handle.",
1913
0
     function );
1914
1915
0
    return( -1 );
1916
0
  }
1917
0
  if( internal_container->superblock == NULL )
1918
0
  {
1919
0
    libcerror_error_set(
1920
0
     error,
1921
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1922
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1923
0
     "%s: invalid container - missing superblock.",
1924
0
     function );
1925
1926
0
    return( -1 );
1927
0
  }
1928
0
  if( size == NULL )
1929
0
  {
1930
0
    libcerror_error_set(
1931
0
     error,
1932
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1933
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1934
0
     "%s: invalid size.",
1935
0
     function );
1936
1937
0
    return( -1 );
1938
0
  }
1939
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1940
0
  if( libcthreads_read_write_lock_grab_for_read(
1941
0
       internal_container->read_write_lock,
1942
0
       error ) != 1 )
1943
0
  {
1944
0
    libcerror_error_set(
1945
0
     error,
1946
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1947
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1948
0
     "%s: unable to grab read/write lock for reading.",
1949
0
     function );
1950
1951
0
    return( -1 );
1952
0
  }
1953
0
#endif
1954
0
  *size = internal_container->io_handle->container_size;
1955
1956
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1957
0
  if( libcthreads_read_write_lock_release_for_read(
1958
0
       internal_container->read_write_lock,
1959
0
       error ) != 1 )
1960
0
  {
1961
0
    libcerror_error_set(
1962
0
     error,
1963
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1964
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1965
0
     "%s: unable to release read/write lock for reading.",
1966
0
     function );
1967
1968
0
    return( -1 );
1969
0
  }
1970
0
#endif
1971
0
  return( 1 );
1972
0
}
1973
1974
/* Retrieves the identifier
1975
 * The identifier is an UUID stored in big-endian and is 16 bytes of size
1976
 * Returns 1 if successful or -1 on error
1977
 */
1978
int libfsapfs_container_get_identifier(
1979
     libfsapfs_container_t *container,
1980
     uint8_t *uuid_data,
1981
     size_t uuid_data_size,
1982
     libcerror_error_t **error )
1983
0
{
1984
0
  libfsapfs_internal_container_t *internal_container = NULL;
1985
0
  static char *function                              = "libfsapfs_container_get_identifier";
1986
0
  int result                                         = 1;
1987
1988
0
  if( container == NULL )
1989
0
  {
1990
0
    libcerror_error_set(
1991
0
     error,
1992
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1993
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1994
0
     "%s: invalid container.",
1995
0
     function );
1996
1997
0
    return( -1 );
1998
0
  }
1999
0
  internal_container = (libfsapfs_internal_container_t *) container;
2000
2001
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2002
0
  if( libcthreads_read_write_lock_grab_for_read(
2003
0
       internal_container->read_write_lock,
2004
0
       error ) != 1 )
2005
0
  {
2006
0
    libcerror_error_set(
2007
0
     error,
2008
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2009
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2010
0
     "%s: unable to grab read/write lock for reading.",
2011
0
     function );
2012
2013
0
    return( -1 );
2014
0
  }
2015
0
#endif
2016
0
  if( libfsapfs_container_superblock_get_container_identifier(
2017
0
       internal_container->superblock,
2018
0
       uuid_data,
2019
0
       uuid_data_size,
2020
0
       error ) != 1 )
2021
0
  {
2022
0
    libcerror_error_set(
2023
0
     error,
2024
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2025
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2026
0
     "%s: unable to retrieve container identifier.",
2027
0
     function );
2028
2029
0
    result = -1;
2030
0
  }
2031
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2032
0
  if( libcthreads_read_write_lock_release_for_read(
2033
0
       internal_container->read_write_lock,
2034
0
       error ) != 1 )
2035
0
  {
2036
0
    libcerror_error_set(
2037
0
     error,
2038
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2039
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2040
0
     "%s: unable to release read/write lock for reading.",
2041
0
     function );
2042
2043
0
    return( -1 );
2044
0
  }
2045
0
#endif
2046
0
  return( result );
2047
0
}
2048
2049
/* Determines if the container is locked
2050
 * Returns 1 if locked, 0 if not or -1 on error
2051
 */
2052
int libfsapfs_container_is_locked(
2053
     libfsapfs_container_t *container,
2054
     libcerror_error_t **error )
2055
0
{
2056
0
  libfsapfs_internal_container_t *internal_container = NULL;
2057
0
  static char *function                              = "libfsapfs_container_is_locked";
2058
0
  uint8_t is_locked                                  = 0;
2059
2060
0
  if( container == NULL )
2061
0
  {
2062
0
    libcerror_error_set(
2063
0
     error,
2064
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2065
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2066
0
     "%s: invalid container.",
2067
0
     function );
2068
2069
0
    return( -1 );
2070
0
  }
2071
0
  internal_container = (libfsapfs_internal_container_t *) container;
2072
2073
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2074
0
  if( libcthreads_read_write_lock_grab_for_read(
2075
0
       internal_container->read_write_lock,
2076
0
       error ) != 1 )
2077
0
  {
2078
0
    libcerror_error_set(
2079
0
     error,
2080
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2081
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2082
0
     "%s: unable to grab read/write lock for reading.",
2083
0
     function );
2084
2085
0
    return( -1 );
2086
0
  }
2087
0
#endif
2088
0
  if( internal_container->key_bag != NULL )
2089
0
  {
2090
0
    is_locked = internal_container->key_bag->is_locked;
2091
0
  }
2092
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2093
0
  if( libcthreads_read_write_lock_release_for_read(
2094
0
       internal_container->read_write_lock,
2095
0
       error ) != 1 )
2096
0
  {
2097
0
    libcerror_error_set(
2098
0
     error,
2099
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2100
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2101
0
     "%s: unable to release read/write lock for reading.",
2102
0
     function );
2103
2104
0
    return( -1 );
2105
0
  }
2106
0
#endif
2107
0
  return( is_locked );
2108
0
}
2109
2110
/* Retrieves the number of volumes
2111
 * Returns 1 if successful or -1 on error
2112
 */
2113
int libfsapfs_container_get_number_of_volumes(
2114
     libfsapfs_container_t *container,
2115
     int *number_of_volumes,
2116
     libcerror_error_t **error )
2117
0
{
2118
0
  libfsapfs_internal_container_t *internal_container = NULL;
2119
0
  static char *function                              = "libfsapfs_container_get_number_of_volumes";
2120
2121
0
  if( container == NULL )
2122
0
  {
2123
0
    libcerror_error_set(
2124
0
     error,
2125
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2126
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2127
0
     "%s: invalid container.",
2128
0
     function );
2129
2130
0
    return( -1 );
2131
0
  }
2132
0
  internal_container = (libfsapfs_internal_container_t *) container;
2133
2134
0
  if( internal_container->superblock == NULL )
2135
0
  {
2136
0
    libcerror_error_set(
2137
0
     error,
2138
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2139
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2140
0
     "%s: invalid container - missing superblock.",
2141
0
     function );
2142
2143
0
    return( -1 );
2144
0
  }
2145
0
  if( number_of_volumes == NULL )
2146
0
  {
2147
0
    libcerror_error_set(
2148
0
     error,
2149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2151
0
     "%s: invalid number of volumes.",
2152
0
     function );
2153
2154
0
    return( -1 );
2155
0
  }
2156
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2157
0
  if( libcthreads_read_write_lock_grab_for_read(
2158
0
       internal_container->read_write_lock,
2159
0
       error ) != 1 )
2160
0
  {
2161
0
    libcerror_error_set(
2162
0
     error,
2163
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2164
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2165
0
     "%s: unable to grab read/write lock for reading.",
2166
0
     function );
2167
2168
0
    return( -1 );
2169
0
  }
2170
0
#endif
2171
0
  *number_of_volumes = internal_container->superblock->number_of_volumes;
2172
2173
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2174
0
  if( libcthreads_read_write_lock_release_for_read(
2175
0
       internal_container->read_write_lock,
2176
0
       error ) != 1 )
2177
0
  {
2178
0
    libcerror_error_set(
2179
0
     error,
2180
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2181
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2182
0
     "%s: unable to release read/write lock for reading.",
2183
0
     function );
2184
2185
0
    return( -1 );
2186
0
  }
2187
0
#endif
2188
0
  return( 1 );
2189
0
}
2190
2191
/* Retrieves a specific of volume
2192
 * The volume reference must be freed after use with libfsapfs_volume_free
2193
 * Returns 1 if successful or -1 on error
2194
 */
2195
int libfsapfs_container_get_volume_by_index(
2196
     libfsapfs_container_t *container,
2197
     int volume_index,
2198
     libfsapfs_volume_t **volume,
2199
     libcerror_error_t **error )
2200
0
{
2201
0
  libfsapfs_internal_container_t *internal_container       = NULL;
2202
0
  libfsapfs_object_map_descriptor_t *object_map_descriptor = NULL;
2203
0
  static char *function                                    = "libfsapfs_container_get_volume_by_index";
2204
0
  off64_t file_offset                                      = 0;
2205
2206
0
  if( container == NULL )
2207
0
  {
2208
0
    libcerror_error_set(
2209
0
     error,
2210
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2211
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2212
0
     "%s: invalid container.",
2213
0
     function );
2214
2215
0
    return( -1 );
2216
0
  }
2217
0
  internal_container = (libfsapfs_internal_container_t *) container;
2218
2219
0
  if( internal_container->superblock == NULL )
2220
0
  {
2221
0
    libcerror_error_set(
2222
0
     error,
2223
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2224
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2225
0
     "%s: invalid container - missing superblock.",
2226
0
     function );
2227
2228
0
    return( -1 );
2229
0
  }
2230
0
  if( ( volume_index < 0 )
2231
0
   || ( volume_index >= (int) internal_container->superblock->number_of_volumes ) )
2232
0
  {
2233
0
    libcerror_error_set(
2234
0
     error,
2235
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2236
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2237
0
     "%s: invalid volume index value out of bounds.",
2238
0
     function );
2239
2240
0
    return( -1 );
2241
0
  }
2242
0
  if( volume == NULL )
2243
0
  {
2244
0
    libcerror_error_set(
2245
0
     error,
2246
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2247
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2248
0
     "%s: invalid volume.",
2249
0
     function );
2250
2251
0
    return( -1 );
2252
0
  }
2253
0
  if( *volume != NULL )
2254
0
  {
2255
0
    libcerror_error_set(
2256
0
     error,
2257
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2258
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2259
0
     "%s: invalid volume value already set.",
2260
0
     function );
2261
2262
0
    return( -1 );
2263
0
  }
2264
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2265
0
  if( libcthreads_read_write_lock_grab_for_read(
2266
0
       internal_container->read_write_lock,
2267
0
       error ) != 1 )
2268
0
  {
2269
0
    libcerror_error_set(
2270
0
     error,
2271
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2272
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2273
0
     "%s: unable to grab read/write lock for reading.",
2274
0
     function );
2275
2276
0
    return( -1 );
2277
0
  }
2278
0
#endif
2279
0
  if( libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
2280
0
       internal_container->object_map_btree,
2281
0
       internal_container->file_io_handle,
2282
0
       internal_container->superblock->volume_object_identifiers[ volume_index ],
2283
0
       internal_container->superblock->object_transaction_identifier,
2284
0
       &object_map_descriptor,
2285
0
       error ) != 1 )
2286
0
  {
2287
0
    libcerror_error_set(
2288
0
     error,
2289
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2290
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2291
0
     "%s: unable to retrieve object map descriptor for volume object identifier: %" PRIu64 " (transaction: %" PRIu64 ").",
2292
0
     function,
2293
0
     internal_container->superblock->volume_object_identifiers[ volume_index ],
2294
0
     internal_container->superblock->object_transaction_identifier );
2295
2296
0
    goto on_error;
2297
0
  }
2298
0
  if( object_map_descriptor == NULL )
2299
0
  {
2300
0
    libcerror_error_set(
2301
0
     error,
2302
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2303
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2304
0
     "%s: invalid object map descriptor.",
2305
0
     function );
2306
2307
0
    goto on_error;
2308
0
  }
2309
0
  if( libfsapfs_volume_initialize(
2310
0
       volume,
2311
0
       internal_container->io_handle,
2312
0
       internal_container->file_io_handle,
2313
0
       internal_container->key_bag,
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_INITIALIZE_FAILED,
2320
0
     "%s: unable to create volume.",
2321
0
     function );
2322
2323
0
    goto on_error;
2324
0
  }
2325
0
  file_offset = (off64_t) ( object_map_descriptor->physical_address * internal_container->io_handle->block_size );
2326
2327
0
  if( libfsapfs_object_map_descriptor_free(
2328
0
       &object_map_descriptor,
2329
0
       error ) != 1 )
2330
0
  {
2331
0
    libcerror_error_set(
2332
0
     error,
2333
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2334
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2335
0
     "%s: unable to free object map descriptor.",
2336
0
     function );
2337
2338
0
    goto on_error;
2339
0
  }
2340
0
  if( libfsapfs_internal_volume_open_read(
2341
0
       (libfsapfs_internal_volume_t *) *volume,
2342
0
       internal_container->file_io_handle,
2343
0
       file_offset,
2344
0
       error ) != 1 )
2345
0
  {
2346
0
    libcerror_error_set(
2347
0
     error,
2348
0
     LIBCERROR_ERROR_DOMAIN_IO,
2349
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
2350
0
     "%s: unable to open volume: %d.",
2351
0
     function,
2352
0
     volume_index );
2353
2354
0
    goto on_error;
2355
0
  }
2356
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2357
0
  if( libcthreads_read_write_lock_release_for_read(
2358
0
       internal_container->read_write_lock,
2359
0
       error ) != 1 )
2360
0
  {
2361
0
    libcerror_error_set(
2362
0
     error,
2363
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2364
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2365
0
     "%s: unable to release read/write lock for reading.",
2366
0
     function );
2367
2368
0
    return( -1 );
2369
0
  }
2370
0
#endif
2371
0
  return( 1 );
2372
2373
0
on_error:
2374
0
  if( object_map_descriptor != NULL )
2375
0
  {
2376
0
    libfsapfs_object_map_descriptor_free(
2377
0
     &object_map_descriptor,
2378
0
     NULL );
2379
0
  }
2380
0
  if( *volume != NULL )
2381
0
  {
2382
0
    libfsapfs_volume_free(
2383
0
     volume,
2384
0
     NULL );
2385
0
  }
2386
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2387
0
  libcthreads_read_write_lock_release_for_read(
2388
0
   internal_container->read_write_lock,
2389
0
   NULL );
2390
0
#endif
2391
0
  return( -1 );
2392
0
}
2393