Coverage Report

Created: 2026-07-25 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsapfs/libfsapfs/libfsapfs_file_system_btree.c
Line
Count
Source
1
/*
2
 * The file system B-tree functions
3
 *
4
 * Copyright (C) 2018-2026, 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
1.24k
{
67
1.24k
  static char *function = "libfsapfs_file_system_btree_initialize";
68
69
1.24k
  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
1.24k
  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
1.24k
  *file_system_btree = memory_allocate_structure(
92
1.24k
                        libfsapfs_file_system_btree_t );
93
94
1.24k
  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
1.24k
  if( memory_set(
106
1.24k
       *file_system_btree,
107
1.24k
       0,
108
1.24k
       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
1.24k
  if( libfcache_cache_initialize(
125
1.24k
       &( ( *file_system_btree )->data_block_cache ),
126
1.24k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
127
1.24k
       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
1.24k
  if( libfcache_cache_initialize(
139
1.24k
       &( ( *file_system_btree )->node_cache ),
140
1.24k
       LIBFSAPFS_MAXIMUM_CACHE_ENTRIES_BTREE_NODES,
141
1.24k
       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
1.24k
  ( *file_system_btree )->io_handle              = io_handle;
153
1.24k
  ( *file_system_btree )->encryption_context     = encryption_context;
154
1.24k
  ( *file_system_btree )->data_block_vector      = data_block_vector;
155
1.24k
  ( *file_system_btree )->object_map_btree       = object_map_btree;
156
1.24k
  ( *file_system_btree )->root_node_block_number = root_node_block_number;
157
1.24k
  ( *file_system_btree )->use_case_folding       = use_case_folding;
158
159
1.24k
  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
1.24k
}
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
1.24k
{
179
1.24k
  static char *function = "libfsapfs_file_system_btree_free";
180
1.24k
  int result            = 1;
181
182
1.24k
  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
1.24k
  if( *file_system_btree != NULL )
194
1.24k
  {
195
    /* The io_handle, data_block_vector and object_map_btree are referenced and freed elsewhere
196
     */
197
1.24k
    if( libfcache_cache_free(
198
1.24k
         &( ( *file_system_btree )->node_cache ),
199
1.24k
         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
1.24k
    if( libfcache_cache_free(
211
1.24k
         &( ( *file_system_btree )->data_block_cache ),
212
1.24k
         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
1.24k
    memory_free(
224
1.24k
     *file_system_btree );
225
226
1.24k
    *file_system_btree = NULL;
227
1.24k
  }
228
1.24k
  return( result );
229
1.24k
}
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
735
{
242
735
  libfsapfs_object_map_descriptor_t *object_map_descriptor = NULL;
243
735
  static char *function                                    = "libfsapfs_file_system_btree_get_sub_node_block_number_from_entry";
244
735
  uint64_t sub_node_object_identifier                      = 0;
245
735
  int result                                               = 0;
246
247
735
  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
735
  if( entry == NULL )
259
11
  {
260
11
    libcerror_error_set(
261
11
     error,
262
11
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
263
11
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
264
11
     "%s: invalid B-tree entry.",
265
11
     function );
266
267
11
    return( -1 );
268
11
  }
269
724
  if( entry->value_data == NULL )
270
74
  {
271
74
    libcerror_error_set(
272
74
     error,
273
74
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
274
74
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
275
74
     "%s: invalid B-tree entry - missing value data.",
276
74
     function );
277
278
74
    return( -1 );
279
74
  }
280
650
  if( entry->value_data_size != 8 )
281
21
  {
282
21
    libcerror_error_set(
283
21
     error,
284
21
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
285
21
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
286
21
     "%s: invalid B-tree entry - unsupported value data size.",
287
21
     function );
288
289
21
    return( -1 );
290
21
  }
291
629
  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
629
  byte_stream_copy_to_uint64_little_endian(
303
629
   entry->value_data,
304
629
   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
629
  result = libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
317
629
            file_system_btree->object_map_btree,
318
629
            file_io_handle,
319
629
            sub_node_object_identifier,
320
629
            transaction_identifier,
321
629
            &object_map_descriptor,
322
629
            error );
323
324
629
  if( result == -1 )
325
9
  {
326
9
    libcerror_error_set(
327
9
     error,
328
9
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
9
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
330
9
     "%s: unable to retrieve object map descriptor for sub node object identifier: %" PRIu64 " (transaction: %" PRIu64 ").",
331
9
     function,
332
9
     sub_node_object_identifier,
333
9
     transaction_identifier );
334
335
9
    goto on_error;
336
9
  }
337
620
  else if( result != 0 )
338
615
  {
339
615
    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
615
    *sub_node_block_number = object_map_descriptor->physical_address;
360
361
615
    if( libfsapfs_object_map_descriptor_free(
362
615
         &object_map_descriptor,
363
615
         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
615
  }
375
620
  return( result );
376
377
9
on_error:
378
9
  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
9
  return( -1 );
385
629
}
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
1.88k
{
397
1.88k
  libfcache_cache_value_t *cache_value = NULL;
398
1.88k
  libfsapfs_btree_node_t *node         = NULL;
399
1.88k
  libfsapfs_data_block_t *data_block   = NULL;
400
1.88k
  static char *function                = "libfsapfs_file_system_btree_get_root_node";
401
1.88k
  int result                           = 0;
402
403
#if defined( HAVE_PROFILER )
404
  int64_t profiler_start_timestamp     = 0;
405
#endif
406
407
1.88k
  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
1.88k
  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
1.88k
  if( root_node_block_number > (uint64_t) INT_MAX )
430
59
  {
431
59
    libcerror_error_set(
432
59
     error,
433
59
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
434
59
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
435
59
     "%s: invalid root node block number value out of bounds.",
436
59
     function );
437
438
59
    return( -1 );
439
59
  }
440
1.82k
  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
1.82k
  result = libfcache_cache_get_value_by_identifier(
472
1.82k
            file_system_btree->node_cache,
473
1.82k
            0,
474
1.82k
            (off64_t) root_node_block_number,
475
1.82k
            0,
476
1.82k
            &cache_value,
477
1.82k
            error );
478
479
1.82k
  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
1.82k
  else if( result == 0 )
491
1.18k
  {
492
1.18k
    if( libfdata_vector_get_element_value_by_index(
493
1.18k
         file_system_btree->data_block_vector,
494
1.18k
         (intptr_t *) file_io_handle,
495
1.18k
         (libfdata_cache_t *) file_system_btree->data_block_cache,
496
1.18k
         (int) root_node_block_number,
497
1.18k
         (intptr_t **) &data_block,
498
1.18k
         0,
499
1.18k
         error ) != 1 )
500
31
    {
501
31
      libcerror_error_set(
502
31
       error,
503
31
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
504
31
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
505
31
       "%s: unable to retrieve data block: %" PRIu64 ".",
506
31
       function,
507
31
       root_node_block_number );
508
509
31
      goto on_error;
510
31
    }
511
1.15k
    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
1.15k
    if( libfsapfs_btree_node_initialize(
524
1.15k
         &node,
525
1.15k
         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
1.15k
    if( libfsapfs_btree_node_read_data(
537
1.15k
         node,
538
1.15k
         data_block->data,
539
1.15k
         data_block->data_size,
540
1.15k
         error ) != 1 )
541
5
    {
542
5
      libcerror_error_set(
543
5
       error,
544
5
       LIBCERROR_ERROR_DOMAIN_IO,
545
5
       LIBCERROR_IO_ERROR_READ_FAILED,
546
5
       "%s: unable to read B-tree node.",
547
5
       function );
548
549
5
      goto on_error;
550
5
    }
551
1.14k
    if( node->object_type == 0x00000000UL )
552
1
    {
553
1
      if( libfsapfs_btree_node_free(
554
1
           &node,
555
1
           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
1
      return( 0 );
567
1
    }
568
1.14k
    if( ( node->object_type != 0x00000002UL )
569
23
     && ( node->object_type != 0x10000002UL ) )
570
19
    {
571
19
      libcerror_error_set(
572
19
       error,
573
19
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
574
19
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
575
19
       "%s: invalid object type: 0x%08" PRIx32 ".",
576
19
       function,
577
19
       node->object_type );
578
579
19
      goto on_error;
580
19
    }
581
1.12k
    if( node->object_subtype != 0x0000000eUL )
582
46
    {
583
46
      libcerror_error_set(
584
46
       error,
585
46
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
586
46
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
587
46
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
588
46
       function,
589
46
       node->object_subtype );
590
591
46
      goto on_error;
592
46
    }
593
1.08k
    if( ( ( node->node_header->flags & 0x0001 ) == 0 )
594
1.08k
     || ( ( node->node_header->flags & 0x0004 ) != 0 ) )
595
2
    {
596
2
      libcerror_error_set(
597
2
       error,
598
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
599
2
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
600
2
       "%s: unsupported flags: 0x%04" PRIx16 ".",
601
2
       function,
602
2
       node->node_header->flags );
603
604
2
      goto on_error;
605
2
    }
606
1.08k
    if( node->footer->node_size != 4096 )
607
45
    {
608
45
      libcerror_error_set(
609
45
       error,
610
45
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
611
45
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
612
45
       "%s: invalid node size value out of bounds.",
613
45
       function );
614
615
45
      goto on_error;
616
45
    }
617
1.03k
    if( node->footer->key_size != 0 )
618
5
    {
619
5
      libcerror_error_set(
620
5
       error,
621
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
622
5
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
623
5
       "%s: invalid key size value out of bounds.",
624
5
       function );
625
626
5
      goto on_error;
627
5
    }
628
1.03k
    if( node->footer->value_size != 0 )
629
38
    {
630
38
      libcerror_error_set(
631
38
       error,
632
38
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
633
38
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
634
38
       "%s: invalid value size value out of bounds.",
635
38
       function );
636
637
38
      goto on_error;
638
38
    }
639
992
    if( libfcache_cache_set_value_by_identifier(
640
992
         file_system_btree->node_cache,
641
992
         0,
642
992
         (off64_t) root_node_block_number,
643
992
         0,
644
992
         (intptr_t *) node,
645
992
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_btree_node_free,
646
992
         LIBFCACHE_CACHE_VALUE_FLAG_MANAGED,
647
992
         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
992
    node = NULL;
659
660
992
    if( libfcache_cache_get_value_by_identifier(
661
992
         file_system_btree->node_cache,
662
992
         0,
663
992
         (off64_t) root_node_block_number,
664
992
         0,
665
992
         &cache_value,
666
992
         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
992
  }
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
1.62k
  if( libfcache_cache_value_get_value(
702
1.62k
       cache_value,
703
1.62k
       (intptr_t **) root_node,
704
1.62k
       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
1.62k
  return( 1 );
716
717
191
on_error:
718
191
  if( node != NULL )
719
160
  {
720
160
    libfsapfs_btree_node_free(
721
160
     &node,
722
160
     NULL );
723
160
  }
724
191
  return( -1 );
725
1.62k
}
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
615
{
737
615
  libfcache_cache_value_t *cache_value = NULL;
738
615
  libfsapfs_btree_node_t *node         = NULL;
739
615
  libfsapfs_data_block_t *data_block   = NULL;
740
615
  static char *function                = "libfsapfs_file_system_btree_get_sub_node";
741
615
  int result                           = 0;
742
743
#if defined( HAVE_PROFILER )
744
  int64_t profiler_start_timestamp     = 0;
745
#endif
746
747
615
  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
615
  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
615
  if( sub_node_block_number > (uint64_t) INT_MAX )
770
45
  {
771
45
    libcerror_error_set(
772
45
     error,
773
45
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
774
45
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
775
45
     "%s: invalid sub node block number value out of bounds.",
776
45
     function );
777
778
45
    return( -1 );
779
45
  }
780
570
  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
570
  result = libfcache_cache_get_value_by_identifier(
812
570
            file_system_btree->node_cache,
813
570
            0,
814
570
            (off64_t) sub_node_block_number,
815
570
            0,
816
570
            &cache_value,
817
570
            error );
818
819
570
  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
570
  else if( result == 0 )
831
56
  {
832
56
    if( libfdata_vector_get_element_value_by_index(
833
56
         file_system_btree->data_block_vector,
834
56
         (intptr_t *) file_io_handle,
835
56
         (libfdata_cache_t *) file_system_btree->data_block_cache,
836
56
         (int) sub_node_block_number,
837
56
         (intptr_t **) &data_block,
838
56
         0,
839
56
         error ) != 1 )
840
9
    {
841
9
      libcerror_error_set(
842
9
       error,
843
9
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
844
9
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
845
9
       "%s: unable to retrieve data block: %" PRIu64 ".",
846
9
       function,
847
9
       sub_node_block_number );
848
849
9
      goto on_error;
850
9
    }
851
47
    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
47
    if( libfsapfs_btree_node_initialize(
864
47
         &node,
865
47
         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
47
    if( libfsapfs_btree_node_read_data(
877
47
         node,
878
47
         data_block->data,
879
47
         data_block->data_size,
880
47
         error ) != 1 )
881
2
    {
882
2
      libcerror_error_set(
883
2
       error,
884
2
       LIBCERROR_ERROR_DOMAIN_IO,
885
2
       LIBCERROR_IO_ERROR_READ_FAILED,
886
2
       "%s: unable to read B-tree node.",
887
2
       function );
888
889
2
      goto on_error;
890
2
    }
891
45
    if( ( node->object_type != 0x00000003UL )
892
25
     && ( node->object_type != 0x10000003UL ) )
893
18
    {
894
18
      libcerror_error_set(
895
18
       error,
896
18
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
897
18
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
898
18
       "%s: invalid object type: 0x%08" PRIx32 ".",
899
18
       function,
900
18
       node->object_type );
901
902
18
      goto on_error;
903
18
    }
904
27
    if( node->object_subtype != 0x0000000eUL )
905
23
    {
906
23
      libcerror_error_set(
907
23
       error,
908
23
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
909
23
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
910
23
       "%s: invalid object subtype: 0x%08" PRIx32 ".",
911
23
       function,
912
23
       node->object_subtype );
913
914
23
      goto on_error;
915
23
    }
916
4
    if( ( ( node->node_header->flags & 0x0001 ) != 0 )
917
3
     || ( ( 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
516
  if( libfcache_cache_value_get_value(
992
516
       cache_value,
993
516
       (intptr_t **) sub_node,
994
516
       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
516
  return( 1 );
1006
1007
54
on_error:
1008
54
  if( node != NULL )
1009
45
  {
1010
45
    libfsapfs_btree_node_free(
1011
45
     &node,
1012
45
     NULL );
1013
45
  }
1014
54
  return( -1 );
1015
516
}
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
373
{
1028
373
  libfsapfs_btree_entry_t *entry          = NULL;
1029
373
  libfsapfs_btree_entry_t *previous_entry = NULL;
1030
373
  static char *function                   = "libfsapfs_file_system_btree_get_entry_from_node_by_identifier";
1031
373
  uint64_t file_system_identifier         = 0;
1032
373
  uint64_t lookup_identifier              = 0;
1033
373
  uint8_t file_system_data_type           = 0;
1034
373
  int btree_entry_index                   = 0;
1035
373
  int is_leaf_node                        = 0;
1036
373
  int number_of_entries                   = 0;
1037
1038
373
  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
373
  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
373
  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
373
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1084
373
                  node,
1085
373
                  error );
1086
1087
373
  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
373
  if( libfsapfs_btree_node_get_number_of_entries(
1099
373
       node,
1100
373
       &number_of_entries,
1101
373
       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
373
  lookup_identifier = ( (uint64_t) data_type << 60 ) | identifier;
1113
1114
373
  for( btree_entry_index = 0;
1115
7.18k
       btree_entry_index < number_of_entries;
1116
6.80k
       btree_entry_index++ )
1117
7.15k
  {
1118
7.15k
    if( libfsapfs_btree_node_get_entry_by_index(
1119
7.15k
         node,
1120
7.15k
         btree_entry_index,
1121
7.15k
         &entry,
1122
7.15k
         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
7.15k
    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
7.15k
    if( entry->key_data == NULL )
1146
10
    {
1147
10
      libcerror_error_set(
1148
10
       error,
1149
10
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1150
10
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1151
10
       "%s: invalid B-tree entry: %d - missing key data.",
1152
10
       function,
1153
10
       btree_entry_index );
1154
1155
10
      return( -1 );
1156
10
    }
1157
7.14k
    if( entry->key_data_size < 8 )
1158
4
    {
1159
4
      libcerror_error_set(
1160
4
       error,
1161
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1162
4
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1163
4
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1164
4
       function,
1165
4
       btree_entry_index );
1166
1167
4
      return( -1 );
1168
4
    }
1169
7.14k
    byte_stream_copy_to_uint64_little_endian(
1170
7.14k
     entry->key_data,
1171
7.14k
     file_system_identifier );
1172
1173
7.14k
    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
7.14k
    if( is_leaf_node != 0 )
1189
7.14k
    {
1190
7.14k
      if( file_system_identifier == lookup_identifier )
1191
335
      {
1192
335
        *btree_entry = entry;
1193
1194
335
        return( 1 );
1195
335
      }
1196
7.14k
    }
1197
0
    else
1198
0
    {
1199
0
      file_system_identifier &= 0x0fffffffffffffffUL;
1200
1201
0
      if( file_system_identifier >= identifier )
1202
0
      {
1203
0
        if( ( previous_entry == NULL )
1204
0
         || ( ( file_system_identifier == identifier )
1205
0
          &&  ( file_system_data_type <= data_type ) ) )
1206
0
        {
1207
0
          previous_entry = entry;
1208
0
        }
1209
0
        *btree_entry = previous_entry;
1210
1211
0
        return( 1 );
1212
0
      }
1213
0
      previous_entry = entry;
1214
0
    }
1215
7.14k
  }
1216
24
  if( is_leaf_node == 0 )
1217
0
  {
1218
0
    *btree_entry = previous_entry;
1219
1220
0
    return( 1 );
1221
0
  }
1222
24
  return( 0 );
1223
24
}
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
373
{
1238
373
  libfsapfs_btree_entry_t *entry = NULL;
1239
373
  libfsapfs_btree_node_t *node   = NULL;
1240
373
  static char *function          = "libfsapfs_file_system_btree_get_entry_by_identifier";
1241
373
  uint64_t sub_node_block_number = 0;
1242
373
  int is_leaf_node               = 0;
1243
373
  int recursion_depth            = 0;
1244
373
  int result                     = 0;
1245
1246
373
  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
373
  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
373
  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
373
  result = libfsapfs_file_system_btree_get_root_node(
1280
373
            file_system_btree,
1281
373
            file_io_handle,
1282
373
            file_system_btree->root_node_block_number,
1283
373
            &node,
1284
373
            error );
1285
1286
373
  if( result == -1 )
1287
0
  {
1288
0
    libcerror_error_set(
1289
0
     error,
1290
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1292
0
     "%s: unable to retrieve B-tree root node.",
1293
0
     function );
1294
1295
0
    return( -1 );
1296
0
  }
1297
373
  else if( result == 0 )
1298
0
  {
1299
0
    return( 0 );
1300
0
  }
1301
373
  do
1302
373
  {
1303
373
    if( ( recursion_depth < 0 )
1304
373
     || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1305
0
    {
1306
0
      libcerror_error_set(
1307
0
       error,
1308
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1309
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1310
0
       "%s: invalid recursion depth value out of bounds.",
1311
0
       function );
1312
1313
0
      return( -1 );
1314
0
    }
1315
373
    is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1316
373
                    node,
1317
373
                    error );
1318
1319
373
    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
373
    result = libfsapfs_file_system_btree_get_entry_from_node_by_identifier(
1331
373
              file_system_btree,
1332
373
              node,
1333
373
              identifier,
1334
373
              data_type,
1335
373
              &entry,
1336
373
              error );
1337
1338
373
    if( result == -1 )
1339
14
    {
1340
14
      libcerror_error_set(
1341
14
       error,
1342
14
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1343
14
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1344
14
       "%s: unable to retrieve entry from B-tree node.",
1345
14
       function );
1346
1347
14
      return( -1 );
1348
14
    }
1349
359
    else if( result == 0 )
1350
24
    {
1351
24
      break;
1352
24
    }
1353
335
    if( is_leaf_node != 0 )
1354
335
    {
1355
335
      *btree_node  = node;
1356
335
      *btree_entry = entry;
1357
1358
335
      return( 1 );
1359
335
    }
1360
0
    if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
1361
0
         file_system_btree,
1362
0
         file_io_handle,
1363
0
         entry,
1364
0
         transaction_identifier,
1365
0
         &sub_node_block_number,
1366
0
         error ) != 1 )
1367
0
    {
1368
0
      libcerror_error_set(
1369
0
       error,
1370
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1371
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1372
0
       "%s: unable to determine sub node block number.",
1373
0
       function );
1374
1375
0
      return( -1 );
1376
0
    }
1377
0
    node = NULL;
1378
1379
0
    if( libfsapfs_file_system_btree_get_sub_node(
1380
0
         file_system_btree,
1381
0
         file_io_handle,
1382
0
         sub_node_block_number,
1383
0
         &node,
1384
0
         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
0
    recursion_depth++;
1397
0
  }
1398
373
  while( is_leaf_node == 0 );
1399
1400
24
  return( 0 );
1401
373
}
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
1.22k
{
1416
1.22k
  libfsapfs_btree_entry_t *entry                      = NULL;
1417
1.22k
  libfsapfs_directory_record_t *safe_directory_record = NULL;
1418
1.22k
  static char *function                               = "libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf8_name";
1419
1.22k
  uint64_t file_system_identifier                     = 0;
1420
1.22k
  uint64_t lookup_identifier                          = 0;
1421
1.22k
  int compare_result                                  = 0;
1422
1.22k
  int entry_index                                     = 0;
1423
1.22k
  int is_leaf_node                                    = 0;
1424
1.22k
  int number_of_entries                               = 0;
1425
1426
#if defined( HAVE_DEBUG_OUTPUT )
1427
  uint8_t file_system_data_type                       = 0;
1428
#endif
1429
1430
1.22k
  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
1.22k
  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
1.22k
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1462
1.22k
                  node,
1463
1.22k
                  error );
1464
1465
1.22k
  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
1.22k
  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
1.22k
  if( libfsapfs_btree_node_get_number_of_entries(
1488
1.22k
       node,
1489
1.22k
       &number_of_entries,
1490
1.22k
       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
1.22k
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD << 60 ) | parent_identifier;
1502
1503
1.22k
  for( entry_index = 0;
1504
14.4k
       entry_index < number_of_entries;
1505
13.2k
       entry_index++ )
1506
14.2k
  {
1507
14.2k
    if( libfsapfs_btree_node_get_entry_by_index(
1508
14.2k
         node,
1509
14.2k
         entry_index,
1510
14.2k
         &entry,
1511
14.2k
         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
14.2k
    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
14.2k
    if( entry->key_data == NULL )
1535
22
    {
1536
22
      libcerror_error_set(
1537
22
       error,
1538
22
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1539
22
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1540
22
       "%s: invalid B-tree entry: %d - missing key data.",
1541
22
       function,
1542
22
       entry_index );
1543
1544
22
      goto on_error;
1545
22
    }
1546
14.2k
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
1547
28
    {
1548
28
      libcerror_error_set(
1549
28
       error,
1550
28
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1551
28
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1552
28
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1553
28
       function,
1554
28
       entry_index );
1555
1556
28
      goto on_error;
1557
28
    }
1558
14.2k
    byte_stream_copy_to_uint64_little_endian(
1559
14.2k
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
1560
14.2k
     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
14.2k
    if( file_system_identifier == lookup_identifier )
1578
2.05k
    {
1579
2.05k
      if( libfsapfs_directory_record_initialize(
1580
2.05k
           &safe_directory_record,
1581
2.05k
           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
2.05k
      if( libfsapfs_directory_record_read_key_data(
1593
2.05k
           safe_directory_record,
1594
2.05k
           entry->key_data,
1595
2.05k
           (size_t) entry->key_data_size,
1596
2.05k
           error ) != 1 )
1597
63
      {
1598
63
        libcerror_error_set(
1599
63
         error,
1600
63
         LIBCERROR_ERROR_DOMAIN_IO,
1601
63
         LIBCERROR_IO_ERROR_READ_FAILED,
1602
63
         "%s: unable to read directory record key data.",
1603
63
         function );
1604
1605
63
        goto on_error;
1606
63
      }
1607
1.99k
      compare_result = libfsapfs_directory_record_compare_name_with_utf8_string(
1608
1.99k
                        safe_directory_record,
1609
1.99k
                        utf8_string,
1610
1.99k
                        utf8_string_length,
1611
1.99k
                        name_hash,
1612
1.99k
                        file_system_btree->use_case_folding,
1613
1.99k
                        error );
1614
1615
1.99k
      if( compare_result == -1 )
1616
32
      {
1617
32
        libcerror_error_set(
1618
32
         error,
1619
32
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1620
32
         LIBCERROR_RUNTIME_ERROR_GENERIC,
1621
32
         "%s: unable to compare UTF-8 string with name of directory record.",
1622
32
         function );
1623
1624
32
        goto on_error;
1625
32
      }
1626
1.96k
      else if( compare_result == LIBUNA_COMPARE_EQUAL )
1627
892
      {
1628
892
        if( libfsapfs_directory_record_read_value_data(
1629
892
             safe_directory_record,
1630
892
             entry->value_data,
1631
892
             (size_t) entry->value_data_size,
1632
892
             error ) != 1 )
1633
59
        {
1634
59
          libcerror_error_set(
1635
59
           error,
1636
59
           LIBCERROR_ERROR_DOMAIN_IO,
1637
59
           LIBCERROR_IO_ERROR_READ_FAILED,
1638
59
           "%s: unable to read directory record value data.",
1639
59
           function );
1640
1641
59
          goto on_error;
1642
59
        }
1643
833
        *directory_record = safe_directory_record;
1644
1645
833
        return( 1 );
1646
892
      }
1647
1.07k
      if( libfsapfs_directory_record_free(
1648
1.07k
           &safe_directory_record,
1649
1.07k
           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
1.07k
    }
1661
14.2k
  }
1662
183
  return( 0 );
1663
1664
204
on_error:
1665
204
  if( safe_directory_record != NULL )
1666
154
  {
1667
154
    libfsapfs_directory_record_free(
1668
154
     &safe_directory_record,
1669
154
     NULL );
1670
154
  }
1671
204
  return( -1 );
1672
1.22k
}
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
748
{
1690
748
  libfsapfs_btree_entry_t *entry                      = NULL;
1691
748
  libfsapfs_btree_entry_t *previous_entry             = NULL;
1692
748
  libfsapfs_btree_node_t *sub_node                    = NULL;
1693
748
  libfsapfs_directory_record_t *safe_directory_record = NULL;
1694
748
  static char *function                               = "libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name";
1695
748
  uint64_t file_system_identifier                     = 0;
1696
748
  uint64_t sub_node_block_number                      = 0;
1697
748
  uint8_t file_system_data_type                       = 0;
1698
748
  int compare_result                                  = 0;
1699
748
  int entry_index                                     = 0;
1700
748
  int is_leaf_node                                    = 0;
1701
748
  int number_of_entries                               = 0;
1702
748
  int result                                          = 0;
1703
1704
748
  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
748
  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
748
  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
748
  if( ( recursion_depth < 0 )
1738
748
   || ( recursion_depth > LIBFSAPFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1739
2
  {
1740
2
    libcerror_error_set(
1741
2
     error,
1742
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1743
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1744
2
     "%s: invalid recursion depth value out of bounds.",
1745
2
     function );
1746
1747
2
    return( -1 );
1748
2
  }
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
746
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1760
746
                  node,
1761
746
                  error );
1762
1763
746
  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
746
  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
746
  if( libfsapfs_btree_node_get_number_of_entries(
1786
746
       node,
1787
746
       &number_of_entries,
1788
746
       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
746
  for( entry_index = 0;
1800
3.70k
       entry_index < number_of_entries;
1801
2.95k
       entry_index++ )
1802
3.34k
  {
1803
3.34k
    if( libfsapfs_btree_node_get_entry_by_index(
1804
3.34k
         node,
1805
3.34k
         entry_index,
1806
3.34k
         &entry,
1807
3.34k
         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
3.34k
    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
3.34k
    if( entry->key_data == NULL )
1831
5
    {
1832
5
      libcerror_error_set(
1833
5
       error,
1834
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1835
5
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1836
5
       "%s: invalid B-tree entry: %d - missing key data.",
1837
5
       function,
1838
5
       entry_index );
1839
1840
5
      goto on_error;
1841
5
    }
1842
3.34k
    if( entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
1843
3
    {
1844
3
      libcerror_error_set(
1845
3
       error,
1846
3
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1847
3
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1848
3
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
1849
3
       function,
1850
3
       entry_index );
1851
1852
3
      goto on_error;
1853
3
    }
1854
3.34k
    byte_stream_copy_to_uint64_little_endian(
1855
3.34k
     ( (fsapfs_file_system_btree_key_common_t *) entry->key_data )->file_system_identifier,
1856
3.34k
     file_system_identifier );
1857
1858
3.34k
    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
3.34k
    file_system_identifier &= 0x0fffffffffffffffUL;
1874
1875
3.34k
    if( ( file_system_identifier > parent_identifier )
1876
2.97k
     || ( ( file_system_identifier == parent_identifier )
1877
1.03k
      &&  ( file_system_data_type > LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD ) ) )
1878
367
    {
1879
367
      break;
1880
367
    }
1881
2.97k
    if( ( file_system_identifier == parent_identifier )
1882
1.03k
     && ( file_system_data_type == LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD ) )
1883
44
    {
1884
44
      if( libfsapfs_directory_record_initialize(
1885
44
           &safe_directory_record,
1886
44
           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
44
      if( libfsapfs_directory_record_read_key_data(
1898
44
           safe_directory_record,
1899
44
           entry->key_data,
1900
44
           (size_t) entry->key_data_size,
1901
44
           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
42
      compare_result = libfsapfs_directory_record_compare_name_with_utf8_string(
1915
42
                        safe_directory_record,
1916
42
                        utf8_string,
1917
42
                        utf8_string_length,
1918
42
                        name_hash,
1919
42
                        0,
1920
42
                        error );
1921
1922
42
      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
41
      if( libfsapfs_directory_record_free(
1934
41
           &safe_directory_record,
1935
41
           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
41
      if( compare_result == LIBUNA_COMPARE_LESS )
1947
11
      {
1948
11
        break;
1949
11
      }
1950
41
    }
1951
2.95k
    previous_entry = entry;
1952
2.95k
  }
1953
735
  if( libfsapfs_file_system_btree_get_sub_node_block_number_from_entry(
1954
735
       file_system_btree,
1955
735
       file_io_handle,
1956
735
       previous_entry,
1957
735
       transaction_identifier,
1958
735
       &sub_node_block_number,
1959
735
       error ) != 1 )
1960
120
  {
1961
120
    libcerror_error_set(
1962
120
     error,
1963
120
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1964
120
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1965
120
     "%s: unable to determine sub node block number.",
1966
120
     function );
1967
1968
120
    goto on_error;
1969
120
  }
1970
615
  if( libfsapfs_file_system_btree_get_sub_node(
1971
615
       file_system_btree,
1972
615
       file_io_handle,
1973
615
       sub_node_block_number,
1974
615
       &sub_node,
1975
615
       error ) != 1 )
1976
99
  {
1977
99
    libcerror_error_set(
1978
99
     error,
1979
99
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1980
99
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1981
99
     "%s: unable to retrieve B-tree sub node from block: %" PRIu64 ".",
1982
99
     function,
1983
99
     sub_node_block_number );
1984
1985
99
    goto on_error;
1986
99
  }
1987
516
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
1988
516
                  sub_node,
1989
516
                  error );
1990
1991
516
  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
516
  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
515
  else
2015
515
  {
2016
515
    result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name(
2017
515
        file_system_btree,
2018
515
        file_io_handle,
2019
515
        sub_node,
2020
515
        parent_identifier,
2021
515
        utf8_string,
2022
515
        utf8_string_length,
2023
515
        name_hash,
2024
515
        transaction_identifier,
2025
515
        directory_record,
2026
515
        recursion_depth + 1,
2027
515
        error );
2028
515
  }
2029
516
  if( result == -1 )
2030
515
  {
2031
515
    libcerror_error_set(
2032
515
     error,
2033
515
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2034
515
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2035
515
     "%s: unable to retrieve directory entry by name.",
2036
515
     function );
2037
2038
515
    goto on_error;
2039
515
  }
2040
1
  sub_node = NULL;
2041
2042
1
  return( result );
2043
2044
745
on_error:
2045
745
  if( *directory_record != NULL )
2046
0
  {
2047
0
    libfsapfs_directory_record_free(
2048
0
     directory_record,
2049
0
     NULL );
2050
0
  }
2051
745
  if( safe_directory_record != NULL )
2052
3
  {
2053
3
    libfsapfs_directory_record_free(
2054
3
     &safe_directory_record,
2055
3
     NULL );
2056
3
  }
2057
745
  return( -1 );
2058
516
}
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
0
{
2727
0
  libfsapfs_btree_entry_t *btree_entry           = NULL;
2728
0
  libfsapfs_directory_record_t *directory_record = NULL;
2729
0
  static char *function                          = "libfsapfs_file_system_btree_get_directory_entries_from_leaf_node";
2730
0
  uint64_t file_system_identifier                = 0;
2731
0
  uint64_t lookup_identifier                     = 0;
2732
0
  int btree_entry_index                          = 0;
2733
0
  int entry_index                                = 0;
2734
0
  int found_directory_entry                      = 0;
2735
0
  int is_leaf_node                               = 0;
2736
0
  int number_of_entries                          = 0;
2737
2738
#if defined( HAVE_DEBUG_OUTPUT )
2739
  uint8_t file_system_data_type                  = 0;
2740
#endif
2741
2742
0
  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
0
  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
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
2765
0
                  node,
2766
0
                  error );
2767
2768
0
  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
0
  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
0
  if( libfsapfs_btree_node_get_number_of_entries(
2800
0
       node,
2801
0
       &number_of_entries,
2802
0
       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
0
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_DIRECTORY_RECORD << 60 ) | parent_identifier;
2814
2815
0
  for( btree_entry_index = 0;
2816
0
       btree_entry_index < number_of_entries;
2817
0
       btree_entry_index++ )
2818
0
  {
2819
0
    if( libfsapfs_btree_node_get_entry_by_index(
2820
0
         node,
2821
0
         btree_entry_index,
2822
0
         &btree_entry,
2823
0
         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
0
    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
0
    if( btree_entry->key_data == NULL )
2847
0
    {
2848
0
      libcerror_error_set(
2849
0
       error,
2850
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2851
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2852
0
       "%s: invalid B-tree entry: %d - missing key data.",
2853
0
       function,
2854
0
       btree_entry_index );
2855
2856
0
      goto on_error;
2857
0
    }
2858
0
    if( btree_entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
2859
0
    {
2860
0
      libcerror_error_set(
2861
0
       error,
2862
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2863
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2864
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
2865
0
       function,
2866
0
       btree_entry_index );
2867
2868
0
      goto on_error;
2869
0
    }
2870
0
    byte_stream_copy_to_uint64_little_endian(
2871
0
     ( (fsapfs_file_system_btree_key_common_t *) btree_entry->key_data )->file_system_identifier,
2872
0
     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
0
    if( ( file_system_identifier & 0x0fffffffffffffffUL ) > parent_identifier )
2890
0
    {
2891
0
      break;
2892
0
    }
2893
0
    if( file_system_identifier != lookup_identifier )
2894
0
    {
2895
0
      continue;
2896
0
    }
2897
0
    if( libfsapfs_directory_record_initialize(
2898
0
         &directory_record,
2899
0
         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
0
    if( libfsapfs_directory_record_read_key_data(
2911
0
         directory_record,
2912
0
         btree_entry->key_data,
2913
0
         (size_t) btree_entry->key_data_size,
2914
0
         error ) != 1 )
2915
0
    {
2916
0
      libcerror_error_set(
2917
0
       error,
2918
0
       LIBCERROR_ERROR_DOMAIN_IO,
2919
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2920
0
       "%s: unable to read directory record key data.",
2921
0
       function );
2922
2923
0
      goto on_error;
2924
0
    }
2925
0
    if( libfsapfs_directory_record_read_value_data(
2926
0
         directory_record,
2927
0
         btree_entry->value_data,
2928
0
         (size_t) btree_entry->value_data_size,
2929
0
         error ) != 1 )
2930
0
    {
2931
0
      libcerror_error_set(
2932
0
       error,
2933
0
       LIBCERROR_ERROR_DOMAIN_IO,
2934
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2935
0
       "%s: unable to read directory record value data.",
2936
0
       function );
2937
2938
0
      goto on_error;
2939
0
    }
2940
0
    if( libcdata_array_append_entry(
2941
0
         directory_entries,
2942
0
         &entry_index,
2943
0
         (intptr_t *) directory_record,
2944
0
         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
0
    directory_record = NULL;
2956
2957
0
    found_directory_entry = 1;
2958
0
  }
2959
0
  return( found_directory_entry );
2960
2961
0
on_error:
2962
0
  if( directory_record != NULL )
2963
0
  {
2964
0
    libfsapfs_directory_record_free(
2965
0
     &directory_record,
2966
0
     NULL );
2967
0
  }
2968
0
  libcdata_array_empty(
2969
0
   directory_entries,
2970
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
2971
0
   NULL );
2972
2973
0
  return( -1 );
2974
0
}
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
0
{
3370
0
  libfsapfs_btree_node_t *root_node = NULL;
3371
0
  static char *function             = "libfsapfs_file_system_btree_get_directory_entries";
3372
0
  int is_leaf_node                  = 0;
3373
0
  int result                        = 0;
3374
3375
#if defined( HAVE_PROFILER )
3376
  int64_t profiler_start_timestamp  = 0;
3377
#endif
3378
3379
0
  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
0
  result = libfsapfs_file_system_btree_get_root_node(
3421
0
            file_system_btree,
3422
0
            file_io_handle,
3423
0
            file_system_btree->root_node_block_number,
3424
0
            &root_node,
3425
0
            error );
3426
3427
0
  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
0
  else if( result == 0 )
3439
0
  {
3440
0
    return( 0 );
3441
0
  }
3442
0
  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
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3454
0
                  root_node,
3455
0
                  error );
3456
3457
0
  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
0
  if( is_leaf_node != 0 )
3469
0
  {
3470
0
    result = libfsapfs_file_system_btree_get_directory_entries_from_leaf_node(
3471
0
              file_system_btree,
3472
0
              root_node,
3473
0
              parent_identifier,
3474
0
              directory_entries,
3475
0
              error );
3476
0
  }
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
0
  if( result == -1 )
3490
0
  {
3491
0
    libcerror_error_set(
3492
0
     error,
3493
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3494
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3495
0
     "%s: unable to retrieve directory entries: %" PRIu64 " from file system B-tree root node.",
3496
0
     function,
3497
0
     parent_identifier );
3498
3499
0
    goto on_error;
3500
0
  }
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
0
  return( result );
3525
3526
0
on_error:
3527
0
  libcdata_array_empty(
3528
0
   directory_entries,
3529
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
3530
0
   NULL );
3531
3532
0
  return( -1 );
3533
0
}
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
264
{
3545
264
  libfsapfs_attribute_values_t *attribute_values = NULL;
3546
264
  libfsapfs_btree_entry_t *btree_entry           = NULL;
3547
264
  static char *function                          = "libfsapfs_file_system_btree_get_attributes_from_leaf_node";
3548
264
  uint64_t file_system_identifier                = 0;
3549
264
  uint64_t lookup_identifier                     = 0;
3550
264
  int btree_entry_index                          = 0;
3551
264
  int entry_index                                = 0;
3552
264
  int found_attribute                            = 0;
3553
264
  int is_leaf_node                               = 0;
3554
264
  int number_of_entries                          = 0;
3555
3556
#if defined( HAVE_DEBUG_OUTPUT )
3557
  uint8_t file_system_data_type                  = 0;
3558
#endif
3559
3560
264
  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
264
  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
264
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
3583
264
                  node,
3584
264
                  error );
3585
3586
264
  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
264
  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
264
  if( libfsapfs_btree_node_get_number_of_entries(
3618
264
       node,
3619
264
       &number_of_entries,
3620
264
       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
264
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_EXTENDED_ATTRIBUTE << 60 ) | identifier;
3632
3633
264
  for( btree_entry_index = 0;
3634
5.91k
       btree_entry_index < number_of_entries;
3635
5.64k
       btree_entry_index++ )
3636
5.82k
  {
3637
5.82k
    if( libfsapfs_btree_node_get_entry_by_index(
3638
5.82k
         node,
3639
5.82k
         btree_entry_index,
3640
5.82k
         &btree_entry,
3641
5.82k
         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
5.82k
    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
5.82k
    if( btree_entry->key_data == NULL )
3665
4
    {
3666
4
      libcerror_error_set(
3667
4
       error,
3668
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3669
4
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3670
4
       "%s: invalid B-tree entry: %d - missing key data.",
3671
4
       function,
3672
4
       btree_entry_index );
3673
3674
4
      goto on_error;
3675
4
    }
3676
5.82k
    if( btree_entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
3677
5
    {
3678
5
      libcerror_error_set(
3679
5
       error,
3680
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3681
5
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3682
5
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
3683
5
       function,
3684
5
       btree_entry_index );
3685
3686
5
      goto on_error;
3687
5
    }
3688
5.81k
    byte_stream_copy_to_uint64_little_endian(
3689
5.81k
     ( (fsapfs_file_system_btree_key_common_t *) btree_entry->key_data )->file_system_identifier,
3690
5.81k
     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
5.81k
    if( ( file_system_identifier & 0x0fffffffffffffffUL ) > identifier )
3708
99
    {
3709
99
      break;
3710
99
    }
3711
5.71k
    if( file_system_identifier != lookup_identifier )
3712
5.38k
    {
3713
5.38k
      continue;
3714
5.38k
    }
3715
335
    if( libfsapfs_attribute_values_initialize(
3716
335
         &attribute_values,
3717
335
         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
335
    if( libfsapfs_attribute_values_read_key_data(
3729
335
         attribute_values,
3730
335
         btree_entry->key_data,
3731
335
         (size_t) btree_entry->key_data_size,
3732
335
         error ) != 1 )
3733
30
    {
3734
30
      libcerror_error_set(
3735
30
       error,
3736
30
       LIBCERROR_ERROR_DOMAIN_IO,
3737
30
       LIBCERROR_IO_ERROR_READ_FAILED,
3738
30
       "%s: unable to read attribute values key data.",
3739
30
       function );
3740
3741
30
      goto on_error;
3742
30
    }
3743
305
    if( libfsapfs_attribute_values_read_value_data(
3744
305
         attribute_values,
3745
305
         btree_entry->value_data,
3746
305
         (size_t) btree_entry->value_data_size,
3747
305
         error ) != 1 )
3748
40
    {
3749
40
      libcerror_error_set(
3750
40
       error,
3751
40
       LIBCERROR_ERROR_DOMAIN_IO,
3752
40
       LIBCERROR_IO_ERROR_READ_FAILED,
3753
40
       "%s: unable to read attribute values value data.",
3754
40
       function );
3755
3756
40
      goto on_error;
3757
40
    }
3758
265
    if( libcdata_array_append_entry(
3759
265
         extended_attributes_array,
3760
265
         &entry_index,
3761
265
         (intptr_t *) attribute_values,
3762
265
         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
265
    attribute_values = NULL;
3774
3775
265
    found_attribute = 1;
3776
265
  }
3777
185
  return( found_attribute );
3778
3779
79
on_error:
3780
79
  if( attribute_values != NULL )
3781
70
  {
3782
70
    libfsapfs_attribute_values_free(
3783
70
     &attribute_values,
3784
70
     NULL );
3785
70
  }
3786
79
  libcdata_array_empty(
3787
79
   extended_attributes_array,
3788
79
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_attribute_values_free,
3789
79
   NULL );
3790
3791
79
  return( -1 );
3792
264
}
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
264
{
4188
264
  libfsapfs_btree_node_t *root_node = NULL;
4189
264
  static char *function             = "libfsapfs_file_system_btree_get_attributes";
4190
264
  int is_leaf_node                  = 0;
4191
264
  int result                        = 0;
4192
4193
#if defined( HAVE_PROFILER )
4194
  int64_t profiler_start_timestamp  = 0;
4195
#endif
4196
4197
264
  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
264
  result = libfsapfs_file_system_btree_get_root_node(
4239
264
            file_system_btree,
4240
264
            file_io_handle,
4241
264
            file_system_btree->root_node_block_number,
4242
264
            &root_node,
4243
264
            error );
4244
4245
264
  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
264
  else if( result == 0 )
4257
0
  {
4258
0
    return( 0 );
4259
0
  }
4260
264
  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
264
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4272
264
                  root_node,
4273
264
                  error );
4274
4275
264
  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
264
  if( is_leaf_node != 0 )
4287
264
  {
4288
264
    result = libfsapfs_file_system_btree_get_attributes_from_leaf_node(
4289
264
              file_system_btree,
4290
264
              root_node,
4291
264
              identifier,
4292
264
              extended_attributes_array,
4293
264
              error );
4294
264
  }
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
264
  if( result == -1 )
4308
79
  {
4309
79
    libcerror_error_set(
4310
79
     error,
4311
79
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4312
79
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4313
79
     "%s: unable to retrieve attributes: %" PRIu64 " from file system B-tree root node.",
4314
79
     function,
4315
79
     identifier );
4316
4317
79
    goto on_error;
4318
79
  }
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
185
  return( result );
4343
4344
79
on_error:
4345
79
  libcdata_array_empty(
4346
79
   extended_attributes_array,
4347
79
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_attribute_values_free,
4348
79
   NULL );
4349
4350
79
  return( -1 );
4351
264
}
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
0
{
4363
0
  libfsapfs_btree_entry_t *btree_entry = NULL;
4364
0
  libfsapfs_file_extent_t *file_extent = NULL;
4365
0
  static char *function                = "libfsapfs_file_system_btree_get_file_extents_from_leaf_node";
4366
0
  uint64_t file_system_identifier      = 0;
4367
0
  uint64_t lookup_identifier           = 0;
4368
0
  int btree_entry_index                = 0;
4369
0
  int entry_index                      = 0;
4370
0
  int found_file_extent                = 0;
4371
0
  int is_leaf_node                     = 0;
4372
0
  int number_of_entries                = 0;
4373
4374
#if defined( HAVE_DEBUG_OUTPUT )
4375
  uint8_t file_system_data_type        = 0;
4376
#endif
4377
4378
0
  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
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
4390
0
                  node,
4391
0
                  error );
4392
4393
0
  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
0
  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
0
  if( libfsapfs_btree_node_get_number_of_entries(
4425
0
       node,
4426
0
       &number_of_entries,
4427
0
       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
0
  lookup_identifier = ( (uint64_t) LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_FILE_EXTENT << 60 ) | identifier;
4439
4440
0
  for( btree_entry_index = 0;
4441
0
       btree_entry_index < number_of_entries;
4442
0
       btree_entry_index++ )
4443
0
  {
4444
0
    if( libfsapfs_btree_node_get_entry_by_index(
4445
0
         node,
4446
0
         btree_entry_index,
4447
0
         &btree_entry,
4448
0
         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
0
    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
0
    if( btree_entry->key_data == NULL )
4472
0
    {
4473
0
      libcerror_error_set(
4474
0
       error,
4475
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4476
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4477
0
       "%s: invalid B-tree entry: %d - missing key data.",
4478
0
       function,
4479
0
       btree_entry_index );
4480
4481
0
      goto on_error;
4482
0
    }
4483
0
    if( btree_entry->key_data_size < sizeof( fsapfs_file_system_btree_key_common_t ) )
4484
0
    {
4485
0
      libcerror_error_set(
4486
0
       error,
4487
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4488
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
4489
0
       "%s: invalid B-tree entry: %d - key data size value out of bounds.",
4490
0
       function,
4491
0
       btree_entry_index );
4492
4493
0
      goto on_error;
4494
0
    }
4495
0
    byte_stream_copy_to_uint64_little_endian(
4496
0
     ( (fsapfs_file_system_btree_key_common_t *) btree_entry->key_data )->file_system_identifier,
4497
0
     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
0
    if( ( file_system_identifier & 0x0fffffffffffffffUL ) > identifier )
4515
0
    {
4516
0
      break;
4517
0
    }
4518
0
    if( file_system_identifier != lookup_identifier )
4519
0
    {
4520
0
      continue;
4521
0
    }
4522
0
    if( libfsapfs_file_extent_initialize(
4523
0
         &file_extent,
4524
0
         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
0
    if( libfsapfs_file_extent_read_key_data(
4536
0
         file_extent,
4537
0
         btree_entry->key_data,
4538
0
         (size_t) btree_entry->key_data_size,
4539
0
         error ) != 1 )
4540
0
    {
4541
0
      libcerror_error_set(
4542
0
       error,
4543
0
       LIBCERROR_ERROR_DOMAIN_IO,
4544
0
       LIBCERROR_IO_ERROR_READ_FAILED,
4545
0
       "%s: unable to read file extent key data.",
4546
0
       function );
4547
4548
0
      goto on_error;
4549
0
    }
4550
0
    if( libfsapfs_file_extent_read_value_data(
4551
0
         file_extent,
4552
0
         btree_entry->value_data,
4553
0
         (size_t) btree_entry->value_data_size,
4554
0
         error ) != 1 )
4555
0
    {
4556
0
      libcerror_error_set(
4557
0
       error,
4558
0
       LIBCERROR_ERROR_DOMAIN_IO,
4559
0
       LIBCERROR_IO_ERROR_READ_FAILED,
4560
0
       "%s: unable to read file extent value data.",
4561
0
       function );
4562
4563
0
      goto on_error;
4564
0
    }
4565
0
    if( libcdata_array_append_entry(
4566
0
         file_extents,
4567
0
         &entry_index,
4568
0
         (intptr_t *) file_extent,
4569
0
         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
0
    file_extent = NULL;
4581
4582
0
    found_file_extent = 1;
4583
0
  }
4584
0
  return( found_file_extent );
4585
4586
0
on_error:
4587
0
  if( file_extent != NULL )
4588
0
  {
4589
0
    libfsapfs_file_extent_free(
4590
0
     &file_extent,
4591
0
     NULL );
4592
0
  }
4593
0
  libcdata_array_empty(
4594
0
   file_extents,
4595
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
4596
0
   NULL );
4597
4598
0
  return( -1 );
4599
0
}
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
0
{
5022
0
  libfsapfs_btree_node_t *root_node = NULL;
5023
0
  static char *function             = "libfsapfs_file_system_btree_get_file_extents";
5024
0
  int is_leaf_node                  = 0;
5025
0
  int result                        = 0;
5026
5027
0
  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
0
  result = libfsapfs_file_system_btree_get_root_node(
5049
0
            file_system_btree,
5050
0
            file_io_handle,
5051
0
            file_system_btree->root_node_block_number,
5052
0
            &root_node,
5053
0
            error );
5054
5055
0
  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
0
  else if( result == 0 )
5067
0
  {
5068
0
    return( 0 );
5069
0
  }
5070
0
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
5071
0
                  root_node,
5072
0
                  error );
5073
5074
0
  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
0
  if( is_leaf_node != 0 )
5086
0
  {
5087
0
    result = libfsapfs_file_system_btree_get_file_extents_from_leaf_node(
5088
0
              file_system_btree,
5089
0
              root_node,
5090
0
              identifier,
5091
0
              file_extents,
5092
0
              error );
5093
0
  }
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
0
  if( result == -1 )
5107
0
  {
5108
0
    libcerror_error_set(
5109
0
     error,
5110
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5111
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5112
0
     "%s: unable to retrieve file extents: %" PRIu64 " from file system B-tree root node.",
5113
0
     function,
5114
0
     identifier );
5115
5116
0
    goto on_error;
5117
0
  }
5118
0
  return( result );
5119
5120
0
on_error:
5121
0
  libcdata_array_empty(
5122
0
   file_extents,
5123
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
5124
0
   NULL );
5125
5126
0
  return( -1 );
5127
0
}
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
0
{
5140
0
  libfsapfs_btree_entry_t *btree_entry = NULL;
5141
0
  libfsapfs_btree_node_t *btree_node   = NULL;
5142
0
  libfsapfs_inode_t *safe_inode        = NULL;
5143
0
  static char *function                = "libfsapfs_file_system_btree_get_inode_by_identifier";
5144
0
  int result                           = 0;
5145
5146
#if defined( HAVE_PROFILER )
5147
  int64_t profiler_start_timestamp     = 0;
5148
#endif
5149
5150
0
  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
0
  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
0
  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
0
  result = libfsapfs_file_system_btree_get_entry_by_identifier(
5214
0
            file_system_btree,
5215
0
            file_io_handle,
5216
0
            identifier,
5217
0
            LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_INODE,
5218
0
            transaction_identifier,
5219
0
            &btree_node,
5220
0
            &btree_entry,
5221
0
            error );
5222
5223
0
  if( result == -1 )
5224
0
  {
5225
0
    libcerror_error_set(
5226
0
     error,
5227
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5228
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5229
0
     "%s: unable to retrieve entry from B-tree node.",
5230
0
     function );
5231
5232
0
    goto on_error;
5233
0
  }
5234
0
  else if( result != 0 )
5235
0
  {
5236
0
    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
0
    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
0
    if( libfsapfs_inode_initialize(
5259
0
         &safe_inode,
5260
0
         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
0
    if( libfsapfs_inode_read_key_data(
5272
0
         safe_inode,
5273
0
         btree_entry->key_data,
5274
0
         (size_t) btree_entry->key_data_size,
5275
0
         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
0
    if( libfsapfs_inode_read_value_data(
5287
0
         safe_inode,
5288
0
         btree_entry->value_data,
5289
0
         (size_t) btree_entry->value_data_size,
5290
0
         error ) != 1 )
5291
0
    {
5292
0
      libcerror_error_set(
5293
0
       error,
5294
0
       LIBCERROR_ERROR_DOMAIN_IO,
5295
0
       LIBCERROR_IO_ERROR_READ_FAILED,
5296
0
       "%s: unable to read inode value data.",
5297
0
       function );
5298
5299
0
      goto on_error;
5300
0
    }
5301
0
    btree_node = NULL;
5302
0
  }
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
0
  *inode = safe_inode;
5327
5328
0
  return( result );
5329
5330
0
on_error:
5331
0
  if( safe_inode != NULL )
5332
0
  {
5333
0
    libfsapfs_inode_free(
5334
0
     &safe_inode,
5335
0
     NULL );
5336
0
  }
5337
0
  return( -1 );
5338
0
}
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.24k
{
5672
1.24k
  libfsapfs_btree_entry_t *btree_entry                = NULL;
5673
1.24k
  libfsapfs_btree_node_t *btree_node                  = NULL;
5674
1.24k
  libfsapfs_btree_node_t *root_node                   = NULL;
5675
1.24k
  libfsapfs_directory_record_t *safe_directory_record = NULL;
5676
1.24k
  const uint8_t *utf8_string_segment                  = NULL;
5677
1.24k
  static char *function                               = "libfsapfs_file_system_btree_get_inode_by_utf8_path";
5678
1.24k
  libuna_unicode_character_t unicode_character        = 0;
5679
1.24k
  size_t utf8_string_index                            = 0;
5680
1.24k
  size_t utf8_string_segment_length                   = 0;
5681
1.24k
  uint64_t lookup_identifier                          = 0;
5682
1.24k
  uint32_t name_hash                                  = 0;
5683
1.24k
  int is_leaf_node                                    = 0;
5684
1.24k
  int result                                          = 0;
5685
5686
1.24k
  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.24k
  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.24k
  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.24k
  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.24k
  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.24k
  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.24k
  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.24k
  result = libfsapfs_file_system_btree_get_root_node(
5764
1.24k
            file_system_btree,
5765
1.24k
            file_io_handle,
5766
1.24k
            file_system_btree->root_node_block_number,
5767
1.24k
            &root_node,
5768
1.24k
            error );
5769
5770
1.24k
  if( result == -1 )
5771
250
  {
5772
250
    libcerror_error_set(
5773
250
     error,
5774
250
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5775
250
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5776
250
     "%s: unable to retrieve B-tree root node.",
5777
250
     function );
5778
5779
250
    goto on_error;
5780
250
  }
5781
993
  else if( result == 0 )
5782
1
  {
5783
1
    return( 0 );
5784
1
  }
5785
992
  is_leaf_node = libfsapfs_btree_node_is_leaf_node(
5786
992
                  root_node,
5787
992
                  error );
5788
5789
992
  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
992
  lookup_identifier = parent_identifier;
5801
5802
992
  if( utf8_string_length > 0 )
5803
992
  {
5804
    /* Ignore a leading separator
5805
     */
5806
992
    if( utf8_string[ utf8_string_index ] == (uint8_t) LIBFSAPFS_SEPARATOR )
5807
992
    {
5808
992
      utf8_string_index++;
5809
992
    }
5810
992
  }
5811
992
  if( ( utf8_string_length == 0 )
5812
992
   || ( utf8_string_length == 1 ) )
5813
0
  {
5814
0
    result = 1;
5815
0
  }
5816
1.82k
  else while( utf8_string_index < utf8_string_length )
5817
1.45k
  {
5818
1.45k
    utf8_string_segment        = &( utf8_string[ utf8_string_index ] );
5819
1.45k
    utf8_string_segment_length = utf8_string_index;
5820
5821
15.1k
    while( utf8_string_index < utf8_string_length )
5822
14.6k
    {
5823
14.6k
      if( libuna_unicode_character_copy_from_utf8(
5824
14.6k
           &unicode_character,
5825
14.6k
           utf8_string,
5826
14.6k
           utf8_string_length,
5827
14.6k
           &utf8_string_index,
5828
14.6k
           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
14.6k
      if( ( unicode_character == (libuna_unicode_character_t) LIBFSAPFS_SEPARATOR )
5840
13.6k
       || ( unicode_character == 0 ) )
5841
992
      {
5842
992
        utf8_string_segment_length += 1;
5843
5844
992
        break;
5845
992
      }
5846
14.6k
    }
5847
1.45k
    utf8_string_segment_length = utf8_string_index - utf8_string_segment_length;
5848
5849
1.45k
    if( utf8_string_segment_length == 0 )
5850
0
    {
5851
0
      result = 0;
5852
0
    }
5853
1.45k
    else
5854
1.45k
    {
5855
1.45k
      if( libfsapfs_name_hash_calculate_from_utf8_string(
5856
1.45k
           &name_hash,
5857
1.45k
           utf8_string_segment,
5858
1.45k
           utf8_string_segment_length,
5859
1.45k
           file_system_btree->use_case_folding,
5860
1.45k
           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.45k
      if( safe_directory_record != NULL )
5872
460
      {
5873
460
        if( libfsapfs_directory_record_free(
5874
460
             &safe_directory_record,
5875
460
             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
460
      }
5887
1.45k
      if( is_leaf_node != 0 )
5888
1.21k
      {
5889
1.21k
        result = libfsapfs_file_system_btree_get_directory_record_from_leaf_node_by_utf8_name(
5890
1.21k
            file_system_btree,
5891
1.21k
            root_node,
5892
1.21k
            lookup_identifier,
5893
1.21k
            utf8_string_segment,
5894
1.21k
            utf8_string_segment_length,
5895
1.21k
                  name_hash,
5896
1.21k
            &safe_directory_record,
5897
1.21k
            error );
5898
1.21k
      }
5899
233
      else
5900
233
      {
5901
233
        result = libfsapfs_file_system_btree_get_directory_record_from_branch_node_by_utf8_name(
5902
233
            file_system_btree,
5903
233
            file_io_handle,
5904
233
            root_node,
5905
233
            lookup_identifier,
5906
233
            utf8_string_segment,
5907
233
            utf8_string_segment_length,
5908
233
                  name_hash,
5909
233
                  transaction_identifier,
5910
233
            &safe_directory_record,
5911
233
            0,
5912
233
            error );
5913
233
      }
5914
1.45k
    }
5915
1.45k
    if( result == -1 )
5916
436
    {
5917
436
      libcerror_error_set(
5918
436
       error,
5919
436
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5920
436
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5921
436
       "%s: unable to retrieve directory entry by name.",
5922
436
       function );
5923
5924
436
      goto on_error;
5925
436
    }
5926
1.01k
    else if( result == 0 )
5927
183
    {
5928
183
      break;
5929
183
    }
5930
833
    if( libfsapfs_directory_record_get_identifier(
5931
833
         safe_directory_record,
5932
833
         &lookup_identifier,
5933
833
         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
833
  }
5945
556
  root_node = NULL;
5946
5947
556
  if( result != 0 )
5948
373
  {
5949
373
    result = libfsapfs_file_system_btree_get_entry_by_identifier(
5950
373
              file_system_btree,
5951
373
              file_io_handle,
5952
373
              lookup_identifier,
5953
373
              LIBFSAPFS_FILE_SYSTEM_DATA_TYPE_INODE,
5954
373
              transaction_identifier,
5955
373
              &btree_node,
5956
373
              &btree_entry,
5957
373
              error );
5958
5959
373
    if( result != 1 )
5960
38
    {
5961
38
      libcerror_error_set(
5962
38
       error,
5963
38
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5964
38
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5965
38
       "%s: unable to retrieve entry from B-tree node.",
5966
38
       function );
5967
5968
38
      goto on_error;
5969
38
    }
5970
335
    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
335
    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
335
    if( libfsapfs_inode_initialize(
5993
335
         inode,
5994
335
         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
335
    if( libfsapfs_inode_read_key_data(
6006
335
         *inode,
6007
335
         btree_entry->key_data,
6008
335
         (size_t) btree_entry->key_data_size,
6009
335
         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
335
    if( libfsapfs_inode_read_value_data(
6021
335
         *inode,
6022
335
         btree_entry->value_data,
6023
335
         (size_t) btree_entry->value_data_size,
6024
335
         error ) != 1 )
6025
71
    {
6026
71
      libcerror_error_set(
6027
71
       error,
6028
71
       LIBCERROR_ERROR_DOMAIN_IO,
6029
71
       LIBCERROR_IO_ERROR_READ_FAILED,
6030
71
       "%s: unable to read inode value data.",
6031
71
       function );
6032
6033
71
      goto on_error;
6034
71
    }
6035
264
    btree_node = NULL;
6036
6037
264
    *directory_record = safe_directory_record;
6038
264
  }
6039
447
  return( result );
6040
6041
795
on_error:
6042
795
  if( safe_directory_record != NULL )
6043
109
  {
6044
109
    libfsapfs_directory_record_free(
6045
109
     &safe_directory_record,
6046
109
     NULL );
6047
109
  }
6048
795
  if( *inode != NULL )
6049
71
  {
6050
71
    libfsapfs_inode_free(
6051
71
     inode,
6052
71
     NULL );
6053
71
  }
6054
795
  return( -1 );
6055
556
}
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
     NULL );
6770
0
  }
6771
0
  return( -1 );
6772
0
}
6773