Coverage Report

Created: 2024-02-25 07:20

/src/libfshfs/libfshfs/libfshfs_attributes_btree_file.c
Line
Count
Source (jump to first uncovered line)
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
9.58k
{
49
9.58k
  libfshfs_attributes_btree_key_t *safe_node_key = NULL;
50
9.58k
  libfshfs_btree_node_record_t *node_record      = NULL;
51
9.58k
  static char *function                          = "libfshfs_attributes_btree_file_get_key_from_node_by_index";
52
53
9.58k
  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
9.58k
  if( libfshfs_btree_node_get_record_by_index(
65
9.58k
       node,
66
9.58k
       record_index,
67
9.58k
       &node_record,
68
9.58k
       error ) == -1 )
69
7
  {
70
7
    libcerror_error_set(
71
7
     error,
72
7
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
7
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
74
7
     "%s: unable to retrieve node record: %" PRIu16 ".",
75
7
     function,
76
7
     record_index );
77
78
7
    goto on_error;
79
7
  }
80
9.58k
  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
9.58k
  if( node_record->key_value == NULL )
93
6.48k
  {
94
6.48k
    if( libfshfs_attributes_btree_key_initialize(
95
6.48k
         &safe_node_key,
96
6.48k
         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.48k
    if( libfshfs_attributes_btree_key_read_data(
108
6.48k
         safe_node_key,
109
6.48k
         node_record->data,
110
6.48k
         node_record->data_size,
111
6.48k
         error ) != 1 )
112
132
    {
113
132
      libcerror_error_set(
114
132
       error,
115
132
       LIBCERROR_ERROR_DOMAIN_IO,
116
132
       LIBCERROR_IO_ERROR_READ_FAILED,
117
132
       "%s: unable to read attributes B-tree key.",
118
132
       function );
119
120
132
      goto on_error;
121
132
    }
122
6.35k
    node_record->key_value               = (intptr_t *) safe_node_key;
123
6.35k
    node_record->key_value_free_function = (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attributes_btree_key_free;
124
6.35k
  }
125
9.44k
  *node_key = (libfshfs_attributes_btree_key_t *) node_record->key_value;
126
127
9.44k
  return( 1 );
128
129
139
on_error:
130
139
  if( safe_node_key != NULL )
131
132
  {
132
132
    libfshfs_attributes_btree_key_free(
133
132
     &safe_node_key,
134
132
     NULL );
135
132
  }
136
139
  return( -1 );
137
9.58k
}
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.03k
{
147
4.03k
  static char *function = "libfshfs_attributes_btree_file_get_sub_node_number_from_key";
148
149
4.03k
  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.03k
  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.03k
  if( node_key->record_data_size < 4 )
172
6
  {
173
6
    libcerror_error_set(
174
6
     error,
175
6
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
176
6
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
177
6
     "%s: invalid attributes B-tree key - record data size value out of bounds.",
178
6
     function );
179
180
6
    return( -1 );
181
6
  }
182
4.03k
  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.03k
  byte_stream_copy_to_uint32_big_endian(
194
4.03k
   node_key->record_data,
195
4.03k
   *sub_node_number );
196
197
4.03k
  return( 1 );
198
4.03k
}
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
681
{
209
681
  libfshfs_attribute_record_t *safe_attribute_record = NULL;
210
681
  static char *function                              = "libfshfs_attributes_btree_file_get_attribute_from_record_data";
211
212
681
  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
681
  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
681
  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
681
  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
681
  if( libfshfs_attribute_record_initialize(
257
681
       &safe_attribute_record,
258
681
       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
681
  if( libfshfs_attribute_record_set_name(
270
681
       safe_attribute_record,
271
681
       node_key->name_data,
272
681
       node_key->name_size,
273
681
       error ) != 1 )
274
16
  {
275
16
    libcerror_error_set(
276
16
     error,
277
16
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
278
16
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
279
16
     "%s: unable to set name of attribute record.",
280
16
     function );
281
282
16
    goto on_error;
283
16
  }
284
665
  if( libfshfs_attribute_record_read_data(
285
665
       safe_attribute_record,
286
665
       node_key->record_data,
287
665
       node_key->record_data_size,
288
665
       error ) != 1 )
289
173
  {
290
173
    libcerror_error_set(
291
173
     error,
292
173
     LIBCERROR_ERROR_DOMAIN_IO,
293
173
     LIBCERROR_IO_ERROR_READ_FAILED,
294
173
     "%s: unable to read attribute record.",
295
173
     function );
296
297
173
    goto on_error;
298
173
  }
299
492
  *attribute_record = safe_attribute_record;
300
301
492
  return( 1 );
302
303
189
on_error:
304
189
  if( safe_attribute_record != NULL )
305
189
  {
306
189
    libfshfs_attribute_record_free(
307
189
     &safe_attribute_record,
308
189
     NULL );
309
189
  }
310
189
  return( -1 );
311
665
}
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
2.70k
{
323
2.70k
  libfshfs_attribute_record_t *attribute_record = NULL;
324
2.70k
  libfshfs_attributes_btree_key_t *node_key     = NULL;
325
2.70k
  static char *function                         = "libfshfs_attributes_btree_file_get_attributes_from_leaf_node";
326
2.70k
  uint16_t record_index                         = 0;
327
2.70k
  int entry_index                               = 0;
328
2.70k
  int is_leaf_node                              = 0;
329
330
2.70k
  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
2.70k
  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
2.70k
  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
2.70k
  is_leaf_node = libfshfs_btree_node_is_leaf_node(
364
2.70k
                  node,
365
2.70k
                  error );
366
367
2.70k
  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
2.70k
  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
2.70k
  for( record_index = 0;
390
4.43k
       record_index < node->descriptor->number_of_records;
391
2.70k
       record_index++ )
392
4.02k
  {
393
4.02k
    if( libfshfs_attributes_btree_file_get_key_from_node_by_index(
394
4.02k
         node,
395
4.02k
         record_index,
396
4.02k
         &node_key,
397
4.02k
         error ) == -1 )
398
105
    {
399
105
      libcerror_error_set(
400
105
       error,
401
105
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
402
105
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
403
105
       "%s: unable to retrieve attributes B-tree key: %" PRIu16 ".",
404
105
       function,
405
105
       record_index );
406
407
105
      goto on_error;
408
105
    }
409
3.91k
    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
3.91k
    if( node_key->identifier == identifier )
422
681
    {
423
681
      if( libfshfs_attributes_btree_file_get_attribute_from_record_data(
424
681
           btree_file,
425
681
           node_key,
426
681
           &attribute_record,
427
681
           error ) != 1 )
428
189
      {
429
189
        libcerror_error_set(
430
189
         error,
431
189
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
432
189
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
433
189
         "%s: unable to retrieve attribute from record data.",
434
189
         function );
435
436
189
        goto on_error;
437
189
      }
438
492
      if( libcdata_array_append_entry(
439
492
           attributes,
440
492
           &entry_index,
441
492
           (intptr_t *) attribute_record,
442
492
           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
492
      attribute_record = NULL;
454
492
    }
455
3.72k
    if( node_key->identifier > identifier )
456
1.99k
    {
457
1.99k
      break;
458
1.99k
    }
459
3.72k
  }
460
2.40k
  return( 1 );
461
462
294
on_error:
463
294
  if( attribute_record != NULL )
464
0
  {
465
0
    libfshfs_attribute_record_free(
466
0
     &attribute_record,
467
0
     NULL );
468
0
  }
469
294
  libcdata_array_empty(
470
294
   attributes,
471
294
   (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free,
472
294
   NULL );
473
474
294
  return( -1 );
475
2.70k
}
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.44k
{
490
1.44k
  libfshfs_attributes_btree_key_t *last_node_key = NULL;
491
1.44k
  libfshfs_attributes_btree_key_t *node_key      = NULL;
492
1.44k
  libfshfs_btree_node_t *sub_node                = NULL;
493
1.44k
  static char *function                          = "libfshfs_attributes_btree_file_get_attributes_from_branch_node";
494
1.44k
  uint32_t sub_node_number                       = 0;
495
1.44k
  uint16_t record_index                          = 0;
496
1.44k
  uint8_t node_type                              = 0;
497
1.44k
  int is_branch_node                             = 0;
498
1.44k
  int result                                     = 0;
499
500
1.44k
  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.44k
  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.44k
  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.44k
  if( ( recursion_depth < 0 )
534
1.44k
   || ( 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.44k
  is_branch_node = libfshfs_btree_node_is_branch_node(
546
1.44k
                    node,
547
1.44k
                    error );
548
549
1.44k
  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.44k
  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.44k
  if( libfshfs_attributes_btree_file_get_key_from_node_by_index(
572
1.44k
       node,
573
1.44k
       0,
574
1.44k
       &last_node_key,
575
1.44k
       error ) == -1 )
576
19
  {
577
19
    libcerror_error_set(
578
19
     error,
579
19
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
19
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
581
19
     "%s: unable to retrieve attributes B-tree key: 0.",
582
19
     function );
583
584
19
    goto on_error;
585
19
  }
586
1.42k
  node_key = last_node_key;
587
588
1.42k
  for( record_index = 1;
589
5.56k
       record_index <= node->descriptor->number_of_records;
590
4.14k
       record_index++ )
591
5.01k
  {
592
5.01k
    if( record_index < node->descriptor->number_of_records )
593
4.12k
    {
594
4.12k
      if( libfshfs_attributes_btree_file_get_key_from_node_by_index(
595
4.12k
           node,
596
4.12k
           record_index,
597
4.12k
           &node_key,
598
4.12k
           error ) == -1 )
599
15
      {
600
15
        libcerror_error_set(
601
15
         error,
602
15
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
603
15
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
604
15
         "%s: unable to retrieve attributes B-tree key: %" PRIu16 ".",
605
15
         function,
606
15
         record_index );
607
608
15
        goto on_error;
609
15
      }
610
4.11k
      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.11k
    }
623
4.99k
    if( ( record_index == node->descriptor->number_of_records )
624
4.99k
     || ( node_key->identifier >= identifier ) )
625
4.03k
    {
626
4.03k
      if( libfshfs_attributes_btree_file_get_sub_node_number_from_key(
627
4.03k
           last_node_key,
628
4.03k
           &sub_node_number,
629
4.03k
           error ) != 1 )
630
6
      {
631
6
        libcerror_error_set(
632
6
         error,
633
6
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
634
6
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
635
6
         "%s: unable to retrieve sub node number from attributes B-Tree key.",
636
6
         function );
637
638
6
        goto on_error;
639
6
      }
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.03k
      if( libfshfs_btree_file_get_node_by_number(
653
4.03k
           btree_file,
654
4.03k
           file_io_handle,
655
4.03k
           node_cache,
656
4.03k
           recursion_depth,
657
4.03k
           sub_node_number,
658
4.03k
           &sub_node,
659
4.03k
           error ) == -1 )
660
108
      {
661
108
        libcerror_error_set(
662
108
         error,
663
108
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
664
108
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
665
108
         "%s: unable to retrieve B-tree sub node: %" PRIu32 ".",
666
108
         function,
667
108
         sub_node_number );
668
669
108
        goto on_error;
670
108
      }
671
3.92k
      if( libfshfs_btree_node_get_node_type(
672
3.92k
           sub_node,
673
3.92k
           &node_type,
674
3.92k
           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
3.92k
      if( node_type == 0x00 )
687
1.14k
      {
688
1.14k
        result = libfshfs_attributes_btree_file_get_attributes_from_branch_node(
689
1.14k
                  btree_file,
690
1.14k
                  file_io_handle,
691
1.14k
                  node_cache,
692
1.14k
                  sub_node,
693
1.14k
                  identifier,
694
1.14k
                  attributes,
695
1.14k
                  recursion_depth + 1,
696
1.14k
                  error );
697
1.14k
      }
698
2.77k
      else if( node_type == 0xff )
699
2.23k
      {
700
2.23k
        result = libfshfs_attributes_btree_file_get_attributes_from_leaf_node(
701
2.23k
                  btree_file,
702
2.23k
                  sub_node,
703
2.23k
                  identifier,
704
2.23k
                  attributes,
705
2.23k
                  error );
706
2.23k
      }
707
3.92k
      if( result != 1 )
708
506
      {
709
506
        libcerror_error_set(
710
506
         error,
711
506
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
712
506
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
713
506
         "%s: unable to retrieve attributes from attributes B-tree node: %" PRIu32 ".",
714
506
         function,
715
506
         sub_node_number );
716
717
506
        goto on_error;
718
506
      }
719
3.41k
      if( node_key->identifier > identifier )
720
235
      {
721
235
        break;
722
235
      }
723
3.41k
    }
724
4.14k
    last_node_key = node_key;
725
4.14k
  }
726
786
  return( 1 );
727
728
654
on_error:
729
654
  libcdata_array_empty(
730
654
   attributes,
731
654
   (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free,
732
654
   NULL );
733
734
654
  return( -1 );
735
1.42k
}
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
1.09k
{
748
1.09k
  libfshfs_btree_node_t *root_node = NULL;
749
1.09k
  static char *function            = "libfshfs_attributes_btree_file_get_attributes";
750
1.09k
  uint8_t node_type                = 0;
751
1.09k
  int result                       = 1;
752
753
1.09k
  if( libfshfs_btree_file_get_root_node(
754
1.09k
       btree_file,
755
1.09k
       file_io_handle,
756
1.09k
       node_cache,
757
1.09k
       &root_node,
758
1.09k
       error ) == -1 )
759
314
  {
760
314
    libcerror_error_set(
761
314
     error,
762
314
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
763
314
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
764
314
     "%s: unable to retrieve B-tree root node.",
765
314
     function );
766
767
314
    goto on_error;
768
314
  }
769
782
  if( libfshfs_btree_node_get_node_type(
770
782
       root_node,
771
782
       &node_type,
772
782
       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
782
  if( node_type == 0x00 )
784
292
  {
785
292
    result = libfshfs_attributes_btree_file_get_attributes_from_branch_node(
786
292
              btree_file,
787
292
              file_io_handle,
788
292
              node_cache,
789
292
              root_node,
790
292
              identifier,
791
292
              attributes,
792
292
              1,
793
292
              error );
794
292
  }
795
490
  else if( node_type == 0xff )
796
466
  {
797
466
    result = libfshfs_attributes_btree_file_get_attributes_from_leaf_node(
798
466
              btree_file,
799
466
              root_node,
800
466
              identifier,
801
466
              attributes,
802
466
              error );
803
466
  }
804
782
  if( result != 1 )
805
468
  {
806
468
    libcerror_error_set(
807
468
     error,
808
468
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
809
468
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
810
468
     "%s: unable to retrieve attributes from attributes B-tree root node.",
811
468
     function );
812
813
468
    goto on_error;
814
468
  }
815
314
  return( 1 );
816
817
782
on_error:
818
782
  libcdata_array_empty(
819
782
   attributes,
820
782
   (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free,
821
782
   NULL );
822
823
782
  return( -1 );
824
782
}
825