Coverage Report

Created: 2025-12-05 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsapfs/libfsapfs/libfsapfs_object_map_btree.c
Line
Count
Source
1
/*
2
 * The object map B-tree functions
3
 *
4
 * Copyright (C) 2018-2025, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <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
7.73k
{
54
7.73k
  static char *function = "libfsapfs_object_map_btree_initialize";
55
56
7.73k
  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
7.73k
  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
7.73k
  *object_map_btree = memory_allocate_structure(
79
7.73k
                       libfsapfs_object_map_btree_t );
80
81
7.73k
  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
7.73k
  if( memory_set(
93
7.73k
       *object_map_btree,
94
7.73k
       0,
95
7.73k
       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
7.73k
  if( libfcache_cache_initialize(
112
7.73k
       &( ( *object_map_btree )->data_block_cache ),
113
7.73k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
114
7.73k
       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
7.73k
  if( libfcache_cache_initialize(
126
7.73k
       &( ( *object_map_btree )->node_cache ),
127
7.73k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_BTREE_NODES,
128
7.73k
       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
7.73k
  ( *object_map_btree )->io_handle              = io_handle;
140
7.73k
  ( *object_map_btree )->data_block_vector      = data_block_vector;
141
7.73k
  ( *object_map_btree )->root_node_block_number = root_node_block_number;
142
143
7.73k
  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
7.73k
}
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
7.73k
{
163
7.73k
  static char *function = "libfsapfs_object_map_btree_free";
164
7.73k
  int result            = 1;
165
166
7.73k
  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
7.73k
  if( *object_map_btree != NULL )
178
7.73k
  {
179
    /* The data_block_vector is referenced and freed elsewhere
180
     */
181
7.73k
    if( libfcache_cache_free(
182
7.73k
         &( ( *object_map_btree )->node_cache ),
183
7.73k
         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
7.73k
    if( libfcache_cache_free(
195
7.73k
         &( ( *object_map_btree )->data_block_cache ),
196
7.73k
         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
7.73k
    memory_free(
208
7.73k
     *object_map_btree );
209
210
7.73k
    *object_map_btree = NULL;
211
7.73k
  }
212
7.73k
  return( result );
213
7.73k
}
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
7.58k
{
225
7.58k
  libfcache_cache_value_t *cache_value = NULL;
226
7.58k
  libfsapfs_btree_node_t *node         = NULL;
227
7.58k
  libfsapfs_data_block_t *data_block   = NULL;
228
7.58k
  static char *function                = "libfsapfs_object_map_btree_get_root_node";
229
7.58k
  int result                           = 0;
230
231
#if defined( HAVE_PROFILER )
232
  int64_t profiler_start_timestamp     = 0;
233
#endif
234
235
7.58k
  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
7.58k
  if( root_node_block_number > (uint64_t) INT_MAX )
247
164
  {
248
164
    libcerror_error_set(
249
164
     error,
250
164
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
251
164
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
252
164
     "%s: invalid root node block number value out of bounds.",
253
164
     function );
254
255
164
    return( -1 );
256
164
  }
257
7.41k
  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
7.41k
  result = libfcache_cache_get_value_by_identifier(
289
7.41k
            object_map_btree->node_cache,
290
7.41k
            0,
291
7.41k
            (off64_t) root_node_block_number,
292
7.41k
            0,
293
7.41k
            &cache_value,
294
7.41k
            error );
295
296
7.41k
  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
7.41k
  else if( result == 0 )
308
6.57k
  {
309
6.57k
    if( libfdata_vector_get_element_value_by_index(
310
6.57k
         object_map_btree->data_block_vector,
311
6.57k
         (intptr_t *) file_io_handle,
312
6.57k
         (libfdata_cache_t *) object_map_btree->data_block_cache,
313
6.57k
         (int) root_node_block_number,
314
6.57k
         (intptr_t **) &data_block,
315
6.57k
         0,
316
6.57k
         error ) != 1 )
317
274
    {
318
274
      libcerror_error_set(
319
274
       error,
320
274
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
321
274
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
322
274
       "%s: unable to retrieve data block: %" PRIu64 ".",
323
274
       function,
324
274
       root_node_block_number );
325
326
274
      goto on_error;
327
274
    }
328
6.29k
    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
6.29k
    if( libfsapfs_btree_node_initialize(
341
6.29k
         &node,
342
6.29k
         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
6.29k
    if( libfsapfs_btree_node_read_data(
354
6.29k
         node,
355
6.29k
         data_block->data,
356
6.29k
         data_block->data_size,
357
6.29k
         error ) != 1 )
358
411
    {
359
411
      libcerror_error_set(
360
411
       error,
361
411
       LIBCERROR_ERROR_DOMAIN_IO,
362
411
       LIBCERROR_IO_ERROR_READ_FAILED,
363
411
       "%s: unable to read B-tree node.",
364
411
       function );
365
366
411
      goto on_error;
367
411
    }
368
5.88k
    if( node->object_type != 0x40000002UL )
369
80
    {
370
80
      libcerror_error_set(
371
80
       error,
372
80
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
373
80
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
374
80
       "%s: invalid object type: 0x%08" PRIx32 ".",
375
80
       function,
376
80
       node->object_type );
377
378
80
      goto on_error;
379
80
    }
380
5.80k
    if( node->object_subtype != 0x0000000bUL )
381
114
    {
382
114
      libcerror_error_set(
383
114
       error,
384
114
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
114
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
386
114
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
387
114
       function,
388
114
       node->object_subtype );
389
390
114
      goto on_error;
391
114
    }
392
5.69k
    if( ( ( node->node_header->flags & 0x0001 ) == 0 )
393
5.69k
     || ( ( node->node_header->flags & 0x0004 ) == 0 ) )
394
6
    {
395
6
      libcerror_error_set(
396
6
       error,
397
6
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
6
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
399
6
       "%s: unsupported flags: 0x%04" PRIx16 ".",
400
6
       function,
401
6
       node->node_header->flags );
402
403
6
      goto on_error;
404
6
    }
405
5.68k
    if( node->footer->node_size != 4096 )
406
60
    {
407
60
      libcerror_error_set(
408
60
       error,
409
60
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
410
60
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
411
60
       "%s: invalid node size value out of bounds.",
412
60
       function );
413
414
60
      goto on_error;
415
60
    }
416
5.62k
    if( node->footer->key_size != sizeof( fsapfs_object_map_btree_key_t ) )
417
85
    {
418
85
      libcerror_error_set(
419
85
       error,
420
85
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
421
85
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
422
85
       "%s: invalid key size value out of bounds.",
423
85
       function );
424
425
85
      goto on_error;
426
85
    }
427
5.54k
    if( node->footer->value_size != sizeof( fsapfs_object_map_btree_value_t ) )
428
101
    {
429
101
      libcerror_error_set(
430
101
       error,
431
101
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
432
101
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
433
101
       "%s: invalid value size value out of bounds.",
434
101
       function );
435
436
101
      goto on_error;
437
101
    }
438
5.44k
    if( libfcache_cache_set_value_by_identifier(
439
5.44k
         object_map_btree->node_cache,
440
5.44k
         0,
441
5.44k
         (off64_t) root_node_block_number,
442
5.44k
         0,
443
5.44k
         (intptr_t *) node,
444
5.44k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
445
5.44k
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
446
5.44k
         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
5.44k
    node = NULL;
458
459
5.44k
    if( libfcache_cache_get_value_by_identifier(
460
5.44k
         object_map_btree->node_cache,
461
5.44k
         0,
462
5.44k
         (off64_t) root_node_block_number,
463
5.44k
         0,
464
5.44k
         &cache_value,
465
5.44k
         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
5.44k
  }
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
6.28k
  if( libfcache_cache_value_get_value(
501
6.28k
       cache_value,
502
6.28k
       (intptr_t **) root_node,
503
6.28k
       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
6.28k
  return( 1 );
515
516
1.13k
on_error:
517
1.13k
  if( node != NULL )
518
857
  {
519
857
    libfsapfs_btree_node_free(
520
857
     &node,
521
857
     NULL );
522
857
  }
523
1.13k
  return( -1 );
524
6.28k
}
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
2.27k
{
536
2.27k
  libfcache_cache_value_t *cache_value = NULL;
537
2.27k
  libfsapfs_btree_node_t *node         = NULL;
538
2.27k
  libfsapfs_data_block_t *data_block   = NULL;
539
2.27k
  static char *function                = "libfsapfs_object_map_btree_get_sub_node";
540
2.27k
  int result                           = 0;
541
542
#if defined( HAVE_PROFILER )
543
  int64_t profiler_start_timestamp     = 0;
544
#endif
545
546
2.27k
  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
2.27k
  if( sub_node_block_number > (uint64_t) INT_MAX )
558
276
  {
559
276
    libcerror_error_set(
560
276
     error,
561
276
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
276
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
563
276
     "%s: invalid sub node block number value out of bounds.",
564
276
     function );
565
566
276
    return( -1 );
567
276
  }
568
2.00k
  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
2.00k
  result = libfcache_cache_get_value_by_identifier(
600
2.00k
            object_map_btree->node_cache,
601
2.00k
            0,
602
2.00k
            (off64_t) sub_node_block_number,
603
2.00k
            0,
604
2.00k
            &cache_value,
605
2.00k
            error );
606
607
2.00k
  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
2.00k
  else if( result == 0 )
619
201
  {
620
201
    if( libfdata_vector_get_element_value_by_index(
621
201
         object_map_btree->data_block_vector,
622
201
         (intptr_t *) file_io_handle,
623
201
         (libfdata_cache_t *) object_map_btree->data_block_cache,
624
201
         (int) sub_node_block_number,
625
201
         (intptr_t **) &data_block,
626
201
         0,
627
201
         error ) != 1 )
628
92
    {
629
92
      libcerror_error_set(
630
92
       error,
631
92
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
632
92
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
633
92
       "%s: unable to retrieve data block: %" PRIu64 ".",
634
92
       function,
635
92
       sub_node_block_number );
636
637
92
      goto on_error;
638
92
    }
639
109
    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
109
    if( libfsapfs_btree_node_initialize(
652
109
         &node,
653
109
         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
109
    if( libfsapfs_btree_node_read_data(
665
109
         node,
666
109
         data_block->data,
667
109
         data_block->data_size,
668
109
         error ) != 1 )
669
29
    {
670
29
      libcerror_error_set(
671
29
       error,
672
29
       LIBCERROR_ERROR_DOMAIN_IO,
673
29
       LIBCERROR_IO_ERROR_READ_FAILED,
674
29
       "%s: unable to read B-tree node.",
675
29
       function );
676
677
29
      goto on_error;
678
29
    }
679
80
    if( node->object_type != 0x40000003UL )
680
32
    {
681
32
      libcerror_error_set(
682
32
       error,
683
32
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
684
32
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
685
32
       "%s: invalid object type: 0x%08" PRIx32 ".",
686
32
       function,
687
32
       node->object_type );
688
689
32
      goto on_error;
690
32
    }
691
48
    if( node->object_subtype != 0x0000000bUL )
692
42
    {
693
42
      libcerror_error_set(
694
42
       error,
695
42
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
696
42
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
697
42
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
698
42
       function,
699
42
       node->object_subtype );
700
701
42
      goto on_error;
702
42
    }
703
6
    if( ( ( node->node_header->flags & 0x0001 ) != 0 )
704
4
     || ( ( node->node_header->flags & 0x0004 ) == 0 ) )
705
4
    {
706
4
      libcerror_error_set(
707
4
       error,
708
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
709
4
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
710
4
       "%s: unsupported flags: 0x%04" PRIx16 ".",
711
4
       function,
712
4
       node->node_header->flags );
713
714
4
      goto on_error;
715
4
    }
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
1.80k
  if( libfcache_cache_value_get_value(
779
1.80k
       cache_value,
780
1.80k
       (intptr_t **) sub_node,
781
1.80k
       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
1.80k
  return( 1 );
793
794
199
on_error:
795
199
  if( node != NULL )
796
107
  {
797
107
    libfsapfs_btree_node_free(
798
107
     &node,
799
107
     NULL );
800
107
  }
801
199
  return( -1 );
802
1.80k
}
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
     uint64_t transaction_identifier,
812
     libfsapfs_btree_entry_t **btree_entry,
813
     libcerror_error_t **error )
814
8.08k
{
815
8.08k
  libfsapfs_btree_entry_t *entry          = NULL;
816
8.08k
  libfsapfs_btree_entry_t *previous_entry = NULL;
817
8.08k
  static char *function                   = "libfsapfs_object_map_btree_get_entry_from_node_by_identifier";
818
8.08k
  uint64_t object_map_identifier          = 0;
819
8.08k
  uint64_t object_map_transaction         = 0;
820
8.08k
  uint64_t previous_object_map_identifier = 0;
821
8.08k
  int btree_entry_index                   = 0;
822
8.08k
  int is_leaf_node                        = 0;
823
8.08k
  int number_of_entries                   = 0;
824
825
8.08k
  if( object_map_btree == NULL )
826
0
  {
827
0
    libcerror_error_set(
828
0
     error,
829
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
830
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
831
0
     "%s: invalid object map B-tree.",
832
0
     function );
833
834
0
    return( -1 );
835
0
  }
836
8.08k
  if( btree_entry == NULL )
837
0
  {
838
0
    libcerror_error_set(
839
0
     error,
840
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
841
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
842
0
     "%s: invalid B-tree entry.",
843
0
     function );
844
845
0
    return( -1 );
846
0
  }
847
#if defined( HAVE_DEBUG_OUTPUT )
848
  if( libcnotify_verbose != 0 )
849
  {
850
    libcnotify_printf(
851
     "%s: retrieving B-tree entry identifier: %" PRIu64 " (transaction: %" PRIu64 ").\n",
852
     function,
853
     object_identifier,
854
     transaction_identifier );
855
  }
856
#endif
857
8.08k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
858
8.08k
                  node,
859
8.08k
                  error );
860
861
8.08k
  if( is_leaf_node == -1 )
862
0
  {
863
0
    libcerror_error_set(
864
0
     error,
865
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
866
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
867
0
     "%s: unable to determine if B-tree node is a leaf node.",
868
0
     function );
869
870
0
    return( -1 );
871
0
  }
872
8.08k
  if( libfsapfs_btree_node_get_number_of_entries(
873
8.08k
       node,
874
8.08k
       &number_of_entries,
875
8.08k
       error ) != 1 )
876
0
  {
877
0
    libcerror_error_set(
878
0
     error,
879
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
880
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
881
0
     "%s: unable to retrieve number of entries from B-tree node.",
882
0
     function );
883
884
0
    return( -1 );
885
0
  }
886
8.08k
  for( btree_entry_index = 0;
887
25.3k
       btree_entry_index < number_of_entries;
888
17.3k
       btree_entry_index++ )
889
18.8k
  {
890
18.8k
    if( libfsapfs_btree_node_get_entry_by_index(
891
18.8k
         node,
892
18.8k
         btree_entry_index,
893
18.8k
         &entry,
894
18.8k
         error ) != 1 )
895
0
    {
896
0
      libcerror_error_set(
897
0
       error,
898
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
899
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
900
0
       "%s: unable to retrieve number of entries from B-tree node.",
901
0
       function );
902
903
0
      return( -1 );
904
0
    }
905
18.8k
    if( entry == NULL )
906
0
    {
907
0
      libcerror_error_set(
908
0
       error,
909
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
910
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
911
0
       "%s: invalid B-tree entry: %d.",
912
0
       function,
913
0
       btree_entry_index );
914
915
0
      return( -1 );
916
0
    }
917
18.8k
    if( entry->key_data == NULL )
918
0
    {
919
0
      libcerror_error_set(
920
0
       error,
921
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
922
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
923
0
       "%s: invalid B-tree entry: %d - missing key data.",
924
0
       function,
925
0
       btree_entry_index );
926
927
0
      return( -1 );
928
0
    }
929
18.8k
    if( entry->key_data_size < 16 )
930
0
    {
931
0
      libcerror_error_set(
932
0
       error,
933
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
934
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
935
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
936
0
       function,
937
0
       btree_entry_index );
938
939
0
      return( -1 );
940
0
    }
941
18.8k
    byte_stream_copy_to_uint64_little_endian(
942
18.8k
     &( entry->key_data[ 0 ] ),
943
18.8k
     object_map_identifier );
944
945
18.8k
    byte_stream_copy_to_uint64_little_endian(
946
18.8k
     &( entry->key_data[ 8 ] ),
947
18.8k
     object_map_transaction );
948
949
#if defined( HAVE_DEBUG_OUTPUT )
950
    if( libcnotify_verbose != 0 )
951
    {
952
      libcnotify_printf(
953
       "%s: B-tree entry: %d, identifier: %" PRIu64 " (transaction: %" PRIu64 ")\n",
954
       function,
955
       btree_entry_index,
956
       object_map_identifier,
957
       object_map_transaction );
958
    }
959
#endif
960
18.8k
    if( object_map_identifier > object_identifier )
961
1.20k
    {
962
1.20k
      break;
963
1.20k
    }
964
17.6k
    else if( ( object_map_identifier == object_identifier )
965
9.38k
          && ( object_map_transaction > transaction_identifier ) )
966
337
    {
967
337
      break;
968
337
    }
969
17.3k
    previous_entry                 = entry;
970
17.3k
    previous_object_map_identifier = object_map_identifier;
971
17.3k
  }
972
8.08k
  if( is_leaf_node != 0 )
973
5.80k
  {
974
5.80k
    if( previous_object_map_identifier == object_identifier )
975
5.52k
    {
976
5.52k
      *btree_entry = previous_entry;
977
978
5.52k
      return( 1 );
979
5.52k
    }
980
5.80k
  }
981
2.28k
  else
982
2.28k
  {
983
2.28k
    if( ( previous_entry == NULL )
984
2.23k
     || ( ( object_map_identifier == object_identifier )
985
609
      &&  ( object_map_transaction <= transaction_identifier ) ) )
986
365
    {
987
365
      previous_entry = entry;
988
365
    }
989
2.28k
    *btree_entry = previous_entry;
990
991
2.28k
    return( 1 );
992
2.28k
  }
993
277
  return( 0 );
994
8.08k
}
995
996
/* Retrieves an entry for a specific identifier from the object map B-tree
997
 * Returns 1 if successful, 0 if not found or -1 on error
998
 */
999
int libfsapfs_object_map_btree_get_entry_by_identifier(
1000
     libfsapfs_object_map_btree_t *object_map_btree,
1001
     libbfio_handle_t *file_io_handle,
1002
     uint64_t object_identifier,
1003
     uint64_t transaction_identifier,
1004
     libfsapfs_btree_node_t **btree_node,
1005
     libfsapfs_btree_entry_t **btree_entry,
1006
     libcerror_error_t **error )
1007
7.58k
{
1008
7.58k
  libfsapfs_btree_entry_t *entry = NULL;
1009
7.58k
  libfsapfs_btree_node_t *node   = NULL;
1010
7.58k
  static char *function          = "libfsapfs_object_map_btree_get_entry_by_identifier";
1011
7.58k
  uint64_t sub_node_block_number = 0;
1012
7.58k
  int is_leaf_node               = 0;
1013
7.58k
  int recursion_depth            = 0;
1014
7.58k
  int result                     = 0;
1015
1016
7.58k
  if( object_map_btree == NULL )
1017
0
  {
1018
0
    libcerror_error_set(
1019
0
     error,
1020
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1021
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1022
0
     "%s: invalid object map B-tree.",
1023
0
     function );
1024
1025
0
    return( -1 );
1026
0
  }
1027
7.58k
  if( btree_node == NULL )
1028
0
  {
1029
0
    libcerror_error_set(
1030
0
     error,
1031
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1032
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1033
0
     "%s: invalid B-tree node.",
1034
0
     function );
1035
1036
0
    return( -1 );
1037
0
  }
1038
7.58k
  if( btree_entry == NULL )
1039
0
  {
1040
0
    libcerror_error_set(
1041
0
     error,
1042
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1043
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1044
0
     "%s: invalid B-tree entry.",
1045
0
     function );
1046
1047
0
    return( -1 );
1048
0
  }
1049
7.58k
  if( libfsapfs_object_map_btree_get_root_node(
1050
7.58k
       object_map_btree,
1051
7.58k
       file_io_handle,
1052
7.58k
       object_map_btree->root_node_block_number,
1053
7.58k
       &node,
1054
7.58k
       error ) != 1 )
1055
1.29k
  {
1056
1.29k
    libcerror_error_set(
1057
1.29k
     error,
1058
1.29k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1059
1.29k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1060
1.29k
     "%s: unable to retrieve B-tree root node.",
1061
1.29k
     function );
1062
1063
1.29k
    return( -1 );
1064
1.29k
  }
1065
6.28k
  do
1066
8.08k
  {
1067
8.08k
    if( ( recursion_depth < 0 )
1068
8.08k
     || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1069
7
    {
1070
7
      libcerror_error_set(
1071
7
       error,
1072
7
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1073
7
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1074
7
       "%s: invalid recursion depth value out of bounds.",
1075
7
       function );
1076
1077
7
      return( -1 );
1078
7
    }
1079
8.08k
    is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1080
8.08k
                    node,
1081
8.08k
                    error );
1082
1083
8.08k
    if( is_leaf_node == -1 )
1084
0
    {
1085
0
      libcerror_error_set(
1086
0
       error,
1087
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1088
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1089
0
       "%s: unable to determine if B-tree node is a leaf node.",
1090
0
       function );
1091
1092
0
      return( -1 );
1093
0
    }
1094
8.08k
    result = libfsapfs_object_map_btree_get_entry_from_node_by_identifier(
1095
8.08k
              object_map_btree,
1096
8.08k
              node,
1097
8.08k
              object_identifier,
1098
8.08k
              transaction_identifier,
1099
8.08k
              &entry,
1100
8.08k
              error );
1101
1102
8.08k
    if( result == -1 )
1103
0
    {
1104
0
      libcerror_error_set(
1105
0
       error,
1106
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1107
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1108
0
       "%s: unable to retrieve entry from B-tree node.",
1109
0
       function );
1110
1111
0
      return( -1 );
1112
0
    }
1113
8.08k
    else if( result == 0 )
1114
277
    {
1115
277
      break;
1116
277
    }
1117
7.80k
    if( is_leaf_node != 0 )
1118
5.52k
    {
1119
5.52k
      *btree_node  = node;
1120
5.52k
      *btree_entry = entry;
1121
1122
5.52k
      return( 1 );
1123
5.52k
    }
1124
2.28k
    if( entry == NULL )
1125
4
    {
1126
4
      libcerror_error_set(
1127
4
       error,
1128
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1129
4
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1130
4
       "%s: invalid B-tree entry.",
1131
4
       function );
1132
1133
4
      return( -1 );
1134
4
    }
1135
2.27k
    if( entry->value_data == NULL )
1136
0
    {
1137
0
      libcerror_error_set(
1138
0
       error,
1139
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1140
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1141
0
       "%s: invalid B-tree entry - missing value data.",
1142
0
       function );
1143
1144
0
      return( -1 );
1145
0
    }
1146
2.27k
    if( entry->value_data_size != 8 )
1147
0
    {
1148
0
      libcerror_error_set(
1149
0
       error,
1150
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1151
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1152
0
       "%s: invalid B-tree entry - unsupported value data size.",
1153
0
       function );
1154
1155
0
      return( -1 );
1156
0
    }
1157
2.27k
    byte_stream_copy_to_uint64_little_endian(
1158
2.27k
     entry->value_data,
1159
2.27k
     sub_node_block_number );
1160
1161
#if defined( HAVE_DEBUG_OUTPUT )
1162
    if( libcnotify_verbose != 0 )
1163
    {
1164
      libcnotify_printf(
1165
       "%s: B-tree sub node block number: %" PRIu64 "\n",
1166
       function,
1167
       sub_node_block_number );
1168
    }
1169
#endif
1170
2.27k
    node = NULL;
1171
1172
2.27k
    if( libfsapfs_object_map_btree_get_sub_node(
1173
2.27k
         object_map_btree,
1174
2.27k
         file_io_handle,
1175
2.27k
         sub_node_block_number,
1176
2.27k
         &node,
1177
2.27k
         error ) != 1 )
1178
475
    {
1179
475
      libcerror_error_set(
1180
475
       error,
1181
475
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1182
475
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1183
475
       "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1184
475
       function,
1185
475
       sub_node_block_number );
1186
1187
475
      return( -1 );
1188
475
    }
1189
1.80k
    recursion_depth++;
1190
1.80k
  }
1191
6.28k
  while( is_leaf_node == 0 );
1192
1193
277
  return( 0 );
1194
6.28k
}
1195
1196
/* Retrieves the object map descriptor of a specific object identifier
1197
 * Returns 1 if successful, 0 if no such value or -1 on error
1198
 */
1199
int libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
1200
     libfsapfs_object_map_btree_t *object_map_btree,
1201
     libbfio_handle_t *file_io_handle,
1202
     uint64_t object_identifier,
1203
     uint64_t transaction_identifier,
1204
     libfsapfs_object_map_descriptor_t **descriptor,
1205
     libcerror_error_t **error )
1206
7.58k
{
1207
7.58k
  libfsapfs_btree_entry_t *entry                     = NULL;
1208
7.58k
  libfsapfs_btree_node_t *node                       = NULL;
1209
7.58k
  libfsapfs_object_map_descriptor_t *safe_descriptor = NULL;
1210
7.58k
  static char *function                              = "libfsapfs_object_map_btree_get_descriptor_by_object_identifier";
1211
7.58k
  int result                                         = 0;
1212
1213
7.58k
  if( object_map_btree == NULL )
1214
0
  {
1215
0
    libcerror_error_set(
1216
0
     error,
1217
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1218
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1219
0
     "%s: invalid object map B-tree.",
1220
0
     function );
1221
1222
0
    return( -1 );
1223
0
  }
1224
7.58k
  if( descriptor == NULL )
1225
0
  {
1226
0
    libcerror_error_set(
1227
0
     error,
1228
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1229
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1230
0
     "%s: invalid descriptor.",
1231
0
     function );
1232
1233
0
    return( -1 );
1234
0
  }
1235
7.58k
  if( *descriptor != NULL )
1236
0
  {
1237
0
    libcerror_error_set(
1238
0
     error,
1239
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1240
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1241
0
     "%s: invalid descriptor value already set.",
1242
0
     function );
1243
1244
0
    return( -1 );
1245
0
  }
1246
7.58k
  result = libfsapfs_object_map_btree_get_entry_by_identifier(
1247
7.58k
            object_map_btree,
1248
7.58k
            file_io_handle,
1249
7.58k
            object_identifier,
1250
7.58k
            transaction_identifier,
1251
7.58k
            &node,
1252
7.58k
            &entry,
1253
7.58k
            error );
1254
1255
7.58k
  if( result == -1 )
1256
1.78k
  {
1257
1.78k
    libcerror_error_set(
1258
1.78k
     error,
1259
1.78k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1260
1.78k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1261
1.78k
     "%s: unable to retrieve entry from B-tree.",
1262
1.78k
     function );
1263
1264
1.78k
    goto on_error;
1265
1.78k
  }
1266
5.80k
  else if( result != 0 )
1267
5.52k
  {
1268
5.52k
    if( node == 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 node.",
1275
0
       function );
1276
1277
0
      goto on_error;
1278
0
    }
1279
5.52k
    if( entry == NULL )
1280
5
    {
1281
5
      libcerror_error_set(
1282
5
       error,
1283
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1284
5
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1285
5
       "%s: invalid B-tree entry.",
1286
5
       function );
1287
1288
5
      goto on_error;
1289
5
    }
1290
5.52k
    if( libfsapfs_object_map_descriptor_initialize(
1291
5.52k
         &safe_descriptor,
1292
5.52k
         error ) != 1 )
1293
0
    {
1294
0
      libcerror_error_set(
1295
0
       error,
1296
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1297
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1298
0
       "%s: unable to create object map descriptor.",
1299
0
       function );
1300
1301
0
      goto on_error;
1302
0
    }
1303
5.52k
    if( libfsapfs_object_map_descriptor_read_key_data(
1304
5.52k
         safe_descriptor,
1305
5.52k
         entry->key_data,
1306
5.52k
         (size_t) entry->key_data_size,
1307
5.52k
         error ) != 1 )
1308
0
    {
1309
0
      libcerror_error_set(
1310
0
       error,
1311
0
       LIBCERROR_ERROR_DOMAIN_IO,
1312
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1313
0
       "%s: unable to read object map descriptor key data.",
1314
0
       function );
1315
1316
0
      goto on_error;
1317
0
    }
1318
5.52k
    if( libfsapfs_object_map_descriptor_read_value_data(
1319
5.52k
         safe_descriptor,
1320
5.52k
         entry->value_data,
1321
5.52k
         (size_t) entry->value_data_size,
1322
5.52k
         error ) != 1 )
1323
0
    {
1324
0
      libcerror_error_set(
1325
0
       error,
1326
0
       LIBCERROR_ERROR_DOMAIN_IO,
1327
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1328
0
       "%s: unable to read object map descriptor value data.",
1329
0
       function );
1330
1331
0
      goto on_error;
1332
0
    }
1333
5.52k
    node = NULL;
1334
5.52k
  }
1335
5.79k
  *descriptor = safe_descriptor;
1336
1337
5.79k
  return( result );
1338
1339
1.78k
on_error:
1340
1.78k
  if( safe_descriptor != NULL )
1341
0
  {
1342
0
    libfsapfs_object_map_descriptor_free(
1343
0
     &safe_descriptor,
1344
     NULL );
1345
0
  }
1346
1.78k
  return( -1 );
1347
7.58k
}
1348