Coverage Report

Created: 2025-10-14 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfshfs/libfshfs/libfshfs_attributes_btree_file.c
Line
Count
Source
1
/*
2
 * The attributes B-tree file functions
3
 *
4
 * Copyright (C) 2009-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <types.h>
25
26
#include "libfshfs_attribute_record.h"
27
#include "libfshfs_attributes_btree_file.h"
28
#include "libfshfs_attributes_btree_key.h"
29
#include "libfshfs_btree_file.h"
30
#include "libfshfs_btree_node_cache.h"
31
#include "libfshfs_definitions.h"
32
#include "libfshfs_file_record.h"
33
#include "libfshfs_libbfio.h"
34
#include "libfshfs_libcdata.h"
35
#include "libfshfs_libcerror.h"
36
#include "libfshfs_libcnotify.h"
37
38
#include "fshfs_attributes_file.h"
39
40
/* Retrieves the attributes B-tree key from a specific B-tree node record
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libfshfs_attributes_btree_file_get_key_from_node_by_index(
44
     libfshfs_btree_node_t *node,
45
     uint16_t record_index,
46
     libfshfs_attributes_btree_key_t **node_key,
47
     libcerror_error_t **error )
48
11.8k
{
49
11.8k
  libfshfs_attributes_btree_key_t *safe_node_key = NULL;
50
11.8k
  libfshfs_btree_node_record_t *node_record      = NULL;
51
11.8k
  static char *function                          = "libfshfs_attributes_btree_file_get_key_from_node_by_index";
52
53
11.8k
  if( node_key == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid attributes B-tree key.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
11.8k
  if( libfshfs_btree_node_get_record_by_index(
65
11.8k
       node,
66
11.8k
       record_index,
67
11.8k
       &node_record,
68
11.8k
       error ) == -1 )
69
9
  {
70
9
    libcerror_error_set(
71
9
     error,
72
9
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
9
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
74
9
     "%s: unable to retrieve node record: %" PRIu16 ".",
75
9
     function,
76
9
     record_index );
77
78
9
    goto on_error;
79
9
  }
80
11.8k
  if( node_record == NULL )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
85
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
86
0
     "%s: missing B-tree node record: %" PRIu16 ".",
87
0
     function,
88
0
     record_index );
89
90
0
    goto on_error;
91
0
  }
92
11.8k
  if( node_record->key_value == NULL )
93
6.69k
  {
94
6.69k
    if( libfshfs_attributes_btree_key_initialize(
95
6.69k
         &safe_node_key,
96
6.69k
         error ) != 1 )
97
0
    {
98
0
      libcerror_error_set(
99
0
       error,
100
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
101
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
102
0
       "%s: unable to create attributes B-tree key.",
103
0
       function );
104
105
0
      goto on_error;
106
0
    }
107
6.69k
    if( libfshfs_attributes_btree_key_read_data(
108
6.69k
         safe_node_key,
109
6.69k
         node_record->data,
110
6.69k
         node_record->data_size,
111
6.69k
         error ) != 1 )
112
87
    {
113
87
      libcerror_error_set(
114
87
       error,
115
87
       LIBCERROR_ERROR_DOMAIN_IO,
116
87
       LIBCERROR_IO_ERROR_READ_FAILED,
117
87
       "%s: unable to read attributes B-tree key.",
118
87
       function );
119
120
87
      goto on_error;
121
87
    }
122
6.60k
    node_record->key_value               = (intptr_t *) safe_node_key;
123
6.60k
    node_record->key_value_free_function = (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attributes_btree_key_free;
124
6.60k
  }
125
11.7k
  *node_key = (libfshfs_attributes_btree_key_t *) node_record->key_value;
126
127
11.7k
  return( 1 );
128
129
96
on_error:
130
96
  if( safe_node_key != NULL )
131
87
  {
132
87
    libfshfs_attributes_btree_key_free(
133
87
     &safe_node_key,
134
87
     NULL );
135
87
  }
136
96
  return( -1 );
137
11.8k
}
138
139
/* Retrieves a sub node number for from the attributes B-tree key
140
 * Returns 1 if successful or -1 on error
141
 */
142
int libfshfs_attributes_btree_file_get_sub_node_number_from_key(
143
     libfshfs_attributes_btree_key_t *node_key,
144
     uint32_t *sub_node_number,
145
     libcerror_error_t **error )
146
4.69k
{
147
4.69k
  static char *function = "libfshfs_attributes_btree_file_get_sub_node_number_from_key";
148
149
4.69k
  if( node_key == NULL )
150
0
  {
151
0
    libcerror_error_set(
152
0
     error,
153
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
154
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
155
0
     "%s: invalid attributes B-tree key.",
156
0
     function );
157
158
0
    return( -1 );
159
0
  }
160
4.69k
  if( node_key->record_data == NULL )
161
0
  {
162
0
    libcerror_error_set(
163
0
     error,
164
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
165
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
166
0
     "%s: invalid attributes B-tree key - missing record data.",
167
0
     function );
168
169
0
    return( -1 );
170
0
  }
171
4.69k
  if( node_key->record_data_size < 4 )
172
5
  {
173
5
    libcerror_error_set(
174
5
     error,
175
5
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
176
5
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
177
5
     "%s: invalid attributes B-tree key - record data size value out of bounds.",
178
5
     function );
179
180
5
    return( -1 );
181
5
  }
182
4.68k
  if( sub_node_number == 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 sub node number.",
189
0
     function );
190
191
0
    return( -1 );
192
0
  }
193
4.68k
  byte_stream_copy_to_uint32_big_endian(
194
4.68k
   node_key->record_data,
195
4.68k
   *sub_node_number );
196
197
4.68k
  return( 1 );
198
4.68k
}
199
200
/* Retrieves an attribute for from the attributes B-tree record data
201
 * Returns 1 if successful or -1 on error
202
 */
203
int libfshfs_attributes_btree_file_get_attribute_from_record_data(
204
     libfshfs_btree_file_t *btree_file,
205
     libfshfs_attributes_btree_key_t *node_key,
206
     libfshfs_attribute_record_t **attribute_record,
207
     libcerror_error_t **error )
208
1.30k
{
209
1.30k
  libfshfs_attribute_record_t *safe_attribute_record = NULL;
210
1.30k
  static char *function                              = "libfshfs_attributes_btree_file_get_attribute_from_record_data";
211
212
1.30k
  if( btree_file == NULL )
213
0
  {
214
0
    libcerror_error_set(
215
0
     error,
216
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
217
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
218
0
     "%s: invalid B-tree file.",
219
0
     function );
220
221
0
    return( -1 );
222
0
  }
223
1.30k
  if( node_key == NULL )
224
0
  {
225
0
    libcerror_error_set(
226
0
     error,
227
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
228
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
229
0
     "%s: invalid attributes B-tree key.",
230
0
     function );
231
232
0
    return( -1 );
233
0
  }
234
1.30k
  if( attribute_record == NULL )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
240
0
     "%s: invalid attribute record.",
241
0
     function );
242
243
0
    return( -1 );
244
0
  }
245
1.30k
  if( *attribute_record != NULL )
246
0
  {
247
0
    libcerror_error_set(
248
0
     error,
249
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
251
0
     "%s: invalid attribute record value already set.",
252
0
     function );
253
254
0
    return( -1 );
255
0
  }
256
1.30k
  if( libfshfs_attribute_record_initialize(
257
1.30k
       &safe_attribute_record,
258
1.30k
       error ) != 1 )
259
0
  {
260
0
    libcerror_error_set(
261
0
     error,
262
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
263
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
264
0
     "%s: unable to create attribute record.",
265
0
     function );
266
267
0
    goto on_error;
268
0
  }
269
1.30k
  if( libfshfs_attribute_record_set_name(
270
1.30k
       safe_attribute_record,
271
1.30k
       node_key->name_data,
272
1.30k
       node_key->name_size,
273
1.30k
       error ) != 1 )
274
13
  {
275
13
    libcerror_error_set(
276
13
     error,
277
13
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
278
13
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
279
13
     "%s: unable to set name of attribute record.",
280
13
     function );
281
282
13
    goto on_error;
283
13
  }
284
1.29k
  if( libfshfs_attribute_record_read_data(
285
1.29k
       safe_attribute_record,
286
1.29k
       node_key->record_data,
287
1.29k
       node_key->record_data_size,
288
1.29k
       error ) != 1 )
289
178
  {
290
178
    libcerror_error_set(
291
178
     error,
292
178
     LIBCERROR_ERROR_DOMAIN_IO,
293
178
     LIBCERROR_IO_ERROR_READ_FAILED,
294
178
     "%s: unable to read attribute record.",
295
178
     function );
296
297
178
    goto on_error;
298
178
  }
299
1.11k
  *attribute_record = safe_attribute_record;
300
301
1.11k
  return( 1 );
302
303
191
on_error:
304
191
  if( safe_attribute_record != NULL )
305
191
  {
306
191
    libfshfs_attribute_record_free(
307
191
     &safe_attribute_record,
308
191
     NULL );
309
191
  }
310
191
  return( -1 );
311
1.29k
}
312
313
/* Retrieves the attributes for a specific parent identifier from the attributes B-tree leaf node
314
 * Returns 1 if successful or -1 on error
315
 */
316
int libfshfs_attributes_btree_file_get_attributes_from_leaf_node(
317
     libfshfs_btree_file_t *btree_file,
318
     libfshfs_btree_node_t *node,
319
     uint32_t identifier,
320
     libcdata_array_t *attributes,
321
     libcerror_error_t **error )
322
3.09k
{
323
3.09k
  libfshfs_attribute_record_t *attribute_record = NULL;
324
3.09k
  libfshfs_attributes_btree_key_t *node_key     = NULL;
325
3.09k
  static char *function                         = "libfshfs_attributes_btree_file_get_attributes_from_leaf_node";
326
3.09k
  uint16_t record_index                         = 0;
327
3.09k
  int entry_index                               = 0;
328
3.09k
  int is_leaf_node                              = 0;
329
330
3.09k
  if( btree_file == NULL )
331
0
  {
332
0
    libcerror_error_set(
333
0
     error,
334
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
335
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
336
0
     "%s: invalid B-tree file.",
337
0
     function );
338
339
0
    return( -1 );
340
0
  }
341
3.09k
  if( node == NULL )
342
0
  {
343
0
    libcerror_error_set(
344
0
     error,
345
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
346
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
347
0
     "%s: invalid B-tree node.",
348
0
     function );
349
350
0
    return( -1 );
351
0
  }
352
3.09k
  if( node->descriptor == NULL )
353
0
  {
354
0
    libcerror_error_set(
355
0
     error,
356
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
357
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
358
0
     "%s: invalid B-tree node - missing descriptor.",
359
0
     function );
360
361
0
    return( -1 );
362
0
  }
363
3.09k
  is_leaf_node = libfshfs_btree_node_is_leaf_node(
364
3.09k
                  node,
365
3.09k
                  error );
366
367
3.09k
  if( is_leaf_node == -1 )
368
0
  {
369
0
    libcerror_error_set(
370
0
     error,
371
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
372
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
373
0
     "%s: unable to determine if B-tree node is a leaf node.",
374
0
     function );
375
376
0
    goto on_error;
377
0
  }
378
3.09k
  else if( is_leaf_node == 0 )
379
0
  {
380
0
    libcerror_error_set(
381
0
     error,
382
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
383
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
384
0
     "%s: invalid node - not a leaf node.",
385
0
     function );
386
387
0
    goto on_error;
388
0
  }
389
3.09k
  for( record_index = 0;
390
6.01k
       record_index < node->descriptor->number_of_records;
391
3.09k
       record_index++ )
392
5.39k
  {
393
5.39k
    if( libfshfs_attributes_btree_file_get_key_from_node_by_index(
394
5.39k
         node,
395
5.39k
         record_index,
396
5.39k
         &node_key,
397
5.39k
         error ) == -1 )
398
67
    {
399
67
      libcerror_error_set(
400
67
       error,
401
67
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
402
67
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
403
67
       "%s: unable to retrieve attributes B-tree key: %" PRIu16 ".",
404
67
       function,
405
67
       record_index );
406
407
67
      goto on_error;
408
67
    }
409
5.33k
    if( node_key == NULL )
410
0
    {
411
0
      libcerror_error_set(
412
0
       error,
413
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
414
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
415
0
       "%s: missing attributes B-tree key: %" PRIu16 ".",
416
0
       function,
417
0
       record_index );
418
419
0
      goto on_error;
420
0
    }
421
5.33k
    if( node_key->identifier == identifier )
422
1.30k
    {
423
1.30k
      if( libfshfs_attributes_btree_file_get_attribute_from_record_data(
424
1.30k
           btree_file,
425
1.30k
           node_key,
426
1.30k
           &attribute_record,
427
1.30k
           error ) != 1 )
428
191
      {
429
191
        libcerror_error_set(
430
191
         error,
431
191
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
432
191
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
433
191
         "%s: unable to retrieve attribute from record data.",
434
191
         function );
435
436
191
        goto on_error;
437
191
      }
438
1.11k
      if( libcdata_array_append_entry(
439
1.11k
           attributes,
440
1.11k
           &entry_index,
441
1.11k
           (intptr_t *) attribute_record,
442
1.11k
           error ) != 1 )
443
0
      {
444
0
        libcerror_error_set(
445
0
         error,
446
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
447
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
448
0
         "%s: unable to append attribute record to array.",
449
0
         function );
450
451
0
        goto on_error;
452
0
      }
453
1.11k
      attribute_record = NULL;
454
1.11k
    }
455
5.13k
    if( node_key->identifier > identifier )
456
2.22k
    {
457
2.22k
      break;
458
2.22k
    }
459
5.13k
  }
460
2.83k
  return( 1 );
461
462
258
on_error:
463
258
  if( attribute_record != NULL )
464
0
  {
465
0
    libfshfs_attribute_record_free(
466
0
     &attribute_record,
467
0
     NULL );
468
0
  }
469
258
  libcdata_array_empty(
470
258
   attributes,
471
258
   (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free,
472
258
   NULL );
473
474
258
  return( -1 );
475
3.09k
}
476
477
/* Retrieves the attributes for a specific parent identifier from the attributes B-tree branch node
478
 * Returns 1 if successful or -1 on error
479
 */
480
int libfshfs_attributes_btree_file_get_attributes_from_branch_node(
481
     libfshfs_btree_file_t *btree_file,
482
     libbfio_handle_t *file_io_handle,
483
     libfshfs_btree_node_cache_t *node_cache,
484
     libfshfs_btree_node_t *node,
485
     uint32_t identifier,
486
     libcdata_array_t *attributes,
487
     int recursion_depth,
488
     libcerror_error_t **error )
489
1.54k
{
490
1.54k
  libfshfs_attributes_btree_key_t *last_node_key = NULL;
491
1.54k
  libfshfs_attributes_btree_key_t *node_key      = NULL;
492
1.54k
  libfshfs_btree_node_t *sub_node                = NULL;
493
1.54k
  static char *function                          = "libfshfs_attributes_btree_file_get_attributes_from_branch_node";
494
1.54k
  uint32_t sub_node_number                       = 0;
495
1.54k
  uint16_t record_index                          = 0;
496
1.54k
  uint8_t node_type                              = 0;
497
1.54k
  int is_branch_node                             = 0;
498
1.54k
  int result                                     = 0;
499
500
1.54k
  if( btree_file == NULL )
501
0
  {
502
0
    libcerror_error_set(
503
0
     error,
504
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
505
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
506
0
     "%s: invalid B-tree file.",
507
0
     function );
508
509
0
    return( -1 );
510
0
  }
511
1.54k
  if( node == NULL )
512
0
  {
513
0
    libcerror_error_set(
514
0
     error,
515
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
516
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
517
0
     "%s: invalid B-tree node.",
518
0
     function );
519
520
0
    return( -1 );
521
0
  }
522
1.54k
  if( node->descriptor == NULL )
523
0
  {
524
0
    libcerror_error_set(
525
0
     error,
526
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
527
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
528
0
     "%s: invalid B-tree node - missing descriptor.",
529
0
     function );
530
531
0
    return( -1 );
532
0
  }
533
1.54k
  if( ( recursion_depth < 0 )
534
1.54k
   || ( recursion_depth > LIBFSHFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
535
0
  {
536
0
    libcerror_error_set(
537
0
     error,
538
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
539
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
540
0
     "%s: invalid recursion depth value out of bounds.",
541
0
     function );
542
543
0
    return( -1 );
544
0
  }
545
1.54k
  is_branch_node = libfshfs_btree_node_is_branch_node(
546
1.54k
                    node,
547
1.54k
                    error );
548
549
1.54k
  if( is_branch_node == -1 )
550
0
  {
551
0
    libcerror_error_set(
552
0
     error,
553
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
554
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
555
0
     "%s: unable to determine if B-tree node is a branch node.",
556
0
     function );
557
558
0
    goto on_error;
559
0
  }
560
1.54k
  else if( is_branch_node == 0 )
561
0
  {
562
0
    libcerror_error_set(
563
0
     error,
564
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
565
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
566
0
     "%s: invalid node - not a branch node.",
567
0
     function );
568
569
0
    goto on_error;
570
0
  }
571
1.54k
  if( libfshfs_attributes_btree_file_get_key_from_node_by_index(
572
1.54k
       node,
573
1.54k
       0,
574
1.54k
       &last_node_key,
575
1.54k
       error ) == -1 )
576
10
  {
577
10
    libcerror_error_set(
578
10
     error,
579
10
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
10
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
581
10
     "%s: unable to retrieve attributes B-tree key: 0.",
582
10
     function );
583
584
10
    goto on_error;
585
10
  }
586
1.53k
  node_key = last_node_key;
587
588
1.53k
  for( record_index = 1;
589
6.69k
       record_index <= node->descriptor->number_of_records;
590
5.15k
       record_index++ )
591
5.97k
  {
592
5.97k
    if( record_index < node->descriptor->number_of_records )
593
4.93k
    {
594
4.93k
      if( libfshfs_attributes_btree_file_get_key_from_node_by_index(
595
4.93k
           node,
596
4.93k
           record_index,
597
4.93k
           &node_key,
598
4.93k
           error ) == -1 )
599
19
      {
600
19
        libcerror_error_set(
601
19
         error,
602
19
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
603
19
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
604
19
         "%s: unable to retrieve attributes B-tree key: %" PRIu16 ".",
605
19
         function,
606
19
         record_index );
607
608
19
        goto on_error;
609
19
      }
610
4.91k
      if( node_key == NULL )
611
0
      {
612
0
        libcerror_error_set(
613
0
         error,
614
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
615
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
616
0
         "%s: missing attributes B-tree key: %" PRIu16 ".",
617
0
         function,
618
0
         record_index );
619
620
0
        goto on_error;
621
0
      }
622
4.91k
    }
623
5.95k
    if( ( record_index == node->descriptor->number_of_records )
624
4.91k
     || ( node_key->identifier >= identifier ) )
625
4.69k
    {
626
4.69k
      if( libfshfs_attributes_btree_file_get_sub_node_number_from_key(
627
4.69k
           last_node_key,
628
4.69k
           &sub_node_number,
629
4.69k
           error ) != 1 )
630
5
      {
631
5
        libcerror_error_set(
632
5
         error,
633
5
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
634
5
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
635
5
         "%s: unable to retrieve sub node number from attributes B-Tree key.",
636
5
         function );
637
638
5
        goto on_error;
639
5
      }
640
#if defined( HAVE_DEBUG_OUTPUT )
641
      if( libcnotify_verbose != 0 )
642
      {
643
        libcnotify_printf(
644
         "%s: B-tree sub node number\t: %" PRIu32 "\n",
645
         function,
646
         sub_node_number );
647
648
        libcnotify_printf(
649
         "\n" );
650
      }
651
#endif
652
4.68k
      if( libfshfs_btree_file_get_node_by_number(
653
4.68k
           btree_file,
654
4.68k
           file_io_handle,
655
4.68k
           node_cache,
656
4.68k
           recursion_depth,
657
4.68k
           sub_node_number,
658
4.68k
           &sub_node,
659
4.68k
           error ) == -1 )
660
92
      {
661
92
        libcerror_error_set(
662
92
         error,
663
92
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
664
92
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
665
92
         "%s: unable to retrieve B-tree sub node: %" PRIu32 ".",
666
92
         function,
667
92
         sub_node_number );
668
669
92
        goto on_error;
670
92
      }
671
4.59k
      if( libfshfs_btree_node_get_node_type(
672
4.59k
           sub_node,
673
4.59k
           &node_type,
674
4.59k
           error ) != 1 )
675
0
      {
676
0
        libcerror_error_set(
677
0
         error,
678
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
679
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
680
0
         "%s: unable to determine if B-tree sub node: %" PRIu32 " type.",
681
0
         function,
682
0
         sub_node_number );
683
684
0
        goto on_error;
685
0
      }
686
4.59k
      if( node_type == 0x00 )
687
1.30k
      {
688
1.30k
        result = libfshfs_attributes_btree_file_get_attributes_from_branch_node(
689
1.30k
                  btree_file,
690
1.30k
                  file_io_handle,
691
1.30k
                  node_cache,
692
1.30k
                  sub_node,
693
1.30k
                  identifier,
694
1.30k
                  attributes,
695
1.30k
                  recursion_depth + 1,
696
1.30k
                  error );
697
1.30k
      }
698
3.28k
      else if( node_type == 0xff )
699
2.68k
      {
700
2.68k
        result = libfshfs_attributes_btree_file_get_attributes_from_leaf_node(
701
2.68k
                  btree_file,
702
2.68k
                  sub_node,
703
2.68k
                  identifier,
704
2.68k
                  attributes,
705
2.68k
                  error );
706
2.68k
      }
707
4.59k
      if( result != 1 )
708
490
      {
709
490
        libcerror_error_set(
710
490
         error,
711
490
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
712
490
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
713
490
         "%s: unable to retrieve attributes from attributes B-tree node: %" PRIu32 ".",
714
490
         function,
715
490
         sub_node_number );
716
717
490
        goto on_error;
718
490
      }
719
4.10k
      if( node_key->identifier > identifier )
720
216
      {
721
216
        break;
722
216
      }
723
4.10k
    }
724
5.15k
    last_node_key = node_key;
725
5.15k
  }
726
930
  return( 1 );
727
728
616
on_error:
729
616
  libcdata_array_empty(
730
616
   attributes,
731
616
   (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free,
732
616
   NULL );
733
734
616
  return( -1 );
735
1.53k
}
736
737
/* Retrieves the attributes for a specific parent identifier from the attributes B-tree file
738
 * Returns 1 if successful or -1 on error
739
 */
740
int libfshfs_attributes_btree_file_get_attributes(
741
     libfshfs_btree_file_t *btree_file,
742
     libbfio_handle_t *file_io_handle,
743
     libfshfs_btree_node_cache_t *node_cache,
744
     uint32_t identifier,
745
     libcdata_array_t *attributes,
746
     libcerror_error_t **error )
747
977
{
748
977
  libfshfs_btree_node_t *root_node = NULL;
749
977
  static char *function            = "libfshfs_attributes_btree_file_get_attributes";
750
977
  uint8_t node_type                = 0;
751
977
  int result                       = 1;
752
753
977
  if( libfshfs_btree_file_get_root_node(
754
977
       btree_file,
755
977
       file_io_handle,
756
977
       node_cache,
757
977
       &root_node,
758
977
       error ) == -1 )
759
312
  {
760
312
    libcerror_error_set(
761
312
     error,
762
312
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
763
312
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
764
312
     "%s: unable to retrieve B-tree root node.",
765
312
     function );
766
767
312
    goto on_error;
768
312
  }
769
665
  if( libfshfs_btree_node_get_node_type(
770
665
       root_node,
771
665
       &node_type,
772
665
       error ) != 1 )
773
0
  {
774
0
    libcerror_error_set(
775
0
     error,
776
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
777
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
778
0
     "%s: unable to determine if B-tree root node type.",
779
0
     function );
780
781
0
    goto on_error;
782
0
  }
783
665
  if( node_type == 0x00 )
784
238
  {
785
238
    result = libfshfs_attributes_btree_file_get_attributes_from_branch_node(
786
238
              btree_file,
787
238
              file_io_handle,
788
238
              node_cache,
789
238
              root_node,
790
238
              identifier,
791
238
              attributes,
792
238
              1,
793
238
              error );
794
238
  }
795
427
  else if( node_type == 0xff )
796
410
  {
797
410
    result = libfshfs_attributes_btree_file_get_attributes_from_leaf_node(
798
410
              btree_file,
799
410
              root_node,
800
410
              identifier,
801
410
              attributes,
802
410
              error );
803
410
  }
804
665
  if( result != 1 )
805
408
  {
806
408
    libcerror_error_set(
807
408
     error,
808
408
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
809
408
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
810
408
     "%s: unable to retrieve attributes from attributes B-tree root node.",
811
408
     function );
812
813
408
    goto on_error;
814
408
  }
815
257
  return( 1 );
816
817
720
on_error:
818
720
  libcdata_array_empty(
819
720
   attributes,
820
720
   (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free,
821
720
   NULL );
822
823
720
  return( -1 );
824
665
}
825