Coverage Report

Created: 2024-02-25 07:20

/src/libfsapfs/libfsapfs/libfsapfs_snapshot_metadata_tree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The snapshot metadata 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_debug.h"
31
#include "libfsapfs_definitions.h"
32
#include "libfsapfs_io_handle.h"
33
#include "libfsapfs_libbfio.h"
34
#include "libfsapfs_libcerror.h"
35
#include "libfsapfs_libcnotify.h"
36
#include "libfsapfs_libfcache.h"
37
#include "libfsapfs_libfdata.h"
38
#include "libfsapfs_object_map_btree.h"
39
#include "libfsapfs_object_map_descriptor.h"
40
#include "libfsapfs_snapshot_metadata.h"
41
#include "libfsapfs_snapshot_metadata_tree.h"
42
43
#include "fsapfs_object.h"
44
#include "fsapfs_snapshot_metadata.h"
45
46
/* Creates a snapshot metadata tree
47
 * Make sure the value snapshot_metadata_tree is referencing, is set to NULL
48
 * Returns 1 if successful or -1 on error
49
 */
50
int libfsapfs_snapshot_metadata_tree_initialize(
51
     libfsapfs_snapshot_metadata_tree_t **snapshot_metadata_tree,
52
     libfsapfs_io_handle_t *io_handle,
53
     libfdata_vector_t *data_block_vector,
54
     libfsapfs_object_map_btree_t *object_map_btree,
55
     uint64_t root_node_block_number,
56
     libcerror_error_t **error )
57
4.08k
{
58
4.08k
  static char *function = "libfsapfs_snapshot_metadata_tree_initialize";
59
60
4.08k
  if( snapshot_metadata_tree == NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
65
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
66
0
     "%s: invalid snapshot metadata tree.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
4.08k
  if( *snapshot_metadata_tree != NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
76
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
77
0
     "%s: invalid snapshot metadata tree value already set.",
78
0
     function );
79
80
0
    return( -1 );
81
0
  }
82
4.08k
  *snapshot_metadata_tree = memory_allocate_structure(
83
4.08k
                             libfsapfs_snapshot_metadata_tree_t );
84
85
4.08k
  if( *snapshot_metadata_tree == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
91
0
     "%s: unable to create snapshot metadata tree.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
4.08k
  if( memory_set(
97
4.08k
       *snapshot_metadata_tree,
98
4.08k
       0,
99
4.08k
       sizeof( libfsapfs_snapshot_metadata_tree_t ) ) == NULL )
100
0
  {
101
0
    libcerror_error_set(
102
0
     error,
103
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
104
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
105
0
     "%s: unable to clear snapshot metadata tree.",
106
0
     function );
107
108
0
    memory_free(
109
0
     *snapshot_metadata_tree );
110
111
0
    *snapshot_metadata_tree = NULL;
112
113
0
    return( -1 );
114
0
  }
115
4.08k
  if( libfcache_cache_initialize(
116
4.08k
       &( ( *snapshot_metadata_tree )->data_block_cache ),
117
4.08k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
118
4.08k
       error ) != 1 )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
123
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
124
0
     "%s: unable to create data block cache.",
125
0
     function );
126
127
0
    goto on_error;
128
0
  }
129
4.08k
  if( libfcache_cache_initialize(
130
4.08k
       &( ( *snapshot_metadata_tree )->node_cache ),
131
4.08k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_BTREE_NODES,
132
4.08k
       error ) != 1 )
133
0
  {
134
0
    libcerror_error_set(
135
0
     error,
136
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
137
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
138
0
     "%s: unable to create node cache.",
139
0
     function );
140
141
0
    goto on_error;
142
0
  }
143
4.08k
  ( *snapshot_metadata_tree )->io_handle              = io_handle;
144
4.08k
  ( *snapshot_metadata_tree )->data_block_vector      = data_block_vector;
145
4.08k
  ( *snapshot_metadata_tree )->object_map_btree       = object_map_btree;
146
4.08k
  ( *snapshot_metadata_tree )->root_node_block_number = root_node_block_number;
147
148
4.08k
  return( 1 );
149
150
0
on_error:
151
0
  if( *snapshot_metadata_tree != NULL )
152
0
  {
153
0
    memory_free(
154
0
     *snapshot_metadata_tree );
155
156
0
    *snapshot_metadata_tree = NULL;
157
0
  }
158
0
  return( -1 );
159
4.08k
}
160
161
/* Frees a snapshot metadata tree
162
 * Returns 1 if successful or -1 on error
163
 */
164
int libfsapfs_snapshot_metadata_tree_free(
165
     libfsapfs_snapshot_metadata_tree_t **snapshot_metadata_tree,
166
     libcerror_error_t **error )
167
4.08k
{
168
4.08k
  static char *function = "libfsapfs_snapshot_metadata_tree_free";
169
4.08k
  int result            = 1;
170
171
4.08k
  if( snapshot_metadata_tree == NULL )
172
0
  {
173
0
    libcerror_error_set(
174
0
     error,
175
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
176
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
177
0
     "%s: invalid snapshot metadata tree.",
178
0
     function );
179
180
0
    return( -1 );
181
0
  }
182
4.08k
  if( *snapshot_metadata_tree != NULL )
183
4.08k
  {
184
    /* The data_block_vector is referenced and freed elsewhere
185
     */
186
4.08k
    if( libfcache_cache_free(
187
4.08k
         &( ( *snapshot_metadata_tree )->node_cache ),
188
4.08k
         error ) != 1 )
189
0
    {
190
0
      libcerror_error_set(
191
0
       error,
192
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
193
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
194
0
       "%s: unable to free node cache.",
195
0
       function );
196
197
0
      result = -1;
198
0
    }
199
4.08k
    if( libfcache_cache_free(
200
4.08k
         &( ( *snapshot_metadata_tree )->data_block_cache ),
201
4.08k
         error ) != 1 )
202
0
    {
203
0
      libcerror_error_set(
204
0
       error,
205
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
206
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
207
0
       "%s: unable to free data block cache.",
208
0
       function );
209
210
0
      result = -1;
211
0
    }
212
4.08k
    memory_free(
213
4.08k
     *snapshot_metadata_tree );
214
215
4.08k
    *snapshot_metadata_tree = NULL;
216
4.08k
  }
217
4.08k
  return( result );
218
4.08k
}
219
220
/* Retrieves the sub node block number from a B-tree entry
221
 * Returns 1 if successful, 0 if not found or -1 on error
222
 */
223
int libfsapfs_snapshot_metadata_tree_get_sub_node_block_number_from_entry(
224
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
225
     libbfio_handle_t *file_io_handle,
226
     libfsapfs_btree_entry_t *entry,
227
     uint64_t transaction_identifier,
228
     uint64_t *sub_node_block_number,
229
     libcerror_error_t **error )
230
1.66k
{
231
1.66k
  libfsapfs_object_map_descriptor_t *object_map_descriptor = NULL;
232
1.66k
  static char *function                                    = "libfsapfs_snapshot_metadata_tree_get_sub_node_block_number_from_entry";
233
1.66k
  uint64_t sub_node_object_identifier                      = 0;
234
1.66k
  int result                                               = 0;
235
236
1.66k
  if( snapshot_metadata_tree == NULL )
237
0
  {
238
0
    libcerror_error_set(
239
0
     error,
240
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
241
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
242
0
     "%s: invalid snapshot metadata tree.",
243
0
     function );
244
245
0
    return( -1 );
246
0
  }
247
1.66k
  if( entry == NULL )
248
0
  {
249
0
    libcerror_error_set(
250
0
     error,
251
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
252
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
253
0
     "%s: invalid B-tree entry.",
254
0
     function );
255
256
0
    return( -1 );
257
0
  }
258
1.66k
  if( entry->value_data == NULL )
259
11
  {
260
11
    libcerror_error_set(
261
11
     error,
262
11
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
263
11
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
264
11
     "%s: invalid B-tree entry - missing value data.",
265
11
     function );
266
267
11
    return( -1 );
268
11
  }
269
1.65k
  if( entry->value_data_size != 8 )
270
39
  {
271
39
    libcerror_error_set(
272
39
     error,
273
39
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
274
39
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
275
39
     "%s: invalid B-tree entry - unsupported value data size.",
276
39
     function );
277
278
39
    return( -1 );
279
39
  }
280
1.61k
  if( sub_node_block_number == NULL )
281
0
  {
282
0
    libcerror_error_set(
283
0
     error,
284
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
285
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
286
0
     "%s: invalid sub node block number.",
287
0
     function );
288
289
0
    return( -1 );
290
0
  }
291
1.61k
  byte_stream_copy_to_uint64_little_endian(
292
1.61k
   entry->value_data,
293
1.61k
   sub_node_object_identifier );
294
295
#if defined( HAVE_DEBUG_OUTPUT )
296
  if( libcnotify_verbose != 0 )
297
  {
298
    libcnotify_printf(
299
     "%s: sub node object identifier: %" PRIu64 " (transaction: %" PRIu64 ")\n",
300
     function,
301
     sub_node_object_identifier,
302
     transaction_identifier );
303
  }
304
#endif
305
1.61k
  result = libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
306
1.61k
            snapshot_metadata_tree->object_map_btree,
307
1.61k
            file_io_handle,
308
1.61k
            sub_node_object_identifier,
309
1.61k
            transaction_identifier,
310
1.61k
            &object_map_descriptor,
311
1.61k
            error );
312
313
1.61k
  if( result == -1 )
314
195
  {
315
195
    libcerror_error_set(
316
195
     error,
317
195
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
318
195
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
319
195
     "%s: unable to retrieve object map descriptor for sub node object identifier: %" PRIu64 " (transaction: %" PRIu64 ").",
320
195
     function,
321
195
     sub_node_object_identifier,
322
195
     transaction_identifier );
323
324
195
    goto on_error;
325
195
  }
326
1.42k
  else if( result != 0 )
327
1.22k
  {
328
1.22k
    if( object_map_descriptor == 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 object map descriptor.",
335
0
       function );
336
337
0
      goto on_error;
338
0
    }
339
#if defined( HAVE_DEBUG_OUTPUT )
340
    if( libcnotify_verbose != 0 )
341
    {
342
      libcnotify_printf(
343
       "%s: sub node block number: %" PRIu64 "\n",
344
       function,
345
       object_map_descriptor->physical_address );
346
    }
347
#endif
348
1.22k
    *sub_node_block_number = object_map_descriptor->physical_address;
349
350
1.22k
    if( libfsapfs_object_map_descriptor_free(
351
1.22k
         &object_map_descriptor,
352
1.22k
         error ) != 1 )
353
0
    {
354
0
      libcerror_error_set(
355
0
       error,
356
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
357
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
358
0
       "%s: unable to free object map descriptor.",
359
0
       function );
360
361
0
      goto on_error;
362
0
    }
363
1.22k
  }
364
1.42k
  return( result );
365
366
195
on_error:
367
195
  if( object_map_descriptor != NULL )
368
0
  {
369
0
    libfsapfs_object_map_descriptor_free(
370
0
     &object_map_descriptor,
371
0
     NULL );
372
0
  }
373
195
  return( -1 );
374
1.61k
}
375
376
/* Retrieves the snapshot metadata tree root node
377
 * Returns 1 if successful or -1 on error
378
 */
379
int libfsapfs_snapshot_metadata_tree_get_root_node(
380
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
381
     libbfio_handle_t *file_io_handle,
382
     uint64_t root_node_block_number,
383
     libfsapfs_btree_node_t **root_node,
384
     libcerror_error_t **error )
385
4.08k
{
386
4.08k
  libfcache_cache_value_t *cache_value = NULL;
387
4.08k
  libfsapfs_btree_node_t *node         = NULL;
388
4.08k
  libfsapfs_data_block_t *data_block   = NULL;
389
4.08k
  static char *function                = "libfsapfs_snapshot_metadata_tree_get_root_node";
390
4.08k
  int result                           = 0;
391
392
#if defined( HAVE_PROFILER )
393
  int64_t profiler_start_timestamp     = 0;
394
#endif
395
396
4.08k
  if( snapshot_metadata_tree == NULL )
397
0
  {
398
0
    libcerror_error_set(
399
0
     error,
400
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
401
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
402
0
     "%s: invalid snapshot metadata tree.",
403
0
     function );
404
405
0
    return( -1 );
406
0
  }
407
4.08k
  if( root_node_block_number > (uint64_t) INT_MAX )
408
115
  {
409
115
    libcerror_error_set(
410
115
     error,
411
115
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
412
115
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
413
115
     "%s: invalid root node block number value out of bounds.",
414
115
     function );
415
416
115
    return( -1 );
417
115
  }
418
3.96k
  if( root_node == NULL )
419
0
  {
420
0
    libcerror_error_set(
421
0
     error,
422
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
423
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
424
0
     "%s: invalid root node.",
425
0
     function );
426
427
0
    return( -1 );
428
0
  }
429
#if defined( HAVE_PROFILER )
430
  if( snapshot_metadata_tree->io_handle->profiler != NULL )
431
  {
432
    if( libfsapfs_profiler_start_timing(
433
         snapshot_metadata_tree->io_handle->profiler,
434
         &profiler_start_timestamp,
435
         error ) != 1 )
436
    {
437
      libcerror_error_set(
438
       error,
439
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
440
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
441
       "%s: unable to start timing.",
442
       function );
443
444
      goto on_error;
445
    }
446
  }
447
#endif /* defined( HAVE_PROFILER ) */
448
449
3.96k
  result = libfcache_cache_get_value_by_identifier(
450
3.96k
            snapshot_metadata_tree->node_cache,
451
3.96k
            0,
452
3.96k
            (off64_t) root_node_block_number,
453
3.96k
            0,
454
3.96k
            &cache_value,
455
3.96k
            error );
456
457
3.96k
  if( result == -1 )
458
0
  {
459
0
    libcerror_error_set(
460
0
     error,
461
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
462
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
463
0
     "%s: unable to retrieve value from cache.",
464
0
     function );
465
466
0
    goto on_error;
467
0
  }
468
3.96k
  else if( result == 0 )
469
3.96k
  {
470
3.96k
    if( libfdata_vector_get_element_value_by_index(
471
3.96k
         snapshot_metadata_tree->data_block_vector,
472
3.96k
         (intptr_t *) file_io_handle,
473
3.96k
         (libfdata_cache_t *) snapshot_metadata_tree->data_block_cache,
474
3.96k
         (int) root_node_block_number,
475
3.96k
         (intptr_t **) &data_block,
476
3.96k
         0,
477
3.96k
         error ) != 1 )
478
24
    {
479
24
      libcerror_error_set(
480
24
       error,
481
24
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
482
24
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
483
24
       "%s: unable to retrieve data block: %" PRIu64 ".",
484
24
       function,
485
24
       root_node_block_number );
486
487
24
      goto on_error;
488
24
    }
489
3.94k
    if( data_block == NULL )
490
0
    {
491
0
      libcerror_error_set(
492
0
       error,
493
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
494
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
495
0
       "%s: invalid data block: %" PRIu64 ".",
496
0
       function,
497
0
       root_node_block_number );
498
499
0
      goto on_error;
500
0
    }
501
3.94k
    if( libfsapfs_btree_node_initialize(
502
3.94k
         &node,
503
3.94k
         error ) != 1 )
504
0
    {
505
0
      libcerror_error_set(
506
0
       error,
507
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
508
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
509
0
       "%s: unable to create B-tree node.",
510
0
       function );
511
512
0
      goto on_error;
513
0
    }
514
3.94k
    if( libfsapfs_btree_node_read_data(
515
3.94k
         node,
516
3.94k
         data_block->data,
517
3.94k
         data_block->data_size,
518
3.94k
         error ) != 1 )
519
40
    {
520
40
      libcerror_error_set(
521
40
       error,
522
40
       LIBCERROR_ERROR_DOMAIN_IO,
523
40
       LIBCERROR_IO_ERROR_READ_FAILED,
524
40
       "%s: unable to read B-tree node.",
525
40
       function );
526
527
40
      goto on_error;
528
40
    }
529
3.90k
    if( node->object_type != 0x40000002UL )
530
66
    {
531
66
      libcerror_error_set(
532
66
       error,
533
66
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
534
66
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
535
66
       "%s: invalid object type: 0x%08" PRIx32 ".",
536
66
       function,
537
66
       node->object_type );
538
539
66
      goto on_error;
540
66
    }
541
3.83k
    if( node->object_subtype != 0x00000010UL )
542
126
    {
543
126
      libcerror_error_set(
544
126
       error,
545
126
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
546
126
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
547
126
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
548
126
       function,
549
126
       node->object_subtype );
550
551
126
      goto on_error;
552
126
    }
553
3.71k
    if( ( node->node_header->flags & 0x0001 ) == 0 )
554
4
    {
555
4
      libcerror_error_set(
556
4
       error,
557
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
558
4
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
559
4
       "%s: unsupported flags: 0x%04" PRIx16 ".",
560
4
       function,
561
4
       node->node_header->flags );
562
563
4
      goto on_error;
564
4
    }
565
3.70k
    if( node->footer->node_size != 4096 )
566
70
    {
567
70
      libcerror_error_set(
568
70
       error,
569
70
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
570
70
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
571
70
       "%s: invalid node size value out of bounds.",
572
70
       function );
573
574
70
      goto on_error;
575
70
    }
576
3.63k
    if( node->footer->key_size != 0 )
577
117
    {
578
117
      libcerror_error_set(
579
117
       error,
580
117
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
581
117
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
582
117
       "%s: invalid key size value out of bounds.",
583
117
       function );
584
585
117
      goto on_error;
586
117
    }
587
3.51k
    if( node->footer->value_size != 0 )
588
130
    {
589
130
      libcerror_error_set(
590
130
       error,
591
130
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
592
130
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
593
130
       "%s: invalid value size value out of bounds.",
594
130
       function );
595
596
130
      goto on_error;
597
130
    }
598
3.38k
    if( libfcache_cache_set_value_by_identifier(
599
3.38k
         snapshot_metadata_tree->node_cache,
600
3.38k
         0,
601
3.38k
         (off64_t) root_node_block_number,
602
3.38k
         0,
603
3.38k
         (intptr_t *) node,
604
3.38k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
605
3.38k
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
606
3.38k
         error ) != 1 )
607
0
    {
608
0
      libcerror_error_set(
609
0
       error,
610
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
611
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
612
0
       "%s: unable to set value in cache.",
613
0
       function );
614
615
0
      goto on_error;
616
0
    }
617
3.38k
    node = NULL;
618
619
3.38k
    if( libfcache_cache_get_value_by_identifier(
620
3.38k
         snapshot_metadata_tree->node_cache,
621
3.38k
         0,
622
3.38k
         (off64_t) root_node_block_number,
623
3.38k
         0,
624
3.38k
         &cache_value,
625
3.38k
         error ) != 1 )
626
0
    {
627
0
      libcerror_error_set(
628
0
       error,
629
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
630
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
631
0
       "%s: unable to retrieve value from cache.",
632
0
       function );
633
634
0
      goto on_error;
635
0
    }
636
3.38k
  }
637
#if defined( HAVE_PROFILER )
638
  if( snapshot_metadata_tree->io_handle->profiler != NULL )
639
  {
640
    if( libfsapfs_profiler_stop_timing(
641
         snapshot_metadata_tree->io_handle->profiler,
642
         profiler_start_timestamp,
643
         function,
644
         root_node_block_number * snapshot_metadata_tree->io_handle->block_size,
645
         snapshot_metadata_tree->io_handle->block_size,
646
         error ) != 1 )
647
    {
648
      libcerror_error_set(
649
       error,
650
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
651
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
652
       "%s: unable to stop timing.",
653
       function );
654
655
      goto on_error;
656
    }
657
  }
658
#endif /* defined( HAVE_PROFILER ) */
659
660
3.38k
  if( libfcache_cache_value_get_value(
661
3.38k
       cache_value,
662
3.38k
       (intptr_t **) root_node,
663
3.38k
       error ) != 1 )
664
0
  {
665
0
    libcerror_error_set(
666
0
     error,
667
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
668
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
669
0
     "%s: unable to retrieve root node.",
670
0
     function );
671
672
0
    goto on_error;
673
0
  }
674
3.38k
  return( 1 );
675
676
577
on_error:
677
577
  if( node != NULL )
678
553
  {
679
553
    libfsapfs_btree_node_free(
680
553
     &node,
681
553
     NULL );
682
553
  }
683
577
  return( -1 );
684
3.38k
}
685
686
/* Retrieves a snapshot metadata tree sub node
687
 * Returns 1 if successful or -1 on error
688
 */
689
int libfsapfs_snapshot_metadata_tree_get_sub_node(
690
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
691
     libbfio_handle_t *file_io_handle,
692
     uint64_t sub_node_block_number,
693
     libfsapfs_btree_node_t **sub_node,
694
     libcerror_error_t **error )
695
1.22k
{
696
1.22k
  libfcache_cache_value_t *cache_value = NULL;
697
1.22k
  libfsapfs_btree_node_t *node         = NULL;
698
1.22k
  libfsapfs_data_block_t *data_block   = NULL;
699
1.22k
  static char *function                = "libfsapfs_snapshot_metadata_tree_get_sub_node";
700
1.22k
  int result                           = 0;
701
702
#if defined( HAVE_PROFILER )
703
  int64_t profiler_start_timestamp     = 0;
704
#endif
705
706
1.22k
  if( snapshot_metadata_tree == NULL )
707
0
  {
708
0
    libcerror_error_set(
709
0
     error,
710
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
711
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
712
0
     "%s: invalid snapshot metadata tree.",
713
0
     function );
714
715
0
    return( -1 );
716
0
  }
717
1.22k
  if( sub_node_block_number > (uint64_t) INT_MAX )
718
145
  {
719
145
    libcerror_error_set(
720
145
     error,
721
145
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
722
145
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
723
145
     "%s: invalid sub node block number value out of bounds.",
724
145
     function );
725
726
145
    return( -1 );
727
145
  }
728
1.08k
  if( sub_node == NULL )
729
0
  {
730
0
    libcerror_error_set(
731
0
     error,
732
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
733
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
734
0
     "%s: invalid sub node.",
735
0
     function );
736
737
0
    return( -1 );
738
0
  }
739
#if defined( HAVE_PROFILER )
740
  if( snapshot_metadata_tree->io_handle->profiler != NULL )
741
  {
742
    if( libfsapfs_profiler_start_timing(
743
         snapshot_metadata_tree->io_handle->profiler,
744
         &profiler_start_timestamp,
745
         error ) != 1 )
746
    {
747
      libcerror_error_set(
748
       error,
749
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
750
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
751
       "%s: unable to start timing.",
752
       function );
753
754
      goto on_error;
755
    }
756
  }
757
#endif /* defined( HAVE_PROFILER ) */
758
759
1.08k
  result = libfcache_cache_get_value_by_identifier(
760
1.08k
            snapshot_metadata_tree->node_cache,
761
1.08k
            0,
762
1.08k
            (off64_t) sub_node_block_number,
763
1.08k
            0,
764
1.08k
            &cache_value,
765
1.08k
            error );
766
767
1.08k
  if( result == -1 )
768
0
  {
769
0
    libcerror_error_set(
770
0
     error,
771
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
772
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
773
0
     "%s: unable to retrieve value from cache.",
774
0
     function );
775
776
0
    goto on_error;
777
0
  }
778
1.08k
  else if( result == 0 )
779
234
  {
780
234
    if( libfdata_vector_get_element_value_by_index(
781
234
         snapshot_metadata_tree->data_block_vector,
782
234
         (intptr_t *) file_io_handle,
783
234
         (libfdata_cache_t *) snapshot_metadata_tree->data_block_cache,
784
234
         (int) sub_node_block_number,
785
234
         (intptr_t **) &data_block,
786
234
         0,
787
234
         error ) != 1 )
788
69
    {
789
69
      libcerror_error_set(
790
69
       error,
791
69
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
792
69
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
793
69
       "%s: unable to retrieve data block: %" PRIu64 ".",
794
69
       function,
795
69
       sub_node_block_number );
796
797
69
      goto on_error;
798
69
    }
799
165
    if( data_block == NULL )
800
0
    {
801
0
      libcerror_error_set(
802
0
       error,
803
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
804
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
805
0
       "%s: invalid data block: %" PRIu64 ".",
806
0
       function,
807
0
       sub_node_block_number );
808
809
0
      goto on_error;
810
0
    }
811
165
    if( libfsapfs_btree_node_initialize(
812
165
         &node,
813
165
         error ) != 1 )
814
0
    {
815
0
      libcerror_error_set(
816
0
       error,
817
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
818
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
819
0
       "%s: unable to create B-tree node.",
820
0
       function );
821
822
0
      goto on_error;
823
0
    }
824
165
    if( libfsapfs_btree_node_read_data(
825
165
         node,
826
165
         data_block->data,
827
165
         data_block->data_size,
828
165
         error ) != 1 )
829
6
    {
830
6
      libcerror_error_set(
831
6
       error,
832
6
       LIBCERROR_ERROR_DOMAIN_IO,
833
6
       LIBCERROR_IO_ERROR_READ_FAILED,
834
6
       "%s: unable to read B-tree node.",
835
6
       function );
836
837
6
      goto on_error;
838
6
    }
839
159
    if( node->object_type != 0x40000003UL )
840
26
    {
841
26
      libcerror_error_set(
842
26
       error,
843
26
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
844
26
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
845
26
       "%s: invalid object type: 0x%08" PRIx32 ".",
846
26
       function,
847
26
       node->object_type );
848
849
26
      goto on_error;
850
26
    }
851
133
    if( node->object_subtype != 0x00000010UL )
852
81
    {
853
81
      libcerror_error_set(
854
81
       error,
855
81
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
856
81
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
857
81
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
858
81
       function,
859
81
       node->object_subtype );
860
861
81
      goto on_error;
862
81
    }
863
52
    if( ( node->node_header->flags & 0x0001 ) != 0 )
864
3
    {
865
3
      libcerror_error_set(
866
3
       error,
867
3
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
868
3
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
869
3
       "%s: unsupported flags: 0x%04" PRIx16 ".",
870
3
       function,
871
3
       node->node_header->flags );
872
873
3
      goto on_error;
874
3
    }
875
49
    if( libfcache_cache_set_value_by_identifier(
876
49
         snapshot_metadata_tree->node_cache,
877
49
         0,
878
49
         (off64_t) sub_node_block_number,
879
49
         0,
880
49
         (intptr_t *) node,
881
49
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
882
49
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
883
49
         error ) != 1 )
884
0
    {
885
0
      libcerror_error_set(
886
0
       error,
887
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
888
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
889
0
       "%s: unable to set value in cache.",
890
0
       function );
891
892
0
      goto on_error;
893
0
    }
894
49
    node = NULL;
895
896
49
    if( libfcache_cache_get_value_by_identifier(
897
49
         snapshot_metadata_tree->node_cache,
898
49
         0,
899
49
         (off64_t) sub_node_block_number,
900
49
         0,
901
49
         &cache_value,
902
49
         error ) != 1 )
903
0
    {
904
0
      libcerror_error_set(
905
0
       error,
906
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
907
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
908
0
       "%s: unable to retrieve value from cache.",
909
0
       function );
910
911
0
      goto on_error;
912
0
    }
913
49
  }
914
#if defined( HAVE_PROFILER )
915
  if( snapshot_metadata_tree->io_handle->profiler != NULL )
916
  {
917
    if( libfsapfs_profiler_stop_timing(
918
         snapshot_metadata_tree->io_handle->profiler,
919
         profiler_start_timestamp,
920
         function,
921
         sub_node_block_number * snapshot_metadata_tree->io_handle->block_size,
922
         snapshot_metadata_tree->io_handle->block_size,
923
         error ) != 1 )
924
    {
925
      libcerror_error_set(
926
       error,
927
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
928
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
929
       "%s: unable to stop timing.",
930
       function );
931
932
      goto on_error;
933
    }
934
  }
935
#endif /* defined( HAVE_PROFILER ) */
936
937
899
  if( libfcache_cache_value_get_value(
938
899
       cache_value,
939
899
       (intptr_t **) sub_node,
940
899
       error ) != 1 )
941
0
  {
942
0
    libcerror_error_set(
943
0
     error,
944
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
945
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
946
0
     "%s: unable to retrieve sub node.",
947
0
     function );
948
949
0
    goto on_error;
950
0
  }
951
899
  return( 1 );
952
953
185
on_error:
954
185
  if( node != NULL )
955
116
  {
956
116
    libfsapfs_btree_node_free(
957
116
     &node,
958
116
     NULL );
959
116
  }
960
185
  return( -1 );
961
899
}
962
963
/* Retrieves an entry for a specific identifier from the snapshot metadata tree node
964
 * Returns 1 if successful, 0 if not found or -1 on error
965
 */
966
int libfsapfs_snapshot_metadata_tree_get_entry_from_node_by_identifier(
967
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
968
     libfsapfs_btree_node_t *node,
969
     uint64_t object_identifier,
970
     libfsapfs_btree_entry_t **btree_entry,
971
     libcerror_error_t **error )
972
0
{
973
0
  libfsapfs_btree_entry_t *entry          = NULL;
974
0
  libfsapfs_btree_entry_t *previous_entry = NULL;
975
0
  static char *function                   = "libfsapfs_snapshot_metadata_tree_get_entry_from_node_by_identifier";
976
0
  uint64_t snapshot_metadata_identifier   = 0;
977
0
  uint8_t snapshot_metadata_data_type     = 0;
978
0
  int btree_entry_index                   = 0;
979
0
  int is_leaf_node                        = 0;
980
0
  int number_of_entries                   = 0;
981
982
0
  if( snapshot_metadata_tree == NULL )
983
0
  {
984
0
    libcerror_error_set(
985
0
     error,
986
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
987
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
988
0
     "%s: invalid snapshot metadata tree.",
989
0
     function );
990
991
0
    return( -1 );
992
0
  }
993
0
  if( btree_entry == NULL )
994
0
  {
995
0
    libcerror_error_set(
996
0
     error,
997
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
998
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
999
0
     "%s: invalid B-tree entry.",
1000
0
     function );
1001
1002
0
    return( -1 );
1003
0
  }
1004
#if defined( HAVE_DEBUG_OUTPUT )
1005
  if( libcnotify_verbose != 0 )
1006
  {
1007
    libcnotify_printf(
1008
     "%s: retrieving B-tree entry identifier: %" PRIu64 ".\n",
1009
     function,
1010
     object_identifier );
1011
  }
1012
#endif
1013
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1014
0
                  node,
1015
0
                  error );
1016
1017
0
  if( is_leaf_node == -1 )
1018
0
  {
1019
0
    libcerror_error_set(
1020
0
     error,
1021
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1022
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1023
0
     "%s: unable to determine if B-tree node is a leaf node.",
1024
0
     function );
1025
1026
0
    return( -1 );
1027
0
  }
1028
0
  if( libfsapfs_btree_node_get_number_of_entries(
1029
0
       node,
1030
0
       &number_of_entries,
1031
0
       error ) != 1 )
1032
0
  {
1033
0
    libcerror_error_set(
1034
0
     error,
1035
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1036
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1037
0
     "%s: unable to retrieve number of entries from B-tree node.",
1038
0
     function );
1039
1040
0
    return( -1 );
1041
0
  }
1042
0
  for( btree_entry_index = 0;
1043
0
       btree_entry_index < number_of_entries;
1044
0
       btree_entry_index++ )
1045
0
  {
1046
0
    if( libfsapfs_btree_node_get_entry_by_index(
1047
0
         node,
1048
0
         btree_entry_index,
1049
0
         &entry,
1050
0
         error ) != 1 )
1051
0
    {
1052
0
      libcerror_error_set(
1053
0
       error,
1054
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1055
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1056
0
       "%s: unable to retrieve number of entries from B-tree node.",
1057
0
       function );
1058
1059
0
      return( -1 );
1060
0
    }
1061
0
    if( entry == NULL )
1062
0
    {
1063
0
      libcerror_error_set(
1064
0
       error,
1065
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1066
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1067
0
       "%s: invalid B-tree entry: %d.",
1068
0
       function,
1069
0
       btree_entry_index );
1070
1071
0
      return( -1 );
1072
0
    }
1073
0
    if( entry->key_data == NULL )
1074
0
    {
1075
0
      libcerror_error_set(
1076
0
       error,
1077
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1078
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1079
0
       "%s: invalid B-tree entry: %d - missing key data.",
1080
0
       function,
1081
0
       btree_entry_index );
1082
1083
0
      return( -1 );
1084
0
    }
1085
0
    if( entry->key_data_size < 8 )
1086
0
    {
1087
0
      libcerror_error_set(
1088
0
       error,
1089
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1090
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1091
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1092
0
       function,
1093
0
       btree_entry_index );
1094
1095
0
      return( -1 );
1096
0
    }
1097
0
    byte_stream_copy_to_uint64_little_endian(
1098
0
     entry->key_data,
1099
0
     snapshot_metadata_identifier );
1100
1101
0
    snapshot_metadata_data_type = (uint8_t) ( snapshot_metadata_identifier >> 60 );
1102
1103
#if defined( HAVE_DEBUG_OUTPUT )
1104
    if( libcnotify_verbose != 0 )
1105
    {
1106
      libcnotify_printf(
1107
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
1108
       function,
1109
       btree_entry_index,
1110
       snapshot_metadata_identifier & 0x0fffffffffffffffUL,
1111
       snapshot_metadata_data_type,
1112
       libfsapfs_debug_print_file_system_data_type(
1113
        snapshot_metadata_data_type ) );
1114
    }
1115
#endif
1116
0
    snapshot_metadata_identifier &= 0x0fffffffffffffffUL;
1117
1118
0
    if( is_leaf_node != 0 )
1119
0
    {
1120
0
      if( snapshot_metadata_identifier == object_identifier )
1121
0
      {
1122
0
        *btree_entry = entry;
1123
1124
0
        return( 1 );
1125
0
      }
1126
0
    }
1127
0
    else
1128
0
    {
1129
0
      if( snapshot_metadata_identifier >= object_identifier )
1130
0
      {
1131
0
        if( ( previous_entry == NULL )
1132
0
         || ( snapshot_metadata_identifier == object_identifier ) )
1133
0
        {
1134
0
          previous_entry = entry;
1135
0
        }
1136
0
        *btree_entry = previous_entry;
1137
1138
0
        return( 1 );
1139
0
      }
1140
0
      previous_entry = entry;
1141
0
    }
1142
0
  }
1143
0
  if( is_leaf_node == 0 )
1144
0
  {
1145
0
    *btree_entry = previous_entry;
1146
1147
0
    return( 1 );
1148
0
  }
1149
0
  return( 0 );
1150
0
}
1151
1152
/* Retrieves an entry for a specific identifier from the snapshot metadata tree
1153
 * Returns 1 if successful, 0 if not found or -1 on error
1154
 */
1155
int libfsapfs_snapshot_metadata_tree_get_entry_by_identifier(
1156
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
1157
     libbfio_handle_t *file_io_handle,
1158
     uint64_t object_identifier,
1159
     libfsapfs_btree_node_t **btree_node,
1160
     libfsapfs_btree_entry_t **btree_entry,
1161
     libcerror_error_t **error )
1162
0
{
1163
0
  libfsapfs_btree_entry_t *entry = NULL;
1164
0
  libfsapfs_btree_node_t *node   = NULL;
1165
0
  static char *function          = "libfsapfs_snapshot_metadata_tree_get_entry_by_identifier";
1166
0
  uint64_t sub_node_block_number = 0;
1167
0
  int is_leaf_node               = 0;
1168
0
  int recursion_depth            = 0;
1169
0
  int result                     = 0;
1170
1171
0
  if( snapshot_metadata_tree == NULL )
1172
0
  {
1173
0
    libcerror_error_set(
1174
0
     error,
1175
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1176
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1177
0
     "%s: invalid snapshot metadata tree.",
1178
0
     function );
1179
1180
0
    return( -1 );
1181
0
  }
1182
0
  if( btree_node == NULL )
1183
0
  {
1184
0
    libcerror_error_set(
1185
0
     error,
1186
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1187
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1188
0
     "%s: invalid B-tree node.",
1189
0
     function );
1190
1191
0
    return( -1 );
1192
0
  }
1193
0
  if( btree_entry == NULL )
1194
0
  {
1195
0
    libcerror_error_set(
1196
0
     error,
1197
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1198
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1199
0
     "%s: invalid B-tree entry.",
1200
0
     function );
1201
1202
0
    return( -1 );
1203
0
  }
1204
0
  if( libfsapfs_snapshot_metadata_tree_get_root_node(
1205
0
       snapshot_metadata_tree,
1206
0
       file_io_handle,
1207
0
       snapshot_metadata_tree->root_node_block_number,
1208
0
       &node,
1209
0
       error ) != 1 )
1210
0
  {
1211
0
    libcerror_error_set(
1212
0
     error,
1213
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1214
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1215
0
     "%s: unable to retrieve B-tree root node.",
1216
0
     function );
1217
1218
0
    return( -1 );
1219
0
  }
1220
0
  do
1221
0
  {
1222
0
    if( ( recursion_depth < 0 )
1223
0
     || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1224
0
    {
1225
0
      libcerror_error_set(
1226
0
       error,
1227
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1228
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1229
0
       "%s: invalid recursion depth value out of bounds.",
1230
0
       function );
1231
1232
0
      return( -1 );
1233
0
    }
1234
0
    is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1235
0
                    node,
1236
0
                    error );
1237
1238
0
    if( is_leaf_node == -1 )
1239
0
    {
1240
0
      libcerror_error_set(
1241
0
       error,
1242
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1243
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1244
0
       "%s: unable to determine if B-tree node is a leaf node.",
1245
0
       function );
1246
1247
0
      return( -1 );
1248
0
    }
1249
0
    result = libfsapfs_snapshot_metadata_tree_get_entry_from_node_by_identifier(
1250
0
              snapshot_metadata_tree,
1251
0
              node,
1252
0
              object_identifier,
1253
0
              &entry,
1254
0
              error );
1255
1256
0
    if( result == -1 )
1257
0
    {
1258
0
      libcerror_error_set(
1259
0
       error,
1260
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1261
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1262
0
       "%s: unable to retrieve entry from B-tree node.",
1263
0
       function );
1264
1265
0
      return( -1 );
1266
0
    }
1267
0
    else if( result == 0 )
1268
0
    {
1269
0
      break;
1270
0
    }
1271
0
    if( is_leaf_node != 0 )
1272
0
    {
1273
0
      *btree_node  = node;
1274
0
      *btree_entry = entry;
1275
1276
0
      return( 1 );
1277
0
    }
1278
0
    if( entry == NULL )
1279
0
    {
1280
0
      libcerror_error_set(
1281
0
       error,
1282
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1283
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1284
0
       "%s: invalid B-tree entry.",
1285
0
       function );
1286
1287
0
      return( -1 );
1288
0
    }
1289
0
    if( entry->value_data == NULL )
1290
0
    {
1291
0
      libcerror_error_set(
1292
0
       error,
1293
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1294
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1295
0
       "%s: invalid B-tree entry - missing value data.",
1296
0
       function );
1297
1298
0
      return( -1 );
1299
0
    }
1300
0
    if( entry->value_data_size != 8 )
1301
0
    {
1302
0
      libcerror_error_set(
1303
0
       error,
1304
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1305
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1306
0
       "%s: invalid B-tree entry - unsupported value data size.",
1307
0
       function );
1308
1309
0
      return( -1 );
1310
0
    }
1311
0
    byte_stream_copy_to_uint64_little_endian(
1312
0
     entry->value_data,
1313
0
     sub_node_block_number );
1314
1315
#if defined( HAVE_DEBUG_OUTPUT )
1316
    if( libcnotify_verbose != 0 )
1317
    {
1318
      libcnotify_printf(
1319
       "%s: B-tree sub node block number: %" PRIu64 "\n",
1320
       function,
1321
       sub_node_block_number );
1322
    }
1323
#endif
1324
0
    node = NULL;
1325
1326
0
    if( libfsapfs_snapshot_metadata_tree_get_sub_node(
1327
0
         snapshot_metadata_tree,
1328
0
         file_io_handle,
1329
0
         sub_node_block_number,
1330
0
         &node,
1331
0
         error ) != 1 )
1332
0
    {
1333
0
      libcerror_error_set(
1334
0
       error,
1335
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1336
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1337
0
       "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1338
0
       function,
1339
0
       sub_node_block_number );
1340
1341
0
      return( -1 );
1342
0
    }
1343
0
    recursion_depth++;
1344
0
  }
1345
0
  while( is_leaf_node == 0 );
1346
1347
0
  return( 0 );
1348
0
}
1349
1350
/* Retrieves the snapshot metadata of a specific object identifier
1351
 * Returns 1 if successful, 0 if no such value or -1 on error
1352
 */
1353
int libfsapfs_snapshot_metadata_tree_get_metadata_by_object_identifier(
1354
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
1355
     libbfio_handle_t *file_io_handle,
1356
     uint64_t object_identifier,
1357
     libfsapfs_snapshot_metadata_t **metadata,
1358
     libcerror_error_t **error )
1359
0
{
1360
0
  libfsapfs_btree_entry_t *entry = NULL;
1361
0
  libfsapfs_btree_node_t *node   = NULL;
1362
0
  static char *function          = "libfsapfs_snapshot_metadata_tree_get_metadata_by_object_identifier";
1363
0
  int result                     = 0;
1364
1365
0
  if( snapshot_metadata_tree == NULL )
1366
0
  {
1367
0
    libcerror_error_set(
1368
0
     error,
1369
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1370
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1371
0
     "%s: invalid snapshot metadata tree.",
1372
0
     function );
1373
1374
0
    return( -1 );
1375
0
  }
1376
0
  if( metadata == NULL )
1377
0
  {
1378
0
    libcerror_error_set(
1379
0
     error,
1380
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1381
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1382
0
     "%s: invalid metadata.",
1383
0
     function );
1384
1385
0
    return( -1 );
1386
0
  }
1387
0
  if( *metadata != NULL )
1388
0
  {
1389
0
    libcerror_error_set(
1390
0
     error,
1391
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1392
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1393
0
     "%s: invalid metadata value already set.",
1394
0
     function );
1395
1396
0
    return( -1 );
1397
0
  }
1398
0
  result = libfsapfs_snapshot_metadata_tree_get_entry_by_identifier(
1399
0
            snapshot_metadata_tree,
1400
0
            file_io_handle,
1401
0
            object_identifier,
1402
0
            &node,
1403
0
            &entry,
1404
0
            error );
1405
1406
0
  if( result == -1 )
1407
0
  {
1408
0
    libcerror_error_set(
1409
0
     error,
1410
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1411
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1412
0
     "%s: unable to retrieve entry from B-tree.",
1413
0
     function );
1414
1415
0
    goto on_error;
1416
0
  }
1417
0
  else if( result != 0 )
1418
0
  {
1419
0
    if( node == NULL )
1420
0
    {
1421
0
      libcerror_error_set(
1422
0
       error,
1423
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1424
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1425
0
       "%s: invalid B-tree node.",
1426
0
       function );
1427
1428
0
      goto on_error;
1429
0
    }
1430
0
    if( entry == NULL )
1431
0
    {
1432
0
      libcerror_error_set(
1433
0
       error,
1434
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1435
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1436
0
       "%s: invalid B-tree entry.",
1437
0
       function );
1438
1439
0
      goto on_error;
1440
0
    }
1441
0
    if( libfsapfs_snapshot_metadata_initialize(
1442
0
         metadata,
1443
0
         error ) != 1 )
1444
0
    {
1445
0
      libcerror_error_set(
1446
0
       error,
1447
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1448
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1449
0
       "%s: unable to create snapshot metadata.",
1450
0
       function );
1451
1452
0
      goto on_error;
1453
0
    }
1454
0
    if( libfsapfs_snapshot_metadata_read_key_data(
1455
0
         *metadata,
1456
0
         entry->key_data,
1457
0
         (size_t) entry->key_data_size,
1458
0
         error ) != 1 )
1459
0
    {
1460
0
      libcerror_error_set(
1461
0
       error,
1462
0
       LIBCERROR_ERROR_DOMAIN_IO,
1463
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1464
0
       "%s: unable to read snapshot metadata key data.",
1465
0
       function );
1466
1467
0
      goto on_error;
1468
0
    }
1469
0
    if( libfsapfs_snapshot_metadata_read_value_data(
1470
0
         *metadata,
1471
0
         entry->value_data,
1472
0
         (size_t) entry->value_data_size,
1473
0
         error ) != 1 )
1474
0
    {
1475
0
      libcerror_error_set(
1476
0
       error,
1477
0
       LIBCERROR_ERROR_DOMAIN_IO,
1478
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1479
0
       "%s: unable to read snapshot metadata value data.",
1480
0
       function );
1481
1482
0
      goto on_error;
1483
0
    }
1484
0
    node = NULL;
1485
0
  }
1486
0
  return( result );
1487
1488
0
on_error:
1489
0
  if( *metadata != NULL )
1490
0
  {
1491
0
    libfsapfs_snapshot_metadata_free(
1492
0
     metadata,
1493
0
     NULL );
1494
0
  }
1495
0
  return( -1 );
1496
0
}
1497
1498
/* Retrieves snapshots for a specific parent identifier from the snapshot metadata tree leaf node
1499
 * Returns 1 if successful, 0 if not found or -1 on error
1500
 */
1501
int libfsapfs_snapshot_metadata_tree_get_snapshots_from_leaf_node(
1502
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
1503
     libfsapfs_btree_node_t *node,
1504
     libcdata_array_t *snapshots,
1505
     libcerror_error_t **error )
1506
2.38k
{
1507
2.38k
  libfsapfs_btree_entry_t *entry                   = NULL;
1508
2.38k
  libfsapfs_snapshot_metadata_t *snapshot_metadata = NULL;
1509
2.38k
  static char *function                            = "libfsapfs_snapshot_metadata_tree_get_snapshots_from_leaf_node";
1510
2.38k
  uint64_t snapshot_metadata_identifier            = 0;
1511
2.38k
  uint8_t snapshot_metadata_data_type              = 0;
1512
2.38k
  int btree_entry_index                            = 0;
1513
2.38k
  int entry_index                                  = 0;
1514
2.38k
  int found_snapshot_metadata                      = 0;
1515
2.38k
  int is_leaf_node                                 = 0;
1516
2.38k
  int number_of_entries                            = 0;
1517
1518
2.38k
  if( snapshot_metadata_tree == NULL )
1519
0
  {
1520
0
    libcerror_error_set(
1521
0
     error,
1522
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1523
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1524
0
     "%s: invalid snapshot metadata tree.",
1525
0
     function );
1526
1527
0
    return( -1 );
1528
0
  }
1529
2.38k
  if( node == NULL )
1530
0
  {
1531
0
    libcerror_error_set(
1532
0
     error,
1533
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1534
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1535
0
     "%s: invalid node.",
1536
0
     function );
1537
1538
0
    return( -1 );
1539
0
  }
1540
2.38k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1541
2.38k
                  node,
1542
2.38k
                  error );
1543
1544
2.38k
  if( is_leaf_node == -1 )
1545
0
  {
1546
0
    libcerror_error_set(
1547
0
     error,
1548
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1549
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1550
0
     "%s: unable to determine if B-tree node is a leaf node.",
1551
0
     function );
1552
1553
0
    goto on_error;
1554
0
  }
1555
2.38k
  else if( is_leaf_node == 0 )
1556
0
  {
1557
0
    libcerror_error_set(
1558
0
     error,
1559
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1560
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1561
0
     "%s: invalid node - not a leaf node.",
1562
0
     function );
1563
1564
0
    goto on_error;
1565
0
  }
1566
2.38k
  if( libfsapfs_btree_node_get_number_of_entries(
1567
2.38k
       node,
1568
2.38k
       &number_of_entries,
1569
2.38k
       error ) != 1 )
1570
0
  {
1571
0
    libcerror_error_set(
1572
0
     error,
1573
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1574
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1575
0
     "%s: unable to retrieve number of entries from B-tree node.",
1576
0
     function );
1577
1578
0
    goto on_error;
1579
0
  }
1580
2.38k
  for( btree_entry_index = 0;
1581
2.54k
       btree_entry_index < number_of_entries;
1582
2.38k
       btree_entry_index++ )
1583
390
  {
1584
390
    if( libfsapfs_btree_node_get_entry_by_index(
1585
390
         node,
1586
390
         btree_entry_index,
1587
390
         &entry,
1588
390
         error ) != 1 )
1589
0
    {
1590
0
      libcerror_error_set(
1591
0
       error,
1592
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1593
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1594
0
       "%s: unable to retrieve number of entries from B-tree node.",
1595
0
       function );
1596
1597
0
      goto on_error;
1598
0
    }
1599
390
    if( entry == NULL )
1600
0
    {
1601
0
      libcerror_error_set(
1602
0
       error,
1603
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1604
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1605
0
       "%s: invalid B-tree entry: %d.",
1606
0
       function,
1607
0
       btree_entry_index );
1608
1609
0
      goto on_error;
1610
0
    }
1611
390
    if( entry->key_data == NULL )
1612
15
    {
1613
15
      libcerror_error_set(
1614
15
       error,
1615
15
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1616
15
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1617
15
       "%s: invalid B-tree entry: %d - missing key data.",
1618
15
       function,
1619
15
       btree_entry_index );
1620
1621
15
      goto on_error;
1622
15
    }
1623
375
    if( entry->key_data_size < 8 )
1624
8
    {
1625
8
      libcerror_error_set(
1626
8
       error,
1627
8
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1628
8
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1629
8
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1630
8
       function,
1631
8
       btree_entry_index );
1632
1633
8
      return( -1 );
1634
8
    }
1635
367
    byte_stream_copy_to_uint64_little_endian(
1636
367
     entry->key_data,
1637
367
     snapshot_metadata_identifier );
1638
1639
367
    snapshot_metadata_data_type = (uint8_t) ( snapshot_metadata_identifier >> 60 );
1640
1641
#if defined( HAVE_DEBUG_OUTPUT )
1642
    if( libcnotify_verbose != 0 )
1643
    {
1644
      libcnotify_printf(
1645
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
1646
       function,
1647
       btree_entry_index,
1648
       snapshot_metadata_identifier & 0x0fffffffffffffffUL,
1649
       snapshot_metadata_data_type,
1650
       libfsapfs_debug_print_file_system_data_type(
1651
        snapshot_metadata_data_type ) );
1652
    }
1653
#endif
1654
367
    if( snapshot_metadata_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_SNAPSHOT_METADATA )
1655
89
    {
1656
89
      break;
1657
89
    }
1658
278
    if( libfsapfs_snapshot_metadata_initialize(
1659
278
         &snapshot_metadata,
1660
278
         error ) != 1 )
1661
0
    {
1662
0
      libcerror_error_set(
1663
0
       error,
1664
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1665
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1666
0
       "%s: unable to create snapshot metadata.",
1667
0
       function );
1668
1669
0
      goto on_error;
1670
0
    }
1671
278
    if( libfsapfs_snapshot_metadata_read_key_data(
1672
278
         snapshot_metadata,
1673
278
         entry->key_data,
1674
278
         (size_t) entry->key_data_size,
1675
278
         error ) != 1 )
1676
0
    {
1677
0
      libcerror_error_set(
1678
0
       error,
1679
0
       LIBCERROR_ERROR_DOMAIN_IO,
1680
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1681
0
       "%s: unable to read snapshot metadata key data.",
1682
0
       function );
1683
1684
0
      goto on_error;
1685
0
    }
1686
278
    if( libfsapfs_snapshot_metadata_read_value_data(
1687
278
         snapshot_metadata,
1688
278
         entry->value_data,
1689
278
         (size_t) entry->value_data_size,
1690
278
         error ) != 1 )
1691
115
    {
1692
115
      libcerror_error_set(
1693
115
       error,
1694
115
       LIBCERROR_ERROR_DOMAIN_IO,
1695
115
       LIBCERROR_IO_ERROR_READ_FAILED,
1696
115
       "%s: unable to read snapshot metadata value data.",
1697
115
       function );
1698
1699
115
      goto on_error;
1700
115
    }
1701
163
    if( libcdata_array_append_entry(
1702
163
         snapshots,
1703
163
         &entry_index,
1704
163
         (intptr_t *) snapshot_metadata,
1705
163
         error ) != 1 )
1706
0
    {
1707
0
      libcerror_error_set(
1708
0
       error,
1709
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1710
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1711
0
       "%s: unable to append snapshot metadata to array.",
1712
0
       function );
1713
1714
0
      goto on_error;
1715
0
    }
1716
163
    snapshot_metadata = NULL;
1717
1718
163
    found_snapshot_metadata = 1;
1719
163
  }
1720
2.24k
  return( found_snapshot_metadata );
1721
1722
130
on_error:
1723
130
  if( snapshot_metadata != NULL )
1724
115
  {
1725
115
    libfsapfs_snapshot_metadata_free(
1726
115
     &snapshot_metadata,
1727
115
     NULL );
1728
115
  }
1729
130
  libcdata_array_empty(
1730
130
   snapshots,
1731
130
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
1732
130
   NULL );
1733
1734
130
  return( -1 );
1735
2.38k
}
1736
1737
/* Retrieves snapshots for a specific parent identifier from the snapshot metadata tree branch node
1738
 * Returns 1 if successful, 0 if not found or -1 on error
1739
 */
1740
int libfsapfs_snapshot_metadata_tree_get_snapshots_from_branch_node(
1741
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
1742
     libbfio_handle_t *file_io_handle,
1743
     libfsapfs_btree_node_t *node,
1744
     uint64_t transaction_identifier,
1745
     libcdata_array_t *snapshots,
1746
     int recursion_depth,
1747
     libcerror_error_t **error )
1748
1.90k
{
1749
1.90k
  libfsapfs_btree_entry_t *entry        = NULL;
1750
1.90k
  libfsapfs_btree_node_t *sub_node      = NULL;
1751
1.90k
  static char *function                 = "libfsapfs_snapshot_metadata_tree_get_snapshots_from_branch_node";
1752
1.90k
  uint64_t snapshot_metadata_identifier = 0;
1753
1.90k
  uint64_t sub_node_block_number        = 0;
1754
1.90k
  uint8_t snapshot_metadata_data_type   = 0;
1755
1.90k
  int entry_index                       = 0;
1756
1.90k
  int found_snapshot_metadata           = 0;
1757
1.90k
  int is_leaf_node                      = 0;
1758
1.90k
  int number_of_entries                 = 0;
1759
1.90k
  int result                            = 0;
1760
1761
1.90k
  if( snapshot_metadata_tree == NULL )
1762
0
  {
1763
0
    libcerror_error_set(
1764
0
     error,
1765
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1766
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1767
0
     "%s: invalid snapshot metadata tree.",
1768
0
     function );
1769
1770
0
    return( -1 );
1771
0
  }
1772
1.90k
  if( node == NULL )
1773
0
  {
1774
0
    libcerror_error_set(
1775
0
     error,
1776
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1777
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1778
0
     "%s: invalid node.",
1779
0
     function );
1780
1781
0
    return( -1 );
1782
0
  }
1783
1.90k
  if( ( recursion_depth < 0 )
1784
1.90k
   || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1785
3
  {
1786
3
    libcerror_error_set(
1787
3
     error,
1788
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1789
3
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1790
3
     "%s: invalid recursion depth value out of bounds.",
1791
3
     function );
1792
1793
3
    return( -1 );
1794
3
  }
1795
1.90k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1796
1.90k
                  node,
1797
1.90k
                  error );
1798
1799
1.90k
  if( is_leaf_node == -1 )
1800
0
  {
1801
0
    libcerror_error_set(
1802
0
     error,
1803
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1804
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1805
0
     "%s: unable to determine if B-tree node is a leaf node.",
1806
0
     function );
1807
1808
0
    goto on_error;
1809
0
  }
1810
1.90k
  else if( is_leaf_node != 0 )
1811
0
  {
1812
0
    libcerror_error_set(
1813
0
     error,
1814
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1815
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1816
0
     "%s: invalid node - not a branch node.",
1817
0
     function );
1818
1819
0
    goto on_error;
1820
0
  }
1821
1.90k
  if( libfsapfs_btree_node_get_number_of_entries(
1822
1.90k
       node,
1823
1.90k
       &number_of_entries,
1824
1.90k
       error ) != 1 )
1825
0
  {
1826
0
    libcerror_error_set(
1827
0
     error,
1828
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1829
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1830
0
     "%s: unable to retrieve number of entries from B-tree node.",
1831
0
     function );
1832
1833
0
    goto on_error;
1834
0
  }
1835
1.90k
  for( entry_index = 0;
1836
2.02k
       entry_index < number_of_entries;
1837
1.90k
       entry_index++ )
1838
1.72k
  {
1839
1.72k
    if( libfsapfs_btree_node_get_entry_by_index(
1840
1.72k
         node,
1841
1.72k
         entry_index,
1842
1.72k
         &entry,
1843
1.72k
         error ) != 1 )
1844
0
    {
1845
0
      libcerror_error_set(
1846
0
       error,
1847
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1848
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1849
0
       "%s: unable to retrieve number of entries from B-tree node.",
1850
0
       function );
1851
1852
0
      goto on_error;
1853
0
    }
1854
1.72k
    if( entry == NULL )
1855
0
    {
1856
0
      libcerror_error_set(
1857
0
       error,
1858
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1859
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1860
0
       "%s: invalid B-tree entry: %d.",
1861
0
       function,
1862
0
       entry_index );
1863
1864
0
      goto on_error;
1865
0
    }
1866
1.72k
    if( entry->key_data == NULL )
1867
9
    {
1868
9
      libcerror_error_set(
1869
9
       error,
1870
9
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1871
9
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1872
9
       "%s: invalid B-tree entry: %d - missing key data.",
1873
9
       function,
1874
9
       entry_index );
1875
1876
9
      goto on_error;
1877
9
    }
1878
1.71k
    if( entry->key_data_size < 8 )
1879
9
    {
1880
9
      libcerror_error_set(
1881
9
       error,
1882
9
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1883
9
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1884
9
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1885
9
       function,
1886
9
       entry_index );
1887
1888
9
      goto on_error;
1889
9
    }
1890
1.70k
    byte_stream_copy_to_uint64_little_endian(
1891
1.70k
     entry->key_data,
1892
1.70k
     snapshot_metadata_identifier );
1893
1894
1.70k
    snapshot_metadata_data_type = (uint8_t) ( snapshot_metadata_identifier >> 60 );
1895
1896
#if defined( HAVE_DEBUG_OUTPUT )
1897
    if( libcnotify_verbose != 0 )
1898
    {
1899
      libcnotify_printf(
1900
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
1901
       function,
1902
       entry_index,
1903
       snapshot_metadata_identifier & 0x0fffffffffffffffUL,
1904
       snapshot_metadata_data_type,
1905
       libfsapfs_debug_print_file_system_data_type(
1906
        snapshot_metadata_data_type ) );
1907
    }
1908
#endif
1909
1.70k
    if( snapshot_metadata_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_SNAPSHOT_METADATA )
1910
37
    {
1911
37
      break;
1912
37
    }
1913
1.66k
    if( libfsapfs_snapshot_metadata_tree_get_sub_node_block_number_from_entry(
1914
1.66k
         snapshot_metadata_tree,
1915
1.66k
         file_io_handle,
1916
1.66k
         entry,
1917
1.66k
         transaction_identifier,
1918
1.66k
         &sub_node_block_number,
1919
1.66k
         error ) != 1 )
1920
436
    {
1921
436
      libcerror_error_set(
1922
436
       error,
1923
436
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1924
436
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1925
436
       "%s: unable to determine sub node block number.",
1926
436
       function );
1927
1928
436
      goto on_error;
1929
436
    }
1930
1.22k
    if( libfsapfs_snapshot_metadata_tree_get_sub_node(
1931
1.22k
         snapshot_metadata_tree,
1932
1.22k
         file_io_handle,
1933
1.22k
         sub_node_block_number,
1934
1.22k
         &sub_node,
1935
1.22k
         error ) != 1 )
1936
330
    {
1937
330
      libcerror_error_set(
1938
330
       error,
1939
330
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1940
330
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1941
330
       "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1942
330
       function,
1943
330
       sub_node_block_number );
1944
1945
330
      goto on_error;
1946
330
    }
1947
899
    is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1948
899
                    sub_node,
1949
899
                    error );
1950
1951
899
    if( is_leaf_node == -1 )
1952
0
    {
1953
0
      libcerror_error_set(
1954
0
       error,
1955
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1956
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1957
0
       "%s: unable to determine if B-tree sub node is a leaf node.",
1958
0
       function );
1959
1960
0
      goto on_error;
1961
0
    }
1962
899
    if( is_leaf_node != 0 )
1963
62
    {
1964
62
      result = libfsapfs_snapshot_metadata_tree_get_snapshots_from_leaf_node(
1965
62
                snapshot_metadata_tree,
1966
62
                sub_node,
1967
62
                snapshots,
1968
62
                error );
1969
62
    }
1970
837
    else
1971
837
    {
1972
837
      result = libfsapfs_snapshot_metadata_tree_get_snapshots_from_branch_node(
1973
837
                snapshot_metadata_tree,
1974
837
                file_io_handle,
1975
837
                sub_node,
1976
837
                transaction_identifier,
1977
837
                snapshots,
1978
837
                recursion_depth + 1,
1979
837
                error );
1980
837
    }
1981
899
    if( result == -1 )
1982
775
    {
1983
775
      libcerror_error_set(
1984
775
       error,
1985
775
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1986
775
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1987
775
       "%s: unable to retrieve snapshots from snapshot metadata tree sub node.",
1988
775
       function );
1989
1990
775
      goto on_error;
1991
775
    }
1992
124
    else if( result != 0 )
1993
0
    {
1994
0
      found_snapshot_metadata = 1;
1995
0
    }
1996
124
    sub_node = NULL;
1997
124
  }
1998
344
  return( found_snapshot_metadata );
1999
2000
1.55k
on_error:
2001
1.55k
  libcdata_array_empty(
2002
1.55k
   snapshots,
2003
1.55k
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
2004
1.55k
   NULL );
2005
2006
1.55k
  return( -1 );
2007
1.90k
}
2008
2009
/* Retrieves snapshots for a specific parent identifier from the snapshot metadata tree
2010
 * Returns 1 if successful, 0 if not found or -1 on error
2011
 */
2012
int libfsapfs_snapshot_metadata_tree_get_snapshots(
2013
     libfsapfs_snapshot_metadata_tree_t *snapshot_metadata_tree,
2014
     libbfio_handle_t *file_io_handle,
2015
     uint64_t transaction_identifier,
2016
     libcdata_array_t *snapshots,
2017
     libcerror_error_t **error )
2018
4.08k
{
2019
4.08k
  libfsapfs_btree_node_t *root_node = NULL;
2020
4.08k
  static char *function             = "libfsapfs_snapshot_metadata_tree_get_snapshots";
2021
4.08k
  int is_leaf_node                  = 0;
2022
4.08k
  int result                        = 0;
2023
2024
#if defined( HAVE_PROFILER )
2025
  int64_t profiler_start_timestamp  = 0;
2026
#endif
2027
2028
4.08k
  if( snapshot_metadata_tree == NULL )
2029
0
  {
2030
0
    libcerror_error_set(
2031
0
     error,
2032
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2033
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2034
0
     "%s: invalid snapshot metadata tree.",
2035
0
     function );
2036
2037
0
    return( -1 );
2038
0
  }
2039
#if defined( HAVE_PROFILER )
2040
  if( snapshot_metadata_tree->io_handle->profiler != NULL )
2041
  {
2042
    if( libfsapfs_profiler_start_timing(
2043
         snapshot_metadata_tree->io_handle->profiler,
2044
         &profiler_start_timestamp,
2045
         error ) != 1 )
2046
    {
2047
      libcerror_error_set(
2048
       error,
2049
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2050
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2051
       "%s: unable to start timing.",
2052
       function );
2053
2054
      goto on_error;
2055
    }
2056
  }
2057
#endif /* defined( HAVE_PROFILER ) */
2058
2059
4.08k
  if( libfsapfs_snapshot_metadata_tree_get_root_node(
2060
4.08k
       snapshot_metadata_tree,
2061
4.08k
       file_io_handle,
2062
4.08k
       snapshot_metadata_tree->root_node_block_number,
2063
4.08k
       &root_node,
2064
4.08k
       error ) != 1 )
2065
692
  {
2066
692
    libcerror_error_set(
2067
692
     error,
2068
692
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2069
692
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2070
692
     "%s: unable to retrieve B-tree root node.",
2071
692
     function );
2072
2073
692
    goto on_error;
2074
692
  }
2075
3.38k
  if( root_node == NULL )
2076
0
  {
2077
0
    libcerror_error_set(
2078
0
     error,
2079
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2080
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2081
0
     "%s: invalid B-tree root node.",
2082
0
     function );
2083
2084
0
    goto on_error;
2085
0
  }
2086
3.38k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
2087
3.38k
                  root_node,
2088
3.38k
                  error );
2089
2090
3.38k
  if( is_leaf_node == -1 )
2091
0
  {
2092
0
    libcerror_error_set(
2093
0
     error,
2094
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2095
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2096
0
     "%s: unable to determine if B-tree root node is a leaf node.",
2097
0
     function );
2098
2099
0
    goto on_error;
2100
0
  }
2101
3.38k
  if( is_leaf_node != 0 )
2102
2.32k
  {
2103
2.32k
    result = libfsapfs_snapshot_metadata_tree_get_snapshots_from_leaf_node(
2104
2.32k
              snapshot_metadata_tree,
2105
2.32k
              root_node,
2106
2.32k
              snapshots,
2107
2.32k
              error );
2108
2.32k
  }
2109
1.06k
  else
2110
1.06k
  {
2111
1.06k
    result = libfsapfs_snapshot_metadata_tree_get_snapshots_from_branch_node(
2112
1.06k
              snapshot_metadata_tree,
2113
1.06k
              file_io_handle,
2114
1.06k
              root_node,
2115
1.06k
              transaction_identifier,
2116
1.06k
              snapshots,
2117
1.06k
              0,
2118
1.06k
              error );
2119
1.06k
  }
2120
3.38k
  if( result == -1 )
2121
925
  {
2122
925
    libcerror_error_set(
2123
925
     error,
2124
925
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2125
925
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2126
925
     "%s: unable to retrieve snapshots from snapshot metadata tree root node.",
2127
925
     function );
2128
2129
925
    goto on_error;
2130
925
  }
2131
#if defined( HAVE_PROFILER )
2132
  if( snapshot_metadata_tree->io_handle->profiler != NULL )
2133
  {
2134
    if( libfsapfs_profiler_stop_timing(
2135
         snapshot_metadata_tree->io_handle->profiler,
2136
         profiler_start_timestamp,
2137
         function,
2138
         0,
2139
         0,
2140
         error ) != 1 )
2141
    {
2142
      libcerror_error_set(
2143
       error,
2144
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2145
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2146
       "%s: unable to stop timing.",
2147
       function );
2148
2149
      goto on_error;
2150
    }
2151
  }
2152
#endif /* defined( HAVE_PROFILER ) */
2153
2154
2.46k
  return( result );
2155
2156
1.61k
on_error:
2157
1.61k
  libcdata_array_empty(
2158
1.61k
   snapshots,
2159
1.61k
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
2160
1.61k
   NULL );
2161
2162
1.61k
  return( -1 );
2163
3.38k
}
2164