Coverage Report

Created: 2025-07-04 07:01

/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-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 <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
8.30k
{
54
8.30k
  static char *function = "libfsapfs_object_map_btree_initialize";
55
56
8.30k
  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
8.30k
  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
8.30k
  *object_map_btree = memory_allocate_structure(
79
8.30k
                       libfsapfs_object_map_btree_t );
80
81
8.30k
  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
8.30k
  if( memory_set(
93
8.30k
       *object_map_btree,
94
8.30k
       0,
95
8.30k
       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
8.30k
  if( libfcache_cache_initialize(
112
8.30k
       &( ( *object_map_btree )->data_block_cache ),
113
8.30k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
114
8.30k
       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
8.30k
  if( libfcache_cache_initialize(
126
8.30k
       &( ( *object_map_btree )->node_cache ),
127
8.30k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_BTREE_NODES,
128
8.30k
       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
8.30k
  ( *object_map_btree )->io_handle              = io_handle;
140
8.30k
  ( *object_map_btree )->data_block_vector      = data_block_vector;
141
8.30k
  ( *object_map_btree )->root_node_block_number = root_node_block_number;
142
143
8.30k
  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
8.30k
}
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
8.30k
{
163
8.30k
  static char *function = "libfsapfs_object_map_btree_free";
164
8.30k
  int result            = 1;
165
166
8.30k
  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
8.30k
  if( *object_map_btree != NULL )
178
8.30k
  {
179
    /* The data_block_vector is referenced and freed elsewhere
180
     */
181
8.30k
    if( libfcache_cache_free(
182
8.30k
         &( ( *object_map_btree )->node_cache ),
183
8.30k
         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
8.30k
    if( libfcache_cache_free(
195
8.30k
         &( ( *object_map_btree )->data_block_cache ),
196
8.30k
         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
8.30k
    memory_free(
208
8.30k
     *object_map_btree );
209
210
8.30k
    *object_map_btree = NULL;
211
8.30k
  }
212
8.30k
  return( result );
213
8.30k
}
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
8.32k
{
225
8.32k
  libfcache_cache_value_t *cache_value = NULL;
226
8.32k
  libfsapfs_btree_node_t *node         = NULL;
227
8.32k
  libfsapfs_data_block_t *data_block   = NULL;
228
8.32k
  static char *function                = "libfsapfs_object_map_btree_get_root_node";
229
8.32k
  int result                           = 0;
230
231
#if defined( HAVE_PROFILER )
232
  int64_t profiler_start_timestamp     = 0;
233
#endif
234
235
8.32k
  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
8.32k
  if( root_node_block_number > (uint64_t) INT_MAX )
247
186
  {
248
186
    libcerror_error_set(
249
186
     error,
250
186
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
251
186
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
252
186
     "%s: invalid root node block number value out of bounds.",
253
186
     function );
254
255
186
    return( -1 );
256
186
  }
257
8.13k
  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
8.13k
  result = libfcache_cache_get_value_by_identifier(
289
8.13k
            object_map_btree->node_cache,
290
8.13k
            0,
291
8.13k
            (off64_t) root_node_block_number,
292
8.13k
            0,
293
8.13k
            &cache_value,
294
8.13k
            error );
295
296
8.13k
  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
8.13k
  else if( result == 0 )
308
7.03k
  {
309
7.03k
    if( libfdata_vector_get_element_value_by_index(
310
7.03k
         object_map_btree->data_block_vector,
311
7.03k
         (intptr_t *) file_io_handle,
312
7.03k
         (libfdata_cache_t *) object_map_btree->data_block_cache,
313
7.03k
         (int) root_node_block_number,
314
7.03k
         (intptr_t **) &data_block,
315
7.03k
         0,
316
7.03k
         error ) != 1 )
317
281
    {
318
281
      libcerror_error_set(
319
281
       error,
320
281
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
321
281
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
322
281
       "%s: unable to retrieve data block: %" PRIu64 ".",
323
281
       function,
324
281
       root_node_block_number );
325
326
281
      goto on_error;
327
281
    }
328
6.75k
    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.75k
    if( libfsapfs_btree_node_initialize(
341
6.75k
         &node,
342
6.75k
         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.75k
    if( libfsapfs_btree_node_read_data(
354
6.75k
         node,
355
6.75k
         data_block->data,
356
6.75k
         data_block->data_size,
357
6.75k
         error ) != 1 )
358
449
    {
359
449
      libcerror_error_set(
360
449
       error,
361
449
       LIBCERROR_ERROR_DOMAIN_IO,
362
449
       LIBCERROR_IO_ERROR_READ_FAILED,
363
449
       "%s: unable to read B-tree node.",
364
449
       function );
365
366
449
      goto on_error;
367
449
    }
368
6.30k
    if( node->object_type != 0x40000002UL )
369
63
    {
370
63
      libcerror_error_set(
371
63
       error,
372
63
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
373
63
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
374
63
       "%s: invalid object type: 0x%08" PRIx32 ".",
375
63
       function,
376
63
       node->object_type );
377
378
63
      goto on_error;
379
63
    }
380
6.24k
    if( node->object_subtype != 0x0000000bUL )
381
111
    {
382
111
      libcerror_error_set(
383
111
       error,
384
111
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
111
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
386
111
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
387
111
       function,
388
111
       node->object_subtype );
389
390
111
      goto on_error;
391
111
    }
392
6.13k
    if( ( ( node->node_header->flags & 0x0001 ) == 0 )
393
6.13k
     || ( ( node->node_header->flags & 0x0004 ) == 0 ) )
394
5
    {
395
5
      libcerror_error_set(
396
5
       error,
397
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
5
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
399
5
       "%s: unsupported flags: 0x%04" PRIx16 ".",
400
5
       function,
401
5
       node->node_header->flags );
402
403
5
      goto on_error;
404
5
    }
405
6.12k
    if( node->footer->node_size != 4096 )
406
112
    {
407
112
      libcerror_error_set(
408
112
       error,
409
112
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
410
112
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
411
112
       "%s: invalid node size value out of bounds.",
412
112
       function );
413
414
112
      goto on_error;
415
112
    }
416
6.01k
    if( node->footer->key_size != sizeof( fsapfs_object_map_btree_key_t ) )
417
91
    {
418
91
      libcerror_error_set(
419
91
       error,
420
91
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
421
91
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
422
91
       "%s: invalid key size value out of bounds.",
423
91
       function );
424
425
91
      goto on_error;
426
91
    }
427
5.92k
    if( node->footer->value_size != sizeof( fsapfs_object_map_btree_value_t ) )
428
100
    {
429
100
      libcerror_error_set(
430
100
       error,
431
100
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
432
100
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
433
100
       "%s: invalid value size value out of bounds.",
434
100
       function );
435
436
100
      goto on_error;
437
100
    }
438
5.82k
    if( libfcache_cache_set_value_by_identifier(
439
5.82k
         object_map_btree->node_cache,
440
5.82k
         0,
441
5.82k
         (off64_t) root_node_block_number,
442
5.82k
         0,
443
5.82k
         (intptr_t *) node,
444
5.82k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
445
5.82k
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
446
5.82k
         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.82k
    node = NULL;
458
459
5.82k
    if( libfcache_cache_get_value_by_identifier(
460
5.82k
         object_map_btree->node_cache,
461
5.82k
         0,
462
5.82k
         (off64_t) root_node_block_number,
463
5.82k
         0,
464
5.82k
         &cache_value,
465
5.82k
         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.82k
  }
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.92k
  if( libfcache_cache_value_get_value(
501
6.92k
       cache_value,
502
6.92k
       (intptr_t **) root_node,
503
6.92k
       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.92k
  return( 1 );
515
516
1.21k
on_error:
517
1.21k
  if( node != NULL )
518
931
  {
519
931
    libfsapfs_btree_node_free(
520
931
     &node,
521
931
     NULL );
522
931
  }
523
1.21k
  return( -1 );
524
6.92k
}
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
3.91k
{
536
3.91k
  libfcache_cache_value_t *cache_value = NULL;
537
3.91k
  libfsapfs_btree_node_t *node         = NULL;
538
3.91k
  libfsapfs_data_block_t *data_block   = NULL;
539
3.91k
  static char *function                = "libfsapfs_object_map_btree_get_sub_node";
540
3.91k
  int result                           = 0;
541
542
#if defined( HAVE_PROFILER )
543
  int64_t profiler_start_timestamp     = 0;
544
#endif
545
546
3.91k
  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
3.91k
  if( sub_node_block_number > (uint64_t) INT_MAX )
558
354
  {
559
354
    libcerror_error_set(
560
354
     error,
561
354
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
354
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
563
354
     "%s: invalid sub node block number value out of bounds.",
564
354
     function );
565
566
354
    return( -1 );
567
354
  }
568
3.55k
  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
3.55k
  result = libfcache_cache_get_value_by_identifier(
600
3.55k
            object_map_btree->node_cache,
601
3.55k
            0,
602
3.55k
            (off64_t) sub_node_block_number,
603
3.55k
            0,
604
3.55k
            &cache_value,
605
3.55k
            error );
606
607
3.55k
  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
3.55k
  else if( result == 0 )
619
218
  {
620
218
    if( libfdata_vector_get_element_value_by_index(
621
218
         object_map_btree->data_block_vector,
622
218
         (intptr_t *) file_io_handle,
623
218
         (libfdata_cache_t *) object_map_btree->data_block_cache,
624
218
         (int) sub_node_block_number,
625
218
         (intptr_t **) &data_block,
626
218
         0,
627
218
         error ) != 1 )
628
103
    {
629
103
      libcerror_error_set(
630
103
       error,
631
103
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
632
103
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
633
103
       "%s: unable to retrieve data block: %" PRIu64 ".",
634
103
       function,
635
103
       sub_node_block_number );
636
637
103
      goto on_error;
638
103
    }
639
115
    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
115
    if( libfsapfs_btree_node_initialize(
652
115
         &node,
653
115
         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
115
    if( libfsapfs_btree_node_read_data(
665
115
         node,
666
115
         data_block->data,
667
115
         data_block->data_size,
668
115
         error ) != 1 )
669
31
    {
670
31
      libcerror_error_set(
671
31
       error,
672
31
       LIBCERROR_ERROR_DOMAIN_IO,
673
31
       LIBCERROR_IO_ERROR_READ_FAILED,
674
31
       "%s: unable to read B-tree node.",
675
31
       function );
676
677
31
      goto on_error;
678
31
    }
679
84
    if( node->object_type != 0x40000003UL )
680
36
    {
681
36
      libcerror_error_set(
682
36
       error,
683
36
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
684
36
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
685
36
       "%s: invalid object type: 0x%08" PRIx32 ".",
686
36
       function,
687
36
       node->object_type );
688
689
36
      goto on_error;
690
36
    }
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
6
     || ( ( 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
3.34k
  if( libfcache_cache_value_get_value(
779
3.34k
       cache_value,
780
3.34k
       (intptr_t **) sub_node,
781
3.34k
       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
3.34k
  return( 1 );
793
794
216
on_error:
795
216
  if( node != NULL )
796
113
  {
797
113
    libfsapfs_btree_node_free(
798
113
     &node,
799
113
     NULL );
800
113
  }
801
216
  return( -1 );
802
3.34k
}
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
10.2k
{
815
10.2k
  libfsapfs_btree_entry_t *entry          = NULL;
816
10.2k
  libfsapfs_btree_entry_t *previous_entry = NULL;
817
10.2k
  static char *function                   = "libfsapfs_object_map_btree_get_entry_from_node_by_identifier";
818
10.2k
  uint64_t object_map_identifier          = 0;
819
10.2k
  uint64_t object_map_transaction         = 0;
820
10.2k
  uint64_t previous_object_map_identifier = 0;
821
10.2k
  int btree_entry_index                   = 0;
822
10.2k
  int is_leaf_node                        = 0;
823
10.2k
  int number_of_entries                   = 0;
824
825
10.2k
  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
10.2k
  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
10.2k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
858
10.2k
                  node,
859
10.2k
                  error );
860
861
10.2k
  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
10.2k
  if( libfsapfs_btree_node_get_number_of_entries(
873
10.2k
       node,
874
10.2k
       &number_of_entries,
875
10.2k
       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
10.2k
  for( btree_entry_index = 0;
887
32.0k
       btree_entry_index < number_of_entries;
888
21.7k
       btree_entry_index++ )
889
24.9k
  {
890
24.9k
    if( libfsapfs_btree_node_get_entry_by_index(
891
24.9k
         node,
892
24.9k
         btree_entry_index,
893
24.9k
         &entry,
894
24.9k
         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
24.9k
    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
24.9k
    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
24.9k
    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
24.9k
    byte_stream_copy_to_uint64_little_endian(
942
24.9k
     &( entry->key_data[ 0 ] ),
943
24.9k
     object_map_identifier );
944
945
24.9k
    byte_stream_copy_to_uint64_little_endian(
946
24.9k
     &( entry->key_data[ 8 ] ),
947
24.9k
     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
24.9k
    if( object_map_identifier > object_identifier )
961
1.72k
    {
962
1.72k
      break;
963
1.72k
    }
964
23.2k
    else if( ( object_map_identifier == object_identifier )
965
23.2k
          && ( object_map_transaction > transaction_identifier ) )
966
1.41k
    {
967
1.41k
      break;
968
1.41k
    }
969
21.7k
    previous_entry                 = entry;
970
21.7k
    previous_object_map_identifier = object_map_identifier;
971
21.7k
  }
972
10.2k
  if( is_leaf_node != 0 )
973
6.33k
  {
974
6.33k
    if( previous_object_map_identifier == object_identifier )
975
6.00k
    {
976
6.00k
      *btree_entry = previous_entry;
977
978
6.00k
      return( 1 );
979
6.00k
    }
980
6.33k
  }
981
3.91k
  else
982
3.91k
  {
983
3.91k
    if( ( previous_entry == NULL )
984
3.91k
     || ( ( object_map_identifier == object_identifier )
985
3.87k
      &&  ( object_map_transaction <= transaction_identifier ) ) )
986
405
    {
987
405
      previous_entry = entry;
988
405
    }
989
3.91k
    *btree_entry = previous_entry;
990
991
3.91k
    return( 1 );
992
3.91k
  }
993
332
  return( 0 );
994
10.2k
}
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
8.32k
{
1008
8.32k
  libfsapfs_btree_entry_t *entry = NULL;
1009
8.32k
  libfsapfs_btree_node_t *node   = NULL;
1010
8.32k
  static char *function          = "libfsapfs_object_map_btree_get_entry_by_identifier";
1011
8.32k
  uint64_t sub_node_block_number = 0;
1012
8.32k
  int is_leaf_node               = 0;
1013
8.32k
  int recursion_depth            = 0;
1014
8.32k
  int result                     = 0;
1015
1016
8.32k
  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
8.32k
  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
8.32k
  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
8.32k
  if( libfsapfs_object_map_btree_get_root_node(
1050
8.32k
       object_map_btree,
1051
8.32k
       file_io_handle,
1052
8.32k
       object_map_btree->root_node_block_number,
1053
8.32k
       &node,
1054
8.32k
       error ) != 1 )
1055
1.39k
  {
1056
1.39k
    libcerror_error_set(
1057
1.39k
     error,
1058
1.39k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1059
1.39k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1060
1.39k
     "%s: unable to retrieve B-tree root node.",
1061
1.39k
     function );
1062
1063
1.39k
    return( -1 );
1064
1.39k
  }
1065
6.92k
  do
1066
10.2k
  {
1067
10.2k
    if( ( recursion_depth < 0 )
1068
10.2k
     || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1069
13
    {
1070
13
      libcerror_error_set(
1071
13
       error,
1072
13
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1073
13
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1074
13
       "%s: invalid recursion depth value out of bounds.",
1075
13
       function );
1076
1077
13
      return( -1 );
1078
13
    }
1079
10.2k
    is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1080
10.2k
                    node,
1081
10.2k
                    error );
1082
1083
10.2k
    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
10.2k
    result = libfsapfs_object_map_btree_get_entry_from_node_by_identifier(
1095
10.2k
              object_map_btree,
1096
10.2k
              node,
1097
10.2k
              object_identifier,
1098
10.2k
              transaction_identifier,
1099
10.2k
              &entry,
1100
10.2k
              error );
1101
1102
10.2k
    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
10.2k
    else if( result == 0 )
1114
332
    {
1115
332
      break;
1116
332
    }
1117
9.92k
    if( is_leaf_node != 0 )
1118
6.00k
    {
1119
6.00k
      *btree_node  = node;
1120
6.00k
      *btree_entry = entry;
1121
1122
6.00k
      return( 1 );
1123
6.00k
    }
1124
3.91k
    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
3.91k
    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
3.91k
    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
3.91k
    byte_stream_copy_to_uint64_little_endian(
1158
3.91k
     entry->value_data,
1159
3.91k
     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
3.91k
    node = NULL;
1171
1172
3.91k
    if( libfsapfs_object_map_btree_get_sub_node(
1173
3.91k
         object_map_btree,
1174
3.91k
         file_io_handle,
1175
3.91k
         sub_node_block_number,
1176
3.91k
         &node,
1177
3.91k
         error ) != 1 )
1178
570
    {
1179
570
      libcerror_error_set(
1180
570
       error,
1181
570
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1182
570
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1183
570
       "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1184
570
       function,
1185
570
       sub_node_block_number );
1186
1187
570
      return( -1 );
1188
570
    }
1189
3.34k
    recursion_depth++;
1190
3.34k
  }
1191
6.92k
  while( is_leaf_node == 0 );
1192
1193
332
  return( 0 );
1194
6.92k
}
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
8.32k
{
1207
8.32k
  libfsapfs_btree_entry_t *entry                     = NULL;
1208
8.32k
  libfsapfs_btree_node_t *node                       = NULL;
1209
8.32k
  libfsapfs_object_map_descriptor_t *safe_descriptor = NULL;
1210
8.32k
  static char *function                              = "libfsapfs_object_map_btree_get_descriptor_by_object_identifier";
1211
8.32k
  int result                                         = 0;
1212
1213
8.32k
  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
8.32k
  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
8.32k
  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
8.32k
  result = libfsapfs_object_map_btree_get_entry_by_identifier(
1247
8.32k
            object_map_btree,
1248
8.32k
            file_io_handle,
1249
8.32k
            object_identifier,
1250
8.32k
            transaction_identifier,
1251
8.32k
            &node,
1252
8.32k
            &entry,
1253
8.32k
            error );
1254
1255
8.32k
  if( result == -1 )
1256
1.98k
  {
1257
1.98k
    libcerror_error_set(
1258
1.98k
     error,
1259
1.98k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1260
1.98k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1261
1.98k
     "%s: unable to retrieve entry from B-tree.",
1262
1.98k
     function );
1263
1264
1.98k
    goto on_error;
1265
1.98k
  }
1266
6.33k
  else if( result != 0 )
1267
6.00k
  {
1268
6.00k
    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
6.00k
    if( entry == NULL )
1280
6
    {
1281
6
      libcerror_error_set(
1282
6
       error,
1283
6
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1284
6
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1285
6
       "%s: invalid B-tree entry.",
1286
6
       function );
1287
1288
6
      goto on_error;
1289
6
    }
1290
5.99k
    if( libfsapfs_object_map_descriptor_initialize(
1291
5.99k
         &safe_descriptor,
1292
5.99k
         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.99k
    if( libfsapfs_object_map_descriptor_read_key_data(
1304
5.99k
         safe_descriptor,
1305
5.99k
         entry->key_data,
1306
5.99k
         (size_t) entry->key_data_size,
1307
5.99k
         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.99k
    if( libfsapfs_object_map_descriptor_read_value_data(
1319
5.99k
         safe_descriptor,
1320
5.99k
         entry->value_data,
1321
5.99k
         (size_t) entry->value_data_size,
1322
5.99k
         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.99k
    node = NULL;
1334
5.99k
  }
1335
6.33k
  *descriptor = safe_descriptor;
1336
1337
6.33k
  return( result );
1338
1339
1.99k
on_error:
1340
1.99k
  if( safe_descriptor != NULL )
1341
0
  {
1342
0
    libfsapfs_object_map_descriptor_free(
1343
0
     &safe_descriptor,
1344
0
     NULL );
1345
0
  }
1346
1.99k
  return( -1 );
1347
8.32k
}
1348