Coverage Report

Created: 2024-02-25 07:20

/src/libfsapfs/libfsapfs/libfsapfs_file_system_btree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The file system 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_attribute_values.h"
28
#include "libfsapfs_btree_entry.h"
29
#include "libfsapfs_btree_node.h"
30
#include "libfsapfs_data_block.h"
31
#include "libfsapfs_debug.h"
32
#include "libfsapfs_definitions.h"
33
#include "libfsapfs_directory_record.h"
34
#include "libfsapfs_encryption_context.h"
35
#include "libfsapfs_file_extent.h"
36
#include "libfsapfs_file_system_btree.h"
37
#include "libfsapfs_inode.h"
38
#include "libfsapfs_io_handle.h"
39
#include "libfsapfs_libbfio.h"
40
#include "libfsapfs_libcdata.h"
41
#include "libfsapfs_libcerror.h"
42
#include "libfsapfs_libcnotify.h"
43
#include "libfsapfs_libfcache.h"
44
#include "libfsapfs_libfdata.h"
45
#include "libfsapfs_libuna.h"
46
#include "libfsapfs_name_hash.h"
47
#include "libfsapfs_object_map_btree.h"
48
#include "libfsapfs_object_map_descriptor.h"
49
50
#include "fsapfs_file_system.h"
51
#include "fsapfs_object.h"
52
53
/* Creates a file system B-tree
54
 * Make sure the value file_system_btree is referencing, is set to NULL
55
 * Returns 1 if successful or -1 on error
56
 */
57
int libfsapfs_file_system_btree_initialize(
58
     libfsapfs_file_system_btree_t **file_system_btree,
59
     libfsapfs_io_handle_t *io_handle,
60
     libfsapfs_encryption_context_t *encryption_context,
61
     libfdata_vector_t *data_block_vector,
62
     libfsapfs_object_map_btree_t *object_map_btree,
63
     uint64_t root_node_block_number,
64
     uint8_t use_case_folding,
65
     libcerror_error_t **error )
66
2.33k
{
67
2.33k
  static char *function = "libfsapfs_file_system_btree_initialize";
68
69
2.33k
  if( file_system_btree == NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
74
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
75
0
     "%s: invalid file system B-tree.",
76
0
     function );
77
78
0
    return( -1 );
79
0
  }
80
2.33k
  if( *file_system_btree != NULL )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
85
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
86
0
     "%s: invalid file system B-tree value already set.",
87
0
     function );
88
89
0
    return( -1 );
90
0
  }
91
2.33k
  *file_system_btree = memory_allocate_structure(
92
2.33k
                        libfsapfs_file_system_btree_t );
93
94
2.33k
  if( *file_system_btree == NULL )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
99
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
100
0
     "%s: unable to create file system B-tree.",
101
0
     function );
102
103
0
    goto on_error;
104
0
  }
105
2.33k
  if( memory_set(
106
2.33k
       *file_system_btree,
107
2.33k
       0,
108
2.33k
       sizeof( libfsapfs_file_system_btree_t ) ) == NULL )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
113
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
114
0
     "%s: unable to clear file system B-tree.",
115
0
     function );
116
117
0
    memory_free(
118
0
     *file_system_btree );
119
120
0
    *file_system_btree = NULL;
121
122
0
    return( -1 );
123
0
  }
124
2.33k
  if( libfcache_cache_initialize(
125
2.33k
       &( ( *file_system_btree )->data_block_cache ),
126
2.33k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
127
2.33k
       error ) != 1 )
128
0
  {
129
0
    libcerror_error_set(
130
0
     error,
131
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
132
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
133
0
     "%s: unable to create data block cache.",
134
0
     function );
135
136
0
    goto on_error;
137
0
  }
138
2.33k
  if( libfcache_cache_initialize(
139
2.33k
       &( ( *file_system_btree )->node_cache ),
140
2.33k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_BTREE_NODES,
141
2.33k
       error ) != 1 )
142
0
  {
143
0
    libcerror_error_set(
144
0
     error,
145
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
146
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
147
0
     "%s: unable to create node cache.",
148
0
     function );
149
150
0
    goto on_error;
151
0
  }
152
2.33k
  ( *file_system_btree )->io_handle              = io_handle;
153
2.33k
  ( *file_system_btree )->encryption_context     = encryption_context;
154
2.33k
  ( *file_system_btree )->data_block_vector      = data_block_vector;
155
2.33k
  ( *file_system_btree )->object_map_btree       = object_map_btree;
156
2.33k
  ( *file_system_btree )->root_node_block_number = root_node_block_number;
157
2.33k
  ( *file_system_btree )->use_case_folding       = use_case_folding;
158
159
2.33k
  return( 1 );
160
161
0
on_error:
162
0
  if( *file_system_btree != NULL )
163
0
  {
164
0
    memory_free(
165
0
     *file_system_btree );
166
167
0
    *file_system_btree = NULL;
168
0
  }
169
0
  return( -1 );
170
2.33k
}
171
172
/* Frees a file system B-tree
173
 * Returns 1 if successful or -1 on error
174
 */
175
int libfsapfs_file_system_btree_free(
176
     libfsapfs_file_system_btree_t **file_system_btree,
177
     libcerror_error_t **error )
178
2.33k
{
179
2.33k
  static char *function = "libfsapfs_file_system_btree_free";
180
2.33k
  int result            = 1;
181
182
2.33k
  if( file_system_btree == NULL )
183
0
  {
184
0
    libcerror_error_set(
185
0
     error,
186
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
187
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
188
0
     "%s: invalid file system B-tree.",
189
0
     function );
190
191
0
    return( -1 );
192
0
  }
193
2.33k
  if( *file_system_btree != NULL )
194
2.33k
  {
195
    /* The io_handle, data_block_vector and object_map_btree are referenced and freed elsewhere
196
     */
197
2.33k
    if( libfcache_cache_free(
198
2.33k
         &( ( *file_system_btree )->node_cache ),
199
2.33k
         error ) != 1 )
200
0
    {
201
0
      libcerror_error_set(
202
0
       error,
203
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
204
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
205
0
       "%s: unable to free node cache.",
206
0
       function );
207
208
0
      result = -1;
209
0
    }
210
2.33k
    if( libfcache_cache_free(
211
2.33k
         &( ( *file_system_btree )->data_block_cache ),
212
2.33k
         error ) != 1 )
213
0
    {
214
0
      libcerror_error_set(
215
0
       error,
216
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
217
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
218
0
       "%s: unable to free data block cache.",
219
0
       function );
220
221
0
      result = -1;
222
0
    }
223
2.33k
    memory_free(
224
2.33k
     *file_system_btree );
225
226
2.33k
    *file_system_btree = NULL;
227
2.33k
  }
228
2.33k
  return( result );
229
2.33k
}
230
231
/* Retrieves the sub node block number from a B-tree entry
232
 * Returns 1 if successful, 0 if not found or -1 on error
233
 */
234
int libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
235
     libfsapfs_file_system_btree_t *file_system_btree,
236
     libbfio_handle_t *file_io_handle,
237
     libfsapfs_btree_entry_t *entry,
238
     uint64_t transaction_identifier,
239
     uint64_t *sub_node_block_number,
240
     libcerror_error_t **error )
241
1.10k
{
242
1.10k
  libfsapfs_object_map_descriptor_t *object_map_descriptor = NULL;
243
1.10k
  static char *function                                    = "libfsapfs_file_system_btree_get_sub_node_block_number_from_entry";
244
1.10k
  uint64_t sub_node_object_identifier                      = 0;
245
1.10k
  int result                                               = 0;
246
247
1.10k
  if( file_system_btree == 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 file system B-tree.",
254
0
     function );
255
256
0
    return( -1 );
257
0
  }
258
1.10k
  if( entry == NULL )
259
15
  {
260
15
    libcerror_error_set(
261
15
     error,
262
15
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
263
15
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
264
15
     "%s: invalid B-tree entry.",
265
15
     function );
266
267
15
    return( -1 );
268
15
  }
269
1.09k
  if( entry->value_data == NULL )
270
91
  {
271
91
    libcerror_error_set(
272
91
     error,
273
91
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
274
91
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
275
91
     "%s: invalid B-tree entry - missing value data.",
276
91
     function );
277
278
91
    return( -1 );
279
91
  }
280
1.00k
  if( entry->value_data_size != 8 )
281
132
  {
282
132
    libcerror_error_set(
283
132
     error,
284
132
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
285
132
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
286
132
     "%s: invalid B-tree entry - unsupported value data size.",
287
132
     function );
288
289
132
    return( -1 );
290
132
  }
291
870
  if( sub_node_block_number == NULL )
292
0
  {
293
0
    libcerror_error_set(
294
0
     error,
295
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
296
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
297
0
     "%s: invalid sub node block number.",
298
0
     function );
299
300
0
    return( -1 );
301
0
  }
302
870
  byte_stream_copy_to_uint64_little_endian(
303
870
   entry->value_data,
304
870
   sub_node_object_identifier );
305
306
#if defined( HAVE_DEBUG_OUTPUT )
307
  if( libcnotify_verbose != 0 )
308
  {
309
    libcnotify_printf(
310
     "%s: sub node object identifier: %" PRIu64 " (transaction: %" PRIu64 ")\n",
311
     function,
312
     sub_node_object_identifier,
313
     transaction_identifier );
314
  }
315
#endif
316
870
  result = libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
317
870
            file_system_btree->object_map_btree,
318
870
            file_io_handle,
319
870
            sub_node_object_identifier,
320
870
            transaction_identifier,
321
870
            &object_map_descriptor,
322
870
            error );
323
324
870
  if( result == -1 )
325
14
  {
326
14
    libcerror_error_set(
327
14
     error,
328
14
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
14
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
330
14
     "%s: unable to retrieve object map descriptor for sub node object identifier: %" PRIu64 " (transaction: %" PRIu64 ").",
331
14
     function,
332
14
     sub_node_object_identifier,
333
14
     transaction_identifier );
334
335
14
    goto on_error;
336
14
  }
337
856
  else if( result != 0 )
338
848
  {
339
848
    if( object_map_descriptor == NULL )
340
0
    {
341
0
      libcerror_error_set(
342
0
       error,
343
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
344
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
345
0
       "%s: invalid object map descriptor.",
346
0
       function );
347
348
0
      goto on_error;
349
0
    }
350
#if defined( HAVE_DEBUG_OUTPUT )
351
    if( libcnotify_verbose != 0 )
352
    {
353
      libcnotify_printf(
354
       "%s: sub node block number: %" PRIu64 "\n",
355
       function,
356
       object_map_descriptor->physical_address );
357
    }
358
#endif
359
848
    *sub_node_block_number = object_map_descriptor->physical_address;
360
361
848
    if( libfsapfs_object_map_descriptor_free(
362
848
         &object_map_descriptor,
363
848
         error ) != 1 )
364
0
    {
365
0
      libcerror_error_set(
366
0
       error,
367
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
368
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
369
0
       "%s: unable to free object map descriptor.",
370
0
       function );
371
372
0
      goto on_error;
373
0
    }
374
848
  }
375
856
  return( result );
376
377
14
on_error:
378
14
  if( object_map_descriptor != NULL )
379
0
  {
380
0
    libfsapfs_object_map_descriptor_free(
381
0
     &object_map_descriptor,
382
0
     NULL );
383
0
  }
384
14
  return( -1 );
385
870
}
386
387
/* Retrieves the file system B-tree root node
388
 * Returns 1 if successful, 0 if not available or -1 on error
389
 */
390
int libfsapfs_file_system_btree_get_root_node(
391
     libfsapfs_file_system_btree_t *file_system_btree,
392
     libbfio_handle_t *file_io_handle,
393
     uint64_t root_node_block_number,
394
     libfsapfs_btree_node_t **root_node,
395
     libcerror_error_t **error )
396
5.67k
{
397
5.67k
  libfcache_cache_value_t *cache_value = NULL;
398
5.67k
  libfsapfs_btree_node_t *node         = NULL;
399
5.67k
  libfsapfs_data_block_t *data_block   = NULL;
400
5.67k
  static char *function                = "libfsapfs_file_system_btree_get_root_node";
401
5.67k
  int result                           = 0;
402
403
#if defined( HAVE_PROFILER )
404
  int64_t profiler_start_timestamp     = 0;
405
#endif
406
407
5.67k
  if( file_system_btree == NULL )
408
0
  {
409
0
    libcerror_error_set(
410
0
     error,
411
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
412
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
413
0
     "%s: invalid file system B-tree.",
414
0
     function );
415
416
0
    return( -1 );
417
0
  }
418
5.67k
  if( file_system_btree->io_handle == NULL )
419
0
  {
420
0
    libcerror_error_set(
421
0
     error,
422
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
423
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
424
0
     "%s: invalid file system B-tree entry - missing IO handle.",
425
0
     function );
426
427
0
    return( -1 );
428
0
  }
429
5.67k
  if( root_node_block_number > (uint64_t) INT_MAX )
430
117
  {
431
117
    libcerror_error_set(
432
117
     error,
433
117
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
434
117
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
435
117
     "%s: invalid root node block number value out of bounds.",
436
117
     function );
437
438
117
    return( -1 );
439
117
  }
440
5.55k
  if( root_node == NULL )
441
0
  {
442
0
    libcerror_error_set(
443
0
     error,
444
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
445
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
446
0
     "%s: invalid root node.",
447
0
     function );
448
449
0
    return( -1 );
450
0
  }
451
#if defined( HAVE_PROFILER )
452
  if( file_system_btree->io_handle->profiler != NULL )
453
  {
454
    if( libfsapfs_profiler_start_timing(
455
         file_system_btree->io_handle->profiler,
456
         &profiler_start_timestamp,
457
         error ) != 1 )
458
    {
459
      libcerror_error_set(
460
       error,
461
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
462
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
463
       "%s: unable to start timing.",
464
       function );
465
466
      goto on_error;
467
    }
468
  }
469
#endif /* defined( HAVE_PROFILER ) */
470
471
5.55k
  result = libfcache_cache_get_value_by_identifier(
472
5.55k
            file_system_btree->node_cache,
473
5.55k
            0,
474
5.55k
            (off64_t) root_node_block_number,
475
5.55k
            0,
476
5.55k
            &cache_value,
477
5.55k
            error );
478
479
5.55k
  if( result == -1 )
480
0
  {
481
0
    libcerror_error_set(
482
0
     error,
483
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
484
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
485
0
     "%s: unable to retrieve value from cache.",
486
0
     function );
487
488
0
    goto on_error;
489
0
  }
490
5.55k
  else if( result == 0 )
491
2.22k
  {
492
2.22k
    if( libfdata_vector_get_element_value_by_index(
493
2.22k
         file_system_btree->data_block_vector,
494
2.22k
         (intptr_t *) file_io_handle,
495
2.22k
         (libfdata_cache_t *) file_system_btree->data_block_cache,
496
2.22k
         (int) root_node_block_number,
497
2.22k
         (intptr_t **) &data_block,
498
2.22k
         0,
499
2.22k
         error ) != 1 )
500
42
    {
501
42
      libcerror_error_set(
502
42
       error,
503
42
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
504
42
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
505
42
       "%s: unable to retrieve data block: %" PRIu64 ".",
506
42
       function,
507
42
       root_node_block_number );
508
509
42
      goto on_error;
510
42
    }
511
2.17k
    if( data_block == NULL )
512
0
    {
513
0
      libcerror_error_set(
514
0
       error,
515
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
516
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
517
0
       "%s: invalid data block: %" PRIu64 ".",
518
0
       function,
519
0
       root_node_block_number );
520
521
0
      goto on_error;
522
0
    }
523
2.17k
    if( libfsapfs_btree_node_initialize(
524
2.17k
         &node,
525
2.17k
         error ) != 1 )
526
0
    {
527
0
      libcerror_error_set(
528
0
       error,
529
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
530
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
531
0
       "%s: unable to create B-tree node.",
532
0
       function );
533
534
0
      goto on_error;
535
0
    }
536
2.17k
    if( libfsapfs_btree_node_read_data(
537
2.17k
         node,
538
2.17k
         data_block->data,
539
2.17k
         data_block->data_size,
540
2.17k
         error ) != 1 )
541
7
    {
542
7
      libcerror_error_set(
543
7
       error,
544
7
       LIBCERROR_ERROR_DOMAIN_IO,
545
7
       LIBCERROR_IO_ERROR_READ_FAILED,
546
7
       "%s: unable to read B-tree node.",
547
7
       function );
548
549
7
      goto on_error;
550
7
    }
551
2.17k
    if( node->object_type == 0x00000000UL )
552
2
    {
553
2
      if( libfsapfs_btree_node_free(
554
2
           &node,
555
2
           error ) != 1 )
556
0
      {
557
0
        libcerror_error_set(
558
0
         error,
559
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
560
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
561
0
         "%s: unable to free node.",
562
0
         function );
563
564
0
        goto on_error;
565
0
      }
566
2
      return( 0 );
567
2
    }
568
2.16k
    if( ( node->object_type != 0x00000002UL )
569
2.16k
     && ( node->object_type != 0x10000002UL ) )
570
36
    {
571
36
      libcerror_error_set(
572
36
       error,
573
36
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
574
36
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
575
36
       "%s: invalid object type: 0x%08" PRIx32 ".",
576
36
       function,
577
36
       node->object_type );
578
579
36
      goto on_error;
580
36
    }
581
2.13k
    if( node->object_subtype != 0x0000000eUL )
582
89
    {
583
89
      libcerror_error_set(
584
89
       error,
585
89
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
586
89
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
587
89
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
588
89
       function,
589
89
       node->object_subtype );
590
591
89
      goto on_error;
592
89
    }
593
2.04k
    if( ( ( node->node_header->flags & 0x0001 ) == 0 )
594
2.04k
     || ( ( node->node_header->flags & 0x0004 ) != 0 ) )
595
5
    {
596
5
      libcerror_error_set(
597
5
       error,
598
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
599
5
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
600
5
       "%s: unsupported flags: 0x%04" PRIx16 ".",
601
5
       function,
602
5
       node->node_header->flags );
603
604
5
      goto on_error;
605
5
    }
606
2.03k
    if( node->footer->node_size != 4096 )
607
90
    {
608
90
      libcerror_error_set(
609
90
       error,
610
90
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
611
90
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
612
90
       "%s: invalid node size value out of bounds.",
613
90
       function );
614
615
90
      goto on_error;
616
90
    }
617
1.94k
    if( node->footer->key_size != 0 )
618
82
    {
619
82
      libcerror_error_set(
620
82
       error,
621
82
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
622
82
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
623
82
       "%s: invalid key size value out of bounds.",
624
82
       function );
625
626
82
      goto on_error;
627
82
    }
628
1.86k
    if( node->footer->value_size != 0 )
629
58
    {
630
58
      libcerror_error_set(
631
58
       error,
632
58
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
633
58
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
634
58
       "%s: invalid value size value out of bounds.",
635
58
       function );
636
637
58
      goto on_error;
638
58
    }
639
1.80k
    if( libfcache_cache_set_value_by_identifier(
640
1.80k
         file_system_btree->node_cache,
641
1.80k
         0,
642
1.80k
         (off64_t) root_node_block_number,
643
1.80k
         0,
644
1.80k
         (intptr_t *) node,
645
1.80k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
646
1.80k
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
647
1.80k
         error ) != 1 )
648
0
    {
649
0
      libcerror_error_set(
650
0
       error,
651
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
652
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
653
0
       "%s: unable to set value in cache.",
654
0
       function );
655
656
0
      goto on_error;
657
0
    }
658
1.80k
    node = NULL;
659
660
1.80k
    if( libfcache_cache_get_value_by_identifier(
661
1.80k
         file_system_btree->node_cache,
662
1.80k
         0,
663
1.80k
         (off64_t) root_node_block_number,
664
1.80k
         0,
665
1.80k
         &cache_value,
666
1.80k
         error ) != 1 )
667
0
    {
668
0
      libcerror_error_set(
669
0
       error,
670
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
671
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
672
0
       "%s: unable to retrieve value from cache.",
673
0
       function );
674
675
0
      goto on_error;
676
0
    }
677
1.80k
  }
678
#if defined( HAVE_PROFILER )
679
  if( file_system_btree->io_handle->profiler != NULL )
680
  {
681
    if( libfsapfs_profiler_stop_timing(
682
         file_system_btree->io_handle->profiler,
683
         profiler_start_timestamp,
684
         function,
685
         root_node_block_number * file_system_btree->io_handle->block_size,
686
         file_system_btree->io_handle->block_size,
687
         error ) != 1 )
688
    {
689
      libcerror_error_set(
690
       error,
691
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
692
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
693
       "%s: unable to stop timing.",
694
       function );
695
696
      goto on_error;
697
    }
698
  }
699
#endif /* defined( HAVE_PROFILER ) */
700
701
5.14k
  if( libfcache_cache_value_get_value(
702
5.14k
       cache_value,
703
5.14k
       (intptr_t **) root_node,
704
5.14k
       error ) != 1 )
705
0
  {
706
0
    libcerror_error_set(
707
0
     error,
708
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
709
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
710
0
     "%s: unable to retrieve root node.",
711
0
     function );
712
713
0
    goto on_error;
714
0
  }
715
5.14k
  return( 1 );
716
717
409
on_error:
718
409
  if( node != NULL )
719
367
  {
720
367
    libfsapfs_btree_node_free(
721
367
     &node,
722
367
     NULL );
723
367
  }
724
409
  return( -1 );
725
5.14k
}
726
727
/* Retrieves a file system B-tree sub node
728
 * Returns 1 if successful or -1 on error
729
 */
730
int libfsapfs_file_system_btree_get_sub_node(
731
     libfsapfs_file_system_btree_t *file_system_btree,
732
     libbfio_handle_t *file_io_handle,
733
     uint64_t sub_node_block_number,
734
     libfsapfs_btree_node_t **sub_node,
735
     libcerror_error_t **error )
736
848
{
737
848
  libfcache_cache_value_t *cache_value = NULL;
738
848
  libfsapfs_btree_node_t *node         = NULL;
739
848
  libfsapfs_data_block_t *data_block   = NULL;
740
848
  static char *function                = "libfsapfs_file_system_btree_get_sub_node";
741
848
  int result                           = 0;
742
743
#if defined( HAVE_PROFILER )
744
  int64_t profiler_start_timestamp     = 0;
745
#endif
746
747
848
  if( file_system_btree == NULL )
748
0
  {
749
0
    libcerror_error_set(
750
0
     error,
751
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
752
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
753
0
     "%s: invalid file system B-tree.",
754
0
     function );
755
756
0
    return( -1 );
757
0
  }
758
848
  if( file_system_btree->io_handle == NULL )
759
0
  {
760
0
    libcerror_error_set(
761
0
     error,
762
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
763
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
764
0
     "%s: invalid file system B-tree entry - missing IO handle.",
765
0
     function );
766
767
0
    return( -1 );
768
0
  }
769
848
  if( sub_node_block_number > (uint64_t) INT_MAX )
770
49
  {
771
49
    libcerror_error_set(
772
49
     error,
773
49
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
774
49
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
775
49
     "%s: invalid sub node block number value out of bounds.",
776
49
     function );
777
778
49
    return( -1 );
779
49
  }
780
799
  if( sub_node == NULL )
781
0
  {
782
0
    libcerror_error_set(
783
0
     error,
784
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
785
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
786
0
     "%s: invalid sub node.",
787
0
     function );
788
789
0
    return( -1 );
790
0
  }
791
#if defined( HAVE_PROFILER )
792
  if( file_system_btree->io_handle->profiler != NULL )
793
  {
794
    if( libfsapfs_profiler_start_timing(
795
         file_system_btree->io_handle->profiler,
796
         &profiler_start_timestamp,
797
         error ) != 1 )
798
    {
799
      libcerror_error_set(
800
       error,
801
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
802
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
803
       "%s: unable to start timing.",
804
       function );
805
806
      goto on_error;
807
    }
808
  }
809
#endif /* defined( HAVE_PROFILER ) */
810
811
799
  result = libfcache_cache_get_value_by_identifier(
812
799
            file_system_btree->node_cache,
813
799
            0,
814
799
            (off64_t) sub_node_block_number,
815
799
            0,
816
799
            &cache_value,
817
799
            error );
818
819
799
  if( result == -1 )
820
0
  {
821
0
    libcerror_error_set(
822
0
     error,
823
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
824
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
825
0
     "%s: unable to retrieve value from cache.",
826
0
     function );
827
828
0
    goto on_error;
829
0
  }
830
799
  else if( result == 0 )
831
28
  {
832
28
    if( libfdata_vector_get_element_value_by_index(
833
28
         file_system_btree->data_block_vector,
834
28
         (intptr_t *) file_io_handle,
835
28
         (libfdata_cache_t *) file_system_btree->data_block_cache,
836
28
         (int) sub_node_block_number,
837
28
         (intptr_t **) &data_block,
838
28
         0,
839
28
         error ) != 1 )
840
7
    {
841
7
      libcerror_error_set(
842
7
       error,
843
7
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
844
7
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
845
7
       "%s: unable to retrieve data block: %" PRIu64 ".",
846
7
       function,
847
7
       sub_node_block_number );
848
849
7
      goto on_error;
850
7
    }
851
21
    if( data_block == NULL )
852
0
    {
853
0
      libcerror_error_set(
854
0
       error,
855
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
856
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
857
0
       "%s: invalid data block: %" PRIu64 ".",
858
0
       function,
859
0
       sub_node_block_number );
860
861
0
      goto on_error;
862
0
    }
863
21
    if( libfsapfs_btree_node_initialize(
864
21
         &node,
865
21
         error ) != 1 )
866
0
    {
867
0
      libcerror_error_set(
868
0
       error,
869
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
870
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
871
0
       "%s: unable to create B-tree node.",
872
0
       function );
873
874
0
      goto on_error;
875
0
    }
876
21
    if( libfsapfs_btree_node_read_data(
877
21
         node,
878
21
         data_block->data,
879
21
         data_block->data_size,
880
21
         error ) != 1 )
881
1
    {
882
1
      libcerror_error_set(
883
1
       error,
884
1
       LIBCERROR_ERROR_DOMAIN_IO,
885
1
       LIBCERROR_IO_ERROR_READ_FAILED,
886
1
       "%s: unable to read B-tree node.",
887
1
       function );
888
889
1
      goto on_error;
890
1
    }
891
20
    if( ( node->object_type != 0x00000003UL )
892
20
     && ( node->object_type != 0x10000003UL ) )
893
10
    {
894
10
      libcerror_error_set(
895
10
       error,
896
10
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
897
10
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
898
10
       "%s: invalid object type: 0x%08" PRIx32 ".",
899
10
       function,
900
10
       node->object_type );
901
902
10
      goto on_error;
903
10
    }
904
10
    if( node->object_subtype != 0x0000000eUL )
905
6
    {
906
6
      libcerror_error_set(
907
6
       error,
908
6
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
909
6
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
910
6
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
911
6
       function,
912
6
       node->object_subtype );
913
914
6
      goto on_error;
915
6
    }
916
4
    if( ( ( node->node_header->flags & 0x0001 ) != 0 )
917
4
     || ( ( node->node_header->flags & 0x0004 ) != 0 ) )
918
2
    {
919
2
      libcerror_error_set(
920
2
       error,
921
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
922
2
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
923
2
       "%s: unsupported flags: 0x%04" PRIx16 ".",
924
2
       function,
925
2
       node->node_header->flags );
926
927
2
      goto on_error;
928
2
    }
929
2
    if( libfcache_cache_set_value_by_identifier(
930
2
         file_system_btree->node_cache,
931
2
         0,
932
2
         (off64_t) sub_node_block_number,
933
2
         0,
934
2
         (intptr_t *) node,
935
2
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
936
2
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
937
2
         error ) != 1 )
938
0
    {
939
0
      libcerror_error_set(
940
0
       error,
941
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
942
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
943
0
       "%s: unable to set value in cache.",
944
0
       function );
945
946
0
      goto on_error;
947
0
    }
948
2
    node = NULL;
949
950
2
    if( libfcache_cache_get_value_by_identifier(
951
2
         file_system_btree->node_cache,
952
2
         0,
953
2
         (off64_t) sub_node_block_number,
954
2
         0,
955
2
         &cache_value,
956
2
         error ) != 1 )
957
0
    {
958
0
      libcerror_error_set(
959
0
       error,
960
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
961
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
962
0
       "%s: unable to retrieve value from cache.",
963
0
       function );
964
965
0
      goto on_error;
966
0
    }
967
2
  }
968
#if defined( HAVE_PROFILER )
969
  if( file_system_btree->io_handle->profiler != NULL )
970
  {
971
    if( libfsapfs_profiler_stop_timing(
972
         file_system_btree->io_handle->profiler,
973
         profiler_start_timestamp,
974
         function,
975
         sub_node_block_number * file_system_btree->io_handle->block_size,
976
         file_system_btree->io_handle->block_size,
977
         error ) != 1 )
978
    {
979
      libcerror_error_set(
980
       error,
981
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
982
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
983
       "%s: unable to stop timing.",
984
       function );
985
986
      goto on_error;
987
    }
988
  }
989
#endif /* defined( HAVE_PROFILER ) */
990
991
773
  if( libfcache_cache_value_get_value(
992
773
       cache_value,
993
773
       (intptr_t **) sub_node,
994
773
       error ) != 1 )
995
0
  {
996
0
    libcerror_error_set(
997
0
     error,
998
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
999
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1000
0
     "%s: unable to retrieve sub node.",
1001
0
     function );
1002
1003
0
    goto on_error;
1004
0
  }
1005
773
  return( 1 );
1006
1007
26
on_error:
1008
26
  if( node != NULL )
1009
19
  {
1010
19
    libfsapfs_btree_node_free(
1011
19
     &node,
1012
19
     NULL );
1013
19
  }
1014
26
  return( -1 );
1015
773
}
1016
1017
/* Retrieves an entry for a specific identifier from the file system B-tree node
1018
 * Returns 1 if successful, 0 if not found or -1 on error
1019
 */
1020
int libfsapfs_file_system_btree_get_entry_from_node_by_identifier(
1021
     libfsapfs_file_system_btree_t *file_system_btree,
1022
     libfsapfs_btree_node_t *node,
1023
     uint64_t identifier,
1024
     uint8_t data_type,
1025
     libfsapfs_btree_entry_t **btree_entry,
1026
     libcerror_error_t **error )
1027
2.44k
{
1028
2.44k
  libfsapfs_btree_entry_t *entry          = NULL;
1029
2.44k
  libfsapfs_btree_entry_t *previous_entry = NULL;
1030
2.44k
  static char *function                   = "libfsapfs_file_system_btree_get_entry_from_node_by_identifier";
1031
2.44k
  uint64_t file_system_identifier         = 0;
1032
2.44k
  uint64_t lookup_identifier              = 0;
1033
2.44k
  uint8_t file_system_data_type           = 0;
1034
2.44k
  int btree_entry_index                   = 0;
1035
2.44k
  int is_leaf_node                        = 0;
1036
2.44k
  int number_of_entries                   = 0;
1037
1038
2.44k
  if( file_system_btree == 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 file system B-tree.",
1045
0
     function );
1046
1047
0
    return( -1 );
1048
0
  }
1049
2.44k
  if( node == NULL )
1050
0
  {
1051
0
    libcerror_error_set(
1052
0
     error,
1053
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1054
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1055
0
     "%s: invalid node.",
1056
0
     function );
1057
1058
0
    return( -1 );
1059
0
  }
1060
2.44k
  if( btree_entry == NULL )
1061
0
  {
1062
0
    libcerror_error_set(
1063
0
     error,
1064
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1065
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1066
0
     "%s: invalid B-tree entry.",
1067
0
     function );
1068
1069
0
    return( -1 );
1070
0
  }
1071
#if defined( HAVE_DEBUG_OUTPUT )
1072
  if( libcnotify_verbose != 0 )
1073
  {
1074
    libcnotify_printf(
1075
     "%s: retrieving B-tree entry identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
1076
     function,
1077
     identifier,
1078
     data_type,
1079
     libfsapfs_debug_print_file_system_data_type(
1080
      data_type ) );
1081
  }
1082
#endif
1083
2.44k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1084
2.44k
                  node,
1085
2.44k
                  error );
1086
1087
2.44k
  if( is_leaf_node == -1 )
1088
0
  {
1089
0
    libcerror_error_set(
1090
0
     error,
1091
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1092
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1093
0
     "%s: unable to determine if B-tree node is a leaf node.",
1094
0
     function );
1095
1096
0
    return( -1 );
1097
0
  }
1098
2.44k
  if( libfsapfs_btree_node_get_number_of_entries(
1099
2.44k
       node,
1100
2.44k
       &number_of_entries,
1101
2.44k
       error ) != 1 )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1107
0
     "%s: unable to retrieve number of entries from B-tree node.",
1108
0
     function );
1109
1110
0
    return( -1 );
1111
0
  }
1112
2.44k
  lookup_identifier = ( (uint64_t) data_type << 60 ) | identifier;
1113
1114
2.44k
  for( btree_entry_index = 0;
1115
32.3k
       btree_entry_index < number_of_entries;
1116
29.9k
       btree_entry_index++ )
1117
32.2k
  {
1118
32.2k
    if( libfsapfs_btree_node_get_entry_by_index(
1119
32.2k
         node,
1120
32.2k
         btree_entry_index,
1121
32.2k
         &entry,
1122
32.2k
         error ) != 1 )
1123
0
    {
1124
0
      libcerror_error_set(
1125
0
       error,
1126
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1127
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1128
0
       "%s: unable to retrieve number of entries from B-tree node.",
1129
0
       function );
1130
1131
0
      return( -1 );
1132
0
    }
1133
32.2k
    if( entry == NULL )
1134
0
    {
1135
0
      libcerror_error_set(
1136
0
       error,
1137
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1138
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1139
0
       "%s: invalid B-tree entry: %d.",
1140
0
       function,
1141
0
       btree_entry_index );
1142
1143
0
      return( -1 );
1144
0
    }
1145
32.2k
    if( entry->key_data == NULL )
1146
9
    {
1147
9
      libcerror_error_set(
1148
9
       error,
1149
9
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1150
9
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1151
9
       "%s: invalid B-tree entry: %d - missing key data.",
1152
9
       function,
1153
9
       btree_entry_index );
1154
1155
9
      return( -1 );
1156
9
    }
1157
32.2k
    if( entry->key_data_size < 8 )
1158
9
    {
1159
9
      libcerror_error_set(
1160
9
       error,
1161
9
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1162
9
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1163
9
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1164
9
       function,
1165
9
       btree_entry_index );
1166
1167
9
      return( -1 );
1168
9
    }
1169
32.2k
    byte_stream_copy_to_uint64_little_endian(
1170
32.2k
     entry->key_data,
1171
32.2k
     file_system_identifier );
1172
1173
32.2k
    file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
1174
1175
#if defined( HAVE_DEBUG_OUTPUT )
1176
    if( libcnotify_verbose != 0 )
1177
    {
1178
      libcnotify_printf(
1179
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
1180
       function,
1181
       btree_entry_index,
1182
       file_system_identifier & 0x0fffffffffffffffUL,
1183
       file_system_data_type,
1184
       libfsapfs_debug_print_file_system_data_type(
1185
        file_system_data_type ) );
1186
    }
1187
#endif
1188
32.2k
    if( is_leaf_node != 0 )
1189
30.9k
    {
1190
30.9k
      if( file_system_identifier == lookup_identifier )
1191
1.68k
      {
1192
1.68k
        *btree_entry = entry;
1193
1194
1.68k
        return( 1 );
1195
1.68k
      }
1196
30.9k
    }
1197
1.25k
    else
1198
1.25k
    {
1199
1.25k
      file_system_identifier &= 0x0fffffffffffffffUL;
1200
1201
1.25k
      if( file_system_identifier >= identifier )
1202
648
      {
1203
648
        if( ( previous_entry == NULL )
1204
648
         || ( ( file_system_identifier == identifier )
1205
363
          &&  ( file_system_data_type <= data_type ) ) )
1206
289
        {
1207
289
          previous_entry = entry;
1208
289
        }
1209
648
        *btree_entry = previous_entry;
1210
1211
648
        return( 1 );
1212
648
      }
1213
604
      previous_entry = entry;
1214
604
    }
1215
32.2k
  }
1216
98
  if( is_leaf_node == 0 )
1217
8
  {
1218
8
    *btree_entry = previous_entry;
1219
1220
8
    return( 1 );
1221
8
  }
1222
90
  return( 0 );
1223
98
}
1224
1225
/* Retrieves an entry for a specific identifier from the file system B-tree
1226
 * Returns 1 if successful, 0 if not found or -1 on error
1227
 */
1228
int libfsapfs_file_system_btree_get_entry_by_identifier(
1229
     libfsapfs_file_system_btree_t *file_system_btree,
1230
     libbfio_handle_t *file_io_handle,
1231
     uint64_t identifier,
1232
     uint8_t data_type,
1233
     uint64_t transaction_identifier,
1234
     libfsapfs_btree_node_t **btree_node,
1235
     libfsapfs_btree_entry_t **btree_entry,
1236
     libcerror_error_t **error )
1237
2.21k
{
1238
2.21k
  libfsapfs_btree_entry_t *entry = NULL;
1239
2.21k
  libfsapfs_btree_node_t *node   = NULL;
1240
2.21k
  static char *function          = "libfsapfs_file_system_btree_get_entry_by_identifier";
1241
2.21k
  uint64_t sub_node_block_number = 0;
1242
2.21k
  int is_leaf_node               = 0;
1243
2.21k
  int recursion_depth            = 0;
1244
2.21k
  int result                     = 0;
1245
1246
2.21k
  if( file_system_btree == NULL )
1247
0
  {
1248
0
    libcerror_error_set(
1249
0
     error,
1250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1251
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1252
0
     "%s: invalid file system B-tree.",
1253
0
     function );
1254
1255
0
    return( -1 );
1256
0
  }
1257
2.21k
  if( btree_node == NULL )
1258
0
  {
1259
0
    libcerror_error_set(
1260
0
     error,
1261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1262
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1263
0
     "%s: invalid B-tree node.",
1264
0
     function );
1265
1266
0
    return( -1 );
1267
0
  }
1268
2.21k
  if( btree_entry == NULL )
1269
0
  {
1270
0
    libcerror_error_set(
1271
0
     error,
1272
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1273
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1274
0
     "%s: invalid B-tree entry.",
1275
0
     function );
1276
1277
0
    return( -1 );
1278
0
  }
1279
2.21k
  result = libfsapfs_file_system_btree_get_root_node(
1280
2.21k
            file_system_btree,
1281
2.21k
            file_io_handle,
1282
2.21k
            file_system_btree->root_node_block_number,
1283
2.21k
            &node,
1284
2.21k
            error );
1285
1286
2.21k
  if( result == -1 )
1287
275
  {
1288
275
    libcerror_error_set(
1289
275
     error,
1290
275
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291
275
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1292
275
     "%s: unable to retrieve B-tree root node.",
1293
275
     function );
1294
1295
275
    return( -1 );
1296
275
  }
1297
1.93k
  else if( result == 0 )
1298
1
  {
1299
1
    return( 0 );
1300
1
  }
1301
1.93k
  do
1302
2.44k
  {
1303
2.44k
    if( ( recursion_depth < 0 )
1304
2.44k
     || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1305
2
    {
1306
2
      libcerror_error_set(
1307
2
       error,
1308
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1309
2
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1310
2
       "%s: invalid recursion depth value out of bounds.",
1311
2
       function );
1312
1313
2
      return( -1 );
1314
2
    }
1315
2.44k
    is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1316
2.44k
                    node,
1317
2.44k
                    error );
1318
1319
2.44k
    if( is_leaf_node == -1 )
1320
0
    {
1321
0
      libcerror_error_set(
1322
0
       error,
1323
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1324
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1325
0
       "%s: unable to determine if B-tree node is a leaf node.",
1326
0
       function );
1327
1328
0
      return( -1 );
1329
0
    }
1330
2.44k
    result = libfsapfs_file_system_btree_get_entry_from_node_by_identifier(
1331
2.44k
              file_system_btree,
1332
2.44k
              node,
1333
2.44k
              identifier,
1334
2.44k
              data_type,
1335
2.44k
              &entry,
1336
2.44k
              error );
1337
1338
2.44k
    if( result == -1 )
1339
18
    {
1340
18
      libcerror_error_set(
1341
18
       error,
1342
18
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1343
18
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1344
18
       "%s: unable to retrieve entry from B-tree node.",
1345
18
       function );
1346
1347
18
      return( -1 );
1348
18
    }
1349
2.42k
    else if( result == 0 )
1350
90
    {
1351
90
      break;
1352
90
    }
1353
2.33k
    if( is_leaf_node != 0 )
1354
1.68k
    {
1355
1.68k
      *btree_node  = node;
1356
1.68k
      *btree_entry = entry;
1357
1358
1.68k
      return( 1 );
1359
1.68k
    }
1360
656
    if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
1361
656
         file_system_btree,
1362
656
         file_io_handle,
1363
656
         entry,
1364
656
         transaction_identifier,
1365
656
         &sub_node_block_number,
1366
656
         error ) != 1 )
1367
142
    {
1368
142
      libcerror_error_set(
1369
142
       error,
1370
142
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1371
142
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1372
142
       "%s: unable to determine sub node block number.",
1373
142
       function );
1374
1375
142
      return( -1 );
1376
142
    }
1377
514
    node = NULL;
1378
1379
514
    if( libfsapfs_file_system_btree_get_sub_node(
1380
514
         file_system_btree,
1381
514
         file_io_handle,
1382
514
         sub_node_block_number,
1383
514
         &node,
1384
514
         error ) != 1 )
1385
0
    {
1386
0
      libcerror_error_set(
1387
0
       error,
1388
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1389
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1390
0
       "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1391
0
       function,
1392
0
       sub_node_block_number );
1393
1394
0
      return( -1 );
1395
0
    }
1396
514
    recursion_depth++;
1397
514
  }
1398
1.93k
  while( is_leaf_node == 0 );
1399
1400
90
  return( 0 );
1401
1.93k
}
1402
1403
/* Retrieves a directory record for an UTF-8 encoded name from the file system B-tree leaf node
1404
 * Returns 1 if successful, 0 if not found or -1 on error
1405
 */
1406
int libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf8_name(
1407
     libfsapfs_file_system_btree_t *file_system_btree,
1408
     libfsapfs_btree_node_t *node,
1409
     uint64_t parent_identifier,
1410
     const uint8_t *utf8_string,
1411
     size_t utf8_string_length,
1412
     uint32_t name_hash,
1413
     libfsapfs_directory_record_t **directory_record,
1414
     libcerror_error_t **error )
1415
965
{
1416
965
  libfsapfs_btree_entry_t *entry                      = NULL;
1417
965
  libfsapfs_directory_record_t *safe_directory_record = NULL;
1418
965
  static char *function                               = "libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf8_name";
1419
965
  uint64_t file_system_identifier                     = 0;
1420
965
  uint64_t lookup_identifier                          = 0;
1421
965
  int compare_result                                  = 0;
1422
965
  int entry_index                                     = 0;
1423
965
  int is_leaf_node                                    = 0;
1424
965
  int number_of_entries                               = 0;
1425
1426
#if defined( HAVE_DEBUG_OUTPUT )
1427
  uint8_t file_system_data_type                       = 0;
1428
#endif
1429
1430
965
  if( file_system_btree == NULL )
1431
0
  {
1432
0
    libcerror_error_set(
1433
0
     error,
1434
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1435
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1436
0
     "%s: invalid file system B-tree.",
1437
0
     function );
1438
1439
0
    return( -1 );
1440
0
  }
1441
965
  if( directory_record == NULL )
1442
0
  {
1443
0
    libcerror_error_set(
1444
0
     error,
1445
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1446
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1447
0
     "%s: invalid directory record.",
1448
0
     function );
1449
1450
0
    return( -1 );
1451
0
  }
1452
#if defined( HAVE_DEBUG_OUTPUT )
1453
  if( libcnotify_verbose != 0 )
1454
  {
1455
    libcnotify_printf(
1456
     "%s: retrieving directory record: %" PRIu64 "\n",
1457
     function,
1458
     parent_identifier );
1459
  }
1460
#endif
1461
965
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1462
965
                  node,
1463
965
                  error );
1464
1465
965
  if( is_leaf_node == -1 )
1466
0
  {
1467
0
    libcerror_error_set(
1468
0
     error,
1469
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1470
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1471
0
     "%s: unable to determine if B-tree node is a leaf node.",
1472
0
     function );
1473
1474
0
    goto on_error;
1475
0
  }
1476
965
  else if( is_leaf_node == 0 )
1477
0
  {
1478
0
    libcerror_error_set(
1479
0
     error,
1480
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1481
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1482
0
     "%s: invalid node - not a leaf node.",
1483
0
     function );
1484
1485
0
    goto on_error;
1486
0
  }
1487
965
  if( libfsapfs_btree_node_get_number_of_entries(
1488
965
       node,
1489
965
       &number_of_entries,
1490
965
       error ) != 1 )
1491
0
  {
1492
0
    libcerror_error_set(
1493
0
     error,
1494
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1495
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1496
0
     "%s: unable to retrieve number of entries from B-tree node.",
1497
0
     function );
1498
1499
0
    goto on_error;
1500
0
  }
1501
965
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD << 60 ) | parent_identifier;
1502
1503
965
  for( entry_index = 0;
1504
11.7k
       entry_index < number_of_entries;
1505
10.7k
       entry_index++ )
1506
11.5k
  {
1507
11.5k
    if( libfsapfs_btree_node_get_entry_by_index(
1508
11.5k
         node,
1509
11.5k
         entry_index,
1510
11.5k
         &entry,
1511
11.5k
         error ) != 1 )
1512
0
    {
1513
0
      libcerror_error_set(
1514
0
       error,
1515
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1516
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1517
0
       "%s: unable to retrieve number of entries from B-tree node.",
1518
0
       function );
1519
1520
0
      goto on_error;
1521
0
    }
1522
11.5k
    if( entry == NULL )
1523
0
    {
1524
0
      libcerror_error_set(
1525
0
       error,
1526
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1527
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1528
0
       "%s: invalid B-tree entry: %d.",
1529
0
       function,
1530
0
       entry_index );
1531
1532
0
      goto on_error;
1533
0
    }
1534
11.5k
    if( entry->key_data == NULL )
1535
14
    {
1536
14
      libcerror_error_set(
1537
14
       error,
1538
14
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1539
14
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1540
14
       "%s: invalid B-tree entry: %d - missing key data.",
1541
14
       function,
1542
14
       entry_index );
1543
1544
14
      goto on_error;
1545
14
    }
1546
11.5k
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
1547
22
    {
1548
22
      libcerror_error_set(
1549
22
       error,
1550
22
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1551
22
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1552
22
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1553
22
       function,
1554
22
       entry_index );
1555
1556
22
      goto on_error;
1557
22
    }
1558
11.5k
    byte_stream_copy_to_uint64_little_endian(
1559
11.5k
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
1560
11.5k
     file_system_identifier );
1561
1562
#if defined( HAVE_DEBUG_OUTPUT )
1563
    if( libcnotify_verbose != 0 )
1564
    {
1565
      file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
1566
1567
      libcnotify_printf(
1568
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
1569
       function,
1570
       entry_index,
1571
       file_system_identifier & 0x0fffffffffffffffUL,
1572
       file_system_data_type,
1573
       libfsapfs_debug_print_file_system_data_type(
1574
        file_system_data_type ) );
1575
    }
1576
#endif
1577
11.5k
    if( file_system_identifier == lookup_identifier )
1578
1.64k
    {
1579
1.64k
      if( libfsapfs_directory_record_initialize(
1580
1.64k
           &safe_directory_record,
1581
1.64k
           error ) != 1 )
1582
0
      {
1583
0
        libcerror_error_set(
1584
0
         error,
1585
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1586
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1587
0
         "%s: unable to create directory record.",
1588
0
         function );
1589
1590
0
        goto on_error;
1591
0
      }
1592
1.64k
      if( libfsapfs_directory_record_read_key_data(
1593
1.64k
           safe_directory_record,
1594
1.64k
           entry->key_data,
1595
1.64k
           (size_t) entry->key_data_size,
1596
1.64k
           error ) != 1 )
1597
30
      {
1598
30
        libcerror_error_set(
1599
30
         error,
1600
30
         LIBCERROR_ERROR_DOMAIN_IO,
1601
30
         LIBCERROR_IO_ERROR_READ_FAILED,
1602
30
         "%s: unable to read directory record key data.",
1603
30
         function );
1604
1605
30
        goto on_error;
1606
30
      }
1607
1.61k
      compare_result = libfsapfs_directory_record_compare_name_with_utf8_string(
1608
1.61k
                        safe_directory_record,
1609
1.61k
                        utf8_string,
1610
1.61k
                        utf8_string_length,
1611
1.61k
                        name_hash,
1612
1.61k
                        file_system_btree->use_case_folding,
1613
1.61k
                        error );
1614
1615
1.61k
      if( compare_result == -1 )
1616
41
      {
1617
41
        libcerror_error_set(
1618
41
         error,
1619
41
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1620
41
         LIBCERROR_RUNTIME_ERROR_GENERIC,
1621
41
         "%s: unable to compare UTF-8 string with name of directory record.",
1622
41
         function );
1623
1624
41
        goto on_error;
1625
41
      }
1626
1.57k
      else if( compare_result == LIBUNA_COMPARE_EQUAL )
1627
731
      {
1628
731
        if( libfsapfs_directory_record_read_value_data(
1629
731
             safe_directory_record,
1630
731
             entry->value_data,
1631
731
             (size_t) entry->value_data_size,
1632
731
             error ) != 1 )
1633
46
        {
1634
46
          libcerror_error_set(
1635
46
           error,
1636
46
           LIBCERROR_ERROR_DOMAIN_IO,
1637
46
           LIBCERROR_IO_ERROR_READ_FAILED,
1638
46
           "%s: unable to read directory record value data.",
1639
46
           function );
1640
1641
46
          goto on_error;
1642
46
        }
1643
685
        *directory_record = safe_directory_record;
1644
1645
685
        return( 1 );
1646
731
      }
1647
847
      if( libfsapfs_directory_record_free(
1648
847
           &safe_directory_record,
1649
847
           error ) != 1 )
1650
0
      {
1651
0
        libcerror_error_set(
1652
0
         error,
1653
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1654
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1655
0
         "%s: unable to free directory record.",
1656
0
         function );
1657
1658
0
        goto on_error;
1659
0
      }
1660
847
    }
1661
11.5k
  }
1662
127
  return( 0 );
1663
1664
153
on_error:
1665
153
  if( safe_directory_record != NULL )
1666
117
  {
1667
117
    libfsapfs_directory_record_free(
1668
117
     &safe_directory_record,
1669
117
     NULL );
1670
117
  }
1671
153
  return( -1 );
1672
965
}
1673
1674
/* Retrieves a directory record for an UTF-8 encoded name from the file system B-tree branch node
1675
 * Returns 1 if successful, 0 if not found or -1 on error
1676
 */
1677
int libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name(
1678
     libfsapfs_file_system_btree_t *file_system_btree,
1679
     libbfio_handle_t *file_io_handle,
1680
     libfsapfs_btree_node_t *node,
1681
     uint64_t parent_identifier,
1682
     const uint8_t *utf8_string,
1683
     size_t utf8_string_length,
1684
     uint32_t name_hash,
1685
     uint64_t transaction_identifier,
1686
     libfsapfs_directory_record_t **directory_record,
1687
     int recursion_depth,
1688
     libcerror_error_t **error )
1689
461
{
1690
461
  libfsapfs_btree_entry_t *entry                      = NULL;
1691
461
  libfsapfs_btree_entry_t *previous_entry             = NULL;
1692
461
  libfsapfs_btree_node_t *sub_node                    = NULL;
1693
461
  libfsapfs_directory_record_t *safe_directory_record = NULL;
1694
461
  static char *function                               = "libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name";
1695
461
  uint64_t file_system_identifier                     = 0;
1696
461
  uint64_t sub_node_block_number                      = 0;
1697
461
  uint8_t file_system_data_type                       = 0;
1698
461
  int compare_result                                  = 0;
1699
461
  int entry_index                                     = 0;
1700
461
  int is_leaf_node                                    = 0;
1701
461
  int number_of_entries                               = 0;
1702
461
  int result                                          = 0;
1703
1704
461
  if( file_system_btree == NULL )
1705
0
  {
1706
0
    libcerror_error_set(
1707
0
     error,
1708
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1709
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1710
0
     "%s: invalid file system B-tree.",
1711
0
     function );
1712
1713
0
    return( -1 );
1714
0
  }
1715
461
  if( node == NULL )
1716
0
  {
1717
0
    libcerror_error_set(
1718
0
     error,
1719
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1720
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1721
0
     "%s: invalid node.",
1722
0
     function );
1723
1724
0
    return( -1 );
1725
0
  }
1726
461
  if( directory_record == NULL )
1727
0
  {
1728
0
    libcerror_error_set(
1729
0
     error,
1730
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1731
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1732
0
     "%s: invalid directory record.",
1733
0
     function );
1734
1735
0
    return( -1 );
1736
0
  }
1737
461
  if( ( recursion_depth < 0 )
1738
461
   || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1739
1
  {
1740
1
    libcerror_error_set(
1741
1
     error,
1742
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1743
1
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1744
1
     "%s: invalid recursion depth value out of bounds.",
1745
1
     function );
1746
1747
1
    return( -1 );
1748
1
  }
1749
#if defined( HAVE_DEBUG_OUTPUT )
1750
  if( libcnotify_verbose != 0 )
1751
  {
1752
    libcnotify_printf(
1753
     "%s: retrieving directory record: %" PRIu64 " (transaction: %" PRIu64 ")\n",
1754
     function,
1755
     parent_identifier,
1756
     transaction_identifier );
1757
  }
1758
#endif
1759
460
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1760
460
                  node,
1761
460
                  error );
1762
1763
460
  if( is_leaf_node == -1 )
1764
0
  {
1765
0
    libcerror_error_set(
1766
0
     error,
1767
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1768
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1769
0
     "%s: unable to determine if B-tree node is a leaf node.",
1770
0
     function );
1771
1772
0
    goto on_error;
1773
0
  }
1774
460
  else if( is_leaf_node != 0 )
1775
0
  {
1776
0
    libcerror_error_set(
1777
0
     error,
1778
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1779
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1780
0
     "%s: invalid node - not a branch node.",
1781
0
     function );
1782
1783
0
    goto on_error;
1784
0
  }
1785
460
  if( libfsapfs_btree_node_get_number_of_entries(
1786
460
       node,
1787
460
       &number_of_entries,
1788
460
       error ) != 1 )
1789
0
  {
1790
0
    libcerror_error_set(
1791
0
     error,
1792
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1793
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1794
0
     "%s: unable to retrieve number of entries from B-tree node.",
1795
0
     function );
1796
1797
0
    goto on_error;
1798
0
  }
1799
460
  for( entry_index = 0;
1800
2.45k
       entry_index < number_of_entries;
1801
1.99k
       entry_index++ )
1802
2.37k
  {
1803
2.37k
    if( libfsapfs_btree_node_get_entry_by_index(
1804
2.37k
         node,
1805
2.37k
         entry_index,
1806
2.37k
         &entry,
1807
2.37k
         error ) != 1 )
1808
0
    {
1809
0
      libcerror_error_set(
1810
0
       error,
1811
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1812
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1813
0
       "%s: unable to retrieve number of entries from B-tree node.",
1814
0
       function );
1815
1816
0
      goto on_error;
1817
0
    }
1818
2.37k
    if( entry == NULL )
1819
0
    {
1820
0
      libcerror_error_set(
1821
0
       error,
1822
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1823
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1824
0
       "%s: invalid B-tree entry: %d.",
1825
0
       function,
1826
0
       entry_index );
1827
1828
0
      goto on_error;
1829
0
    }
1830
2.37k
    if( entry->key_data == NULL )
1831
1
    {
1832
1
      libcerror_error_set(
1833
1
       error,
1834
1
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1835
1
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1836
1
       "%s: invalid B-tree entry: %d - missing key data.",
1837
1
       function,
1838
1
       entry_index );
1839
1840
1
      goto on_error;
1841
1
    }
1842
2.37k
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
1843
4
    {
1844
4
      libcerror_error_set(
1845
4
       error,
1846
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1847
4
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1848
4
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1849
4
       function,
1850
4
       entry_index );
1851
1852
4
      goto on_error;
1853
4
    }
1854
2.36k
    byte_stream_copy_to_uint64_little_endian(
1855
2.36k
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
1856
2.36k
     file_system_identifier );
1857
1858
2.36k
    file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
1859
1860
#if defined( HAVE_DEBUG_OUTPUT )
1861
    if( libcnotify_verbose != 0 )
1862
    {
1863
      libcnotify_printf(
1864
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
1865
       function,
1866
       entry_index,
1867
       file_system_identifier & 0x0fffffffffffffffUL,
1868
       file_system_data_type,
1869
       libfsapfs_debug_print_file_system_data_type(
1870
        file_system_data_type ) );
1871
    }
1872
#endif
1873
2.36k
    file_system_identifier &= 0x0fffffffffffffffUL;
1874
1875
2.36k
    if( ( file_system_identifier > parent_identifier )
1876
2.36k
     || ( ( file_system_identifier == parent_identifier )
1877
1.99k
      &&  ( file_system_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD ) ) )
1878
370
    {
1879
370
      break;
1880
370
    }
1881
1.99k
    if( ( file_system_identifier == parent_identifier )
1882
1.99k
     && ( file_system_data_type == LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD ) )
1883
45
    {
1884
45
      if( libfsapfs_directory_record_initialize(
1885
45
           &safe_directory_record,
1886
45
           error ) != 1 )
1887
0
      {
1888
0
        libcerror_error_set(
1889
0
         error,
1890
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1891
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1892
0
         "%s: unable to create directory record.",
1893
0
         function );
1894
1895
0
        goto on_error;
1896
0
      }
1897
45
      if( libfsapfs_directory_record_read_key_data(
1898
45
           safe_directory_record,
1899
45
           entry->key_data,
1900
45
           (size_t) entry->key_data_size,
1901
45
           error ) != 1 )
1902
2
      {
1903
2
        libcerror_error_set(
1904
2
         error,
1905
2
         LIBCERROR_ERROR_DOMAIN_IO,
1906
2
         LIBCERROR_IO_ERROR_READ_FAILED,
1907
2
         "%s: unable to read directory record key data.",
1908
2
         function );
1909
1910
2
        goto on_error;
1911
2
      }
1912
      /* The directory records are sorted by case-sensitive name
1913
       */
1914
43
      compare_result = libfsapfs_directory_record_compare_name_with_utf8_string(
1915
43
                        safe_directory_record,
1916
43
                        utf8_string,
1917
43
                        utf8_string_length,
1918
43
                        name_hash,
1919
43
                        0,
1920
43
                        error );
1921
1922
43
      if( compare_result == -1 )
1923
1
      {
1924
1
        libcerror_error_set(
1925
1
         error,
1926
1
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1927
1
         LIBCERROR_RUNTIME_ERROR_GENERIC,
1928
1
         "%s: unable to compare UTF-8 string with name of directory record.",
1929
1
         function );
1930
1931
1
        goto on_error;
1932
1
      }
1933
42
      if( libfsapfs_directory_record_free(
1934
42
           &safe_directory_record,
1935
42
           error ) != 1 )
1936
0
      {
1937
0
        libcerror_error_set(
1938
0
         error,
1939
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1940
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1941
0
         "%s: unable to free directory record.",
1942
0
         function );
1943
1944
0
        goto on_error;
1945
0
      }
1946
42
      if( compare_result == LIBUNA_COMPARE_LESS )
1947
1
      {
1948
1
        break;
1949
1
      }
1950
42
    }
1951
1.99k
    previous_entry = entry;
1952
1.99k
  }
1953
452
  if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
1954
452
       file_system_btree,
1955
452
       file_io_handle,
1956
452
       previous_entry,
1957
452
       transaction_identifier,
1958
452
       &sub_node_block_number,
1959
452
       error ) != 1 )
1960
118
  {
1961
118
    libcerror_error_set(
1962
118
     error,
1963
118
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1964
118
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1965
118
     "%s: unable to determine sub node block number.",
1966
118
     function );
1967
1968
118
    goto on_error;
1969
118
  }
1970
334
  if( libfsapfs_file_system_btree_get_sub_node(
1971
334
       file_system_btree,
1972
334
       file_io_handle,
1973
334
       sub_node_block_number,
1974
334
       &sub_node,
1975
334
       error ) != 1 )
1976
75
  {
1977
75
    libcerror_error_set(
1978
75
     error,
1979
75
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1980
75
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1981
75
     "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1982
75
     function,
1983
75
     sub_node_block_number );
1984
1985
75
    goto on_error;
1986
75
  }
1987
259
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1988
259
                  sub_node,
1989
259
                  error );
1990
1991
259
  if( is_leaf_node == -1 )
1992
0
  {
1993
0
    libcerror_error_set(
1994
0
     error,
1995
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1996
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1997
0
     "%s: unable to determine if B-tree sub node is a leaf node.",
1998
0
     function );
1999
2000
0
    goto on_error;
2001
0
  }
2002
259
  if( is_leaf_node != 0 )
2003
1
  {
2004
1
    result = libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf8_name(
2005
1
        file_system_btree,
2006
1
        sub_node,
2007
1
        parent_identifier,
2008
1
        utf8_string,
2009
1
        utf8_string_length,
2010
1
        name_hash,
2011
1
        directory_record,
2012
1
        error );
2013
1
  }
2014
258
  else
2015
258
  {
2016
258
    result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name(
2017
258
        file_system_btree,
2018
258
        file_io_handle,
2019
258
        sub_node,
2020
258
        parent_identifier,
2021
258
        utf8_string,
2022
258
        utf8_string_length,
2023
258
        name_hash,
2024
258
        transaction_identifier,
2025
258
        directory_record,
2026
258
        recursion_depth + 1,
2027
258
        error );
2028
258
  }
2029
259
  if( result == -1 )
2030
258
  {
2031
258
    libcerror_error_set(
2032
258
     error,
2033
258
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2034
258
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2035
258
     "%s: unable to retrieve directory entry by name.",
2036
258
     function );
2037
2038
258
    goto on_error;
2039
258
  }
2040
1
  sub_node = NULL;
2041
2042
1
  return( result );
2043
2044
459
on_error:
2045
459
  if( *directory_record != NULL )
2046
0
  {
2047
0
    libfsapfs_directory_record_free(
2048
0
     directory_record,
2049
0
     NULL );
2050
0
  }
2051
459
  if( safe_directory_record != NULL )
2052
3
  {
2053
3
    libfsapfs_directory_record_free(
2054
3
     &safe_directory_record,
2055
3
     NULL );
2056
3
  }
2057
459
  return( -1 );
2058
259
}
2059
2060
/* Retrieves a directory record for an UTF-16 encoded name from the file system B-tree leaf node
2061
 * Returns 1 if successful, 0 if not found or -1 on error
2062
 */
2063
int libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf16_name(
2064
     libfsapfs_file_system_btree_t *file_system_btree,
2065
     libfsapfs_btree_node_t *node,
2066
     uint64_t parent_identifier,
2067
     const uint16_t *utf16_string,
2068
     size_t utf16_string_length,
2069
     uint32_t name_hash,
2070
     libfsapfs_directory_record_t **directory_record,
2071
     libcerror_error_t **error )
2072
0
{
2073
0
  libfsapfs_btree_entry_t *entry                      = NULL;
2074
0
  libfsapfs_directory_record_t *safe_directory_record = NULL;
2075
0
  static char *function                               = "libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf16_name";
2076
0
  uint64_t file_system_identifier                     = 0;
2077
0
  uint64_t lookup_identifier                          = 0;
2078
0
  int compare_result                                  = 0;
2079
0
  int entry_index                                     = 0;
2080
0
  int is_leaf_node                                    = 0;
2081
0
  int number_of_entries                               = 0;
2082
2083
#if defined( HAVE_DEBUG_OUTPUT )
2084
  uint8_t file_system_data_type                       = 0;
2085
#endif
2086
2087
0
  if( file_system_btree == NULL )
2088
0
  {
2089
0
    libcerror_error_set(
2090
0
     error,
2091
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2092
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2093
0
     "%s: invalid file system B-tree.",
2094
0
     function );
2095
2096
0
    return( -1 );
2097
0
  }
2098
0
  if( directory_record == NULL )
2099
0
  {
2100
0
    libcerror_error_set(
2101
0
     error,
2102
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2103
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2104
0
     "%s: invalid directory record.",
2105
0
     function );
2106
2107
0
    return( -1 );
2108
0
  }
2109
#if defined( HAVE_DEBUG_OUTPUT )
2110
  if( libcnotify_verbose != 0 )
2111
  {
2112
    libcnotify_printf(
2113
     "%s: retrieving directory record: %" PRIu64 "\n",
2114
     function,
2115
     parent_identifier );
2116
  }
2117
#endif
2118
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
2119
0
                  node,
2120
0
                  error );
2121
2122
0
  if( is_leaf_node == -1 )
2123
0
  {
2124
0
    libcerror_error_set(
2125
0
     error,
2126
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2127
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2128
0
     "%s: unable to determine if B-tree node is a leaf node.",
2129
0
     function );
2130
2131
0
    goto on_error;
2132
0
  }
2133
0
  else if( is_leaf_node == 0 )
2134
0
  {
2135
0
    libcerror_error_set(
2136
0
     error,
2137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2138
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2139
0
     "%s: invalid node - not a leaf node.",
2140
0
     function );
2141
2142
0
    goto on_error;
2143
0
  }
2144
0
  if( libfsapfs_btree_node_get_number_of_entries(
2145
0
       node,
2146
0
       &number_of_entries,
2147
0
       error ) != 1 )
2148
0
  {
2149
0
    libcerror_error_set(
2150
0
     error,
2151
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2152
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2153
0
     "%s: unable to retrieve number of entries from B-tree node.",
2154
0
     function );
2155
2156
0
    goto on_error;
2157
0
  }
2158
0
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD << 60 ) | parent_identifier;
2159
2160
0
  for( entry_index = 0;
2161
0
       entry_index < number_of_entries;
2162
0
       entry_index++ )
2163
0
  {
2164
0
    if( libfsapfs_btree_node_get_entry_by_index(
2165
0
         node,
2166
0
         entry_index,
2167
0
         &entry,
2168
0
         error ) != 1 )
2169
0
    {
2170
0
      libcerror_error_set(
2171
0
       error,
2172
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2173
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2174
0
       "%s: unable to retrieve number of entries from B-tree node.",
2175
0
       function );
2176
2177
0
      goto on_error;
2178
0
    }
2179
0
    if( entry == NULL )
2180
0
    {
2181
0
      libcerror_error_set(
2182
0
       error,
2183
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2184
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2185
0
       "%s: invalid B-tree entry: %d.",
2186
0
       function,
2187
0
       entry_index );
2188
2189
0
      goto on_error;
2190
0
    }
2191
0
    if( entry->key_data == NULL )
2192
0
    {
2193
0
      libcerror_error_set(
2194
0
       error,
2195
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2196
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2197
0
       "%s: invalid B-tree entry: %d - missing key data.",
2198
0
       function,
2199
0
       entry_index );
2200
2201
0
      goto on_error;
2202
0
    }
2203
0
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
2204
0
    {
2205
0
      libcerror_error_set(
2206
0
       error,
2207
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2208
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2209
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
2210
0
       function,
2211
0
       entry_index );
2212
2213
0
      goto on_error;
2214
0
    }
2215
0
    byte_stream_copy_to_uint64_little_endian(
2216
0
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
2217
0
     file_system_identifier );
2218
2219
#if defined( HAVE_DEBUG_OUTPUT )
2220
    if( libcnotify_verbose != 0 )
2221
    {
2222
      file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
2223
2224
      libcnotify_printf(
2225
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
2226
       function,
2227
       entry_index,
2228
       file_system_identifier & 0x0fffffffffffffffUL,
2229
       file_system_data_type,
2230
       libfsapfs_debug_print_file_system_data_type(
2231
        file_system_data_type ) );
2232
    }
2233
#endif
2234
0
    if( file_system_identifier == lookup_identifier )
2235
0
    {
2236
0
      if( libfsapfs_directory_record_initialize(
2237
0
           &safe_directory_record,
2238
0
           error ) != 1 )
2239
0
      {
2240
0
        libcerror_error_set(
2241
0
         error,
2242
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2243
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2244
0
         "%s: unable to create directory record.",
2245
0
         function );
2246
2247
0
        goto on_error;
2248
0
      }
2249
0
      if( libfsapfs_directory_record_read_key_data(
2250
0
           safe_directory_record,
2251
0
           entry->key_data,
2252
0
           (size_t) entry->key_data_size,
2253
0
           error ) != 1 )
2254
0
      {
2255
0
        libcerror_error_set(
2256
0
         error,
2257
0
         LIBCERROR_ERROR_DOMAIN_IO,
2258
0
         LIBCERROR_IO_ERROR_READ_FAILED,
2259
0
         "%s: unable to read directory record key data.",
2260
0
         function );
2261
2262
0
        goto on_error;
2263
0
      }
2264
0
      compare_result = libfsapfs_directory_record_compare_name_with_utf16_string(
2265
0
                        safe_directory_record,
2266
0
                        utf16_string,
2267
0
                        utf16_string_length,
2268
0
                        name_hash,
2269
0
                        file_system_btree->use_case_folding,
2270
0
                        error );
2271
2272
0
      if( compare_result == -1 )
2273
0
      {
2274
0
        libcerror_error_set(
2275
0
         error,
2276
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2277
0
         LIBCERROR_RUNTIME_ERROR_GENERIC,
2278
0
         "%s: unable to compare UTF-16 string with name of directory record.",
2279
0
         function );
2280
2281
0
        goto on_error;
2282
0
      }
2283
0
      else if( compare_result == LIBUNA_COMPARE_EQUAL )
2284
0
      {
2285
0
        if( libfsapfs_directory_record_read_value_data(
2286
0
             safe_directory_record,
2287
0
             entry->value_data,
2288
0
             (size_t) entry->value_data_size,
2289
0
             error ) != 1 )
2290
0
        {
2291
0
          libcerror_error_set(
2292
0
           error,
2293
0
           LIBCERROR_ERROR_DOMAIN_IO,
2294
0
           LIBCERROR_IO_ERROR_READ_FAILED,
2295
0
           "%s: unable to read directory record value data.",
2296
0
           function );
2297
2298
0
          goto on_error;
2299
0
        }
2300
0
        *directory_record = safe_directory_record;
2301
2302
0
        return( 1 );
2303
0
      }
2304
0
      if( libfsapfs_directory_record_free(
2305
0
           &safe_directory_record,
2306
0
           error ) != 1 )
2307
0
      {
2308
0
        libcerror_error_set(
2309
0
         error,
2310
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2311
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2312
0
         "%s: unable to free directory record.",
2313
0
         function );
2314
2315
0
        goto on_error;
2316
0
      }
2317
0
    }
2318
0
  }
2319
0
  return( 0 );
2320
2321
0
on_error:
2322
0
  if( safe_directory_record != NULL )
2323
0
  {
2324
0
    libfsapfs_directory_record_free(
2325
0
     &safe_directory_record,
2326
0
     NULL );
2327
0
  }
2328
0
  return( -1 );
2329
0
}
2330
2331
/* Retrieves a directory record for an UTF-16 encoded name from the file system B-tree branch node
2332
 * Returns 1 if successful, 0 if not found or -1 on error
2333
 */
2334
int libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf16_name(
2335
     libfsapfs_file_system_btree_t *file_system_btree,
2336
     libbfio_handle_t *file_io_handle,
2337
     libfsapfs_btree_node_t *node,
2338
     uint64_t parent_identifier,
2339
     const uint16_t *utf16_string,
2340
     size_t utf16_string_length,
2341
     uint32_t name_hash,
2342
     uint64_t transaction_identifier,
2343
     libfsapfs_directory_record_t **directory_record,
2344
     int recursion_depth,
2345
     libcerror_error_t **error )
2346
0
{
2347
0
  libfsapfs_btree_entry_t *entry                      = NULL;
2348
0
  libfsapfs_btree_entry_t *previous_entry             = NULL;
2349
0
  libfsapfs_btree_node_t *sub_node                    = NULL;
2350
0
  libfsapfs_directory_record_t *safe_directory_record = NULL;
2351
0
  static char *function                               = "libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf16_name";
2352
0
  uint64_t file_system_identifier                     = 0;
2353
0
  uint64_t sub_node_block_number                      = 0;
2354
0
  uint8_t file_system_data_type                       = 0;
2355
0
  int compare_result                                  = 0;
2356
0
  int entry_index                                     = 0;
2357
0
  int is_leaf_node                                    = 0;
2358
0
  int number_of_entries                               = 0;
2359
0
  int result                                          = 0;
2360
2361
0
  if( file_system_btree == NULL )
2362
0
  {
2363
0
    libcerror_error_set(
2364
0
     error,
2365
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2366
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2367
0
     "%s: invalid file system B-tree.",
2368
0
     function );
2369
2370
0
    return( -1 );
2371
0
  }
2372
0
  if( node == NULL )
2373
0
  {
2374
0
    libcerror_error_set(
2375
0
     error,
2376
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2377
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2378
0
     "%s: invalid node.",
2379
0
     function );
2380
2381
0
    return( -1 );
2382
0
  }
2383
0
  if( directory_record == NULL )
2384
0
  {
2385
0
    libcerror_error_set(
2386
0
     error,
2387
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2388
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2389
0
     "%s: invalid directory record.",
2390
0
     function );
2391
2392
0
    return( -1 );
2393
0
  }
2394
0
  if( ( recursion_depth < 0 )
2395
0
   || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
2396
0
  {
2397
0
    libcerror_error_set(
2398
0
     error,
2399
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2400
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2401
0
     "%s: invalid recursion depth value out of bounds.",
2402
0
     function );
2403
2404
0
    return( -1 );
2405
0
  }
2406
#if defined( HAVE_DEBUG_OUTPUT )
2407
  if( libcnotify_verbose != 0 )
2408
  {
2409
    libcnotify_printf(
2410
     "%s: retrieving directory record: %" PRIu64 " (transaction: %" PRIu64 ")\n",
2411
     function,
2412
     parent_identifier,
2413
     transaction_identifier );
2414
  }
2415
#endif
2416
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
2417
0
                  node,
2418
0
                  error );
2419
2420
0
  if( is_leaf_node == -1 )
2421
0
  {
2422
0
    libcerror_error_set(
2423
0
     error,
2424
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2425
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2426
0
     "%s: unable to determine if B-tree node is a leaf node.",
2427
0
     function );
2428
2429
0
    goto on_error;
2430
0
  }
2431
0
  else if( is_leaf_node != 0 )
2432
0
  {
2433
0
    libcerror_error_set(
2434
0
     error,
2435
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2436
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2437
0
     "%s: invalid node - not a branch node.",
2438
0
     function );
2439
2440
0
    goto on_error;
2441
0
  }
2442
0
  if( libfsapfs_btree_node_get_number_of_entries(
2443
0
       node,
2444
0
       &number_of_entries,
2445
0
       error ) != 1 )
2446
0
  {
2447
0
    libcerror_error_set(
2448
0
     error,
2449
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2450
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2451
0
     "%s: unable to retrieve number of entries from B-tree node.",
2452
0
     function );
2453
2454
0
    goto on_error;
2455
0
  }
2456
0
  for( entry_index = 0;
2457
0
       entry_index < number_of_entries;
2458
0
       entry_index++ )
2459
0
  {
2460
0
    if( libfsapfs_btree_node_get_entry_by_index(
2461
0
         node,
2462
0
         entry_index,
2463
0
         &entry,
2464
0
         error ) != 1 )
2465
0
    {
2466
0
      libcerror_error_set(
2467
0
       error,
2468
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2469
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2470
0
       "%s: unable to retrieve number of entries from B-tree node.",
2471
0
       function );
2472
2473
0
      goto on_error;
2474
0
    }
2475
0
    if( entry == NULL )
2476
0
    {
2477
0
      libcerror_error_set(
2478
0
       error,
2479
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2480
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2481
0
       "%s: invalid B-tree entry: %d.",
2482
0
       function,
2483
0
       entry_index );
2484
2485
0
      goto on_error;
2486
0
    }
2487
0
    if( entry->key_data == NULL )
2488
0
    {
2489
0
      libcerror_error_set(
2490
0
       error,
2491
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2492
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2493
0
       "%s: invalid B-tree entry: %d - missing key data.",
2494
0
       function,
2495
0
       entry_index );
2496
2497
0
      goto on_error;
2498
0
    }
2499
0
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
2500
0
    {
2501
0
      libcerror_error_set(
2502
0
       error,
2503
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2504
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2505
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
2506
0
       function,
2507
0
       entry_index );
2508
2509
0
      goto on_error;
2510
0
    }
2511
0
    byte_stream_copy_to_uint64_little_endian(
2512
0
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
2513
0
     file_system_identifier );
2514
2515
0
    file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
2516
2517
#if defined( HAVE_DEBUG_OUTPUT )
2518
    if( libcnotify_verbose != 0 )
2519
    {
2520
      libcnotify_printf(
2521
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
2522
       function,
2523
       entry_index,
2524
       file_system_identifier & 0x0fffffffffffffffUL,
2525
       file_system_data_type,
2526
       libfsapfs_debug_print_file_system_data_type(
2527
        file_system_data_type ) );
2528
    }
2529
#endif
2530
0
    file_system_identifier &= 0x0fffffffffffffffUL;
2531
2532
0
    if( ( file_system_identifier > parent_identifier )
2533
0
     || ( ( file_system_identifier == parent_identifier )
2534
0
      &&  ( file_system_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD ) ) )
2535
0
    {
2536
0
      break;
2537
0
    }
2538
0
    if( ( file_system_identifier == parent_identifier )
2539
0
     && ( file_system_data_type == LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD ) )
2540
0
    {
2541
0
      if( libfsapfs_directory_record_initialize(
2542
0
           &safe_directory_record,
2543
0
           error ) != 1 )
2544
0
      {
2545
0
        libcerror_error_set(
2546
0
         error,
2547
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2548
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2549
0
         "%s: unable to create directory record.",
2550
0
         function );
2551
2552
0
        goto on_error;
2553
0
      }
2554
0
      if( libfsapfs_directory_record_read_key_data(
2555
0
           safe_directory_record,
2556
0
           entry->key_data,
2557
0
           (size_t) entry->key_data_size,
2558
0
           error ) != 1 )
2559
0
      {
2560
0
        libcerror_error_set(
2561
0
         error,
2562
0
         LIBCERROR_ERROR_DOMAIN_IO,
2563
0
         LIBCERROR_IO_ERROR_READ_FAILED,
2564
0
         "%s: unable to read directory record key data.",
2565
0
         function );
2566
2567
0
        goto on_error;
2568
0
      }
2569
      /* The directory records are sorted by case-sensitive name
2570
       */
2571
0
      compare_result = libfsapfs_directory_record_compare_name_with_utf16_string(
2572
0
                        safe_directory_record,
2573
0
                        utf16_string,
2574
0
                        utf16_string_length,
2575
0
                        name_hash,
2576
0
                        0,
2577
0
                        error );
2578
2579
0
      if( compare_result == -1 )
2580
0
      {
2581
0
        libcerror_error_set(
2582
0
         error,
2583
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2584
0
         LIBCERROR_RUNTIME_ERROR_GENERIC,
2585
0
         "%s: unable to compare UTF-16 string with name of directory record.",
2586
0
         function );
2587
2588
0
        goto on_error;
2589
0
      }
2590
0
      if( libfsapfs_directory_record_free(
2591
0
           &safe_directory_record,
2592
0
           error ) != 1 )
2593
0
      {
2594
0
        libcerror_error_set(
2595
0
         error,
2596
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2597
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2598
0
         "%s: unable to free directory record.",
2599
0
         function );
2600
2601
0
        goto on_error;
2602
0
      }
2603
0
      if( compare_result == LIBUNA_COMPARE_LESS )
2604
0
      {
2605
0
        break;
2606
0
      }
2607
0
    }
2608
0
    previous_entry = entry;
2609
0
  }
2610
0
  if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
2611
0
       file_system_btree,
2612
0
       file_io_handle,
2613
0
       previous_entry,
2614
0
       transaction_identifier,
2615
0
       &sub_node_block_number,
2616
0
       error ) != 1 )
2617
0
  {
2618
0
    libcerror_error_set(
2619
0
     error,
2620
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2621
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2622
0
     "%s: unable to determine sub node block number.",
2623
0
     function );
2624
2625
0
    goto on_error;
2626
0
  }
2627
0
  if( libfsapfs_file_system_btree_get_sub_node(
2628
0
       file_system_btree,
2629
0
       file_io_handle,
2630
0
       sub_node_block_number,
2631
0
       &sub_node,
2632
0
       error ) != 1 )
2633
0
  {
2634
0
    libcerror_error_set(
2635
0
     error,
2636
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2637
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2638
0
     "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
2639
0
     function,
2640
0
     sub_node_block_number );
2641
2642
0
    goto on_error;
2643
0
  }
2644
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
2645
0
                  sub_node,
2646
0
                  error );
2647
2648
0
  if( is_leaf_node == -1 )
2649
0
  {
2650
0
    libcerror_error_set(
2651
0
     error,
2652
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2653
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2654
0
     "%s: unable to determine if B-tree sub node is a leaf node.",
2655
0
     function );
2656
2657
0
    goto on_error;
2658
0
  }
2659
0
  if( is_leaf_node != 0 )
2660
0
  {
2661
0
    result = libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf16_name(
2662
0
        file_system_btree,
2663
0
        sub_node,
2664
0
        parent_identifier,
2665
0
        utf16_string,
2666
0
        utf16_string_length,
2667
0
        name_hash,
2668
0
        directory_record,
2669
0
        error );
2670
0
  }
2671
0
  else
2672
0
  {
2673
0
    result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf16_name(
2674
0
        file_system_btree,
2675
0
        file_io_handle,
2676
0
        sub_node,
2677
0
        parent_identifier,
2678
0
        utf16_string,
2679
0
        utf16_string_length,
2680
0
        name_hash,
2681
0
        transaction_identifier,
2682
0
        directory_record,
2683
0
        recursion_depth + 1,
2684
0
        error );
2685
0
  }
2686
0
  if( result == -1 )
2687
0
  {
2688
0
    libcerror_error_set(
2689
0
     error,
2690
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2691
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2692
0
     "%s: unable to retrieve directory entry by name.",
2693
0
     function );
2694
2695
0
    goto on_error;
2696
0
  }
2697
0
  sub_node = NULL;
2698
2699
0
  return( result );
2700
2701
0
on_error:
2702
0
  if( *directory_record != NULL )
2703
0
  {
2704
0
    libfsapfs_directory_record_free(
2705
0
     directory_record,
2706
0
     NULL );
2707
0
  }
2708
0
  if( safe_directory_record != NULL )
2709
0
  {
2710
0
    libfsapfs_directory_record_free(
2711
0
     &safe_directory_record,
2712
0
     NULL );
2713
0
  }
2714
0
  return( -1 );
2715
0
}
2716
2717
/* Retrieves directory entries for a specific parent identifier from the file system B-tree leaf node
2718
 * Returns 1 if successful, 0 if not found or -1 on error
2719
 */
2720
int libfsapfs_file_system_btree_get_directory_entries_from_leaf_node(
2721
     libfsapfs_file_system_btree_t *file_system_btree,
2722
     libfsapfs_btree_node_t *node,
2723
     uint64_t parent_identifier,
2724
     libcdata_array_t *directory_entries,
2725
     libcerror_error_t **error )
2726
771
{
2727
771
  libfsapfs_btree_entry_t *btree_entry           = NULL;
2728
771
  libfsapfs_directory_record_t *directory_record = NULL;
2729
771
  static char *function                          = "libfsapfs_file_system_btree_get_directory_entries_from_leaf_node";
2730
771
  uint64_t file_system_identifier                = 0;
2731
771
  uint64_t lookup_identifier                     = 0;
2732
771
  int btree_entry_index                          = 0;
2733
771
  int entry_index                                = 0;
2734
771
  int found_directory_entry                      = 0;
2735
771
  int is_leaf_node                               = 0;
2736
771
  int number_of_entries                          = 0;
2737
2738
#if defined( HAVE_DEBUG_OUTPUT )
2739
  uint8_t file_system_data_type                  = 0;
2740
#endif
2741
2742
771
  if( file_system_btree == NULL )
2743
0
  {
2744
0
    libcerror_error_set(
2745
0
     error,
2746
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2747
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2748
0
     "%s: invalid file system B-tree.",
2749
0
     function );
2750
2751
0
    return( -1 );
2752
0
  }
2753
771
  if( node == NULL )
2754
0
  {
2755
0
    libcerror_error_set(
2756
0
     error,
2757
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2758
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2759
0
     "%s: invalid node.",
2760
0
     function );
2761
2762
0
    return( -1 );
2763
0
  }
2764
771
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
2765
771
                  node,
2766
771
                  error );
2767
2768
771
  if( is_leaf_node == -1 )
2769
0
  {
2770
0
    libcerror_error_set(
2771
0
     error,
2772
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2773
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2774
0
     "%s: unable to determine if B-tree node is a leaf node.",
2775
0
     function );
2776
2777
0
    goto on_error;
2778
0
  }
2779
771
  else if( is_leaf_node == 0 )
2780
0
  {
2781
0
    libcerror_error_set(
2782
0
     error,
2783
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2784
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2785
0
     "%s: invalid node - not a leaf node.",
2786
0
     function );
2787
2788
0
    goto on_error;
2789
0
  }
2790
#if defined( HAVE_DEBUG_OUTPUT )
2791
  if( libcnotify_verbose != 0 )
2792
  {
2793
    libcnotify_printf(
2794
     "%s: retrieving directory entries of: %" PRIu64 "\n",
2795
     function,
2796
     parent_identifier );
2797
  }
2798
#endif
2799
771
  if( libfsapfs_btree_node_get_number_of_entries(
2800
771
       node,
2801
771
       &number_of_entries,
2802
771
       error ) != 1 )
2803
0
  {
2804
0
    libcerror_error_set(
2805
0
     error,
2806
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2807
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2808
0
     "%s: unable to retrieve number of entries from B-tree node.",
2809
0
     function );
2810
2811
0
    goto on_error;
2812
0
  }
2813
771
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD << 60 ) | parent_identifier;
2814
2815
771
  for( btree_entry_index = 0;
2816
2.37k
       btree_entry_index < number_of_entries;
2817
1.60k
       btree_entry_index++ )
2818
2.36k
  {
2819
2.36k
    if( libfsapfs_btree_node_get_entry_by_index(
2820
2.36k
         node,
2821
2.36k
         btree_entry_index,
2822
2.36k
         &btree_entry,
2823
2.36k
         error ) != 1 )
2824
0
    {
2825
0
      libcerror_error_set(
2826
0
       error,
2827
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2828
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2829
0
       "%s: unable to retrieve number of entries from B-tree node.",
2830
0
       function );
2831
2832
0
      goto on_error;
2833
0
    }
2834
2.36k
    if( btree_entry == NULL )
2835
0
    {
2836
0
      libcerror_error_set(
2837
0
       error,
2838
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2839
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2840
0
       "%s: invalid B-tree entry: %d.",
2841
0
       function,
2842
0
       btree_entry_index );
2843
2844
0
      goto on_error;
2845
0
    }
2846
2.36k
    if( btree_entry->key_data == NULL )
2847
4
    {
2848
4
      libcerror_error_set(
2849
4
       error,
2850
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2851
4
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2852
4
       "%s: invalid B-tree entry: %d - missing key data.",
2853
4
       function,
2854
4
       btree_entry_index );
2855
2856
4
      goto on_error;
2857
4
    }
2858
2.35k
    if( btree_entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
2859
3
    {
2860
3
      libcerror_error_set(
2861
3
       error,
2862
3
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2863
3
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2864
3
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
2865
3
       function,
2866
3
       btree_entry_index );
2867
2868
3
      goto on_error;
2869
3
    }
2870
2.35k
    byte_stream_copy_to_uint64_little_endian(
2871
2.35k
     ( (fsapfs_file_system_btree_key_common_t *) btree_entry->key_data )->file_system_identifier,
2872
2.35k
     file_system_identifier );
2873
2874
#if defined( HAVE_DEBUG_OUTPUT )
2875
    if( libcnotify_verbose != 0 )
2876
    {
2877
      file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
2878
2879
      libcnotify_printf(
2880
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
2881
       function,
2882
       btree_entry_index,
2883
       file_system_identifier & 0x0fffffffffffffffUL,
2884
       file_system_data_type,
2885
       libfsapfs_debug_print_file_system_data_type(
2886
        file_system_data_type ) );
2887
    }
2888
#endif
2889
2.35k
    if( ( file_system_identifier & 0x0fffffffffffffffUL ) > parent_identifier )
2890
679
    {
2891
679
      break;
2892
679
    }
2893
1.67k
    if( file_system_identifier != lookup_identifier )
2894
877
    {
2895
877
      continue;
2896
877
    }
2897
797
    if( libfsapfs_directory_record_initialize(
2898
797
         &directory_record,
2899
797
         error ) != 1 )
2900
0
    {
2901
0
      libcerror_error_set(
2902
0
       error,
2903
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2904
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2905
0
       "%s: unable to create directory record.",
2906
0
       function );
2907
2908
0
      goto on_error;
2909
0
    }
2910
797
    if( libfsapfs_directory_record_read_key_data(
2911
797
         directory_record,
2912
797
         btree_entry->key_data,
2913
797
         (size_t) btree_entry->key_data_size,
2914
797
         error ) != 1 )
2915
16
    {
2916
16
      libcerror_error_set(
2917
16
       error,
2918
16
       LIBCERROR_ERROR_DOMAIN_IO,
2919
16
       LIBCERROR_IO_ERROR_READ_FAILED,
2920
16
       "%s: unable to read directory record key data.",
2921
16
       function );
2922
2923
16
      goto on_error;
2924
16
    }
2925
781
    if( libfsapfs_directory_record_read_value_data(
2926
781
         directory_record,
2927
781
         btree_entry->value_data,
2928
781
         (size_t) btree_entry->value_data_size,
2929
781
         error ) != 1 )
2930
57
    {
2931
57
      libcerror_error_set(
2932
57
       error,
2933
57
       LIBCERROR_ERROR_DOMAIN_IO,
2934
57
       LIBCERROR_IO_ERROR_READ_FAILED,
2935
57
       "%s: unable to read directory record value data.",
2936
57
       function );
2937
2938
57
      goto on_error;
2939
57
    }
2940
724
    if( libcdata_array_append_entry(
2941
724
         directory_entries,
2942
724
         &entry_index,
2943
724
         (intptr_t *) directory_record,
2944
724
         error ) != 1 )
2945
0
    {
2946
0
      libcerror_error_set(
2947
0
       error,
2948
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2949
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2950
0
       "%s: unable to append directory record to array.",
2951
0
       function );
2952
2953
0
      goto on_error;
2954
0
    }
2955
724
    directory_record = NULL;
2956
2957
724
    found_directory_entry = 1;
2958
724
  }
2959
691
  return( found_directory_entry );
2960
2961
80
on_error:
2962
80
  if( directory_record != NULL )
2963
73
  {
2964
73
    libfsapfs_directory_record_free(
2965
73
     &directory_record,
2966
73
     NULL );
2967
73
  }
2968
80
  libcdata_array_empty(
2969
80
   directory_entries,
2970
80
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
2971
80
   NULL );
2972
2973
80
  return( -1 );
2974
771
}
2975
2976
/* Retrieves directory entries for a specific parent identifier from the file system B-tree branch node
2977
 * Returns 1 if successful, 0 if not found or -1 on error
2978
 */
2979
int libfsapfs_file_system_btree_get_directory_entries_from_branch_node(
2980
     libfsapfs_file_system_btree_t *file_system_btree,
2981
     libbfio_handle_t *file_io_handle,
2982
     libfsapfs_btree_node_t *node,
2983
     uint64_t parent_identifier,
2984
     uint64_t transaction_identifier,
2985
     libcdata_array_t *directory_entries,
2986
     int recursion_depth,
2987
     libcerror_error_t **error )
2988
0
{
2989
0
  libfsapfs_btree_entry_t *entry          = NULL;
2990
0
  libfsapfs_btree_entry_t *previous_entry = NULL;
2991
0
  libfsapfs_btree_node_t *sub_node        = NULL;
2992
0
  static char *function                   = "libfsapfs_file_system_btree_get_directory_entries_from_branch_node";
2993
0
  uint64_t file_system_identifier         = 0;
2994
0
  uint64_t sub_node_block_number          = 0;
2995
0
  uint8_t file_system_data_type           = 0;
2996
0
  int entry_index                         = 0;
2997
0
  int found_directory_entry               = 0;
2998
0
  int is_leaf_node                        = 0;
2999
0
  int number_of_entries                   = 0;
3000
0
  int result                              = 0;
3001
3002
0
  if( file_system_btree == NULL )
3003
0
  {
3004
0
    libcerror_error_set(
3005
0
     error,
3006
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3007
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3008
0
     "%s: invalid file system B-tree.",
3009
0
     function );
3010
3011
0
    return( -1 );
3012
0
  }
3013
0
  if( node == NULL )
3014
0
  {
3015
0
    libcerror_error_set(
3016
0
     error,
3017
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3018
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3019
0
     "%s: invalid node.",
3020
0
     function );
3021
3022
0
    return( -1 );
3023
0
  }
3024
0
  if( ( recursion_depth < 0 )
3025
0
   || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
3026
0
  {
3027
0
    libcerror_error_set(
3028
0
     error,
3029
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3030
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3031
0
     "%s: invalid recursion depth value out of bounds.",
3032
0
     function );
3033
3034
0
    return( -1 );
3035
0
  }
3036
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3037
0
                  node,
3038
0
                  error );
3039
3040
0
  if( is_leaf_node == -1 )
3041
0
  {
3042
0
    libcerror_error_set(
3043
0
     error,
3044
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3045
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3046
0
     "%s: unable to determine if B-tree node is a leaf node.",
3047
0
     function );
3048
3049
0
    goto on_error;
3050
0
  }
3051
0
  else if( is_leaf_node != 0 )
3052
0
  {
3053
0
    libcerror_error_set(
3054
0
     error,
3055
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3056
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3057
0
     "%s: invalid node - not a branch node.",
3058
0
     function );
3059
3060
0
    goto on_error;
3061
0
  }
3062
#if defined( HAVE_DEBUG_OUTPUT )
3063
  if( libcnotify_verbose != 0 )
3064
  {
3065
    libcnotify_printf(
3066
     "%s: retrieving directory entries of: %" PRIu64 " (transaction: %" PRIu64 ")\n",
3067
     function,
3068
     parent_identifier,
3069
     transaction_identifier );
3070
  }
3071
#endif
3072
0
  if( libfsapfs_btree_node_get_number_of_entries(
3073
0
       node,
3074
0
       &number_of_entries,
3075
0
       error ) != 1 )
3076
0
  {
3077
0
    libcerror_error_set(
3078
0
     error,
3079
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3080
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3081
0
     "%s: unable to retrieve number of entries from B-tree node.",
3082
0
     function );
3083
3084
0
    goto on_error;
3085
0
  }
3086
0
  for( entry_index = 0;
3087
0
       entry_index < number_of_entries;
3088
0
       entry_index++ )
3089
0
  {
3090
0
    if( libfsapfs_btree_node_get_entry_by_index(
3091
0
         node,
3092
0
         entry_index,
3093
0
         &entry,
3094
0
         error ) != 1 )
3095
0
    {
3096
0
      libcerror_error_set(
3097
0
       error,
3098
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3099
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3100
0
       "%s: unable to retrieve number of entries from B-tree node.",
3101
0
       function );
3102
3103
0
      goto on_error;
3104
0
    }
3105
0
    if( entry == NULL )
3106
0
    {
3107
0
      libcerror_error_set(
3108
0
       error,
3109
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3110
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3111
0
       "%s: invalid B-tree entry: %d.",
3112
0
       function,
3113
0
       entry_index );
3114
3115
0
      goto on_error;
3116
0
    }
3117
0
    if( entry->key_data == NULL )
3118
0
    {
3119
0
      libcerror_error_set(
3120
0
       error,
3121
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3122
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3123
0
       "%s: invalid B-tree entry: %d - missing key data.",
3124
0
       function,
3125
0
       entry_index );
3126
3127
0
      goto on_error;
3128
0
    }
3129
0
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
3130
0
    {
3131
0
      libcerror_error_set(
3132
0
       error,
3133
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3134
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3135
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
3136
0
       function,
3137
0
       entry_index );
3138
3139
0
      goto on_error;
3140
0
    }
3141
0
    byte_stream_copy_to_uint64_little_endian(
3142
0
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
3143
0
     file_system_identifier );
3144
3145
0
    file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
3146
3147
#if defined( HAVE_DEBUG_OUTPUT )
3148
    if( libcnotify_verbose != 0 )
3149
    {
3150
      libcnotify_printf(
3151
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
3152
       function,
3153
       entry_index,
3154
       file_system_identifier & 0x0fffffffffffffffUL,
3155
       file_system_data_type,
3156
       libfsapfs_debug_print_file_system_data_type(
3157
        file_system_data_type ) );
3158
    }
3159
#endif
3160
0
    file_system_identifier &= 0x0fffffffffffffffUL;
3161
3162
0
    if( ( file_system_identifier > parent_identifier )
3163
0
     || ( ( file_system_identifier == parent_identifier )
3164
0
      &&  ( file_system_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD ) ) )
3165
0
    {
3166
0
      break;
3167
0
    }
3168
0
    if( ( file_system_identifier == parent_identifier )
3169
0
     && ( file_system_data_type == LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD )
3170
0
     && ( previous_entry != NULL ) )
3171
0
    {
3172
0
      if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
3173
0
           file_system_btree,
3174
0
           file_io_handle,
3175
0
           previous_entry,
3176
0
           transaction_identifier,
3177
0
           &sub_node_block_number,
3178
0
           error ) != 1 )
3179
0
      {
3180
0
        libcerror_error_set(
3181
0
         error,
3182
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3183
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3184
0
         "%s: unable to determine sub node block number.",
3185
0
         function );
3186
3187
0
        goto on_error;
3188
0
      }
3189
0
      if( libfsapfs_file_system_btree_get_sub_node(
3190
0
           file_system_btree,
3191
0
           file_io_handle,
3192
0
           sub_node_block_number,
3193
0
           &sub_node,
3194
0
           error ) != 1 )
3195
0
      {
3196
0
        libcerror_error_set(
3197
0
         error,
3198
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3199
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3200
0
         "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
3201
0
         function,
3202
0
         sub_node_block_number );
3203
3204
0
        goto on_error;
3205
0
      }
3206
0
      is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3207
0
                      sub_node,
3208
0
                      error );
3209
3210
0
      if( is_leaf_node == -1 )
3211
0
      {
3212
0
        libcerror_error_set(
3213
0
         error,
3214
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3215
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3216
0
         "%s: unable to determine if B-tree sub node is a leaf node.",
3217
0
         function );
3218
3219
0
        goto on_error;
3220
0
      }
3221
0
      if( is_leaf_node != 0 )
3222
0
      {
3223
0
        result = libfsapfs_file_system_btree_get_directory_entries_from_leaf_node(
3224
0
                  file_system_btree,
3225
0
                  sub_node,
3226
0
                  parent_identifier,
3227
0
                  directory_entries,
3228
0
                  error );
3229
0
      }
3230
0
      else
3231
0
      {
3232
0
        result = libfsapfs_file_system_btree_get_directory_entries_from_branch_node(
3233
0
                  file_system_btree,
3234
0
                  file_io_handle,
3235
0
                  sub_node,
3236
0
                  parent_identifier,
3237
0
                  transaction_identifier,
3238
0
                  directory_entries,
3239
0
                  recursion_depth + 1,
3240
0
                  error );
3241
0
      }
3242
0
      if( result == -1 )
3243
0
      {
3244
0
        libcerror_error_set(
3245
0
         error,
3246
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3247
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3248
0
         "%s: unable to retrieve directory entries: %" PRIu64 " from file system B-tree sub node.",
3249
0
         function,
3250
0
         parent_identifier );
3251
3252
0
        goto on_error;
3253
0
      }
3254
0
      else if( result != 0 )
3255
0
      {
3256
0
        found_directory_entry = 1;
3257
0
      }
3258
0
      sub_node = NULL;
3259
0
    }
3260
0
    previous_entry = entry;
3261
0
  }
3262
0
  if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
3263
0
       file_system_btree,
3264
0
       file_io_handle,
3265
0
       previous_entry,
3266
0
       transaction_identifier,
3267
0
       &sub_node_block_number,
3268
0
       error ) != 1 )
3269
0
  {
3270
0
    libcerror_error_set(
3271
0
     error,
3272
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3273
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3274
0
     "%s: unable to determine sub node block number.",
3275
0
     function );
3276
3277
0
    goto on_error;
3278
0
  }
3279
0
  if( libfsapfs_file_system_btree_get_sub_node(
3280
0
       file_system_btree,
3281
0
       file_io_handle,
3282
0
       sub_node_block_number,
3283
0
       &sub_node,
3284
0
       error ) != 1 )
3285
0
  {
3286
0
    libcerror_error_set(
3287
0
     error,
3288
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3289
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3290
0
     "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
3291
0
     function,
3292
0
     sub_node_block_number );
3293
3294
0
    goto on_error;
3295
0
  }
3296
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3297
0
                  sub_node,
3298
0
                  error );
3299
3300
0
  if( is_leaf_node == -1 )
3301
0
  {
3302
0
    libcerror_error_set(
3303
0
     error,
3304
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3305
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3306
0
     "%s: unable to determine if B-tree sub node is a leaf node.",
3307
0
     function );
3308
3309
0
    goto on_error;
3310
0
  }
3311
0
  if( is_leaf_node != 0 )
3312
0
  {
3313
0
    result = libfsapfs_file_system_btree_get_directory_entries_from_leaf_node(
3314
0
              file_system_btree,
3315
0
              sub_node,
3316
0
              parent_identifier,
3317
0
              directory_entries,
3318
0
              error );
3319
0
  }
3320
0
  else
3321
0
  {
3322
0
    result = libfsapfs_file_system_btree_get_directory_entries_from_branch_node(
3323
0
              file_system_btree,
3324
0
              file_io_handle,
3325
0
              sub_node,
3326
0
              parent_identifier,
3327
0
              transaction_identifier,
3328
0
              directory_entries,
3329
0
              recursion_depth + 1,
3330
0
              error );
3331
0
  }
3332
0
  if( result == -1 )
3333
0
  {
3334
0
    libcerror_error_set(
3335
0
     error,
3336
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3337
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3338
0
     "%s: unable to retrieve directory entries: %" PRIu64 " from file system B-tree sub node.",
3339
0
     function,
3340
0
     parent_identifier );
3341
3342
0
    goto on_error;
3343
0
  }
3344
0
  else if( result != 0 )
3345
0
  {
3346
0
    found_directory_entry = 1;
3347
0
  }
3348
0
  return( found_directory_entry );
3349
3350
0
on_error:
3351
0
  libcdata_array_empty(
3352
0
   directory_entries,
3353
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
3354
0
   NULL );
3355
3356
0
  return( -1 );
3357
0
}
3358
3359
/* Retrieves directory entries for a specific parent identifier from the file system B-tree
3360
 * Returns 1 if successful, 0 if not found or -1 on error
3361
 */
3362
int libfsapfs_file_system_btree_get_directory_entries(
3363
     libfsapfs_file_system_btree_t *file_system_btree,
3364
     libbfio_handle_t *file_io_handle,
3365
     uint64_t parent_identifier,
3366
     uint64_t transaction_identifier,
3367
     libcdata_array_t *directory_entries,
3368
     libcerror_error_t **error )
3369
771
{
3370
771
  libfsapfs_btree_node_t *root_node = NULL;
3371
771
  static char *function             = "libfsapfs_file_system_btree_get_directory_entries";
3372
771
  int is_leaf_node                  = 0;
3373
771
  int result                        = 0;
3374
3375
#if defined( HAVE_PROFILER )
3376
  int64_t profiler_start_timestamp  = 0;
3377
#endif
3378
3379
771
  if( file_system_btree == NULL )
3380
0
  {
3381
0
    libcerror_error_set(
3382
0
     error,
3383
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3384
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3385
0
     "%s: invalid file system B-tree.",
3386
0
     function );
3387
3388
0
    return( -1 );
3389
0
  }
3390
#if defined( HAVE_PROFILER )
3391
  if( file_system_btree->io_handle->profiler != NULL )
3392
  {
3393
    if( libfsapfs_profiler_start_timing(
3394
         file_system_btree->io_handle->profiler,
3395
         &profiler_start_timestamp,
3396
         error ) != 1 )
3397
    {
3398
      libcerror_error_set(
3399
       error,
3400
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3401
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3402
       "%s: unable to start timing.",
3403
       function );
3404
3405
      goto on_error;
3406
    }
3407
  }
3408
#endif /* defined( HAVE_PROFILER ) */
3409
3410
#if defined( HAVE_DEBUG_OUTPUT )
3411
  if( libcnotify_verbose != 0 )
3412
  {
3413
    libcnotify_printf(
3414
     "%s: retrieving directory entries of: %" PRIu64 " (transaction: %" PRIu64 ")\n",
3415
     function,
3416
     parent_identifier,
3417
     transaction_identifier );
3418
  }
3419
#endif
3420
771
  result = libfsapfs_file_system_btree_get_root_node(
3421
771
            file_system_btree,
3422
771
            file_io_handle,
3423
771
            file_system_btree->root_node_block_number,
3424
771
            &root_node,
3425
771
            error );
3426
3427
771
  if( result == -1 )
3428
0
  {
3429
0
    libcerror_error_set(
3430
0
     error,
3431
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3432
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3433
0
     "%s: unable to retrieve B-tree root node.",
3434
0
     function );
3435
3436
0
    goto on_error;
3437
0
  }
3438
771
  else if( result == 0 )
3439
0
  {
3440
0
    return( 0 );
3441
0
  }
3442
771
  if( root_node == NULL )
3443
0
  {
3444
0
    libcerror_error_set(
3445
0
     error,
3446
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3447
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3448
0
     "%s: invalid B-tree root node.",
3449
0
     function );
3450
3451
0
    goto on_error;
3452
0
  }
3453
771
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3454
771
                  root_node,
3455
771
                  error );
3456
3457
771
  if( is_leaf_node == -1 )
3458
0
  {
3459
0
    libcerror_error_set(
3460
0
     error,
3461
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3462
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3463
0
     "%s: unable to determine if B-tree root node is a leaf node.",
3464
0
     function );
3465
3466
0
    goto on_error;
3467
0
  }
3468
771
  if( is_leaf_node != 0 )
3469
771
  {
3470
771
    result = libfsapfs_file_system_btree_get_directory_entries_from_leaf_node(
3471
771
              file_system_btree,
3472
771
              root_node,
3473
771
              parent_identifier,
3474
771
              directory_entries,
3475
771
              error );
3476
771
  }
3477
0
  else
3478
0
  {
3479
0
    result = libfsapfs_file_system_btree_get_directory_entries_from_branch_node(
3480
0
              file_system_btree,
3481
0
              file_io_handle,
3482
0
              root_node,
3483
0
              parent_identifier,
3484
0
              transaction_identifier,
3485
0
              directory_entries,
3486
0
              0,
3487
0
              error );
3488
0
  }
3489
771
  if( result == -1 )
3490
80
  {
3491
80
    libcerror_error_set(
3492
80
     error,
3493
80
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3494
80
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3495
80
     "%s: unable to retrieve directory entries: %" PRIu64 " from file system B-tree root node.",
3496
80
     function,
3497
80
     parent_identifier );
3498
3499
80
    goto on_error;
3500
80
  }
3501
#if defined( HAVE_PROFILER )
3502
  if( file_system_btree->io_handle->profiler != NULL )
3503
  {
3504
    if( libfsapfs_profiler_stop_timing(
3505
         file_system_btree->io_handle->profiler,
3506
         profiler_start_timestamp,
3507
         function,
3508
         0,
3509
         0,
3510
         error ) != 1 )
3511
    {
3512
      libcerror_error_set(
3513
       error,
3514
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3515
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3516
       "%s: unable to stop timing.",
3517
       function );
3518
3519
      goto on_error;
3520
    }
3521
  }
3522
#endif /* defined( HAVE_PROFILER ) */
3523
3524
691
  return( result );
3525
3526
80
on_error:
3527
80
  libcdata_array_empty(
3528
80
   directory_entries,
3529
80
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
3530
80
   NULL );
3531
3532
80
  return( -1 );
3533
771
}
3534
3535
/* Retrieves attributes for a specific identifier from the file system B-tree leaf node
3536
 * Returns 1 if successful, 0 if not found or -1 on error
3537
 */
3538
int libfsapfs_file_system_btree_get_attributes_from_leaf_node(
3539
     libfsapfs_file_system_btree_t *file_system_btree,
3540
     libfsapfs_btree_node_t *node,
3541
     uint64_t identifier,
3542
     libcdata_array_t *extended_attributes_array,
3543
     libcerror_error_t **error )
3544
1.04k
{
3545
1.04k
  libfsapfs_attribute_values_t *attribute_values = NULL;
3546
1.04k
  libfsapfs_btree_entry_t *btree_entry           = NULL;
3547
1.04k
  static char *function                          = "libfsapfs_file_system_btree_get_attributes_from_leaf_node";
3548
1.04k
  uint64_t file_system_identifier                = 0;
3549
1.04k
  uint64_t lookup_identifier                     = 0;
3550
1.04k
  int btree_entry_index                          = 0;
3551
1.04k
  int entry_index                                = 0;
3552
1.04k
  int found_attribute                            = 0;
3553
1.04k
  int is_leaf_node                               = 0;
3554
1.04k
  int number_of_entries                          = 0;
3555
3556
#if defined( HAVE_DEBUG_OUTPUT )
3557
  uint8_t file_system_data_type                  = 0;
3558
#endif
3559
3560
1.04k
  if( file_system_btree == NULL )
3561
0
  {
3562
0
    libcerror_error_set(
3563
0
     error,
3564
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3565
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3566
0
     "%s: invalid file system B-tree.",
3567
0
     function );
3568
3569
0
    return( -1 );
3570
0
  }
3571
1.04k
  if( node == NULL )
3572
0
  {
3573
0
    libcerror_error_set(
3574
0
     error,
3575
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3576
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3577
0
     "%s: invalid node.",
3578
0
     function );
3579
3580
0
    return( -1 );
3581
0
  }
3582
1.04k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3583
1.04k
                  node,
3584
1.04k
                  error );
3585
3586
1.04k
  if( is_leaf_node == -1 )
3587
0
  {
3588
0
    libcerror_error_set(
3589
0
     error,
3590
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3591
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3592
0
     "%s: unable to determine if B-tree node is a leaf node.",
3593
0
     function );
3594
3595
0
    goto on_error;
3596
0
  }
3597
1.04k
  else if( is_leaf_node == 0 )
3598
0
  {
3599
0
    libcerror_error_set(
3600
0
     error,
3601
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3602
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3603
0
     "%s: invalid node - not a leaf node.",
3604
0
     function );
3605
3606
0
    goto on_error;
3607
0
  }
3608
#if defined( HAVE_DEBUG_OUTPUT )
3609
  if( libcnotify_verbose != 0 )
3610
  {
3611
    libcnotify_printf(
3612
     "%s: retrieving extended attributes of: %" PRIu64 "\n",
3613
     function,
3614
     identifier );
3615
  }
3616
#endif
3617
1.04k
  if( libfsapfs_btree_node_get_number_of_entries(
3618
1.04k
       node,
3619
1.04k
       &number_of_entries,
3620
1.04k
       error ) != 1 )
3621
0
  {
3622
0
    libcerror_error_set(
3623
0
     error,
3624
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3625
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3626
0
     "%s: unable to retrieve number of entries from B-tree node.",
3627
0
     function );
3628
3629
0
    goto on_error;
3630
0
  }
3631
1.04k
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_EXTENDED_ATTRIBUTE << 60 ) | identifier;
3632
3633
1.04k
  for( btree_entry_index = 0;
3634
13.8k
       btree_entry_index < number_of_entries;
3635
12.7k
       btree_entry_index++ )
3636
13.6k
  {
3637
13.6k
    if( libfsapfs_btree_node_get_entry_by_index(
3638
13.6k
         node,
3639
13.6k
         btree_entry_index,
3640
13.6k
         &btree_entry,
3641
13.6k
         error ) != 1 )
3642
0
    {
3643
0
      libcerror_error_set(
3644
0
       error,
3645
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3646
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3647
0
       "%s: unable to retrieve number of entries from B-tree node.",
3648
0
       function );
3649
3650
0
      goto on_error;
3651
0
    }
3652
13.6k
    if( btree_entry == NULL )
3653
0
    {
3654
0
      libcerror_error_set(
3655
0
       error,
3656
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3657
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3658
0
       "%s: invalid B-tree entry: %d.",
3659
0
       function,
3660
0
       btree_entry_index );
3661
3662
0
      goto on_error;
3663
0
    }
3664
13.6k
    if( btree_entry->key_data == NULL )
3665
84
    {
3666
84
      libcerror_error_set(
3667
84
       error,
3668
84
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3669
84
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3670
84
       "%s: invalid B-tree entry: %d - missing key data.",
3671
84
       function,
3672
84
       btree_entry_index );
3673
3674
84
      goto on_error;
3675
84
    }
3676
13.5k
    if( btree_entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
3677
21
    {
3678
21
      libcerror_error_set(
3679
21
       error,
3680
21
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3681
21
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3682
21
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
3683
21
       function,
3684
21
       btree_entry_index );
3685
3686
21
      goto on_error;
3687
21
    }
3688
13.5k
    byte_stream_copy_to_uint64_little_endian(
3689
13.5k
     ( (fsapfs_file_system_btree_key_common_t *) btree_entry->key_data )->file_system_identifier,
3690
13.5k
     file_system_identifier );
3691
3692
#if defined( HAVE_DEBUG_OUTPUT )
3693
    if( libcnotify_verbose != 0 )
3694
    {
3695
      file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
3696
3697
      libcnotify_printf(
3698
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
3699
       function,
3700
       btree_entry_index,
3701
       file_system_identifier & 0x0fffffffffffffffUL,
3702
       file_system_data_type,
3703
       libfsapfs_debug_print_file_system_data_type(
3704
        file_system_data_type ) );
3705
    }
3706
#endif
3707
13.5k
    if( ( file_system_identifier & 0x0fffffffffffffffUL ) > identifier )
3708
579
    {
3709
579
      break;
3710
579
    }
3711
12.9k
    if( file_system_identifier != lookup_identifier )
3712
12.3k
    {
3713
12.3k
      continue;
3714
12.3k
    }
3715
614
    if( libfsapfs_attribute_values_initialize(
3716
614
         &attribute_values,
3717
614
         error ) != 1 )
3718
0
    {
3719
0
      libcerror_error_set(
3720
0
       error,
3721
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3722
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3723
0
       "%s: unable to create attribute values.",
3724
0
       function );
3725
3726
0
      goto on_error;
3727
0
    }
3728
614
    if( libfsapfs_attribute_values_read_key_data(
3729
614
         attribute_values,
3730
614
         btree_entry->key_data,
3731
614
         (size_t) btree_entry->key_data_size,
3732
614
         error ) != 1 )
3733
129
    {
3734
129
      libcerror_error_set(
3735
129
       error,
3736
129
       LIBCERROR_ERROR_DOMAIN_IO,
3737
129
       LIBCERROR_IO_ERROR_READ_FAILED,
3738
129
       "%s: unable to read attribute values key data.",
3739
129
       function );
3740
3741
129
      goto on_error;
3742
129
    }
3743
485
    if( libfsapfs_attribute_values_read_value_data(
3744
485
         attribute_values,
3745
485
         btree_entry->value_data,
3746
485
         (size_t) btree_entry->value_data_size,
3747
485
         error ) != 1 )
3748
102
    {
3749
102
      libcerror_error_set(
3750
102
       error,
3751
102
       LIBCERROR_ERROR_DOMAIN_IO,
3752
102
       LIBCERROR_IO_ERROR_READ_FAILED,
3753
102
       "%s: unable to read attribute values value data.",
3754
102
       function );
3755
3756
102
      goto on_error;
3757
102
    }
3758
383
    if( libcdata_array_append_entry(
3759
383
         extended_attributes_array,
3760
383
         &entry_index,
3761
383
         (intptr_t *) attribute_values,
3762
383
         error ) != 1 )
3763
0
    {
3764
0
      libcerror_error_set(
3765
0
       error,
3766
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3767
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
3768
0
       "%s: unable to append attribute values to extended attributes array.",
3769
0
       function );
3770
3771
0
      goto on_error;
3772
0
    }
3773
383
    attribute_values = NULL;
3774
3775
383
    found_attribute = 1;
3776
383
  }
3777
707
  return( found_attribute );
3778
3779
336
on_error:
3780
336
  if( attribute_values != NULL )
3781
231
  {
3782
231
    libfsapfs_attribute_values_free(
3783
231
     &attribute_values,
3784
231
     NULL );
3785
231
  }
3786
336
  libcdata_array_empty(
3787
336
   extended_attributes_array,
3788
336
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_attribute_values_free,
3789
336
   NULL );
3790
3791
336
  return( -1 );
3792
1.04k
}
3793
3794
/* Retrieves attributes for a specific identifier from the file system B-tree branch node
3795
 * Returns 1 if successful, 0 if not found or -1 on error
3796
 */
3797
int libfsapfs_file_system_btree_get_attributes_from_branch_node(
3798
     libfsapfs_file_system_btree_t *file_system_btree,
3799
     libbfio_handle_t *file_io_handle,
3800
     libfsapfs_btree_node_t *node,
3801
     uint64_t identifier,
3802
     uint64_t transaction_identifier,
3803
     libcdata_array_t *extended_attributes_array,
3804
     int recursion_depth,
3805
     libcerror_error_t **error )
3806
0
{
3807
0
  libfsapfs_btree_entry_t *entry          = NULL;
3808
0
  libfsapfs_btree_entry_t *previous_entry = NULL;
3809
0
  libfsapfs_btree_node_t *sub_node        = NULL;
3810
0
  static char *function                   = "libfsapfs_file_system_btree_get_attributes_from_branch_node";
3811
0
  uint64_t file_system_identifier         = 0;
3812
0
  uint64_t sub_node_block_number          = 0;
3813
0
  uint8_t file_system_data_type           = 0;
3814
0
  int entry_index                         = 0;
3815
0
  int found_attribute                     = 0;
3816
0
  int is_leaf_node                        = 0;
3817
0
  int number_of_entries                   = 0;
3818
0
  int result                              = 0;
3819
3820
0
  if( file_system_btree == NULL )
3821
0
  {
3822
0
    libcerror_error_set(
3823
0
     error,
3824
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3825
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3826
0
     "%s: invalid file system B-tree.",
3827
0
     function );
3828
3829
0
    return( -1 );
3830
0
  }
3831
0
  if( node == NULL )
3832
0
  {
3833
0
    libcerror_error_set(
3834
0
     error,
3835
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3836
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3837
0
     "%s: invalid node.",
3838
0
     function );
3839
3840
0
    return( -1 );
3841
0
  }
3842
0
  if( ( recursion_depth < 0 )
3843
0
   || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
3844
0
  {
3845
0
    libcerror_error_set(
3846
0
     error,
3847
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3848
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3849
0
     "%s: invalid recursion depth value out of bounds.",
3850
0
     function );
3851
3852
0
    return( -1 );
3853
0
  }
3854
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3855
0
                  node,
3856
0
                  error );
3857
3858
0
  if( is_leaf_node == -1 )
3859
0
  {
3860
0
    libcerror_error_set(
3861
0
     error,
3862
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3863
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3864
0
     "%s: unable to determine if B-tree node is a leaf node.",
3865
0
     function );
3866
3867
0
    goto on_error;
3868
0
  }
3869
0
  else if( is_leaf_node != 0 )
3870
0
  {
3871
0
    libcerror_error_set(
3872
0
     error,
3873
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3874
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3875
0
     "%s: invalid node - not a branch node.",
3876
0
     function );
3877
3878
0
    goto on_error;
3879
0
  }
3880
#if defined( HAVE_DEBUG_OUTPUT )
3881
  if( libcnotify_verbose != 0 )
3882
  {
3883
    libcnotify_printf(
3884
     "%s: retrieving attributes of: %" PRIu64 " (transaction: %" PRIu64 ")\n",
3885
     function,
3886
     identifier,
3887
     transaction_identifier );
3888
  }
3889
#endif
3890
0
  if( libfsapfs_btree_node_get_number_of_entries(
3891
0
       node,
3892
0
       &number_of_entries,
3893
0
       error ) != 1 )
3894
0
  {
3895
0
    libcerror_error_set(
3896
0
     error,
3897
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3898
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3899
0
     "%s: unable to retrieve number of entries from B-tree node.",
3900
0
     function );
3901
3902
0
    goto on_error;
3903
0
  }
3904
0
  for( entry_index = 0;
3905
0
       entry_index < number_of_entries;
3906
0
       entry_index++ )
3907
0
  {
3908
0
    if( libfsapfs_btree_node_get_entry_by_index(
3909
0
         node,
3910
0
         entry_index,
3911
0
         &entry,
3912
0
         error ) != 1 )
3913
0
    {
3914
0
      libcerror_error_set(
3915
0
       error,
3916
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3917
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3918
0
       "%s: unable to retrieve number of entries from B-tree node.",
3919
0
       function );
3920
3921
0
      goto on_error;
3922
0
    }
3923
0
    if( entry == NULL )
3924
0
    {
3925
0
      libcerror_error_set(
3926
0
       error,
3927
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3928
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3929
0
       "%s: invalid B-tree entry: %d.",
3930
0
       function,
3931
0
       entry_index );
3932
3933
0
      goto on_error;
3934
0
    }
3935
0
    if( entry->key_data == NULL )
3936
0
    {
3937
0
      libcerror_error_set(
3938
0
       error,
3939
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3940
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3941
0
       "%s: invalid B-tree entry: %d - missing key data.",
3942
0
       function,
3943
0
       entry_index );
3944
3945
0
      goto on_error;
3946
0
    }
3947
0
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
3948
0
    {
3949
0
      libcerror_error_set(
3950
0
       error,
3951
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3952
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3953
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
3954
0
       function,
3955
0
       entry_index );
3956
3957
0
      goto on_error;
3958
0
    }
3959
0
    byte_stream_copy_to_uint64_little_endian(
3960
0
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
3961
0
     file_system_identifier );
3962
3963
0
    file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
3964
3965
#if defined( HAVE_DEBUG_OUTPUT )
3966
    if( libcnotify_verbose != 0 )
3967
    {
3968
      libcnotify_printf(
3969
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
3970
       function,
3971
       entry_index,
3972
       file_system_identifier & 0x0fffffffffffffffUL,
3973
       file_system_data_type,
3974
       libfsapfs_debug_print_file_system_data_type(
3975
        file_system_data_type ) );
3976
    }
3977
#endif
3978
0
    file_system_identifier &= 0x0fffffffffffffffUL;
3979
3980
0
    if( ( file_system_identifier > identifier )
3981
0
     || ( ( file_system_identifier == identifier )
3982
0
      &&  ( file_system_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_EXTENDED_ATTRIBUTE ) ) )
3983
0
    {
3984
0
      break;
3985
0
    }
3986
0
    if( ( file_system_identifier == identifier )
3987
0
     && ( file_system_data_type == LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_EXTENDED_ATTRIBUTE )
3988
0
     && ( previous_entry != NULL ) )
3989
0
    {
3990
0
      if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
3991
0
           file_system_btree,
3992
0
           file_io_handle,
3993
0
           previous_entry,
3994
0
           transaction_identifier,
3995
0
           &sub_node_block_number,
3996
0
           error ) != 1 )
3997
0
      {
3998
0
        libcerror_error_set(
3999
0
         error,
4000
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4001
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4002
0
         "%s: unable to determine sub node block number.",
4003
0
         function );
4004
4005
0
        goto on_error;
4006
0
      }
4007
0
      if( libfsapfs_file_system_btree_get_sub_node(
4008
0
           file_system_btree,
4009
0
           file_io_handle,
4010
0
           sub_node_block_number,
4011
0
           &sub_node,
4012
0
           error ) != 1 )
4013
0
      {
4014
0
        libcerror_error_set(
4015
0
         error,
4016
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4017
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4018
0
         "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
4019
0
         function,
4020
0
         sub_node_block_number );
4021
4022
0
        goto on_error;
4023
0
      }
4024
0
      is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4025
0
                      sub_node,
4026
0
                      error );
4027
4028
0
      if( is_leaf_node == -1 )
4029
0
      {
4030
0
        libcerror_error_set(
4031
0
         error,
4032
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4033
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4034
0
         "%s: unable to determine if B-tree sub node is a leaf node.",
4035
0
         function );
4036
4037
0
        goto on_error;
4038
0
      }
4039
0
      if( is_leaf_node != 0 )
4040
0
      {
4041
0
        result = libfsapfs_file_system_btree_get_attributes_from_leaf_node(
4042
0
                  file_system_btree,
4043
0
                  sub_node,
4044
0
                  identifier,
4045
0
                  extended_attributes_array,
4046
0
                  error );
4047
0
      }
4048
0
      else
4049
0
      {
4050
0
        result = libfsapfs_file_system_btree_get_attributes_from_branch_node(
4051
0
                  file_system_btree,
4052
0
                  file_io_handle,
4053
0
                  sub_node,
4054
0
                  identifier,
4055
0
                  transaction_identifier,
4056
0
                  extended_attributes_array,
4057
0
                  recursion_depth + 1,
4058
0
                  error );
4059
0
      }
4060
0
      if( result == -1 )
4061
0
      {
4062
0
        libcerror_error_set(
4063
0
         error,
4064
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4065
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4066
0
         "%s: unable to retrieve attributes: %" PRIu64 " from file system B-tree sub node.",
4067
0
         function,
4068
0
         identifier );
4069
4070
0
        goto on_error;
4071
0
      }
4072
0
      else if( result != 0 )
4073
0
      {
4074
0
        found_attribute = 1;
4075
0
      }
4076
0
      sub_node = NULL;
4077
0
    }
4078
0
    previous_entry = entry;
4079
0
  }
4080
0
  if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
4081
0
       file_system_btree,
4082
0
       file_io_handle,
4083
0
       previous_entry,
4084
0
       transaction_identifier,
4085
0
       &sub_node_block_number,
4086
0
       error ) != 1 )
4087
0
  {
4088
0
    libcerror_error_set(
4089
0
     error,
4090
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4091
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4092
0
     "%s: unable to determine sub node block number.",
4093
0
     function );
4094
4095
0
    goto on_error;
4096
0
  }
4097
0
  if( libfsapfs_file_system_btree_get_sub_node(
4098
0
       file_system_btree,
4099
0
       file_io_handle,
4100
0
       sub_node_block_number,
4101
0
       &sub_node,
4102
0
       error ) != 1 )
4103
0
  {
4104
0
    libcerror_error_set(
4105
0
     error,
4106
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4107
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4108
0
     "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
4109
0
     function,
4110
0
     sub_node_block_number );
4111
4112
0
    goto on_error;
4113
0
  }
4114
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4115
0
                  sub_node,
4116
0
                  error );
4117
4118
0
  if( is_leaf_node == -1 )
4119
0
  {
4120
0
    libcerror_error_set(
4121
0
     error,
4122
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4123
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4124
0
     "%s: unable to determine if B-tree sub node is a leaf node.",
4125
0
     function );
4126
4127
0
    goto on_error;
4128
0
  }
4129
0
  if( is_leaf_node != 0 )
4130
0
  {
4131
0
    result = libfsapfs_file_system_btree_get_attributes_from_leaf_node(
4132
0
              file_system_btree,
4133
0
              sub_node,
4134
0
              identifier,
4135
0
              extended_attributes_array,
4136
0
              error );
4137
0
  }
4138
0
  else
4139
0
  {
4140
0
    result = libfsapfs_file_system_btree_get_attributes_from_branch_node(
4141
0
              file_system_btree,
4142
0
              file_io_handle,
4143
0
              sub_node,
4144
0
              identifier,
4145
0
              transaction_identifier,
4146
0
              extended_attributes_array,
4147
0
              recursion_depth + 1,
4148
0
              error );
4149
0
  }
4150
0
  if( result == -1 )
4151
0
  {
4152
0
    libcerror_error_set(
4153
0
     error,
4154
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4155
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4156
0
     "%s: unable to retrieve attributes: %" PRIu64 " from file system B-tree sub node.",
4157
0
     function,
4158
0
     identifier );
4159
4160
0
    goto on_error;
4161
0
  }
4162
0
  else if( result != 0 )
4163
0
  {
4164
0
    found_attribute = 1;
4165
0
  }
4166
0
  return( found_attribute );
4167
4168
0
on_error:
4169
0
  libcdata_array_empty(
4170
0
   extended_attributes_array,
4171
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_attribute_values_free,
4172
0
   NULL );
4173
4174
0
  return( -1 );
4175
0
}
4176
4177
/* Retrieves attributes for a specific identifier from the file system B-tree
4178
 * Returns 1 if successful, 0 if not found or -1 on error
4179
 */
4180
int libfsapfs_file_system_btree_get_attributes(
4181
     libfsapfs_file_system_btree_t *file_system_btree,
4182
     libbfio_handle_t *file_io_handle,
4183
     uint64_t identifier,
4184
     uint64_t transaction_identifier,
4185
     libcdata_array_t *extended_attributes_array,
4186
     libcerror_error_t **error )
4187
1.04k
{
4188
1.04k
  libfsapfs_btree_node_t *root_node = NULL;
4189
1.04k
  static char *function             = "libfsapfs_file_system_btree_get_attributes";
4190
1.04k
  int is_leaf_node                  = 0;
4191
1.04k
  int result                        = 0;
4192
4193
#if defined( HAVE_PROFILER )
4194
  int64_t profiler_start_timestamp  = 0;
4195
#endif
4196
4197
1.04k
  if( file_system_btree == NULL )
4198
0
  {
4199
0
    libcerror_error_set(
4200
0
     error,
4201
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4202
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4203
0
     "%s: invalid file system B-tree.",
4204
0
     function );
4205
4206
0
    return( -1 );
4207
0
  }
4208
#if defined( HAVE_PROFILER )
4209
  if( file_system_btree->io_handle->profiler != NULL )
4210
  {
4211
    if( libfsapfs_profiler_start_timing(
4212
         file_system_btree->io_handle->profiler,
4213
         &profiler_start_timestamp,
4214
         error ) != 1 )
4215
    {
4216
      libcerror_error_set(
4217
       error,
4218
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4219
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4220
       "%s: unable to start timing.",
4221
       function );
4222
4223
      goto on_error;
4224
    }
4225
  }
4226
#endif /* defined( HAVE_PROFILER ) */
4227
4228
#if defined( HAVE_DEBUG_OUTPUT )
4229
  if( libcnotify_verbose != 0 )
4230
  {
4231
    libcnotify_printf(
4232
     "%s: retrieving attributes of: %" PRIu64 " (transaction: %" PRIu64 ")\n",
4233
     function,
4234
     identifier,
4235
     transaction_identifier );
4236
  }
4237
#endif
4238
1.04k
  result = libfsapfs_file_system_btree_get_root_node(
4239
1.04k
            file_system_btree,
4240
1.04k
            file_io_handle,
4241
1.04k
            file_system_btree->root_node_block_number,
4242
1.04k
            &root_node,
4243
1.04k
            error );
4244
4245
1.04k
  if( result == -1 )
4246
0
  {
4247
0
    libcerror_error_set(
4248
0
     error,
4249
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4250
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4251
0
     "%s: unable to retrieve B-tree root node.",
4252
0
     function );
4253
4254
0
    goto on_error;
4255
0
  }
4256
1.04k
  else if( result == 0 )
4257
0
  {
4258
0
    return( 0 );
4259
0
  }
4260
1.04k
  if( root_node == NULL )
4261
0
  {
4262
0
    libcerror_error_set(
4263
0
     error,
4264
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4265
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4266
0
     "%s: invalid B-tree root node.",
4267
0
     function );
4268
4269
0
    goto on_error;
4270
0
  }
4271
1.04k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4272
1.04k
                  root_node,
4273
1.04k
                  error );
4274
4275
1.04k
  if( is_leaf_node == -1 )
4276
0
  {
4277
0
    libcerror_error_set(
4278
0
     error,
4279
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4280
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4281
0
     "%s: unable to determine if B-tree root node is a leaf node.",
4282
0
     function );
4283
4284
0
    goto on_error;
4285
0
  }
4286
1.04k
  if( is_leaf_node != 0 )
4287
1.04k
  {
4288
1.04k
    result = libfsapfs_file_system_btree_get_attributes_from_leaf_node(
4289
1.04k
              file_system_btree,
4290
1.04k
              root_node,
4291
1.04k
              identifier,
4292
1.04k
              extended_attributes_array,
4293
1.04k
              error );
4294
1.04k
  }
4295
0
  else
4296
0
  {
4297
0
    result = libfsapfs_file_system_btree_get_attributes_from_branch_node(
4298
0
              file_system_btree,
4299
0
              file_io_handle,
4300
0
              root_node,
4301
0
              identifier,
4302
0
              transaction_identifier,
4303
0
              extended_attributes_array,
4304
0
              0,
4305
0
              error );
4306
0
  }
4307
1.04k
  if( result == -1 )
4308
336
  {
4309
336
    libcerror_error_set(
4310
336
     error,
4311
336
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4312
336
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4313
336
     "%s: unable to retrieve attributes: %" PRIu64 " from file system B-tree root node.",
4314
336
     function,
4315
336
     identifier );
4316
4317
336
    goto on_error;
4318
336
  }
4319
#if defined( HAVE_PROFILER )
4320
  if( file_system_btree->io_handle->profiler != NULL )
4321
  {
4322
    if( libfsapfs_profiler_stop_timing(
4323
         file_system_btree->io_handle->profiler,
4324
         profiler_start_timestamp,
4325
         function,
4326
         0,
4327
         0,
4328
         error ) != 1 )
4329
    {
4330
      libcerror_error_set(
4331
       error,
4332
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4333
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4334
       "%s: unable to stop timing.",
4335
       function );
4336
4337
      goto on_error;
4338
    }
4339
  }
4340
#endif /* defined( HAVE_PROFILER ) */
4341
4342
707
  return( result );
4343
4344
336
on_error:
4345
336
  libcdata_array_empty(
4346
336
   extended_attributes_array,
4347
336
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_attribute_values_free,
4348
336
   NULL );
4349
4350
336
  return( -1 );
4351
1.04k
}
4352
4353
/* Retrieves file extents for a specific identifier from the file system B-tree leaf node
4354
 * Returns 1 if successful, 0 if not found or -1 on error
4355
 */
4356
int libfsapfs_file_system_btree_get_file_extents_from_leaf_node(
4357
     libfsapfs_file_system_btree_t *file_system_btree,
4358
     libfsapfs_btree_node_t *node,
4359
     uint64_t identifier,
4360
     libcdata_array_t *file_extents,
4361
     libcerror_error_t **error )
4362
606
{
4363
606
  libfsapfs_btree_entry_t *btree_entry = NULL;
4364
606
  libfsapfs_file_extent_t *file_extent = NULL;
4365
606
  static char *function                = "libfsapfs_file_system_btree_get_file_extents_from_leaf_node";
4366
606
  uint64_t file_system_identifier      = 0;
4367
606
  uint64_t lookup_identifier           = 0;
4368
606
  int btree_entry_index                = 0;
4369
606
  int entry_index                      = 0;
4370
606
  int found_file_extent                = 0;
4371
606
  int is_leaf_node                     = 0;
4372
606
  int number_of_entries                = 0;
4373
4374
#if defined( HAVE_DEBUG_OUTPUT )
4375
  uint8_t file_system_data_type        = 0;
4376
#endif
4377
4378
606
  if( file_system_btree == NULL )
4379
0
  {
4380
0
    libcerror_error_set(
4381
0
     error,
4382
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4383
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4384
0
     "%s: invalid file system B-tree.",
4385
0
     function );
4386
4387
0
    return( -1 );
4388
0
  }
4389
606
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4390
606
                  node,
4391
606
                  error );
4392
4393
606
  if( is_leaf_node == -1 )
4394
0
  {
4395
0
    libcerror_error_set(
4396
0
     error,
4397
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4398
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4399
0
     "%s: unable to determine if B-tree node is a leaf node.",
4400
0
     function );
4401
4402
0
    goto on_error;
4403
0
  }
4404
606
  else if( is_leaf_node == 0 )
4405
0
  {
4406
0
    libcerror_error_set(
4407
0
     error,
4408
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4409
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4410
0
     "%s: invalid node - not a leaf node.",
4411
0
     function );
4412
4413
0
    goto on_error;
4414
0
  }
4415
#if defined( HAVE_DEBUG_OUTPUT )
4416
  if( libcnotify_verbose != 0 )
4417
  {
4418
    libcnotify_printf(
4419
     "%s: retrieving file extents of: %" PRIu64 "\n",
4420
     function,
4421
     identifier );
4422
  }
4423
#endif
4424
606
  if( libfsapfs_btree_node_get_number_of_entries(
4425
606
       node,
4426
606
       &number_of_entries,
4427
606
       error ) != 1 )
4428
0
  {
4429
0
    libcerror_error_set(
4430
0
     error,
4431
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4432
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4433
0
     "%s: unable to retrieve number of entries from B-tree node.",
4434
0
     function );
4435
4436
0
    goto on_error;
4437
0
  }
4438
606
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_FILE_EXTENT << 60 ) | identifier;
4439
4440
606
  for( btree_entry_index = 0;
4441
13.6k
       btree_entry_index < number_of_entries;
4442
13.0k
       btree_entry_index++ )
4443
13.3k
  {
4444
13.3k
    if( libfsapfs_btree_node_get_entry_by_index(
4445
13.3k
         node,
4446
13.3k
         btree_entry_index,
4447
13.3k
         &btree_entry,
4448
13.3k
         error ) != 1 )
4449
0
    {
4450
0
      libcerror_error_set(
4451
0
       error,
4452
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4453
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4454
0
       "%s: unable to retrieve number of entries from B-tree node.",
4455
0
       function );
4456
4457
0
      goto on_error;
4458
0
    }
4459
13.3k
    if( btree_entry == NULL )
4460
0
    {
4461
0
      libcerror_error_set(
4462
0
       error,
4463
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4464
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4465
0
       "%s: invalid B-tree entry: %d.",
4466
0
       function,
4467
0
       btree_entry_index );
4468
4469
0
      goto on_error;
4470
0
    }
4471
13.3k
    if( btree_entry->key_data == NULL )
4472
30
    {
4473
30
      libcerror_error_set(
4474
30
       error,
4475
30
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4476
30
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4477
30
       "%s: invalid B-tree entry: %d - missing key data.",
4478
30
       function,
4479
30
       btree_entry_index );
4480
4481
30
      goto on_error;
4482
30
    }
4483
13.3k
    if( btree_entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
4484
15
    {
4485
15
      libcerror_error_set(
4486
15
       error,
4487
15
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4488
15
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
4489
15
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
4490
15
       function,
4491
15
       btree_entry_index );
4492
4493
15
      goto on_error;
4494
15
    }
4495
13.3k
    byte_stream_copy_to_uint64_little_endian(
4496
13.3k
     ( (fsapfs_file_system_btree_key_common_t *) btree_entry->key_data )->file_system_identifier,
4497
13.3k
     file_system_identifier );
4498
4499
#if defined( HAVE_DEBUG_OUTPUT )
4500
    if( libcnotify_verbose != 0 )
4501
    {
4502
      file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
4503
4504
      libcnotify_printf(
4505
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
4506
       function,
4507
       btree_entry_index,
4508
       file_system_identifier & 0x0fffffffffffffffUL,
4509
       file_system_data_type,
4510
       libfsapfs_debug_print_file_system_data_type(
4511
        file_system_data_type ) );
4512
    }
4513
#endif
4514
13.3k
    if( ( file_system_identifier & 0x0fffffffffffffffUL ) > identifier )
4515
160
    {
4516
160
      break;
4517
160
    }
4518
13.1k
    if( file_system_identifier != lookup_identifier )
4519
12.4k
    {
4520
12.4k
      continue;
4521
12.4k
    }
4522
675
    if( libfsapfs_file_extent_initialize(
4523
675
         &file_extent,
4524
675
         error ) != 1 )
4525
0
    {
4526
0
      libcerror_error_set(
4527
0
       error,
4528
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4529
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4530
0
       "%s: unable to create file extent.",
4531
0
       function );
4532
4533
0
      goto on_error;
4534
0
    }
4535
675
    if( libfsapfs_file_extent_read_key_data(
4536
675
         file_extent,
4537
675
         btree_entry->key_data,
4538
675
         (size_t) btree_entry->key_data_size,
4539
675
         error ) != 1 )
4540
28
    {
4541
28
      libcerror_error_set(
4542
28
       error,
4543
28
       LIBCERROR_ERROR_DOMAIN_IO,
4544
28
       LIBCERROR_IO_ERROR_READ_FAILED,
4545
28
       "%s: unable to read file extent key data.",
4546
28
       function );
4547
4548
28
      goto on_error;
4549
28
    }
4550
647
    if( libfsapfs_file_extent_read_value_data(
4551
647
         file_extent,
4552
647
         btree_entry->value_data,
4553
647
         (size_t) btree_entry->value_data_size,
4554
647
         error ) != 1 )
4555
51
    {
4556
51
      libcerror_error_set(
4557
51
       error,
4558
51
       LIBCERROR_ERROR_DOMAIN_IO,
4559
51
       LIBCERROR_IO_ERROR_READ_FAILED,
4560
51
       "%s: unable to read file extent value data.",
4561
51
       function );
4562
4563
51
      goto on_error;
4564
51
    }
4565
596
    if( libcdata_array_append_entry(
4566
596
         file_extents,
4567
596
         &entry_index,
4568
596
         (intptr_t *) file_extent,
4569
596
         error ) != 1 )
4570
0
    {
4571
0
      libcerror_error_set(
4572
0
       error,
4573
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4574
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
4575
0
       "%s: unable to append file extent to array.",
4576
0
       function );
4577
4578
0
      goto on_error;
4579
0
    }
4580
596
    file_extent = NULL;
4581
4582
596
    found_file_extent = 1;
4583
596
  }
4584
482
  return( found_file_extent );
4585
4586
124
on_error:
4587
124
  if( file_extent != NULL )
4588
79
  {
4589
79
    libfsapfs_file_extent_free(
4590
79
     &file_extent,
4591
79
     NULL );
4592
79
  }
4593
124
  libcdata_array_empty(
4594
124
   file_extents,
4595
124
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
4596
124
   NULL );
4597
4598
124
  return( -1 );
4599
606
}
4600
4601
/* Retrieves file extents for a specific identifier from the file system B-tree branch node
4602
 * Returns 1 if successful, 0 if not found or -1 on error
4603
 */
4604
int libfsapfs_file_system_btree_get_file_extents_from_branch_node(
4605
     libfsapfs_file_system_btree_t *file_system_btree,
4606
     libbfio_handle_t *file_io_handle,
4607
     libfsapfs_btree_node_t *node,
4608
     uint64_t identifier,
4609
     uint64_t transaction_identifier,
4610
     libcdata_array_t *file_extents,
4611
     int recursion_depth,
4612
     libcerror_error_t **error )
4613
0
{
4614
0
  libfsapfs_btree_entry_t *entry          = NULL;
4615
0
  libfsapfs_btree_entry_t *previous_entry = NULL;
4616
0
  libfsapfs_btree_node_t *sub_node        = NULL;
4617
0
  static char *function                   = "libfsapfs_file_system_btree_get_file_extents_from_branch_node";
4618
0
  uint64_t file_extent_logical_address    = 0;
4619
0
  uint64_t file_system_identifier         = 0;
4620
0
  uint64_t sub_node_block_number          = 0;
4621
0
  uint8_t file_system_data_type           = 0;
4622
0
  int entry_index                         = 0;
4623
0
  int found_file_extent                   = 0;
4624
0
  int is_leaf_node                        = 0;
4625
0
  int number_of_entries                   = 0;
4626
0
  int result                              = 0;
4627
4628
0
  if( file_system_btree == NULL )
4629
0
  {
4630
0
    libcerror_error_set(
4631
0
     error,
4632
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4633
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4634
0
     "%s: invalid file system B-tree.",
4635
0
     function );
4636
4637
0
    return( -1 );
4638
0
  }
4639
0
  if( node == NULL )
4640
0
  {
4641
0
    libcerror_error_set(
4642
0
     error,
4643
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4644
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4645
0
     "%s: invalid node.",
4646
0
     function );
4647
4648
0
    return( -1 );
4649
0
  }
4650
0
  if( ( recursion_depth < 0 )
4651
0
   || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
4652
0
  {
4653
0
    libcerror_error_set(
4654
0
     error,
4655
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4656
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
4657
0
     "%s: invalid recursion depth value out of bounds.",
4658
0
     function );
4659
4660
0
    return( -1 );
4661
0
  }
4662
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4663
0
                  node,
4664
0
                  error );
4665
4666
0
  if( is_leaf_node == -1 )
4667
0
  {
4668
0
    libcerror_error_set(
4669
0
     error,
4670
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4671
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4672
0
     "%s: unable to determine if B-tree node is a leaf node.",
4673
0
     function );
4674
4675
0
    goto on_error;
4676
0
  }
4677
0
  else if( is_leaf_node != 0 )
4678
0
  {
4679
0
    libcerror_error_set(
4680
0
     error,
4681
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4682
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4683
0
     "%s: invalid node - not a branch node.",
4684
0
     function );
4685
4686
0
    goto on_error;
4687
0
  }
4688
#if defined( HAVE_DEBUG_OUTPUT )
4689
  if( libcnotify_verbose != 0 )
4690
  {
4691
    libcnotify_printf(
4692
     "%s: retrieving file extents of: %" PRIu64 " (transaction: %" PRIu64 ")\n",
4693
     function,
4694
     identifier,
4695
     transaction_identifier );
4696
  }
4697
#endif
4698
0
  if( libfsapfs_btree_node_get_number_of_entries(
4699
0
       node,
4700
0
       &number_of_entries,
4701
0
       error ) != 1 )
4702
0
  {
4703
0
    libcerror_error_set(
4704
0
     error,
4705
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4706
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4707
0
     "%s: unable to retrieve number of entries from B-tree node.",
4708
0
     function );
4709
4710
0
    goto on_error;
4711
0
  }
4712
0
  for( entry_index = 0;
4713
0
       entry_index < number_of_entries;
4714
0
       entry_index++ )
4715
0
  {
4716
0
    if( libfsapfs_btree_node_get_entry_by_index(
4717
0
         node,
4718
0
         entry_index,
4719
0
         &entry,
4720
0
         error ) != 1 )
4721
0
    {
4722
0
      libcerror_error_set(
4723
0
       error,
4724
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4725
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4726
0
       "%s: unable to retrieve number of entries from B-tree node.",
4727
0
       function );
4728
4729
0
      goto on_error;
4730
0
    }
4731
0
    if( entry == NULL )
4732
0
    {
4733
0
      libcerror_error_set(
4734
0
       error,
4735
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4736
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4737
0
       "%s: invalid B-tree entry: %d.",
4738
0
       function,
4739
0
       entry_index );
4740
4741
0
      goto on_error;
4742
0
    }
4743
0
    if( entry->key_data == NULL )
4744
0
    {
4745
0
      libcerror_error_set(
4746
0
       error,
4747
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4748
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4749
0
       "%s: invalid B-tree entry: %d - missing key data.",
4750
0
       function,
4751
0
       entry_index );
4752
4753
0
      goto on_error;
4754
0
    }
4755
0
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
4756
0
    {
4757
0
      libcerror_error_set(
4758
0
       error,
4759
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4760
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
4761
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
4762
0
       function,
4763
0
       entry_index );
4764
4765
0
      goto on_error;
4766
0
    }
4767
0
    byte_stream_copy_to_uint64_little_endian(
4768
0
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
4769
0
     file_system_identifier );
4770
4771
0
    file_system_data_type = (uint8_t) ( file_system_identifier >> 60 );
4772
4773
#if defined( HAVE_DEBUG_OUTPUT )
4774
    if( libcnotify_verbose != 0 )
4775
    {
4776
      libcnotify_printf(
4777
       "%s: B-tree entry: %d, identifier: %" PRIu64 ", data type: 0x%" PRIx8 " %s\n",
4778
       function,
4779
       entry_index,
4780
       file_system_identifier & 0x0fffffffffffffffUL,
4781
       file_system_data_type,
4782
       libfsapfs_debug_print_file_system_data_type(
4783
        file_system_data_type ) );
4784
    }
4785
#endif
4786
0
    file_system_identifier &= 0x0fffffffffffffffUL;
4787
4788
0
    if( ( file_system_identifier > identifier )
4789
0
     || ( ( file_system_identifier == identifier )
4790
0
      &&  ( file_system_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_FILE_EXTENT ) ) )
4791
0
    {
4792
0
      break;
4793
0
    }
4794
0
    if( ( file_system_identifier == identifier )
4795
0
     && ( file_system_data_type == LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_FILE_EXTENT ) )
4796
0
    {
4797
0
      if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_file_extent_t ) )
4798
0
      {
4799
0
        libcerror_error_set(
4800
0
         error,
4801
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4802
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
4803
0
         "%s: invalid B-tree entry: %d - key data size value out of bounds.",
4804
0
         function,
4805
0
         entry_index );
4806
4807
0
        goto on_error;
4808
0
      }
4809
0
      byte_stream_copy_to_uint64_little_endian(
4810
0
       ( (fsapfs_file_system_btree_key_file_extent_t *) entry->key_data )->logical_address,
4811
0
       file_extent_logical_address );
4812
0
    }
4813
0
    else
4814
0
    {
4815
0
      file_extent_logical_address = 0;
4816
0
    }
4817
0
    if( ( file_system_identifier == identifier )
4818
0
     && ( file_system_data_type == LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_FILE_EXTENT )
4819
0
     && ( file_extent_logical_address > 0 )
4820
0
     && ( previous_entry != NULL ) )
4821
0
    {
4822
0
      if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
4823
0
           file_system_btree,
4824
0
           file_io_handle,
4825
0
           previous_entry,
4826
0
           transaction_identifier,
4827
0
           &sub_node_block_number,
4828
0
           error ) != 1 )
4829
0
      {
4830
0
        libcerror_error_set(
4831
0
         error,
4832
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4833
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4834
0
         "%s: unable to determine sub node block number.",
4835
0
         function );
4836
4837
0
        goto on_error;
4838
0
      }
4839
0
      if( libfsapfs_file_system_btree_get_sub_node(
4840
0
           file_system_btree,
4841
0
           file_io_handle,
4842
0
           sub_node_block_number,
4843
0
           &sub_node,
4844
0
           error ) != 1 )
4845
0
      {
4846
0
        libcerror_error_set(
4847
0
         error,
4848
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4849
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4850
0
         "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
4851
0
         function,
4852
0
         sub_node_block_number );
4853
4854
0
        goto on_error;
4855
0
      }
4856
0
      is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4857
0
                      sub_node,
4858
0
                      error );
4859
4860
0
      if( is_leaf_node == -1 )
4861
0
      {
4862
0
        libcerror_error_set(
4863
0
         error,
4864
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4865
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4866
0
         "%s: unable to determine if B-tree sub node is a leaf node.",
4867
0
         function );
4868
4869
0
        goto on_error;
4870
0
      }
4871
0
      if( is_leaf_node != 0 )
4872
0
      {
4873
0
        result = libfsapfs_file_system_btree_get_file_extents_from_leaf_node(
4874
0
                  file_system_btree,
4875
0
                  sub_node,
4876
0
                  identifier,
4877
0
                  file_extents,
4878
0
                  error );
4879
0
      }
4880
0
      else
4881
0
      {
4882
0
        result = libfsapfs_file_system_btree_get_file_extents_from_branch_node(
4883
0
                  file_system_btree,
4884
0
                  file_io_handle,
4885
0
                  sub_node,
4886
0
                  identifier,
4887
0
                  transaction_identifier,
4888
0
                  file_extents,
4889
0
                  recursion_depth + 1,
4890
0
                  error );
4891
0
      }
4892
0
      if( result == -1 )
4893
0
      {
4894
0
        libcerror_error_set(
4895
0
         error,
4896
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4897
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4898
0
         "%s: unable to retrieve file extents: %" PRIu64 " from file system B-tree sub node.",
4899
0
         function,
4900
0
         identifier );
4901
4902
0
        goto on_error;
4903
0
      }
4904
0
      else if( result != 0 )
4905
0
      {
4906
0
        found_file_extent = 1;
4907
0
      }
4908
0
      sub_node = NULL;
4909
0
    }
4910
0
    previous_entry = entry;
4911
0
  }
4912
  /* Fall-through for the last B-Tree entry
4913
   */
4914
0
  if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
4915
0
       file_system_btree,
4916
0
       file_io_handle,
4917
0
       previous_entry,
4918
0
       transaction_identifier,
4919
0
       &sub_node_block_number,
4920
0
       error ) != 1 )
4921
0
  {
4922
0
    libcerror_error_set(
4923
0
     error,
4924
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4925
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4926
0
     "%s: unable to determine sub node block number.",
4927
0
     function );
4928
4929
0
    goto on_error;
4930
0
  }
4931
0
  if( libfsapfs_file_system_btree_get_sub_node(
4932
0
       file_system_btree,
4933
0
       file_io_handle,
4934
0
       sub_node_block_number,
4935
0
       &sub_node,
4936
0
       error ) != 1 )
4937
0
  {
4938
0
    libcerror_error_set(
4939
0
     error,
4940
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4941
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4942
0
     "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
4943
0
     function,
4944
0
     sub_node_block_number );
4945
4946
0
    goto on_error;
4947
0
  }
4948
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4949
0
                  sub_node,
4950
0
                  error );
4951
4952
0
  if( is_leaf_node == -1 )
4953
0
  {
4954
0
    libcerror_error_set(
4955
0
     error,
4956
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4957
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4958
0
     "%s: unable to determine if B-tree sub node is a leaf node.",
4959
0
     function );
4960
4961
0
    goto on_error;
4962
0
  }
4963
0
  if( is_leaf_node != 0 )
4964
0
  {
4965
0
    result = libfsapfs_file_system_btree_get_file_extents_from_leaf_node(
4966
0
              file_system_btree,
4967
0
              sub_node,
4968
0
              identifier,
4969
0
              file_extents,
4970
0
              error );
4971
0
  }
4972
0
  else
4973
0
  {
4974
0
    result = libfsapfs_file_system_btree_get_file_extents_from_branch_node(
4975
0
              file_system_btree,
4976
0
              file_io_handle,
4977
0
              sub_node,
4978
0
              identifier,
4979
0
              transaction_identifier,
4980
0
              file_extents,
4981
0
              recursion_depth + 1,
4982
0
              error );
4983
0
  }
4984
0
  if( result == -1 )
4985
0
  {
4986
0
    libcerror_error_set(
4987
0
     error,
4988
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4989
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4990
0
     "%s: unable to retrieve file extents: %" PRIu64 " from file system B-tree sub node.",
4991
0
     function,
4992
0
     identifier );
4993
4994
0
    goto on_error;
4995
0
  }
4996
0
  else if( result != 0 )
4997
0
  {
4998
0
    found_file_extent = 1;
4999
0
  }
5000
0
  return( found_file_extent );
5001
5002
0
on_error:
5003
0
  libcdata_array_empty(
5004
0
   file_extents,
5005
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
5006
0
   NULL );
5007
5008
0
  return( -1 );
5009
0
}
5010
5011
/* Retrieves file extents for a specific identifier from the file system B-tree
5012
 * Returns 1 if successful, 0 if not found or -1 on error
5013
 */
5014
int libfsapfs_file_system_btree_get_file_extents(
5015
     libfsapfs_file_system_btree_t *file_system_btree,
5016
     libbfio_handle_t *file_io_handle,
5017
     uint64_t identifier,
5018
     uint64_t transaction_identifier,
5019
     libcdata_array_t *file_extents,
5020
     libcerror_error_t **error )
5021
606
{
5022
606
  libfsapfs_btree_node_t *root_node = NULL;
5023
606
  static char *function             = "libfsapfs_file_system_btree_get_file_extents";
5024
606
  int is_leaf_node                  = 0;
5025
606
  int result                        = 0;
5026
5027
606
  if( file_system_btree == NULL )
5028
0
  {
5029
0
    libcerror_error_set(
5030
0
     error,
5031
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5032
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5033
0
     "%s: invalid file system B-tree.",
5034
0
     function );
5035
5036
0
    return( -1 );
5037
0
  }
5038
#if defined( HAVE_DEBUG_OUTPUT )
5039
  if( libcnotify_verbose != 0 )
5040
  {
5041
    libcnotify_printf(
5042
     "%s: retrieving file extents of: %" PRIu64 " (transaction: %" PRIu64 ")\n",
5043
     function,
5044
     identifier,
5045
     transaction_identifier );
5046
  }
5047
#endif
5048
606
  result = libfsapfs_file_system_btree_get_root_node(
5049
606
            file_system_btree,
5050
606
            file_io_handle,
5051
606
            file_system_btree->root_node_block_number,
5052
606
            &root_node,
5053
606
            error );
5054
5055
606
  if( result == -1 )
5056
0
  {
5057
0
    libcerror_error_set(
5058
0
     error,
5059
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5060
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5061
0
     "%s: unable to retrieve B-tree root node.",
5062
0
     function );
5063
5064
0
    goto on_error;
5065
0
  }
5066
606
  else if( result == 0 )
5067
0
  {
5068
0
    return( 0 );
5069
0
  }
5070
606
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
5071
606
                  root_node,
5072
606
                  error );
5073
5074
606
  if( is_leaf_node == -1 )
5075
0
  {
5076
0
    libcerror_error_set(
5077
0
     error,
5078
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5079
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5080
0
     "%s: unable to determine if B-tree root node is a leaf node.",
5081
0
     function );
5082
5083
0
    goto on_error;
5084
0
  }
5085
606
  if( is_leaf_node != 0 )
5086
606
  {
5087
606
    result = libfsapfs_file_system_btree_get_file_extents_from_leaf_node(
5088
606
              file_system_btree,
5089
606
              root_node,
5090
606
              identifier,
5091
606
              file_extents,
5092
606
              error );
5093
606
  }
5094
0
  else
5095
0
  {
5096
0
    result = libfsapfs_file_system_btree_get_file_extents_from_branch_node(
5097
0
              file_system_btree,
5098
0
              file_io_handle,
5099
0
              root_node,
5100
0
              identifier,
5101
0
              transaction_identifier,
5102
0
              file_extents,
5103
0
              0,
5104
0
              error );
5105
0
  }
5106
606
  if( result == -1 )
5107
124
  {
5108
124
    libcerror_error_set(
5109
124
     error,
5110
124
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5111
124
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5112
124
     "%s: unable to retrieve file extents: %" PRIu64 " from file system B-tree root node.",
5113
124
     function,
5114
124
     identifier );
5115
5116
124
    goto on_error;
5117
124
  }
5118
482
  return( result );
5119
5120
124
on_error:
5121
124
  libcdata_array_empty(
5122
124
   file_extents,
5123
124
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
5124
124
   NULL );
5125
5126
124
  return( -1 );
5127
606
}
5128
5129
/* Retrieves an inode for a specific identifier from the file system B-tree
5130
 * Returns 1 if successful, 0 if not found or -1 on error
5131
 */
5132
int libfsapfs_file_system_btree_get_inode_by_identifier(
5133
     libfsapfs_file_system_btree_t *file_system_btree,
5134
     libbfio_handle_t *file_io_handle,
5135
     uint64_t identifier,
5136
     uint64_t transaction_identifier,
5137
     libfsapfs_inode_t **inode,
5138
     libcerror_error_t **error )
5139
1.90k
{
5140
1.90k
  libfsapfs_btree_entry_t *btree_entry = NULL;
5141
1.90k
  libfsapfs_btree_node_t *btree_node   = NULL;
5142
1.90k
  libfsapfs_inode_t *safe_inode        = NULL;
5143
1.90k
  static char *function                = "libfsapfs_file_system_btree_get_inode_by_identifier";
5144
1.90k
  int result                           = 0;
5145
5146
#if defined( HAVE_PROFILER )
5147
  int64_t profiler_start_timestamp     = 0;
5148
#endif
5149
5150
1.90k
  if( file_system_btree == NULL )
5151
0
  {
5152
0
    libcerror_error_set(
5153
0
     error,
5154
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5155
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5156
0
     "%s: invalid file system B-tree.",
5157
0
     function );
5158
5159
0
    return( -1 );
5160
0
  }
5161
1.90k
  if( inode == NULL )
5162
0
  {
5163
0
    libcerror_error_set(
5164
0
     error,
5165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5167
0
     "%s: invalid inode.",
5168
0
     function );
5169
5170
0
    return( -1 );
5171
0
  }
5172
1.90k
  if( *inode != NULL )
5173
0
  {
5174
0
    libcerror_error_set(
5175
0
     error,
5176
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5177
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
5178
0
     "%s: invalid inode value already set.",
5179
0
     function );
5180
5181
0
    return( -1 );
5182
0
  }
5183
#if defined( HAVE_PROFILER )
5184
  if( file_system_btree->io_handle->profiler != NULL )
5185
  {
5186
    if( libfsapfs_profiler_start_timing(
5187
         file_system_btree->io_handle->profiler,
5188
         &profiler_start_timestamp,
5189
         error ) != 1 )
5190
    {
5191
      libcerror_error_set(
5192
       error,
5193
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5194
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5195
       "%s: unable to start timing.",
5196
       function );
5197
5198
      goto on_error;
5199
    }
5200
  }
5201
#endif /* defined( HAVE_PROFILER ) */
5202
5203
#if defined( HAVE_DEBUG_OUTPUT )
5204
  if( libcnotify_verbose != 0 )
5205
  {
5206
    libcnotify_printf(
5207
     "%s: retrieving inode of: %" PRIu64 " (transaction: %" PRIu64 ")\n",
5208
     function,
5209
     identifier,
5210
     transaction_identifier );
5211
  }
5212
#endif
5213
1.90k
  result = libfsapfs_file_system_btree_get_entry_by_identifier(
5214
1.90k
            file_system_btree,
5215
1.90k
            file_io_handle,
5216
1.90k
            identifier,
5217
1.90k
            LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_INODE,
5218
1.90k
            transaction_identifier,
5219
1.90k
            &btree_node,
5220
1.90k
            &btree_entry,
5221
1.90k
            error );
5222
5223
1.90k
  if( result == -1 )
5224
430
  {
5225
430
    libcerror_error_set(
5226
430
     error,
5227
430
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5228
430
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5229
430
     "%s: unable to retrieve entry from B-tree node.",
5230
430
     function );
5231
5232
430
    goto on_error;
5233
430
  }
5234
1.47k
  else if( result != 0 )
5235
1.41k
  {
5236
1.41k
    if( btree_node == NULL )
5237
0
    {
5238
0
      libcerror_error_set(
5239
0
       error,
5240
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5241
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5242
0
       "%s: invalid B-tree node.",
5243
0
       function );
5244
5245
0
      goto on_error;
5246
0
    }
5247
1.41k
    if( btree_entry == NULL )
5248
0
    {
5249
0
      libcerror_error_set(
5250
0
       error,
5251
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5252
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5253
0
       "%s: invalid B-tree entry.",
5254
0
       function );
5255
5256
0
      goto on_error;
5257
0
    }
5258
1.41k
    if( libfsapfs_inode_initialize(
5259
1.41k
         &safe_inode,
5260
1.41k
         error ) != 1 )
5261
0
    {
5262
0
      libcerror_error_set(
5263
0
       error,
5264
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5265
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
5266
0
       "%s: unable to create inode.",
5267
0
       function );
5268
5269
0
      goto on_error;
5270
0
    }
5271
1.41k
    if( libfsapfs_inode_read_key_data(
5272
1.41k
         safe_inode,
5273
1.41k
         btree_entry->key_data,
5274
1.41k
         (size_t) btree_entry->key_data_size,
5275
1.41k
         error ) != 1 )
5276
0
    {
5277
0
      libcerror_error_set(
5278
0
       error,
5279
0
       LIBCERROR_ERROR_DOMAIN_IO,
5280
0
       LIBCERROR_IO_ERROR_READ_FAILED,
5281
0
       "%s: unable to read inode key data.",
5282
0
       function );
5283
5284
0
      goto on_error;
5285
0
    }
5286
1.41k
    if( libfsapfs_inode_read_value_data(
5287
1.41k
         safe_inode,
5288
1.41k
         btree_entry->value_data,
5289
1.41k
         (size_t) btree_entry->value_data_size,
5290
1.41k
         error ) != 1 )
5291
79
    {
5292
79
      libcerror_error_set(
5293
79
       error,
5294
79
       LIBCERROR_ERROR_DOMAIN_IO,
5295
79
       LIBCERROR_IO_ERROR_READ_FAILED,
5296
79
       "%s: unable to read inode value data.",
5297
79
       function );
5298
5299
79
      goto on_error;
5300
79
    }
5301
1.33k
    btree_node = NULL;
5302
1.33k
  }
5303
#if defined( HAVE_PROFILER )
5304
  if( file_system_btree->io_handle->profiler != NULL )
5305
  {
5306
    if( libfsapfs_profiler_stop_timing(
5307
         file_system_btree->io_handle->profiler,
5308
         profiler_start_timestamp,
5309
         function,
5310
         0,
5311
         0,
5312
         error ) != 1 )
5313
    {
5314
      libcerror_error_set(
5315
       error,
5316
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5317
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5318
       "%s: unable to stop timing.",
5319
       function );
5320
5321
      goto on_error;
5322
    }
5323
  }
5324
#endif /* defined( HAVE_PROFILER ) */
5325
5326
1.39k
  *inode = safe_inode;
5327
5328
1.39k
  return( result );
5329
5330
509
on_error:
5331
509
  if( safe_inode != NULL )
5332
79
  {
5333
79
    libfsapfs_inode_free(
5334
79
     &safe_inode,
5335
79
     NULL );
5336
79
  }
5337
509
  return( -1 );
5338
1.90k
}
5339
5340
/* Retrieves an inode for an UTF-8 encoded name from the file system B-tree
5341
 * Returns 1 if successful, 0 if not found or -1 on error
5342
 */
5343
int libfsapfs_file_system_btree_get_inode_by_utf8_name(
5344
     libfsapfs_file_system_btree_t *file_system_btree,
5345
     libbfio_handle_t *file_io_handle,
5346
     uint64_t parent_identifier,
5347
     const uint8_t *utf8_string,
5348
     size_t utf8_string_length,
5349
     uint64_t transaction_identifier,
5350
     libfsapfs_inode_t **inode,
5351
     libfsapfs_directory_record_t **directory_record,
5352
     libcerror_error_t **error )
5353
0
{
5354
0
  libfsapfs_btree_entry_t *btree_entry = NULL;
5355
0
  libfsapfs_btree_node_t *btree_node   = NULL;
5356
0
  libfsapfs_btree_node_t *root_node    = NULL;
5357
0
  static char *function                = "libfsapfs_file_system_btree_get_inode_by_utf8_name";
5358
0
  uint64_t lookup_identifier           = 0;
5359
0
  uint32_t name_hash                   = 0;
5360
0
  int is_leaf_node                     = 0;
5361
0
  int result                           = 0;
5362
5363
0
  if( file_system_btree == NULL )
5364
0
  {
5365
0
    libcerror_error_set(
5366
0
     error,
5367
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5368
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5369
0
     "%s: invalid file system B-tree.",
5370
0
     function );
5371
5372
0
    return( -1 );
5373
0
  }
5374
0
  if( utf8_string == NULL )
5375
0
  {
5376
0
    libcerror_error_set(
5377
0
     error,
5378
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5379
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5380
0
     "%s: invalid UTF-8 string.",
5381
0
     function );
5382
5383
0
    return( -1 );
5384
0
  }
5385
0
  if( utf8_string_length > (size_t) SSIZE_MAX )
5386
0
  {
5387
0
    libcerror_error_set(
5388
0
     error,
5389
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5390
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
5391
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
5392
0
     function );
5393
5394
0
    return( -1 );
5395
0
  }
5396
0
  if( inode == NULL )
5397
0
  {
5398
0
    libcerror_error_set(
5399
0
     error,
5400
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5401
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5402
0
     "%s: invalid inode.",
5403
0
     function );
5404
5405
0
    return( -1 );
5406
0
  }
5407
0
  if( *inode != NULL )
5408
0
  {
5409
0
    libcerror_error_set(
5410
0
     error,
5411
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5412
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
5413
0
     "%s: invalid inode value already set.",
5414
0
     function );
5415
5416
0
    return( -1 );
5417
0
  }
5418
0
  if( directory_record == NULL )
5419
0
  {
5420
0
    libcerror_error_set(
5421
0
     error,
5422
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5423
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5424
0
     "%s: invalid directory record.",
5425
0
     function );
5426
5427
0
    return( -1 );
5428
0
  }
5429
0
  if( *directory_record != NULL )
5430
0
  {
5431
0
    libcerror_error_set(
5432
0
     error,
5433
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5434
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
5435
0
     "%s: invalid directory record value already set.",
5436
0
     function );
5437
5438
0
    return( -1 );
5439
0
  }
5440
0
  result = libfsapfs_file_system_btree_get_root_node(
5441
0
            file_system_btree,
5442
0
            file_io_handle,
5443
0
            file_system_btree->root_node_block_number,
5444
0
            &root_node,
5445
0
            error );
5446
5447
0
  if( result == -1 )
5448
0
  {
5449
0
    libcerror_error_set(
5450
0
     error,
5451
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5452
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5453
0
     "%s: unable to retrieve B-tree root node.",
5454
0
     function );
5455
5456
0
    goto on_error;
5457
0
  }
5458
0
  else if( result == 0 )
5459
0
  {
5460
0
    return( 0 );
5461
0
  }
5462
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
5463
0
                  root_node,
5464
0
                  error );
5465
5466
0
  if( is_leaf_node == -1 )
5467
0
  {
5468
0
    libcerror_error_set(
5469
0
     error,
5470
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5471
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5472
0
     "%s: unable to determine if B-tree root node is a leaf node.",
5473
0
     function );
5474
5475
0
    goto on_error;
5476
0
  }
5477
0
  if( libfsapfs_name_hash_calculate_from_utf8_string(
5478
0
       &name_hash,
5479
0
       utf8_string,
5480
0
       utf8_string_length,
5481
0
       file_system_btree->use_case_folding,
5482
0
       error ) != 1 )
5483
0
  {
5484
0
    libcerror_error_set(
5485
0
     error,
5486
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5487
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5488
0
     "%s: unable to determine name hash.",
5489
0
     function );
5490
5491
0
    goto on_error;
5492
0
  }
5493
0
  if( is_leaf_node != 0 )
5494
0
  {
5495
0
    result = libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf8_name(
5496
0
        file_system_btree,
5497
0
        root_node,
5498
0
        parent_identifier,
5499
0
        utf8_string,
5500
0
        utf8_string_length,
5501
0
        name_hash,
5502
0
        directory_record,
5503
0
        error );
5504
0
  }
5505
0
  else
5506
0
  {
5507
0
    result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name(
5508
0
        file_system_btree,
5509
0
        file_io_handle,
5510
0
        root_node,
5511
0
        parent_identifier,
5512
0
        utf8_string,
5513
0
        utf8_string_length,
5514
0
        name_hash,
5515
0
        transaction_identifier,
5516
0
        directory_record,
5517
0
        0,
5518
0
        error );
5519
0
  }
5520
0
  if( result == -1 )
5521
0
  {
5522
0
    libcerror_error_set(
5523
0
     error,
5524
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5525
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5526
0
     "%s: unable to retrieve directory entry by name.",
5527
0
     function );
5528
5529
0
    goto on_error;
5530
0
  }
5531
0
  else if( result != 0 )
5532
0
  {
5533
0
    if( libfsapfs_directory_record_get_identifier(
5534
0
         *directory_record,
5535
0
         &lookup_identifier,
5536
0
         error ) != 1 )
5537
0
    {
5538
0
      libcerror_error_set(
5539
0
       error,
5540
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5541
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5542
0
       "%s: unable to retrieve directory entry identifier.",
5543
0
       function );
5544
5545
0
      goto on_error;
5546
0
    }
5547
0
  }
5548
0
  root_node = NULL;
5549
5550
0
  if( result != 0 )
5551
0
  {
5552
0
    result = libfsapfs_file_system_btree_get_entry_by_identifier(
5553
0
              file_system_btree,
5554
0
              file_io_handle,
5555
0
              lookup_identifier,
5556
0
              LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_INODE,
5557
0
              transaction_identifier,
5558
0
              &btree_node,
5559
0
              &btree_entry,
5560
0
              error );
5561
5562
0
    if( result != 0 )
5563
0
    {
5564
0
      libcerror_error_set(
5565
0
       error,
5566
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5567
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5568
0
       "%s: unable to retrieve entry from B-tree node.",
5569
0
       function );
5570
5571
0
      goto on_error;
5572
0
    }
5573
0
    if( btree_node == NULL )
5574
0
    {
5575
0
      libcerror_error_set(
5576
0
       error,
5577
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5578
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5579
0
       "%s: invalid B-tree node.",
5580
0
       function );
5581
5582
0
      goto on_error;
5583
0
    }
5584
0
    if( btree_entry == NULL )
5585
0
    {
5586
0
      libcerror_error_set(
5587
0
       error,
5588
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5589
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5590
0
       "%s: invalid B-tree entry.",
5591
0
       function );
5592
5593
0
      goto on_error;
5594
0
    }
5595
0
    if( libfsapfs_inode_initialize(
5596
0
         inode,
5597
0
         error ) != 1 )
5598
0
    {
5599
0
      libcerror_error_set(
5600
0
       error,
5601
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5602
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
5603
0
       "%s: unable to create inode.",
5604
0
       function );
5605
5606
0
      goto on_error;
5607
0
    }
5608
0
    if( libfsapfs_inode_read_key_data(
5609
0
         *inode,
5610
0
         btree_entry->key_data,
5611
0
         (size_t) btree_entry->key_data_size,
5612
0
         error ) != 1 )
5613
0
    {
5614
0
      libcerror_error_set(
5615
0
       error,
5616
0
       LIBCERROR_ERROR_DOMAIN_IO,
5617
0
       LIBCERROR_IO_ERROR_READ_FAILED,
5618
0
       "%s: unable to read inode key data.",
5619
0
       function );
5620
5621
0
      goto on_error;
5622
0
    }
5623
0
    if( libfsapfs_inode_read_value_data(
5624
0
         *inode,
5625
0
         btree_entry->value_data,
5626
0
         (size_t) btree_entry->value_data_size,
5627
0
         error ) != 1 )
5628
0
    {
5629
0
      libcerror_error_set(
5630
0
       error,
5631
0
       LIBCERROR_ERROR_DOMAIN_IO,
5632
0
       LIBCERROR_IO_ERROR_READ_FAILED,
5633
0
       "%s: unable to read inode value data.",
5634
0
       function );
5635
5636
0
      goto on_error;
5637
0
    }
5638
0
    btree_node = NULL;
5639
0
  }
5640
0
  return( result );
5641
5642
0
on_error:
5643
0
  if( *directory_record != NULL )
5644
0
  {
5645
0
    libfsapfs_directory_record_free(
5646
0
     directory_record,
5647
0
     NULL );
5648
0
  }
5649
0
  if( *inode != NULL )
5650
0
  {
5651
0
    libfsapfs_inode_free(
5652
0
     inode,
5653
0
     NULL );
5654
0
  }
5655
0
  return( -1 );
5656
0
}
5657
5658
/* Retrieves an inode for an UTF-8 encoded path from the file system B-tree
5659
 * Returns 1 if successful, 0 if not found or -1 on error
5660
 */
5661
int libfsapfs_file_system_btree_get_inode_by_utf8_path(
5662
     libfsapfs_file_system_btree_t *file_system_btree,
5663
     libbfio_handle_t *file_io_handle,
5664
     uint64_t parent_identifier,
5665
     const uint8_t *utf8_string,
5666
     size_t utf8_string_length,
5667
     uint64_t transaction_identifier,
5668
     libfsapfs_inode_t **inode,
5669
     libfsapfs_directory_record_t **directory_record,
5670
     libcerror_error_t **error )
5671
1.04k
{
5672
1.04k
  libfsapfs_btree_entry_t *btree_entry                = NULL;
5673
1.04k
  libfsapfs_btree_node_t *btree_node                  = NULL;
5674
1.04k
  libfsapfs_btree_node_t *root_node                   = NULL;
5675
1.04k
  libfsapfs_directory_record_t *safe_directory_record = NULL;
5676
1.04k
  const uint8_t *utf8_string_segment                  = NULL;
5677
1.04k
  static char *function                               = "libfsapfs_file_system_btree_get_inode_by_utf8_path";
5678
1.04k
  libuna_unicode_character_t unicode_character        = 0;
5679
1.04k
  size_t utf8_string_index                            = 0;
5680
1.04k
  size_t utf8_string_segment_length                   = 0;
5681
1.04k
  uint64_t lookup_identifier                          = 0;
5682
1.04k
  uint32_t name_hash                                  = 0;
5683
1.04k
  int is_leaf_node                                    = 0;
5684
1.04k
  int result                                          = 0;
5685
5686
1.04k
  if( file_system_btree == NULL )
5687
0
  {
5688
0
    libcerror_error_set(
5689
0
     error,
5690
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5691
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5692
0
     "%s: invalid file system B-tree.",
5693
0
     function );
5694
5695
0
    return( -1 );
5696
0
  }
5697
1.04k
  if( utf8_string == NULL )
5698
0
  {
5699
0
    libcerror_error_set(
5700
0
     error,
5701
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5702
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5703
0
     "%s: invalid UTF-8 string.",
5704
0
     function );
5705
5706
0
    return( -1 );
5707
0
  }
5708
1.04k
  if( utf8_string_length > (size_t) SSIZE_MAX )
5709
0
  {
5710
0
    libcerror_error_set(
5711
0
     error,
5712
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5713
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
5714
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
5715
0
     function );
5716
5717
0
    return( -1 );
5718
0
  }
5719
1.04k
  if( inode == NULL )
5720
0
  {
5721
0
    libcerror_error_set(
5722
0
     error,
5723
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5724
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5725
0
     "%s: invalid inode.",
5726
0
     function );
5727
5728
0
    return( -1 );
5729
0
  }
5730
1.04k
  if( *inode != NULL )
5731
0
  {
5732
0
    libcerror_error_set(
5733
0
     error,
5734
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5735
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
5736
0
     "%s: invalid inode value already set.",
5737
0
     function );
5738
5739
0
    return( -1 );
5740
0
  }
5741
1.04k
  if( directory_record == NULL )
5742
0
  {
5743
0
    libcerror_error_set(
5744
0
     error,
5745
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5746
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5747
0
     "%s: invalid directory record.",
5748
0
     function );
5749
5750
0
    return( -1 );
5751
0
  }
5752
1.04k
  if( *directory_record != NULL )
5753
0
  {
5754
0
    libcerror_error_set(
5755
0
     error,
5756
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5757
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
5758
0
     "%s: invalid directory record value already set.",
5759
0
     function );
5760
5761
0
    return( -1 );
5762
0
  }
5763
1.04k
  result = libfsapfs_file_system_btree_get_root_node(
5764
1.04k
            file_system_btree,
5765
1.04k
            file_io_handle,
5766
1.04k
            file_system_btree->root_node_block_number,
5767
1.04k
            &root_node,
5768
1.04k
            error );
5769
5770
1.04k
  if( result == -1 )
5771
251
  {
5772
251
    libcerror_error_set(
5773
251
     error,
5774
251
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5775
251
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5776
251
     "%s: unable to retrieve B-tree root node.",
5777
251
     function );
5778
5779
251
    goto on_error;
5780
251
  }
5781
792
  else if( result == 0 )
5782
1
  {
5783
1
    return( 0 );
5784
1
  }
5785
791
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
5786
791
                  root_node,
5787
791
                  error );
5788
5789
791
  if( is_leaf_node == -1 )
5790
0
  {
5791
0
    libcerror_error_set(
5792
0
     error,
5793
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5794
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5795
0
     "%s: unable to determine if B-tree root node is a leaf node.",
5796
0
     function );
5797
5798
0
    goto on_error;
5799
0
  }
5800
791
  lookup_identifier = parent_identifier;
5801
5802
791
  if( utf8_string_length > 0 )
5803
791
  {
5804
    /* Ignore a leading separator
5805
     */
5806
791
    if( utf8_string[ utf8_string_index ] == (uint8_t) LIBFSAPFS_SEPARATOR )
5807
791
    {
5808
791
      utf8_string_index++;
5809
791
    }
5810
791
  }
5811
791
  if( ( utf8_string_length == 0 )
5812
791
   || ( utf8_string_length == 1 ) )
5813
0
  {
5814
0
    result = 1;
5815
0
  }
5816
1.47k
  else while( utf8_string_index < utf8_string_length )
5817
1.16k
  {
5818
1.16k
    utf8_string_segment        = &( utf8_string[ utf8_string_index ] );
5819
1.16k
    utf8_string_segment_length = utf8_string_index;
5820
5821
12.1k
    while( utf8_string_index < utf8_string_length )
5822
11.7k
    {
5823
11.7k
      if( libuna_unicode_character_copy_from_utf8(
5824
11.7k
           &unicode_character,
5825
11.7k
           utf8_string,
5826
11.7k
           utf8_string_length,
5827
11.7k
           &utf8_string_index,
5828
11.7k
           error ) != 1 )
5829
0
      {
5830
0
        libcerror_error_set(
5831
0
         error,
5832
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5833
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
5834
0
         "%s: unable to copy UTF-8 string to Unicode character.",
5835
0
         function );
5836
5837
0
        goto on_error;
5838
0
      }
5839
11.7k
      if( ( unicode_character == (libuna_unicode_character_t) LIBFSAPFS_SEPARATOR )
5840
11.7k
       || ( unicode_character == 0 ) )
5841
791
      {
5842
791
        utf8_string_segment_length += 1;
5843
5844
791
        break;
5845
791
      }
5846
11.7k
    }
5847
1.16k
    utf8_string_segment_length = utf8_string_index - utf8_string_segment_length;
5848
5849
1.16k
    if( utf8_string_segment_length == 0 )
5850
0
    {
5851
0
      result = 0;
5852
0
    }
5853
1.16k
    else
5854
1.16k
    {
5855
1.16k
      if( libfsapfs_name_hash_calculate_from_utf8_string(
5856
1.16k
           &name_hash,
5857
1.16k
           utf8_string_segment,
5858
1.16k
           utf8_string_segment_length,
5859
1.16k
           file_system_btree->use_case_folding,
5860
1.16k
           error ) != 1 )
5861
0
      {
5862
0
        libcerror_error_set(
5863
0
         error,
5864
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5865
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5866
0
         "%s: unable to determine name hash.",
5867
0
         function );
5868
5869
0
        goto on_error;
5870
0
      }
5871
1.16k
      if( safe_directory_record != NULL )
5872
376
      {
5873
376
        if( libfsapfs_directory_record_free(
5874
376
             &safe_directory_record,
5875
376
             error ) != 1 )
5876
0
        {
5877
0
          libcerror_error_set(
5878
0
           error,
5879
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
5880
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
5881
0
           "%s: unable to free directory record.",
5882
0
           function );
5883
5884
0
          goto on_error;
5885
0
        }
5886
376
      }
5887
1.16k
      if( is_leaf_node != 0 )
5888
964
      {
5889
964
        result = libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf8_name(
5890
964
            file_system_btree,
5891
964
            root_node,
5892
964
            lookup_identifier,
5893
964
            utf8_string_segment,
5894
964
            utf8_string_segment_length,
5895
964
                  name_hash,
5896
964
            &safe_directory_record,
5897
964
            error );
5898
964
      }
5899
203
      else
5900
203
      {
5901
203
        result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name(
5902
203
            file_system_btree,
5903
203
            file_io_handle,
5904
203
            root_node,
5905
203
            lookup_identifier,
5906
203
            utf8_string_segment,
5907
203
            utf8_string_segment_length,
5908
203
                  name_hash,
5909
203
                  transaction_identifier,
5910
203
            &safe_directory_record,
5911
203
            0,
5912
203
            error );
5913
203
      }
5914
1.16k
    }
5915
1.16k
    if( result == -1 )
5916
355
    {
5917
355
      libcerror_error_set(
5918
355
       error,
5919
355
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5920
355
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5921
355
       "%s: unable to retrieve directory entry by name.",
5922
355
       function );
5923
5924
355
      goto on_error;
5925
355
    }
5926
812
    else if( result == 0 )
5927
127
    {
5928
127
      break;
5929
127
    }
5930
685
    if( libfsapfs_directory_record_get_identifier(
5931
685
         safe_directory_record,
5932
685
         &lookup_identifier,
5933
685
         error ) != 1 )
5934
0
    {
5935
0
      libcerror_error_set(
5936
0
       error,
5937
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5938
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5939
0
       "%s: unable to retrieve directory entry identifier.",
5940
0
       function );
5941
5942
0
      goto on_error;
5943
0
    }
5944
685
  }
5945
436
  root_node = NULL;
5946
5947
436
  if( result != 0 )
5948
309
  {
5949
309
    result = libfsapfs_file_system_btree_get_entry_by_identifier(
5950
309
              file_system_btree,
5951
309
              file_io_handle,
5952
309
              lookup_identifier,
5953
309
              LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_INODE,
5954
309
              transaction_identifier,
5955
309
              &btree_node,
5956
309
              &btree_entry,
5957
309
              error );
5958
5959
309
    if( result != 1 )
5960
37
    {
5961
37
      libcerror_error_set(
5962
37
       error,
5963
37
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5964
37
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5965
37
       "%s: unable to retrieve entry from B-tree node.",
5966
37
       function );
5967
5968
37
      goto on_error;
5969
37
    }
5970
272
    if( btree_node == NULL )
5971
0
    {
5972
0
      libcerror_error_set(
5973
0
       error,
5974
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5975
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5976
0
       "%s: invalid B-tree node.",
5977
0
       function );
5978
5979
0
      goto on_error;
5980
0
    }
5981
272
    if( btree_entry == NULL )
5982
0
    {
5983
0
      libcerror_error_set(
5984
0
       error,
5985
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5986
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5987
0
       "%s: invalid B-tree entry.",
5988
0
       function );
5989
5990
0
      goto on_error;
5991
0
    }
5992
272
    if( libfsapfs_inode_initialize(
5993
272
         inode,
5994
272
         error ) != 1 )
5995
0
    {
5996
0
      libcerror_error_set(
5997
0
       error,
5998
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5999
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
6000
0
       "%s: unable to create inode.",
6001
0
       function );
6002
6003
0
      goto on_error;
6004
0
    }
6005
272
    if( libfsapfs_inode_read_key_data(
6006
272
         *inode,
6007
272
         btree_entry->key_data,
6008
272
         (size_t) btree_entry->key_data_size,
6009
272
         error ) != 1 )
6010
0
    {
6011
0
      libcerror_error_set(
6012
0
       error,
6013
0
       LIBCERROR_ERROR_DOMAIN_IO,
6014
0
       LIBCERROR_IO_ERROR_READ_FAILED,
6015
0
       "%s: unable to read inode key data.",
6016
0
       function );
6017
6018
0
      goto on_error;
6019
0
    }
6020
272
    if( libfsapfs_inode_read_value_data(
6021
272
         *inode,
6022
272
         btree_entry->value_data,
6023
272
         (size_t) btree_entry->value_data_size,
6024
272
         error ) != 1 )
6025
54
    {
6026
54
      libcerror_error_set(
6027
54
       error,
6028
54
       LIBCERROR_ERROR_DOMAIN_IO,
6029
54
       LIBCERROR_IO_ERROR_READ_FAILED,
6030
54
       "%s: unable to read inode value data.",
6031
54
       function );
6032
6033
54
      goto on_error;
6034
54
    }
6035
218
    btree_node = NULL;
6036
6037
218
    *directory_record = safe_directory_record;
6038
218
  }
6039
345
  return( result );
6040
6041
697
on_error:
6042
697
  if( safe_directory_record != NULL )
6043
91
  {
6044
91
    libfsapfs_directory_record_free(
6045
91
     &safe_directory_record,
6046
91
     NULL );
6047
91
  }
6048
697
  if( *inode != NULL )
6049
54
  {
6050
54
    libfsapfs_inode_free(
6051
54
     inode,
6052
54
     NULL );
6053
54
  }
6054
697
  return( -1 );
6055
436
}
6056
6057
/* Retrieves an inode for an UTF-16 encoded name from the file system B-tree
6058
 * Returns 1 if successful, 0 if not found or -1 on error
6059
 */
6060
int libfsapfs_file_system_btree_get_inode_by_utf16_name(
6061
     libfsapfs_file_system_btree_t *file_system_btree,
6062
     libbfio_handle_t *file_io_handle,
6063
     uint64_t parent_identifier,
6064
     const uint16_t *utf16_string,
6065
     size_t utf16_string_length,
6066
     uint64_t transaction_identifier,
6067
     libfsapfs_inode_t **inode,
6068
     libfsapfs_directory_record_t **directory_record,
6069
     libcerror_error_t **error )
6070
0
{
6071
0
  libfsapfs_btree_entry_t *btree_entry = NULL;
6072
0
  libfsapfs_btree_node_t *btree_node   = NULL;
6073
0
  libfsapfs_btree_node_t *root_node    = NULL;
6074
0
  static char *function                = "libfsapfs_file_system_btree_get_inode_by_utf16_name";
6075
0
  uint64_t lookup_identifier           = 0;
6076
0
  uint32_t name_hash                   = 0;
6077
0
  int is_leaf_node                     = 0;
6078
0
  int result                           = 0;
6079
6080
0
  if( file_system_btree == NULL )
6081
0
  {
6082
0
    libcerror_error_set(
6083
0
     error,
6084
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6085
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6086
0
     "%s: invalid file system B-tree.",
6087
0
     function );
6088
6089
0
    return( -1 );
6090
0
  }
6091
0
  if( utf16_string == NULL )
6092
0
  {
6093
0
    libcerror_error_set(
6094
0
     error,
6095
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6096
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6097
0
     "%s: invalid UTF-16 string.",
6098
0
     function );
6099
6100
0
    return( -1 );
6101
0
  }
6102
0
  if( utf16_string_length > (size_t) SSIZE_MAX )
6103
0
  {
6104
0
    libcerror_error_set(
6105
0
     error,
6106
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6107
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
6108
0
     "%s: invalid UTF-16 string length value exceeds maximum.",
6109
0
     function );
6110
6111
0
    return( -1 );
6112
0
  }
6113
0
  if( inode == NULL )
6114
0
  {
6115
0
    libcerror_error_set(
6116
0
     error,
6117
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6118
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6119
0
     "%s: invalid inode.",
6120
0
     function );
6121
6122
0
    return( -1 );
6123
0
  }
6124
0
  if( *inode != NULL )
6125
0
  {
6126
0
    libcerror_error_set(
6127
0
     error,
6128
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6129
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
6130
0
     "%s: invalid inode value already set.",
6131
0
     function );
6132
6133
0
    return( -1 );
6134
0
  }
6135
0
  if( directory_record == NULL )
6136
0
  {
6137
0
    libcerror_error_set(
6138
0
     error,
6139
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6140
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6141
0
     "%s: invalid directory record.",
6142
0
     function );
6143
6144
0
    return( -1 );
6145
0
  }
6146
0
  if( *directory_record != NULL )
6147
0
  {
6148
0
    libcerror_error_set(
6149
0
     error,
6150
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6151
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
6152
0
     "%s: invalid directory record value already set.",
6153
0
     function );
6154
6155
0
    return( -1 );
6156
0
  }
6157
0
  result = libfsapfs_file_system_btree_get_root_node(
6158
0
            file_system_btree,
6159
0
            file_io_handle,
6160
0
            file_system_btree->root_node_block_number,
6161
0
            &root_node,
6162
0
            error );
6163
6164
0
  if( result == -1 )
6165
0
  {
6166
0
    libcerror_error_set(
6167
0
     error,
6168
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6169
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6170
0
     "%s: unable to retrieve B-tree root node.",
6171
0
     function );
6172
6173
0
    goto on_error;
6174
0
  }
6175
0
  else if( result == 0 )
6176
0
  {
6177
0
    return( 0 );
6178
0
  }
6179
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
6180
0
                  root_node,
6181
0
                  error );
6182
6183
0
  if( is_leaf_node == -1 )
6184
0
  {
6185
0
    libcerror_error_set(
6186
0
     error,
6187
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6188
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6189
0
     "%s: unable to determine if B-tree root node is a leaf node.",
6190
0
     function );
6191
6192
0
    goto on_error;
6193
0
  }
6194
0
  if( libfsapfs_name_hash_calculate_from_utf16_string(
6195
0
       &name_hash,
6196
0
       utf16_string,
6197
0
       utf16_string_length,
6198
0
       file_system_btree->use_case_folding,
6199
0
       error ) != 1 )
6200
0
  {
6201
0
    libcerror_error_set(
6202
0
     error,
6203
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6204
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6205
0
     "%s: unable to determine name hash.",
6206
0
     function );
6207
6208
0
    goto on_error;
6209
0
  }
6210
0
  if( is_leaf_node != 0 )
6211
0
  {
6212
0
    result = libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf16_name(
6213
0
        file_system_btree,
6214
0
        root_node,
6215
0
        parent_identifier,
6216
0
        utf16_string,
6217
0
        utf16_string_length,
6218
0
        name_hash,
6219
0
        directory_record,
6220
0
        error );
6221
0
  }
6222
0
  else
6223
0
  {
6224
0
    result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf16_name(
6225
0
        file_system_btree,
6226
0
        file_io_handle,
6227
0
        root_node,
6228
0
        parent_identifier,
6229
0
        utf16_string,
6230
0
        utf16_string_length,
6231
0
        name_hash,
6232
0
        transaction_identifier,
6233
0
        directory_record,
6234
0
        0,
6235
0
        error );
6236
0
  }
6237
0
  if( result == -1 )
6238
0
  {
6239
0
    libcerror_error_set(
6240
0
     error,
6241
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6242
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6243
0
     "%s: unable to retrieve directory entry by name.",
6244
0
     function );
6245
6246
0
    goto on_error;
6247
0
  }
6248
0
  else if( result != 0 )
6249
0
  {
6250
0
    if( libfsapfs_directory_record_get_identifier(
6251
0
         *directory_record,
6252
0
         &lookup_identifier,
6253
0
         error ) != 1 )
6254
0
    {
6255
0
      libcerror_error_set(
6256
0
       error,
6257
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6258
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6259
0
       "%s: unable to retrieve directory entry identifier.",
6260
0
       function );
6261
6262
0
      goto on_error;
6263
0
    }
6264
0
  }
6265
0
  root_node = NULL;
6266
6267
0
  if( result != 0 )
6268
0
  {
6269
0
    result = libfsapfs_file_system_btree_get_entry_by_identifier(
6270
0
              file_system_btree,
6271
0
              file_io_handle,
6272
0
              lookup_identifier,
6273
0
              LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_INODE,
6274
0
              transaction_identifier,
6275
0
              &btree_node,
6276
0
              &btree_entry,
6277
0
              error );
6278
6279
0
    if( result != 0 )
6280
0
    {
6281
0
      libcerror_error_set(
6282
0
       error,
6283
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6284
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6285
0
       "%s: unable to retrieve entry from B-tree node.",
6286
0
       function );
6287
6288
0
      goto on_error;
6289
0
    }
6290
0
    if( btree_node == NULL )
6291
0
    {
6292
0
      libcerror_error_set(
6293
0
       error,
6294
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6295
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
6296
0
       "%s: invalid B-tree node.",
6297
0
       function );
6298
6299
0
      goto on_error;
6300
0
    }
6301
0
    if( btree_entry == NULL )
6302
0
    {
6303
0
      libcerror_error_set(
6304
0
       error,
6305
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6306
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
6307
0
       "%s: invalid B-tree entry.",
6308
0
       function );
6309
6310
0
      goto on_error;
6311
0
    }
6312
0
    if( libfsapfs_inode_initialize(
6313
0
         inode,
6314
0
         error ) != 1 )
6315
0
    {
6316
0
      libcerror_error_set(
6317
0
       error,
6318
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6319
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
6320
0
       "%s: unable to create inode.",
6321
0
       function );
6322
6323
0
      goto on_error;
6324
0
    }
6325
0
    if( libfsapfs_inode_read_key_data(
6326
0
         *inode,
6327
0
         btree_entry->key_data,
6328
0
         (size_t) btree_entry->key_data_size,
6329
0
         error ) != 1 )
6330
0
    {
6331
0
      libcerror_error_set(
6332
0
       error,
6333
0
       LIBCERROR_ERROR_DOMAIN_IO,
6334
0
       LIBCERROR_IO_ERROR_READ_FAILED,
6335
0
       "%s: unable to read inode key data.",
6336
0
       function );
6337
6338
0
      goto on_error;
6339
0
    }
6340
0
    if( libfsapfs_inode_read_value_data(
6341
0
         *inode,
6342
0
         btree_entry->value_data,
6343
0
         (size_t) btree_entry->value_data_size,
6344
0
         error ) != 1 )
6345
0
    {
6346
0
      libcerror_error_set(
6347
0
       error,
6348
0
       LIBCERROR_ERROR_DOMAIN_IO,
6349
0
       LIBCERROR_IO_ERROR_READ_FAILED,
6350
0
       "%s: unable to read inode value data.",
6351
0
       function );
6352
6353
0
      goto on_error;
6354
0
    }
6355
0
    btree_node = NULL;
6356
0
  }
6357
0
  return( result );
6358
6359
0
on_error:
6360
0
  if( *directory_record != NULL )
6361
0
  {
6362
0
    libfsapfs_directory_record_free(
6363
0
     directory_record,
6364
0
     NULL );
6365
0
  }
6366
0
  if( *inode != NULL )
6367
0
  {
6368
0
    libfsapfs_inode_free(
6369
0
     inode,
6370
0
     NULL );
6371
0
  }
6372
0
  return( -1 );
6373
0
}
6374
6375
/* Retrieves an inode for an UTF-16 encoded path from the file system B-tree
6376
 * Returns 1 if successful, 0 if not found or -1 on error
6377
 */
6378
int libfsapfs_file_system_btree_get_inode_by_utf16_path(
6379
     libfsapfs_file_system_btree_t *file_system_btree,
6380
     libbfio_handle_t *file_io_handle,
6381
     uint64_t parent_identifier,
6382
     const uint16_t *utf16_string,
6383
     size_t utf16_string_length,
6384
     uint64_t transaction_identifier,
6385
     libfsapfs_inode_t **inode,
6386
     libfsapfs_directory_record_t **directory_record,
6387
     libcerror_error_t **error )
6388
0
{
6389
0
  libfsapfs_btree_entry_t *btree_entry                = NULL;
6390
0
  libfsapfs_btree_node_t *btree_node                  = NULL;
6391
0
  libfsapfs_btree_node_t *root_node                   = NULL;
6392
0
  libfsapfs_directory_record_t *safe_directory_record = NULL;
6393
0
  const uint16_t *utf16_string_segment                = NULL;
6394
0
  static char *function                               = "libfsapfs_file_system_btree_get_inode_by_utf16_path";
6395
0
  libuna_unicode_character_t unicode_character        = 0;
6396
0
  size_t utf16_string_index                           = 0;
6397
0
  size_t utf16_string_segment_length                  = 0;
6398
0
  uint64_t lookup_identifier                          = 0;
6399
0
  uint32_t name_hash                                  = 0;
6400
0
  int is_leaf_node                                    = 0;
6401
0
  int result                                          = 0;
6402
6403
0
  if( file_system_btree == NULL )
6404
0
  {
6405
0
    libcerror_error_set(
6406
0
     error,
6407
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6408
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6409
0
     "%s: invalid file system B-tree.",
6410
0
     function );
6411
6412
0
    return( -1 );
6413
0
  }
6414
0
  if( utf16_string == NULL )
6415
0
  {
6416
0
    libcerror_error_set(
6417
0
     error,
6418
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6419
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6420
0
     "%s: invalid UTF-16 string.",
6421
0
     function );
6422
6423
0
    return( -1 );
6424
0
  }
6425
0
  if( utf16_string_length > (size_t) SSIZE_MAX )
6426
0
  {
6427
0
    libcerror_error_set(
6428
0
     error,
6429
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6430
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
6431
0
     "%s: invalid UTF-16 string length value exceeds maximum.",
6432
0
     function );
6433
6434
0
    return( -1 );
6435
0
  }
6436
0
  if( inode == NULL )
6437
0
  {
6438
0
    libcerror_error_set(
6439
0
     error,
6440
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6441
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6442
0
     "%s: invalid inode.",
6443
0
     function );
6444
6445
0
    return( -1 );
6446
0
  }
6447
0
  if( *inode != NULL )
6448
0
  {
6449
0
    libcerror_error_set(
6450
0
     error,
6451
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6452
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
6453
0
     "%s: invalid inode value already set.",
6454
0
     function );
6455
6456
0
    return( -1 );
6457
0
  }
6458
0
  if( directory_record == NULL )
6459
0
  {
6460
0
    libcerror_error_set(
6461
0
     error,
6462
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
6463
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
6464
0
     "%s: invalid directory record.",
6465
0
     function );
6466
6467
0
    return( -1 );
6468
0
  }
6469
0
  if( *directory_record != NULL )
6470
0
  {
6471
0
    libcerror_error_set(
6472
0
     error,
6473
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6474
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
6475
0
     "%s: invalid directory record value already set.",
6476
0
     function );
6477
6478
0
    return( -1 );
6479
0
  }
6480
0
  result = libfsapfs_file_system_btree_get_root_node(
6481
0
            file_system_btree,
6482
0
            file_io_handle,
6483
0
            file_system_btree->root_node_block_number,
6484
0
            &root_node,
6485
0
            error );
6486
6487
0
  if( result == -1 )
6488
0
  {
6489
0
    libcerror_error_set(
6490
0
     error,
6491
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6492
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6493
0
     "%s: unable to retrieve B-tree root node.",
6494
0
     function );
6495
6496
0
    goto on_error;
6497
0
  }
6498
0
  else if( result == 0 )
6499
0
  {
6500
0
    return( 0 );
6501
0
  }
6502
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
6503
0
                  root_node,
6504
0
                  error );
6505
6506
0
  if( is_leaf_node == -1 )
6507
0
  {
6508
0
    libcerror_error_set(
6509
0
     error,
6510
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
6511
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6512
0
     "%s: unable to determine if B-tree root node is a leaf node.",
6513
0
     function );
6514
6515
0
    goto on_error;
6516
0
  }
6517
0
  lookup_identifier = parent_identifier;
6518
6519
0
  if( utf16_string_length > 0 )
6520
0
  {
6521
    /* Ignore a leading separator
6522
     */
6523
0
    if( utf16_string[ utf16_string_index ] == (uint16_t) LIBFSAPFS_SEPARATOR )
6524
0
    {
6525
0
      utf16_string_index++;
6526
0
    }
6527
0
  }
6528
0
  if( ( utf16_string_length == 0 )
6529
0
   || ( utf16_string_length == 1 ) )
6530
0
  {
6531
0
    result = 1;
6532
0
  }
6533
0
  else while( utf16_string_index < utf16_string_length )
6534
0
  {
6535
0
    utf16_string_segment        = &( utf16_string[ utf16_string_index ] );
6536
0
    utf16_string_segment_length = utf16_string_index;
6537
6538
0
    while( utf16_string_index < utf16_string_length )
6539
0
    {
6540
0
      if( libuna_unicode_character_copy_from_utf16(
6541
0
           &unicode_character,
6542
0
           utf16_string,
6543
0
           utf16_string_length,
6544
0
           &utf16_string_index,
6545
0
           error ) != 1 )
6546
0
      {
6547
0
        libcerror_error_set(
6548
0
         error,
6549
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
6550
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
6551
0
         "%s: unable to copy UTF-16 string to Unicode character.",
6552
0
         function );
6553
6554
0
        goto on_error;
6555
0
      }
6556
0
      if( ( unicode_character == (libuna_unicode_character_t) LIBFSAPFS_SEPARATOR )
6557
0
       || ( unicode_character == 0 ) )
6558
0
      {
6559
0
        utf16_string_segment_length += 1;
6560
6561
0
        break;
6562
0
      }
6563
0
    }
6564
0
    utf16_string_segment_length = utf16_string_index - utf16_string_segment_length;
6565
6566
0
    if( utf16_string_segment_length == 0 )
6567
0
    {
6568
0
      result = 0;
6569
0
    }
6570
0
    else
6571
0
    {
6572
0
      if( libfsapfs_name_hash_calculate_from_utf16_string(
6573
0
           &name_hash,
6574
0
           utf16_string_segment,
6575
0
           utf16_string_segment_length,
6576
0
           file_system_btree->use_case_folding,
6577
0
           error ) != 1 )
6578
0
      {
6579
0
        libcerror_error_set(
6580
0
         error,
6581
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
6582
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6583
0
         "%s: unable to determine name hash.",
6584
0
         function );
6585
6586
0
        goto on_error;
6587
0
      }
6588
0
      if( safe_directory_record != NULL )
6589
0
      {
6590
0
        if( libfsapfs_directory_record_free(
6591
0
             &safe_directory_record,
6592
0
             error ) != 1 )
6593
0
        {
6594
0
          libcerror_error_set(
6595
0
           error,
6596
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
6597
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
6598
0
           "%s: unable to free directory record.",
6599
0
           function );
6600
6601
0
          goto on_error;
6602
0
        }
6603
0
      }
6604
0
      if( is_leaf_node != 0 )
6605
0
      {
6606
0
        result = libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf16_name(
6607
0
            file_system_btree,
6608
0
            root_node,
6609
0
            lookup_identifier,
6610
0
            utf16_string_segment,
6611
0
            utf16_string_segment_length,
6612
0
                  name_hash,
6613
0
            &safe_directory_record,
6614
0
            error );
6615
0
      }
6616
0
      else
6617
0
      {
6618
0
        result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf16_name(
6619
0
            file_system_btree,
6620
0
            file_io_handle,
6621
0
            root_node,
6622
0
            lookup_identifier,
6623
0
            utf16_string_segment,
6624
0
            utf16_string_segment_length,
6625
0
                  name_hash,
6626
0
                  transaction_identifier,
6627
0
            &safe_directory_record,
6628
0
            0,
6629
0
            error );
6630
0
      }
6631
0
    }
6632
0
    if( result == -1 )
6633
0
    {
6634
0
      libcerror_error_set(
6635
0
       error,
6636
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6637
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6638
0
       "%s: unable to retrieve directory entry by name.",
6639
0
       function );
6640
6641
0
      goto on_error;
6642
0
    }
6643
0
    else if( result == 0 )
6644
0
    {
6645
0
      break;
6646
0
    }
6647
0
    if( libfsapfs_directory_record_get_identifier(
6648
0
         safe_directory_record,
6649
0
         &lookup_identifier,
6650
0
         error ) != 1 )
6651
0
    {
6652
0
      libcerror_error_set(
6653
0
       error,
6654
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6655
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6656
0
       "%s: unable to retrieve directory entry identifier.",
6657
0
       function );
6658
6659
0
      goto on_error;
6660
0
    }
6661
0
  }
6662
0
  root_node = NULL;
6663
6664
0
  if( result != 0 )
6665
0
  {
6666
0
    result = libfsapfs_file_system_btree_get_entry_by_identifier(
6667
0
              file_system_btree,
6668
0
              file_io_handle,
6669
0
              lookup_identifier,
6670
0
              LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_INODE,
6671
0
              transaction_identifier,
6672
0
              &btree_node,
6673
0
              &btree_entry,
6674
0
              error );
6675
6676
0
    if( result != 1 )
6677
0
    {
6678
0
      libcerror_error_set(
6679
0
       error,
6680
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6681
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
6682
0
       "%s: unable to retrieve entry from B-tree node.",
6683
0
       function );
6684
6685
0
      goto on_error;
6686
0
    }
6687
0
    if( btree_node == NULL )
6688
0
    {
6689
0
      libcerror_error_set(
6690
0
       error,
6691
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6692
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
6693
0
       "%s: invalid B-tree node.",
6694
0
       function );
6695
6696
0
      goto on_error;
6697
0
    }
6698
0
    if( btree_entry == NULL )
6699
0
    {
6700
0
      libcerror_error_set(
6701
0
       error,
6702
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6703
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
6704
0
       "%s: invalid B-tree entry.",
6705
0
       function );
6706
6707
0
      goto on_error;
6708
0
    }
6709
0
    if( libfsapfs_inode_initialize(
6710
0
         inode,
6711
0
         error ) != 1 )
6712
0
    {
6713
0
      libcerror_error_set(
6714
0
       error,
6715
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
6716
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
6717
0
       "%s: unable to create inode.",
6718
0
       function );
6719
6720
0
      goto on_error;
6721
0
    }
6722
0
    if( libfsapfs_inode_read_key_data(
6723
0
         *inode,
6724
0
         btree_entry->key_data,
6725
0
         (size_t) btree_entry->key_data_size,
6726
0
         error ) != 1 )
6727
0
    {
6728
0
      libcerror_error_set(
6729
0
       error,
6730
0
       LIBCERROR_ERROR_DOMAIN_IO,
6731
0
       LIBCERROR_IO_ERROR_READ_FAILED,
6732
0
       "%s: unable to read inode key data.",
6733
0
       function );
6734
6735
0
      goto on_error;
6736
0
    }
6737
0
    if( libfsapfs_inode_read_value_data(
6738
0
         *inode,
6739
0
         btree_entry->value_data,
6740
0
         (size_t) btree_entry->value_data_size,
6741
0
         error ) != 1 )
6742
0
    {
6743
0
      libcerror_error_set(
6744
0
       error,
6745
0
       LIBCERROR_ERROR_DOMAIN_IO,
6746
0
       LIBCERROR_IO_ERROR_READ_FAILED,
6747
0
       "%s: unable to read inode value data.",
6748
0
       function );
6749
6750
0
      goto on_error;
6751
0
    }
6752
0
    btree_node = NULL;
6753
6754
0
    *directory_record = safe_directory_record;
6755
0
  }
6756
0
  return( result );
6757
6758
0
on_error:
6759
0
  if( safe_directory_record != NULL )
6760
0
  {
6761
0
    libfsapfs_directory_record_free(
6762
0
     &safe_directory_record,
6763
0
     NULL );
6764
0
  }
6765
0
  if( *inode != NULL )
6766
0
  {
6767
0
    libfsapfs_inode_free(
6768
0
     inode,
6769
0
     NULL );
6770
0
  }
6771
0
  return( -1 );
6772
0
}
6773