Coverage Report

Created: 2023-06-07 06:53

/src/libfsapfs/libfsapfs/libfsapfs_object_map_btree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The object map B-tree 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 <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libfsapfs_btree_entry.h"
28
#include "libfsapfs_btree_node.h"
29
#include "libfsapfs_data_block.h"
30
#include "libfsapfs_definitions.h"
31
#include "libfsapfs_io_handle.h"
32
#include "libfsapfs_libbfio.h"
33
#include "libfsapfs_libcerror.h"
34
#include "libfsapfs_libcnotify.h"
35
#include "libfsapfs_libfcache.h"
36
#include "libfsapfs_libfdata.h"
37
#include "libfsapfs_object_map_btree.h"
38
#include "libfsapfs_object_map_descriptor.h"
39
40
#include "fsapfs_object.h"
41
#include "fsapfs_object_map.h"
42
43
/* Creates a object map B-tree
44
 * Make sure the value object_map_btree is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfsapfs_object_map_btree_initialize(
48
     libfsapfs_object_map_btree_t **object_map_btree,
49
     libfsapfs_io_handle_t *io_handle,
50
     libfdata_vector_t *data_block_vector,
51
     uint64_t root_node_block_number,
52
     libcerror_error_t **error )
53
11.6k
{
54
11.6k
  static char *function = "libfsapfs_object_map_btree_initialize";
55
56
11.6k
  if( object_map_btree == NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62
0
     "%s: invalid object map B-tree.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
11.6k
  if( *object_map_btree != NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
72
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
73
0
     "%s: invalid object map B-tree value already set.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
11.6k
  *object_map_btree = memory_allocate_structure(
79
11.6k
                       libfsapfs_object_map_btree_t );
80
81
11.6k
  if( *object_map_btree == NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
86
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
87
0
     "%s: unable to create object map B-tree.",
88
0
     function );
89
90
0
    goto on_error;
91
0
  }
92
11.6k
  if( memory_set(
93
11.6k
       *object_map_btree,
94
11.6k
       0,
95
11.6k
       sizeof( libfsapfs_object_map_btree_t ) ) == NULL )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
100
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
101
0
     "%s: unable to clear object map B-tree.",
102
0
     function );
103
104
0
    memory_free(
105
0
     *object_map_btree );
106
107
0
    *object_map_btree = NULL;
108
109
0
    return( -1 );
110
0
  }
111
11.6k
  if( libfcache_cache_initialize(
112
11.6k
       &( ( *object_map_btree )->data_block_cache ),
113
11.6k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
114
11.6k
       error ) != 1 )
115
0
  {
116
0
    libcerror_error_set(
117
0
     error,
118
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
119
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
120
0
     "%s: unable to create data block cache.",
121
0
     function );
122
123
0
    goto on_error;
124
0
  }
125
11.6k
  if( libfcache_cache_initialize(
126
11.6k
       &( ( *object_map_btree )->node_cache ),
127
11.6k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_BTREE_NODES,
128
11.6k
       error ) != 1 )
129
0
  {
130
0
    libcerror_error_set(
131
0
     error,
132
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
133
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
134
0
     "%s: unable to create node cache.",
135
0
     function );
136
137
0
    goto on_error;
138
0
  }
139
11.6k
  ( *object_map_btree )->io_handle              = io_handle;
140
11.6k
  ( *object_map_btree )->data_block_vector      = data_block_vector;
141
11.6k
  ( *object_map_btree )->root_node_block_number = root_node_block_number;
142
143
11.6k
  return( 1 );
144
145
0
on_error:
146
0
  if( *object_map_btree != NULL )
147
0
  {
148
0
    memory_free(
149
0
     *object_map_btree );
150
151
0
    *object_map_btree = NULL;
152
0
  }
153
0
  return( -1 );
154
11.6k
}
155
156
/* Frees a object map B-tree
157
 * Returns 1 if successful or -1 on error
158
 */
159
int libfsapfs_object_map_btree_free(
160
     libfsapfs_object_map_btree_t **object_map_btree,
161
     libcerror_error_t **error )
162
11.6k
{
163
11.6k
  static char *function = "libfsapfs_object_map_btree_free";
164
11.6k
  int result            = 1;
165
166
11.6k
  if( object_map_btree == NULL )
167
0
  {
168
0
    libcerror_error_set(
169
0
     error,
170
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
171
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
172
0
     "%s: invalid object map B-tree.",
173
0
     function );
174
175
0
    return( -1 );
176
0
  }
177
11.6k
  if( *object_map_btree != NULL )
178
11.6k
  {
179
    /* The data_block_vector is referenced and freed elsewhere
180
     */
181
11.6k
    if( libfcache_cache_free(
182
11.6k
         &( ( *object_map_btree )->node_cache ),
183
11.6k
         error ) != 1 )
184
0
    {
185
0
      libcerror_error_set(
186
0
       error,
187
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
188
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
189
0
       "%s: unable to free node cache.",
190
0
       function );
191
192
0
      result = -1;
193
0
    }
194
11.6k
    if( libfcache_cache_free(
195
11.6k
         &( ( *object_map_btree )->data_block_cache ),
196
11.6k
         error ) != 1 )
197
0
    {
198
0
      libcerror_error_set(
199
0
       error,
200
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
201
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
202
0
       "%s: unable to free data block cache.",
203
0
       function );
204
205
0
      result = -1;
206
0
    }
207
11.6k
    memory_free(
208
11.6k
     *object_map_btree );
209
210
11.6k
    *object_map_btree = NULL;
211
11.6k
  }
212
11.6k
  return( result );
213
11.6k
}
214
215
/* Retrieves the object map B-tree root node
216
 * Returns 1 if successful or -1 on error
217
 */
218
int libfsapfs_object_map_btree_get_root_node(
219
     libfsapfs_object_map_btree_t *object_map_btree,
220
     libbfio_handle_t *file_io_handle,
221
     uint64_t root_node_block_number,
222
     libfsapfs_btree_node_t **root_node,
223
     libcerror_error_t **error )
224
11.9k
{
225
11.9k
  libfcache_cache_value_t *cache_value = NULL;
226
11.9k
  libfsapfs_btree_node_t *node         = NULL;
227
11.9k
  libfsapfs_data_block_t *data_block   = NULL;
228
11.9k
  static char *function                = "libfsapfs_object_map_btree_get_root_node";
229
11.9k
  int result                           = 0;
230
231
#if defined( HAVE_PROFILER )
232
  int64_t profiler_start_timestamp     = 0;
233
#endif
234
235
11.9k
  if( object_map_btree == NULL )
236
0
  {
237
0
    libcerror_error_set(
238
0
     error,
239
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
241
0
     "%s: invalid object map B-tree.",
242
0
     function );
243
244
0
    return( -1 );
245
0
  }
246
11.9k
  if( root_node_block_number > (uint64_t) INT_MAX )
247
327
  {
248
327
    libcerror_error_set(
249
327
     error,
250
327
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
251
327
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
252
327
     "%s: invalid root node block number value out of bounds.",
253
327
     function );
254
255
327
    return( -1 );
256
327
  }
257
11.5k
  if( root_node == NULL )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
263
0
     "%s: invalid root node.",
264
0
     function );
265
266
0
    return( -1 );
267
0
  }
268
#if defined( HAVE_PROFILER )
269
  if( object_map_btree->io_handle->profiler != NULL )
270
  {
271
    if( libfsapfs_profiler_start_timing(
272
         object_map_btree->io_handle->profiler,
273
         &profiler_start_timestamp,
274
         error ) != 1 )
275
    {
276
      libcerror_error_set(
277
       error,
278
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
279
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
280
       "%s: unable to start timing.",
281
       function );
282
283
      goto on_error;
284
    }
285
  }
286
#endif /* defined( HAVE_PROFILER ) */
287
288
11.5k
  result = libfcache_cache_get_value_by_identifier(
289
11.5k
            object_map_btree->node_cache,
290
11.5k
            0,
291
11.5k
            (off64_t) root_node_block_number,
292
11.5k
            0,
293
11.5k
            &cache_value,
294
11.5k
            error );
295
296
11.5k
  if( result == -1 )
297
0
  {
298
0
    libcerror_error_set(
299
0
     error,
300
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
301
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
302
0
     "%s: unable to retrieve value from cache.",
303
0
     function );
304
305
0
    goto on_error;
306
0
  }
307
11.5k
  else if( result == 0 )
308
10.0k
  {
309
10.0k
    if( libfdata_vector_get_element_value_by_index(
310
10.0k
         object_map_btree->data_block_vector,
311
10.0k
         (intptr_t *) file_io_handle,
312
10.0k
         (libfdata_cache_t *) object_map_btree->data_block_cache,
313
10.0k
         (int) root_node_block_number,
314
10.0k
         (intptr_t **) &data_block,
315
10.0k
         0,
316
10.0k
         error ) != 1 )
317
372
    {
318
372
      libcerror_error_set(
319
372
       error,
320
372
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
321
372
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
322
372
       "%s: unable to retrieve data block: %" PRIu64 ".",
323
372
       function,
324
372
       root_node_block_number );
325
326
372
      goto on_error;
327
372
    }
328
9.70k
    if( data_block == NULL )
329
0
    {
330
0
      libcerror_error_set(
331
0
       error,
332
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
334
0
       "%s: invalid data block: %" PRIu64 ".",
335
0
       function,
336
0
       root_node_block_number );
337
338
0
      goto on_error;
339
0
    }
340
9.70k
    if( libfsapfs_btree_node_initialize(
341
9.70k
         &node,
342
9.70k
         error ) != 1 )
343
0
    {
344
0
      libcerror_error_set(
345
0
       error,
346
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
347
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
348
0
       "%s: unable to create B-tree node.",
349
0
       function );
350
351
0
      goto on_error;
352
0
    }
353
9.70k
    if( libfsapfs_btree_node_read_data(
354
9.70k
         node,
355
9.70k
         data_block->data,
356
9.70k
         data_block->data_size,
357
9.70k
         error ) != 1 )
358
708
    {
359
708
      libcerror_error_set(
360
708
       error,
361
708
       LIBCERROR_ERROR_DOMAIN_IO,
362
708
       LIBCERROR_IO_ERROR_READ_FAILED,
363
708
       "%s: unable to read B-tree node.",
364
708
       function );
365
366
708
      goto on_error;
367
708
    }
368
8.99k
    if( node->object_type != 0x40000002UL )
369
114
    {
370
114
      libcerror_error_set(
371
114
       error,
372
114
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
373
114
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
374
114
       "%s: invalid object type: 0x%08" PRIx32 ".",
375
114
       function,
376
114
       node->object_type );
377
378
114
      goto on_error;
379
114
    }
380
8.88k
    if( node->object_subtype != 0x0000000bUL )
381
165
    {
382
165
      libcerror_error_set(
383
165
       error,
384
165
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
165
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
386
165
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
387
165
       function,
388
165
       node->object_subtype );
389
390
165
      goto on_error;
391
165
    }
392
8.71k
    if( ( ( node->node_header->flags & 0x0001 ) == 0 )
393
8.71k
     || ( ( node->node_header->flags & 0x0004 ) == 0 ) )
394
7
    {
395
7
      libcerror_error_set(
396
7
       error,
397
7
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
7
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
399
7
       "%s: unsupported flags: 0x%04" PRIx16 ".",
400
7
       function,
401
7
       node->node_header->flags );
402
403
7
      goto on_error;
404
7
    }
405
8.71k
    if( node->footer->node_size != 4096 )
406
168
    {
407
168
      libcerror_error_set(
408
168
       error,
409
168
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
410
168
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
411
168
       "%s: invalid node size value out of bounds.",
412
168
       function );
413
414
168
      goto on_error;
415
168
    }
416
8.54k
    if( node->footer->key_size != sizeof( fsapfs_object_map_btree_key_t ) )
417
144
    {
418
144
      libcerror_error_set(
419
144
       error,
420
144
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
421
144
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
422
144
       "%s: invalid key size value out of bounds.",
423
144
       function );
424
425
144
      goto on_error;
426
144
    }
427
8.39k
    if( node->footer->value_size != sizeof( fsapfs_object_map_btree_value_t ) )
428
122
    {
429
122
      libcerror_error_set(
430
122
       error,
431
122
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
432
122
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
433
122
       "%s: invalid value size value out of bounds.",
434
122
       function );
435
436
122
      goto on_error;
437
122
    }
438
8.27k
    if( libfcache_cache_set_value_by_identifier(
439
8.27k
         object_map_btree->node_cache,
440
8.27k
         0,
441
8.27k
         (off64_t) root_node_block_number,
442
8.27k
         0,
443
8.27k
         (intptr_t *) node,
444
8.27k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
445
8.27k
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
446
8.27k
         error ) != 1 )
447
0
    {
448
0
      libcerror_error_set(
449
0
       error,
450
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
451
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
452
0
       "%s: unable to set value in cache.",
453
0
       function );
454
455
0
      goto on_error;
456
0
    }
457
8.27k
    node = NULL;
458
459
8.27k
    if( libfcache_cache_get_value_by_identifier(
460
8.27k
         object_map_btree->node_cache,
461
8.27k
         0,
462
8.27k
         (off64_t) root_node_block_number,
463
8.27k
         0,
464
8.27k
         &cache_value,
465
8.27k
         error ) != 1 )
466
0
    {
467
0
      libcerror_error_set(
468
0
       error,
469
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
470
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
471
0
       "%s: unable to retrieve value from cache.",
472
0
       function );
473
474
0
      goto on_error;
475
0
    }
476
8.27k
  }
477
#if defined( HAVE_PROFILER )
478
  if( object_map_btree->io_handle->profiler != NULL )
479
  {
480
    if( libfsapfs_profiler_stop_timing(
481
         object_map_btree->io_handle->profiler,
482
         profiler_start_timestamp,
483
         function,
484
         root_node_block_number * object_map_btree->io_handle->block_size,
485
         object_map_btree->io_handle->block_size,
486
         error ) != 1 )
487
    {
488
      libcerror_error_set(
489
       error,
490
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
491
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
492
       "%s: unable to stop timing.",
493
       function );
494
495
      goto on_error;
496
    }
497
  }
498
#endif /* defined( HAVE_PROFILER ) */
499
500
9.79k
  if( libfcache_cache_value_get_value(
501
9.79k
       cache_value,
502
9.79k
       (intptr_t **) root_node,
503
9.79k
       error ) != 1 )
504
0
  {
505
0
    libcerror_error_set(
506
0
     error,
507
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
508
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
509
0
     "%s: unable to retrieve root node.",
510
0
     function );
511
512
0
    goto on_error;
513
0
  }
514
9.79k
  return( 1 );
515
516
1.80k
on_error:
517
1.80k
  if( node != NULL )
518
1.42k
  {
519
1.42k
    libfsapfs_btree_node_free(
520
1.42k
     &node,
521
1.42k
     NULL );
522
1.42k
  }
523
1.80k
  return( -1 );
524
9.79k
}
525
526
/* Retrieves a object map B-tree sub node
527
 * Returns 1 if successful or -1 on error
528
 */
529
int libfsapfs_object_map_btree_get_sub_node(
530
     libfsapfs_object_map_btree_t *object_map_btree,
531
     libbfio_handle_t *file_io_handle,
532
     uint64_t sub_node_block_number,
533
     libfsapfs_btree_node_t **sub_node,
534
     libcerror_error_t **error )
535
1.28k
{
536
1.28k
  libfcache_cache_value_t *cache_value = NULL;
537
1.28k
  libfsapfs_btree_node_t *node         = NULL;
538
1.28k
  libfsapfs_data_block_t *data_block   = NULL;
539
1.28k
  static char *function                = "libfsapfs_object_map_btree_get_sub_node";
540
1.28k
  int result                           = 0;
541
542
#if defined( HAVE_PROFILER )
543
  int64_t profiler_start_timestamp     = 0;
544
#endif
545
546
1.28k
  if( object_map_btree == NULL )
547
0
  {
548
0
    libcerror_error_set(
549
0
     error,
550
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
551
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
552
0
     "%s: invalid object map B-tree.",
553
0
     function );
554
555
0
    return( -1 );
556
0
  }
557
1.28k
  if( sub_node_block_number > (uint64_t) INT_MAX )
558
230
  {
559
230
    libcerror_error_set(
560
230
     error,
561
230
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
230
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
563
230
     "%s: invalid sub node block number value out of bounds.",
564
230
     function );
565
566
230
    return( -1 );
567
230
  }
568
1.05k
  if( sub_node == NULL )
569
0
  {
570
0
    libcerror_error_set(
571
0
     error,
572
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
573
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
574
0
     "%s: invalid sub node.",
575
0
     function );
576
577
0
    return( -1 );
578
0
  }
579
#if defined( HAVE_PROFILER )
580
  if( object_map_btree->io_handle->profiler != NULL )
581
  {
582
    if( libfsapfs_profiler_start_timing(
583
         object_map_btree->io_handle->profiler,
584
         &profiler_start_timestamp,
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 start timing.",
592
       function );
593
594
      goto on_error;
595
    }
596
  }
597
#endif /* defined( HAVE_PROFILER ) */
598
599
1.05k
  result = libfcache_cache_get_value_by_identifier(
600
1.05k
            object_map_btree->node_cache,
601
1.05k
            0,
602
1.05k
            (off64_t) sub_node_block_number,
603
1.05k
            0,
604
1.05k
            &cache_value,
605
1.05k
            error );
606
607
1.05k
  if( result == -1 )
608
0
  {
609
0
    libcerror_error_set(
610
0
     error,
611
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
612
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
613
0
     "%s: unable to retrieve value from cache.",
614
0
     function );
615
616
0
    goto on_error;
617
0
  }
618
1.05k
  else if( result == 0 )
619
279
  {
620
279
    if( libfdata_vector_get_element_value_by_index(
621
279
         object_map_btree->data_block_vector,
622
279
         (intptr_t *) file_io_handle,
623
279
         (libfdata_cache_t *) object_map_btree->data_block_cache,
624
279
         (int) sub_node_block_number,
625
279
         (intptr_t **) &data_block,
626
279
         0,
627
279
         error ) != 1 )
628
144
    {
629
144
      libcerror_error_set(
630
144
       error,
631
144
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
632
144
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
633
144
       "%s: unable to retrieve data block: %" PRIu64 ".",
634
144
       function,
635
144
       sub_node_block_number );
636
637
144
      goto on_error;
638
144
    }
639
135
    if( data_block == NULL )
640
0
    {
641
0
      libcerror_error_set(
642
0
       error,
643
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
644
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
645
0
       "%s: invalid data block: %" PRIu64 ".",
646
0
       function,
647
0
       sub_node_block_number );
648
649
0
      goto on_error;
650
0
    }
651
135
    if( libfsapfs_btree_node_initialize(
652
135
         &node,
653
135
         error ) != 1 )
654
0
    {
655
0
      libcerror_error_set(
656
0
       error,
657
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
658
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
659
0
       "%s: unable to create B-tree node.",
660
0
       function );
661
662
0
      goto on_error;
663
0
    }
664
135
    if( libfsapfs_btree_node_read_data(
665
135
         node,
666
135
         data_block->data,
667
135
         data_block->data_size,
668
135
         error ) != 1 )
669
16
    {
670
16
      libcerror_error_set(
671
16
       error,
672
16
       LIBCERROR_ERROR_DOMAIN_IO,
673
16
       LIBCERROR_IO_ERROR_READ_FAILED,
674
16
       "%s: unable to read B-tree node.",
675
16
       function );
676
677
16
      goto on_error;
678
16
    }
679
119
    if( node->object_type != 0x40000003UL )
680
37
    {
681
37
      libcerror_error_set(
682
37
       error,
683
37
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
684
37
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
685
37
       "%s: invalid object type: 0x%08" PRIx32 ".",
686
37
       function,
687
37
       node->object_type );
688
689
37
      goto on_error;
690
37
    }
691
82
    if( node->object_subtype != 0x0000000bUL )
692
74
    {
693
74
      libcerror_error_set(
694
74
       error,
695
74
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
696
74
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
697
74
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
698
74
       function,
699
74
       node->object_subtype );
700
701
74
      goto on_error;
702
74
    }
703
8
    if( ( ( node->node_header->flags & 0x0001 ) != 0 )
704
8
     || ( ( node->node_header->flags & 0x0004 ) == 0 ) )
705
6
    {
706
6
      libcerror_error_set(
707
6
       error,
708
6
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
709
6
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
710
6
       "%s: unsupported flags: 0x%04" PRIx16 ".",
711
6
       function,
712
6
       node->node_header->flags );
713
714
6
      goto on_error;
715
6
    }
716
2
    if( libfcache_cache_set_value_by_identifier(
717
2
         object_map_btree->node_cache,
718
2
         0,
719
2
         (off64_t) sub_node_block_number,
720
2
         0,
721
2
         (intptr_t *) node,
722
2
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
723
2
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
724
2
         error ) != 1 )
725
0
    {
726
0
      libcerror_error_set(
727
0
       error,
728
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
729
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
730
0
       "%s: unable to set value in cache.",
731
0
       function );
732
733
0
      goto on_error;
734
0
    }
735
2
    node = NULL;
736
737
2
    if( libfcache_cache_get_value_by_identifier(
738
2
         object_map_btree->node_cache,
739
2
         0,
740
2
         (off64_t) sub_node_block_number,
741
2
         0,
742
2
         &cache_value,
743
2
         error ) != 1 )
744
0
    {
745
0
      libcerror_error_set(
746
0
       error,
747
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
748
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
749
0
       "%s: unable to retrieve value from cache.",
750
0
       function );
751
752
0
      goto on_error;
753
0
    }
754
2
  }
755
#if defined( HAVE_PROFILER )
756
  if( object_map_btree->io_handle->profiler != NULL )
757
  {
758
    if( libfsapfs_profiler_stop_timing(
759
         object_map_btree->io_handle->profiler,
760
         profiler_start_timestamp,
761
         function,
762
         sub_node_block_number * object_map_btree->io_handle->block_size,
763
         object_map_btree->io_handle->block_size,
764
         error ) != 1 )
765
    {
766
      libcerror_error_set(
767
       error,
768
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
769
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
770
       "%s: unable to stop timing.",
771
       function );
772
773
      goto on_error;
774
    }
775
  }
776
#endif /* defined( HAVE_PROFILER ) */
777
778
773
  if( libfcache_cache_value_get_value(
779
773
       cache_value,
780
773
       (intptr_t **) sub_node,
781
773
       error ) != 1 )
782
0
  {
783
0
    libcerror_error_set(
784
0
     error,
785
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
786
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
787
0
     "%s: unable to retrieve sub node.",
788
0
     function );
789
790
0
    goto on_error;
791
0
  }
792
773
  return( 1 );
793
794
277
on_error:
795
277
  if( node != NULL )
796
133
  {
797
133
    libfsapfs_btree_node_free(
798
133
     &node,
799
133
     NULL );
800
133
  }
801
277
  return( -1 );
802
773
}
803
804
/* Retrieves an entry for a specific identifier from the object map B-tree node
805
 * Returns 1 if successful, 0 if not found or -1 on error
806
 */
807
int libfsapfs_object_map_btree_get_entry_from_node_by_identifier(
808
     libfsapfs_object_map_btree_t *object_map_btree,
809
     libfsapfs_btree_node_t *node,
810
     uint64_t object_identifier,
811
     libfsapfs_btree_entry_t **btree_entry,
812
     libcerror_error_t **error )
813
10.5k
{
814
10.5k
  libfsapfs_btree_entry_t *entry          = NULL;
815
10.5k
  libfsapfs_btree_entry_t *previous_entry = NULL;
816
10.5k
  static char *function                   = "libfsapfs_object_map_btree_get_entry_from_node_by_identifier";
817
10.5k
  uint64_t object_map_identifier          = 0;
818
10.5k
  int btree_entry_index                   = 0;
819
10.5k
  int is_leaf_node                        = 0;
820
10.5k
  int number_of_entries                   = 0;
821
822
10.5k
  if( object_map_btree == NULL )
823
0
  {
824
0
    libcerror_error_set(
825
0
     error,
826
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
827
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
828
0
     "%s: invalid object map B-tree.",
829
0
     function );
830
831
0
    return( -1 );
832
0
  }
833
10.5k
  if( btree_entry == NULL )
834
0
  {
835
0
    libcerror_error_set(
836
0
     error,
837
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
838
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
839
0
     "%s: invalid B-tree entry.",
840
0
     function );
841
842
0
    return( -1 );
843
0
  }
844
#if defined( HAVE_DEBUG_OUTPUT )
845
  if( libcnotify_verbose != 0 )
846
  {
847
    libcnotify_printf(
848
     "%s: retrieving B-tree entry identifier: %" PRIu64 ".\n",
849
     function,
850
     object_identifier );
851
  }
852
#endif
853
10.5k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
854
10.5k
                  node,
855
10.5k
                  error );
856
857
10.5k
  if( is_leaf_node == -1 )
858
0
  {
859
0
    libcerror_error_set(
860
0
     error,
861
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
862
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
863
0
     "%s: unable to determine if B-tree node is a leaf node.",
864
0
     function );
865
866
0
    return( -1 );
867
0
  }
868
10.5k
  if( libfsapfs_btree_node_get_number_of_entries(
869
10.5k
       node,
870
10.5k
       &number_of_entries,
871
10.5k
       error ) != 1 )
872
0
  {
873
0
    libcerror_error_set(
874
0
     error,
875
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
876
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
877
0
     "%s: unable to retrieve number of entries from B-tree node.",
878
0
     function );
879
880
0
    return( -1 );
881
0
  }
882
10.5k
  for( btree_entry_index = 0;
883
24.7k
       btree_entry_index < number_of_entries;
884
14.2k
       btree_entry_index++ )
885
23.9k
  {
886
23.9k
    if( libfsapfs_btree_node_get_entry_by_index(
887
23.9k
         node,
888
23.9k
         btree_entry_index,
889
23.9k
         &entry,
890
23.9k
         error ) != 1 )
891
0
    {
892
0
      libcerror_error_set(
893
0
       error,
894
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
895
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
896
0
       "%s: unable to retrieve number of entries from B-tree node.",
897
0
       function );
898
899
0
      return( -1 );
900
0
    }
901
23.9k
    if( entry == NULL )
902
0
    {
903
0
      libcerror_error_set(
904
0
       error,
905
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
906
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
907
0
       "%s: invalid B-tree entry: %d.",
908
0
       function,
909
0
       btree_entry_index );
910
911
0
      return( -1 );
912
0
    }
913
23.9k
    if( entry->key_data == 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 B-tree entry: %d - missing key data.",
920
0
       function,
921
0
       btree_entry_index );
922
923
0
      return( -1 );
924
0
    }
925
23.9k
    if( entry->key_data_size < 8 )
926
0
    {
927
0
      libcerror_error_set(
928
0
       error,
929
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
930
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
931
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
932
0
       function,
933
0
       btree_entry_index );
934
935
0
      return( -1 );
936
0
    }
937
23.9k
    byte_stream_copy_to_uint64_little_endian(
938
23.9k
     entry->key_data,
939
23.9k
     object_map_identifier );
940
941
#if defined( HAVE_DEBUG_OUTPUT )
942
    if( libcnotify_verbose != 0 )
943
    {
944
      libcnotify_printf(
945
       "%s: B-tree entry: %d, identifier: %" PRIu64 "\n",
946
       function,
947
       btree_entry_index,
948
       object_map_identifier );
949
    }
950
#endif
951
23.9k
    if( object_map_identifier > object_identifier )
952
629
    {
953
629
      break;
954
629
    }
955
23.3k
    if( is_leaf_node != 0 )
956
15.5k
    {
957
15.5k
      if( object_map_identifier == object_identifier )
958
8.83k
      {
959
8.83k
        *btree_entry = entry;
960
961
8.83k
        return( 1 );
962
8.83k
      }
963
15.5k
    }
964
7.77k
    else
965
7.77k
    {
966
7.77k
      if( object_map_identifier >= object_identifier )
967
278
      {
968
278
        if( ( previous_entry == NULL )
969
278
         || ( object_map_identifier == object_identifier ) )
970
278
        {
971
278
          previous_entry = entry;
972
278
        }
973
278
        *btree_entry = previous_entry;
974
975
278
        return( 1 );
976
278
      }
977
7.50k
      previous_entry = entry;
978
7.50k
    }
979
23.3k
  }
980
1.45k
  if( is_leaf_node == 0 )
981
1.02k
  {
982
1.02k
    *btree_entry = previous_entry;
983
984
1.02k
    return( 1 );
985
1.02k
  }
986
424
  return( 0 );
987
1.45k
}
988
989
/* Retrieves an entry for a specific identifier from the object map B-tree
990
 * Returns 1 if successful, 0 if not found or -1 on error
991
 */
992
int libfsapfs_object_map_btree_get_entry_by_identifier(
993
     libfsapfs_object_map_btree_t *object_map_btree,
994
     libbfio_handle_t *file_io_handle,
995
     uint64_t object_identifier,
996
     libfsapfs_btree_node_t **btree_node,
997
     libfsapfs_btree_entry_t **btree_entry,
998
     libcerror_error_t **error )
999
11.9k
{
1000
11.9k
  libfsapfs_btree_entry_t *entry = NULL;
1001
11.9k
  libfsapfs_btree_node_t *node   = NULL;
1002
11.9k
  static char *function          = "libfsapfs_object_map_btree_get_entry_by_identifier";
1003
11.9k
  uint64_t sub_node_block_number = 0;
1004
11.9k
  int is_leaf_node               = 0;
1005
11.9k
  int recursion_depth            = 0;
1006
11.9k
  int result                     = 0;
1007
1008
11.9k
  if( object_map_btree == NULL )
1009
0
  {
1010
0
    libcerror_error_set(
1011
0
     error,
1012
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1013
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1014
0
     "%s: invalid object map B-tree.",
1015
0
     function );
1016
1017
0
    return( -1 );
1018
0
  }
1019
11.9k
  if( btree_node == NULL )
1020
0
  {
1021
0
    libcerror_error_set(
1022
0
     error,
1023
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1024
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1025
0
     "%s: invalid B-tree node.",
1026
0
     function );
1027
1028
0
    return( -1 );
1029
0
  }
1030
11.9k
  if( btree_entry == NULL )
1031
0
  {
1032
0
    libcerror_error_set(
1033
0
     error,
1034
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1035
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1036
0
     "%s: invalid B-tree entry.",
1037
0
     function );
1038
1039
0
    return( -1 );
1040
0
  }
1041
11.9k
  if( libfsapfs_object_map_btree_get_root_node(
1042
11.9k
       object_map_btree,
1043
11.9k
       file_io_handle,
1044
11.9k
       object_map_btree->root_node_block_number,
1045
11.9k
       &node,
1046
11.9k
       error ) != 1 )
1047
2.12k
  {
1048
2.12k
    libcerror_error_set(
1049
2.12k
     error,
1050
2.12k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1051
2.12k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1052
2.12k
     "%s: unable to retrieve B-tree root node.",
1053
2.12k
     function );
1054
1055
2.12k
    return( -1 );
1056
2.12k
  }
1057
9.79k
  do
1058
10.5k
  {
1059
10.5k
    if( ( recursion_depth < 0 )
1060
10.5k
     || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1061
3
    {
1062
3
      libcerror_error_set(
1063
3
       error,
1064
3
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1065
3
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1066
3
       "%s: invalid recursion depth value out of bounds.",
1067
3
       function );
1068
1069
3
      return( -1 );
1070
3
    }
1071
10.5k
    is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1072
10.5k
                    node,
1073
10.5k
                    error );
1074
1075
10.5k
    if( is_leaf_node == -1 )
1076
0
    {
1077
0
      libcerror_error_set(
1078
0
       error,
1079
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1080
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1081
0
       "%s: unable to determine if B-tree node is a leaf node.",
1082
0
       function );
1083
1084
0
      return( -1 );
1085
0
    }
1086
10.5k
    result = libfsapfs_object_map_btree_get_entry_from_node_by_identifier(
1087
10.5k
              object_map_btree,
1088
10.5k
              node,
1089
10.5k
              object_identifier,
1090
10.5k
              &entry,
1091
10.5k
              error );
1092
1093
10.5k
    if( result == -1 )
1094
0
    {
1095
0
      libcerror_error_set(
1096
0
       error,
1097
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1098
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1099
0
       "%s: unable to retrieve entry from B-tree node.",
1100
0
       function );
1101
1102
0
      return( -1 );
1103
0
    }
1104
10.5k
    else if( result == 0 )
1105
424
    {
1106
424
      break;
1107
424
    }
1108
10.1k
    if( is_leaf_node != 0 )
1109
8.83k
    {
1110
8.83k
      *btree_node  = node;
1111
8.83k
      *btree_entry = entry;
1112
1113
8.83k
      return( 1 );
1114
8.83k
    }
1115
1.30k
    if( entry == NULL )
1116
24
    {
1117
24
      libcerror_error_set(
1118
24
       error,
1119
24
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1120
24
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1121
24
       "%s: invalid B-tree entry.",
1122
24
       function );
1123
1124
24
      return( -1 );
1125
24
    }
1126
1.28k
    if( entry->value_data == NULL )
1127
0
    {
1128
0
      libcerror_error_set(
1129
0
       error,
1130
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1131
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1132
0
       "%s: invalid B-tree entry - missing value data.",
1133
0
       function );
1134
1135
0
      return( -1 );
1136
0
    }
1137
1.28k
    if( entry->value_data_size != 8 )
1138
0
    {
1139
0
      libcerror_error_set(
1140
0
       error,
1141
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1142
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1143
0
       "%s: invalid B-tree entry - unsupported value data size.",
1144
0
       function );
1145
1146
0
      return( -1 );
1147
0
    }
1148
1.28k
    byte_stream_copy_to_uint64_little_endian(
1149
1.28k
     entry->value_data,
1150
1.28k
     sub_node_block_number );
1151
1152
#if defined( HAVE_DEBUG_OUTPUT )
1153
    if( libcnotify_verbose != 0 )
1154
    {
1155
      libcnotify_printf(
1156
       "%s: B-tree sub node block number: %" PRIu64 "\n",
1157
       function,
1158
       sub_node_block_number );
1159
    }
1160
#endif
1161
1.28k
    node = NULL;
1162
1163
1.28k
    if( libfsapfs_object_map_btree_get_sub_node(
1164
1.28k
         object_map_btree,
1165
1.28k
         file_io_handle,
1166
1.28k
         sub_node_block_number,
1167
1.28k
         &node,
1168
1.28k
         error ) != 1 )
1169
507
    {
1170
507
      libcerror_error_set(
1171
507
       error,
1172
507
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1173
507
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1174
507
       "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1175
507
       function,
1176
507
       sub_node_block_number );
1177
1178
507
      return( -1 );
1179
507
    }
1180
773
    recursion_depth++;
1181
773
  }
1182
9.79k
  while( is_leaf_node == 0 );
1183
1184
424
  return( 0 );
1185
9.79k
}
1186
1187
/* Retrieves the object map descriptor of a specific object identifier
1188
 * Returns 1 if successful, 0 if no such value or -1 on error
1189
 */
1190
int libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
1191
     libfsapfs_object_map_btree_t *object_map_btree,
1192
     libbfio_handle_t *file_io_handle,
1193
     uint64_t object_identifier,
1194
     libfsapfs_object_map_descriptor_t **descriptor,
1195
     libcerror_error_t **error )
1196
11.9k
{
1197
11.9k
  libfsapfs_btree_entry_t *entry                     = NULL;
1198
11.9k
  libfsapfs_btree_node_t *node                       = NULL;
1199
11.9k
  libfsapfs_object_map_descriptor_t *safe_descriptor = NULL;
1200
11.9k
  static char *function                              = "libfsapfs_object_map_btree_get_descriptor_by_object_identifier";
1201
11.9k
  int result                                         = 0;
1202
1203
11.9k
  if( object_map_btree == NULL )
1204
0
  {
1205
0
    libcerror_error_set(
1206
0
     error,
1207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1208
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1209
0
     "%s: invalid object map B-tree.",
1210
0
     function );
1211
1212
0
    return( -1 );
1213
0
  }
1214
11.9k
  if( descriptor == NULL )
1215
0
  {
1216
0
    libcerror_error_set(
1217
0
     error,
1218
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1219
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1220
0
     "%s: invalid descriptor.",
1221
0
     function );
1222
1223
0
    return( -1 );
1224
0
  }
1225
11.9k
  if( *descriptor != NULL )
1226
0
  {
1227
0
    libcerror_error_set(
1228
0
     error,
1229
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1230
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1231
0
     "%s: invalid descriptor value already set.",
1232
0
     function );
1233
1234
0
    return( -1 );
1235
0
  }
1236
11.9k
  result = libfsapfs_object_map_btree_get_entry_by_identifier(
1237
11.9k
            object_map_btree,
1238
11.9k
            file_io_handle,
1239
11.9k
            object_identifier,
1240
11.9k
            &node,
1241
11.9k
            &entry,
1242
11.9k
            error );
1243
1244
11.9k
  if( result == -1 )
1245
2.66k
  {
1246
2.66k
    libcerror_error_set(
1247
2.66k
     error,
1248
2.66k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1249
2.66k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1250
2.66k
     "%s: unable to retrieve entry from B-tree.",
1251
2.66k
     function );
1252
1253
2.66k
    goto on_error;
1254
2.66k
  }
1255
9.25k
  else if( result != 0 )
1256
8.83k
  {
1257
8.83k
    if( node == NULL )
1258
0
    {
1259
0
      libcerror_error_set(
1260
0
       error,
1261
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1262
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1263
0
       "%s: invalid B-tree node.",
1264
0
       function );
1265
1266
0
      goto on_error;
1267
0
    }
1268
8.83k
    if( entry == NULL )
1269
0
    {
1270
0
      libcerror_error_set(
1271
0
       error,
1272
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1273
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1274
0
       "%s: invalid B-tree entry.",
1275
0
       function );
1276
1277
0
      goto on_error;
1278
0
    }
1279
8.83k
    if( libfsapfs_object_map_descriptor_initialize(
1280
8.83k
         &safe_descriptor,
1281
8.83k
         error ) != 1 )
1282
0
    {
1283
0
      libcerror_error_set(
1284
0
       error,
1285
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1286
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1287
0
       "%s: unable to create object map descriptor.",
1288
0
       function );
1289
1290
0
      goto on_error;
1291
0
    }
1292
8.83k
    if( libfsapfs_object_map_descriptor_read_key_data(
1293
8.83k
         safe_descriptor,
1294
8.83k
         entry->key_data,
1295
8.83k
         (size_t) entry->key_data_size,
1296
8.83k
         error ) != 1 )
1297
0
    {
1298
0
      libcerror_error_set(
1299
0
       error,
1300
0
       LIBCERROR_ERROR_DOMAIN_IO,
1301
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1302
0
       "%s: unable to read object map descriptor key data.",
1303
0
       function );
1304
1305
0
      goto on_error;
1306
0
    }
1307
8.83k
    if( libfsapfs_object_map_descriptor_read_value_data(
1308
8.83k
         safe_descriptor,
1309
8.83k
         entry->value_data,
1310
8.83k
         (size_t) entry->value_data_size,
1311
8.83k
         error ) != 1 )
1312
0
    {
1313
0
      libcerror_error_set(
1314
0
       error,
1315
0
       LIBCERROR_ERROR_DOMAIN_IO,
1316
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1317
0
       "%s: unable to read object map descriptor value data.",
1318
0
       function );
1319
1320
0
      goto on_error;
1321
0
    }
1322
8.83k
    node = NULL;
1323
8.83k
  }
1324
9.25k
  *descriptor = safe_descriptor;
1325
1326
9.25k
  return( result );
1327
1328
2.66k
on_error:
1329
2.66k
  if( safe_descriptor != NULL )
1330
0
  {
1331
0
    libfsapfs_object_map_descriptor_free(
1332
0
     &safe_descriptor,
1333
0
     NULL );
1334
0
  }
1335
2.66k
  return( -1 );
1336
11.9k
}
1337